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

📄 sa1111.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
 *	@dev: device to restore * *	Restore the general state of the SA1111; clock control and *	interrupt controller.  Other parts of the SA1111 must be *	restored by their respective drivers, and must be called *	via LDM after this function. */static int sa1111_resume(struct platform_device *dev){	struct sa1111 *sachip = platform_get_drvdata(dev);	struct sa1111_save_data *save;	unsigned long flags, id;	void __iomem *base;	save = (struct sa1111_save_data *)dev->dev.power.saved_state;	if (!save)		return 0;	spin_lock_irqsave(&sachip->lock, flags);	/*	 * Ensure that the SA1111 is still here.	 * FIXME: shouldn't do this here.	 */	id = sa1111_readl(sachip->base + SA1111_SKID);	if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {		__sa1111_remove(sachip);		platform_set_drvdata(dev, NULL);		kfree(save);		return 0;	}	/*	 * First of all, wake up the chip.	 */	sa1111_wake(sachip);	sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);	sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);	base = sachip->base;	sa1111_writel(save->skcr,     base + SA1111_SKCR);	sa1111_writel(save->skpcr,    base + SA1111_SKPCR);	sa1111_writel(save->skcdr,    base + SA1111_SKCDR);	sa1111_writel(save->skaud,    base + SA1111_SKAUD);	sa1111_writel(save->skpwm0,   base + SA1111_SKPWM0);	sa1111_writel(save->skpwm1,   base + SA1111_SKPWM1);	base = sachip->base + SA1111_INTC;	sa1111_writel(save->intpol0,  base + SA1111_INTPOL0);	sa1111_writel(save->intpol1,  base + SA1111_INTPOL1);	sa1111_writel(save->inten0,   base + SA1111_INTEN0);	sa1111_writel(save->inten1,   base + SA1111_INTEN1);	sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);	sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);	sa1111_writel(save->wakeen0,  base + SA1111_WAKEEN0);	sa1111_writel(save->wakeen1,  base + SA1111_WAKEEN1);	spin_unlock_irqrestore(&sachip->lock, flags);	dev->dev.power.saved_state = NULL;	kfree(save);	return 0;}#else#define sa1111_suspend NULL#define sa1111_resume  NULL#endifstatic int sa1111_probe(struct platform_device *pdev){	struct resource *mem;	int irq;	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);	if (!mem)		return -EINVAL;	irq = platform_get_irq(pdev, 0);	return __sa1111_probe(&pdev->dev, mem, irq);}static int sa1111_remove(struct platform_device *pdev){	struct sa1111 *sachip = platform_get_drvdata(pdev);	if (sachip) {		__sa1111_remove(sachip);		platform_set_drvdata(pdev, NULL);#ifdef CONFIG_PM		kfree(pdev->dev.power.saved_state);		pdev->dev.power.saved_state = NULL;#endif	}	return 0;}/* *	Not sure if this should be on the system bus or not yet. *	We really want some way to register a system device at *	the per-machine level, and then have this driver pick *	up the registered devices. * *	We also need to handle the SDRAM configuration for *	PXA250/SA1110 machine classes. */static struct platform_driver sa1111_device_driver = {	.probe		= sa1111_probe,	.remove		= sa1111_remove,	.suspend	= sa1111_suspend,	.resume		= sa1111_resume,	.driver		= {		.name	= "sa1111",	},};/* *	Get the parent device driver (us) structure *	from a child function device */static inline struct sa1111 *sa1111_chip_driver(struct sa1111_dev *sadev){	return (struct sa1111 *)dev_get_drvdata(sadev->dev.parent);}/* * The bits in the opdiv field are non-linear. */static unsigned char opdiv_table[] = { 1, 4, 2, 8 };static unsigned int __sa1111_pll_clock(struct sa1111 *sachip){	unsigned int skcdr, fbdiv, ipdiv, opdiv;	skcdr = sa1111_readl(sachip->base + SA1111_SKCDR);	fbdiv = (skcdr & 0x007f) + 2;	ipdiv = ((skcdr & 0x0f80) >> 7) + 2;	opdiv = opdiv_table[(skcdr & 0x3000) >> 12];	return 3686400 * fbdiv / (ipdiv * opdiv);}/** *	sa1111_pll_clock - return the current PLL clock frequency. *	@sadev: SA1111 function block * *	BUG: we should look at SKCR.  We also blindly believe that *	the chip is being fed with the 3.6864MHz clock. * *	Returns the PLL clock in Hz. */unsigned int sa1111_pll_clock(struct sa1111_dev *sadev){	struct sa1111 *sachip = sa1111_chip_driver(sadev);	return __sa1111_pll_clock(sachip);}/** *	sa1111_select_audio_mode - select I2S or AC link mode *	@sadev: SA1111 function block *	@mode: One of %SA1111_AUDIO_ACLINK or %SA1111_AUDIO_I2S * *	Frob the SKCR to select AC Link mode or I2S mode for *	the audio block. */void sa1111_select_audio_mode(struct sa1111_dev *sadev, int mode){	struct sa1111 *sachip = sa1111_chip_driver(sadev);	unsigned long flags;	unsigned int val;	spin_lock_irqsave(&sachip->lock, flags);	val = sa1111_readl(sachip->base + SA1111_SKCR);	if (mode == SA1111_AUDIO_I2S) {		val &= ~SKCR_SELAC;	} else {		val |= SKCR_SELAC;	}	sa1111_writel(val, sachip->base + SA1111_SKCR);	spin_unlock_irqrestore(&sachip->lock, flags);}/** *	sa1111_set_audio_rate - set the audio sample rate *	@sadev: SA1111 SAC function block *	@rate: sample rate to select */int sa1111_set_audio_rate(struct sa1111_dev *sadev, int rate){	struct sa1111 *sachip = sa1111_chip_driver(sadev);	unsigned int div;	if (sadev->devid != SA1111_DEVID_SAC)		return -EINVAL;	div = (__sa1111_pll_clock(sachip) / 256 + rate / 2) / rate;	if (div == 0)		div = 1;	if (div > 128)		div = 128;	sa1111_writel(div - 1, sachip->base + SA1111_SKAUD);	return 0;}/** *	sa1111_get_audio_rate - get the audio sample rate *	@sadev: SA1111 SAC function block device */int sa1111_get_audio_rate(struct sa1111_dev *sadev){	struct sa1111 *sachip = sa1111_chip_driver(sadev);	unsigned long div;	if (sadev->devid != SA1111_DEVID_SAC)		return -EINVAL;	div = sa1111_readl(sachip->base + SA1111_SKAUD) + 1;	return __sa1111_pll_clock(sachip) / (256 * div);}void sa1111_set_io_dir(struct sa1111_dev *sadev,		       unsigned int bits, unsigned int dir,		       unsigned int sleep_dir){	struct sa1111 *sachip = sa1111_chip_driver(sadev);	unsigned long flags;	unsigned int val;	void __iomem *gpio = sachip->base + SA1111_GPIO;#define MODIFY_BITS(port, mask, dir)		\	if (mask) {				\		val = sa1111_readl(port);	\		val &= ~(mask);			\		val |= (dir) & (mask);		\		sa1111_writel(val, port);	\	}	spin_lock_irqsave(&sachip->lock, flags);	MODIFY_BITS(gpio + SA1111_GPIO_PADDR, bits & 15, dir);	MODIFY_BITS(gpio + SA1111_GPIO_PBDDR, (bits >> 8) & 255, dir >> 8);	MODIFY_BITS(gpio + SA1111_GPIO_PCDDR, (bits >> 16) & 255, dir >> 16);	MODIFY_BITS(gpio + SA1111_GPIO_PASDR, bits & 15, sleep_dir);	MODIFY_BITS(gpio + SA1111_GPIO_PBSDR, (bits >> 8) & 255, sleep_dir >> 8);	MODIFY_BITS(gpio + SA1111_GPIO_PCSDR, (bits >> 16) & 255, sleep_dir >> 16);	spin_unlock_irqrestore(&sachip->lock, flags);}void sa1111_set_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v){	struct sa1111 *sachip = sa1111_chip_driver(sadev);	unsigned long flags;	unsigned int val;	void __iomem *gpio = sachip->base + SA1111_GPIO;	spin_lock_irqsave(&sachip->lock, flags);	MODIFY_BITS(gpio + SA1111_GPIO_PADWR, bits & 15, v);	MODIFY_BITS(gpio + SA1111_GPIO_PBDWR, (bits >> 8) & 255, v >> 8);	MODIFY_BITS(gpio + SA1111_GPIO_PCDWR, (bits >> 16) & 255, v >> 16);	spin_unlock_irqrestore(&sachip->lock, flags);}void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v){	struct sa1111 *sachip = sa1111_chip_driver(sadev);	unsigned long flags;	unsigned int val;	void __iomem *gpio = sachip->base + SA1111_GPIO;	spin_lock_irqsave(&sachip->lock, flags);	MODIFY_BITS(gpio + SA1111_GPIO_PASSR, bits & 15, v);	MODIFY_BITS(gpio + SA1111_GPIO_PBSSR, (bits >> 8) & 255, v >> 8);	MODIFY_BITS(gpio + SA1111_GPIO_PCSSR, (bits >> 16) & 255, v >> 16);	spin_unlock_irqrestore(&sachip->lock, flags);}/* * Individual device operations. *//** *	sa1111_enable_device - enable an on-chip SA1111 function block *	@sadev: SA1111 function block device to enable */void sa1111_enable_device(struct sa1111_dev *sadev){	struct sa1111 *sachip = sa1111_chip_driver(sadev);	unsigned long flags;	unsigned int val;	spin_lock_irqsave(&sachip->lock, flags);	val = sa1111_readl(sachip->base + SA1111_SKPCR);	sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR);	spin_unlock_irqrestore(&sachip->lock, flags);}/** *	sa1111_disable_device - disable an on-chip SA1111 function block *	@sadev: SA1111 function block device to disable */void sa1111_disable_device(struct sa1111_dev *sadev){	struct sa1111 *sachip = sa1111_chip_driver(sadev);	unsigned long flags;	unsigned int val;	spin_lock_irqsave(&sachip->lock, flags);	val = sa1111_readl(sachip->base + SA1111_SKPCR);	sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR);	spin_unlock_irqrestore(&sachip->lock, flags);}/* *	SA1111 "Register Access Bus." * *	We model this as a regular bus type, and hang devices directly *	off this. */static int sa1111_match(struct device *_dev, struct device_driver *_drv){	struct sa1111_dev *dev = SA1111_DEV(_dev);	struct sa1111_driver *drv = SA1111_DRV(_drv);	return dev->devid == drv->devid;}static int sa1111_bus_suspend(struct device *dev, pm_message_t state){	struct sa1111_dev *sadev = SA1111_DEV(dev);	struct sa1111_driver *drv = SA1111_DRV(dev->driver);	int ret = 0;	if (drv && drv->suspend)		ret = drv->suspend(sadev, state);	return ret;}static int sa1111_bus_resume(struct device *dev){	struct sa1111_dev *sadev = SA1111_DEV(dev);	struct sa1111_driver *drv = SA1111_DRV(dev->driver);	int ret = 0;	if (drv && drv->resume)		ret = drv->resume(sadev);	return ret;}static int sa1111_bus_probe(struct device *dev){	struct sa1111_dev *sadev = SA1111_DEV(dev);	struct sa1111_driver *drv = SA1111_DRV(dev->driver);	int ret = -ENODEV;	if (drv->probe)		ret = drv->probe(sadev);	return ret;}static int sa1111_bus_remove(struct device *dev){	struct sa1111_dev *sadev = SA1111_DEV(dev);	struct sa1111_driver *drv = SA1111_DRV(dev->driver);	int ret = 0;	if (drv->remove)		ret = drv->remove(sadev);	return ret;}struct bus_type sa1111_bus_type = {	.name		= "sa1111-rab",	.match		= sa1111_match,	.suspend	= sa1111_bus_suspend,	.resume		= sa1111_bus_resume,};int sa1111_driver_register(struct sa1111_driver *driver){	driver->drv.probe = sa1111_bus_probe;	driver->drv.remove = sa1111_bus_remove;	driver->drv.bus = &sa1111_bus_type;	return driver_register(&driver->drv);}void sa1111_driver_unregister(struct sa1111_driver *driver){	driver_unregister(&driver->drv);}static int __init sa1111_init(void){	int ret = bus_register(&sa1111_bus_type);	if (ret == 0)		platform_driver_register(&sa1111_device_driver);	return ret;}static void __exit sa1111_exit(void){	platform_driver_unregister(&sa1111_device_driver);	bus_unregister(&sa1111_bus_type);}subsys_initcall(sa1111_init);module_exit(sa1111_exit);MODULE_DESCRIPTION("Intel Corporation SA1111 core driver");MODULE_LICENSE("GPL");EXPORT_SYMBOL(sa1111_select_audio_mode);EXPORT_SYMBOL(sa1111_set_audio_rate);EXPORT_SYMBOL(sa1111_get_audio_rate);EXPORT_SYMBOL(sa1111_set_io_dir);EXPORT_SYMBOL(sa1111_set_io);EXPORT_SYMBOL(sa1111_set_sleep_io);EXPORT_SYMBOL(sa1111_enable_device);EXPORT_SYMBOL(sa1111_disable_device);EXPORT_SYMBOL(sa1111_pll_clock);EXPORT_SYMBOL(sa1111_bus_type);EXPORT_SYMBOL(sa1111_driver_register);EXPORT_SYMBOL(sa1111_driver_unregister);

⌨️ 快捷键说明

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