⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 via-pmu.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (--timeout < 0) {			printk(KERN_ERR "init_pmu: timed out acking intrs\n");			return 0;		}		if (pmu_state == idle)			adb_int_pending = 1;		via_pmu_interrupt(0, 0, 0);		udelay(10);	}	/* Tell PMU we are ready.  */	if (pmu_kind == PMU_KEYLARGO_BASED) {		pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);		while (!req.complete)			pmu_poll();	}	/* Read PMU version */	pmu_request(&req, NULL, 1, PMU_GET_VERSION);	while (!req.complete)		pmu_poll();	if (req.reply_len > 0)		pmu_version = req.reply[0];	return 1;}intpmu_get_model(void){	return pmu_kind;}#ifdef CONFIG_PMAC_PBOOK/*  * WARNING ! This code probably needs some debugging... -- BenH. */static void __pmacdone_battery_state_ohare(struct adb_request* req){	unsigned int bat_flags = 0;	int current = 0;	unsigned int capa, max, voltage, time;	int lrange[] = { 0, 275, 850, 1680, 2325, 				2765, 3160, 3500, 3830, 4115, 				4360, 4585, 4795, 4990, 5170, 				5340, 5510, 5710, 5930, 6150, 				6370, 6500				};		if (req->reply[0] & 0x01)		pmu_power_flags |= PMU_PWR_AC_PRESENT;	else		pmu_power_flags &= ~PMU_PWR_AC_PRESENT;	if (req->reply[0] & 0x04) {		int vb, i, j, charge, pcharge;		bat_flags |= PMU_BATT_PRESENT;		vb = (req->reply[1] << 8) | req->reply[2];		voltage = ((vb * 2650) + 726650)/100;		current = *((signed char *)&req->reply[5]);		if ((req->reply[0] & 0x01) == 0 && (current > 200))			vb += (current - 200) * 15;		else if (req->reply[0] & 0x02)			vb = (vb - 10) * 100;	  	i = (33000 - vb) / 10;	  	j = i - (i % 100);	  	if (j <= 0)	       		charge = 0;	  	else if (j >= 21)	       		charge = 650000;	  	else			charge = (lrange[j + 1] - lrange[j]) * (i - j) + (lrange[j] * 100);		charge = (1000 - charge / 650) / 10;		if (req->reply[0] & 0x40) {			pcharge = (req->reply[6] << 8) + req->reply[7];			if (pcharge > 6500)				pcharge = 6500;			pcharge *= 100;			pcharge = (1000 - pcharge / 650) / 10;			if (pcharge < charge)				charge = pcharge;		}		capa = charge;		max = 100;		time = (charge * 274) / current;		current = -current;			} else		capa = max = current = voltage = time = 0;	if ((req->reply[0] & 0x02) && (current > 0))		bat_flags |= PMU_BATT_CHARGING;	if (req->reply[0] & 0x04) /* CHECK THIS ONE */		bat_flags |= PMU_BATT_PRESENT;	pmu_batteries[pmu_cur_battery].flags = bat_flags;	pmu_batteries[pmu_cur_battery].charge = capa;	pmu_batteries[pmu_cur_battery].max_charge = max;	pmu_batteries[pmu_cur_battery].current = current;	pmu_batteries[pmu_cur_battery].voltage = voltage;	pmu_batteries[pmu_cur_battery].time_remaining = time;}static void __pmacdone_battery_state_smart(struct adb_request* req){	/* format:	 *  [0] : format of this structure (known: 3,4,5)	 *  [1] : flags	 *  	 *  format 3 & 4:	 *  	 *  [2] : charge	 *  [3] : max charge	 *  [4] : current	 *  [5] : voltage	 *  	 *  format 5:	 *  	 *  [2][3] : charge	 *  [4][5] : max charge	 *  [6][7] : current	 *  [8][9] : voltage	 */	 	unsigned int bat_flags = 0;	int current;	unsigned int capa, max, voltage;		if (req->reply[1] & 0x01)		pmu_power_flags |= PMU_PWR_AC_PRESENT;	else		pmu_power_flags &= ~PMU_PWR_AC_PRESENT;	if (req->reply[1] & 0x04) {		bat_flags |= PMU_BATT_PRESENT;		switch(req->reply[0]) {			case 3:			case 4: capa = req->reply[2];				max = req->reply[3];				current = *((signed char *)&req->reply[4]);				voltage = req->reply[5];				break;			case 5: capa = (req->reply[2] << 8) | req->reply[3];				max = (req->reply[4] << 8) | req->reply[5];				current = *((signed short *)&req->reply[6]);				voltage = (req->reply[8] << 8) | req->reply[9];				break;			default:				printk(KERN_WARNING "pmu.c : unrecognized battery info, len: %d, %02x %02x %02x %02x\n",					req->reply_len, req->reply[0], req->reply[1], req->reply[2], req->reply[3]);				break;		}	} else		capa = max = current = voltage = 0;	if ((req->reply[1] & 0x01) && (current > 0))		bat_flags |= PMU_BATT_CHARGING;	pmu_batteries[pmu_cur_battery].flags = bat_flags;	pmu_batteries[pmu_cur_battery].charge = capa;	pmu_batteries[pmu_cur_battery].max_charge = max;	pmu_batteries[pmu_cur_battery].current = current;	pmu_batteries[pmu_cur_battery].voltage = voltage;	if (current) {		if ((req->reply[1] & 0x01) && (current > 0))			pmu_batteries[pmu_cur_battery].time_remaining				= ((max-capa) * 3600) / current;		else			pmu_batteries[pmu_cur_battery].time_remaining				= (capa * 3600) / (-current);	} else		pmu_batteries[pmu_cur_battery].time_remaining = 0;	pmu_cur_battery = (pmu_cur_battery + 1) % pmu_battery_count;}static void __pmacquery_battery_state(void){	if (!batt_req.complete)		return;	if (pmu_kind == PMU_OHARE_BASED)		pmu_request(&batt_req, done_battery_state_ohare,			1, PMU_BATTERY_STATE);	else		pmu_request(&batt_req, done_battery_state_smart,			2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1);}#endif /* CONFIG_PMAC_PBOOK */static intproc_get_info(char *page, char **start, off_t off,		int count, int *eof, void *data){	char* p = page;	p += sprintf(p, "PMU driver version     : %d\n", PMU_DRIVER_VERSION);	p += sprintf(p, "PMU firmware version   : %02x\n", pmu_version);#ifdef CONFIG_PMAC_PBOOK	p += sprintf(p, "AC Power               : %d\n",		((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0));	p += sprintf(p, "Battery count          : %d\n", pmu_battery_count);#endif /* CONFIG_PMAC_PBOOK */	return p - page;}#ifdef CONFIG_PMAC_PBOOKstatic intproc_get_batt(char *page, char **start, off_t off,		int count, int *eof, void *data){	int batnum = (int)data;	char *p = page;		p += sprintf(p, "\n");	p += sprintf(p, "flags      : %08x\n",		pmu_batteries[batnum].flags);	p += sprintf(p, "charge     : %d\n",		pmu_batteries[batnum].charge);	p += sprintf(p, "max_charge : %d\n",		pmu_batteries[batnum].max_charge);	p += sprintf(p, "current    : %d\n",		pmu_batteries[batnum].current);	p += sprintf(p, "voltage    : %d\n",		pmu_batteries[batnum].voltage);	p += sprintf(p, "time rem.  : %d\n",		pmu_batteries[batnum].time_remaining);	return p - page;}#endif /* CONFIG_PMAC_PBOOK */static intproc_read_options(char *page, char **start, off_t off,			int count, int *eof, void *data){	char *p = page;#ifdef CONFIG_PMAC_PBOOK	if (pmu_kind == PMU_KEYLARGO_BASED && can_sleep)		p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup);#endif /* CONFIG_PMAC_PBOOK */	return p - page;}			static intproc_write_options(struct file *file, const char *buffer,			unsigned long count, void *data){	char tmp[33];	char *label, *val;	unsigned long fcount = count;		if (!count)		return -EINVAL;	if (count > 32)		count = 32;	if (copy_from_user(tmp, buffer, count))		return -EFAULT;	tmp[count] = 0;	label = tmp;	while(*label == ' ')		label++;	val = label;	while(*val && (*val != '=')) {		if (*val == ' ')			*val = 0;		val++;	}	if ((*val) == 0)		return -EINVAL;	*(val++) = 0;	while(*val == ' ')		val++;#ifdef CONFIG_PMAC_PBOOK	if (pmu_kind == PMU_KEYLARGO_BASED && can_sleep)		if (!strcmp(label, "lid_wakeup"))			option_lid_wakeup = ((*val) == '1');#endif /* CONFIG_PMAC_PBOOK */	return fcount;}#ifdef CONFIG_ADB/* Send an ADB command */static int __openfirmwarepmu_send_request(struct adb_request *req, int sync){	int i, ret;	if ((vias == NULL) || (!pmu_fully_inited)) {		req->complete = 1;		return -ENXIO;	}	ret = -EINVAL;	switch (req->data[0]) {	case PMU_PACKET:		for (i = 0; i < req->nbytes - 1; ++i)			req->data[i] = req->data[i+1];		--req->nbytes;		if (pmu_data_len[req->data[0]][1] != 0) {			req->reply[0] = ADB_RET_OK;			req->reply_len = 1;		} else			req->reply_len = 0;		ret = pmu_queue_request(req);		break;	case CUDA_PACKET:		switch (req->data[1]) {		case CUDA_GET_TIME:			if (req->nbytes != 2)				break;			req->data[0] = PMU_READ_RTC;			req->nbytes = 1;			req->reply_len = 3;			req->reply[0] = CUDA_PACKET;			req->reply[1] = 0;			req->reply[2] = CUDA_GET_TIME;			ret = pmu_queue_request(req);			break;		case CUDA_SET_TIME:			if (req->nbytes != 6)				break;			req->data[0] = PMU_SET_RTC;			req->nbytes = 5;			for (i = 1; i <= 4; ++i)				req->data[i] = req->data[i+1];			req->reply_len = 3;			req->reply[0] = CUDA_PACKET;			req->reply[1] = 0;			req->reply[2] = CUDA_SET_TIME;			ret = pmu_queue_request(req);			break;		}		break;	case ADB_PACKET:	    	if (!pmu_has_adb)    			return -ENXIO;		for (i = req->nbytes - 1; i > 1; --i)			req->data[i+2] = req->data[i];		req->data[3] = req->nbytes - 2;		req->data[2] = pmu_adb_flags;		/*req->data[1] = req->data[1];*/		req->data[0] = PMU_ADB_CMD;		req->nbytes += 2;		req->reply_expected = 1;		req->reply_len = 0;		ret = pmu_queue_request(req);		break;	}	if (ret) {		req->complete = 1;		return ret;	}	if (sync)		while (!req->complete)			pmu_poll();	return 0;}/* Enable/disable autopolling */static int __openfirmwarepmu_adb_autopoll(int devs){	struct adb_request req;	if ((vias == NULL) || (!pmu_fully_inited) || !pmu_has_adb)		return -ENXIO;	if (devs) {		adb_dev_map = devs;		pmu_request(&req, NULL, 5, PMU_ADB_CMD, 0, 0x86,			    adb_dev_map >> 8, adb_dev_map);		pmu_adb_flags = 2;	} else {		pmu_request(&req, NULL, 1, PMU_ADB_POLL_OFF);		pmu_adb_flags = 0;	}	while (!req.complete)		pmu_poll();	return 0;}/* Reset the ADB bus */static int __openfirmwarepmu_adb_reset_bus(void){	struct adb_request req;	int save_autopoll = adb_dev_map;	if ((vias == NULL) || (!pmu_fully_inited) || !pmu_has_adb)		return -ENXIO;	/* anyone got a better idea?? */	pmu_adb_autopoll(0);	req.nbytes = 5;	req.done = NULL;	req.data[0] = PMU_ADB_CMD;	req.data[1] = 0;	req.data[2] = ADB_BUSRESET;	req.data[3] = 0;	req.data[4] = 0;	req.reply_len = 0;	req.reply_expected = 1;	if (pmu_queue_request(&req) != 0) {		printk(KERN_ERR "pmu_adb_reset_bus: pmu_queue_request failed\n");		return -EIO;	}	while (!req.complete)		pmu_poll();	if (save_autopoll != 0)		pmu_adb_autopoll(save_autopoll);	return 0;}#endif /* CONFIG_ADB *//* Construct and send a pmu request */int __openfirmwarepmu_request(struct adb_request *req, void (*done)(struct adb_request *),	    int nbytes, ...){	va_list list;	int i;	if (vias == NULL)		return -ENXIO;	if (nbytes < 0 || nbytes > 32) {		printk(KERN_ERR "pmu_request: bad nbytes (%d)\n", nbytes);		req->complete = 1;		return -EINVAL;	}	req->nbytes = nbytes;	req->done = done;	va_start(list, nbytes);	for (i = 0; i < nbytes; ++i)		req->data[i] = va_arg(list, int);	va_end(list);	req->reply_len = 0;	req->reply_expected = 0;	return pmu_queue_request(req);}int __openfirmwarepmu_queue_request(struct adb_request *req){	unsigned long flags;	int nsend;	if (via == NULL) {		req->complete = 1;		return -ENXIO;	}	if (req->nbytes <= 0) {		req->complete = 1;		return 0;	}	nsend = pmu_data_len[req->data[0]][0];	if (nsend >= 0 && req->nbytes != nsend + 1) {		req->complete = 1;		return -EINVAL;	}	req->next = 0;	req->sent = 0;	req->complete = 0;	spin_lock_irqsave(&pmu_lock, flags);	if (current_req != 0) {		last_req->next = req;		last_req = req;	} else {		current_req = req;		last_req = req;		if (pmu_state == idle)			pmu_start();	}	spin_unlock_irqrestore(&pmu_lock, flags);	return 0;}static void __openfirmwarewait_for_ack(void){	/* Sightly increased the delay, I had one occurence of the message	 * reported	 */	int timeout = 4000;	while ((in_8(&via[B]) & TACK) == 0) {		if (--timeout < 0) {			printk(KERN_ERR "PMU not responding (!ack)\n");			return;		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -