xref: /openbmc/linux/drivers/mfd/ucb1x00-core.c (revision 334a41ce)
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>
26a3364409SRussell King #include <linux/irq.h>
2705c45ca9SRussell King #include <linux/device.h>
28a621aaedSArjan van de Ven #include <linux/mutex.h>
29c8602edfSThomas Kunze #include <linux/mfd/ucb1x00.h>
305a09b712SRussell King #include <linux/pm.h>
319ca3dc80SThomas Kunze #include <linux/gpio.h>
3205c45ca9SRussell King 
33a621aaedSArjan van de Ven static DEFINE_MUTEX(ucb1x00_mutex);
3405c45ca9SRussell King static LIST_HEAD(ucb1x00_drivers);
3505c45ca9SRussell King static LIST_HEAD(ucb1x00_devices);
3605c45ca9SRussell King 
3705c45ca9SRussell King /**
3805c45ca9SRussell King  *	ucb1x00_io_set_dir - set IO direction
3905c45ca9SRussell King  *	@ucb: UCB1x00 structure describing chip
4005c45ca9SRussell King  *	@in:  bitfield of IO pins to be set as inputs
4105c45ca9SRussell King  *	@out: bitfield of IO pins to be set as outputs
4205c45ca9SRussell King  *
4305c45ca9SRussell King  *	Set the IO direction of the ten general purpose IO pins on
4405c45ca9SRussell King  *	the UCB1x00 chip.  The @in bitfield has priority over the
4505c45ca9SRussell King  *	@out bitfield, in that if you specify a pin as both input
4605c45ca9SRussell King  *	and output, it will end up as an input.
4705c45ca9SRussell King  *
4805c45ca9SRussell King  *	ucb1x00_enable must have been called to enable the comms
4905c45ca9SRussell King  *	before using this function.
5005c45ca9SRussell King  *
5105c45ca9SRussell King  *	This function takes a spinlock, disabling interrupts.
5205c45ca9SRussell King  */
5305c45ca9SRussell King void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out)
5405c45ca9SRussell King {
5505c45ca9SRussell King 	unsigned long flags;
5605c45ca9SRussell King 
5705c45ca9SRussell King 	spin_lock_irqsave(&ucb->io_lock, flags);
5805c45ca9SRussell King 	ucb->io_dir |= out;
5905c45ca9SRussell King 	ucb->io_dir &= ~in;
6005c45ca9SRussell King 
6105c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
6205c45ca9SRussell King 	spin_unlock_irqrestore(&ucb->io_lock, flags);
6305c45ca9SRussell King }
6405c45ca9SRussell King 
6505c45ca9SRussell King /**
6605c45ca9SRussell King  *	ucb1x00_io_write - set or clear IO outputs
6705c45ca9SRussell King  *	@ucb:   UCB1x00 structure describing chip
6805c45ca9SRussell King  *	@set:   bitfield of IO pins to set to logic '1'
6905c45ca9SRussell King  *	@clear: bitfield of IO pins to set to logic '0'
7005c45ca9SRussell King  *
7105c45ca9SRussell King  *	Set the IO output state of the specified IO pins.  The value
7205c45ca9SRussell King  *	is retained if the pins are subsequently configured as inputs.
7305c45ca9SRussell King  *	The @clear bitfield has priority over the @set bitfield -
7405c45ca9SRussell King  *	outputs will be cleared.
7505c45ca9SRussell King  *
7605c45ca9SRussell King  *	ucb1x00_enable must have been called to enable the comms
7705c45ca9SRussell King  *	before using this function.
7805c45ca9SRussell King  *
7905c45ca9SRussell King  *	This function takes a spinlock, disabling interrupts.
8005c45ca9SRussell King  */
8105c45ca9SRussell King void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear)
8205c45ca9SRussell King {
8305c45ca9SRussell King 	unsigned long flags;
8405c45ca9SRussell King 
8505c45ca9SRussell King 	spin_lock_irqsave(&ucb->io_lock, flags);
8605c45ca9SRussell King 	ucb->io_out |= set;
8705c45ca9SRussell King 	ucb->io_out &= ~clear;
8805c45ca9SRussell King 
8905c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
9005c45ca9SRussell King 	spin_unlock_irqrestore(&ucb->io_lock, flags);
9105c45ca9SRussell King }
9205c45ca9SRussell King 
9305c45ca9SRussell King /**
9405c45ca9SRussell King  *	ucb1x00_io_read - read the current state of the IO pins
9505c45ca9SRussell King  *	@ucb: UCB1x00 structure describing chip
9605c45ca9SRussell King  *
9705c45ca9SRussell King  *	Return a bitfield describing the logic state of the ten
9805c45ca9SRussell King  *	general purpose IO pins.
9905c45ca9SRussell King  *
10005c45ca9SRussell King  *	ucb1x00_enable must have been called to enable the comms
10105c45ca9SRussell King  *	before using this function.
10205c45ca9SRussell King  *
103cae15476SRussell King  *	This function does not take any mutexes or spinlocks.
10405c45ca9SRussell King  */
10505c45ca9SRussell King unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
10605c45ca9SRussell King {
10705c45ca9SRussell King 	return ucb1x00_reg_read(ucb, UCB_IO_DATA);
10805c45ca9SRussell King }
10905c45ca9SRussell King 
1109ca3dc80SThomas Kunze static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
1119ca3dc80SThomas Kunze {
1129ca3dc80SThomas Kunze 	struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
1139ca3dc80SThomas Kunze 	unsigned long flags;
1149ca3dc80SThomas Kunze 
1159ca3dc80SThomas Kunze 	spin_lock_irqsave(&ucb->io_lock, flags);
1169ca3dc80SThomas Kunze 	if (value)
1179ca3dc80SThomas Kunze 		ucb->io_out |= 1 << offset;
1189ca3dc80SThomas Kunze 	else
1199ca3dc80SThomas Kunze 		ucb->io_out &= ~(1 << offset);
1209ca3dc80SThomas Kunze 
121ed442b67SRussell King 	ucb1x00_enable(ucb);
1229ca3dc80SThomas Kunze 	ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
123ed442b67SRussell King 	ucb1x00_disable(ucb);
1249ca3dc80SThomas Kunze 	spin_unlock_irqrestore(&ucb->io_lock, flags);
1259ca3dc80SThomas Kunze }
1269ca3dc80SThomas Kunze 
1279ca3dc80SThomas Kunze static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
1289ca3dc80SThomas Kunze {
1299ca3dc80SThomas Kunze 	struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
130ed442b67SRussell King 	unsigned val;
131ed442b67SRussell King 
132ed442b67SRussell King 	ucb1x00_enable(ucb);
133ed442b67SRussell King 	val = ucb1x00_reg_read(ucb, UCB_IO_DATA);
134ed442b67SRussell King 	ucb1x00_disable(ucb);
135ed442b67SRussell King 
136ed442b67SRussell King 	return val & (1 << offset);
1379ca3dc80SThomas Kunze }
1389ca3dc80SThomas Kunze 
1399ca3dc80SThomas Kunze static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
1409ca3dc80SThomas Kunze {
1419ca3dc80SThomas Kunze 	struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
1429ca3dc80SThomas Kunze 	unsigned long flags;
1439ca3dc80SThomas Kunze 
1449ca3dc80SThomas Kunze 	spin_lock_irqsave(&ucb->io_lock, flags);
1459ca3dc80SThomas Kunze 	ucb->io_dir &= ~(1 << offset);
146ed442b67SRussell King 	ucb1x00_enable(ucb);
1479ca3dc80SThomas Kunze 	ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
148ed442b67SRussell King 	ucb1x00_disable(ucb);
1499ca3dc80SThomas Kunze 	spin_unlock_irqrestore(&ucb->io_lock, flags);
1509ca3dc80SThomas Kunze 
1519ca3dc80SThomas Kunze 	return 0;
1529ca3dc80SThomas Kunze }
1539ca3dc80SThomas Kunze 
1549ca3dc80SThomas Kunze static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
1559ca3dc80SThomas Kunze 		, int value)
1569ca3dc80SThomas Kunze {
1579ca3dc80SThomas Kunze 	struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
1589ca3dc80SThomas Kunze 	unsigned long flags;
159c23bb602SRussell King 	unsigned old, mask = 1 << offset;
1609ca3dc80SThomas Kunze 
1619ca3dc80SThomas Kunze 	spin_lock_irqsave(&ucb->io_lock, flags);
162c23bb602SRussell King 	old = ucb->io_out;
1639ca3dc80SThomas Kunze 	if (value)
164c23bb602SRussell King 		ucb->io_out |= mask;
1659ca3dc80SThomas Kunze 	else
166c23bb602SRussell King 		ucb->io_out &= ~mask;
167c23bb602SRussell King 
168ed442b67SRussell King 	ucb1x00_enable(ucb);
169c23bb602SRussell King 	if (old != ucb->io_out)
1709ca3dc80SThomas Kunze 		ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
171c23bb602SRussell King 
172c23bb602SRussell King 	if (!(ucb->io_dir & mask)) {
173c23bb602SRussell King 		ucb->io_dir |= mask;
174c23bb602SRussell King 		ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
175c23bb602SRussell King 	}
176ed442b67SRussell King 	ucb1x00_disable(ucb);
1779ca3dc80SThomas Kunze 	spin_unlock_irqrestore(&ucb->io_lock, flags);
1789ca3dc80SThomas Kunze 
1799ca3dc80SThomas Kunze 	return 0;
1809ca3dc80SThomas Kunze }
1819ca3dc80SThomas Kunze 
182a3364409SRussell King static int ucb1x00_to_irq(struct gpio_chip *chip, unsigned offset)
183a3364409SRussell King {
184a3364409SRussell King 	struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
185a3364409SRussell King 
186a3364409SRussell King 	return ucb->irq_base > 0 ? ucb->irq_base + offset : -ENXIO;
187a3364409SRussell King }
188a3364409SRussell King 
18905c45ca9SRussell King /*
19005c45ca9SRussell King  * UCB1300 data sheet says we must:
19105c45ca9SRussell King  *  1. enable ADC	=> 5us (including reference startup time)
19205c45ca9SRussell King  *  2. select input	=> 51*tsibclk  => 4.3us
19305c45ca9SRussell King  *  3. start conversion	=> 102*tsibclk => 8.5us
19405c45ca9SRussell King  * (tsibclk = 1/11981000)
19505c45ca9SRussell King  * Period between SIB 128-bit frames = 10.7us
19605c45ca9SRussell King  */
19705c45ca9SRussell King 
19805c45ca9SRussell King /**
19905c45ca9SRussell King  *	ucb1x00_adc_enable - enable the ADC converter
20005c45ca9SRussell King  *	@ucb: UCB1x00 structure describing chip
20105c45ca9SRussell King  *
20205c45ca9SRussell King  *	Enable the ucb1x00 and ADC converter on the UCB1x00 for use.
20305c45ca9SRussell King  *	Any code wishing to use the ADC converter must call this
20405c45ca9SRussell King  *	function prior to using it.
20505c45ca9SRussell King  *
206cae15476SRussell King  *	This function takes the ADC mutex to prevent two or more
20705c45ca9SRussell King  *	concurrent uses, and therefore may sleep.  As a result, it
20805c45ca9SRussell King  *	can only be called from process context, not interrupt
20905c45ca9SRussell King  *	context.
21005c45ca9SRussell King  *
21105c45ca9SRussell King  *	You should release the ADC as soon as possible using
21205c45ca9SRussell King  *	ucb1x00_adc_disable.
21305c45ca9SRussell King  */
21405c45ca9SRussell King void ucb1x00_adc_enable(struct ucb1x00 *ucb)
21505c45ca9SRussell King {
216cae15476SRussell King 	mutex_lock(&ucb->adc_mutex);
21705c45ca9SRussell King 
21805c45ca9SRussell King 	ucb->adc_cr |= UCB_ADC_ENA;
21905c45ca9SRussell King 
22005c45ca9SRussell King 	ucb1x00_enable(ucb);
22105c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
22205c45ca9SRussell King }
22305c45ca9SRussell King 
22405c45ca9SRussell King /**
22505c45ca9SRussell King  *	ucb1x00_adc_read - read the specified ADC channel
22605c45ca9SRussell King  *	@ucb: UCB1x00 structure describing chip
22705c45ca9SRussell King  *	@adc_channel: ADC channel mask
22805c45ca9SRussell King  *	@sync: wait for syncronisation pulse.
22905c45ca9SRussell King  *
23005c45ca9SRussell King  *	Start an ADC conversion and wait for the result.  Note that
23105c45ca9SRussell King  *	synchronised ADC conversions (via the ADCSYNC pin) must wait
23205c45ca9SRussell King  *	until the trigger is asserted and the conversion is finished.
23305c45ca9SRussell King  *
23405c45ca9SRussell King  *	This function currently spins waiting for the conversion to
23505c45ca9SRussell King  *	complete (2 frames max without sync).
23605c45ca9SRussell King  *
23705c45ca9SRussell King  *	If called for a synchronised ADC conversion, it may sleep
238cae15476SRussell King  *	with the ADC mutex held.
23905c45ca9SRussell King  */
24005c45ca9SRussell King unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
24105c45ca9SRussell King {
24205c45ca9SRussell King 	unsigned int val;
24305c45ca9SRussell King 
24405c45ca9SRussell King 	if (sync)
24505c45ca9SRussell King 		adc_channel |= UCB_ADC_SYNC_ENA;
24605c45ca9SRussell King 
24705c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel);
24805c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START);
24905c45ca9SRussell King 
25005c45ca9SRussell King 	for (;;) {
25105c45ca9SRussell King 		val = ucb1x00_reg_read(ucb, UCB_ADC_DATA);
25205c45ca9SRussell King 		if (val & UCB_ADC_DAT_VAL)
25305c45ca9SRussell King 			break;
25405c45ca9SRussell King 		/* yield to other processes */
25505c45ca9SRussell King 		set_current_state(TASK_INTERRUPTIBLE);
25605c45ca9SRussell King 		schedule_timeout(1);
25705c45ca9SRussell King 	}
25805c45ca9SRussell King 
25905c45ca9SRussell King 	return UCB_ADC_DAT(val);
26005c45ca9SRussell King }
26105c45ca9SRussell King 
26205c45ca9SRussell King /**
26305c45ca9SRussell King  *	ucb1x00_adc_disable - disable the ADC converter
26405c45ca9SRussell King  *	@ucb: UCB1x00 structure describing chip
26505c45ca9SRussell King  *
266cae15476SRussell King  *	Disable the ADC converter and release the ADC mutex.
26705c45ca9SRussell King  */
26805c45ca9SRussell King void ucb1x00_adc_disable(struct ucb1x00 *ucb)
26905c45ca9SRussell King {
27005c45ca9SRussell King 	ucb->adc_cr &= ~UCB_ADC_ENA;
27105c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
27205c45ca9SRussell King 	ucb1x00_disable(ucb);
27305c45ca9SRussell King 
274cae15476SRussell King 	mutex_unlock(&ucb->adc_mutex);
27505c45ca9SRussell King }
27605c45ca9SRussell King 
27705c45ca9SRussell King /*
27805c45ca9SRussell King  * UCB1x00 Interrupt handling.
27905c45ca9SRussell King  *
28005c45ca9SRussell King  * The UCB1x00 can generate interrupts when the SIBCLK is stopped.
28105c45ca9SRussell King  * Since we need to read an internal register, we must re-enable
28205c45ca9SRussell King  * SIBCLK to talk to the chip.  We leave the clock running until
28305c45ca9SRussell King  * we have finished processing all interrupts from the chip.
28405c45ca9SRussell King  */
285a3364409SRussell King static void ucb1x00_irq(unsigned int irq, struct irq_desc *desc)
28605c45ca9SRussell King {
287a3364409SRussell King 	struct ucb1x00 *ucb = irq_desc_get_handler_data(desc);
28805c45ca9SRussell King 	unsigned int isr, i;
28905c45ca9SRussell King 
29005c45ca9SRussell King 	ucb1x00_enable(ucb);
29105c45ca9SRussell King 	isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
29205c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
29305c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
29405c45ca9SRussell King 
295a3364409SRussell King 	for (i = 0; i < 16 && isr; i++, isr >>= 1, irq++)
296a3364409SRussell King 		if (isr & 1)
297a3364409SRussell King 			generic_handle_irq(ucb->irq_base + i);
29805c45ca9SRussell King 	ucb1x00_disable(ucb);
29905c45ca9SRussell King }
30005c45ca9SRussell King 
301a3364409SRussell King static void ucb1x00_irq_update(struct ucb1x00 *ucb, unsigned mask)
30205c45ca9SRussell King {
30305c45ca9SRussell King 	ucb1x00_enable(ucb);
304a3364409SRussell King 	if (ucb->irq_ris_enbl & mask)
305a3364409SRussell King 		ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
306a3364409SRussell King 				  ucb->irq_mask);
307a3364409SRussell King 	if (ucb->irq_fal_enbl & mask)
308a3364409SRussell King 		ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
309a3364409SRussell King 				  ucb->irq_mask);
31005c45ca9SRussell King 	ucb1x00_disable(ucb);
31105c45ca9SRussell King }
31205c45ca9SRussell King 
313a3364409SRussell King static void ucb1x00_irq_noop(struct irq_data *data)
31405c45ca9SRussell King {
31505c45ca9SRussell King }
31605c45ca9SRussell King 
317a3364409SRussell King static void ucb1x00_irq_mask(struct irq_data *data)
31805c45ca9SRussell King {
319a3364409SRussell King 	struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
320a3364409SRussell King 	unsigned mask = 1 << (data->irq - ucb->irq_base);
32105c45ca9SRussell King 
322a3364409SRussell King 	raw_spin_lock(&ucb->irq_lock);
323a3364409SRussell King 	ucb->irq_mask &= ~mask;
324a3364409SRussell King 	ucb1x00_irq_update(ucb, mask);
325a3364409SRussell King 	raw_spin_unlock(&ucb->irq_lock);
32605c45ca9SRussell King }
32705c45ca9SRussell King 
328a3364409SRussell King static void ucb1x00_irq_unmask(struct irq_data *data)
329a3364409SRussell King {
330a3364409SRussell King 	struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
331a3364409SRussell King 	unsigned mask = 1 << (data->irq - ucb->irq_base);
332a3364409SRussell King 
333a3364409SRussell King 	raw_spin_lock(&ucb->irq_lock);
334a3364409SRussell King 	ucb->irq_mask |= mask;
335a3364409SRussell King 	ucb1x00_irq_update(ucb, mask);
336a3364409SRussell King 	raw_spin_unlock(&ucb->irq_lock);
33705c45ca9SRussell King }
33805c45ca9SRussell King 
339a3364409SRussell King static int ucb1x00_irq_set_type(struct irq_data *data, unsigned int type)
340a3364409SRussell King {
341a3364409SRussell King 	struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
342a3364409SRussell King 	unsigned mask = 1 << (data->irq - ucb->irq_base);
343a3364409SRussell King 
344a3364409SRussell King 	raw_spin_lock(&ucb->irq_lock);
345a3364409SRussell King 	if (type & IRQ_TYPE_EDGE_RISING)
346a3364409SRussell King 		ucb->irq_ris_enbl |= mask;
347a3364409SRussell King 	else
348a3364409SRussell King 		ucb->irq_ris_enbl &= ~mask;
349a3364409SRussell King 
350a3364409SRussell King 	if (type & IRQ_TYPE_EDGE_FALLING)
351a3364409SRussell King 		ucb->irq_fal_enbl |= mask;
352a3364409SRussell King 	else
353a3364409SRussell King 		ucb->irq_fal_enbl &= ~mask;
354a3364409SRussell King 	if (ucb->irq_mask & mask) {
355a3364409SRussell King 		ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
356a3364409SRussell King 				  ucb->irq_mask);
357a3364409SRussell King 		ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
358a3364409SRussell King 				  ucb->irq_mask);
359a3364409SRussell King 	}
360a3364409SRussell King 	raw_spin_unlock(&ucb->irq_lock);
361a3364409SRussell King 
362a3364409SRussell King 	return 0;
363a3364409SRussell King }
364a3364409SRussell King 
36533237616SRussell King static int ucb1x00_irq_set_wake(struct irq_data *data, unsigned int on)
36633237616SRussell King {
36733237616SRussell King 	struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
36833237616SRussell King 	struct ucb1x00_plat_data *pdata = ucb->mcp->attached_device.platform_data;
36933237616SRussell King 	unsigned mask = 1 << (data->irq - ucb->irq_base);
37033237616SRussell King 
37133237616SRussell King 	if (!pdata || !pdata->can_wakeup)
37233237616SRussell King 		return -EINVAL;
37333237616SRussell King 
37433237616SRussell King 	raw_spin_lock(&ucb->irq_lock);
37533237616SRussell King 	if (on)
37633237616SRussell King 		ucb->irq_wake |= mask;
37733237616SRussell King 	else
37833237616SRussell King 		ucb->irq_wake &= ~mask;
37933237616SRussell King 	raw_spin_unlock(&ucb->irq_lock);
38033237616SRussell King 
38133237616SRussell King 	return 0;
38233237616SRussell King }
38333237616SRussell King 
384a3364409SRussell King static struct irq_chip ucb1x00_irqchip = {
385a3364409SRussell King 	.name = "ucb1x00",
386a3364409SRussell King 	.irq_ack = ucb1x00_irq_noop,
387a3364409SRussell King 	.irq_mask = ucb1x00_irq_mask,
388a3364409SRussell King 	.irq_unmask = ucb1x00_irq_unmask,
389a3364409SRussell King 	.irq_set_type = ucb1x00_irq_set_type,
39033237616SRussell King 	.irq_set_wake = ucb1x00_irq_set_wake,
391a3364409SRussell King };
392a3364409SRussell King 
39305c45ca9SRussell King static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv)
39405c45ca9SRussell King {
39505c45ca9SRussell King 	struct ucb1x00_dev *dev;
39605c45ca9SRussell King 	int ret = -ENOMEM;
39705c45ca9SRussell King 
39805c45ca9SRussell King 	dev = kmalloc(sizeof(struct ucb1x00_dev), GFP_KERNEL);
39905c45ca9SRussell King 	if (dev) {
40005c45ca9SRussell King 		dev->ucb = ucb;
40105c45ca9SRussell King 		dev->drv = drv;
40205c45ca9SRussell King 
40305c45ca9SRussell King 		ret = drv->add(dev);
40405c45ca9SRussell King 
40505c45ca9SRussell King 		if (ret == 0) {
40665b539bbSRussell King 			list_add_tail(&dev->dev_node, &ucb->devs);
40765b539bbSRussell King 			list_add_tail(&dev->drv_node, &drv->devs);
40805c45ca9SRussell King 		} else {
40905c45ca9SRussell King 			kfree(dev);
41005c45ca9SRussell King 		}
41105c45ca9SRussell King 	}
41205c45ca9SRussell King 	return ret;
41305c45ca9SRussell King }
41405c45ca9SRussell King 
41505c45ca9SRussell King static void ucb1x00_remove_dev(struct ucb1x00_dev *dev)
41605c45ca9SRussell King {
41705c45ca9SRussell King 	dev->drv->remove(dev);
41805c45ca9SRussell King 	list_del(&dev->dev_node);
41905c45ca9SRussell King 	list_del(&dev->drv_node);
42005c45ca9SRussell King 	kfree(dev);
42105c45ca9SRussell King }
42205c45ca9SRussell King 
42305c45ca9SRussell King /*
42405c45ca9SRussell King  * Try to probe our interrupt, rather than relying on lots of
42505c45ca9SRussell King  * hard-coded machine dependencies.  For reference, the expected
42605c45ca9SRussell King  * IRQ mappings are:
42705c45ca9SRussell King  *
42805c45ca9SRussell King  *  	Machine		Default IRQ
42905c45ca9SRussell King  *	adsbitsy	IRQ_GPCIN4
43005c45ca9SRussell King  *	cerf		IRQ_GPIO_UCB1200_IRQ
43105c45ca9SRussell King  *	flexanet	IRQ_GPIO_GUI
43205c45ca9SRussell King  *	freebird	IRQ_GPIO_FREEBIRD_UCB1300_IRQ
43305c45ca9SRussell King  *	graphicsclient	ADS_EXT_IRQ(8)
43405c45ca9SRussell King  *	graphicsmaster	ADS_EXT_IRQ(8)
43505c45ca9SRussell King  *	lart		LART_IRQ_UCB1200
43605c45ca9SRussell King  *	omnimeter	IRQ_GPIO23
43705c45ca9SRussell King  *	pfs168		IRQ_GPIO_UCB1300_IRQ
43805c45ca9SRussell King  *	simpad		IRQ_GPIO_UCB1300_IRQ
43905c45ca9SRussell King  *	shannon		SHANNON_IRQ_GPIO_IRQ_CODEC
44005c45ca9SRussell King  *	yopy		IRQ_GPIO_UCB1200_IRQ
44105c45ca9SRussell King  */
44205c45ca9SRussell King static int ucb1x00_detect_irq(struct ucb1x00 *ucb)
44305c45ca9SRussell King {
44405c45ca9SRussell King 	unsigned long mask;
44505c45ca9SRussell King 
44605c45ca9SRussell King 	mask = probe_irq_on();
447cfc73656SIngo Molnar 	if (!mask) {
448cfc73656SIngo Molnar 		probe_irq_off(mask);
44905c45ca9SRussell King 		return NO_IRQ;
450cfc73656SIngo Molnar 	}
45105c45ca9SRussell King 
45205c45ca9SRussell King 	/*
45305c45ca9SRussell King 	 * Enable the ADC interrupt.
45405c45ca9SRussell King 	 */
45505c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
45605c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);
45705c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
45805c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
45905c45ca9SRussell King 
46005c45ca9SRussell King 	/*
46105c45ca9SRussell King 	 * Cause an ADC interrupt.
46205c45ca9SRussell King 	 */
46305c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
46405c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
46505c45ca9SRussell King 
46605c45ca9SRussell King 	/*
46705c45ca9SRussell King 	 * Wait for the conversion to complete.
46805c45ca9SRussell King 	 */
46905c45ca9SRussell King 	while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0);
47005c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_ADC_CR, 0);
47105c45ca9SRussell King 
47205c45ca9SRussell King 	/*
47305c45ca9SRussell King 	 * Disable and clear interrupt.
47405c45ca9SRussell King 	 */
47505c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IE_RIS, 0);
47605c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IE_FAL, 0);
47705c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
47805c45ca9SRussell King 	ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
47905c45ca9SRussell King 
48005c45ca9SRussell King 	/*
48105c45ca9SRussell King 	 * Read triggered interrupt.
48205c45ca9SRussell King 	 */
48305c45ca9SRussell King 	return probe_irq_off(mask);
48405c45ca9SRussell King }
48505c45ca9SRussell King 
4860c55445fSTony Jones static void ucb1x00_release(struct device *dev)
487585f5457SNicolas Pitre {
488585f5457SNicolas Pitre 	struct ucb1x00 *ucb = classdev_to_ucb1x00(dev);
489585f5457SNicolas Pitre 	kfree(ucb);
490585f5457SNicolas Pitre }
491585f5457SNicolas Pitre 
492585f5457SNicolas Pitre static struct class ucb1x00_class = {
493585f5457SNicolas Pitre 	.name		= "ucb1x00",
4940c55445fSTony Jones 	.dev_release	= ucb1x00_release,
495585f5457SNicolas Pitre };
496585f5457SNicolas Pitre 
49705c45ca9SRussell King static int ucb1x00_probe(struct mcp *mcp)
49805c45ca9SRussell King {
4992f7510c6SRussell King 	struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data;
50005c45ca9SRussell King 	struct ucb1x00_driver *drv;
5012f7510c6SRussell King 	struct ucb1x00 *ucb;
502a3364409SRussell King 	unsigned id, i, irq_base;
50305c45ca9SRussell King 	int ret = -ENODEV;
50405c45ca9SRussell King 
5052f7510c6SRussell King 	/* Tell the platform to deassert the UCB1x00 reset */
5062f7510c6SRussell King 	if (pdata && pdata->reset)
5072f7510c6SRussell King 		pdata->reset(UCB_RST_PROBE);
5082f7510c6SRussell King 
50905c45ca9SRussell King 	mcp_enable(mcp);
51005c45ca9SRussell King 	id = mcp_reg_read(mcp, UCB_ID);
5112b4d9d2bSRussell King 	mcp_disable(mcp);
51205c45ca9SRussell King 
51365f2e753SRussell King 	if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) {
51465f2e753SRussell King 		printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
5152b4d9d2bSRussell King 		goto out;
51605c45ca9SRussell King 	}
51705c45ca9SRussell King 
518dd00cc48SYoann Padioleau 	ucb = kzalloc(sizeof(struct ucb1x00), GFP_KERNEL);
51905c45ca9SRussell King 	ret = -ENOMEM;
52005c45ca9SRussell King 	if (!ucb)
5212b4d9d2bSRussell King 		goto out;
52205c45ca9SRussell King 
523f5ae587fSRussell King 	device_initialize(&ucb->dev);
5240c55445fSTony Jones 	ucb->dev.class = &ucb1x00_class;
5250c55445fSTony Jones 	ucb->dev.parent = &mcp->attached_device;
52665f2e753SRussell King 	dev_set_name(&ucb->dev, "ucb1x00");
52705c45ca9SRussell King 
528a3364409SRussell King 	raw_spin_lock_init(&ucb->irq_lock);
52905c45ca9SRussell King 	spin_lock_init(&ucb->io_lock);
530cae15476SRussell King 	mutex_init(&ucb->adc_mutex);
53105c45ca9SRussell King 
53265f2e753SRussell King 	ucb->id  = id;
53305c45ca9SRussell King 	ucb->mcp = mcp;
534f5ae587fSRussell King 
535f5ae587fSRussell King 	ret = device_add(&ucb->dev);
536f5ae587fSRussell King 	if (ret)
537f5ae587fSRussell King 		goto err_dev_add;
538f5ae587fSRussell King 
5392b4d9d2bSRussell King 	ucb1x00_enable(ucb);
54005c45ca9SRussell King 	ucb->irq = ucb1x00_detect_irq(ucb);
5412b4d9d2bSRussell King 	ucb1x00_disable(ucb);
54205c45ca9SRussell King 	if (ucb->irq == NO_IRQ) {
543f5ae587fSRussell King 		dev_err(&ucb->dev, "IRQ probe failed\n");
54405c45ca9SRussell King 		ret = -ENODEV;
545f5ae587fSRussell King 		goto err_no_irq;
54605c45ca9SRussell King 	}
54705c45ca9SRussell King 
5489ca3dc80SThomas Kunze 	ucb->gpio.base = -1;
549a3364409SRussell King 	irq_base = pdata ? pdata->irq_base : 0;
550a3364409SRussell King 	ucb->irq_base = irq_alloc_descs(-1, irq_base, 16, -1);
551a3364409SRussell King 	if (ucb->irq_base < 0) {
552a3364409SRussell King 		dev_err(&ucb->dev, "unable to allocate 16 irqs: %d\n",
553a3364409SRussell King 			ucb->irq_base);
554a3364409SRussell King 		goto err_irq_alloc;
555a3364409SRussell King 	}
556a3364409SRussell King 
557a3364409SRussell King 	for (i = 0; i < 16; i++) {
558a3364409SRussell King 		unsigned irq = ucb->irq_base + i;
559a3364409SRussell King 
560a3364409SRussell King 		irq_set_chip_and_handler(irq, &ucb1x00_irqchip, handle_edge_irq);
561a3364409SRussell King 		irq_set_chip_data(irq, ucb);
562a3364409SRussell King 		set_irq_flags(irq, IRQF_VALID | IRQ_NOREQUEST);
563a3364409SRussell King 	}
564a3364409SRussell King 
565a3364409SRussell King 	irq_set_irq_type(ucb->irq, IRQ_TYPE_EDGE_RISING);
566a3364409SRussell King 	irq_set_handler_data(ucb->irq, ucb);
567a3364409SRussell King 	irq_set_chained_handler(ucb->irq, ucb1x00_irq);
568a3364409SRussell King 
569abe06082SRussell King 	if (pdata && pdata->gpio_base) {
5709ca3dc80SThomas Kunze 		ucb->gpio.label = dev_name(&ucb->dev);
5717655b2acSRussell King 		ucb->gpio.dev = &ucb->dev;
5727655b2acSRussell King 		ucb->gpio.owner = THIS_MODULE;
573abe06082SRussell King 		ucb->gpio.base = pdata->gpio_base;
5749ca3dc80SThomas Kunze 		ucb->gpio.ngpio = 10;
5759ca3dc80SThomas Kunze 		ucb->gpio.set = ucb1x00_gpio_set;
5769ca3dc80SThomas Kunze 		ucb->gpio.get = ucb1x00_gpio_get;
5779ca3dc80SThomas Kunze 		ucb->gpio.direction_input = ucb1x00_gpio_direction_input;
5789ca3dc80SThomas Kunze 		ucb->gpio.direction_output = ucb1x00_gpio_direction_output;
579a3364409SRussell King 		ucb->gpio.to_irq = ucb1x00_to_irq;
5809ca3dc80SThomas Kunze 		ret = gpiochip_add(&ucb->gpio);
5819ca3dc80SThomas Kunze 		if (ret)
582f5ae587fSRussell King 			goto err_gpio_add;
5839ca3dc80SThomas Kunze 	} else
5849ca3dc80SThomas Kunze 		dev_info(&ucb->dev, "gpio_base not set so no gpiolib support");
5859ca3dc80SThomas Kunze 
58605c45ca9SRussell King 	mcp_set_drvdata(mcp, ucb);
58705c45ca9SRussell King 
58833237616SRussell King 	if (pdata)
58933237616SRussell King 		device_set_wakeup_capable(&ucb->dev, pdata->can_wakeup);
59033237616SRussell King 
59105c45ca9SRussell King 	INIT_LIST_HEAD(&ucb->devs);
592a621aaedSArjan van de Ven 	mutex_lock(&ucb1x00_mutex);
59365b539bbSRussell King 	list_add_tail(&ucb->node, &ucb1x00_devices);
59405c45ca9SRussell King 	list_for_each_entry(drv, &ucb1x00_drivers, node) {
59505c45ca9SRussell King 		ucb1x00_add_dev(ucb, drv);
59605c45ca9SRussell King 	}
597a621aaedSArjan van de Ven 	mutex_unlock(&ucb1x00_mutex);
5989ca3dc80SThomas Kunze 
5992f7510c6SRussell King 	return ret;
60005c45ca9SRussell King 
601f5ae587fSRussell King  err_gpio_add:
602a3364409SRussell King 	irq_set_chained_handler(ucb->irq, NULL);
603a3364409SRussell King  err_irq_alloc:
604a3364409SRussell King 	if (ucb->irq_base > 0)
605a3364409SRussell King 		irq_free_descs(ucb->irq_base, 16);
606f5ae587fSRussell King  err_no_irq:
607f5ae587fSRussell King 	device_del(&ucb->dev);
608f5ae587fSRussell King  err_dev_add:
609f5ae587fSRussell King 	put_device(&ucb->dev);
61005c45ca9SRussell King  out:
6112f7510c6SRussell King 	if (pdata && pdata->reset)
6122f7510c6SRussell King 		pdata->reset(UCB_RST_PROBE_FAIL);
61305c45ca9SRussell King 	return ret;
61405c45ca9SRussell King }
61505c45ca9SRussell King 
61605c45ca9SRussell King static void ucb1x00_remove(struct mcp *mcp)
61705c45ca9SRussell King {
6182f7510c6SRussell King 	struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data;
61905c45ca9SRussell King 	struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
62005c45ca9SRussell King 	struct list_head *l, *n;
6219ca3dc80SThomas Kunze 	int ret;
62205c45ca9SRussell King 
623a621aaedSArjan van de Ven 	mutex_lock(&ucb1x00_mutex);
62405c45ca9SRussell King 	list_del(&ucb->node);
62505c45ca9SRussell King 	list_for_each_safe(l, n, &ucb->devs) {
62605c45ca9SRussell King 		struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, dev_node);
62705c45ca9SRussell King 		ucb1x00_remove_dev(dev);
62805c45ca9SRussell King 	}
629a621aaedSArjan van de Ven 	mutex_unlock(&ucb1x00_mutex);
63005c45ca9SRussell King 
6319ca3dc80SThomas Kunze 	if (ucb->gpio.base != -1) {
6329ca3dc80SThomas Kunze 		ret = gpiochip_remove(&ucb->gpio);
6339ca3dc80SThomas Kunze 		if (ret)
6349ca3dc80SThomas Kunze 			dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret);
6359ca3dc80SThomas Kunze 	}
6369ca3dc80SThomas Kunze 
637a3364409SRussell King 	irq_set_chained_handler(ucb->irq, NULL);
638a3364409SRussell King 	irq_free_descs(ucb->irq_base, 16);
6390c55445fSTony Jones 	device_unregister(&ucb->dev);
6402f7510c6SRussell King 
6412f7510c6SRussell King 	if (pdata && pdata->reset)
6422f7510c6SRussell King 		pdata->reset(UCB_RST_REMOVE);
64305c45ca9SRussell King }
64405c45ca9SRussell King 
64505c45ca9SRussell King int ucb1x00_register_driver(struct ucb1x00_driver *drv)
64605c45ca9SRussell King {
64705c45ca9SRussell King 	struct ucb1x00 *ucb;
64805c45ca9SRussell King 
64905c45ca9SRussell King 	INIT_LIST_HEAD(&drv->devs);
650a621aaedSArjan van de Ven 	mutex_lock(&ucb1x00_mutex);
65165b539bbSRussell King 	list_add_tail(&drv->node, &ucb1x00_drivers);
65205c45ca9SRussell King 	list_for_each_entry(ucb, &ucb1x00_devices, node) {
65305c45ca9SRussell King 		ucb1x00_add_dev(ucb, drv);
65405c45ca9SRussell King 	}
655a621aaedSArjan van de Ven 	mutex_unlock(&ucb1x00_mutex);
65605c45ca9SRussell King 	return 0;
65705c45ca9SRussell King }
65805c45ca9SRussell King 
65905c45ca9SRussell King void ucb1x00_unregister_driver(struct ucb1x00_driver *drv)
66005c45ca9SRussell King {
66105c45ca9SRussell King 	struct list_head *n, *l;
66205c45ca9SRussell King 
663a621aaedSArjan van de Ven 	mutex_lock(&ucb1x00_mutex);
66405c45ca9SRussell King 	list_del(&drv->node);
66505c45ca9SRussell King 	list_for_each_safe(l, n, &drv->devs) {
66605c45ca9SRussell King 		struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, drv_node);
66705c45ca9SRussell King 		ucb1x00_remove_dev(dev);
66805c45ca9SRussell King 	}
669a621aaedSArjan van de Ven 	mutex_unlock(&ucb1x00_mutex);
67005c45ca9SRussell King }
67105c45ca9SRussell King 
6725a09b712SRussell King static int ucb1x00_suspend(struct device *dev)
67305c45ca9SRussell King {
674334a41ceSJingoo Han 	struct ucb1x00_plat_data *pdata = dev_get_platdata(dev);
6755a09b712SRussell King 	struct ucb1x00 *ucb = dev_get_drvdata(dev);
6765a09b712SRussell King 	struct ucb1x00_dev *udev;
67705c45ca9SRussell King 
678a621aaedSArjan van de Ven 	mutex_lock(&ucb1x00_mutex);
6795a09b712SRussell King 	list_for_each_entry(udev, &ucb->devs, dev_node) {
6805a09b712SRussell King 		if (udev->drv->suspend)
6815a09b712SRussell King 			udev->drv->suspend(udev);
68205c45ca9SRussell King 	}
683a621aaedSArjan van de Ven 	mutex_unlock(&ucb1x00_mutex);
68433237616SRussell King 
68533237616SRussell King 	if (ucb->irq_wake) {
68633237616SRussell King 		unsigned long flags;
68733237616SRussell King 
68833237616SRussell King 		raw_spin_lock_irqsave(&ucb->irq_lock, flags);
68933237616SRussell King 		ucb1x00_enable(ucb);
69033237616SRussell King 		ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
69133237616SRussell King 				  ucb->irq_wake);
69233237616SRussell King 		ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
69333237616SRussell King 				  ucb->irq_wake);
69433237616SRussell King 		ucb1x00_disable(ucb);
69533237616SRussell King 		raw_spin_unlock_irqrestore(&ucb->irq_lock, flags);
69633237616SRussell King 
69733237616SRussell King 		enable_irq_wake(ucb->irq);
69833237616SRussell King 	} else if (pdata && pdata->reset)
69933237616SRussell King 		pdata->reset(UCB_RST_SUSPEND);
70033237616SRussell King 
70105c45ca9SRussell King 	return 0;
70205c45ca9SRussell King }
70305c45ca9SRussell King 
7045a09b712SRussell King static int ucb1x00_resume(struct device *dev)
70505c45ca9SRussell King {
706334a41ceSJingoo Han 	struct ucb1x00_plat_data *pdata = dev_get_platdata(dev);
7075a09b712SRussell King 	struct ucb1x00 *ucb = dev_get_drvdata(dev);
7085a09b712SRussell King 	struct ucb1x00_dev *udev;
70905c45ca9SRussell King 
71033237616SRussell King 	if (!ucb->irq_wake && pdata && pdata->reset)
71133237616SRussell King 		pdata->reset(UCB_RST_RESUME);
71233237616SRussell King 
713ed442b67SRussell King 	ucb1x00_enable(ucb);
7142e95e51eSRussell King 	ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
7159ca3dc80SThomas Kunze 	ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
71633237616SRussell King 
71733237616SRussell King 	if (ucb->irq_wake) {
71833237616SRussell King 		unsigned long flags;
71933237616SRussell King 
72033237616SRussell King 		raw_spin_lock_irqsave(&ucb->irq_lock, flags);
72133237616SRussell King 		ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
72233237616SRussell King 				  ucb->irq_mask);
72333237616SRussell King 		ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
72433237616SRussell King 				  ucb->irq_mask);
72533237616SRussell King 		raw_spin_unlock_irqrestore(&ucb->irq_lock, flags);
72633237616SRussell King 
72733237616SRussell King 		disable_irq_wake(ucb->irq);
72833237616SRussell King 	}
729ed442b67SRussell King 	ucb1x00_disable(ucb);
73033237616SRussell King 
731a621aaedSArjan van de Ven 	mutex_lock(&ucb1x00_mutex);
7325a09b712SRussell King 	list_for_each_entry(udev, &ucb->devs, dev_node) {
7335a09b712SRussell King 		if (udev->drv->resume)
7345a09b712SRussell King 			udev->drv->resume(udev);
73505c45ca9SRussell King 	}
736a621aaedSArjan van de Ven 	mutex_unlock(&ucb1x00_mutex);
73705c45ca9SRussell King 	return 0;
73805c45ca9SRussell King }
73905c45ca9SRussell King 
7405a09b712SRussell King static const struct dev_pm_ops ucb1x00_pm_ops = {
7415a09b712SRussell King 	SET_SYSTEM_SLEEP_PM_OPS(ucb1x00_suspend, ucb1x00_resume)
7425a09b712SRussell King };
7435a09b712SRussell King 
74405c45ca9SRussell King static struct mcp_driver ucb1x00_driver = {
74505c45ca9SRussell King 	.drv		= {
74605c45ca9SRussell King 		.name	= "ucb1x00",
747ddb1e04aSRussell King 		.owner	= THIS_MODULE,
7485a09b712SRussell King 		.pm	= &ucb1x00_pm_ops,
74905c45ca9SRussell King 	},
75005c45ca9SRussell King 	.probe		= ucb1x00_probe,
75105c45ca9SRussell King 	.remove		= ucb1x00_remove,
75205c45ca9SRussell King };
75305c45ca9SRussell King 
75405c45ca9SRussell King static int __init ucb1x00_init(void)
75505c45ca9SRussell King {
75605c45ca9SRussell King 	int ret = class_register(&ucb1x00_class);
75705c45ca9SRussell King 	if (ret == 0) {
75805c45ca9SRussell King 		ret = mcp_driver_register(&ucb1x00_driver);
75905c45ca9SRussell King 		if (ret)
76005c45ca9SRussell King 			class_unregister(&ucb1x00_class);
76105c45ca9SRussell King 	}
76205c45ca9SRussell King 	return ret;
76305c45ca9SRussell King }
76405c45ca9SRussell King 
76505c45ca9SRussell King static void __exit ucb1x00_exit(void)
76605c45ca9SRussell King {
76705c45ca9SRussell King 	mcp_driver_unregister(&ucb1x00_driver);
76805c45ca9SRussell King 	class_unregister(&ucb1x00_class);
76905c45ca9SRussell King }
77005c45ca9SRussell King 
77105c45ca9SRussell King module_init(ucb1x00_init);
77205c45ca9SRussell King module_exit(ucb1x00_exit);
77305c45ca9SRussell King 
77405c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_io_set_dir);
77505c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_io_write);
77605c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_io_read);
77705c45ca9SRussell King 
77805c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_adc_enable);
77905c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_adc_read);
78005c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_adc_disable);
78105c45ca9SRussell King 
78205c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_register_driver);
78305c45ca9SRussell King EXPORT_SYMBOL(ucb1x00_unregister_driver);
78405c45ca9SRussell King 
785ddb1e04aSRussell King MODULE_ALIAS("mcp:ucb1x00");
78605c45ca9SRussell King MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
78705c45ca9SRussell King MODULE_DESCRIPTION("UCB1x00 core driver");
78805c45ca9SRussell King MODULE_LICENSE("GPL");
789