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/module.h> 2005c45ca9SRussell King #include <linux/kernel.h> 21d43c36dcSAlexey Dobriyan #include <linux/sched.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> 28c8602edfSThomas Kunze #include <linux/mfd/ucb1x00.h> 299ca3dc80SThomas Kunze #include <linux/gpio.h> 3005c45ca9SRussell King 31a621aaedSArjan van de Ven static DEFINE_MUTEX(ucb1x00_mutex); 3205c45ca9SRussell King static LIST_HEAD(ucb1x00_drivers); 3305c45ca9SRussell King static LIST_HEAD(ucb1x00_devices); 3405c45ca9SRussell King 3505c45ca9SRussell King /** 3605c45ca9SRussell King * ucb1x00_io_set_dir - set IO direction 3705c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 3805c45ca9SRussell King * @in: bitfield of IO pins to be set as inputs 3905c45ca9SRussell King * @out: bitfield of IO pins to be set as outputs 4005c45ca9SRussell King * 4105c45ca9SRussell King * Set the IO direction of the ten general purpose IO pins on 4205c45ca9SRussell King * the UCB1x00 chip. The @in bitfield has priority over the 4305c45ca9SRussell King * @out bitfield, in that if you specify a pin as both input 4405c45ca9SRussell King * and output, it will end up as an input. 4505c45ca9SRussell King * 4605c45ca9SRussell King * ucb1x00_enable must have been called to enable the comms 4705c45ca9SRussell King * before using this function. 4805c45ca9SRussell King * 4905c45ca9SRussell King * This function takes a spinlock, disabling interrupts. 5005c45ca9SRussell King */ 5105c45ca9SRussell King void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out) 5205c45ca9SRussell King { 5305c45ca9SRussell King unsigned long flags; 5405c45ca9SRussell King 5505c45ca9SRussell King spin_lock_irqsave(&ucb->io_lock, flags); 5605c45ca9SRussell King ucb->io_dir |= out; 5705c45ca9SRussell King ucb->io_dir &= ~in; 5805c45ca9SRussell King 5905c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); 6005c45ca9SRussell King spin_unlock_irqrestore(&ucb->io_lock, flags); 6105c45ca9SRussell King } 6205c45ca9SRussell King 6305c45ca9SRussell King /** 6405c45ca9SRussell King * ucb1x00_io_write - set or clear IO outputs 6505c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 6605c45ca9SRussell King * @set: bitfield of IO pins to set to logic '1' 6705c45ca9SRussell King * @clear: bitfield of IO pins to set to logic '0' 6805c45ca9SRussell King * 6905c45ca9SRussell King * Set the IO output state of the specified IO pins. The value 7005c45ca9SRussell King * is retained if the pins are subsequently configured as inputs. 7105c45ca9SRussell King * The @clear bitfield has priority over the @set bitfield - 7205c45ca9SRussell King * outputs will be cleared. 7305c45ca9SRussell King * 7405c45ca9SRussell King * ucb1x00_enable must have been called to enable the comms 7505c45ca9SRussell King * before using this function. 7605c45ca9SRussell King * 7705c45ca9SRussell King * This function takes a spinlock, disabling interrupts. 7805c45ca9SRussell King */ 7905c45ca9SRussell King void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear) 8005c45ca9SRussell King { 8105c45ca9SRussell King unsigned long flags; 8205c45ca9SRussell King 8305c45ca9SRussell King spin_lock_irqsave(&ucb->io_lock, flags); 8405c45ca9SRussell King ucb->io_out |= set; 8505c45ca9SRussell King ucb->io_out &= ~clear; 8605c45ca9SRussell King 8705c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); 8805c45ca9SRussell King spin_unlock_irqrestore(&ucb->io_lock, flags); 8905c45ca9SRussell King } 9005c45ca9SRussell King 9105c45ca9SRussell King /** 9205c45ca9SRussell King * ucb1x00_io_read - read the current state of the IO pins 9305c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 9405c45ca9SRussell King * 9505c45ca9SRussell King * Return a bitfield describing the logic state of the ten 9605c45ca9SRussell King * general purpose IO pins. 9705c45ca9SRussell King * 9805c45ca9SRussell King * ucb1x00_enable must have been called to enable the comms 9905c45ca9SRussell King * before using this function. 10005c45ca9SRussell King * 101cae15476SRussell King * This function does not take any mutexes or spinlocks. 10205c45ca9SRussell King */ 10305c45ca9SRussell King unsigned int ucb1x00_io_read(struct ucb1x00 *ucb) 10405c45ca9SRussell King { 10505c45ca9SRussell King return ucb1x00_reg_read(ucb, UCB_IO_DATA); 10605c45ca9SRussell King } 10705c45ca9SRussell King 1089ca3dc80SThomas Kunze static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 1099ca3dc80SThomas Kunze { 1109ca3dc80SThomas Kunze struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); 1119ca3dc80SThomas Kunze unsigned long flags; 1129ca3dc80SThomas Kunze 1139ca3dc80SThomas Kunze spin_lock_irqsave(&ucb->io_lock, flags); 1149ca3dc80SThomas Kunze if (value) 1159ca3dc80SThomas Kunze ucb->io_out |= 1 << offset; 1169ca3dc80SThomas Kunze else 1179ca3dc80SThomas Kunze ucb->io_out &= ~(1 << offset); 1189ca3dc80SThomas Kunze 1199ca3dc80SThomas Kunze ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); 1209ca3dc80SThomas Kunze spin_unlock_irqrestore(&ucb->io_lock, flags); 1219ca3dc80SThomas Kunze } 1229ca3dc80SThomas Kunze 1239ca3dc80SThomas Kunze static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset) 1249ca3dc80SThomas Kunze { 1259ca3dc80SThomas Kunze struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); 1269ca3dc80SThomas Kunze return ucb1x00_reg_read(ucb, UCB_IO_DATA) & (1 << offset); 1279ca3dc80SThomas Kunze } 1289ca3dc80SThomas Kunze 1299ca3dc80SThomas Kunze static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 1309ca3dc80SThomas Kunze { 1319ca3dc80SThomas Kunze struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); 1329ca3dc80SThomas Kunze unsigned long flags; 1339ca3dc80SThomas Kunze 1349ca3dc80SThomas Kunze spin_lock_irqsave(&ucb->io_lock, flags); 1359ca3dc80SThomas Kunze ucb->io_dir &= ~(1 << offset); 1369ca3dc80SThomas Kunze ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); 1379ca3dc80SThomas Kunze spin_unlock_irqrestore(&ucb->io_lock, flags); 1389ca3dc80SThomas Kunze 1399ca3dc80SThomas Kunze return 0; 1409ca3dc80SThomas Kunze } 1419ca3dc80SThomas Kunze 1429ca3dc80SThomas Kunze static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset 1439ca3dc80SThomas Kunze , int value) 1449ca3dc80SThomas Kunze { 1459ca3dc80SThomas Kunze struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); 1469ca3dc80SThomas Kunze unsigned long flags; 147c23bb602SRussell King unsigned old, mask = 1 << offset; 1489ca3dc80SThomas Kunze 1499ca3dc80SThomas Kunze spin_lock_irqsave(&ucb->io_lock, flags); 150c23bb602SRussell King old = ucb->io_out; 1519ca3dc80SThomas Kunze if (value) 152c23bb602SRussell King ucb->io_out |= mask; 1539ca3dc80SThomas Kunze else 154c23bb602SRussell King ucb->io_out &= ~mask; 155c23bb602SRussell King 156c23bb602SRussell King if (old != ucb->io_out) 1579ca3dc80SThomas Kunze ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); 158c23bb602SRussell King 159c23bb602SRussell King if (!(ucb->io_dir & mask)) { 160c23bb602SRussell King ucb->io_dir |= mask; 161c23bb602SRussell King ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); 162c23bb602SRussell King } 1639ca3dc80SThomas Kunze spin_unlock_irqrestore(&ucb->io_lock, flags); 1649ca3dc80SThomas Kunze 1659ca3dc80SThomas Kunze return 0; 1669ca3dc80SThomas Kunze } 1679ca3dc80SThomas Kunze 16805c45ca9SRussell King /* 16905c45ca9SRussell King * UCB1300 data sheet says we must: 17005c45ca9SRussell King * 1. enable ADC => 5us (including reference startup time) 17105c45ca9SRussell King * 2. select input => 51*tsibclk => 4.3us 17205c45ca9SRussell King * 3. start conversion => 102*tsibclk => 8.5us 17305c45ca9SRussell King * (tsibclk = 1/11981000) 17405c45ca9SRussell King * Period between SIB 128-bit frames = 10.7us 17505c45ca9SRussell King */ 17605c45ca9SRussell King 17705c45ca9SRussell King /** 17805c45ca9SRussell King * ucb1x00_adc_enable - enable the ADC converter 17905c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 18005c45ca9SRussell King * 18105c45ca9SRussell King * Enable the ucb1x00 and ADC converter on the UCB1x00 for use. 18205c45ca9SRussell King * Any code wishing to use the ADC converter must call this 18305c45ca9SRussell King * function prior to using it. 18405c45ca9SRussell King * 185cae15476SRussell King * This function takes the ADC mutex to prevent two or more 18605c45ca9SRussell King * concurrent uses, and therefore may sleep. As a result, it 18705c45ca9SRussell King * can only be called from process context, not interrupt 18805c45ca9SRussell King * context. 18905c45ca9SRussell King * 19005c45ca9SRussell King * You should release the ADC as soon as possible using 19105c45ca9SRussell King * ucb1x00_adc_disable. 19205c45ca9SRussell King */ 19305c45ca9SRussell King void ucb1x00_adc_enable(struct ucb1x00 *ucb) 19405c45ca9SRussell King { 195cae15476SRussell King mutex_lock(&ucb->adc_mutex); 19605c45ca9SRussell King 19705c45ca9SRussell King ucb->adc_cr |= UCB_ADC_ENA; 19805c45ca9SRussell King 19905c45ca9SRussell King ucb1x00_enable(ucb); 20005c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); 20105c45ca9SRussell King } 20205c45ca9SRussell King 20305c45ca9SRussell King /** 20405c45ca9SRussell King * ucb1x00_adc_read - read the specified ADC channel 20505c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 20605c45ca9SRussell King * @adc_channel: ADC channel mask 20705c45ca9SRussell King * @sync: wait for syncronisation pulse. 20805c45ca9SRussell King * 20905c45ca9SRussell King * Start an ADC conversion and wait for the result. Note that 21005c45ca9SRussell King * synchronised ADC conversions (via the ADCSYNC pin) must wait 21105c45ca9SRussell King * until the trigger is asserted and the conversion is finished. 21205c45ca9SRussell King * 21305c45ca9SRussell King * This function currently spins waiting for the conversion to 21405c45ca9SRussell King * complete (2 frames max without sync). 21505c45ca9SRussell King * 21605c45ca9SRussell King * If called for a synchronised ADC conversion, it may sleep 217cae15476SRussell King * with the ADC mutex held. 21805c45ca9SRussell King */ 21905c45ca9SRussell King unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync) 22005c45ca9SRussell King { 22105c45ca9SRussell King unsigned int val; 22205c45ca9SRussell King 22305c45ca9SRussell King if (sync) 22405c45ca9SRussell King adc_channel |= UCB_ADC_SYNC_ENA; 22505c45ca9SRussell King 22605c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel); 22705c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START); 22805c45ca9SRussell King 22905c45ca9SRussell King for (;;) { 23005c45ca9SRussell King val = ucb1x00_reg_read(ucb, UCB_ADC_DATA); 23105c45ca9SRussell King if (val & UCB_ADC_DAT_VAL) 23205c45ca9SRussell King break; 23305c45ca9SRussell King /* yield to other processes */ 23405c45ca9SRussell King set_current_state(TASK_INTERRUPTIBLE); 23505c45ca9SRussell King schedule_timeout(1); 23605c45ca9SRussell King } 23705c45ca9SRussell King 23805c45ca9SRussell King return UCB_ADC_DAT(val); 23905c45ca9SRussell King } 24005c45ca9SRussell King 24105c45ca9SRussell King /** 24205c45ca9SRussell King * ucb1x00_adc_disable - disable the ADC converter 24305c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 24405c45ca9SRussell King * 245cae15476SRussell King * Disable the ADC converter and release the ADC mutex. 24605c45ca9SRussell King */ 24705c45ca9SRussell King void ucb1x00_adc_disable(struct ucb1x00 *ucb) 24805c45ca9SRussell King { 24905c45ca9SRussell King ucb->adc_cr &= ~UCB_ADC_ENA; 25005c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr); 25105c45ca9SRussell King ucb1x00_disable(ucb); 25205c45ca9SRussell King 253cae15476SRussell King mutex_unlock(&ucb->adc_mutex); 25405c45ca9SRussell King } 25505c45ca9SRussell King 25605c45ca9SRussell King /* 25705c45ca9SRussell King * UCB1x00 Interrupt handling. 25805c45ca9SRussell King * 25905c45ca9SRussell King * The UCB1x00 can generate interrupts when the SIBCLK is stopped. 26005c45ca9SRussell King * Since we need to read an internal register, we must re-enable 26105c45ca9SRussell King * SIBCLK to talk to the chip. We leave the clock running until 26205c45ca9SRussell King * we have finished processing all interrupts from the chip. 26305c45ca9SRussell King */ 2647d12e780SDavid Howells static irqreturn_t ucb1x00_irq(int irqnr, void *devid) 26505c45ca9SRussell King { 26605c45ca9SRussell King struct ucb1x00 *ucb = devid; 26705c45ca9SRussell King struct ucb1x00_irq *irq; 26805c45ca9SRussell King unsigned int isr, i; 26905c45ca9SRussell King 27005c45ca9SRussell King ucb1x00_enable(ucb); 27105c45ca9SRussell King isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS); 27205c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr); 27305c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); 27405c45ca9SRussell King 27505c45ca9SRussell King for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++) 27605c45ca9SRussell King if (isr & 1 && irq->fn) 27705c45ca9SRussell King irq->fn(i, irq->devid); 27805c45ca9SRussell King ucb1x00_disable(ucb); 27905c45ca9SRussell King 28005c45ca9SRussell King return IRQ_HANDLED; 28105c45ca9SRussell King } 28205c45ca9SRussell King 28305c45ca9SRussell King /** 28405c45ca9SRussell King * ucb1x00_hook_irq - hook a UCB1x00 interrupt 28505c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 28605c45ca9SRussell King * @idx: interrupt index 28705c45ca9SRussell King * @fn: function to call when interrupt is triggered 28805c45ca9SRussell King * @devid: device id to pass to interrupt handler 28905c45ca9SRussell King * 29005c45ca9SRussell King * Hook the specified interrupt. You can only register one handler 29105c45ca9SRussell King * for each interrupt source. The interrupt source is not enabled 29205c45ca9SRussell King * by this function; use ucb1x00_enable_irq instead. 29305c45ca9SRussell King * 29405c45ca9SRussell King * Interrupt handlers will be called with other interrupts enabled. 29505c45ca9SRussell King * 29605c45ca9SRussell King * Returns zero on success, or one of the following errors: 29705c45ca9SRussell King * -EINVAL if the interrupt index is invalid 29805c45ca9SRussell King * -EBUSY if the interrupt has already been hooked 29905c45ca9SRussell King */ 30005c45ca9SRussell King int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid) 30105c45ca9SRussell King { 30205c45ca9SRussell King struct ucb1x00_irq *irq; 30305c45ca9SRussell King int ret = -EINVAL; 30405c45ca9SRussell King 30505c45ca9SRussell King if (idx < 16) { 30605c45ca9SRussell King irq = ucb->irq_handler + idx; 30705c45ca9SRussell King ret = -EBUSY; 30805c45ca9SRussell King 30905c45ca9SRussell King spin_lock_irq(&ucb->lock); 31005c45ca9SRussell King if (irq->fn == NULL) { 31105c45ca9SRussell King irq->devid = devid; 31205c45ca9SRussell King irq->fn = fn; 31305c45ca9SRussell King ret = 0; 31405c45ca9SRussell King } 31505c45ca9SRussell King spin_unlock_irq(&ucb->lock); 31605c45ca9SRussell King } 31705c45ca9SRussell King return ret; 31805c45ca9SRussell King } 31905c45ca9SRussell King 32005c45ca9SRussell King /** 32105c45ca9SRussell King * ucb1x00_enable_irq - enable an UCB1x00 interrupt source 32205c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 32305c45ca9SRussell King * @idx: interrupt index 32405c45ca9SRussell King * @edges: interrupt edges to enable 32505c45ca9SRussell King * 32605c45ca9SRussell King * Enable the specified interrupt to trigger on %UCB_RISING, 32705c45ca9SRussell King * %UCB_FALLING or both edges. The interrupt should have been 32805c45ca9SRussell King * hooked by ucb1x00_hook_irq. 32905c45ca9SRussell King */ 33005c45ca9SRussell King void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) 33105c45ca9SRussell King { 33205c45ca9SRussell King unsigned long flags; 33305c45ca9SRussell King 33405c45ca9SRussell King if (idx < 16) { 33505c45ca9SRussell King spin_lock_irqsave(&ucb->lock, flags); 33605c45ca9SRussell King 33705c45ca9SRussell King ucb1x00_enable(ucb); 33805c45ca9SRussell King if (edges & UCB_RISING) { 33905c45ca9SRussell King ucb->irq_ris_enbl |= 1 << idx; 34005c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); 34105c45ca9SRussell King } 34205c45ca9SRussell King if (edges & UCB_FALLING) { 34305c45ca9SRussell King ucb->irq_fal_enbl |= 1 << idx; 34405c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); 34505c45ca9SRussell King } 34605c45ca9SRussell King ucb1x00_disable(ucb); 34705c45ca9SRussell King spin_unlock_irqrestore(&ucb->lock, flags); 34805c45ca9SRussell King } 34905c45ca9SRussell King } 35005c45ca9SRussell King 35105c45ca9SRussell King /** 35205c45ca9SRussell King * ucb1x00_disable_irq - disable an UCB1x00 interrupt source 35305c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 35405c45ca9SRussell King * @edges: interrupt edges to disable 35505c45ca9SRussell King * 35605c45ca9SRussell King * Disable the specified interrupt triggering on the specified 35705c45ca9SRussell King * (%UCB_RISING, %UCB_FALLING or both) edges. 35805c45ca9SRussell King */ 35905c45ca9SRussell King void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges) 36005c45ca9SRussell King { 36105c45ca9SRussell King unsigned long flags; 36205c45ca9SRussell King 36305c45ca9SRussell King if (idx < 16) { 36405c45ca9SRussell King spin_lock_irqsave(&ucb->lock, flags); 36505c45ca9SRussell King 36605c45ca9SRussell King ucb1x00_enable(ucb); 36705c45ca9SRussell King if (edges & UCB_RISING) { 36805c45ca9SRussell King ucb->irq_ris_enbl &= ~(1 << idx); 36905c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); 37005c45ca9SRussell King } 37105c45ca9SRussell King if (edges & UCB_FALLING) { 37205c45ca9SRussell King ucb->irq_fal_enbl &= ~(1 << idx); 37305c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); 37405c45ca9SRussell King } 37505c45ca9SRussell King ucb1x00_disable(ucb); 37605c45ca9SRussell King spin_unlock_irqrestore(&ucb->lock, flags); 37705c45ca9SRussell King } 37805c45ca9SRussell King } 37905c45ca9SRussell King 38005c45ca9SRussell King /** 38105c45ca9SRussell King * ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt 38205c45ca9SRussell King * @ucb: UCB1x00 structure describing chip 38305c45ca9SRussell King * @idx: interrupt index 38405c45ca9SRussell King * @devid: device id. 38505c45ca9SRussell King * 38605c45ca9SRussell King * Disable the interrupt source and remove the handler. devid must 38705c45ca9SRussell King * match the devid passed when hooking the interrupt. 38805c45ca9SRussell King * 38905c45ca9SRussell King * Returns zero on success, or one of the following errors: 39005c45ca9SRussell King * -EINVAL if the interrupt index is invalid 39105c45ca9SRussell King * -ENOENT if devid does not match 39205c45ca9SRussell King */ 39305c45ca9SRussell King int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid) 39405c45ca9SRussell King { 39505c45ca9SRussell King struct ucb1x00_irq *irq; 39605c45ca9SRussell King int ret; 39705c45ca9SRussell King 39805c45ca9SRussell King if (idx >= 16) 39905c45ca9SRussell King goto bad; 40005c45ca9SRussell King 40105c45ca9SRussell King irq = ucb->irq_handler + idx; 40205c45ca9SRussell King ret = -ENOENT; 40305c45ca9SRussell King 40405c45ca9SRussell King spin_lock_irq(&ucb->lock); 40505c45ca9SRussell King if (irq->devid == devid) { 40605c45ca9SRussell King ucb->irq_ris_enbl &= ~(1 << idx); 40705c45ca9SRussell King ucb->irq_fal_enbl &= ~(1 << idx); 40805c45ca9SRussell King 40905c45ca9SRussell King ucb1x00_enable(ucb); 41005c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl); 41105c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl); 41205c45ca9SRussell King ucb1x00_disable(ucb); 41305c45ca9SRussell King 41405c45ca9SRussell King irq->fn = NULL; 41505c45ca9SRussell King irq->devid = NULL; 41605c45ca9SRussell King ret = 0; 41705c45ca9SRussell King } 41805c45ca9SRussell King spin_unlock_irq(&ucb->lock); 41905c45ca9SRussell King return ret; 42005c45ca9SRussell King 42105c45ca9SRussell King bad: 42205c45ca9SRussell King printk(KERN_ERR "Freeing bad UCB1x00 irq %d\n", idx); 42305c45ca9SRussell King return -EINVAL; 42405c45ca9SRussell King } 42505c45ca9SRussell King 42605c45ca9SRussell King static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv) 42705c45ca9SRussell King { 42805c45ca9SRussell King struct ucb1x00_dev *dev; 42905c45ca9SRussell King int ret = -ENOMEM; 43005c45ca9SRussell King 43105c45ca9SRussell King dev = kmalloc(sizeof(struct ucb1x00_dev), GFP_KERNEL); 43205c45ca9SRussell King if (dev) { 43305c45ca9SRussell King dev->ucb = ucb; 43405c45ca9SRussell King dev->drv = drv; 43505c45ca9SRussell King 43605c45ca9SRussell King ret = drv->add(dev); 43705c45ca9SRussell King 43805c45ca9SRussell King if (ret == 0) { 43905c45ca9SRussell King list_add(&dev->dev_node, &ucb->devs); 44005c45ca9SRussell King list_add(&dev->drv_node, &drv->devs); 44105c45ca9SRussell King } else { 44205c45ca9SRussell King kfree(dev); 44305c45ca9SRussell King } 44405c45ca9SRussell King } 44505c45ca9SRussell King return ret; 44605c45ca9SRussell King } 44705c45ca9SRussell King 44805c45ca9SRussell King static void ucb1x00_remove_dev(struct ucb1x00_dev *dev) 44905c45ca9SRussell King { 45005c45ca9SRussell King dev->drv->remove(dev); 45105c45ca9SRussell King list_del(&dev->dev_node); 45205c45ca9SRussell King list_del(&dev->drv_node); 45305c45ca9SRussell King kfree(dev); 45405c45ca9SRussell King } 45505c45ca9SRussell King 45605c45ca9SRussell King /* 45705c45ca9SRussell King * Try to probe our interrupt, rather than relying on lots of 45805c45ca9SRussell King * hard-coded machine dependencies. For reference, the expected 45905c45ca9SRussell King * IRQ mappings are: 46005c45ca9SRussell King * 46105c45ca9SRussell King * Machine Default IRQ 46205c45ca9SRussell King * adsbitsy IRQ_GPCIN4 46305c45ca9SRussell King * cerf IRQ_GPIO_UCB1200_IRQ 46405c45ca9SRussell King * flexanet IRQ_GPIO_GUI 46505c45ca9SRussell King * freebird IRQ_GPIO_FREEBIRD_UCB1300_IRQ 46605c45ca9SRussell King * graphicsclient ADS_EXT_IRQ(8) 46705c45ca9SRussell King * graphicsmaster ADS_EXT_IRQ(8) 46805c45ca9SRussell King * lart LART_IRQ_UCB1200 46905c45ca9SRussell King * omnimeter IRQ_GPIO23 47005c45ca9SRussell King * pfs168 IRQ_GPIO_UCB1300_IRQ 47105c45ca9SRussell King * simpad IRQ_GPIO_UCB1300_IRQ 47205c45ca9SRussell King * shannon SHANNON_IRQ_GPIO_IRQ_CODEC 47305c45ca9SRussell King * yopy IRQ_GPIO_UCB1200_IRQ 47405c45ca9SRussell King */ 47505c45ca9SRussell King static int ucb1x00_detect_irq(struct ucb1x00 *ucb) 47605c45ca9SRussell King { 47705c45ca9SRussell King unsigned long mask; 47805c45ca9SRussell King 47905c45ca9SRussell King mask = probe_irq_on(); 480cfc73656SIngo Molnar if (!mask) { 481cfc73656SIngo Molnar probe_irq_off(mask); 48205c45ca9SRussell King return NO_IRQ; 483cfc73656SIngo Molnar } 48405c45ca9SRussell King 48505c45ca9SRussell King /* 48605c45ca9SRussell King * Enable the ADC interrupt. 48705c45ca9SRussell King */ 48805c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC); 48905c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC); 49005c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff); 49105c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); 49205c45ca9SRussell King 49305c45ca9SRussell King /* 49405c45ca9SRussell King * Cause an ADC interrupt. 49505c45ca9SRussell King */ 49605c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA); 49705c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START); 49805c45ca9SRussell King 49905c45ca9SRussell King /* 50005c45ca9SRussell King * Wait for the conversion to complete. 50105c45ca9SRussell King */ 50205c45ca9SRussell King while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0); 50305c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_ADC_CR, 0); 50405c45ca9SRussell King 50505c45ca9SRussell King /* 50605c45ca9SRussell King * Disable and clear interrupt. 50705c45ca9SRussell King */ 50805c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_RIS, 0); 50905c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_FAL, 0); 51005c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff); 51105c45ca9SRussell King ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); 51205c45ca9SRussell King 51305c45ca9SRussell King /* 51405c45ca9SRussell King * Read triggered interrupt. 51505c45ca9SRussell King */ 51605c45ca9SRussell King return probe_irq_off(mask); 51705c45ca9SRussell King } 51805c45ca9SRussell King 5190c55445fSTony Jones static void ucb1x00_release(struct device *dev) 520585f5457SNicolas Pitre { 521585f5457SNicolas Pitre struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); 522585f5457SNicolas Pitre kfree(ucb); 523585f5457SNicolas Pitre } 524585f5457SNicolas Pitre 525585f5457SNicolas Pitre static struct class ucb1x00_class = { 526585f5457SNicolas Pitre .name = "ucb1x00", 5270c55445fSTony Jones .dev_release = ucb1x00_release, 528585f5457SNicolas Pitre }; 529585f5457SNicolas Pitre 53005c45ca9SRussell King static int ucb1x00_probe(struct mcp *mcp) 53105c45ca9SRussell King { 5322f7510c6SRussell King struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data; 53305c45ca9SRussell King struct ucb1x00_driver *drv; 5342f7510c6SRussell King struct ucb1x00 *ucb; 53505c45ca9SRussell King unsigned int id; 53605c45ca9SRussell King int ret = -ENODEV; 5379ca3dc80SThomas Kunze int temp; 53805c45ca9SRussell King 5392f7510c6SRussell King /* Tell the platform to deassert the UCB1x00 reset */ 5402f7510c6SRussell King if (pdata && pdata->reset) 5412f7510c6SRussell King pdata->reset(UCB_RST_PROBE); 5422f7510c6SRussell King 54305c45ca9SRussell King mcp_enable(mcp); 54405c45ca9SRussell King id = mcp_reg_read(mcp, UCB_ID); 54505c45ca9SRussell King 54665f2e753SRussell King if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) { 54765f2e753SRussell King printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id); 54805c45ca9SRussell King goto err_disable; 54905c45ca9SRussell King } 55005c45ca9SRussell King 551dd00cc48SYoann Padioleau ucb = kzalloc(sizeof(struct ucb1x00), GFP_KERNEL); 55205c45ca9SRussell King ret = -ENOMEM; 55305c45ca9SRussell King if (!ucb) 55405c45ca9SRussell King goto err_disable; 55505c45ca9SRussell King 5560c55445fSTony Jones ucb->dev.class = &ucb1x00_class; 5570c55445fSTony Jones ucb->dev.parent = &mcp->attached_device; 55865f2e753SRussell King dev_set_name(&ucb->dev, "ucb1x00"); 55905c45ca9SRussell King 56005c45ca9SRussell King spin_lock_init(&ucb->lock); 56105c45ca9SRussell King spin_lock_init(&ucb->io_lock); 562cae15476SRussell King mutex_init(&ucb->adc_mutex); 56305c45ca9SRussell King 56465f2e753SRussell King ucb->id = id; 56505c45ca9SRussell King ucb->mcp = mcp; 56605c45ca9SRussell King ucb->irq = ucb1x00_detect_irq(ucb); 56705c45ca9SRussell King if (ucb->irq == NO_IRQ) { 56865f2e753SRussell King printk(KERN_ERR "UCB1x00: IRQ probe failed\n"); 56905c45ca9SRussell King ret = -ENODEV; 57005c45ca9SRussell King goto err_free; 57105c45ca9SRussell King } 57205c45ca9SRussell King 5739ca3dc80SThomas Kunze ucb->gpio.base = -1; 574abe06082SRussell King if (pdata && pdata->gpio_base) { 5759ca3dc80SThomas Kunze ucb->gpio.label = dev_name(&ucb->dev); 576abe06082SRussell King ucb->gpio.base = pdata->gpio_base; 5779ca3dc80SThomas Kunze ucb->gpio.ngpio = 10; 5789ca3dc80SThomas Kunze ucb->gpio.set = ucb1x00_gpio_set; 5799ca3dc80SThomas Kunze ucb->gpio.get = ucb1x00_gpio_get; 5809ca3dc80SThomas Kunze ucb->gpio.direction_input = ucb1x00_gpio_direction_input; 5819ca3dc80SThomas Kunze ucb->gpio.direction_output = ucb1x00_gpio_direction_output; 5829ca3dc80SThomas Kunze ret = gpiochip_add(&ucb->gpio); 5839ca3dc80SThomas Kunze if (ret) 5849ca3dc80SThomas Kunze goto err_free; 5859ca3dc80SThomas Kunze } else 5869ca3dc80SThomas Kunze dev_info(&ucb->dev, "gpio_base not set so no gpiolib support"); 5879ca3dc80SThomas Kunze 588dace1453SThomas Gleixner ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING, 58965f2e753SRussell King "UCB1x00", ucb); 59005c45ca9SRussell King if (ret) { 59165f2e753SRussell King printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", 59265f2e753SRussell King ucb->irq, ret); 5939ca3dc80SThomas Kunze goto err_gpio; 59405c45ca9SRussell King } 59505c45ca9SRussell King 59605c45ca9SRussell King mcp_set_drvdata(mcp, ucb); 59705c45ca9SRussell King 5980c55445fSTony Jones ret = device_register(&ucb->dev); 59905c45ca9SRussell King if (ret) 60005c45ca9SRussell King goto err_irq; 60105c45ca9SRussell King 6029ca3dc80SThomas Kunze 60305c45ca9SRussell King INIT_LIST_HEAD(&ucb->devs); 604a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 60505c45ca9SRussell King list_add(&ucb->node, &ucb1x00_devices); 60605c45ca9SRussell King list_for_each_entry(drv, &ucb1x00_drivers, node) { 60705c45ca9SRussell King ucb1x00_add_dev(ucb, drv); 60805c45ca9SRussell King } 609a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 6109ca3dc80SThomas Kunze 6112f7510c6SRussell King return ret; 61205c45ca9SRussell King 61305c45ca9SRussell King err_irq: 61405c45ca9SRussell King free_irq(ucb->irq, ucb); 6159ca3dc80SThomas Kunze err_gpio: 6169ca3dc80SThomas Kunze if (ucb->gpio.base != -1) 6179ca3dc80SThomas Kunze temp = gpiochip_remove(&ucb->gpio); 61805c45ca9SRussell King err_free: 61905c45ca9SRussell King kfree(ucb); 62005c45ca9SRussell King err_disable: 62105c45ca9SRussell King mcp_disable(mcp); 62205c45ca9SRussell King out: 6232f7510c6SRussell King if (pdata && pdata->reset) 6242f7510c6SRussell King pdata->reset(UCB_RST_PROBE_FAIL); 62505c45ca9SRussell King return ret; 62605c45ca9SRussell King } 62705c45ca9SRussell King 62805c45ca9SRussell King static void ucb1x00_remove(struct mcp *mcp) 62905c45ca9SRussell King { 6302f7510c6SRussell King struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data; 63105c45ca9SRussell King struct ucb1x00 *ucb = mcp_get_drvdata(mcp); 63205c45ca9SRussell King struct list_head *l, *n; 6339ca3dc80SThomas Kunze int ret; 63405c45ca9SRussell King 635a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 63605c45ca9SRussell King list_del(&ucb->node); 63705c45ca9SRussell King list_for_each_safe(l, n, &ucb->devs) { 63805c45ca9SRussell King struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, dev_node); 63905c45ca9SRussell King ucb1x00_remove_dev(dev); 64005c45ca9SRussell King } 641a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 64205c45ca9SRussell King 6439ca3dc80SThomas Kunze if (ucb->gpio.base != -1) { 6449ca3dc80SThomas Kunze ret = gpiochip_remove(&ucb->gpio); 6459ca3dc80SThomas Kunze if (ret) 6469ca3dc80SThomas Kunze dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret); 6479ca3dc80SThomas Kunze } 6489ca3dc80SThomas Kunze 64905c45ca9SRussell King free_irq(ucb->irq, ucb); 6500c55445fSTony Jones device_unregister(&ucb->dev); 6512f7510c6SRussell King 6522f7510c6SRussell King if (pdata && pdata->reset) 6532f7510c6SRussell King pdata->reset(UCB_RST_REMOVE); 65405c45ca9SRussell King } 65505c45ca9SRussell King 65605c45ca9SRussell King int ucb1x00_register_driver(struct ucb1x00_driver *drv) 65705c45ca9SRussell King { 65805c45ca9SRussell King struct ucb1x00 *ucb; 65905c45ca9SRussell King 66005c45ca9SRussell King INIT_LIST_HEAD(&drv->devs); 661a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 66205c45ca9SRussell King list_add(&drv->node, &ucb1x00_drivers); 66305c45ca9SRussell King list_for_each_entry(ucb, &ucb1x00_devices, node) { 66405c45ca9SRussell King ucb1x00_add_dev(ucb, drv); 66505c45ca9SRussell King } 666a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 66705c45ca9SRussell King return 0; 66805c45ca9SRussell King } 66905c45ca9SRussell King 67005c45ca9SRussell King void ucb1x00_unregister_driver(struct ucb1x00_driver *drv) 67105c45ca9SRussell King { 67205c45ca9SRussell King struct list_head *n, *l; 67305c45ca9SRussell King 674a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 67505c45ca9SRussell King list_del(&drv->node); 67605c45ca9SRussell King list_for_each_safe(l, n, &drv->devs) { 67705c45ca9SRussell King struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, drv_node); 67805c45ca9SRussell King ucb1x00_remove_dev(dev); 67905c45ca9SRussell King } 680a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 68105c45ca9SRussell King } 68205c45ca9SRussell King 68305c45ca9SRussell King static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state) 68405c45ca9SRussell King { 68505c45ca9SRussell King struct ucb1x00 *ucb = mcp_get_drvdata(mcp); 68605c45ca9SRussell King struct ucb1x00_dev *dev; 68705c45ca9SRussell King 688a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 68905c45ca9SRussell King list_for_each_entry(dev, &ucb->devs, dev_node) { 69005c45ca9SRussell King if (dev->drv->suspend) 69105c45ca9SRussell King dev->drv->suspend(dev, state); 69205c45ca9SRussell King } 693a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 69405c45ca9SRussell King return 0; 69505c45ca9SRussell King } 69605c45ca9SRussell King 69705c45ca9SRussell King static int ucb1x00_resume(struct mcp *mcp) 69805c45ca9SRussell King { 69905c45ca9SRussell King struct ucb1x00 *ucb = mcp_get_drvdata(mcp); 70005c45ca9SRussell King struct ucb1x00_dev *dev; 70105c45ca9SRussell King 7022e95e51eSRussell King ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); 7039ca3dc80SThomas Kunze ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); 704a621aaedSArjan van de Ven mutex_lock(&ucb1x00_mutex); 70505c45ca9SRussell King list_for_each_entry(dev, &ucb->devs, dev_node) { 70605c45ca9SRussell King if (dev->drv->resume) 70705c45ca9SRussell King dev->drv->resume(dev); 70805c45ca9SRussell King } 709a621aaedSArjan van de Ven mutex_unlock(&ucb1x00_mutex); 71005c45ca9SRussell King return 0; 71105c45ca9SRussell King } 71205c45ca9SRussell King 71305c45ca9SRussell King static struct mcp_driver ucb1x00_driver = { 71405c45ca9SRussell King .drv = { 71505c45ca9SRussell King .name = "ucb1x00", 716ddb1e04aSRussell King .owner = THIS_MODULE, 71705c45ca9SRussell King }, 71805c45ca9SRussell King .probe = ucb1x00_probe, 71905c45ca9SRussell King .remove = ucb1x00_remove, 72005c45ca9SRussell King .suspend = ucb1x00_suspend, 72105c45ca9SRussell King .resume = ucb1x00_resume, 72205c45ca9SRussell King }; 72305c45ca9SRussell King 72405c45ca9SRussell King static int __init ucb1x00_init(void) 72505c45ca9SRussell King { 72605c45ca9SRussell King int ret = class_register(&ucb1x00_class); 72705c45ca9SRussell King if (ret == 0) { 72805c45ca9SRussell King ret = mcp_driver_register(&ucb1x00_driver); 72905c45ca9SRussell King if (ret) 73005c45ca9SRussell King class_unregister(&ucb1x00_class); 73105c45ca9SRussell King } 73205c45ca9SRussell King return ret; 73305c45ca9SRussell King } 73405c45ca9SRussell King 73505c45ca9SRussell King static void __exit ucb1x00_exit(void) 73605c45ca9SRussell King { 73705c45ca9SRussell King mcp_driver_unregister(&ucb1x00_driver); 73805c45ca9SRussell King class_unregister(&ucb1x00_class); 73905c45ca9SRussell King } 74005c45ca9SRussell King 74105c45ca9SRussell King module_init(ucb1x00_init); 74205c45ca9SRussell King module_exit(ucb1x00_exit); 74305c45ca9SRussell King 74405c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_io_set_dir); 74505c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_io_write); 74605c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_io_read); 74705c45ca9SRussell King 74805c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_adc_enable); 74905c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_adc_read); 75005c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_adc_disable); 75105c45ca9SRussell King 75205c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_hook_irq); 75305c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_free_irq); 75405c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_enable_irq); 75505c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_disable_irq); 75605c45ca9SRussell King 75705c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_register_driver); 75805c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_unregister_driver); 75905c45ca9SRussell King 760ddb1e04aSRussell King MODULE_ALIAS("mcp:ucb1x00"); 76105c45ca9SRussell King MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); 76205c45ca9SRussell King MODULE_DESCRIPTION("UCB1x00 core driver"); 76305c45ca9SRussell King MODULE_LICENSE("GPL"); 764