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

📄 locomo.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIS);	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIS);	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);}static void locomo_spi_mask_irq(unsigned int irq){	void __iomem *mapbase = get_irq_chip_data(irq);	unsigned int r;	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);}static void locomo_spi_unmask_irq(unsigned int irq){	void __iomem *mapbase = get_irq_chip_data(irq);	unsigned int r;	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);	r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);}static struct irq_chip locomo_spi_chip = {	.name	= "LOCOMO-spi",	.ack	= locomo_spi_ack_irq,	.mask	= locomo_spi_mask_irq,	.unmask	= locomo_spi_unmask_irq,};static void locomo_setup_irq(struct locomo *lchip){	int irq;	void __iomem *irqbase = lchip->base;	/*	 * Install handler for IRQ_LOCOMO_HW.	 */	set_irq_type(lchip->irq, IRQT_FALLING);	set_irq_chip_data(lchip->irq, irqbase);	set_irq_chained_handler(lchip->irq, locomo_handler);	/* Install handlers for IRQ_LOCOMO_*_BASE */	set_irq_chip(IRQ_LOCOMO_KEY_BASE, &locomo_chip);	set_irq_chip_data(IRQ_LOCOMO_KEY_BASE, irqbase);	set_irq_chained_handler(IRQ_LOCOMO_KEY_BASE, locomo_key_handler);	set_irq_flags(IRQ_LOCOMO_KEY_BASE, IRQF_VALID | IRQF_PROBE);	set_irq_chip(IRQ_LOCOMO_GPIO_BASE, &locomo_chip);	set_irq_chip_data(IRQ_LOCOMO_GPIO_BASE, irqbase);	set_irq_chained_handler(IRQ_LOCOMO_GPIO_BASE, locomo_gpio_handler);	set_irq_flags(IRQ_LOCOMO_GPIO_BASE, IRQF_VALID | IRQF_PROBE);	set_irq_chip(IRQ_LOCOMO_LT_BASE, &locomo_chip);	set_irq_chip_data(IRQ_LOCOMO_LT_BASE, irqbase);	set_irq_chained_handler(IRQ_LOCOMO_LT_BASE, locomo_lt_handler);	set_irq_flags(IRQ_LOCOMO_LT_BASE, IRQF_VALID | IRQF_PROBE);	set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip);	set_irq_chip_data(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_chip_data(LOCOMO_IRQ_KEY_START, irqbase);	set_irq_handler(LOCOMO_IRQ_KEY_START, handle_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_chip_data(irq, irqbase);		set_irq_handler(irq, handle_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_chip_data(LOCOMO_IRQ_LT_START, irqbase);	set_irq_handler(LOCOMO_IRQ_LT_START, handle_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_chip_data(irq, irqbase);		set_irq_handler(irq, handle_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);	kfree(dev);}static intlocomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info){	struct locomo_dev *dev;	int ret;	dev = kzalloc(sizeof(struct locomo_dev), GFP_KERNEL);	if (!dev) {		ret = -ENOMEM;		goto out;	}	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;	if (info->offset)		dev->mapbase = lchip->base + info->offset;	else		dev->mapbase = 0;	dev->length = info->length;	memmove(dev->irq, info->irq, sizeof(dev->irq));	ret = device_register(&dev->dev);	if (ret) { out:		kfree(dev);	}	return ret;}#ifdef CONFIG_PMstruct locomo_save_data {	u16	LCM_GPO;	u16	LCM_SPICT;	u16	LCM_GPE;	u16	LCM_ASD;	u16	LCM_SPIMD;};static int locomo_suspend(struct platform_device *dev, pm_message_t state){	struct locomo *lchip = platform_get_drvdata(dev);	struct locomo_save_data *save;	unsigned long flags;	save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL);	if (!save)		return -ENOMEM;	lchip->saved_state = save;	spin_lock_irqsave(&lchip->lock, flags);	save->LCM_GPO     = locomo_readl(lchip->base + LOCOMO_GPO);	/* GPIO */	locomo_writel(0x00, lchip->base + LOCOMO_GPO);	save->LCM_SPICT   = locomo_readl(lchip->base + LOCOMO_SPICT);	/* SPI */	locomo_writel(0x40, lchip->base + LOCOMO_SPICT);	save->LCM_GPE     = locomo_readl(lchip->base + LOCOMO_GPE);	/* GPIO */	locomo_writel(0x00, lchip->base + LOCOMO_GPE);	save->LCM_ASD     = locomo_readl(lchip->base + LOCOMO_ASD);	/* ADSTART */	locomo_writel(0x00, lchip->base + LOCOMO_ASD);	save->LCM_SPIMD   = locomo_readl(lchip->base + LOCOMO_SPIMD);	/* SPI */	locomo_writel(0x3C14, lchip->base + LOCOMO_SPIMD);	locomo_writel(0x00, lchip->base + LOCOMO_PAIF);	locomo_writel(0x00, lchip->base + LOCOMO_DAC);	locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC);	if ( (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88) )		locomo_writel(0x00, lchip->base + LOCOMO_C32K); 	/* CLK32 off */	else		/* 18MHz already enabled, so no wait */		locomo_writel(0xc1, lchip->base + LOCOMO_C32K); 	/* CLK32 on */	locomo_writel(0x00, lchip->base + LOCOMO_TADC);		/* 18MHz clock off*/	locomo_writel(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC);			/* 22MHz/24MHz clock off */	locomo_writel(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);			/* FL */	spin_unlock_irqrestore(&lchip->lock, flags);	return 0;}static int locomo_resume(struct platform_device *dev){	struct locomo *lchip = platform_get_drvdata(dev);	struct locomo_save_data *save;	unsigned long r;	unsigned long flags;	save = lchip->saved_state;	if (!save)		return 0;	spin_lock_irqsave(&lchip->lock, flags);	locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO);	locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPICT);	locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE);	locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD);	locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPIMD);	locomo_writel(0x00, lchip->base + LOCOMO_C32K);	locomo_writel(0x90, lchip->base + LOCOMO_TADC);	locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC);	r = locomo_readl(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);	r &= 0xFEFF;	locomo_writel(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);	locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD);	spin_unlock_irqrestore(&lchip->lock, flags);	lchip->saved_state = NULL;	kfree(save);	return 0;}#endif/** *	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 = kzalloc(sizeof(struct locomo), GFP_KERNEL);	if (!lchip)		return -ENOMEM;	spin_lock_init(&lchip->lock);	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_KEYBOARD + 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_FRONTLIGHT + LOCOMO_ALS);	locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + 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, &locomo_devices[i]);	return 0; out:	kfree(lchip);	return ret;}static int locomo_remove_child(struct device *dev, void *data){	device_unregister(dev);	return 0;} static void __locomo_remove(struct locomo *lchip){	device_for_each_child(lchip->dev, NULL, locomo_remove_child);	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 platform_device *dev){	struct resource *mem;	int irq;	mem = platform_get_resource(dev, IORESOURCE_MEM, 0);	if (!mem)		return -EINVAL;	irq = platform_get_irq(dev, 0);	if (irq < 0)		return -ENXIO;	return __locomo_probe(&dev->dev, mem, irq);}static int locomo_remove(struct platform_device *dev){	struct locomo *lchip = platform_get_drvdata(dev);	if (lchip) {		__locomo_remove(lchip);		platform_set_drvdata(dev, 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

⌨️ 快捷键说明

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