📄 locomo.c
字号:
{ void *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPIWE); r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); locomo_writel(r, mapbase + LOCOMO_SPIWE); r = locomo_readl(mapbase + LOCOMO_SPIIS); r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); locomo_writel(r, mapbase + LOCOMO_SPIIS); r = locomo_readl(mapbase + LOCOMO_SPIWE); r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); locomo_writel(r, mapbase + LOCOMO_SPIWE);}static void locomo_spi_mask_irq(unsigned int irq){ void *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPIIE); r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); locomo_writel(r, mapbase + LOCOMO_SPIIE);}static void locomo_spi_unmask_irq(unsigned int irq){ void *mapbase = get_irq_chipdata(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPIIE); r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); locomo_writel(r, mapbase + LOCOMO_SPIIE);}static struct irqchip locomo_spi_chip = { .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 *irqbase = lchip->base; /* * Install handler for IRQ_LOCOMO_HW. */ set_irq_type(lchip->irq, IRQT_FALLING); set_irq_chipdata(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_chipdata(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_chipdata(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_chipdata(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_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); kfree(dev);}static intlocomo_init_one_child(struct locomo *lchip, 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; 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 device *dev, pm_message_t state, u32 level){ struct locomo *lchip = dev_get_drvdata(dev); struct locomo_save_data *save; unsigned long flags; if (level != SUSPEND_DISABLE) return 0; save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL); if (!save) return -ENOMEM; dev->power.saved_state = (void *) 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 device *dev, u32 level){ struct locomo *lchip = dev_get_drvdata(dev); struct locomo_save_data *save; unsigned long r; unsigned long flags; if (level != RESUME_ENABLE) return 0; save = (struct locomo_save_data *) dev->power.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); dev->power.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 = kmalloc(sizeof(struct locomo), GFP_KERNEL); if (!lchip) return -ENOMEM; memset(lchip, 0, sizeof(struct locomo)); 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 device *dev){ struct platform_device *pdev = to_platform_device(dev); struct resource *mem; int irq;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -