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

📄 locomo.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	set_irq_flags(IRQ_LOCOMO_LT_BASE, IRQF_VALID | IRQF_PROBE);	set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip);	set_irq_chipdata(IRQ_LOCOMO_SPI_BASE, irqbase);	set_irq_chained_handler(IRQ_LOCOMO_SPI_BASE, locomo_spi_handler);	set_irq_flags(IRQ_LOCOMO_SPI_BASE, IRQF_VALID | IRQF_PROBE);	/* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */	set_irq_chip(LOCOMO_IRQ_KEY_START, &locomo_key_chip);	set_irq_chipdata(LOCOMO_IRQ_KEY_START, irqbase);	set_irq_handler(LOCOMO_IRQ_KEY_START, do_edge_IRQ);	set_irq_flags(LOCOMO_IRQ_KEY_START, IRQF_VALID | IRQF_PROBE);	/* install handlers for IRQ_LOCOMO_GPIO_BASE generated interrupts */	for (irq = LOCOMO_IRQ_GPIO_START; irq < LOCOMO_IRQ_GPIO_START + 16; irq++) {		set_irq_chip(irq, &locomo_gpio_chip);		set_irq_chipdata(irq, irqbase);		set_irq_handler(irq, do_edge_IRQ);		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);	}	/* install handlers for IRQ_LOCOMO_LT_BASE generated interrupts */	set_irq_chip(LOCOMO_IRQ_LT_START, &locomo_lt_chip);	set_irq_chipdata(LOCOMO_IRQ_LT_START, irqbase);	set_irq_handler(LOCOMO_IRQ_LT_START, do_edge_IRQ);	set_irq_flags(LOCOMO_IRQ_LT_START, IRQF_VALID | IRQF_PROBE);	/* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */	for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 3; irq++) {		set_irq_chip(irq, &locomo_spi_chip);		set_irq_chipdata(irq, irqbase);		set_irq_handler(irq, do_edge_IRQ);		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);	}}static void locomo_dev_release(struct device *_dev){	struct locomo_dev *dev = LOCOMO_DEV(_dev);	release_resource(&dev->res);	kfree(dev);}static intlocomo_init_one_child(struct locomo *lchip, struct resource *parent,		      struct locomo_dev_info *info){	struct locomo_dev *dev;	int ret;	dev = kmalloc(sizeof(struct locomo_dev), GFP_KERNEL);	if (!dev) {		ret = -ENOMEM;		goto out;	}	memset(dev, 0, sizeof(struct locomo_dev));	strncpy(dev->dev.bus_id,info->name,sizeof(dev->dev.bus_id));	/*	 * If the parent device has a DMA mask associated with it,	 * propagate it down to the children.	 */	if (lchip->dev->dma_mask) {		dev->dma_mask = *lchip->dev->dma_mask;		dev->dev.dma_mask = &dev->dma_mask;	}	dev->devid	 = info->devid;	dev->dev.parent  = lchip->dev;	dev->dev.bus     = &locomo_bus_type;	dev->dev.release = locomo_dev_release;	dev->dev.coherent_dma_mask = lchip->dev->coherent_dma_mask;	dev->res.start   = lchip->phys + info->offset;	dev->res.end     = dev->res.start + info->length;	dev->res.name    = dev->dev.bus_id;	dev->res.flags   = IORESOURCE_MEM;	dev->mapbase     = lchip->base + info->offset;	memmove(dev->irq, info->irq, sizeof(dev->irq));	if (info->length) {		ret = request_resource(parent, &dev->res);		if (ret) {			printk("LoCoMo: failed to allocate resource for %s\n",				dev->res.name);			goto out;		}	}	ret = device_register(&dev->dev);	if (ret) {		release_resource(&dev->res); out:		kfree(dev);	}	return ret;}/** *	locomo_probe - probe for a single LoCoMo chip. *	@phys_addr: physical address of device. * *	Probe for a LoCoMo chip.  This must be called *	before any other locomo-specific code. * *	Returns: *	%-ENODEV	device not found. *	%-EBUSY		physical address already marked in-use. *	%0		successful. */static int__locomo_probe(struct device *me, struct resource *mem, int irq){	struct locomo *lchip;	unsigned long r;	int i, ret = -ENODEV;	lchip = kmalloc(sizeof(struct locomo), GFP_KERNEL);	if (!lchip)		return -ENOMEM;	memset(lchip, 0, sizeof(struct locomo));	lchip->dev = me;	dev_set_drvdata(lchip->dev, lchip);	lchip->phys = mem->start;	lchip->irq = irq;	/*	 * Map the whole region.  This also maps the	 * registers for our children.	 */	lchip->base = ioremap(mem->start, PAGE_SIZE);	if (!lchip->base) {		ret = -ENOMEM;		goto out;	}	/* locomo initialize */	locomo_writel(0, lchip->base + LOCOMO_ICR);	/* KEYBOARD */	locomo_writel(0, lchip->base + LOCOMO_KIC);	/* GPIO */	locomo_writel(0, lchip->base + LOCOMO_GPO);	locomo_writel( (LOCOMO_GPIO(2) | LOCOMO_GPIO(3) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14))			, lchip->base + LOCOMO_GPE);	locomo_writel( (LOCOMO_GPIO(2) | LOCOMO_GPIO(3) | LOCOMO_GPIO(13) | LOCOMO_GPIO(14))			, lchip->base + LOCOMO_GPD);	locomo_writel(0, lchip->base + LOCOMO_GIE);	/* FrontLight */	locomo_writel(0, lchip->base + LOCOMO_ALS);	locomo_writel(0, lchip->base + LOCOMO_ALD);	/* Longtime timer */	locomo_writel(0, lchip->base + LOCOMO_LTINT);	/* SPI */	locomo_writel(0, lchip->base + LOCOMO_SPIIE);	locomo_writel(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD);	r = locomo_readl(lchip->base + LOCOMO_ASD);	r |= 0x8000;	locomo_writel(r, lchip->base + LOCOMO_ASD);	locomo_writel(6 + 8 + 320 + 30 - 10 - 128 + 4, lchip->base + LOCOMO_HSD);	r = locomo_readl(lchip->base + LOCOMO_HSD);	r |= 0x8000;	locomo_writel(r, lchip->base + LOCOMO_HSD);	locomo_writel(128 / 8, lchip->base + LOCOMO_HSC);	/* XON */	locomo_writel(0x80, lchip->base + LOCOMO_TADC);	udelay(1000);	/* CLK9MEN */	r = locomo_readl(lchip->base + LOCOMO_TADC);	r |= 0x10;	locomo_writel(r, lchip->base + LOCOMO_TADC);	udelay(100);	/* init DAC */	r = locomo_readl(lchip->base + LOCOMO_DAC);	r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;	locomo_writel(r, lchip->base + LOCOMO_DAC);	r = locomo_readl(lchip->base + LOCOMO_VER);	printk(KERN_INFO "LoCoMo Chip: %lu%lu\n", (r >> 8), (r & 0xff));	/*	 * The interrupt controller must be initialised before any	 * other device to ensure that the interrupts are available.	 */	if (lchip->irq != NO_IRQ)		locomo_setup_irq(lchip);	for (i = 0; i < ARRAY_SIZE(locomo_devices); i++)		locomo_init_one_child(lchip, mem, &locomo_devices[i]);	return 0; out:	kfree(lchip);	return ret;}static void __locomo_remove(struct locomo *lchip){	struct list_head *l, *n;	list_for_each_safe(l, n, &lchip->dev->children) {		struct device *d = list_to_dev(l);		device_unregister(d);	}	if (lchip->irq != NO_IRQ) {		set_irq_chained_handler(lchip->irq, NULL);		set_irq_data(lchip->irq, NULL);	}	iounmap(lchip->base);	kfree(lchip);}static int locomo_probe(struct device *dev){	struct platform_device *pdev = to_platform_device(dev);	struct resource *mem = NULL, *irq = NULL;	int i;	for (i = 0; i < pdev->num_resources; i++) {		if (pdev->resource[i].flags & IORESOURCE_MEM)			mem = &pdev->resource[i];		if (pdev->resource[i].flags & IORESOURCE_IRQ)			irq = &pdev->resource[i];	}	return __locomo_probe(dev, mem, irq ? irq->start : NO_IRQ);}static int locomo_remove(struct device *dev){	struct locomo *lchip = dev_get_drvdata(dev);	if (lchip) {		__locomo_remove(lchip);		dev_set_drvdata(dev, NULL);		kfree(dev->saved_state);		dev->saved_state = NULL;	}	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. */static struct device_driver locomo_device_driver = {	.name		= "locomo",	.bus		= &platform_bus_type,	.probe		= locomo_probe,	.remove		= locomo_remove,};/* *	Get the parent device driver (us) structure *	from a child function device */static inline struct locomo *locomo_chip_driver(struct locomo_dev *ldev){	return (struct locomo *)dev_get_drvdata(ldev->dev.parent);}/* *	LoCoMo "Register Access Bus." * *	We model this as a regular bus type, and hang devices directly *	off this. */static int locomo_match(struct device *_dev, struct device_driver *_drv){	struct locomo_dev *dev = LOCOMO_DEV(_dev);	struct locomo_driver *drv = LOCOMO_DRV(_drv);	return dev->devid == drv->devid;}static int locomo_bus_suspend(struct device *dev, u32 state){	struct locomo_dev *ldev = LOCOMO_DEV(dev);	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);	int ret = 0;	if (drv && drv->suspend)		ret = drv->suspend(ldev, state);	return ret;}static int locomo_bus_resume(struct device *dev){	struct locomo_dev *ldev = LOCOMO_DEV(dev);	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);	int ret = 0;	if (drv && drv->resume)		ret = drv->resume(ldev);	return ret;}static int locomo_bus_probe(struct device *dev){	struct locomo_dev *ldev = LOCOMO_DEV(dev);	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);	int ret = -ENODEV;	if (drv->probe)		ret = drv->probe(ldev);	return ret;}static int locomo_bus_remove(struct device *dev){	struct locomo_dev *ldev = LOCOMO_DEV(dev);	struct locomo_driver *drv = LOCOMO_DRV(dev->driver);	int ret = 0;	if (drv->remove)		ret = drv->remove(ldev);	return ret;}struct bus_type locomo_bus_type = {	.name		= "locomo-bus",	.match		= locomo_match,	.suspend	= locomo_bus_suspend,	.resume		= locomo_bus_resume,};int locomo_driver_register(struct locomo_driver *driver){	driver->drv.probe = locomo_bus_probe;	driver->drv.remove = locomo_bus_remove;	driver->drv.bus = &locomo_bus_type;	return driver_register(&driver->drv);}void locomo_driver_unregister(struct locomo_driver *driver){	driver_unregister(&driver->drv);}static int __init locomo_init(void){	int ret = bus_register(&locomo_bus_type);	if (ret == 0)		driver_register(&locomo_device_driver);	return ret;}static void __exit locomo_exit(void){	driver_unregister(&locomo_device_driver);	bus_unregister(&locomo_bus_type);}module_init(locomo_init);module_exit(locomo_exit);MODULE_DESCRIPTION("Sharp LoCoMo core driver");MODULE_LICENSE("GPL");MODULE_AUTHOR("John Lenz <jelenz@students.wisc.edu>");EXPORT_SYMBOL(locomo_driver_register);EXPORT_SYMBOL(locomo_driver_unregister);

⌨️ 快捷键说明

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