aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/88pm860x-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/88pm860x-core.c')
-rw-r--r--drivers/mfd/88pm860x-core.c805
1 files changed, 567 insertions, 238 deletions
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index b73f033b2c60..59d117e9fa31 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -11,50 +11,116 @@
11 11
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/err.h>
14#include <linux/i2c.h> 15#include <linux/i2c.h>
15#include <linux/irq.h> 16#include <linux/irq.h>
16#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/irqdomain.h>
19#include <linux/of.h>
20#include <linux/of_platform.h>
17#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/regmap.h>
23#include <linux/slab.h>
18#include <linux/mfd/core.h> 24#include <linux/mfd/core.h>
19#include <linux/mfd/88pm860x.h> 25#include <linux/mfd/88pm860x.h>
20#include <linux/regulator/machine.h> 26#include <linux/regulator/machine.h>
21 27
22#define INT_STATUS_NUM 3 28#define INT_STATUS_NUM 3
23 29
24static struct resource bk_resources[] __devinitdata = { 30static struct resource bk0_resources[] __devinitdata = {
25 {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,}, 31 {2, 2, "duty cycle", IORESOURCE_REG, },
26 {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,}, 32 {3, 3, "always on", IORESOURCE_REG, },
27 {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,}, 33 {3, 3, "current", IORESOURCE_REG, },
28}; 34};
29 35static struct resource bk1_resources[] __devinitdata = {
30static struct resource led_resources[] __devinitdata = { 36 {4, 4, "duty cycle", IORESOURCE_REG, },
31 {PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO,}, 37 {5, 5, "always on", IORESOURCE_REG, },
32 {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,}, 38 {5, 5, "current", IORESOURCE_REG, },
33 {PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO,}, 39};
34 {PM8606_LED2_RED, PM8606_LED2_RED, "led1-red", IORESOURCE_IO,}, 40static struct resource bk2_resources[] __devinitdata = {
35 {PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,}, 41 {6, 6, "duty cycle", IORESOURCE_REG, },
36 {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,}, 42 {7, 7, "always on", IORESOURCE_REG, },
37}; 43 {5, 5, "current", IORESOURCE_REG, },
38 44};
39static struct resource regulator_resources[] __devinitdata = { 45
40 {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,}, 46static struct resource led0_resources[] __devinitdata = {
41 {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,}, 47 /* RGB1 Red LED */
42 {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,}, 48 {0xd, 0xd, "control", IORESOURCE_REG, },
43 {PM8607_ID_LDO1, PM8607_ID_LDO1, "ldo-01", IORESOURCE_IO,}, 49 {0xc, 0xc, "blink", IORESOURCE_REG, },
44 {PM8607_ID_LDO2, PM8607_ID_LDO2, "ldo-02", IORESOURCE_IO,}, 50};
45 {PM8607_ID_LDO3, PM8607_ID_LDO3, "ldo-03", IORESOURCE_IO,}, 51static struct resource led1_resources[] __devinitdata = {
46 {PM8607_ID_LDO4, PM8607_ID_LDO4, "ldo-04", IORESOURCE_IO,}, 52 /* RGB1 Green LED */
47 {PM8607_ID_LDO5, PM8607_ID_LDO5, "ldo-05", IORESOURCE_IO,}, 53 {0xe, 0xe, "control", IORESOURCE_REG, },
48 {PM8607_ID_LDO6, PM8607_ID_LDO6, "ldo-06", IORESOURCE_IO,}, 54 {0xc, 0xc, "blink", IORESOURCE_REG, },
49 {PM8607_ID_LDO7, PM8607_ID_LDO7, "ldo-07", IORESOURCE_IO,}, 55};
50 {PM8607_ID_LDO8, PM8607_ID_LDO8, "ldo-08", IORESOURCE_IO,}, 56static struct resource led2_resources[] __devinitdata = {
51 {PM8607_ID_LDO9, PM8607_ID_LDO9, "ldo-09", IORESOURCE_IO,}, 57 /* RGB1 Blue LED */
52 {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,}, 58 {0xf, 0xf, "control", IORESOURCE_REG, },
53 {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,}, 59 {0xc, 0xc, "blink", IORESOURCE_REG, },
54 {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,}, 60};
55 {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,}, 61static struct resource led3_resources[] __devinitdata = {
56 {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,}, 62 /* RGB2 Red LED */
57 {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,}, 63 {0x9, 0x9, "control", IORESOURCE_REG, },
64 {0x8, 0x8, "blink", IORESOURCE_REG, },
65};
66static struct resource led4_resources[] __devinitdata = {
67 /* RGB2 Green LED */
68 {0xa, 0xa, "control", IORESOURCE_REG, },
69 {0x8, 0x8, "blink", IORESOURCE_REG, },
70};
71static struct resource led5_resources[] __devinitdata = {
72 /* RGB2 Blue LED */
73 {0xb, 0xb, "control", IORESOURCE_REG, },
74 {0x8, 0x8, "blink", IORESOURCE_REG, },
75};
76
77static struct resource buck1_resources[] __devinitdata = {
78 {0x24, 0x24, "buck set", IORESOURCE_REG, },
79};
80static struct resource buck2_resources[] __devinitdata = {
81 {0x25, 0x25, "buck set", IORESOURCE_REG, },
82};
83static struct resource buck3_resources[] __devinitdata = {
84 {0x26, 0x26, "buck set", IORESOURCE_REG, },
85};
86static struct resource ldo1_resources[] __devinitdata = {
87 {0x10, 0x10, "ldo set", IORESOURCE_REG, },
88};
89static struct resource ldo2_resources[] __devinitdata = {
90 {0x11, 0x11, "ldo set", IORESOURCE_REG, },
91};
92static struct resource ldo3_resources[] __devinitdata = {
93 {0x12, 0x12, "ldo set", IORESOURCE_REG, },
94};
95static struct resource ldo4_resources[] __devinitdata = {
96 {0x13, 0x13, "ldo set", IORESOURCE_REG, },
97};
98static struct resource ldo5_resources[] __devinitdata = {
99 {0x14, 0x14, "ldo set", IORESOURCE_REG, },
100};
101static struct resource ldo6_resources[] __devinitdata = {
102 {0x15, 0x15, "ldo set", IORESOURCE_REG, },
103};
104static struct resource ldo7_resources[] __devinitdata = {
105 {0x16, 0x16, "ldo set", IORESOURCE_REG, },
106};
107static struct resource ldo8_resources[] __devinitdata = {
108 {0x17, 0x17, "ldo set", IORESOURCE_REG, },
109};
110static struct resource ldo9_resources[] __devinitdata = {
111 {0x18, 0x18, "ldo set", IORESOURCE_REG, },
112};
113static struct resource ldo10_resources[] __devinitdata = {
114 {0x19, 0x19, "ldo set", IORESOURCE_REG, },
115};
116static struct resource ldo12_resources[] __devinitdata = {
117 {0x1a, 0x1a, "ldo set", IORESOURCE_REG, },
118};
119static struct resource ldo_vibrator_resources[] __devinitdata = {
120 {0x28, 0x28, "ldo set", IORESOURCE_REG, },
121};
122static struct resource ldo14_resources[] __devinitdata = {
123 {0x1b, 0x1b, "ldo set", IORESOURCE_REG, },
58}; 124};
59 125
60static struct resource touch_resources[] __devinitdata = { 126static struct resource touch_resources[] __devinitdata = {
@@ -90,48 +156,145 @@ static struct resource charger_resources[] __devinitdata = {
90 {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, 156 {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,},
91}; 157};
92 158
93static struct resource preg_resources[] __devinitdata = {
94 {PM8606_ID_PREG, PM8606_ID_PREG, "preg", IORESOURCE_IO,},
95};
96
97static struct resource rtc_resources[] __devinitdata = { 159static struct resource rtc_resources[] __devinitdata = {
98 {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,}, 160 {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
99}; 161};
100 162
101static struct mfd_cell bk_devs[] = { 163static struct mfd_cell bk_devs[] __devinitdata = {
102 {"88pm860x-backlight", 0,}, 164 {
103 {"88pm860x-backlight", 1,}, 165 .name = "88pm860x-backlight",
104 {"88pm860x-backlight", 2,}, 166 .id = 0,
105}; 167 .num_resources = ARRAY_SIZE(bk0_resources),
106 168 .resources = bk0_resources,
107static struct mfd_cell led_devs[] = { 169 }, {
108 {"88pm860x-led", 0,}, 170 .name = "88pm860x-backlight",
109 {"88pm860x-led", 1,}, 171 .id = 1,
110 {"88pm860x-led", 2,}, 172 .num_resources = ARRAY_SIZE(bk1_resources),
111 {"88pm860x-led", 3,}, 173 .resources = bk1_resources,
112 {"88pm860x-led", 4,}, 174 }, {
113 {"88pm860x-led", 5,}, 175 .name = "88pm860x-backlight",
114}; 176 .id = 2,
115 177 .num_resources = ARRAY_SIZE(bk2_resources),
116static struct mfd_cell regulator_devs[] = { 178 .resources = bk2_resources,
117 {"88pm860x-regulator", 0,}, 179 },
118 {"88pm860x-regulator", 1,}, 180};
119 {"88pm860x-regulator", 2,}, 181
120 {"88pm860x-regulator", 3,}, 182static struct mfd_cell led_devs[] __devinitdata = {
121 {"88pm860x-regulator", 4,}, 183 {
122 {"88pm860x-regulator", 5,}, 184 .name = "88pm860x-led",
123 {"88pm860x-regulator", 6,}, 185 .id = 0,
124 {"88pm860x-regulator", 7,}, 186 .num_resources = ARRAY_SIZE(led0_resources),
125 {"88pm860x-regulator", 8,}, 187 .resources = led0_resources,
126 {"88pm860x-regulator", 9,}, 188 }, {
127 {"88pm860x-regulator", 10,}, 189 .name = "88pm860x-led",
128 {"88pm860x-regulator", 11,}, 190 .id = 1,
129 {"88pm860x-regulator", 12,}, 191 .num_resources = ARRAY_SIZE(led1_resources),
130 {"88pm860x-regulator", 13,}, 192 .resources = led1_resources,
131 {"88pm860x-regulator", 14,}, 193 }, {
132 {"88pm860x-regulator", 15,}, 194 .name = "88pm860x-led",
133 {"88pm860x-regulator", 16,}, 195 .id = 2,
134 {"88pm860x-regulator", 17,}, 196 .num_resources = ARRAY_SIZE(led2_resources),
197 .resources = led2_resources,
198 }, {
199 .name = "88pm860x-led",
200 .id = 3,
201 .num_resources = ARRAY_SIZE(led3_resources),
202 .resources = led3_resources,
203 }, {
204 .name = "88pm860x-led",
205 .id = 4,
206 .num_resources = ARRAY_SIZE(led4_resources),
207 .resources = led4_resources,
208 }, {
209 .name = "88pm860x-led",
210 .id = 5,
211 .num_resources = ARRAY_SIZE(led5_resources),
212 .resources = led5_resources,
213 },
214};
215
216static struct mfd_cell reg_devs[] __devinitdata = {
217 {
218 .name = "88pm860x-regulator",
219 .id = 0,
220 .num_resources = ARRAY_SIZE(buck1_resources),
221 .resources = buck1_resources,
222 }, {
223 .name = "88pm860x-regulator",
224 .id = 1,
225 .num_resources = ARRAY_SIZE(buck2_resources),
226 .resources = buck2_resources,
227 }, {
228 .name = "88pm860x-regulator",
229 .id = 2,
230 .num_resources = ARRAY_SIZE(buck3_resources),
231 .resources = buck3_resources,
232 }, {
233 .name = "88pm860x-regulator",
234 .id = 3,
235 .num_resources = ARRAY_SIZE(ldo1_resources),
236 .resources = ldo1_resources,
237 }, {
238 .name = "88pm860x-regulator",
239 .id = 4,
240 .num_resources = ARRAY_SIZE(ldo2_resources),
241 .resources = ldo2_resources,
242 }, {
243 .name = "88pm860x-regulator",
244 .id = 5,
245 .num_resources = ARRAY_SIZE(ldo3_resources),
246 .resources = ldo3_resources,
247 }, {
248 .name = "88pm860x-regulator",
249 .id = 6,
250 .num_resources = ARRAY_SIZE(ldo4_resources),
251 .resources = ldo4_resources,
252 }, {
253 .name = "88pm860x-regulator",
254 .id = 7,
255 .num_resources = ARRAY_SIZE(ldo5_resources),
256 .resources = ldo5_resources,
257 }, {
258 .name = "88pm860x-regulator",
259 .id = 8,
260 .num_resources = ARRAY_SIZE(ldo6_resources),
261 .resources = ldo6_resources,
262 }, {
263 .name = "88pm860x-regulator",
264 .id = 9,
265 .num_resources = ARRAY_SIZE(ldo7_resources),
266 .resources = ldo7_resources,
267 }, {
268 .name = "88pm860x-regulator",
269 .id = 10,
270 .num_resources = ARRAY_SIZE(ldo8_resources),
271 .resources = ldo8_resources,
272 }, {
273 .name = "88pm860x-regulator",
274 .id = 11,
275 .num_resources = ARRAY_SIZE(ldo9_resources),
276 .resources = ldo9_resources,
277 }, {
278 .name = "88pm860x-regulator",
279 .id = 12,
280 .num_resources = ARRAY_SIZE(ldo10_resources),
281 .resources = ldo10_resources,
282 }, {
283 .name = "88pm860x-regulator",
284 .id = 13,
285 .num_resources = ARRAY_SIZE(ldo12_resources),
286 .resources = ldo12_resources,
287 }, {
288 .name = "88pm860x-regulator",
289 .id = 14,
290 .num_resources = ARRAY_SIZE(ldo_vibrator_resources),
291 .resources = ldo_vibrator_resources,
292 }, {
293 .name = "88pm860x-regulator",
294 .id = 15,
295 .num_resources = ARRAY_SIZE(ldo14_resources),
296 .resources = ldo14_resources,
297 },
135}; 298};
136 299
137static struct mfd_cell touch_devs[] = { 300static struct mfd_cell touch_devs[] = {
@@ -360,15 +523,12 @@ static void pm860x_irq_sync_unlock(struct irq_data *data)
360 523
361static void pm860x_irq_enable(struct irq_data *data) 524static void pm860x_irq_enable(struct irq_data *data)
362{ 525{
363 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 526 pm860x_irqs[data->hwirq].enable = pm860x_irqs[data->hwirq].offs;
364 pm860x_irqs[data->irq - chip->irq_base].enable
365 = pm860x_irqs[data->irq - chip->irq_base].offs;
366} 527}
367 528
368static void pm860x_irq_disable(struct irq_data *data) 529static void pm860x_irq_disable(struct irq_data *data)
369{ 530{
370 struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); 531 pm860x_irqs[data->hwirq].enable = 0;
371 pm860x_irqs[data->irq - chip->irq_base].enable = 0;
372} 532}
373 533
374static struct irq_chip pm860x_irq_chip = { 534static struct irq_chip pm860x_irq_chip = {
@@ -379,53 +539,25 @@ static struct irq_chip pm860x_irq_chip = {
379 .irq_disable = pm860x_irq_disable, 539 .irq_disable = pm860x_irq_disable,
380}; 540};
381 541
382static int __devinit device_gpadc_init(struct pm860x_chip *chip, 542static int pm860x_irq_domain_map(struct irq_domain *d, unsigned int virq,
383 struct pm860x_platform_data *pdata) 543 irq_hw_number_t hw)
384{ 544{
385 struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ 545 irq_set_chip_data(virq, d->host_data);
386 : chip->companion; 546 irq_set_chip_and_handler(virq, &pm860x_irq_chip, handle_edge_irq);
387 int data; 547 irq_set_nested_thread(virq, 1);
388 int ret; 548#ifdef CONFIG_ARM
389 549 set_irq_flags(virq, IRQF_VALID);
390 /* initialize GPADC without activating it */ 550#else
391 551 irq_set_noprobe(virq);
392 if (!pdata || !pdata->touch) 552#endif
393 return -EINVAL; 553 return 0;
394
395 /* set GPADC MISC1 register */
396 data = 0;
397 data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK;
398 data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK;
399 data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK;
400 data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK;
401 if (data) {
402 ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
403 if (ret < 0)
404 goto out;
405 }
406 /* set tsi prebias time */
407 if (pdata->touch->tsi_prebias) {
408 data = pdata->touch->tsi_prebias;
409 ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
410 if (ret < 0)
411 goto out;
412 }
413 /* set prebias & prechg time of pen detect */
414 data = 0;
415 data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK;
416 data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK;
417 if (data) {
418 ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
419 if (ret < 0)
420 goto out;
421 }
422
423 ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1,
424 PM8607_GPADC_EN, PM8607_GPADC_EN);
425out:
426 return ret;
427} 554}
428 555
556static struct irq_domain_ops pm860x_irq_domain_ops = {
557 .map = pm860x_irq_domain_map,
558 .xlate = irq_domain_xlate_onetwocell,
559};
560
429static int __devinit device_irq_init(struct pm860x_chip *chip, 561static int __devinit device_irq_init(struct pm860x_chip *chip,
430 struct pm860x_platform_data *pdata) 562 struct pm860x_platform_data *pdata)
431{ 563{
@@ -433,13 +565,9 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
433 : chip->companion; 565 : chip->companion;
434 unsigned char status_buf[INT_STATUS_NUM]; 566 unsigned char status_buf[INT_STATUS_NUM];
435 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; 567 unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
436 int i, data, mask, ret = -EINVAL; 568 int data, mask, ret = -EINVAL;
437 int __irq; 569 int nr_irqs, irq_base = -1;
438 570 struct device_node *node = i2c->dev.of_node;
439 if (!pdata || !pdata->irq_base) {
440 dev_warn(chip->dev, "No interrupt support on IRQ base\n");
441 return -EINVAL;
442 }
443 571
444 mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR 572 mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
445 | PM8607_B0_MISC1_INT_MASK; 573 | PM8607_B0_MISC1_INT_MASK;
@@ -479,26 +607,24 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
479 goto out; 607 goto out;
480 608
481 mutex_init(&chip->irq_lock); 609 mutex_init(&chip->irq_lock);
482 chip->irq_base = pdata->irq_base; 610
611 if (pdata && pdata->irq_base)
612 irq_base = pdata->irq_base;
613 nr_irqs = ARRAY_SIZE(pm860x_irqs);
614 chip->irq_base = irq_alloc_descs(irq_base, 0, nr_irqs, 0);
615 if (chip->irq_base < 0) {
616 dev_err(&i2c->dev, "Failed to allocate interrupts, ret:%d\n",
617 chip->irq_base);
618 ret = -EBUSY;
619 goto out;
620 }
621 irq_domain_add_legacy(node, nr_irqs, chip->irq_base, 0,
622 &pm860x_irq_domain_ops, chip);
483 chip->core_irq = i2c->irq; 623 chip->core_irq = i2c->irq;
484 if (!chip->core_irq) 624 if (!chip->core_irq)
485 goto out; 625 goto out;
486 626
487 /* register IRQ by genirq */ 627 ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags | IRQF_ONESHOT,
488 for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
489 __irq = i + chip->irq_base;
490 irq_set_chip_data(__irq, chip);
491 irq_set_chip_and_handler(__irq, &pm860x_irq_chip,
492 handle_edge_irq);
493 irq_set_nested_thread(__irq, 1);
494#ifdef CONFIG_ARM
495 set_irq_flags(__irq, IRQF_VALID);
496#else
497 irq_set_noprobe(__irq);
498#endif
499 }
500
501 ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags,
502 "88pm860x", chip); 628 "88pm860x", chip);
503 if (ret) { 629 if (ret) {
504 dev_err(chip->dev, "Failed to request IRQ: %d\n", ret); 630 dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
@@ -615,108 +741,122 @@ static void __devinit device_osc_init(struct i2c_client *i2c)
615static void __devinit device_bk_init(struct pm860x_chip *chip, 741static void __devinit device_bk_init(struct pm860x_chip *chip,
616 struct pm860x_platform_data *pdata) 742 struct pm860x_platform_data *pdata)
617{ 743{
618 int ret; 744 int ret, i;
619 int i, j, id; 745
620 746 if (pdata && pdata->backlight) {
621 if ((pdata == NULL) || (pdata->backlight == NULL)) 747 if (pdata->num_backlights > ARRAY_SIZE(bk_devs))
622 return; 748 pdata->num_backlights = ARRAY_SIZE(bk_devs);
623 749 for (i = 0; i < pdata->num_backlights; i++) {
624 if (pdata->num_backlights > ARRAY_SIZE(bk_devs)) 750 bk_devs[i].platform_data = &pdata->backlight[i];
625 pdata->num_backlights = ARRAY_SIZE(bk_devs); 751 bk_devs[i].pdata_size =
626 752 sizeof(struct pm860x_backlight_pdata);
627 for (i = 0; i < pdata->num_backlights; i++) {
628 bk_devs[i].platform_data = &pdata->backlight[i];
629 bk_devs[i].pdata_size = sizeof(struct pm860x_backlight_pdata);
630
631 for (j = 0; j < ARRAY_SIZE(bk_devs); j++) {
632 id = bk_resources[j].start;
633 if (pdata->backlight[i].flags != id)
634 continue;
635
636 bk_devs[i].num_resources = 1;
637 bk_devs[i].resources = &bk_resources[j];
638 ret = mfd_add_devices(chip->dev, 0,
639 &bk_devs[i], 1,
640 &bk_resources[j], 0, NULL);
641 if (ret < 0) {
642 dev_err(chip->dev, "Failed to add "
643 "backlight subdev\n");
644 return;
645 }
646 } 753 }
647 } 754 }
755 ret = mfd_add_devices(chip->dev, 0, bk_devs,
756 ARRAY_SIZE(bk_devs), NULL, 0, NULL);
757 if (ret < 0)
758 dev_err(chip->dev, "Failed to add backlight subdev\n");
648} 759}
649 760
650static void __devinit device_led_init(struct pm860x_chip *chip, 761static void __devinit device_led_init(struct pm860x_chip *chip,
651 struct pm860x_platform_data *pdata) 762 struct pm860x_platform_data *pdata)
652{ 763{
653 int ret; 764 int ret, i;
654 int i, j, id; 765
655 766 if (pdata && pdata->led) {
656 if ((pdata == NULL) || (pdata->led == NULL)) 767 if (pdata->num_leds > ARRAY_SIZE(led_devs))
657 return; 768 pdata->num_leds = ARRAY_SIZE(led_devs);
658 769 for (i = 0; i < pdata->num_leds; i++) {
659 if (pdata->num_leds > ARRAY_SIZE(led_devs)) 770 led_devs[i].platform_data = &pdata->led[i];
660 pdata->num_leds = ARRAY_SIZE(led_devs); 771 led_devs[i].pdata_size =
661 772 sizeof(struct pm860x_led_pdata);
662 for (i = 0; i < pdata->num_leds; i++) {
663 led_devs[i].platform_data = &pdata->led[i];
664 led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata);
665
666 for (j = 0; j < ARRAY_SIZE(led_devs); j++) {
667 id = led_resources[j].start;
668 if (pdata->led[i].flags != id)
669 continue;
670
671 led_devs[i].num_resources = 1;
672 led_devs[i].resources = &led_resources[j],
673 ret = mfd_add_devices(chip->dev, 0,
674 &led_devs[i], 1,
675 &led_resources[j], 0, NULL);
676 if (ret < 0) {
677 dev_err(chip->dev, "Failed to add "
678 "led subdev\n");
679 return;
680 }
681 } 773 }
682 } 774 }
775 ret = mfd_add_devices(chip->dev, 0, led_devs,
776 ARRAY_SIZE(led_devs), NULL, 0, NULL);
777 if (ret < 0) {
778 dev_err(chip->dev, "Failed to add led subdev\n");
779 return;
780 }
683} 781}
684 782
685static void __devinit device_regulator_init(struct pm860x_chip *chip, 783static void __devinit device_regulator_init(struct pm860x_chip *chip,
686 struct pm860x_platform_data *pdata) 784 struct pm860x_platform_data *pdata)
687{ 785{
688 struct regulator_init_data *initdata;
689 int ret; 786 int ret;
690 int i, seq;
691 787
692 if ((pdata == NULL) || (pdata->regulator == NULL)) 788 if (pdata == NULL)
789 return;
790 if (pdata->buck1) {
791 reg_devs[0].platform_data = pdata->buck1;
792 reg_devs[0].pdata_size = sizeof(struct regulator_init_data);
793 }
794 if (pdata->buck2) {
795 reg_devs[1].platform_data = pdata->buck2;
796 reg_devs[1].pdata_size = sizeof(struct regulator_init_data);
797 }
798 if (pdata->buck3) {
799 reg_devs[2].platform_data = pdata->buck3;
800 reg_devs[2].pdata_size = sizeof(struct regulator_init_data);
801 }
802 if (pdata->ldo1) {
803 reg_devs[3].platform_data = pdata->ldo1;
804 reg_devs[3].pdata_size = sizeof(struct regulator_init_data);
805 }
806 if (pdata->ldo2) {
807 reg_devs[4].platform_data = pdata->ldo2;
808 reg_devs[4].pdata_size = sizeof(struct regulator_init_data);
809 }
810 if (pdata->ldo3) {
811 reg_devs[5].platform_data = pdata->ldo3;
812 reg_devs[5].pdata_size = sizeof(struct regulator_init_data);
813 }
814 if (pdata->ldo4) {
815 reg_devs[6].platform_data = pdata->ldo4;
816 reg_devs[6].pdata_size = sizeof(struct regulator_init_data);
817 }
818 if (pdata->ldo5) {
819 reg_devs[7].platform_data = pdata->ldo5;
820 reg_devs[7].pdata_size = sizeof(struct regulator_init_data);
821 }
822 if (pdata->ldo6) {
823 reg_devs[8].platform_data = pdata->ldo6;
824 reg_devs[8].pdata_size = sizeof(struct regulator_init_data);
825 }
826 if (pdata->ldo7) {
827 reg_devs[9].platform_data = pdata->ldo7;
828 reg_devs[9].pdata_size = sizeof(struct regulator_init_data);
829 }
830 if (pdata->ldo8) {
831 reg_devs[10].platform_data = pdata->ldo8;
832 reg_devs[10].pdata_size = sizeof(struct regulator_init_data);
833 }
834 if (pdata->ldo9) {
835 reg_devs[11].platform_data = pdata->ldo9;
836 reg_devs[11].pdata_size = sizeof(struct regulator_init_data);
837 }
838 if (pdata->ldo10) {
839 reg_devs[12].platform_data = pdata->ldo10;
840 reg_devs[12].pdata_size = sizeof(struct regulator_init_data);
841 }
842 if (pdata->ldo12) {
843 reg_devs[13].platform_data = pdata->ldo12;
844 reg_devs[13].pdata_size = sizeof(struct regulator_init_data);
845 }
846 if (pdata->ldo_vibrator) {
847 reg_devs[14].platform_data = pdata->ldo_vibrator;
848 reg_devs[14].pdata_size = sizeof(struct regulator_init_data);
849 }
850 if (pdata->ldo14) {
851 reg_devs[15].platform_data = pdata->ldo14;
852 reg_devs[15].pdata_size = sizeof(struct regulator_init_data);
853 }
854 ret = mfd_add_devices(chip->dev, 0, reg_devs,
855 ARRAY_SIZE(reg_devs), NULL, 0, NULL);
856 if (ret < 0) {
857 dev_err(chip->dev, "Failed to add regulator subdev\n");
693 return; 858 return;
694
695 if (pdata->num_regulators > ARRAY_SIZE(regulator_devs))
696 pdata->num_regulators = ARRAY_SIZE(regulator_devs);
697
698 for (i = 0, seq = -1; i < pdata->num_regulators; i++) {
699 initdata = &pdata->regulator[i];
700 seq = *(unsigned int *)initdata->driver_data;
701 if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) {
702 dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n",
703 seq, initdata->constraints.name);
704 goto out;
705 }
706 regulator_devs[i].platform_data = &pdata->regulator[i];
707 regulator_devs[i].pdata_size = sizeof(struct regulator_init_data);
708 regulator_devs[i].num_resources = 1;
709 regulator_devs[i].resources = &regulator_resources[seq];
710
711 ret = mfd_add_devices(chip->dev, 0, &regulator_devs[i], 1,
712 &regulator_resources[seq], 0, NULL);
713 if (ret < 0) {
714 dev_err(chip->dev, "Failed to add regulator subdev\n");
715 goto out;
716 }
717 } 859 }
718out:
719 return;
720} 860}
721 861
722static void __devinit device_rtc_init(struct pm860x_chip *chip, 862static void __devinit device_rtc_init(struct pm860x_chip *chip,
@@ -785,10 +925,8 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
785 925
786 power_devs[2].platform_data = &preg_init_data; 926 power_devs[2].platform_data = &preg_init_data;
787 power_devs[2].pdata_size = sizeof(struct regulator_init_data); 927 power_devs[2].pdata_size = sizeof(struct regulator_init_data);
788 power_devs[2].num_resources = ARRAY_SIZE(preg_resources);
789 power_devs[2].resources = &preg_resources[0],
790 ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1, 928 ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1,
791 &preg_resources[0], chip->irq_base, NULL); 929 NULL, chip->irq_base, NULL);
792 if (ret < 0) 930 if (ret < 0)
793 dev_err(chip->dev, "Failed to add preg subdev\n"); 931 dev_err(chip->dev, "Failed to add preg subdev\n");
794} 932}
@@ -868,10 +1006,6 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
868 goto out; 1006 goto out;
869 } 1007 }
870 1008
871 ret = device_gpadc_init(chip, pdata);
872 if (ret < 0)
873 goto out;
874
875 ret = device_irq_init(chip, pdata); 1009 ret = device_irq_init(chip, pdata);
876 if (ret < 0) 1010 if (ret < 0)
877 goto out; 1011 goto out;
@@ -895,8 +1029,8 @@ static void __devinit device_8606_init(struct pm860x_chip *chip,
895 device_led_init(chip, pdata); 1029 device_led_init(chip, pdata);
896} 1030}
897 1031
898int __devinit pm860x_device_init(struct pm860x_chip *chip, 1032static int __devinit pm860x_device_init(struct pm860x_chip *chip,
899 struct pm860x_platform_data *pdata) 1033 struct pm860x_platform_data *pdata)
900{ 1034{
901 chip->core_irq = 0; 1035 chip->core_irq = 0;
902 1036
@@ -923,12 +1057,207 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
923 return 0; 1057 return 0;
924} 1058}
925 1059
926void __devexit pm860x_device_exit(struct pm860x_chip *chip) 1060static void __devexit pm860x_device_exit(struct pm860x_chip *chip)
927{ 1061{
928 device_irq_exit(chip); 1062 device_irq_exit(chip);
929 mfd_remove_devices(chip->dev); 1063 mfd_remove_devices(chip->dev);
930} 1064}
931 1065
1066static int verify_addr(struct i2c_client *i2c)
1067{
1068 unsigned short addr_8607[] = {0x30, 0x34};
1069 unsigned short addr_8606[] = {0x10, 0x11};
1070 int size, i;
1071
1072 if (i2c == NULL)
1073 return 0;
1074 size = ARRAY_SIZE(addr_8606);
1075 for (i = 0; i < size; i++) {
1076 if (i2c->addr == *(addr_8606 + i))
1077 return CHIP_PM8606;
1078 }
1079 size = ARRAY_SIZE(addr_8607);
1080 for (i = 0; i < size; i++) {
1081 if (i2c->addr == *(addr_8607 + i))
1082 return CHIP_PM8607;
1083 }
1084 return 0;
1085}
1086
1087static struct regmap_config pm860x_regmap_config = {
1088 .reg_bits = 8,
1089 .val_bits = 8,
1090};
1091
1092static int __devinit pm860x_dt_init(struct device_node *np,
1093 struct device *dev,
1094 struct pm860x_platform_data *pdata)
1095{
1096 int ret;
1097
1098 if (of_get_property(np, "marvell,88pm860x-irq-read-clr", NULL))
1099 pdata->irq_mode = 1;
1100 ret = of_property_read_u32(np, "marvell,88pm860x-slave-addr",
1101 &pdata->companion_addr);
1102 if (ret) {
1103 dev_err(dev, "Not found \"marvell,88pm860x-slave-addr\" "
1104 "property\n");
1105 pdata->companion_addr = 0;
1106 }
1107 return 0;
1108}
1109
1110static int __devinit pm860x_probe(struct i2c_client *client,
1111 const struct i2c_device_id *id)
1112{
1113 struct pm860x_platform_data *pdata = client->dev.platform_data;
1114 struct device_node *node = client->dev.of_node;
1115 struct pm860x_chip *chip;
1116 int ret;
1117
1118 if (node && !pdata) {
1119 /* parse DT to get platform data */
1120 pdata = devm_kzalloc(&client->dev,
1121 sizeof(struct pm860x_platform_data),
1122 GFP_KERNEL);
1123 if (!pdata)
1124 return -ENOMEM;
1125 ret = pm860x_dt_init(node, &client->dev, pdata);
1126 if (ret)
1127 goto err;
1128 } else if (!pdata) {
1129 pr_info("No platform data in %s!\n", __func__);
1130 return -EINVAL;
1131 }
1132
1133 chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
1134 if (chip == NULL) {
1135 ret = -ENOMEM;
1136 goto err;
1137 }
1138
1139 chip->id = verify_addr(client);
1140 chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config);
1141 if (IS_ERR(chip->regmap)) {
1142 ret = PTR_ERR(chip->regmap);
1143 dev_err(&client->dev, "Failed to allocate register map: %d\n",
1144 ret);
1145 kfree(chip);
1146 return ret;
1147 }
1148 chip->client = client;
1149 i2c_set_clientdata(client, chip);
1150 chip->dev = &client->dev;
1151 dev_set_drvdata(chip->dev, chip);
1152
1153 /*
1154 * Both client and companion client shares same platform driver.
1155 * Driver distinguishes them by pdata->companion_addr.
1156 * pdata->companion_addr is only assigned if companion chip exists.
1157 * At the same time, the companion_addr shouldn't equal to client
1158 * address.
1159 */
1160 if (pdata->companion_addr && (pdata->companion_addr != client->addr)) {
1161 chip->companion_addr = pdata->companion_addr;
1162 chip->companion = i2c_new_dummy(chip->client->adapter,
1163 chip->companion_addr);
1164 chip->regmap_companion = regmap_init_i2c(chip->companion,
1165 &pm860x_regmap_config);
1166 if (IS_ERR(chip->regmap_companion)) {
1167 ret = PTR_ERR(chip->regmap_companion);
1168 dev_err(&chip->companion->dev,
1169 "Failed to allocate register map: %d\n", ret);
1170 return ret;
1171 }
1172 i2c_set_clientdata(chip->companion, chip);
1173 }
1174
1175 pm860x_device_init(chip, pdata);
1176 return 0;
1177err:
1178 if (node)
1179 devm_kfree(&client->dev, pdata);
1180 return ret;
1181}
1182
1183static int __devexit pm860x_remove(struct i2c_client *client)
1184{
1185 struct pm860x_chip *chip = i2c_get_clientdata(client);
1186
1187 pm860x_device_exit(chip);
1188 if (chip->companion) {
1189 regmap_exit(chip->regmap_companion);
1190 i2c_unregister_device(chip->companion);
1191 }
1192 regmap_exit(chip->regmap);
1193 kfree(chip);
1194 return 0;
1195}
1196
1197#ifdef CONFIG_PM_SLEEP
1198static int pm860x_suspend(struct device *dev)
1199{
1200 struct i2c_client *client = container_of(dev, struct i2c_client, dev);
1201 struct pm860x_chip *chip = i2c_get_clientdata(client);
1202
1203 if (device_may_wakeup(dev) && chip->wakeup_flag)
1204 enable_irq_wake(chip->core_irq);
1205 return 0;
1206}
1207
1208static int pm860x_resume(struct device *dev)
1209{
1210 struct i2c_client *client = container_of(dev, struct i2c_client, dev);
1211 struct pm860x_chip *chip = i2c_get_clientdata(client);
1212
1213 if (device_may_wakeup(dev) && chip->wakeup_flag)
1214 disable_irq_wake(chip->core_irq);
1215 return 0;
1216}
1217#endif
1218
1219static SIMPLE_DEV_PM_OPS(pm860x_pm_ops, pm860x_suspend, pm860x_resume);
1220
1221static const struct i2c_device_id pm860x_id_table[] = {
1222 { "88PM860x", 0 },
1223 {}
1224};
1225MODULE_DEVICE_TABLE(i2c, pm860x_id_table);
1226
1227static const struct of_device_id pm860x_dt_ids[] = {
1228 { .compatible = "marvell,88pm860x", },
1229 {},
1230};
1231MODULE_DEVICE_TABLE(of, pm860x_dt_ids);
1232
1233static struct i2c_driver pm860x_driver = {
1234 .driver = {
1235 .name = "88PM860x",
1236 .owner = THIS_MODULE,
1237 .pm = &pm860x_pm_ops,
1238 .of_match_table = of_match_ptr(pm860x_dt_ids),
1239 },
1240 .probe = pm860x_probe,
1241 .remove = __devexit_p(pm860x_remove),
1242 .id_table = pm860x_id_table,
1243};
1244
1245static int __init pm860x_i2c_init(void)
1246{
1247 int ret;
1248 ret = i2c_add_driver(&pm860x_driver);
1249 if (ret != 0)
1250 pr_err("Failed to register 88PM860x I2C driver: %d\n", ret);
1251 return ret;
1252}
1253subsys_initcall(pm860x_i2c_init);
1254
1255static void __exit pm860x_i2c_exit(void)
1256{
1257 i2c_del_driver(&pm860x_driver);
1258}
1259module_exit(pm860x_i2c_exit);
1260
932MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x"); 1261MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x");
933MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 1262MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
934MODULE_LICENSE("GPL"); 1263MODULE_LICENSE("GPL");