105c45ca9SRussell King /* 205c45ca9SRussell King * linux/drivers/mfd/ucb1x00-core.c 305c45ca9SRussell King * 405c45ca9SRussell King * Copyright (C) 2001 Russell King, All Rights Reserved. 505c45ca9SRussell King * 605c45ca9SRussell King * This program is free software; you can redistribute it and/or modify 705c45ca9SRussell King * it under the terms of the GNU General Public License as published by 805c45ca9SRussell King * the Free Software Foundation; either version 2 of the License. 905c45ca9SRussell King * 1005c45ca9SRussell King * The UCB1x00 core driver provides basic services for handling IO, 1105c45ca9SRussell King * the ADC, interrupts, and accessing registers. It is designed 1205c45ca9SRussell King * such that everything goes through this layer, thereby providing 1305c45ca9SRussell King * a consistent locking methodology, as well as allowing the drivers 1405c45ca9SRussell King * to be used on other non-MCP-enabled hardware platforms. 1505c45ca9SRussell King * 1605c45ca9SRussell King * Note that all locks are private to this file. Nothing else may 1705c45ca9SRussell King * touch them. 1805c45ca9SRussell King */ 1905c45ca9SRussell King #include <linux/config.h> 2005c45ca9SRussell King #include <linux/module.h> 2105c45ca9SRussell King #include <linux/kernel.h> 2205c45ca9SRussell King #include <linux/slab.h> 2305c45ca9SRussell King #include <linux/init.h> 2405c45ca9SRussell King #include <linux/errno.h> 2505c45ca9SRussell King #include <linux/interrupt.h> 2605c45ca9SRussell King #include <linux/device.h> 27a621aaedSArjan van de Ven #include <linux/mutex.h> 2805c45ca9SRussell King 2905c45ca9SRussell King #include <asm/dma.h> 3005c45ca9SRussell King #include <asm/hardware.h> 3105c45ca9SRussell King 3205c45ca9SRussell King #include "ucb1x00.h" 3305c45ca9SRussell King 34a621aaedSArjan van de Ven static DEFINE_MUTEX(ucb1x00_mutex); 3505c45ca9SRussell King static LIST_HEAD(ucb1x00_drivers); 3605c45ca9SRussell King static LIST_HEAD(ucb1x00_devices); 3705c45ca9SRussell King 3805c45ca9SRussell King /** 3905c45ca9SRussell King * ucb1x00_io_set_dir - set IO direction 4005c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 4105c45ca9SRussell King * @in: bitfield of IO pins to be set as inputs 4205c45ca9SRussell King * @out: bitfield of IO pins to be set as outputs 4305c45ca9SRussell King * 4405c45ca9SRussell King * Set the IO direction of the ten general purpose IO pins on 4505c45ca9SRussell King * the UCB1x00 chip. The @in bitfield has priority over the 4605c45ca9SRussell King * @out bitfield, in that if you specify a pin as both input 4705c45ca9SRussell King * and output, it will end up as an input. 4805c45ca9SRussell King * 4905c45ca9SRussell King * ucb1x00_enable must have been called to enable the comms 5005c45ca9SRussell King * before using this function. 5105c45ca9SRussell King * 5205c45ca9SRussell King * This function takes a spinlock, disabling interrupts. 5305c45ca9SRussell King */ 5405c45ca9SRussell King void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out) 5505c45ca9SRussell King { 5605c45ca9SRussell King unsigned long flags; 5705c45ca9SRussell King 5805c45ca9SRussell King spin_lock_irqsave(&ucb->io_lock, flags); 5905c45ca9SRussell King ucb->io_dir |= out; 6005c45ca9SRussell King ucb->io_dir &= ~in; 6105c45ca9SRussell King 6205c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); 6305c45ca9SRussell King spin_unlock_irqrestore(&ucb->io_lock, flags); 6405c45ca9SRussell King } 6505c45ca9SRussell King 6605c45ca9SRussell King /** 6705c45ca9SRussell King * ucb1x00_io_write - set or clear IO outputs 6805c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 6905c45ca9SRussell King * @set: bitfield of IO pins to set to logic '1' 7005c45ca9SRussell King * @clear: bitfield of IO pins to set to logic '0' 7105c45ca9SRussell King * 7205c45ca9SRussell King * Set the IO output state of the specified IO pins. The value 7305c45ca9SRussell King * is retained if the pins are subsequently configured as inputs. 7405c45ca9SRussell King * The @clear bitfield has priority over the @set bitfield - 7505c45ca9SRussell King * outputs will be cleared. 7605c45ca9SRussell King * 7705c45ca9SRussell King * ucb1x00_enable must have been called to enable the comms 7805c45ca9SRussell King * before using this function. 7905c45ca9SRussell King * 8005c45ca9SRussell King * This function takes a spinlock, disabling interrupts. 8105c45ca9SRussell King */ 8205c45ca9SRussell King void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear) 8305c45ca9SRussell King { 8405c45ca9SRussell King unsigned long flags; 8505c45ca9SRussell King 8605c45ca9SRussell King spin_lock_irqsave(&ucb->io_lock, flags); 8705c45ca9SRussell King ucb->io_out |= set; 8805c45ca9SRussell King ucb->io_out &= ~clear; 8905c45ca9SRussell King 9005c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); 9105c45ca9SRussell King spin_unlock_irqrestore(&ucb->io_lock, flags); 9205c45ca9SRussell King } 9305c45ca9SRussell King 9405c45ca9SRussell King /** 9505c45ca9SRussell King * ucb1x00_io_read - read the current state of the IO pins 9605c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 9705c45ca9SRussell King * 9805c45ca9SRussell King * Return a bitfield describing the logic state of the ten 9905c45ca9SRussell King * general purpose IO pins. 10005c45ca9SRussell King * 10105c45ca9SRussell King * ucb1x00_enable must have been called to enable the comms 10205c45ca9SRussell King * before using this function. 10305c45ca9SRussell King * 10405c45ca9SRussell King * This function does not take any semaphores or spinlocks. 10505c45ca9SRussell King */ 10605c45ca9SRussell King unsigned int ucb1x00_io_read(struct ucb1x00 *ucb) 10705c45ca9SRussell King { 10805c45ca9SRussell King return ucb1x00_reg_read(ucb, UCB_IO_DATA); 10905c45ca9SRussell King } 11005c45ca9SRussell King 11105c45ca9SRussell King /* 11205c45ca9SRussell King * UCB1300 data sheet says we must: 11305c45ca9SRussell King * 1. enable ADC => 5us (including reference startup time) 11405c45ca9SRussell King * 2. select input => 51*tsibclk => 4.3us 11505c45ca9SRussell King * 3. start conversion => 102*tsibclk => 8.5us 11605c45ca9SRussell King * (tsibclk = 1/11981000) 11705c45ca9SRussell King * Period between SIB 128-bit frames = 10.7us 11805c45ca9SRussell King */ 11905c45ca9SRussell King 12005c45ca9SRussell King /** 12105c45ca9SRussell King * ucb1x00_adc_enable - enable the ADC converter 12205c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 12305c45ca9SRussell King * 12405c45ca9SRussell King * Enable the ucb1x00 and ADC converter on the UCB1x00 for use. 12505c45ca9SRussell King * Any code wishing to use the ADC converter must call this 12605c45ca9SRussell King * function prior to using it. 12705c45ca9SRussell King * 12805c45ca9SRussell King * This function takes the ADC semaphore to prevent two or more 12905c45ca9SRussell King * concurrent uses, and therefore may sleep. As a result, it 13005c45ca9SRussell King * can only be called from process context, not interrupt 13105c45ca9SRussell King * context. 13205c45ca9SRussell King * 13305c45ca9SRussell King * You should release the ADC as soon as possible using 13405c45ca9SRussell King * ucb1x00_adc_disable. 13505c45ca9SRussell King */ 13605c45ca9SRussell King void ucb1x00_adc_enable(struct ucb1x00 *ucb) 13705c45ca9SRussell King { 13805c45ca9SRussell King down(&ucb->adc_sem); 13905c45ca9SRussell King 14005c45ca9SRussell King ucb->adc_cr |= UCB_ADC_ENA; 14105c45ca9SRussell King 14205c45ca9SRussell King ucb1x00_enable(ucb); 14305c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); 14405c45ca9SRussell King } 14505c45ca9SRussell King 14605c45ca9SRussell King /** 14705c45ca9SRussell King * ucb1x00_adc_read - read the specified ADC channel 14805c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 14905c45ca9SRussell King * @adc_channel: ADC channel mask 15005c45ca9SRussell King * @sync: wait for syncronisation pulse. 15105c45ca9SRussell King * 15205c45ca9SRussell King * Start an ADC conversion and wait for the result. Note that 15305c45ca9SRussell King * synchronised ADC conversions (via the ADCSYNC pin) must wait 15405c45ca9SRussell King * until the trigger is asserted and the conversion is finished. 15505c45ca9SRussell King * 15605c45ca9SRussell King * This function currently spins waiting for the conversion to 15705c45ca9SRussell King * complete (2 frames max without sync). 15805c45ca9SRussell King * 15905c45ca9SRussell King * If called for a synchronised ADC conversion, it may sleep 16005c45ca9SRussell King * with the ADC semaphore held. 16105c45ca9SRussell King */ 16205c45ca9SRussell King unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync) 16305c45ca9SRussell King { 16405c45ca9SRussell King unsigned int val; 16505c45ca9SRussell King 16605c45ca9SRussell King if (sync) 16705c45ca9SRussell King adc_channel |= UCB_ADC_SYNC_ENA; 16805c45ca9SRussell King 16905c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel); 17005c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START); 17105c45ca9SRussell King 17205c45ca9SRussell King for (;;) { 17305c45ca9SRussell King val = ucb1x00_reg_read(ucb, UCB_ADC_DATA); 17405c45ca9SRussell King if (val & UCB_ADC_DAT_VAL) 17505c45ca9SRussell King break; 17605c45ca9SRussell King /* yield to other processes */ 17705c45ca9SRussell King set_current_state(TASK_INTERRUPTIBLE); 17805c45ca9SRussell King schedule_timeout(1); 17905c45ca9SRussell King } 18005c45ca9SRussell King 18105c45ca9SRussell King return UCB_ADC_DAT(val); 18205c45ca9SRussell King } 18305c45ca9SRussell King 18405c45ca9SRussell King /** 18505c45ca9SRussell King * ucb1x00_adc_disable - disable the ADC converter 18605c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 18705c45ca9SRussell King * 18805c45ca9SRussell King * Disable the ADC converter and release the ADC semaphore. 18905c45ca9SRussell King */ 19005c45ca9SRussell King void ucb1x00_adc_disable(struct ucb1x00 *ucb) 19105c45ca9SRussell King { 19205c45ca9SRussell King ucb->adc_cr &= ~UCB_ADC_ENA; 19305c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); 19405c45ca9SRussell King ucb1x00_disable(ucb); 19505c45ca9SRussell King 19605c45ca9SRussell King up(&ucb->adc_sem); 19705c45ca9SRussell King } 19805c45ca9SRussell King 19905c45ca9SRussell King /* 20005c45ca9SRussell King * UCB1x00 Interrupt handling. 20105c45ca9SRussell King * 20205c45ca9SRussell King * The UCB1x00 can generate interrupts when the SIBCLK is stopped. 20305c45ca9SRussell King * Since we need to read an internal register, we must re-enable 20405c45ca9SRussell King * SIBCLK to talk to the chip. We leave the clock running until 20505c45ca9SRussell King * we have finished processing all interrupts from the chip. 20605c45ca9SRussell King */ 20705c45ca9SRussell King static irqreturn_t ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs) 20805c45ca9SRussell King { 20905c45ca9SRussell King struct ucb1x00 *ucb = devid; 21005c45ca9SRussell King struct ucb1x00_irq *irq; 21105c45ca9SRussell King unsigned int isr, i; 21205c45ca9SRussell King 21305c45ca9SRussell King ucb1x00_enable(ucb); 21405c45ca9SRussell King isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS); 21505c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); 21605c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); 21705c45ca9SRussell King 21805c45ca9SRussell King for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++) 21905c45ca9SRussell King if (isr & 1 && irq->fn) 22005c45ca9SRussell King irq->fn(i, irq->devid); 22105c45ca9SRussell King ucb1x00_disable(ucb); 22205c45ca9SRussell King 22305c45ca9SRussell King return IRQ_HANDLED; 22405c45ca9SRussell King } 22505c45ca9SRussell King 22605c45ca9SRussell King /** 22705c45ca9SRussell King * ucb1x00_hook_irq - hook a UCB1x00 interrupt 22805c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 22905c45ca9SRussell King * @idx: interrupt index 23005c45ca9SRussell King * @fn: function to call when interrupt is triggered 23105c45ca9SRussell King * @devid: device id to pass to interrupt handler 23205c45ca9SRussell King * 23305c45ca9SRussell King * Hook the specified interrupt. You can only register one handler 23405c45ca9SRussell King * for each interrupt source. The interrupt source is not enabled 23505c45ca9SRussell King * by this function; use ucb1x00_enable_irq instead. 23605c45ca9SRussell King * 23705c45ca9SRussell King * Interrupt handlers will be called with other interrupts enabled. 23805c45ca9SRussell King * 23905c45ca9SRussell King * Returns zero on success, or one of the following errors: 24005c45ca9SRussell King * -EINVAL if the interrupt index is invalid 24105c45ca9SRussell King * -EBUSY if the interrupt has already been hooked 24205c45ca9SRussell King */ 24305c45ca9SRussell King int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid) 24405c45ca9SRussell King { 24505c45ca9SRussell King struct ucb1x00_irq *irq; 24605c45ca9SRussell King int ret = -EINVAL; 24705c45ca9SRussell King 24805c45ca9SRussell King if (idx < 16) { 24905c45ca9SRussell King irq = ucb->irq_handler + idx; 25005c45ca9SRussell King ret = -EBUSY; 25105c45ca9SRussell King 25205c45ca9SRussell King spin_lock_irq(&ucb->lock); 25305c45ca9SRussell King if (irq->fn == NULL) { 25405c45ca9SRussell King irq->devid = devid; 25505c45ca9SRussell King irq->fn = fn; 25605c45ca9SRussell King ret = 0; 25705c45ca9SRussell King } 25805c45ca9SRussell King spin_unlock_irq(&ucb->lock); 25905c45ca9SRussell King } 26005c45ca9SRussell King return ret; 26105c45ca9SRussell King } 26205c45ca9SRussell King 26305c45ca9SRussell King /** 26405c45ca9SRussell King * ucb1x00_enable_irq - enable an UCB1x00 interrupt source 26505c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 26605c45ca9SRussell King * @idx: interrupt index 26705c45ca9SRussell King * @edges: interrupt edges to enable 26805c45ca9SRussell King * 26905c45ca9SRussell King * Enable the specified interrupt to trigger on %UCB_RISING, 27005c45ca9SRussell King * %UCB_FALLING or both edges. The interrupt should have been 27105c45ca9SRussell King * hooked by ucb1x00_hook_irq. 27205c45ca9SRussell King */ 27305c45ca9SRussell King void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) 27405c45ca9SRussell King { 27505c45ca9SRussell King unsigned long flags; 27605c45ca9SRussell King 27705c45ca9SRussell King if (idx < 16) { 27805c45ca9SRussell King spin_lock_irqsave(&ucb->lock, flags); 27905c45ca9SRussell King 28005c45ca9SRussell King ucb1x00_enable(ucb); 28105c45ca9SRussell King if (edges & UCB_RISING) { 28205c45ca9SRussell King ucb->irq_ris_enbl |= 1 << idx; 28305c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); 28405c45ca9SRussell King } 28505c45ca9SRussell King if (edges & UCB_FALLING) { 28605c45ca9SRussell King ucb->irq_fal_enbl |= 1 << idx; 28705c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); 28805c45ca9SRussell King } 28905c45ca9SRussell King ucb1x00_disable(ucb); 29005c45ca9SRussell King spin_unlock_irqrestore(&ucb->lock, flags); 29105c45ca9SRussell King } 29205c45ca9SRussell King } 29305c45ca9SRussell King 29405c45ca9SRussell King /** 29505c45ca9SRussell King * ucb1x00_disable_irq - disable an UCB1x00 interrupt source 29605c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 29705c45ca9SRussell King * @edges: interrupt edges to disable 29805c45ca9SRussell King * 29905c45ca9SRussell King * Disable the specified interrupt triggering on the specified 30005c45ca9SRussell King * (%UCB_RISING, %UCB_FALLING or both) edges. 30105c45ca9SRussell King */ 30205c45ca9SRussell King void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) 30305c45ca9SRussell King { 30405c45ca9SRussell King unsigned long flags; 30505c45ca9SRussell King 30605c45ca9SRussell King if (idx < 16) { 30705c45ca9SRussell King spin_lock_irqsave(&ucb->lock, flags); 30805c45ca9SRussell King 30905c45ca9SRussell King ucb1x00_enable(ucb); 31005c45ca9SRussell King if (edges & UCB_RISING) { 31105c45ca9SRussell King ucb->irq_ris_enbl &= ~(1 << idx); 31205c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); 31305c45ca9SRussell King } 31405c45ca9SRussell King if (edges & UCB_FALLING) { 31505c45ca9SRussell King ucb->irq_fal_enbl &= ~(1 << idx); 31605c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); 31705c45ca9SRussell King } 31805c45ca9SRussell King ucb1x00_disable(ucb); 31905c45ca9SRussell King spin_unlock_irqrestore(&ucb->lock, flags); 32005c45ca9SRussell King } 32105c45ca9SRussell King } 32205c45ca9SRussell King 32305c45ca9SRussell King /** 32405c45ca9SRussell King * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt 32505c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 32605c45ca9SRussell King * @idx: interrupt index 32705c45ca9SRussell King * @devid: device id. 32805c45ca9SRussell King * 32905c45ca9SRussell King * Disable the interrupt source and remove the handler. devid must 33005c45ca9SRussell King * match the devid passed when hooking the interrupt. 33105c45ca9SRussell King * 33205c45ca9SRussell King * Returns zero on success, or one of the following errors: 33305c45ca9SRussell King * -EINVAL if the interrupt index is invalid 33405c45ca9SRussell King * -ENOENT if devid does not match 33505c45ca9SRussell King */ 33605c45ca9SRussell King int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid) 33705c45ca9SRussell King { 33805c45ca9SRussell King struct ucb1x00_irq *irq; 33905c45ca9SRussell King int ret; 34005c45ca9SRussell King 34105c45ca9SRussell King if (idx >= 16) 34205c45ca9SRussell King goto bad; 34305c45ca9SRussell King 34405c45ca9SRussell King irq = ucb->irq_handler + idx; 34505c45ca9SRussell King ret = -ENOENT; 34605c45ca9SRussell King 34705c45ca9SRussell King spin_lock_irq(&ucb->lock); 34805c45ca9SRussell King if (irq->devid == devid) { 34905c45ca9SRussell King ucb->irq_ris_enbl &= ~(1 << idx); 35005c45ca9SRussell King ucb->irq_fal_enbl &= ~(1 << idx); 35105c45ca9SRussell King 35205c45ca9SRussell King ucb1x00_enable(ucb); 35305c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); 35405c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); 35505c45ca9SRussell King ucb1x00_disable(ucb); 35605c45ca9SRussell King 35705c45ca9SRussell King irq->fn = NULL; 35805c45ca9SRussell King irq->devid = NULL; 35905c45ca9SRussell King ret = 0; 36005c45ca9SRussell King } 36105c45ca9SRussell King spin_unlock_irq(&ucb->lock); 36205c45ca9SRussell King return ret; 36305c45ca9SRussell King 36405c45ca9SRussell King bad: 36505c45ca9SRussell King printk(KERN_ERR "Freeing bad UCB1x00 irq %d\n", idx); 36605c45ca9SRussell King return -EINVAL; 36705c45ca9SRussell King } 36805c45ca9SRussell King 36905c45ca9SRussell King static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv) 37005c45ca9SRussell King { 37105c45ca9SRussell King struct ucb1x00_dev *dev; 37205c45ca9SRussell King int ret = -ENOMEM; 37305c45ca9SRussell King 37405c45ca9SRussell King dev = kmalloc(sizeof(struct ucb1x00_dev), GFP_KERNEL); 37505c45ca9SRussell King if (dev) { 37605c45ca9SRussell King dev->ucb = ucb; 37705c45ca9SRussell King dev->drv = drv; 37805c45ca9SRussell King 37905c45ca9SRussell King ret = drv->add(dev); 38005c45ca9SRussell King 38105c45ca9SRussell King if (ret == 0) { 38205c45ca9SRussell King list_add(&dev->dev_node, &ucb->devs); 38305c45ca9SRussell King list_add(&dev->drv_node, &drv->devs); 38405c45ca9SRussell King } else { 38505c45ca9SRussell King kfree(dev); 38605c45ca9SRussell King } 38705c45ca9SRussell King } 38805c45ca9SRussell King return ret; 38905c45ca9SRussell King } 39005c45ca9SRussell King 39105c45ca9SRussell King static void ucb1x00_remove_dev(struct ucb1x00_dev *dev) 39205c45ca9SRussell King { 39305c45ca9SRussell King dev->drv->remove(dev); 39405c45ca9SRussell King list_del(&dev->dev_node); 39505c45ca9SRussell King list_del(&dev->drv_node); 39605c45ca9SRussell King kfree(dev); 39705c45ca9SRussell King } 39805c45ca9SRussell King 39905c45ca9SRussell King /* 40005c45ca9SRussell King * Try to probe our interrupt, rather than relying on lots of 40105c45ca9SRussell King * hard-coded machine dependencies. For reference, the expected 40205c45ca9SRussell King * IRQ mappings are: 40305c45ca9SRussell King * 40405c45ca9SRussell King * Machine Default IRQ 40505c45ca9SRussell King * adsbitsy IRQ_GPCIN4 40605c45ca9SRussell King * cerf IRQ_GPIO_UCB1200_IRQ 40705c45ca9SRussell King * flexanet IRQ_GPIO_GUI 40805c45ca9SRussell King * freebird IRQ_GPIO_FREEBIRD_UCB1300_IRQ 40905c45ca9SRussell King * graphicsclient ADS_EXT_IRQ(8) 41005c45ca9SRussell King * graphicsmaster ADS_EXT_IRQ(8) 41105c45ca9SRussell King * lart LART_IRQ_UCB1200 41205c45ca9SRussell King * omnimeter IRQ_GPIO23 41305c45ca9SRussell King * pfs168 IRQ_GPIO_UCB1300_IRQ 41405c45ca9SRussell King * simpad IRQ_GPIO_UCB1300_IRQ 41505c45ca9SRussell King * shannon SHANNON_IRQ_GPIO_IRQ_CODEC 41605c45ca9SRussell King * yopy IRQ_GPIO_UCB1200_IRQ 41705c45ca9SRussell King */ 41805c45ca9SRussell King static int ucb1x00_detect_irq(struct ucb1x00 *ucb) 41905c45ca9SRussell King { 42005c45ca9SRussell King unsigned long mask; 42105c45ca9SRussell King 42205c45ca9SRussell King mask = probe_irq_on(); 42305c45ca9SRussell King if (!mask) 42405c45ca9SRussell King return NO_IRQ; 42505c45ca9SRussell King 42605c45ca9SRussell King /* 42705c45ca9SRussell King * Enable the ADC interrupt. 42805c45ca9SRussell King */ 42905c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC); 43005c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC); 43105c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff); 43205c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); 43305c45ca9SRussell King 43405c45ca9SRussell King /* 43505c45ca9SRussell King * Cause an ADC interrupt. 43605c45ca9SRussell King */ 43705c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA); 43805c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START); 43905c45ca9SRussell King 44005c45ca9SRussell King /* 44105c45ca9SRussell King * Wait for the conversion to complete. 44205c45ca9SRussell King */ 44305c45ca9SRussell King while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0); 44405c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, 0); 44505c45ca9SRussell King 44605c45ca9SRussell King /* 44705c45ca9SRussell King * Disable and clear interrupt. 44805c45ca9SRussell King */ 44905c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_RIS, 0); 45005c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_FAL, 0); 45105c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff); 45205c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); 45305c45ca9SRussell King 45405c45ca9SRussell King /* 45505c45ca9SRussell King * Read triggered interrupt. 45605c45ca9SRussell King */ 45705c45ca9SRussell King return probe_irq_off(mask); 45805c45ca9SRussell King } 45905c45ca9SRussell King 460585f5457SNicolas Pitre static void ucb1x00_release(struct class_device *dev) 461585f5457SNicolas Pitre { 462585f5457SNicolas Pitre struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); 463585f5457SNicolas Pitre kfree(ucb); 464585f5457SNicolas Pitre } 465585f5457SNicolas Pitre 466585f5457SNicolas Pitre static struct class ucb1x00_class = { 467585f5457SNicolas Pitre .name = "ucb1x00", 468585f5457SNicolas Pitre .release = ucb1x00_release, 469585f5457SNicolas Pitre }; 470585f5457SNicolas Pitre 47105c45ca9SRussell King static int ucb1x00_probe(struct mcp *mcp) 47205c45ca9SRussell King { 47305c45ca9SRussell King struct ucb1x00 *ucb; 47405c45ca9SRussell King struct ucb1x00_driver *drv; 47505c45ca9SRussell King unsigned int id; 47605c45ca9SRussell King int ret = -ENODEV; 47705c45ca9SRussell King 47805c45ca9SRussell King mcp_enable(mcp); 47905c45ca9SRussell King id = mcp_reg_read(mcp, UCB_ID); 48005c45ca9SRussell King 48105c45ca9SRussell King if (id != UCB_ID_1200 && id != UCB_ID_1300) { 48205c45ca9SRussell King printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); 48305c45ca9SRussell King goto err_disable; 48405c45ca9SRussell King } 48505c45ca9SRussell King 48605c45ca9SRussell King ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL); 48705c45ca9SRussell King ret = -ENOMEM; 48805c45ca9SRussell King if (!ucb) 48905c45ca9SRussell King goto err_disable; 49005c45ca9SRussell King 49105c45ca9SRussell King memset(ucb, 0, sizeof(struct ucb1x00)); 49205c45ca9SRussell King 49305c45ca9SRussell King ucb->cdev.class = &ucb1x00_class; 49405c45ca9SRussell King ucb->cdev.dev = &mcp->attached_device; 49505c45ca9SRussell King strlcpy(ucb->cdev.class_id, "ucb1x00", sizeof(ucb->cdev.class_id)); 49605c45ca9SRussell King 49705c45ca9SRussell King spin_lock_init(&ucb->lock); 49805c45ca9SRussell King spin_lock_init(&ucb->io_lock); 49905c45ca9SRussell King sema_init(&ucb->adc_sem, 1); 50005c45ca9SRussell King 50105c45ca9SRussell King ucb->id = id; 50205c45ca9SRussell King ucb->mcp = mcp; 50305c45ca9SRussell King ucb->irq = ucb1x00_detect_irq(ucb); 50405c45ca9SRussell King if (ucb->irq == NO_IRQ) { 50505c45ca9SRussell King printk(KERN_ERR "UCB1x00: IRQ probe failed\n"); 50605c45ca9SRussell King ret = -ENODEV; 50705c45ca9SRussell King goto err_free; 50805c45ca9SRussell King } 50905c45ca9SRussell King 5109ded96f2SRussell King ret = request_irq(ucb->irq, ucb1x00_irq, SA_TRIGGER_RISING, 5119ded96f2SRussell King "UCB1x00", ucb); 51205c45ca9SRussell King if (ret) { 51305c45ca9SRussell King printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", 51405c45ca9SRussell King ucb->irq, ret); 51505c45ca9SRussell King goto err_free; 51605c45ca9SRussell King } 51705c45ca9SRussell King 51805c45ca9SRussell King mcp_set_drvdata(mcp, ucb); 51905c45ca9SRussell King 52005c45ca9SRussell King ret = class_device_register(&ucb->cdev); 52105c45ca9SRussell King if (ret) 52205c45ca9SRussell King goto err_irq; 52305c45ca9SRussell King 52405c45ca9SRussell King INIT_LIST_HEAD(&ucb->devs); 525a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 52605c45ca9SRussell King list_add(&ucb->node, &ucb1x00_devices); 52705c45ca9SRussell King list_for_each_entry(drv, &ucb1x00_drivers, node) { 52805c45ca9SRussell King ucb1x00_add_dev(ucb, drv); 52905c45ca9SRussell King } 530a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 53105c45ca9SRussell King goto out; 53205c45ca9SRussell King 53305c45ca9SRussell King err_irq: 53405c45ca9SRussell King free_irq(ucb->irq, ucb); 53505c45ca9SRussell King err_free: 53605c45ca9SRussell King kfree(ucb); 53705c45ca9SRussell King err_disable: 53805c45ca9SRussell King mcp_disable(mcp); 53905c45ca9SRussell King out: 54005c45ca9SRussell King return ret; 54105c45ca9SRussell King } 54205c45ca9SRussell King 54305c45ca9SRussell King static void ucb1x00_remove(struct mcp *mcp) 54405c45ca9SRussell King { 54505c45ca9SRussell King struct ucb1x00 *ucb = mcp_get_drvdata(mcp); 54605c45ca9SRussell King struct list_head *l, *n; 54705c45ca9SRussell King 548a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 54905c45ca9SRussell King list_del(&ucb->node); 55005c45ca9SRussell King list_for_each_safe(l, n, &ucb->devs) { 55105c45ca9SRussell King struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, dev_node); 55205c45ca9SRussell King ucb1x00_remove_dev(dev); 55305c45ca9SRussell King } 554a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 55505c45ca9SRussell King 55605c45ca9SRussell King free_irq(ucb->irq, ucb); 55705c45ca9SRussell King class_device_unregister(&ucb->cdev); 55805c45ca9SRussell King } 55905c45ca9SRussell King 56005c45ca9SRussell King int ucb1x00_register_driver(struct ucb1x00_driver *drv) 56105c45ca9SRussell King { 56205c45ca9SRussell King struct ucb1x00 *ucb; 56305c45ca9SRussell King 56405c45ca9SRussell King INIT_LIST_HEAD(&drv->devs); 565a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 56605c45ca9SRussell King list_add(&drv->node, &ucb1x00_drivers); 56705c45ca9SRussell King list_for_each_entry(ucb, &ucb1x00_devices, node) { 56805c45ca9SRussell King ucb1x00_add_dev(ucb, drv); 56905c45ca9SRussell King } 570a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 57105c45ca9SRussell King return 0; 57205c45ca9SRussell King } 57305c45ca9SRussell King 57405c45ca9SRussell King void ucb1x00_unregister_driver(struct ucb1x00_driver *drv) 57505c45ca9SRussell King { 57605c45ca9SRussell King struct list_head *n, *l; 57705c45ca9SRussell King 578a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 57905c45ca9SRussell King list_del(&drv->node); 58005c45ca9SRussell King list_for_each_safe(l, n, &drv->devs) { 58105c45ca9SRussell King struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, drv_node); 58205c45ca9SRussell King ucb1x00_remove_dev(dev); 58305c45ca9SRussell King } 584a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 58505c45ca9SRussell King } 58605c45ca9SRussell King 58705c45ca9SRussell King static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state) 58805c45ca9SRussell King { 58905c45ca9SRussell King struct ucb1x00 *ucb = mcp_get_drvdata(mcp); 59005c45ca9SRussell King struct ucb1x00_dev *dev; 59105c45ca9SRussell King 592a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 59305c45ca9SRussell King list_for_each_entry(dev, &ucb->devs, dev_node) { 59405c45ca9SRussell King if (dev->drv->suspend) 59505c45ca9SRussell King dev->drv->suspend(dev, state); 59605c45ca9SRussell King } 597a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 59805c45ca9SRussell King return 0; 59905c45ca9SRussell King } 60005c45ca9SRussell King 60105c45ca9SRussell King static int ucb1x00_resume(struct mcp *mcp) 60205c45ca9SRussell King { 60305c45ca9SRussell King struct ucb1x00 *ucb = mcp_get_drvdata(mcp); 60405c45ca9SRussell King struct ucb1x00_dev *dev; 60505c45ca9SRussell King 606a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 60705c45ca9SRussell King list_for_each_entry(dev, &ucb->devs, dev_node) { 60805c45ca9SRussell King if (dev->drv->resume) 60905c45ca9SRussell King dev->drv->resume(dev); 61005c45ca9SRussell King } 611a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 61205c45ca9SRussell King return 0; 61305c45ca9SRussell King } 61405c45ca9SRussell King 61505c45ca9SRussell King static struct mcp_driver ucb1x00_driver = { 61605c45ca9SRussell King .drv = { 61705c45ca9SRussell King .name = "ucb1x00", 61805c45ca9SRussell King }, 61905c45ca9SRussell King .probe = ucb1x00_probe, 62005c45ca9SRussell King .remove = ucb1x00_remove, 62105c45ca9SRussell King .suspend = ucb1x00_suspend, 62205c45ca9SRussell King .resume = ucb1x00_resume, 62305c45ca9SRussell King }; 62405c45ca9SRussell King 62505c45ca9SRussell King static int __init ucb1x00_init(void) 62605c45ca9SRussell King { 62705c45ca9SRussell King int ret = class_register(&ucb1x00_class); 62805c45ca9SRussell King if (ret == 0) { 62905c45ca9SRussell King ret = mcp_driver_register(&ucb1x00_driver); 63005c45ca9SRussell King if (ret) 63105c45ca9SRussell King class_unregister(&ucb1x00_class); 63205c45ca9SRussell King } 63305c45ca9SRussell King return ret; 63405c45ca9SRussell King } 63505c45ca9SRussell King 63605c45ca9SRussell King static void __exit ucb1x00_exit(void) 63705c45ca9SRussell King { 63805c45ca9SRussell King mcp_driver_unregister(&ucb1x00_driver); 63905c45ca9SRussell King class_unregister(&ucb1x00_class); 64005c45ca9SRussell King } 64105c45ca9SRussell King 64205c45ca9SRussell King module_init(ucb1x00_init); 64305c45ca9SRussell King module_exit(ucb1x00_exit); 64405c45ca9SRussell King 64505c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_io_set_dir); 64605c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_io_write); 64705c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_io_read); 64805c45ca9SRussell King 64905c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_adc_enable); 65005c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_adc_read); 65105c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_adc_disable); 65205c45ca9SRussell King 65305c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_hook_irq); 65405c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_free_irq); 65505c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_enable_irq); 65605c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_disable_irq); 65705c45ca9SRussell King 65805c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_register_driver); 65905c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_unregister_driver); 66005c45ca9SRussell King 66105c45ca9SRussell King MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); 66205c45ca9SRussell King MODULE_DESCRIPTION("UCB1x00 core driver"); 66305c45ca9SRussell King MODULE_LICENSE("GPL"); 664