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

📄 via-pmu.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct adb_request req;	out_8(&via[B], via[B] | TREQ);			/* negate TREQ */	out_8(&via[DIRB], (via[DIRB] | TREQ) & ~TACK);	/* TACK in, TREQ out */	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);	timeout =  100000;	while (!req.complete) {		if (--timeout < 0) {			printk(KERN_ERR "init_pmu: no response from PMU\n");			return 0;		}		udelay(10);		pmu_poll();	}	/* ack all pending interrupts */	timeout = 100000;	interrupt_data[0][0] = 1;	while (interrupt_data[0][0] || pmu_state != idle) {		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, NULL);		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);	pmu_wait_complete(&req);	if (req.reply_len > 0)		pmu_version = req.reply[0];		/* Read server mode setting */	if (pmu_kind == PMU_KEYLARGO_BASED) {		pmu_request(&req, NULL, 2, PMU_POWER_EVENTS,			    PMU_PWR_GET_POWERUP_EVENTS);		pmu_wait_complete(&req);		if (req.reply_len == 2) {			if (req.reply[1] & PMU_PWR_WAKEUP_AC_INSERT)				option_server_mode = 1;			printk(KERN_INFO "via-pmu: Server Mode is %s\n",			       option_server_mode ? "enabled" : "disabled");		}	}	return 1;}intpmu_get_model(void){	return pmu_kind;}static void pmu_set_server_mode(int server_mode){	struct adb_request req;	if (pmu_kind != PMU_KEYLARGO_BASED)		return;	option_server_mode = server_mode;	pmu_request(&req, NULL, 2, PMU_POWER_EVENTS, PMU_PWR_GET_POWERUP_EVENTS);	pmu_wait_complete(&req);	if (req.reply_len < 2)		return;	if (server_mode)		pmu_request(&req, NULL, 4, PMU_POWER_EVENTS,			    PMU_PWR_SET_POWERUP_EVENTS,			    req.reply[0], PMU_PWR_WAKEUP_AC_INSERT); 	else		pmu_request(&req, NULL, 4, PMU_POWER_EVENTS,			    PMU_PWR_CLR_POWERUP_EVENTS,			    req.reply[0], PMU_PWR_WAKEUP_AC_INSERT); 	pmu_wait_complete(&req);}/* This new version of the code for 2400/3400/3500 powerbooks * is inspired from the implementation in gkrellm-pmu */static voiddone_battery_state_ohare(struct adb_request* req){	/* format:	 *  [0]    :  flags	 *    0x01 :  AC indicator	 *    0x02 :  charging	 *    0x04 :  battery exist	 *    0x08 :  	 *    0x10 :  	 *    0x20 :  full charged	 *    0x40 :  pcharge reset	 *    0x80 :  battery exist	 *	 *  [1][2] :  battery voltage	 *  [3]    :  CPU temperature	 *  [4]    :  battery temperature	 *  [5]    :  current	 *  [6][7] :  pcharge	 *              --tkoba	 */	unsigned int bat_flags = PMU_BATT_TYPE_HOOPER;	long pcharge, charge, vb, vmax, lmax;	long vmax_charging, vmax_charged;	long amperage, voltage, time, max;	int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO,			NULL, PMAC_MB_INFO_MODEL, 0);	if (req->reply[0] & 0x01)		pmu_power_flags |= PMU_PWR_AC_PRESENT;	else		pmu_power_flags &= ~PMU_PWR_AC_PRESENT;		if (mb == PMAC_TYPE_COMET) {		vmax_charged = 189;		vmax_charging = 213;		lmax = 6500;	} else {		vmax_charged = 330;		vmax_charging = 330;		lmax = 6500;	}	vmax = vmax_charged;	/* If battery installed */	if (req->reply[0] & 0x04) {		bat_flags |= PMU_BATT_PRESENT;		if (req->reply[0] & 0x02)			bat_flags |= PMU_BATT_CHARGING;		vb = (req->reply[1] << 8) | req->reply[2];		voltage = (vb * 265 + 72665) / 10;		amperage = req->reply[5];		if ((req->reply[0] & 0x01) == 0) {			if (amperage > 200)				vb += ((amperage - 200) * 15)/100;		} else if (req->reply[0] & 0x02) {			vb = (vb * 97) / 100;			vmax = vmax_charging;		}		charge = (100 * vb) / vmax;		if (req->reply[0] & 0x40) {			pcharge = (req->reply[6] << 8) + req->reply[7];			if (pcharge > lmax)				pcharge = lmax;			pcharge *= 100;			pcharge = 100 - pcharge / lmax;			if (pcharge < charge)				charge = pcharge;		}		if (amperage > 0)			time = (charge * 16440) / amperage;		else			time = 0;		max = 100;		amperage = -amperage;	} else		charge = max = amperage = voltage = time = 0;	pmu_batteries[pmu_cur_battery].flags = bat_flags;	pmu_batteries[pmu_cur_battery].charge = charge;	pmu_batteries[pmu_cur_battery].max_charge = max;	pmu_batteries[pmu_cur_battery].amperage = amperage;	pmu_batteries[pmu_cur_battery].voltage = voltage;	pmu_batteries[pmu_cur_battery].time_remaining = time;	clear_bit(0, &async_req_locks);}static voiddone_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 = PMU_BATT_TYPE_SMART;	int amperage;	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;	capa = max = amperage = voltage = 0;		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];				amperage = *((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];				amperage = *((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;		}	}	if ((req->reply[1] & 0x01) && (amperage > 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].amperage = amperage;	pmu_batteries[pmu_cur_battery].voltage = voltage;	if (amperage) {		if ((req->reply[1] & 0x01) && (amperage > 0))			pmu_batteries[pmu_cur_battery].time_remaining				= ((max-capa) * 3600) / amperage;		else			pmu_batteries[pmu_cur_battery].time_remaining				= (capa * 3600) / (-amperage);	} else		pmu_batteries[pmu_cur_battery].time_remaining = 0;	pmu_cur_battery = (pmu_cur_battery + 1) % pmu_battery_count;	clear_bit(0, &async_req_locks);}static voidquery_battery_state(void){	if (test_and_set_bit(0, &async_req_locks))		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);}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);	p += sprintf(p, "AC Power               : %d\n",		((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0) || pmu_battery_count == 0);	p += sprintf(p, "Battery count          : %d\n", pmu_battery_count);	return p - page;}static intproc_get_irqstats(char *page, char **start, off_t off,		  int count, int *eof, void *data){	int i;	char* p = page;	static const char *irq_names[] = {		"Total CB1 triggered events",		"Total GPIO1 triggered events",		"PC-Card eject button",		"Sound/Brightness button",		"ADB message",		"Battery state change",		"Environment interrupt",		"Tick timer",		"Ghost interrupt (zero len)",		"Empty interrupt (empty mask)",		"Max irqs in a row"        };	for (i=0; i<11; i++) {		p += sprintf(p, " %2u: %10u (%s)\n",			     i, pmu_irq_stats[i], irq_names[i]);	}	return p - page;}static intproc_get_batt(char *page, char **start, off_t off,		int count, int *eof, void *data){	long batnum = (long)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].amperage);	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;}static intproc_read_options(char *page, char **start, off_t off,			int count, int *eof, void *data){	char *p = page;#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)	if (pmu_kind == PMU_KEYLARGO_BASED &&	    pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)		p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup);#endif	if (pmu_kind == PMU_KEYLARGO_BASED)		p += sprintf(p, "server_mode=%d\n", option_server_mode);	return p - page;}			static intproc_write_options(struct file *file, const char __user *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++;#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)	if (pmu_kind == PMU_KEYLARGO_BASED &&	    pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)		if (!strcmp(label, "lid_wakeup"))			option_lid_wakeup = ((*val) == '1');#endif	if (pmu_kind == PMU_KEYLARGO_BASED && !strcmp(label, "server_mode")) {		int new_value;		new_value = ((*val) == '1');		if (new_value != option_server_mode)			pmu_set_server_mode(new_value);	}	return fcount;}#ifdef CONFIG_ADB/* Send an ADB command */static intpmu_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 intpmu_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 intpmu_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;	}	pmu_wait_complete(&req);	if (save_autopoll != 0)		pmu_adb_autopoll(save_autopoll);	return 0;}#endif /* CONFIG_ADB */

⌨️ 快捷键说明

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