xref: /openbmc/linux/drivers/mfd/88pm860x-core.c (revision a6ccdcd9)
1 /*
2  * Base driver for Marvell 88PM8607
3  *
4  * Copyright (C) 2009 Marvell International Ltd.
5  * 	Haojian Zhuang <haojian.zhuang@marvell.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/i2c.h>
15 #include <linux/irq.h>
16 #include <linux/interrupt.h>
17 #include <linux/platform_device.h>
18 #include <linux/mfd/core.h>
19 #include <linux/mfd/88pm860x.h>
20 #include <linux/regulator/machine.h>
21 
22 #define INT_STATUS_NUM			3
23 
24 static struct resource bk0_resources[] __devinitdata = {
25 	{2, 2, "duty cycle", IORESOURCE_REG, },
26 	{3, 3, "always on",  IORESOURCE_REG, },
27 	{3, 3, "current",    IORESOURCE_REG, },
28 };
29 static struct resource bk1_resources[] __devinitdata = {
30 	{4, 4, "duty cycle", IORESOURCE_REG, },
31 	{5, 5, "always on",  IORESOURCE_REG, },
32 	{5, 5, "current",    IORESOURCE_REG, },
33 };
34 static struct resource bk2_resources[] __devinitdata = {
35 	{6, 6, "duty cycle", IORESOURCE_REG, },
36 	{7, 7, "always on",  IORESOURCE_REG, },
37 	{5, 5, "current",    IORESOURCE_REG, },
38 };
39 
40 static struct resource led_resources[] __devinitdata = {
41 	{PM8606_LED1_RED,   PM8606_LED1_RED,   "led0-red",   IORESOURCE_REG,},
42 	{PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_REG,},
43 	{PM8606_LED1_BLUE,  PM8606_LED1_BLUE,  "led0-blue",  IORESOURCE_REG,},
44 	{PM8606_LED2_RED,   PM8606_LED2_RED,   "led1-red",   IORESOURCE_REG,},
45 	{PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_REG,},
46 	{PM8606_LED2_BLUE,  PM8606_LED2_BLUE,  "led1-blue",  IORESOURCE_REG,},
47 };
48 
49 static struct resource regulator_resources[] __devinitdata = {
50 	{PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_REG,},
51 	{PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_REG,},
52 	{PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_REG,},
53 	{PM8607_ID_LDO1,  PM8607_ID_LDO1,  "ldo-01", IORESOURCE_REG,},
54 	{PM8607_ID_LDO2,  PM8607_ID_LDO2,  "ldo-02", IORESOURCE_REG,},
55 	{PM8607_ID_LDO3,  PM8607_ID_LDO3,  "ldo-03", IORESOURCE_REG,},
56 	{PM8607_ID_LDO4,  PM8607_ID_LDO4,  "ldo-04", IORESOURCE_REG,},
57 	{PM8607_ID_LDO5,  PM8607_ID_LDO5,  "ldo-05", IORESOURCE_REG,},
58 	{PM8607_ID_LDO6,  PM8607_ID_LDO6,  "ldo-06", IORESOURCE_REG,},
59 	{PM8607_ID_LDO7,  PM8607_ID_LDO7,  "ldo-07", IORESOURCE_REG,},
60 	{PM8607_ID_LDO8,  PM8607_ID_LDO8,  "ldo-08", IORESOURCE_REG,},
61 	{PM8607_ID_LDO9,  PM8607_ID_LDO9,  "ldo-09", IORESOURCE_REG,},
62 	{PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_REG,},
63 	{PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_REG,},
64 	{PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_REG,},
65 	{PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_REG,},
66 	{PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_REG,},
67 	{PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_REG,},
68 };
69 
70 static struct resource touch_resources[] __devinitdata = {
71 	{PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,},
72 };
73 
74 static struct resource onkey_resources[] __devinitdata = {
75 	{PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,},
76 };
77 
78 static struct resource codec_resources[] __devinitdata = {
79 	/* Headset microphone insertion or removal */
80 	{PM8607_IRQ_MICIN,   PM8607_IRQ_MICIN,   "micin",   IORESOURCE_IRQ,},
81 	/* Hook-switch press or release */
82 	{PM8607_IRQ_HOOK,    PM8607_IRQ_HOOK,    "hook",    IORESOURCE_IRQ,},
83 	/* Headset insertion or removal */
84 	{PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,},
85 	/* Audio short */
86 	{PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
87 };
88 
89 static struct resource battery_resources[] __devinitdata = {
90 	{PM8607_IRQ_CC,  PM8607_IRQ_CC,  "columb counter", IORESOURCE_IRQ,},
91 	{PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery",        IORESOURCE_IRQ,},
92 };
93 
94 static struct resource charger_resources[] __devinitdata = {
95 	{PM8607_IRQ_CHG,  PM8607_IRQ_CHG,  "charger detect",  IORESOURCE_IRQ,},
96 	{PM8607_IRQ_CHG_DONE,  PM8607_IRQ_CHG_DONE,  "charging done",       IORESOURCE_IRQ,},
97 	{PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout",    IORESOURCE_IRQ,},
98 	{PM8607_IRQ_GPADC1,    PM8607_IRQ_GPADC1,    "battery temperature", IORESOURCE_IRQ,},
99 	{PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,},
100 	{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage",    IORESOURCE_IRQ,},
101 };
102 
103 static struct resource preg_resources[] __devinitdata = {
104 	{PM8606_ID_PREG,  PM8606_ID_PREG,  "preg",   IORESOURCE_REG,},
105 };
106 
107 static struct resource rtc_resources[] __devinitdata = {
108 	{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
109 };
110 
111 static struct mfd_cell bk_devs[] = {
112 	{
113 		.name = "88pm860x-backlight",
114 		.id = 0,
115 		.num_resources = ARRAY_SIZE(bk0_resources),
116 		.resources = bk0_resources,
117 	}, {
118 		.name = "88pm860x-backlight",
119 		.id = 1,
120 		.num_resources = ARRAY_SIZE(bk1_resources),
121 		.resources = bk1_resources,
122 	}, {
123 		.name = "88pm860x-backlight",
124 		.id = 2,
125 		.num_resources = ARRAY_SIZE(bk2_resources),
126 		.resources = bk2_resources,
127 	},
128 };
129 
130 static struct mfd_cell led_devs[] = {
131 	{"88pm860x-led", 0,},
132 	{"88pm860x-led", 1,},
133 	{"88pm860x-led", 2,},
134 	{"88pm860x-led", 3,},
135 	{"88pm860x-led", 4,},
136 	{"88pm860x-led", 5,},
137 };
138 
139 static struct mfd_cell regulator_devs[] = {
140 	{"88pm860x-regulator", 0,},
141 	{"88pm860x-regulator", 1,},
142 	{"88pm860x-regulator", 2,},
143 	{"88pm860x-regulator", 3,},
144 	{"88pm860x-regulator", 4,},
145 	{"88pm860x-regulator", 5,},
146 	{"88pm860x-regulator", 6,},
147 	{"88pm860x-regulator", 7,},
148 	{"88pm860x-regulator", 8,},
149 	{"88pm860x-regulator", 9,},
150 	{"88pm860x-regulator", 10,},
151 	{"88pm860x-regulator", 11,},
152 	{"88pm860x-regulator", 12,},
153 	{"88pm860x-regulator", 13,},
154 	{"88pm860x-regulator", 14,},
155 	{"88pm860x-regulator", 15,},
156 	{"88pm860x-regulator", 16,},
157 	{"88pm860x-regulator", 17,},
158 };
159 
160 static struct mfd_cell touch_devs[] = {
161 	{"88pm860x-touch", -1,},
162 };
163 
164 static struct mfd_cell onkey_devs[] = {
165 	{"88pm860x-onkey", -1,},
166 };
167 
168 static struct mfd_cell codec_devs[] = {
169 	{"88pm860x-codec", -1,},
170 };
171 
172 static struct regulator_consumer_supply preg_supply[] = {
173 	REGULATOR_SUPPLY("preg", "charger-manager"),
174 };
175 
176 static struct regulator_init_data preg_init_data = {
177 	.num_consumer_supplies	= ARRAY_SIZE(preg_supply),
178 	.consumer_supplies	= &preg_supply[0],
179 };
180 
181 static struct mfd_cell power_devs[] = {
182 	{"88pm860x-battery", -1,},
183 	{"88pm860x-charger", -1,},
184 	{"88pm860x-preg",    -1,},
185 };
186 
187 static struct mfd_cell rtc_devs[] = {
188 	{"88pm860x-rtc", -1,},
189 };
190 
191 
192 struct pm860x_irq_data {
193 	int	reg;
194 	int	mask_reg;
195 	int	enable;		/* enable or not */
196 	int	offs;		/* bit offset in mask register */
197 };
198 
199 static struct pm860x_irq_data pm860x_irqs[] = {
200 	[PM8607_IRQ_ONKEY] = {
201 		.reg		= PM8607_INT_STATUS1,
202 		.mask_reg	= PM8607_INT_MASK_1,
203 		.offs		= 1 << 0,
204 	},
205 	[PM8607_IRQ_EXTON] = {
206 		.reg		= PM8607_INT_STATUS1,
207 		.mask_reg	= PM8607_INT_MASK_1,
208 		.offs		= 1 << 1,
209 	},
210 	[PM8607_IRQ_CHG] = {
211 		.reg		= PM8607_INT_STATUS1,
212 		.mask_reg	= PM8607_INT_MASK_1,
213 		.offs		= 1 << 2,
214 	},
215 	[PM8607_IRQ_BAT] = {
216 		.reg		= PM8607_INT_STATUS1,
217 		.mask_reg	= PM8607_INT_MASK_1,
218 		.offs		= 1 << 3,
219 	},
220 	[PM8607_IRQ_RTC] = {
221 		.reg		= PM8607_INT_STATUS1,
222 		.mask_reg	= PM8607_INT_MASK_1,
223 		.offs		= 1 << 4,
224 	},
225 	[PM8607_IRQ_CC] = {
226 		.reg		= PM8607_INT_STATUS1,
227 		.mask_reg	= PM8607_INT_MASK_1,
228 		.offs		= 1 << 5,
229 	},
230 	[PM8607_IRQ_VBAT] = {
231 		.reg		= PM8607_INT_STATUS2,
232 		.mask_reg	= PM8607_INT_MASK_2,
233 		.offs		= 1 << 0,
234 	},
235 	[PM8607_IRQ_VCHG] = {
236 		.reg		= PM8607_INT_STATUS2,
237 		.mask_reg	= PM8607_INT_MASK_2,
238 		.offs		= 1 << 1,
239 	},
240 	[PM8607_IRQ_VSYS] = {
241 		.reg		= PM8607_INT_STATUS2,
242 		.mask_reg	= PM8607_INT_MASK_2,
243 		.offs		= 1 << 2,
244 	},
245 	[PM8607_IRQ_TINT] = {
246 		.reg		= PM8607_INT_STATUS2,
247 		.mask_reg	= PM8607_INT_MASK_2,
248 		.offs		= 1 << 3,
249 	},
250 	[PM8607_IRQ_GPADC0] = {
251 		.reg		= PM8607_INT_STATUS2,
252 		.mask_reg	= PM8607_INT_MASK_2,
253 		.offs		= 1 << 4,
254 	},
255 	[PM8607_IRQ_GPADC1] = {
256 		.reg		= PM8607_INT_STATUS2,
257 		.mask_reg	= PM8607_INT_MASK_2,
258 		.offs		= 1 << 5,
259 	},
260 	[PM8607_IRQ_GPADC2] = {
261 		.reg		= PM8607_INT_STATUS2,
262 		.mask_reg	= PM8607_INT_MASK_2,
263 		.offs		= 1 << 6,
264 	},
265 	[PM8607_IRQ_GPADC3] = {
266 		.reg		= PM8607_INT_STATUS2,
267 		.mask_reg	= PM8607_INT_MASK_2,
268 		.offs		= 1 << 7,
269 	},
270 	[PM8607_IRQ_AUDIO_SHORT] = {
271 		.reg		= PM8607_INT_STATUS3,
272 		.mask_reg	= PM8607_INT_MASK_3,
273 		.offs		= 1 << 0,
274 	},
275 	[PM8607_IRQ_PEN] = {
276 		.reg		= PM8607_INT_STATUS3,
277 		.mask_reg	= PM8607_INT_MASK_3,
278 		.offs		= 1 << 1,
279 	},
280 	[PM8607_IRQ_HEADSET] = {
281 		.reg		= PM8607_INT_STATUS3,
282 		.mask_reg	= PM8607_INT_MASK_3,
283 		.offs		= 1 << 2,
284 	},
285 	[PM8607_IRQ_HOOK] = {
286 		.reg		= PM8607_INT_STATUS3,
287 		.mask_reg	= PM8607_INT_MASK_3,
288 		.offs		= 1 << 3,
289 	},
290 	[PM8607_IRQ_MICIN] = {
291 		.reg		= PM8607_INT_STATUS3,
292 		.mask_reg	= PM8607_INT_MASK_3,
293 		.offs		= 1 << 4,
294 	},
295 	[PM8607_IRQ_CHG_FAIL] = {
296 		.reg		= PM8607_INT_STATUS3,
297 		.mask_reg	= PM8607_INT_MASK_3,
298 		.offs		= 1 << 5,
299 	},
300 	[PM8607_IRQ_CHG_DONE] = {
301 		.reg		= PM8607_INT_STATUS3,
302 		.mask_reg	= PM8607_INT_MASK_3,
303 		.offs		= 1 << 6,
304 	},
305 	[PM8607_IRQ_CHG_FAULT] = {
306 		.reg		= PM8607_INT_STATUS3,
307 		.mask_reg	= PM8607_INT_MASK_3,
308 		.offs		= 1 << 7,
309 	},
310 };
311 
312 static irqreturn_t pm860x_irq(int irq, void *data)
313 {
314 	struct pm860x_chip *chip = data;
315 	struct pm860x_irq_data *irq_data;
316 	struct i2c_client *i2c;
317 	int read_reg = -1, value = 0;
318 	int i;
319 
320 	i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
321 	for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
322 		irq_data = &pm860x_irqs[i];
323 		if (read_reg != irq_data->reg) {
324 			read_reg = irq_data->reg;
325 			value = pm860x_reg_read(i2c, irq_data->reg);
326 		}
327 		if (value & irq_data->enable)
328 			handle_nested_irq(chip->irq_base + i);
329 	}
330 	return IRQ_HANDLED;
331 }
332 
333 static void pm860x_irq_lock(struct irq_data *data)
334 {
335 	struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
336 
337 	mutex_lock(&chip->irq_lock);
338 }
339 
340 static void pm860x_irq_sync_unlock(struct irq_data *data)
341 {
342 	struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
343 	struct pm860x_irq_data *irq_data;
344 	struct i2c_client *i2c;
345 	static unsigned char cached[3] = {0x0, 0x0, 0x0};
346 	unsigned char mask[3];
347 	int i;
348 
349 	i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
350 	/* Load cached value. In initial, all IRQs are masked */
351 	for (i = 0; i < 3; i++)
352 		mask[i] = cached[i];
353 	for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
354 		irq_data = &pm860x_irqs[i];
355 		switch (irq_data->mask_reg) {
356 		case PM8607_INT_MASK_1:
357 			mask[0] &= ~irq_data->offs;
358 			mask[0] |= irq_data->enable;
359 			break;
360 		case PM8607_INT_MASK_2:
361 			mask[1] &= ~irq_data->offs;
362 			mask[1] |= irq_data->enable;
363 			break;
364 		case PM8607_INT_MASK_3:
365 			mask[2] &= ~irq_data->offs;
366 			mask[2] |= irq_data->enable;
367 			break;
368 		default:
369 			dev_err(chip->dev, "wrong IRQ\n");
370 			break;
371 		}
372 	}
373 	/* update mask into registers */
374 	for (i = 0; i < 3; i++) {
375 		if (mask[i] != cached[i]) {
376 			cached[i] = mask[i];
377 			pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]);
378 		}
379 	}
380 
381 	mutex_unlock(&chip->irq_lock);
382 }
383 
384 static void pm860x_irq_enable(struct irq_data *data)
385 {
386 	struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
387 	pm860x_irqs[data->irq - chip->irq_base].enable
388 		= pm860x_irqs[data->irq - chip->irq_base].offs;
389 }
390 
391 static void pm860x_irq_disable(struct irq_data *data)
392 {
393 	struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
394 	pm860x_irqs[data->irq - chip->irq_base].enable = 0;
395 }
396 
397 static struct irq_chip pm860x_irq_chip = {
398 	.name		= "88pm860x",
399 	.irq_bus_lock	= pm860x_irq_lock,
400 	.irq_bus_sync_unlock = pm860x_irq_sync_unlock,
401 	.irq_enable	= pm860x_irq_enable,
402 	.irq_disable	= pm860x_irq_disable,
403 };
404 
405 static int __devinit device_gpadc_init(struct pm860x_chip *chip,
406 				       struct pm860x_platform_data *pdata)
407 {
408 	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
409 				: chip->companion;
410 	int data;
411 	int ret;
412 
413 	/* initialize GPADC without activating it */
414 
415 	if (!pdata || !pdata->touch)
416 		return -EINVAL;
417 
418 	/* set GPADC MISC1 register */
419 	data = 0;
420 	data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK;
421 	data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK;
422 	data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK;
423 	data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK;
424 	if (data) {
425 		ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
426 		if (ret < 0)
427 			goto out;
428 	}
429 	/* set tsi prebias time */
430 	if (pdata->touch->tsi_prebias) {
431 		data = pdata->touch->tsi_prebias;
432 		ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
433 		if (ret < 0)
434 			goto out;
435 	}
436 	/* set prebias & prechg time of pen detect */
437 	data = 0;
438 	data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK;
439 	data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK;
440 	if (data) {
441 		ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
442 		if (ret < 0)
443 			goto out;
444 	}
445 
446 	ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1,
447 			      PM8607_GPADC_EN, PM8607_GPADC_EN);
448 out:
449 	return ret;
450 }
451 
452 static int __devinit device_irq_init(struct pm860x_chip *chip,
453 				     struct pm860x_platform_data *pdata)
454 {
455 	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
456 				: chip->companion;
457 	unsigned char status_buf[INT_STATUS_NUM];
458 	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
459 	int i, data, mask, ret = -EINVAL;
460 	int __irq;
461 
462 	if (!pdata || !pdata->irq_base) {
463 		dev_warn(chip->dev, "No interrupt support on IRQ base\n");
464 		return -EINVAL;
465 	}
466 
467 	mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
468 		| PM8607_B0_MISC1_INT_MASK;
469 	data = 0;
470 	chip->irq_mode = 0;
471 	if (pdata && pdata->irq_mode) {
472 		/*
473 		 * irq_mode defines the way of clearing interrupt. If it's 1,
474 		 * clear IRQ by write. Otherwise, clear it by read.
475 		 * This control bit is valid from 88PM8607 B0 steping.
476 		 */
477 		data |= PM8607_B0_MISC1_INT_CLEAR;
478 		chip->irq_mode = 1;
479 	}
480 	ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, mask, data);
481 	if (ret < 0)
482 		goto out;
483 
484 	/* mask all IRQs */
485 	memset(status_buf, 0, INT_STATUS_NUM);
486 	ret = pm860x_bulk_write(i2c, PM8607_INT_MASK_1,
487 				INT_STATUS_NUM, status_buf);
488 	if (ret < 0)
489 		goto out;
490 
491 	if (chip->irq_mode) {
492 		/* clear interrupt status by write */
493 		memset(status_buf, 0xFF, INT_STATUS_NUM);
494 		ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1,
495 					INT_STATUS_NUM, status_buf);
496 	} else {
497 		/* clear interrupt status by read */
498 		ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1,
499 					INT_STATUS_NUM, status_buf);
500 	}
501 	if (ret < 0)
502 		goto out;
503 
504 	mutex_init(&chip->irq_lock);
505 	chip->irq_base = pdata->irq_base;
506 	chip->core_irq = i2c->irq;
507 	if (!chip->core_irq)
508 		goto out;
509 
510 	/* register IRQ by genirq */
511 	for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
512 		__irq = i + chip->irq_base;
513 		irq_set_chip_data(__irq, chip);
514 		irq_set_chip_and_handler(__irq, &pm860x_irq_chip,
515 					 handle_edge_irq);
516 		irq_set_nested_thread(__irq, 1);
517 #ifdef CONFIG_ARM
518 		set_irq_flags(__irq, IRQF_VALID);
519 #else
520 		irq_set_noprobe(__irq);
521 #endif
522 	}
523 
524 	ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags,
525 				   "88pm860x", chip);
526 	if (ret) {
527 		dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
528 		chip->core_irq = 0;
529 	}
530 
531 	return 0;
532 out:
533 	chip->core_irq = 0;
534 	return ret;
535 }
536 
537 static void device_irq_exit(struct pm860x_chip *chip)
538 {
539 	if (chip->core_irq)
540 		free_irq(chip->core_irq, chip);
541 }
542 
543 int pm8606_osc_enable(struct pm860x_chip *chip, unsigned short client)
544 {
545 	int ret = -EIO;
546 	struct i2c_client *i2c = (chip->id == CHIP_PM8606) ?
547 		chip->client : chip->companion;
548 
549 	dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client);
550 	dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n",
551 			__func__, chip->osc_vote,
552 			chip->osc_status);
553 
554 	mutex_lock(&chip->osc_lock);
555 	/* Update voting status */
556 	chip->osc_vote |= client;
557 	/* If reference group is off - turn on*/
558 	if (chip->osc_status != PM8606_REF_GP_OSC_ON) {
559 		chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
560 		/* Enable Reference group Vsys */
561 		if (pm860x_set_bits(i2c, PM8606_VSYS,
562 				PM8606_VSYS_EN, PM8606_VSYS_EN))
563 			goto out;
564 
565 		/*Enable Internal Oscillator */
566 		if (pm860x_set_bits(i2c, PM8606_MISC,
567 				PM8606_MISC_OSC_EN, PM8606_MISC_OSC_EN))
568 			goto out;
569 		/* Update status (only if writes succeed) */
570 		chip->osc_status = PM8606_REF_GP_OSC_ON;
571 	}
572 	mutex_unlock(&chip->osc_lock);
573 
574 	dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n",
575 			__func__, chip->osc_vote,
576 			chip->osc_status, ret);
577 	return 0;
578 out:
579 	mutex_unlock(&chip->osc_lock);
580 	return ret;
581 }
582 EXPORT_SYMBOL(pm8606_osc_enable);
583 
584 int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client)
585 {
586 	int ret = -EIO;
587 	struct i2c_client *i2c = (chip->id == CHIP_PM8606) ?
588 		chip->client : chip->companion;
589 
590 	dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client);
591 	dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n",
592 			__func__, chip->osc_vote,
593 			chip->osc_status);
594 
595 	mutex_lock(&chip->osc_lock);
596 	/*Update voting status */
597 	chip->osc_vote &= ~(client);
598 	/* If reference group is off and this is the last client to release
599 	 * - turn off */
600 	if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) &&
601 			(chip->osc_vote == REF_GP_NO_CLIENTS)) {
602 		chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
603 		/* Disable Reference group Vsys */
604 		if (pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0))
605 			goto out;
606 		/* Disable Internal Oscillator */
607 		if (pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0))
608 			goto out;
609 		chip->osc_status = PM8606_REF_GP_OSC_OFF;
610 	}
611 	mutex_unlock(&chip->osc_lock);
612 
613 	dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n",
614 			__func__, chip->osc_vote,
615 			chip->osc_status, ret);
616 	return 0;
617 out:
618 	mutex_unlock(&chip->osc_lock);
619 	return ret;
620 }
621 EXPORT_SYMBOL(pm8606_osc_disable);
622 
623 static void __devinit device_osc_init(struct i2c_client *i2c)
624 {
625 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
626 
627 	mutex_init(&chip->osc_lock);
628 	/* init portofino reference group voting and status */
629 	/* Disable Reference group Vsys */
630 	pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0);
631 	/* Disable Internal Oscillator */
632 	pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0);
633 
634 	chip->osc_vote = REF_GP_NO_CLIENTS;
635 	chip->osc_status = PM8606_REF_GP_OSC_OFF;
636 }
637 
638 static void __devinit device_bk_init(struct pm860x_chip *chip,
639 				     struct pm860x_platform_data *pdata)
640 {
641 	int ret, i;
642 
643 	if (pdata && pdata->backlight) {
644 		if (pdata->num_backlights > ARRAY_SIZE(bk_devs))
645 			pdata->num_backlights = ARRAY_SIZE(bk_devs);
646 		for (i = 0; i < pdata->num_backlights; i++) {
647 			bk_devs[i].platform_data = &pdata->backlight[i];
648 			bk_devs[i].pdata_size =
649 				sizeof(struct pm860x_backlight_pdata);
650 		}
651 	}
652 	ret = mfd_add_devices(chip->dev, 0, bk_devs,
653 			      ARRAY_SIZE(bk_devs), NULL, 0);
654 	if (ret < 0)
655 		dev_err(chip->dev, "Failed to add backlight subdev\n");
656 }
657 
658 static void __devinit device_led_init(struct pm860x_chip *chip,
659 				      struct pm860x_platform_data *pdata)
660 {
661 	int ret;
662 	int i, j, id;
663 
664 	if ((pdata == NULL) || (pdata->led == NULL))
665 		return;
666 
667 	if (pdata->num_leds > ARRAY_SIZE(led_devs))
668 		pdata->num_leds = ARRAY_SIZE(led_devs);
669 
670 	for (i = 0; i < pdata->num_leds; i++) {
671 		led_devs[i].platform_data = &pdata->led[i];
672 		led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata);
673 
674 		for (j = 0; j < ARRAY_SIZE(led_devs); j++) {
675 			id = led_resources[j].start;
676 			if (pdata->led[i].flags != id)
677 				continue;
678 
679 			led_devs[i].num_resources = 1;
680 			led_devs[i].resources = &led_resources[j],
681 			ret = mfd_add_devices(chip->dev, 0,
682 					      &led_devs[i], 1,
683 					      &led_resources[j], 0);
684 			if (ret < 0) {
685 				dev_err(chip->dev, "Failed to add "
686 					"led subdev\n");
687 				return;
688 			}
689 		}
690 	}
691 }
692 
693 static void __devinit device_regulator_init(struct pm860x_chip *chip,
694 					    struct pm860x_platform_data *pdata)
695 {
696 	struct regulator_init_data *initdata;
697 	int ret;
698 	int i, seq;
699 
700 	if ((pdata == NULL) || (pdata->regulator == NULL))
701 		return;
702 
703 	if (pdata->num_regulators > ARRAY_SIZE(regulator_devs))
704 		pdata->num_regulators = ARRAY_SIZE(regulator_devs);
705 
706 	for (i = 0, seq = -1; i < pdata->num_regulators; i++) {
707 		initdata = &pdata->regulator[i];
708 		seq = *(unsigned int *)initdata->driver_data;
709 		if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) {
710 			dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n",
711 				seq, initdata->constraints.name);
712 			goto out;
713 		}
714 		regulator_devs[i].platform_data = &pdata->regulator[i];
715 		regulator_devs[i].pdata_size = sizeof(struct regulator_init_data);
716 		regulator_devs[i].num_resources = 1;
717 		regulator_devs[i].resources = &regulator_resources[seq];
718 
719 		ret = mfd_add_devices(chip->dev, 0, &regulator_devs[i], 1,
720 				      &regulator_resources[seq], 0);
721 		if (ret < 0) {
722 			dev_err(chip->dev, "Failed to add regulator subdev\n");
723 			goto out;
724 		}
725 	}
726 out:
727 	return;
728 }
729 
730 static void __devinit device_rtc_init(struct pm860x_chip *chip,
731 				      struct pm860x_platform_data *pdata)
732 {
733 	int ret;
734 
735 	if ((pdata == NULL))
736 		return;
737 
738 	rtc_devs[0].platform_data = pdata->rtc;
739 	rtc_devs[0].pdata_size = sizeof(struct pm860x_rtc_pdata);
740 	rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources);
741 	rtc_devs[0].resources = &rtc_resources[0];
742 	ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
743 			      ARRAY_SIZE(rtc_devs), &rtc_resources[0],
744 			      chip->irq_base);
745 	if (ret < 0)
746 		dev_err(chip->dev, "Failed to add rtc subdev\n");
747 }
748 
749 static void __devinit device_touch_init(struct pm860x_chip *chip,
750 					struct pm860x_platform_data *pdata)
751 {
752 	int ret;
753 
754 	if (pdata == NULL)
755 		return;
756 
757 	touch_devs[0].platform_data = pdata->touch;
758 	touch_devs[0].pdata_size = sizeof(struct pm860x_touch_pdata);
759 	touch_devs[0].num_resources = ARRAY_SIZE(touch_resources);
760 	touch_devs[0].resources = &touch_resources[0];
761 	ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
762 			      ARRAY_SIZE(touch_devs), &touch_resources[0],
763 			      chip->irq_base);
764 	if (ret < 0)
765 		dev_err(chip->dev, "Failed to add touch subdev\n");
766 }
767 
768 static void __devinit device_power_init(struct pm860x_chip *chip,
769 					struct pm860x_platform_data *pdata)
770 {
771 	int ret;
772 
773 	if (pdata == NULL)
774 		return;
775 
776 	power_devs[0].platform_data = pdata->power;
777 	power_devs[0].pdata_size = sizeof(struct pm860x_power_pdata);
778 	power_devs[0].num_resources = ARRAY_SIZE(battery_resources);
779 	power_devs[0].resources = &battery_resources[0],
780 	ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1,
781 			      &battery_resources[0], chip->irq_base);
782 	if (ret < 0)
783 		dev_err(chip->dev, "Failed to add battery subdev\n");
784 
785 	power_devs[1].platform_data = pdata->power;
786 	power_devs[1].pdata_size = sizeof(struct pm860x_power_pdata);
787 	power_devs[1].num_resources = ARRAY_SIZE(charger_resources);
788 	power_devs[1].resources = &charger_resources[0],
789 	ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1,
790 			      &charger_resources[0], chip->irq_base);
791 	if (ret < 0)
792 		dev_err(chip->dev, "Failed to add charger subdev\n");
793 
794 	power_devs[2].platform_data = &preg_init_data;
795 	power_devs[2].pdata_size = sizeof(struct regulator_init_data);
796 	power_devs[2].num_resources = ARRAY_SIZE(preg_resources);
797 	power_devs[2].resources = &preg_resources[0],
798 	ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1,
799 			      &preg_resources[0], chip->irq_base);
800 	if (ret < 0)
801 		dev_err(chip->dev, "Failed to add preg subdev\n");
802 }
803 
804 static void __devinit device_onkey_init(struct pm860x_chip *chip,
805 					struct pm860x_platform_data *pdata)
806 {
807 	int ret;
808 
809 	onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources);
810 	onkey_devs[0].resources = &onkey_resources[0],
811 	ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
812 			      ARRAY_SIZE(onkey_devs), &onkey_resources[0],
813 			      chip->irq_base);
814 	if (ret < 0)
815 		dev_err(chip->dev, "Failed to add onkey subdev\n");
816 }
817 
818 static void __devinit device_codec_init(struct pm860x_chip *chip,
819 					struct pm860x_platform_data *pdata)
820 {
821 	int ret;
822 
823 	codec_devs[0].num_resources = ARRAY_SIZE(codec_resources);
824 	codec_devs[0].resources = &codec_resources[0],
825 	ret = mfd_add_devices(chip->dev, 0, &codec_devs[0],
826 			      ARRAY_SIZE(codec_devs), &codec_resources[0], 0);
827 	if (ret < 0)
828 		dev_err(chip->dev, "Failed to add codec subdev\n");
829 }
830 
831 static void __devinit device_8607_init(struct pm860x_chip *chip,
832 				       struct i2c_client *i2c,
833 				       struct pm860x_platform_data *pdata)
834 {
835 	int data, ret;
836 
837 	ret = pm860x_reg_read(i2c, PM8607_CHIP_ID);
838 	if (ret < 0) {
839 		dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
840 		goto out;
841 	}
842 	switch (ret & PM8607_VERSION_MASK) {
843 	case 0x40:
844 	case 0x50:
845 		dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n",
846 			 ret);
847 		break;
848 	default:
849 		dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
850 			"Chip ID: %02x\n", ret);
851 		goto out;
852 	}
853 
854 	ret = pm860x_reg_read(i2c, PM8607_BUCK3);
855 	if (ret < 0) {
856 		dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret);
857 		goto out;
858 	}
859 	if (ret & PM8607_BUCK3_DOUBLE)
860 		chip->buck3_double = 1;
861 
862 	ret = pm860x_reg_read(i2c, PM8607_B0_MISC1);
863 	if (ret < 0) {
864 		dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret);
865 		goto out;
866 	}
867 
868 	if (pdata && (pdata->i2c_port == PI2C_PORT))
869 		data = PM8607_B0_MISC1_PI2C;
870 	else
871 		data = 0;
872 	ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, PM8607_B0_MISC1_PI2C, data);
873 	if (ret < 0) {
874 		dev_err(chip->dev, "Failed to access MISC1:%d\n", ret);
875 		goto out;
876 	}
877 
878 	ret = device_gpadc_init(chip, pdata);
879 	if (ret < 0)
880 		goto out;
881 
882 	ret = device_irq_init(chip, pdata);
883 	if (ret < 0)
884 		goto out;
885 
886 	device_regulator_init(chip, pdata);
887 	device_rtc_init(chip, pdata);
888 	device_onkey_init(chip, pdata);
889 	device_touch_init(chip, pdata);
890 	device_power_init(chip, pdata);
891 	device_codec_init(chip, pdata);
892 out:
893 	return;
894 }
895 
896 static void __devinit device_8606_init(struct pm860x_chip *chip,
897 				       struct i2c_client *i2c,
898 				       struct pm860x_platform_data *pdata)
899 {
900 	device_osc_init(i2c);
901 	device_bk_init(chip, pdata);
902 	device_led_init(chip, pdata);
903 }
904 
905 int __devinit pm860x_device_init(struct pm860x_chip *chip,
906 		       struct pm860x_platform_data *pdata)
907 {
908 	chip->core_irq = 0;
909 
910 	switch (chip->id) {
911 	case CHIP_PM8606:
912 		device_8606_init(chip, chip->client, pdata);
913 		break;
914 	case CHIP_PM8607:
915 		device_8607_init(chip, chip->client, pdata);
916 		break;
917 	}
918 
919 	if (chip->companion) {
920 		switch (chip->id) {
921 		case CHIP_PM8607:
922 			device_8606_init(chip, chip->companion, pdata);
923 			break;
924 		case CHIP_PM8606:
925 			device_8607_init(chip, chip->companion, pdata);
926 			break;
927 		}
928 	}
929 
930 	return 0;
931 }
932 
933 void __devexit pm860x_device_exit(struct pm860x_chip *chip)
934 {
935 	device_irq_exit(chip);
936 	mfd_remove_devices(chip->dev);
937 }
938 
939 MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x");
940 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
941 MODULE_LICENSE("GPL");
942