xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision 62579266cf9caca5b999560be2b5ceee42fc4d4d)
1*62579266SRabin Vincent /*
2*62579266SRabin Vincent  * Copyright (C) ST-Ericsson SA 2010
3*62579266SRabin Vincent  *
4*62579266SRabin Vincent  * License Terms: GNU General Public License v2
5*62579266SRabin Vincent  * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
6*62579266SRabin Vincent  * Author: Rabin Vincent <rabin.vincent@stericsson.com>
7*62579266SRabin Vincent  */
8*62579266SRabin Vincent 
9*62579266SRabin Vincent #include <linux/kernel.h>
10*62579266SRabin Vincent #include <linux/slab.h>
11*62579266SRabin Vincent #include <linux/init.h>
12*62579266SRabin Vincent #include <linux/irq.h>
13*62579266SRabin Vincent #include <linux/delay.h>
14*62579266SRabin Vincent #include <linux/interrupt.h>
15*62579266SRabin Vincent #include <linux/module.h>
16*62579266SRabin Vincent #include <linux/platform_device.h>
17*62579266SRabin Vincent #include <linux/mfd/core.h>
18*62579266SRabin Vincent #include <linux/mfd/ab8500.h>
19*62579266SRabin Vincent 
20*62579266SRabin Vincent /*
21*62579266SRabin Vincent  * Interrupt register offsets
22*62579266SRabin Vincent  * Bank : 0x0E
23*62579266SRabin Vincent  */
24*62579266SRabin Vincent #define AB8500_IT_SOURCE1_REG		0x0E00
25*62579266SRabin Vincent #define AB8500_IT_SOURCE2_REG		0x0E01
26*62579266SRabin Vincent #define AB8500_IT_SOURCE3_REG		0x0E02
27*62579266SRabin Vincent #define AB8500_IT_SOURCE4_REG		0x0E03
28*62579266SRabin Vincent #define AB8500_IT_SOURCE5_REG		0x0E04
29*62579266SRabin Vincent #define AB8500_IT_SOURCE6_REG		0x0E05
30*62579266SRabin Vincent #define AB8500_IT_SOURCE7_REG		0x0E06
31*62579266SRabin Vincent #define AB8500_IT_SOURCE8_REG		0x0E07
32*62579266SRabin Vincent #define AB8500_IT_SOURCE19_REG		0x0E12
33*62579266SRabin Vincent #define AB8500_IT_SOURCE20_REG		0x0E13
34*62579266SRabin Vincent #define AB8500_IT_SOURCE21_REG		0x0E14
35*62579266SRabin Vincent #define AB8500_IT_SOURCE22_REG		0x0E15
36*62579266SRabin Vincent #define AB8500_IT_SOURCE23_REG		0x0E16
37*62579266SRabin Vincent #define AB8500_IT_SOURCE24_REG		0x0E17
38*62579266SRabin Vincent 
39*62579266SRabin Vincent /*
40*62579266SRabin Vincent  * latch registers
41*62579266SRabin Vincent  */
42*62579266SRabin Vincent #define AB8500_IT_LATCH1_REG		0x0E20
43*62579266SRabin Vincent #define AB8500_IT_LATCH2_REG		0x0E21
44*62579266SRabin Vincent #define AB8500_IT_LATCH3_REG		0x0E22
45*62579266SRabin Vincent #define AB8500_IT_LATCH4_REG		0x0E23
46*62579266SRabin Vincent #define AB8500_IT_LATCH5_REG		0x0E24
47*62579266SRabin Vincent #define AB8500_IT_LATCH6_REG		0x0E25
48*62579266SRabin Vincent #define AB8500_IT_LATCH7_REG		0x0E26
49*62579266SRabin Vincent #define AB8500_IT_LATCH8_REG		0x0E27
50*62579266SRabin Vincent #define AB8500_IT_LATCH9_REG		0x0E28
51*62579266SRabin Vincent #define AB8500_IT_LATCH10_REG		0x0E29
52*62579266SRabin Vincent #define AB8500_IT_LATCH19_REG		0x0E32
53*62579266SRabin Vincent #define AB8500_IT_LATCH20_REG		0x0E33
54*62579266SRabin Vincent #define AB8500_IT_LATCH21_REG		0x0E34
55*62579266SRabin Vincent #define AB8500_IT_LATCH22_REG		0x0E35
56*62579266SRabin Vincent #define AB8500_IT_LATCH23_REG		0x0E36
57*62579266SRabin Vincent #define AB8500_IT_LATCH24_REG		0x0E37
58*62579266SRabin Vincent 
59*62579266SRabin Vincent /*
60*62579266SRabin Vincent  * mask registers
61*62579266SRabin Vincent  */
62*62579266SRabin Vincent 
63*62579266SRabin Vincent #define AB8500_IT_MASK1_REG		0x0E40
64*62579266SRabin Vincent #define AB8500_IT_MASK2_REG		0x0E41
65*62579266SRabin Vincent #define AB8500_IT_MASK3_REG		0x0E42
66*62579266SRabin Vincent #define AB8500_IT_MASK4_REG		0x0E43
67*62579266SRabin Vincent #define AB8500_IT_MASK5_REG		0x0E44
68*62579266SRabin Vincent #define AB8500_IT_MASK6_REG		0x0E45
69*62579266SRabin Vincent #define AB8500_IT_MASK7_REG		0x0E46
70*62579266SRabin Vincent #define AB8500_IT_MASK8_REG		0x0E47
71*62579266SRabin Vincent #define AB8500_IT_MASK9_REG		0x0E48
72*62579266SRabin Vincent #define AB8500_IT_MASK10_REG		0x0E49
73*62579266SRabin Vincent #define AB8500_IT_MASK11_REG		0x0E4A
74*62579266SRabin Vincent #define AB8500_IT_MASK12_REG		0x0E4B
75*62579266SRabin Vincent #define AB8500_IT_MASK13_REG		0x0E4C
76*62579266SRabin Vincent #define AB8500_IT_MASK14_REG		0x0E4D
77*62579266SRabin Vincent #define AB8500_IT_MASK15_REG		0x0E4E
78*62579266SRabin Vincent #define AB8500_IT_MASK16_REG		0x0E4F
79*62579266SRabin Vincent #define AB8500_IT_MASK17_REG		0x0E50
80*62579266SRabin Vincent #define AB8500_IT_MASK18_REG		0x0E51
81*62579266SRabin Vincent #define AB8500_IT_MASK19_REG		0x0E52
82*62579266SRabin Vincent #define AB8500_IT_MASK20_REG		0x0E53
83*62579266SRabin Vincent #define AB8500_IT_MASK21_REG		0x0E54
84*62579266SRabin Vincent #define AB8500_IT_MASK22_REG		0x0E55
85*62579266SRabin Vincent #define AB8500_IT_MASK23_REG		0x0E56
86*62579266SRabin Vincent #define AB8500_IT_MASK24_REG		0x0E57
87*62579266SRabin Vincent 
88*62579266SRabin Vincent #define AB8500_REV_REG			0x1080
89*62579266SRabin Vincent 
90*62579266SRabin Vincent /*
91*62579266SRabin Vincent  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
92*62579266SRabin Vincent  * numbers are indexed into this array with (num / 8).
93*62579266SRabin Vincent  *
94*62579266SRabin Vincent  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
95*62579266SRabin Vincent  * offset 0.
96*62579266SRabin Vincent  */
97*62579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
98*62579266SRabin Vincent 	0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21,
99*62579266SRabin Vincent };
100*62579266SRabin Vincent 
101*62579266SRabin Vincent static int __ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data)
102*62579266SRabin Vincent {
103*62579266SRabin Vincent 	int ret;
104*62579266SRabin Vincent 
105*62579266SRabin Vincent 	dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
106*62579266SRabin Vincent 
107*62579266SRabin Vincent 	ret = ab8500->write(ab8500, addr, data);
108*62579266SRabin Vincent 	if (ret < 0)
109*62579266SRabin Vincent 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
110*62579266SRabin Vincent 			addr, ret);
111*62579266SRabin Vincent 
112*62579266SRabin Vincent 	return ret;
113*62579266SRabin Vincent }
114*62579266SRabin Vincent 
115*62579266SRabin Vincent /**
116*62579266SRabin Vincent  * ab8500_write() - write an AB8500 register
117*62579266SRabin Vincent  * @ab8500: device to write to
118*62579266SRabin Vincent  * @addr: address of the register
119*62579266SRabin Vincent  * @data: value to write
120*62579266SRabin Vincent  */
121*62579266SRabin Vincent int ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data)
122*62579266SRabin Vincent {
123*62579266SRabin Vincent 	int ret;
124*62579266SRabin Vincent 
125*62579266SRabin Vincent 	mutex_lock(&ab8500->lock);
126*62579266SRabin Vincent 	ret = __ab8500_write(ab8500, addr, data);
127*62579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
128*62579266SRabin Vincent 
129*62579266SRabin Vincent 	return ret;
130*62579266SRabin Vincent }
131*62579266SRabin Vincent EXPORT_SYMBOL_GPL(ab8500_write);
132*62579266SRabin Vincent 
133*62579266SRabin Vincent static int __ab8500_read(struct ab8500 *ab8500, u16 addr)
134*62579266SRabin Vincent {
135*62579266SRabin Vincent 	int ret;
136*62579266SRabin Vincent 
137*62579266SRabin Vincent 	ret = ab8500->read(ab8500, addr);
138*62579266SRabin Vincent 	if (ret < 0)
139*62579266SRabin Vincent 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
140*62579266SRabin Vincent 			addr, ret);
141*62579266SRabin Vincent 
142*62579266SRabin Vincent 	dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
143*62579266SRabin Vincent 
144*62579266SRabin Vincent 	return ret;
145*62579266SRabin Vincent }
146*62579266SRabin Vincent 
147*62579266SRabin Vincent /**
148*62579266SRabin Vincent  * ab8500_read() - read an AB8500 register
149*62579266SRabin Vincent  * @ab8500: device to read from
150*62579266SRabin Vincent  * @addr: address of the register
151*62579266SRabin Vincent  */
152*62579266SRabin Vincent int ab8500_read(struct ab8500 *ab8500, u16 addr)
153*62579266SRabin Vincent {
154*62579266SRabin Vincent 	int ret;
155*62579266SRabin Vincent 
156*62579266SRabin Vincent 	mutex_lock(&ab8500->lock);
157*62579266SRabin Vincent 	ret = __ab8500_read(ab8500, addr);
158*62579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
159*62579266SRabin Vincent 
160*62579266SRabin Vincent 	return ret;
161*62579266SRabin Vincent }
162*62579266SRabin Vincent EXPORT_SYMBOL_GPL(ab8500_read);
163*62579266SRabin Vincent 
164*62579266SRabin Vincent /**
165*62579266SRabin Vincent  * ab8500_set_bits() - set a bitfield in an AB8500 register
166*62579266SRabin Vincent  * @ab8500: device to read from
167*62579266SRabin Vincent  * @addr: address of the register
168*62579266SRabin Vincent  * @mask: mask of the bitfield to modify
169*62579266SRabin Vincent  * @data: value to set to the bitfield
170*62579266SRabin Vincent  */
171*62579266SRabin Vincent int ab8500_set_bits(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data)
172*62579266SRabin Vincent {
173*62579266SRabin Vincent 	int ret;
174*62579266SRabin Vincent 
175*62579266SRabin Vincent 	mutex_lock(&ab8500->lock);
176*62579266SRabin Vincent 
177*62579266SRabin Vincent 	ret = __ab8500_read(ab8500, addr);
178*62579266SRabin Vincent 	if (ret < 0)
179*62579266SRabin Vincent 		goto out;
180*62579266SRabin Vincent 
181*62579266SRabin Vincent 	ret &= ~mask;
182*62579266SRabin Vincent 	ret |= data;
183*62579266SRabin Vincent 
184*62579266SRabin Vincent 	ret = __ab8500_write(ab8500, addr, ret);
185*62579266SRabin Vincent 
186*62579266SRabin Vincent out:
187*62579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
188*62579266SRabin Vincent 	return ret;
189*62579266SRabin Vincent }
190*62579266SRabin Vincent EXPORT_SYMBOL_GPL(ab8500_set_bits);
191*62579266SRabin Vincent 
192*62579266SRabin Vincent static void ab8500_irq_lock(unsigned int irq)
193*62579266SRabin Vincent {
194*62579266SRabin Vincent 	struct ab8500 *ab8500 = get_irq_chip_data(irq);
195*62579266SRabin Vincent 
196*62579266SRabin Vincent 	mutex_lock(&ab8500->irq_lock);
197*62579266SRabin Vincent }
198*62579266SRabin Vincent 
199*62579266SRabin Vincent static void ab8500_irq_sync_unlock(unsigned int irq)
200*62579266SRabin Vincent {
201*62579266SRabin Vincent 	struct ab8500 *ab8500 = get_irq_chip_data(irq);
202*62579266SRabin Vincent 	int i;
203*62579266SRabin Vincent 
204*62579266SRabin Vincent 	for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
205*62579266SRabin Vincent 		u8 old = ab8500->oldmask[i];
206*62579266SRabin Vincent 		u8 new = ab8500->mask[i];
207*62579266SRabin Vincent 		int reg;
208*62579266SRabin Vincent 
209*62579266SRabin Vincent 		if (new == old)
210*62579266SRabin Vincent 			continue;
211*62579266SRabin Vincent 
212*62579266SRabin Vincent 		ab8500->oldmask[i] = new;
213*62579266SRabin Vincent 
214*62579266SRabin Vincent 		reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i];
215*62579266SRabin Vincent 		ab8500_write(ab8500, reg, new);
216*62579266SRabin Vincent 	}
217*62579266SRabin Vincent 
218*62579266SRabin Vincent 	mutex_unlock(&ab8500->irq_lock);
219*62579266SRabin Vincent }
220*62579266SRabin Vincent 
221*62579266SRabin Vincent static void ab8500_irq_mask(unsigned int irq)
222*62579266SRabin Vincent {
223*62579266SRabin Vincent 	struct ab8500 *ab8500 = get_irq_chip_data(irq);
224*62579266SRabin Vincent 	int offset = irq - ab8500->irq_base;
225*62579266SRabin Vincent 	int index = offset / 8;
226*62579266SRabin Vincent 	int mask = 1 << (offset % 8);
227*62579266SRabin Vincent 
228*62579266SRabin Vincent 	ab8500->mask[index] |= mask;
229*62579266SRabin Vincent }
230*62579266SRabin Vincent 
231*62579266SRabin Vincent static void ab8500_irq_unmask(unsigned int irq)
232*62579266SRabin Vincent {
233*62579266SRabin Vincent 	struct ab8500 *ab8500 = get_irq_chip_data(irq);
234*62579266SRabin Vincent 	int offset = irq - ab8500->irq_base;
235*62579266SRabin Vincent 	int index = offset / 8;
236*62579266SRabin Vincent 	int mask = 1 << (offset % 8);
237*62579266SRabin Vincent 
238*62579266SRabin Vincent 	ab8500->mask[index] &= ~mask;
239*62579266SRabin Vincent }
240*62579266SRabin Vincent 
241*62579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
242*62579266SRabin Vincent 	.name			= "ab8500",
243*62579266SRabin Vincent 	.bus_lock		= ab8500_irq_lock,
244*62579266SRabin Vincent 	.bus_sync_unlock	= ab8500_irq_sync_unlock,
245*62579266SRabin Vincent 	.mask			= ab8500_irq_mask,
246*62579266SRabin Vincent 	.unmask			= ab8500_irq_unmask,
247*62579266SRabin Vincent };
248*62579266SRabin Vincent 
249*62579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev)
250*62579266SRabin Vincent {
251*62579266SRabin Vincent 	struct ab8500 *ab8500 = dev;
252*62579266SRabin Vincent 	int i;
253*62579266SRabin Vincent 
254*62579266SRabin Vincent 	dev_vdbg(ab8500->dev, "interrupt\n");
255*62579266SRabin Vincent 
256*62579266SRabin Vincent 	for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
257*62579266SRabin Vincent 		int regoffset = ab8500_irq_regoffset[i];
258*62579266SRabin Vincent 		int status;
259*62579266SRabin Vincent 
260*62579266SRabin Vincent 		status = ab8500_read(ab8500, AB8500_IT_LATCH1_REG + regoffset);
261*62579266SRabin Vincent 		if (status <= 0)
262*62579266SRabin Vincent 			continue;
263*62579266SRabin Vincent 
264*62579266SRabin Vincent 		do {
265*62579266SRabin Vincent 			int bit = __ffs(status);
266*62579266SRabin Vincent 			int line = i * 8 + bit;
267*62579266SRabin Vincent 
268*62579266SRabin Vincent 			handle_nested_irq(ab8500->irq_base + line);
269*62579266SRabin Vincent 			status &= ~(1 << bit);
270*62579266SRabin Vincent 		} while (status);
271*62579266SRabin Vincent 	}
272*62579266SRabin Vincent 
273*62579266SRabin Vincent 	return IRQ_HANDLED;
274*62579266SRabin Vincent }
275*62579266SRabin Vincent 
276*62579266SRabin Vincent static int ab8500_irq_init(struct ab8500 *ab8500)
277*62579266SRabin Vincent {
278*62579266SRabin Vincent 	int base = ab8500->irq_base;
279*62579266SRabin Vincent 	int irq;
280*62579266SRabin Vincent 
281*62579266SRabin Vincent 	for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
282*62579266SRabin Vincent 		set_irq_chip_data(irq, ab8500);
283*62579266SRabin Vincent 		set_irq_chip_and_handler(irq, &ab8500_irq_chip,
284*62579266SRabin Vincent 					 handle_simple_irq);
285*62579266SRabin Vincent 		set_irq_nested_thread(irq, 1);
286*62579266SRabin Vincent #ifdef CONFIG_ARM
287*62579266SRabin Vincent 		set_irq_flags(irq, IRQF_VALID);
288*62579266SRabin Vincent #else
289*62579266SRabin Vincent 		set_irq_noprobe(irq);
290*62579266SRabin Vincent #endif
291*62579266SRabin Vincent 	}
292*62579266SRabin Vincent 
293*62579266SRabin Vincent 	return 0;
294*62579266SRabin Vincent }
295*62579266SRabin Vincent 
296*62579266SRabin Vincent static void ab8500_irq_remove(struct ab8500 *ab8500)
297*62579266SRabin Vincent {
298*62579266SRabin Vincent 	int base = ab8500->irq_base;
299*62579266SRabin Vincent 	int irq;
300*62579266SRabin Vincent 
301*62579266SRabin Vincent 	for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
302*62579266SRabin Vincent #ifdef CONFIG_ARM
303*62579266SRabin Vincent 		set_irq_flags(irq, 0);
304*62579266SRabin Vincent #endif
305*62579266SRabin Vincent 		set_irq_chip_and_handler(irq, NULL, NULL);
306*62579266SRabin Vincent 		set_irq_chip_data(irq, NULL);
307*62579266SRabin Vincent 	}
308*62579266SRabin Vincent }
309*62579266SRabin Vincent 
310*62579266SRabin Vincent static struct resource ab8500_gpadc_resources[] = {
311*62579266SRabin Vincent 	{
312*62579266SRabin Vincent 		.name	= "HW_CONV_END",
313*62579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
314*62579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
315*62579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
316*62579266SRabin Vincent 	},
317*62579266SRabin Vincent 	{
318*62579266SRabin Vincent 		.name	= "SW_CONV_END",
319*62579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
320*62579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
321*62579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
322*62579266SRabin Vincent 	},
323*62579266SRabin Vincent };
324*62579266SRabin Vincent 
325*62579266SRabin Vincent static struct resource ab8500_rtc_resources[] = {
326*62579266SRabin Vincent 	{
327*62579266SRabin Vincent 		.name	= "60S",
328*62579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
329*62579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
330*62579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
331*62579266SRabin Vincent 	},
332*62579266SRabin Vincent 	{
333*62579266SRabin Vincent 		.name	= "ALARM",
334*62579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
335*62579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
336*62579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
337*62579266SRabin Vincent 	},
338*62579266SRabin Vincent };
339*62579266SRabin Vincent 
340*62579266SRabin Vincent static struct mfd_cell ab8500_devs[] = {
341*62579266SRabin Vincent 	{
342*62579266SRabin Vincent 		.name = "ab8500-gpadc",
343*62579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
344*62579266SRabin Vincent 		.resources = ab8500_gpadc_resources,
345*62579266SRabin Vincent 	},
346*62579266SRabin Vincent 	{
347*62579266SRabin Vincent 		.name = "ab8500-rtc",
348*62579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
349*62579266SRabin Vincent 		.resources = ab8500_rtc_resources,
350*62579266SRabin Vincent 	},
351*62579266SRabin Vincent 	{ .name = "ab8500-charger", },
352*62579266SRabin Vincent 	{ .name = "ab8500-audio", },
353*62579266SRabin Vincent 	{ .name = "ab8500-usb", },
354*62579266SRabin Vincent 	{ .name = "ab8500-pwm", },
355*62579266SRabin Vincent };
356*62579266SRabin Vincent 
357*62579266SRabin Vincent int __devinit ab8500_init(struct ab8500 *ab8500)
358*62579266SRabin Vincent {
359*62579266SRabin Vincent 	struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
360*62579266SRabin Vincent 	int ret;
361*62579266SRabin Vincent 	int i;
362*62579266SRabin Vincent 
363*62579266SRabin Vincent 	if (plat)
364*62579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
365*62579266SRabin Vincent 
366*62579266SRabin Vincent 	mutex_init(&ab8500->lock);
367*62579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
368*62579266SRabin Vincent 
369*62579266SRabin Vincent 	ret = ab8500_read(ab8500, AB8500_REV_REG);
370*62579266SRabin Vincent 	if (ret < 0)
371*62579266SRabin Vincent 		return ret;
372*62579266SRabin Vincent 
373*62579266SRabin Vincent 	/*
374*62579266SRabin Vincent 	 * 0x0 - Early Drop
375*62579266SRabin Vincent 	 * 0x10 - Cut 1.0
376*62579266SRabin Vincent 	 * 0x11 - Cut 1.1
377*62579266SRabin Vincent 	 */
378*62579266SRabin Vincent 	if (ret == 0x0 || ret == 0x10 || ret == 0x11) {
379*62579266SRabin Vincent 		ab8500->revision = ret;
380*62579266SRabin Vincent 		dev_info(ab8500->dev, "detected chip, revision: %#x\n", ret);
381*62579266SRabin Vincent 	} else {
382*62579266SRabin Vincent 		dev_err(ab8500->dev, "unknown chip, revision: %#x\n", ret);
383*62579266SRabin Vincent 		return -EINVAL;
384*62579266SRabin Vincent 	}
385*62579266SRabin Vincent 
386*62579266SRabin Vincent 	if (plat && plat->init)
387*62579266SRabin Vincent 		plat->init(ab8500);
388*62579266SRabin Vincent 
389*62579266SRabin Vincent 	/* Clear and mask all interrupts */
390*62579266SRabin Vincent 	for (i = 0; i < 10; i++) {
391*62579266SRabin Vincent 		ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i);
392*62579266SRabin Vincent 		ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff);
393*62579266SRabin Vincent 	}
394*62579266SRabin Vincent 
395*62579266SRabin Vincent 	for (i = 18; i < 24; i++) {
396*62579266SRabin Vincent 		ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i);
397*62579266SRabin Vincent 		ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff);
398*62579266SRabin Vincent 	}
399*62579266SRabin Vincent 
400*62579266SRabin Vincent 	for (i = 0; i < AB8500_NUM_IRQ_REGS; i++)
401*62579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
402*62579266SRabin Vincent 
403*62579266SRabin Vincent 	if (ab8500->irq_base) {
404*62579266SRabin Vincent 		ret = ab8500_irq_init(ab8500);
405*62579266SRabin Vincent 		if (ret)
406*62579266SRabin Vincent 			return ret;
407*62579266SRabin Vincent 
408*62579266SRabin Vincent 		ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq,
409*62579266SRabin Vincent 					   IRQF_ONESHOT, "ab8500", ab8500);
410*62579266SRabin Vincent 		if (ret)
411*62579266SRabin Vincent 			goto out_removeirq;
412*62579266SRabin Vincent 	}
413*62579266SRabin Vincent 
414*62579266SRabin Vincent 	ret = mfd_add_devices(ab8500->dev, -1, ab8500_devs,
415*62579266SRabin Vincent 			      ARRAY_SIZE(ab8500_devs), NULL,
416*62579266SRabin Vincent 			      ab8500->irq_base);
417*62579266SRabin Vincent 	if (ret)
418*62579266SRabin Vincent 		goto out_freeirq;
419*62579266SRabin Vincent 
420*62579266SRabin Vincent 	return ret;
421*62579266SRabin Vincent 
422*62579266SRabin Vincent out_freeirq:
423*62579266SRabin Vincent 	if (ab8500->irq_base) {
424*62579266SRabin Vincent 		free_irq(ab8500->irq, ab8500);
425*62579266SRabin Vincent out_removeirq:
426*62579266SRabin Vincent 		ab8500_irq_remove(ab8500);
427*62579266SRabin Vincent 	}
428*62579266SRabin Vincent 	return ret;
429*62579266SRabin Vincent }
430*62579266SRabin Vincent 
431*62579266SRabin Vincent int __devexit ab8500_exit(struct ab8500 *ab8500)
432*62579266SRabin Vincent {
433*62579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
434*62579266SRabin Vincent 	if (ab8500->irq_base) {
435*62579266SRabin Vincent 		free_irq(ab8500->irq, ab8500);
436*62579266SRabin Vincent 		ab8500_irq_remove(ab8500);
437*62579266SRabin Vincent 	}
438*62579266SRabin Vincent 
439*62579266SRabin Vincent 	return 0;
440*62579266SRabin Vincent }
441*62579266SRabin Vincent 
442*62579266SRabin Vincent MODULE_AUTHOR("Srinidhi Kasagar, Rabin Vincent");
443*62579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
444*62579266SRabin Vincent MODULE_LICENSE("GPL v2");
445