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

📄 via-pmu.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
		udelay(10);	}}/* New PMU seems to be very sensitive to those timings, so we make sure * PCI is flushed immediately */static void __openfirmwaresend_byte(int x){	volatile unsigned char *v = via;	out_8(&v[ACR], in_8(&v[ACR]) | SR_OUT | SR_EXT);	out_8(&v[SR], x);	out_8(&v[B], in_8(&v[B]) & ~TREQ);		/* assert TREQ */	(void)in_8(&v[B]);}static void __openfirmwarerecv_byte(){	volatile unsigned char *v = via;	out_8(&v[ACR], (in_8(&v[ACR]) & ~SR_OUT) | SR_EXT);	in_8(&v[SR]);		/* resets SR */	out_8(&v[B], in_8(&v[B]) & ~TREQ);	(void)in_8(&v[B]);}static volatile int disable_poll;static void __openfirmwarepmu_start(){	struct adb_request *req;	/* assert pmu_state == idle */	/* get the packet to send */	req = current_req;	if (req == 0 || pmu_state != idle	    || (/*req->reply_expected && */req_awaiting_reply))		return;	pmu_state = sending;	data_index = 1;	data_len = pmu_data_len[req->data[0]][0];	/* Sounds safer to make sure ACK is high before writing. This helped	 * kill a problem with ADB and some iBooks	 */	wait_for_ack();	/* set the shift register to shift out and send a byte */	send_byte(req->data[0]);}void __openfirmwarepmu_poll(){	if (!via)		return;	if (disable_poll)		return;	/* Kicks ADB read when PMU is suspended */	if (pmu_suspended)		adb_int_pending = 1;	do {		via_pmu_interrupt(0, 0, 0);	} while (pmu_suspended && (adb_int_pending || pmu_state != idle		|| req_awaiting_reply));}/* This function loops until the PMU is idle and prevents it from * anwsering to ADB interrupts. pmu_request can still be called. * This is done to avoid spurrious shutdowns when we know we'll have * interrupts switched off for a long time */void __openfirmwarepmu_suspend(void){	unsigned long flags;#ifdef SUSPEND_USES_PMU	struct adb_request *req;#endif	if (!via)		return;		spin_lock_irqsave(&pmu_lock, flags);	pmu_suspended++;	if (pmu_suspended > 1) {		spin_unlock_irqrestore(&pmu_lock, flags);		return;	}	do {		spin_unlock(&pmu_lock);		via_pmu_interrupt(0, 0, 0);		spin_lock(&pmu_lock);		if (!adb_int_pending && pmu_state == idle && !req_awaiting_reply) {#ifdef SUSPEND_USES_PMU			pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);			spin_unlock_irqrestore(&pmu_lock, flags);			while(!req.complete)				pmu_poll();#else /* SUSPEND_USES_PMU */			if (gpio_irq >= 0)				disable_irq(gpio_irq);			out_8(&via[IER], CB1_INT | IER_CLR);			spin_unlock_irqrestore(&pmu_lock, flags);#endif /* SUSPEND_USES_PMU */			break;		}	} while (1);}void __openfirmwarepmu_resume(void){	unsigned long flags;	if (!via || (pmu_suspended < 1))		return;	spin_lock_irqsave(&pmu_lock, flags);	pmu_suspended--;	if (pmu_suspended > 0) {		spin_unlock_irqrestore(&pmu_lock, flags);		return;	}	adb_int_pending = 1;#ifdef SUSPEND_USES_PMU	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);	spin_unlock_irqrestore(&pmu_lock, flags);	while(!req.complete)		pmu_poll();#else /* SUSPEND_USES_PMU */	if (gpio_irq >= 0)		enable_irq(gpio_irq);	out_8(&via[IER], CB1_INT | IER_SET);	spin_unlock_irqrestore(&pmu_lock, flags);	pmu_poll();#endif /* SUSPEND_USES_PMU */}static void __openfirmwarevia_pmu_interrupt(int irq, void *arg, struct pt_regs *regs){	unsigned long flags;	int intr;	int nloop = 0;	/* This is a bit brutal, we can probably do better */	spin_lock_irqsave(&pmu_lock, flags);	++disable_poll;			for (;;) {		intr = in_8(&via[IFR]) & (SR_INT | CB1_INT);		if (intr == 0)			break;		if (++nloop > 1000) {			printk(KERN_DEBUG "PMU: stuck in intr loop, "			       "intr=%x, ier=%x pmu_state=%d\n",			       intr, in_8(&via[IER]), pmu_state);			break;		}		out_8(&via[IFR], intr);		if (intr & SR_INT)			pmu_sr_intr(regs);		if (intr & CB1_INT)			adb_int_pending = 1;	}	if (pmu_state == idle) {		if (adb_int_pending) {			pmu_state = intack;			/* Sounds safer to make sure ACK is high before writing.			 * This helped kill a problem with ADB and some iBooks			 */			wait_for_ack();			send_byte(PMU_INT_ACK);			adb_int_pending = 0;		} else if (current_req)			pmu_start();	}		--disable_poll;	spin_unlock_irqrestore(&pmu_lock, flags);}static void __openfirmwaregpio1_interrupt(int irq, void *arg, struct pt_regs *regs){	if ((in_8(gpio_reg + 0x9) & 0x02) == 0) {		adb_int_pending = 1;		via_pmu_interrupt(0, 0, 0);	}}static void __openfirmwarepmu_sr_intr(struct pt_regs *regs){	struct adb_request *req;	int bite;	if (via[B] & TREQ) {		printk(KERN_ERR "PMU: spurious SR intr (%x)\n", via[B]);		out_8(&via[IFR], SR_INT);		return;	}	/* The ack may not yet be low when we get the interrupt */	while ((in_8(&via[B]) & TACK) != 0)			;	/* if reading grab the byte, and reset the interrupt */	if (pmu_state == reading || pmu_state == reading_intr)		bite = in_8(&via[SR]);	/* reset TREQ and wait for TACK to go high */	out_8(&via[B], in_8(&via[B]) | TREQ);	wait_for_ack();	switch (pmu_state) {	case sending:		req = current_req;		if (data_len < 0) {			data_len = req->nbytes - 1;			send_byte(data_len);			break;		}		if (data_index <= data_len) {			send_byte(req->data[data_index++]);			break;		}		req->sent = 1;		data_len = pmu_data_len[req->data[0]][1];		if (data_len == 0) {			pmu_state = idle;			current_req = req->next;			if (req->reply_expected)				req_awaiting_reply = req;			else {				spin_unlock(&pmu_lock);				pmu_done(req);				spin_lock(&pmu_lock);			}		} else {			pmu_state = reading;			data_index = 0;			reply_ptr = req->reply + req->reply_len;			recv_byte();		}		break;	case intack:		data_index = 0;		data_len = -1;		pmu_state = reading_intr;		reply_ptr = interrupt_data;		recv_byte();		break;	case reading:	case reading_intr:		if (data_len == -1) {			data_len = bite;			if (bite > 32)				printk(KERN_ERR "PMU: bad reply len %d\n", bite);		} else if (data_index < 32) {			reply_ptr[data_index++] = bite;		}		if (data_index < data_len) {			recv_byte();			break;		}		if (pmu_state == reading_intr) {			spin_unlock(&pmu_lock);			pmu_handle_data(interrupt_data, data_index, regs);			spin_lock(&pmu_lock);		} else {			req = current_req;			current_req = req->next;			req->reply_len += data_index;			spin_unlock(&pmu_lock);			pmu_done(req);			spin_lock(&pmu_lock);		}		pmu_state = idle;		break;	default:		printk(KERN_ERR "via_pmu_interrupt: unknown state %d?\n",		       pmu_state);	}}static void __openfirmwarepmu_done(struct adb_request *req){	req->complete = 1;	if (req->done)		(*req->done)(req);}/* Interrupt data could be the result data from an ADB cmd */static void __openfirmwarepmu_handle_data(unsigned char *data, int len, struct pt_regs *regs){	asleep = 0;	if (drop_interrupts || len < 1) {		adb_int_pending = 0;		return;	}	/* Note: for some reason, we get an interrupt with len=1,	 * data[0]==0 after each normal ADB interrupt, at least	 * on the Pismo. Still investigating...  --BenH	 */	if (data[0] & PMU_INT_ADB) {		if ((data[0] & PMU_INT_ADB_AUTO) == 0) {			struct adb_request *req = req_awaiting_reply;			if (req == 0) {				printk(KERN_ERR "PMU: extra ADB reply\n");				return;			}			req_awaiting_reply = 0;			if (len <= 2)				req->reply_len = 0;			else {				memcpy(req->reply, data + 1, len - 1);				req->reply_len = len - 1;			}			pmu_done(req);		} else {#ifdef CONFIG_XMON			if (len == 4 && data[1] == 0x2c) {				extern int xmon_wants_key, xmon_adb_keycode;				if (xmon_wants_key) {					xmon_adb_keycode = data[2];					return;				}			}#endif /* CONFIG_XMON */#ifdef CONFIG_ADB			/*			 * XXX On the [23]400 the PMU gives us an up			 * event for keycodes 0x74 or 0x75 when the PC			 * card eject buttons are released, so we			 * ignore those events.			 */			if (!(pmu_kind == PMU_OHARE_BASED && len == 4			      && data[1] == 0x2c && data[3] == 0xff			      && (data[2] & ~1) == 0xf4))				adb_input(data+1, len-1, regs, 1);#endif /* CONFIG_ADB */				}	} else {		/* Sound/brightness button pressed */		if ((data[0] & PMU_INT_SNDBRT) && len == 3) {#ifdef CONFIG_PMAC_BACKLIGHT			set_backlight_level(data[1] >> 4);#endif		}#ifdef CONFIG_PMAC_PBOOK		/* Environement or tick interrupt, query batteries */		if (pmu_battery_count && (data[0] & PMU_INT_TICK)) {			if ((--query_batt_timer) == 0) {				query_battery_state();				query_batt_timer = BATTERY_POLLING_COUNT;			}		} else if (pmu_battery_count && (data[0] & PMU_INT_ENVIRONMENT))			query_battery_state(); 		if (data[0])			pmu_pass_intr(data, len);#endif /* CONFIG_PMAC_PBOOK */	}}#ifdef CONFIG_PMAC_BACKLIGHTstatic int backlight_to_bright[] = {	0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e,	0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e}; static int __openfirmwarepmu_set_backlight_enable(int on, int level, void* data){	struct adb_request req;		if (vias == NULL)		return -ENODEV;	if (on) {		pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT,			    backlight_to_bright[level]);		while (!req.complete)			pmu_poll();	}	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,		    PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF));	while (!req.complete)		pmu_poll();	return 0;}static int __openfirmwarepmu_set_backlight_level(int level, void* data){	if (vias == NULL)		return -ENODEV;	if (!bright_req_1.complete)		return -EAGAIN;	pmu_request(&bright_req_1, NULL, 2, PMU_BACKLIGHT_BRIGHT,		backlight_to_bright[level]);	if (!bright_req_2.complete)		return -EAGAIN;	pmu_request(&bright_req_2, NULL, 2, PMU_POWER_CTRL, PMU_POW_BACKLIGHT		| (level > BACKLIGHT_OFF ? PMU_POW_ON : PMU_POW_OFF));	return 0;}#endif /* CONFIG_PMAC_BACKLIGHT */void __openfirmwarepmu_enable_irled(int on){	struct adb_request req;	if (vias == NULL)		return ;	if (pmu_kind == PMU_KEYLARGO_BASED)		return ;	pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_IRLED |	    (on ? PMU_POW_ON : PMU_POW_OFF));	while (!req.complete)		pmu_poll();}void __openfirmwarepmu_restart(void){	struct adb_request req;	cli();	drop_interrupts = 1;		if (pmu_kind != PMU_KEYLARGO_BASED) {		pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |						PMU_INT_TICK );		while(!req.complete)			pmu_poll();	}	pmu_request(&req, NULL, 1, PMU_RESET);	while(!req.complete || (pmu_state != idle))		pmu_poll();	for (;;)		;}void __openfirmwarepmu_shutdown(void){	struct adb_request req;	cli();	drop_interrupts = 1;	if (pmu_kind != PMU_KEYLARGO_BASED) {		pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |						PMU_INT_TICK );		while(!req.complete)			pmu_poll();	}	pmu_request(&req, NULL, 5, PMU_SHUTDOWN,		    'M', 'A', 'T', 'T');	while(!req.complete || (pmu_state != idle))		pmu_poll();	for (;;)		;}intpmu_present(void){	return via != 0;}#ifdef CONFIG_PMAC_PBOOKstatic LIST_HEAD(sleep_notifiers);#ifdef CONFIG_PMstatic intgeneric_notify_sleep(struct pmu_sleep_notifier *self, int when){	switch (when) {		case PBOOK_SLEEP_NOW:			if (pm_send_all(PM_SUSPEND, (void *)3))				return PBOOK_SLEEP_REJECT;			break;		case PBOOK_WAKE:			(void) pm_send_all(PM_RESUME, (void *)0);	}

⌨️ 快捷键说明

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