diff options
Diffstat (limited to 'drivers/mfd/88pm860x-core.c')
-rw-r--r-- | drivers/mfd/88pm860x-core.c | 567 |
1 files changed, 304 insertions, 263 deletions
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 793300c554b4..9c511c1604a5 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c | |||
@@ -17,230 +17,138 @@ | |||
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/mfd/core.h> | 18 | #include <linux/mfd/core.h> |
19 | #include <linux/mfd/88pm860x.h> | 19 | #include <linux/mfd/88pm860x.h> |
20 | #include <linux/regulator/machine.h> | ||
20 | 21 | ||
21 | #define INT_STATUS_NUM 3 | 22 | #define INT_STATUS_NUM 3 |
22 | 23 | ||
23 | char pm860x_backlight_name[][MFD_NAME_SIZE] = { | 24 | static struct resource bk_resources[] __initdata = { |
24 | "backlight-0", | 25 | {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,}, |
25 | "backlight-1", | 26 | {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,}, |
26 | "backlight-2", | 27 | {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,}, |
27 | }; | 28 | }; |
28 | EXPORT_SYMBOL(pm860x_backlight_name); | ||
29 | |||
30 | char pm860x_led_name[][MFD_NAME_SIZE] = { | ||
31 | "led0-red", | ||
32 | "led0-green", | ||
33 | "led0-blue", | ||
34 | "led1-red", | ||
35 | "led1-green", | ||
36 | "led1-blue", | ||
37 | }; | ||
38 | EXPORT_SYMBOL(pm860x_led_name); | ||
39 | |||
40 | #define PM8606_BACKLIGHT_RESOURCE(_i, _x) \ | ||
41 | { \ | ||
42 | .name = pm860x_backlight_name[_i], \ | ||
43 | .start = PM8606_##_x, \ | ||
44 | .end = PM8606_##_x, \ | ||
45 | .flags = IORESOURCE_IO, \ | ||
46 | } | ||
47 | 29 | ||
48 | static struct resource backlight_resources[] = { | 30 | static struct resource led_resources[] __initdata = { |
49 | PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT1, WLED1A), | 31 | {PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO,}, |
50 | PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT2, WLED2A), | 32 | {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,}, |
51 | PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT3, WLED3A), | 33 | {PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO,}, |
34 | {PM8606_LED2_RED, PM8606_LED2_RED, "led1-red", IORESOURCE_IO,}, | ||
35 | {PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,}, | ||
36 | {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,}, | ||
52 | }; | 37 | }; |
53 | 38 | ||
54 | #define PM8606_BACKLIGHT_DEVS(_i) \ | 39 | static struct resource regulator_resources[] __initdata = { |
55 | { \ | 40 | {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,}, |
56 | .name = "88pm860x-backlight", \ | 41 | {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,}, |
57 | .num_resources = 1, \ | 42 | {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,}, |
58 | .resources = &backlight_resources[_i], \ | 43 | {PM8607_ID_LDO1, PM8607_ID_LDO1, "ldo-01", IORESOURCE_IO,}, |
59 | .id = _i, \ | 44 | {PM8607_ID_LDO2, PM8607_ID_LDO2, "ldo-02", IORESOURCE_IO,}, |
60 | } | 45 | {PM8607_ID_LDO3, PM8607_ID_LDO3, "ldo-03", IORESOURCE_IO,}, |
61 | 46 | {PM8607_ID_LDO4, PM8607_ID_LDO4, "ldo-04", IORESOURCE_IO,}, | |
62 | static struct mfd_cell backlight_devs[] = { | 47 | {PM8607_ID_LDO5, PM8607_ID_LDO5, "ldo-05", IORESOURCE_IO,}, |
63 | PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT1), | 48 | {PM8607_ID_LDO6, PM8607_ID_LDO6, "ldo-06", IORESOURCE_IO,}, |
64 | PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT2), | 49 | {PM8607_ID_LDO7, PM8607_ID_LDO7, "ldo-07", IORESOURCE_IO,}, |
65 | PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT3), | 50 | {PM8607_ID_LDO8, PM8607_ID_LDO8, "ldo-08", IORESOURCE_IO,}, |
51 | {PM8607_ID_LDO9, PM8607_ID_LDO9, "ldo-09", IORESOURCE_IO,}, | ||
52 | {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,}, | ||
53 | {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,}, | ||
54 | {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,}, | ||
55 | {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,}, | ||
56 | {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,}, | ||
57 | {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,}, | ||
66 | }; | 58 | }; |
67 | 59 | ||
68 | #define PM8606_LED_RESOURCE(_i, _x) \ | 60 | static struct resource touch_resources[] __initdata = { |
69 | { \ | 61 | {PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,}, |
70 | .name = pm860x_led_name[_i], \ | ||
71 | .start = PM8606_##_x, \ | ||
72 | .end = PM8606_##_x, \ | ||
73 | .flags = IORESOURCE_IO, \ | ||
74 | } | ||
75 | |||
76 | static struct resource led_resources[] = { | ||
77 | PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB1B), | ||
78 | PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB1C), | ||
79 | PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB1D), | ||
80 | PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB2B), | ||
81 | PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB2C), | ||
82 | PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB2D), | ||
83 | }; | 62 | }; |
84 | 63 | ||
85 | #define PM8606_LED_DEVS(_i) \ | 64 | static struct resource onkey_resources[] __initdata = { |
86 | { \ | 65 | {PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,}, |
87 | .name = "88pm860x-led", \ | ||
88 | .num_resources = 1, \ | ||
89 | .resources = &led_resources[_i], \ | ||
90 | .id = _i, \ | ||
91 | } | ||
92 | |||
93 | static struct mfd_cell led_devs[] = { | ||
94 | PM8606_LED_DEVS(PM8606_LED1_RED), | ||
95 | PM8606_LED_DEVS(PM8606_LED1_GREEN), | ||
96 | PM8606_LED_DEVS(PM8606_LED1_BLUE), | ||
97 | PM8606_LED_DEVS(PM8606_LED2_RED), | ||
98 | PM8606_LED_DEVS(PM8606_LED2_GREEN), | ||
99 | PM8606_LED_DEVS(PM8606_LED2_BLUE), | ||
100 | }; | 66 | }; |
101 | 67 | ||
102 | static struct resource touch_resources[] = { | 68 | static struct resource codec_resources[] __initdata = { |
103 | { | 69 | /* Headset microphone insertion or removal */ |
104 | .start = PM8607_IRQ_PEN, | 70 | {PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,}, |
105 | .end = PM8607_IRQ_PEN, | 71 | /* Hook-switch press or release */ |
106 | .flags = IORESOURCE_IRQ, | 72 | {PM8607_IRQ_HOOK, PM8607_IRQ_HOOK, "hook", IORESOURCE_IRQ,}, |
107 | }, | 73 | /* Headset insertion or removal */ |
74 | {PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,}, | ||
75 | /* Audio short */ | ||
76 | {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,}, | ||
108 | }; | 77 | }; |
109 | 78 | ||
110 | static struct mfd_cell touch_devs[] = { | 79 | static struct resource battery_resources[] __initdata = { |
111 | { | 80 | {PM8607_IRQ_CC, PM8607_IRQ_CC, "columb counter", IORESOURCE_IRQ,}, |
112 | .name = "88pm860x-touch", | 81 | {PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery", IORESOURCE_IRQ,}, |
113 | .num_resources = 1, | ||
114 | .resources = &touch_resources[0], | ||
115 | }, | ||
116 | }; | 82 | }; |
117 | 83 | ||
118 | #define PM8607_REG_RESOURCE(_start, _end) \ | 84 | static struct resource charger_resources[] __initdata = { |
119 | { \ | 85 | {PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,}, |
120 | .start = PM8607_##_start, \ | 86 | {PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,}, |
121 | .end = PM8607_##_end, \ | 87 | {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout", IORESOURCE_IRQ,}, |
122 | .flags = IORESOURCE_IO, \ | 88 | {PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature", IORESOURCE_IRQ,}, |
123 | } | 89 | {PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,}, |
124 | 90 | {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, | |
125 | static struct resource power_supply_resources[] = { | ||
126 | { | ||
127 | .name = "88pm860x-power", | ||
128 | .start = PM8607_IRQ_CHG, | ||
129 | .end = PM8607_IRQ_CHG, | ||
130 | .flags = IORESOURCE_IRQ, | ||
131 | }, | ||
132 | }; | 91 | }; |
133 | 92 | ||
134 | static struct mfd_cell power_devs[] = { | 93 | static struct mfd_cell bk_devs[] __initdata = { |
135 | { | 94 | {"88pm860x-backlight", 0,}, |
136 | .name = "88pm860x-power", | 95 | {"88pm860x-backlight", 1,}, |
137 | .num_resources = 1, | 96 | {"88pm860x-backlight", 2,}, |
138 | .resources = &power_supply_resources[0], | ||
139 | .id = -1, | ||
140 | }, | ||
141 | }; | 97 | }; |
142 | 98 | ||
143 | static struct resource onkey_resources[] = { | 99 | static struct mfd_cell led_devs[] __initdata = { |
144 | { | 100 | {"88pm860x-led", 0,}, |
145 | .name = "88pm860x-onkey", | 101 | {"88pm860x-led", 1,}, |
146 | .start = PM8607_IRQ_ONKEY, | 102 | {"88pm860x-led", 2,}, |
147 | .end = PM8607_IRQ_ONKEY, | 103 | {"88pm860x-led", 3,}, |
148 | .flags = IORESOURCE_IRQ, | 104 | {"88pm860x-led", 4,}, |
149 | }, | 105 | {"88pm860x-led", 5,}, |
150 | }; | 106 | }; |
151 | 107 | ||
152 | static struct mfd_cell onkey_devs[] = { | 108 | static struct mfd_cell regulator_devs[] __initdata = { |
153 | { | 109 | {"88pm860x-regulator", 0,}, |
154 | .name = "88pm860x-onkey", | 110 | {"88pm860x-regulator", 1,}, |
155 | .num_resources = 1, | 111 | {"88pm860x-regulator", 2,}, |
156 | .resources = &onkey_resources[0], | 112 | {"88pm860x-regulator", 3,}, |
157 | .id = -1, | 113 | {"88pm860x-regulator", 4,}, |
158 | }, | 114 | {"88pm860x-regulator", 5,}, |
115 | {"88pm860x-regulator", 6,}, | ||
116 | {"88pm860x-regulator", 7,}, | ||
117 | {"88pm860x-regulator", 8,}, | ||
118 | {"88pm860x-regulator", 9,}, | ||
119 | {"88pm860x-regulator", 10,}, | ||
120 | {"88pm860x-regulator", 11,}, | ||
121 | {"88pm860x-regulator", 12,}, | ||
122 | {"88pm860x-regulator", 13,}, | ||
123 | {"88pm860x-regulator", 14,}, | ||
124 | {"88pm860x-regulator", 15,}, | ||
125 | {"88pm860x-regulator", 16,}, | ||
126 | {"88pm860x-regulator", 17,}, | ||
159 | }; | 127 | }; |
160 | 128 | ||
161 | static struct resource codec_resources[] = { | 129 | static struct mfd_cell touch_devs[] __initdata = { |
162 | { | 130 | {"88pm860x-touch", -1,}, |
163 | /* Headset microphone insertion or removal */ | ||
164 | .name = "micin", | ||
165 | .start = PM8607_IRQ_MICIN, | ||
166 | .end = PM8607_IRQ_MICIN, | ||
167 | .flags = IORESOURCE_IRQ, | ||
168 | }, { | ||
169 | /* Hook-switch press or release */ | ||
170 | .name = "hook", | ||
171 | .start = PM8607_IRQ_HOOK, | ||
172 | .end = PM8607_IRQ_HOOK, | ||
173 | .flags = IORESOURCE_IRQ, | ||
174 | }, { | ||
175 | /* Headset insertion or removal */ | ||
176 | .name = "headset", | ||
177 | .start = PM8607_IRQ_HEADSET, | ||
178 | .end = PM8607_IRQ_HEADSET, | ||
179 | .flags = IORESOURCE_IRQ, | ||
180 | }, { | ||
181 | /* Audio short */ | ||
182 | .name = "audio-short", | ||
183 | .start = PM8607_IRQ_AUDIO_SHORT, | ||
184 | .end = PM8607_IRQ_AUDIO_SHORT, | ||
185 | .flags = IORESOURCE_IRQ, | ||
186 | }, | ||
187 | }; | 131 | }; |
188 | 132 | ||
189 | static struct mfd_cell codec_devs[] = { | 133 | static struct mfd_cell onkey_devs[] __initdata = { |
190 | { | 134 | {"88pm860x-onkey", -1,}, |
191 | .name = "88pm860x-codec", | ||
192 | .num_resources = ARRAY_SIZE(codec_resources), | ||
193 | .resources = &codec_resources[0], | ||
194 | .id = -1, | ||
195 | }, | ||
196 | }; | 135 | }; |
197 | 136 | ||
198 | static struct resource regulator_resources[] = { | 137 | static struct mfd_cell codec_devs[] __initdata = { |
199 | PM8607_REG_RESOURCE(BUCK1, BUCK1), | 138 | {"88pm860x-codec", -1,}, |
200 | PM8607_REG_RESOURCE(BUCK2, BUCK2), | ||
201 | PM8607_REG_RESOURCE(BUCK3, BUCK3), | ||
202 | PM8607_REG_RESOURCE(LDO1, LDO1), | ||
203 | PM8607_REG_RESOURCE(LDO2, LDO2), | ||
204 | PM8607_REG_RESOURCE(LDO3, LDO3), | ||
205 | PM8607_REG_RESOURCE(LDO4, LDO4), | ||
206 | PM8607_REG_RESOURCE(LDO5, LDO5), | ||
207 | PM8607_REG_RESOURCE(LDO6, LDO6), | ||
208 | PM8607_REG_RESOURCE(LDO7, LDO7), | ||
209 | PM8607_REG_RESOURCE(LDO8, LDO8), | ||
210 | PM8607_REG_RESOURCE(LDO9, LDO9), | ||
211 | PM8607_REG_RESOURCE(LDO10, LDO10), | ||
212 | PM8607_REG_RESOURCE(LDO12, LDO12), | ||
213 | PM8607_REG_RESOURCE(VIBRATOR_SET, VIBRATOR_SET), | ||
214 | PM8607_REG_RESOURCE(LDO14, LDO14), | ||
215 | }; | 139 | }; |
216 | 140 | ||
217 | #define PM8607_REG_DEVS(_id) \ | 141 | static struct mfd_cell power_devs[] = { |
218 | { \ | 142 | {"88pm860x-battery", -1,}, |
219 | .name = "88pm860x-regulator", \ | 143 | {"88pm860x-charger", -1,}, |
220 | .num_resources = 1, \ | ||
221 | .resources = ®ulator_resources[PM8607_ID_##_id], \ | ||
222 | .id = PM8607_ID_##_id, \ | ||
223 | } | ||
224 | |||
225 | static struct mfd_cell regulator_devs[] = { | ||
226 | PM8607_REG_DEVS(BUCK1), | ||
227 | PM8607_REG_DEVS(BUCK2), | ||
228 | PM8607_REG_DEVS(BUCK3), | ||
229 | PM8607_REG_DEVS(LDO1), | ||
230 | PM8607_REG_DEVS(LDO2), | ||
231 | PM8607_REG_DEVS(LDO3), | ||
232 | PM8607_REG_DEVS(LDO4), | ||
233 | PM8607_REG_DEVS(LDO5), | ||
234 | PM8607_REG_DEVS(LDO6), | ||
235 | PM8607_REG_DEVS(LDO7), | ||
236 | PM8607_REG_DEVS(LDO8), | ||
237 | PM8607_REG_DEVS(LDO9), | ||
238 | PM8607_REG_DEVS(LDO10), | ||
239 | PM8607_REG_DEVS(LDO12), | ||
240 | PM8607_REG_DEVS(LDO13), | ||
241 | PM8607_REG_DEVS(LDO14), | ||
242 | }; | 144 | }; |
243 | 145 | ||
146 | static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)]; | ||
147 | static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)]; | ||
148 | static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)]; | ||
149 | static struct pm860x_touch_pdata touch_pdata; | ||
150 | static struct pm860x_power_pdata power_pdata; | ||
151 | |||
244 | struct pm860x_irq_data { | 152 | struct pm860x_irq_data { |
245 | int reg; | 153 | int reg; |
246 | int mask_reg; | 154 | int mask_reg; |
@@ -595,37 +503,212 @@ static void device_irq_exit(struct pm860x_chip *chip) | |||
595 | free_irq(chip->core_irq, chip); | 503 | free_irq(chip->core_irq, chip); |
596 | } | 504 | } |
597 | 505 | ||
598 | static void __devinit device_8606_init(struct pm860x_chip *chip, | 506 | static void __devinit device_bk_init(struct pm860x_chip *chip, |
599 | struct i2c_client *i2c, | 507 | struct i2c_client *i2c, |
600 | struct pm860x_platform_data *pdata) | 508 | struct pm860x_platform_data *pdata) |
601 | { | 509 | { |
602 | int ret; | 510 | int ret; |
511 | int i, j, id; | ||
512 | |||
513 | if ((pdata == NULL) || (pdata->backlight == NULL)) | ||
514 | return; | ||
515 | |||
516 | if (pdata->num_backlights > ARRAY_SIZE(bk_devs)) | ||
517 | pdata->num_backlights = ARRAY_SIZE(bk_devs); | ||
518 | |||
519 | for (i = 0; i < pdata->num_backlights; i++) { | ||
520 | memcpy(&bk_pdata[i], &pdata->backlight[i], | ||
521 | sizeof(struct pm860x_backlight_pdata)); | ||
522 | bk_devs[i].mfd_data = &bk_pdata[i]; | ||
523 | |||
524 | for (j = 0; j < ARRAY_SIZE(bk_devs); j++) { | ||
525 | id = bk_resources[j].start; | ||
526 | if (bk_pdata[i].flags != id) | ||
527 | continue; | ||
528 | |||
529 | bk_devs[i].num_resources = 1; | ||
530 | bk_devs[i].resources = &bk_resources[j]; | ||
531 | ret = mfd_add_devices(chip->dev, 0, | ||
532 | &bk_devs[i], 1, | ||
533 | &bk_resources[j], 0); | ||
534 | if (ret < 0) { | ||
535 | dev_err(chip->dev, "Failed to add " | ||
536 | "backlight subdev\n"); | ||
537 | return; | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | } | ||
603 | 542 | ||
604 | if (pdata && pdata->backlight) { | 543 | static void __devinit device_led_init(struct pm860x_chip *chip, |
605 | ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0], | 544 | struct i2c_client *i2c, |
606 | ARRAY_SIZE(backlight_devs), | 545 | struct pm860x_platform_data *pdata) |
607 | &backlight_resources[0], 0); | 546 | { |
608 | if (ret < 0) { | 547 | int ret; |
609 | dev_err(chip->dev, "Failed to add backlight " | 548 | int i, j, id; |
610 | "subdev\n"); | 549 | |
611 | goto out_dev; | 550 | if ((pdata == NULL) || (pdata->led == NULL)) |
551 | return; | ||
552 | |||
553 | if (pdata->num_leds > ARRAY_SIZE(led_devs)) | ||
554 | pdata->num_leds = ARRAY_SIZE(led_devs); | ||
555 | |||
556 | for (i = 0; i < pdata->num_leds; i++) { | ||
557 | memcpy(&led_pdata[i], &pdata->led[i], | ||
558 | sizeof(struct pm860x_led_pdata)); | ||
559 | led_devs[i].mfd_data = &led_pdata[i]; | ||
560 | |||
561 | for (j = 0; j < ARRAY_SIZE(led_devs); j++) { | ||
562 | id = led_resources[j].start; | ||
563 | if (led_pdata[i].flags != id) | ||
564 | continue; | ||
565 | |||
566 | led_devs[i].num_resources = 1; | ||
567 | led_devs[i].resources = &led_resources[j], | ||
568 | ret = mfd_add_devices(chip->dev, 0, | ||
569 | &led_devs[i], 1, | ||
570 | &led_resources[j], 0); | ||
571 | if (ret < 0) { | ||
572 | dev_err(chip->dev, "Failed to add " | ||
573 | "led subdev\n"); | ||
574 | return; | ||
575 | } | ||
612 | } | 576 | } |
613 | } | 577 | } |
578 | } | ||
614 | 579 | ||
615 | if (pdata && pdata->led) { | 580 | static void __devinit device_regulator_init(struct pm860x_chip *chip, |
616 | ret = mfd_add_devices(chip->dev, 0, &led_devs[0], | 581 | struct i2c_client *i2c, |
617 | ARRAY_SIZE(led_devs), | 582 | struct pm860x_platform_data *pdata) |
618 | &led_resources[0], 0); | 583 | { |
584 | struct regulator_init_data *initdata; | ||
585 | int ret; | ||
586 | int i, j; | ||
587 | |||
588 | if ((pdata == NULL) || (pdata->regulator == NULL)) | ||
589 | return; | ||
590 | |||
591 | if (pdata->num_regulators > ARRAY_SIZE(regulator_devs)) | ||
592 | pdata->num_regulators = ARRAY_SIZE(regulator_devs); | ||
593 | |||
594 | for (i = 0, j = -1; i < pdata->num_regulators; i++) { | ||
595 | initdata = &pdata->regulator[i]; | ||
596 | if (strstr(initdata->constraints.name, "BUCK")) { | ||
597 | sscanf(initdata->constraints.name, "BUCK%d", &j); | ||
598 | /* BUCK1 ~ BUCK3 */ | ||
599 | if ((j < 1) || (j > 3)) { | ||
600 | dev_err(chip->dev, "Failed to add constraint " | ||
601 | "(%s)\n", initdata->constraints.name); | ||
602 | goto out; | ||
603 | } | ||
604 | j = (j - 1) + PM8607_ID_BUCK1; | ||
605 | } | ||
606 | if (strstr(initdata->constraints.name, "LDO")) { | ||
607 | sscanf(initdata->constraints.name, "LDO%d", &j); | ||
608 | /* LDO1 ~ LDO15 */ | ||
609 | if ((j < 1) || (j > 15)) { | ||
610 | dev_err(chip->dev, "Failed to add constraint " | ||
611 | "(%s)\n", initdata->constraints.name); | ||
612 | goto out; | ||
613 | } | ||
614 | j = (j - 1) + PM8607_ID_LDO1; | ||
615 | } | ||
616 | if (j == -1) { | ||
617 | dev_err(chip->dev, "Failed to add constraint (%s)\n", | ||
618 | initdata->constraints.name); | ||
619 | goto out; | ||
620 | } | ||
621 | memcpy(®ulator_pdata[i], &pdata->regulator[i], | ||
622 | sizeof(struct regulator_init_data)); | ||
623 | regulator_devs[i].mfd_data = ®ulator_pdata[i]; | ||
624 | regulator_devs[i].num_resources = 1; | ||
625 | regulator_devs[i].resources = ®ulator_resources[j]; | ||
626 | |||
627 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, | ||
628 | ®ulator_resources[j], 0); | ||
619 | if (ret < 0) { | 629 | if (ret < 0) { |
620 | dev_err(chip->dev, "Failed to add led " | 630 | dev_err(chip->dev, "Failed to add regulator subdev\n"); |
621 | "subdev\n"); | 631 | goto out; |
622 | goto out_dev; | ||
623 | } | 632 | } |
624 | } | 633 | } |
634 | out: | ||
625 | return; | 635 | return; |
626 | out_dev: | 636 | } |
627 | mfd_remove_devices(chip->dev); | 637 | |
628 | device_irq_exit(chip); | 638 | static void __devinit device_touch_init(struct pm860x_chip *chip, |
639 | struct i2c_client *i2c, | ||
640 | struct pm860x_platform_data *pdata) | ||
641 | { | ||
642 | int ret; | ||
643 | |||
644 | if ((pdata == NULL) || (pdata->touch == NULL)) | ||
645 | return; | ||
646 | |||
647 | memcpy(&touch_pdata, pdata->touch, sizeof(struct pm860x_touch_pdata)); | ||
648 | touch_devs[0].mfd_data = &touch_pdata; | ||
649 | touch_devs[0].num_resources = ARRAY_SIZE(touch_resources); | ||
650 | touch_devs[0].resources = &touch_resources[0]; | ||
651 | ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], | ||
652 | ARRAY_SIZE(touch_devs), &touch_resources[0], | ||
653 | chip->irq_base); | ||
654 | if (ret < 0) | ||
655 | dev_err(chip->dev, "Failed to add touch subdev\n"); | ||
656 | } | ||
657 | |||
658 | static void __devinit device_power_init(struct pm860x_chip *chip, | ||
659 | struct i2c_client *i2c, | ||
660 | struct pm860x_platform_data *pdata) | ||
661 | { | ||
662 | int ret; | ||
663 | |||
664 | if ((pdata == NULL) || (pdata->power == NULL)) | ||
665 | return; | ||
666 | |||
667 | memcpy(&power_pdata, pdata->power, sizeof(struct pm860x_power_pdata)); | ||
668 | power_devs[0].mfd_data = &power_pdata; | ||
669 | power_devs[0].num_resources = ARRAY_SIZE(battery_resources); | ||
670 | power_devs[0].resources = &battery_resources[0], | ||
671 | ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, | ||
672 | &battery_resources[0], chip->irq_base); | ||
673 | if (ret < 0) | ||
674 | dev_err(chip->dev, "Failed to add battery subdev\n"); | ||
675 | |||
676 | power_devs[1].mfd_data = &power_pdata; | ||
677 | power_devs[1].num_resources = ARRAY_SIZE(charger_resources); | ||
678 | power_devs[1].resources = &charger_resources[0], | ||
679 | ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, | ||
680 | &charger_resources[0], chip->irq_base); | ||
681 | if (ret < 0) | ||
682 | dev_err(chip->dev, "Failed to add charger subdev\n"); | ||
683 | } | ||
684 | |||
685 | static void __devinit device_onkey_init(struct pm860x_chip *chip, | ||
686 | struct i2c_client *i2c, | ||
687 | struct pm860x_platform_data *pdata) | ||
688 | { | ||
689 | int ret; | ||
690 | |||
691 | onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources); | ||
692 | onkey_devs[0].resources = &onkey_resources[0], | ||
693 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], | ||
694 | ARRAY_SIZE(onkey_devs), &onkey_resources[0], | ||
695 | chip->irq_base); | ||
696 | if (ret < 0) | ||
697 | dev_err(chip->dev, "Failed to add onkey subdev\n"); | ||
698 | } | ||
699 | |||
700 | static void __devinit device_codec_init(struct pm860x_chip *chip, | ||
701 | struct i2c_client *i2c, | ||
702 | struct pm860x_platform_data *pdata) | ||
703 | { | ||
704 | int ret; | ||
705 | |||
706 | codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); | ||
707 | codec_devs[0].resources = &codec_resources[0], | ||
708 | ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], | ||
709 | ARRAY_SIZE(codec_devs), &codec_resources[0], 0); | ||
710 | if (ret < 0) | ||
711 | dev_err(chip->dev, "Failed to add codec subdev\n"); | ||
629 | } | 712 | } |
630 | 713 | ||
631 | static void __devinit device_8607_init(struct pm860x_chip *chip, | 714 | static void __devinit device_8607_init(struct pm860x_chip *chip, |
@@ -683,55 +766,11 @@ static void __devinit device_8607_init(struct pm860x_chip *chip, | |||
683 | if (ret < 0) | 766 | if (ret < 0) |
684 | goto out; | 767 | goto out; |
685 | 768 | ||
686 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], | 769 | device_regulator_init(chip, i2c, pdata); |
687 | ARRAY_SIZE(regulator_devs), | 770 | device_onkey_init(chip, i2c, pdata); |
688 | ®ulator_resources[0], 0); | 771 | device_touch_init(chip, i2c, pdata); |
689 | if (ret < 0) { | 772 | device_power_init(chip, i2c, pdata); |
690 | dev_err(chip->dev, "Failed to add regulator subdev\n"); | 773 | device_codec_init(chip, i2c, pdata); |
691 | goto out_dev; | ||
692 | } | ||
693 | |||
694 | if (pdata && pdata->touch) { | ||
695 | ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], | ||
696 | ARRAY_SIZE(touch_devs), | ||
697 | &touch_resources[0], 0); | ||
698 | if (ret < 0) { | ||
699 | dev_err(chip->dev, "Failed to add touch " | ||
700 | "subdev\n"); | ||
701 | goto out_dev; | ||
702 | } | ||
703 | } | ||
704 | |||
705 | if (pdata && pdata->power) { | ||
706 | ret = mfd_add_devices(chip->dev, 0, &power_devs[0], | ||
707 | ARRAY_SIZE(power_devs), | ||
708 | &power_supply_resources[0], 0); | ||
709 | if (ret < 0) { | ||
710 | dev_err(chip->dev, "Failed to add power supply " | ||
711 | "subdev\n"); | ||
712 | goto out_dev; | ||
713 | } | ||
714 | } | ||
715 | |||
716 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], | ||
717 | ARRAY_SIZE(onkey_devs), | ||
718 | &onkey_resources[0], 0); | ||
719 | if (ret < 0) { | ||
720 | dev_err(chip->dev, "Failed to add onkey subdev\n"); | ||
721 | goto out_dev; | ||
722 | } | ||
723 | |||
724 | ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], | ||
725 | ARRAY_SIZE(codec_devs), | ||
726 | &codec_resources[0], 0); | ||
727 | if (ret < 0) { | ||
728 | dev_err(chip->dev, "Failed to add codec subdev\n"); | ||
729 | goto out_dev; | ||
730 | } | ||
731 | return; | ||
732 | out_dev: | ||
733 | mfd_remove_devices(chip->dev); | ||
734 | device_irq_exit(chip); | ||
735 | out: | 774 | out: |
736 | return; | 775 | return; |
737 | } | 776 | } |
@@ -743,7 +782,8 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip, | |||
743 | 782 | ||
744 | switch (chip->id) { | 783 | switch (chip->id) { |
745 | case CHIP_PM8606: | 784 | case CHIP_PM8606: |
746 | device_8606_init(chip, chip->client, pdata); | 785 | device_bk_init(chip, chip->client, pdata); |
786 | device_led_init(chip, chip->client, pdata); | ||
747 | break; | 787 | break; |
748 | case CHIP_PM8607: | 788 | case CHIP_PM8607: |
749 | device_8607_init(chip, chip->client, pdata); | 789 | device_8607_init(chip, chip->client, pdata); |
@@ -753,7 +793,8 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip, | |||
753 | if (chip->companion) { | 793 | if (chip->companion) { |
754 | switch (chip->id) { | 794 | switch (chip->id) { |
755 | case CHIP_PM8607: | 795 | case CHIP_PM8607: |
756 | device_8606_init(chip, chip->companion, pdata); | 796 | device_bk_init(chip, chip->companion, pdata); |
797 | device_led_init(chip, chip->companion, pdata); | ||
757 | break; | 798 | break; |
758 | case CHIP_PM8606: | 799 | case CHIP_PM8606: |
759 | device_8607_init(chip, chip->companion, pdata); | 800 | device_8607_init(chip, chip->companion, pdata); |