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

📄 via-pmu.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		return ret;	}		/* Turn off various things. Darwin does some retry tests here... */	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE);	pmu_wait_complete(&req);	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,		PMU_POW_OFF|PMU_POW_BACKLIGHT|PMU_POW_IRLED|PMU_POW_MEDIABAY);	pmu_wait_complete(&req);	/* For 750, save backside cache setting and disable it */	save_l2cr = _get_L2CR();	/* (returns -1 if not available) */	if (!__fake_sleep) {		/* Ask the PMU to put us to sleep */		pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');		pmu_wait_complete(&req);	}	/* The VIA is supposed not to be restored correctly*/	save_via_state();	/* We shut down some HW */	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);	pci_read_config_word(grackle, 0x70, &pmcr1);	/* Apparently, MacOS uses NAP mode for Grackle ??? */	pmcr1 &= ~(GRACKLE_DOZE|GRACKLE_SLEEP); 	pmcr1 |= GRACKLE_PM|GRACKLE_NAP;	pci_write_config_word(grackle, 0x70, pmcr1);	/* Call low-level ASM sleep handler */	if (__fake_sleep)		mdelay(5000);	else		low_sleep_handler();	/* We're awake again, stop grackle PM */	pci_read_config_word(grackle, 0x70, &pmcr1);	pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); 	pci_write_config_word(grackle, 0x70, pmcr1);	pci_dev_put(grackle);	/* Make sure the PMU is idle */	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);	restore_via_state();		/* Restore L2 cache */	if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) 		_set_L2CR(save_l2cr);		/* Restore userland MMU context */	set_context(current->active_mm->context.id, current->active_mm->pgd);	/* Power things up */	pmu_unlock();	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);	pmu_wait_complete(&req);	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0,			PMU_POW0_ON|PMU_POW0_HARD_DRIVE);	pmu_wait_complete(&req);	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,			PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY);	pmu_wait_complete(&req);	pmac_wakeup_devices();	return 0;}static intpowerbook_sleep_Core99(void){	unsigned long save_l2cr;	unsigned long save_l3cr;	struct adb_request req;	int ret;		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) {		printk(KERN_ERR "Sleep mode not supported on this machine\n");		return -ENOSYS;	}	if (num_online_cpus() > 1 || cpu_is_offline(0))		return -EAGAIN;	ret = pmac_suspend_devices();	if (ret) {		printk(KERN_ERR "Sleep rejected by devices\n");		return ret;	}	/* Stop environment and ADB interrupts */	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);	pmu_wait_complete(&req);	/* Tell PMU what events will wake us up */	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,		0xff, 0xff);	pmu_wait_complete(&req);	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_SET_WAKEUP_EVENTS,		0, PMU_PWR_WAKEUP_KEY |		(option_lid_wakeup ? PMU_PWR_WAKEUP_LID_OPEN : 0));	pmu_wait_complete(&req);	/* Save the state of the L2 and L3 caches */	save_l3cr = _get_L3CR();	/* (returns -1 if not available) */	save_l2cr = _get_L2CR();	/* (returns -1 if not available) */	if (!__fake_sleep) {		/* Ask the PMU to put us to sleep */		pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');		pmu_wait_complete(&req);	}	/* The VIA is supposed not to be restored correctly*/	save_via_state();	/* Shut down various ASICs. There's a chance that we can no longer	 * talk to the PMU after this, so I moved it to _after_ sending the	 * sleep command to it. Still need to be checked.	 */	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1);	/* Call low-level ASM sleep handler */	if (__fake_sleep)		mdelay(5000);	else		low_sleep_handler();	/* Restore Apple core ASICs state */	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);	/* Restore VIA */	restore_via_state();	/* tweak LPJ before cpufreq is there */	loops_per_jiffy *= 2;	/* Restore video */	pmac_call_early_video_resume();	/* Restore L2 cache */	if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) 		_set_L2CR(save_l2cr);	/* Restore L3 cache */	if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) 		_set_L3CR(save_l3cr);		/* Restore userland MMU context */	set_context(current->active_mm->context.id, current->active_mm->pgd);	/* Tell PMU we are ready */	pmu_unlock();	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);	pmu_wait_complete(&req);	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);	pmu_wait_complete(&req);	/* Restore LPJ, cpufreq will adjust the cpu frequency */	loops_per_jiffy /= 2;	pmac_wakeup_devices();	return 0;}#define PB3400_MEM_CTRL		0xf8000000#define PB3400_MEM_CTRL_SLEEP	0x70static intpowerbook_sleep_3400(void){	int ret, i, x;	unsigned int hid0;	unsigned long p;	struct adb_request sleep_req;	void __iomem *mem_ctrl;	unsigned int __iomem *mem_ctrl_sleep;	/* first map in the memory controller registers */	mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);	if (mem_ctrl == NULL) {		printk("powerbook_sleep_3400: ioremap failed\n");		return -ENOMEM;	}	mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP;	/* Allocate room for PCI save */	pbook_alloc_pci_save();	ret = pmac_suspend_devices();	if (ret) {		pbook_free_pci_save();		iounmap(mem_ctrl);		printk(KERN_ERR "Sleep rejected by devices\n");		return ret;	}	/* Save the state of PCI config space for some slots */	pbook_pci_save();	/* Set the memory controller to keep the memory refreshed	   while we're asleep */	for (i = 0x403f; i >= 0x4000; --i) {		out_be32(mem_ctrl_sleep, i);		do {			x = (in_be32(mem_ctrl_sleep) >> 16) & 0x3ff;		} while (x == 0);		if (x >= 0x100)			break;	}	/* Ask the PMU to put us to sleep */	pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');	while (!sleep_req.complete)		mb();	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);	/* displacement-flush the L2 cache - necessary? */	for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000)		i = *(volatile int *)p;	asleep = 1;	/* Put the CPU into sleep mode */	hid0 = mfspr(SPRN_HID0);	hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;	mtspr(SPRN_HID0, hid0);	mtmsr(mfmsr() | MSR_POW | MSR_EE);	udelay(10);	/* OK, we're awake again, start restoring things */	out_be32(mem_ctrl_sleep, 0x3f);	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);	pbook_pci_restore();	pmu_unlock();	/* wait for the PMU interrupt sequence to complete */	while (asleep)		mb();	pmac_wakeup_devices();	pbook_free_pci_save();	iounmap(mem_ctrl);	return 0;}#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 *//* * Support for /dev/pmu device */#define RB_SIZE		0x10struct pmu_private {	struct list_head list;	int	rb_get;	int	rb_put;	struct rb_entry {		unsigned short len;		unsigned char data[16];	}	rb_buf[RB_SIZE];	wait_queue_head_t wait;	spinlock_t lock;#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)	int	backlight_locker;#endif};static LIST_HEAD(all_pmu_pvt);static DEFINE_SPINLOCK(all_pvt_lock);static voidpmu_pass_intr(unsigned char *data, int len){	struct pmu_private *pp;	struct list_head *list;	int i;	unsigned long flags;	if (len > sizeof(pp->rb_buf[0].data))		len = sizeof(pp->rb_buf[0].data);	spin_lock_irqsave(&all_pvt_lock, flags);	for (list = &all_pmu_pvt; (list = list->next) != &all_pmu_pvt; ) {		pp = list_entry(list, struct pmu_private, list);		spin_lock(&pp->lock);		i = pp->rb_put + 1;		if (i >= RB_SIZE)			i = 0;		if (i != pp->rb_get) {			struct rb_entry *rp = &pp->rb_buf[pp->rb_put];			rp->len = len;			memcpy(rp->data, data, len);			pp->rb_put = i;			wake_up_interruptible(&pp->wait);		}		spin_unlock(&pp->lock);	}	spin_unlock_irqrestore(&all_pvt_lock, flags);}static intpmu_open(struct inode *inode, struct file *file){	struct pmu_private *pp;	unsigned long flags;	pp = kmalloc(sizeof(struct pmu_private), GFP_KERNEL);	if (pp == 0)		return -ENOMEM;	pp->rb_get = pp->rb_put = 0;	spin_lock_init(&pp->lock);	init_waitqueue_head(&pp->wait);	spin_lock_irqsave(&all_pvt_lock, flags);#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)	pp->backlight_locker = 0;#endif	list_add(&pp->list, &all_pmu_pvt);	spin_unlock_irqrestore(&all_pvt_lock, flags);	file->private_data = pp;	return 0;}static ssize_t pmu_read(struct file *file, char __user *buf,			size_t count, loff_t *ppos){	struct pmu_private *pp = file->private_data;	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	int ret = 0;	if (count < 1 || pp == 0)		return -EINVAL;	if (!access_ok(VERIFY_WRITE, buf, count))		return -EFAULT;	spin_lock_irqsave(&pp->lock, flags);	add_wait_queue(&pp->wait, &wait);	current->state = TASK_INTERRUPTIBLE;	for (;;) {		ret = -EAGAIN;		if (pp->rb_get != pp->rb_put) {			int i = pp->rb_get;			struct rb_entry *rp = &pp->rb_buf[i];			ret = rp->len;			spin_unlock_irqrestore(&pp->lock, flags);			if (ret > count)				ret = count;			if (ret > 0 && copy_to_user(buf, rp->data, ret))				ret = -EFAULT;			if (++i >= RB_SIZE)				i = 0;			spin_lock_irqsave(&pp->lock, flags);			pp->rb_get = i;		}		if (ret >= 0)			break;		if (file->f_flags & O_NONBLOCK)			break;		ret = -ERESTARTSYS;		if (signal_pending(current))			break;		spin_unlock_irqrestore(&pp->lock, flags);		schedule();		spin_lock_irqsave(&pp->lock, flags);	}	current->state = TASK_RUNNING;	remove_wait_queue(&pp->wait, &wait);	spin_unlock_irqrestore(&pp->lock, flags);		return ret;}static ssize_tpmu_write(struct file *file, const char __user *buf,			 size_t count, loff_t *ppos){	return 0;}static unsigned intpmu_fpoll(struct file *filp, poll_table *wait){	struct pmu_private *pp = filp->private_data;	unsigned int mask = 0;	unsigned long flags;		if (pp == 0)		return 0;	poll_wait(filp, &pp->wait, wait);	spin_lock_irqsave(&pp->lock, flags);	if (pp->rb_get != pp->rb_put)		mask |= POLLIN;	spin_unlock_irqrestore(&pp->lock, flags);	return mask;}static intpmu_release(struct inode *inode, struct file *file){	struct pmu_private *pp = file->private_data;	unsigned long flags;	lock_kernel();	if (pp != 0) {		file->private_data = NULL;		spin_lock_irqsave(&all_pvt_lock, flags);		list_del(&pp->list);		spin_unlock_irqrestore(&all_pvt_lock, flags);#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)		if (pp->backlight_locker)			pmac_backlight_enable();#endif		kfree(pp);	}	unlock_kernel();	return 0;}static intpmu_ioctl(struct inode * inode, struct file *filp,		     u_int cmd, u_long arg){	__u32 __user *argp = (__u32 __user *)arg;	int error = -EINVAL;	switch (cmd) {#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)	case PMU_IOC_SLEEP:		if (!capable(CAP_SYS_ADMIN))			return -EACCES;		if (sleep_in_progress)			return -EBUSY;		sleep_in_progress = 1;		switch (pmu_kind) {		case PMU_OHARE_BASED:			error = powerbook_sleep_3400();			break;		case PMU_HEATHROW_BASED:		case PMU_PADDINGTON_BASED:			error = powerbook_sleep_grackle();			break;		case PMU_KEYLARGO_BASED:			error = powerbook_sleep_Core99();			break;		default:			error = -ENOSYS;		}		sleep_in_progress = 0;		break;	case PMU_IOC_CAN_SLEEP:		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)			return put_user(0, argp);		else			return put_user(1, argp);#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */#ifdef CONFIG_PMAC_BACKLIGHT_LEGACY	/* Compatibility ioctl's for backlight */	case PMU_IOC_GET_BACKLIGHT:	{		int brightness;		if (sleep_in_progress)			return -EBUSY;		brightness = pmac_backlight_get_legacy_brightness();		if (brightness < 0)			return brightness;		else			return put_user(brightness, argp);	}	case PMU_IOC_SET_BACKLIGHT:	{		int brightness;		if (sleep_in_progress)			return -EBUSY;		error = get_user(brightness, argp);		if (error)			return error;		return pmac_backlight_set_legacy_brightness(brightness);	}#ifdef CONFIG_INPUT_ADBHID	case PMU_IOC_GRAB_BACKLIGHT: {		struct pmu_private *pp = filp->private_data;		if (pp->backlight_locker)			return 0;		pp->backlight_locker = 1;		pmac_backlight_disable();		return 0;	}#endif /* CONFIG_INPUT_ADBHID */#endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */	case PMU_IOC_GET_MODEL:	    	return put_user(pmu_kind, argp);	case PMU_IOC_HAS_ADB:		return put_user(pmu_has_adb, argp);	}	return error;}static const struct file_operations pmu_device_fops = {	.read		= pmu_read,	.write		= pmu_write,	.poll		= pmu_fpoll,	.ioctl		= pmu_ioctl,	.open		= pmu_open,	.release	= pmu_release,};static struct miscdevice pmu_device = {	PMU_MINOR, "pmu", &pmu_device_fops};static int pmu_device_init(void){	if (!via)		return 0;	if (misc_register(&pmu_device) < 0)		printk(KERN_ERR "via-pmu: cannot register misc device.\n");	return 0;}device_i

⌨️ 快捷键说明

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