diff options
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/Kconfig | 16 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 4 | ||||
-rw-r--r-- | drivers/mfd/da9052-core.c | 690 | ||||
-rw-r--r-- | drivers/mfd/da9052-i2c.c | 140 |
4 files changed, 850 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index f1391c21ef26..baced42c8572 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -328,6 +328,22 @@ config PMIC_DA903X | |||
328 | individual components like LCD backlight, voltage regulators, | 328 | individual components like LCD backlight, voltage regulators, |
329 | LEDs and battery-charger under the corresponding menus. | 329 | LEDs and battery-charger under the corresponding menus. |
330 | 330 | ||
331 | config PMIC_DA9052 | ||
332 | bool | ||
333 | select MFD_CORE | ||
334 | |||
335 | config MFD_DA9052_I2C | ||
336 | bool "Support Dialog Semiconductor DA9052/53 PMIC variants with I2C" | ||
337 | select REGMAP_I2C | ||
338 | select REGMAP_IRQ | ||
339 | select PMIC_DA9052 | ||
340 | depends on I2C=y | ||
341 | help | ||
342 | Support for the Dialog Semiconductor DA9052 PMIC | ||
343 | when controlled using I2C. This driver provides common support | ||
344 | for accessing the device, additional drivers must be enabled in | ||
345 | order to use the functionality of the device. | ||
346 | |||
331 | config PMIC_ADP5520 | 347 | config PMIC_ADP5520 |
332 | bool "Analog Devices ADP5520/01 MFD PMIC Core Support" | 348 | bool "Analog Devices ADP5520/01 MFD PMIC Core Support" |
333 | depends on I2C=y | 349 | depends on I2C=y |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index b2292eb75242..484f209f41e4 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -67,6 +67,10 @@ endif | |||
67 | obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o | 67 | obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o |
68 | 68 | ||
69 | obj-$(CONFIG_PMIC_DA903X) += da903x.o | 69 | obj-$(CONFIG_PMIC_DA903X) += da903x.o |
70 | |||
71 | obj-$(CONFIG_PMIC_DA9052) += da9052-core.o | ||
72 | obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o | ||
73 | |||
70 | max8925-objs := max8925-core.o max8925-i2c.o | 74 | max8925-objs := max8925-core.o max8925-i2c.o |
71 | obj-$(CONFIG_MFD_MAX8925) += max8925.o | 75 | obj-$(CONFIG_MFD_MAX8925) += max8925.o |
72 | obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o | 76 | obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o |
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c new file mode 100644 index 000000000000..a7c115ca56c8 --- /dev/null +++ b/drivers/mfd/da9052-core.c | |||
@@ -0,0 +1,690 @@ | |||
1 | /* | ||
2 | * Device access for Dialog DA9052 PMICs. | ||
3 | * | ||
4 | * Copyright(c) 2011 Dialog Semiconductor Ltd. | ||
5 | * | ||
6 | * Author: David Dajun Chen <dchen@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/mfd/core.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/module.h> | ||
23 | |||
24 | #include <linux/mfd/da9052/da9052.h> | ||
25 | #include <linux/mfd/da9052/pdata.h> | ||
26 | #include <linux/mfd/da9052/reg.h> | ||
27 | |||
28 | #define DA9052_NUM_IRQ_REGS 4 | ||
29 | #define DA9052_IRQ_MASK_POS_1 0x01 | ||
30 | #define DA9052_IRQ_MASK_POS_2 0x02 | ||
31 | #define DA9052_IRQ_MASK_POS_3 0x04 | ||
32 | #define DA9052_IRQ_MASK_POS_4 0x08 | ||
33 | #define DA9052_IRQ_MASK_POS_5 0x10 | ||
34 | #define DA9052_IRQ_MASK_POS_6 0x20 | ||
35 | #define DA9052_IRQ_MASK_POS_7 0x40 | ||
36 | #define DA9052_IRQ_MASK_POS_8 0x80 | ||
37 | |||
38 | static bool da9052_reg_readable(struct device *dev, unsigned int reg) | ||
39 | { | ||
40 | switch (reg) { | ||
41 | case DA9052_PAGE0_CON_REG: | ||
42 | case DA9052_STATUS_A_REG: | ||
43 | case DA9052_STATUS_B_REG: | ||
44 | case DA9052_STATUS_C_REG: | ||
45 | case DA9052_STATUS_D_REG: | ||
46 | case DA9052_EVENT_A_REG: | ||
47 | case DA9052_EVENT_B_REG: | ||
48 | case DA9052_EVENT_C_REG: | ||
49 | case DA9052_EVENT_D_REG: | ||
50 | case DA9052_FAULTLOG_REG: | ||
51 | case DA9052_IRQ_MASK_A_REG: | ||
52 | case DA9052_IRQ_MASK_B_REG: | ||
53 | case DA9052_IRQ_MASK_C_REG: | ||
54 | case DA9052_IRQ_MASK_D_REG: | ||
55 | case DA9052_CONTROL_A_REG: | ||
56 | case DA9052_CONTROL_B_REG: | ||
57 | case DA9052_CONTROL_C_REG: | ||
58 | case DA9052_CONTROL_D_REG: | ||
59 | case DA9052_PDDIS_REG: | ||
60 | case DA9052_INTERFACE_REG: | ||
61 | case DA9052_RESET_REG: | ||
62 | case DA9052_GPIO_0_1_REG: | ||
63 | case DA9052_GPIO_2_3_REG: | ||
64 | case DA9052_GPIO_4_5_REG: | ||
65 | case DA9052_GPIO_6_7_REG: | ||
66 | case DA9052_GPIO_14_15_REG: | ||
67 | case DA9052_ID_0_1_REG: | ||
68 | case DA9052_ID_2_3_REG: | ||
69 | case DA9052_ID_4_5_REG: | ||
70 | case DA9052_ID_6_7_REG: | ||
71 | case DA9052_ID_8_9_REG: | ||
72 | case DA9052_ID_10_11_REG: | ||
73 | case DA9052_ID_12_13_REG: | ||
74 | case DA9052_ID_14_15_REG: | ||
75 | case DA9052_ID_16_17_REG: | ||
76 | case DA9052_ID_18_19_REG: | ||
77 | case DA9052_ID_20_21_REG: | ||
78 | case DA9052_SEQ_STATUS_REG: | ||
79 | case DA9052_SEQ_A_REG: | ||
80 | case DA9052_SEQ_B_REG: | ||
81 | case DA9052_SEQ_TIMER_REG: | ||
82 | case DA9052_BUCKA_REG: | ||
83 | case DA9052_BUCKB_REG: | ||
84 | case DA9052_BUCKCORE_REG: | ||
85 | case DA9052_BUCKPRO_REG: | ||
86 | case DA9052_BUCKMEM_REG: | ||
87 | case DA9052_BUCKPERI_REG: | ||
88 | case DA9052_LDO1_REG: | ||
89 | case DA9052_LDO2_REG: | ||
90 | case DA9052_LDO3_REG: | ||
91 | case DA9052_LDO4_REG: | ||
92 | case DA9052_LDO5_REG: | ||
93 | case DA9052_LDO6_REG: | ||
94 | case DA9052_LDO7_REG: | ||
95 | case DA9052_LDO8_REG: | ||
96 | case DA9052_LDO9_REG: | ||
97 | case DA9052_LDO10_REG: | ||
98 | case DA9052_SUPPLY_REG: | ||
99 | case DA9052_PULLDOWN_REG: | ||
100 | case DA9052_CHGBUCK_REG: | ||
101 | case DA9052_WAITCONT_REG: | ||
102 | case DA9052_ISET_REG: | ||
103 | case DA9052_BATCHG_REG: | ||
104 | case DA9052_CHG_CONT_REG: | ||
105 | case DA9052_INPUT_CONT_REG: | ||
106 | case DA9052_CHG_TIME_REG: | ||
107 | case DA9052_BBAT_CONT_REG: | ||
108 | case DA9052_BOOST_REG: | ||
109 | case DA9052_LED_CONT_REG: | ||
110 | case DA9052_LEDMIN123_REG: | ||
111 | case DA9052_LED1_CONF_REG: | ||
112 | case DA9052_LED2_CONF_REG: | ||
113 | case DA9052_LED3_CONF_REG: | ||
114 | case DA9052_LED1CONT_REG: | ||
115 | case DA9052_LED2CONT_REG: | ||
116 | case DA9052_LED3CONT_REG: | ||
117 | case DA9052_LED_CONT_4_REG: | ||
118 | case DA9052_LED_CONT_5_REG: | ||
119 | case DA9052_ADC_MAN_REG: | ||
120 | case DA9052_ADC_CONT_REG: | ||
121 | case DA9052_ADC_RES_L_REG: | ||
122 | case DA9052_ADC_RES_H_REG: | ||
123 | case DA9052_VDD_RES_REG: | ||
124 | case DA9052_VDD_MON_REG: | ||
125 | case DA9052_ICHG_AV_REG: | ||
126 | case DA9052_ICHG_THD_REG: | ||
127 | case DA9052_ICHG_END_REG: | ||
128 | case DA9052_TBAT_RES_REG: | ||
129 | case DA9052_TBAT_HIGHP_REG: | ||
130 | case DA9052_TBAT_HIGHN_REG: | ||
131 | case DA9052_TBAT_LOW_REG: | ||
132 | case DA9052_T_OFFSET_REG: | ||
133 | case DA9052_ADCIN4_RES_REG: | ||
134 | case DA9052_AUTO4_HIGH_REG: | ||
135 | case DA9052_AUTO4_LOW_REG: | ||
136 | case DA9052_ADCIN5_RES_REG: | ||
137 | case DA9052_AUTO5_HIGH_REG: | ||
138 | case DA9052_AUTO5_LOW_REG: | ||
139 | case DA9052_ADCIN6_RES_REG: | ||
140 | case DA9052_AUTO6_HIGH_REG: | ||
141 | case DA9052_AUTO6_LOW_REG: | ||
142 | case DA9052_TJUNC_RES_REG: | ||
143 | case DA9052_TSI_CONT_A_REG: | ||
144 | case DA9052_TSI_CONT_B_REG: | ||
145 | case DA9052_TSI_X_MSB_REG: | ||
146 | case DA9052_TSI_Y_MSB_REG: | ||
147 | case DA9052_TSI_LSB_REG: | ||
148 | case DA9052_TSI_Z_MSB_REG: | ||
149 | case DA9052_COUNT_S_REG: | ||
150 | case DA9052_COUNT_MI_REG: | ||
151 | case DA9052_COUNT_H_REG: | ||
152 | case DA9052_COUNT_D_REG: | ||
153 | case DA9052_COUNT_MO_REG: | ||
154 | case DA9052_COUNT_Y_REG: | ||
155 | case DA9052_ALARM_MI_REG: | ||
156 | case DA9052_ALARM_H_REG: | ||
157 | case DA9052_ALARM_D_REG: | ||
158 | case DA9052_ALARM_MO_REG: | ||
159 | case DA9052_ALARM_Y_REG: | ||
160 | case DA9052_SECOND_A_REG: | ||
161 | case DA9052_SECOND_B_REG: | ||
162 | case DA9052_SECOND_C_REG: | ||
163 | case DA9052_SECOND_D_REG: | ||
164 | case DA9052_PAGE1_CON_REG: | ||
165 | return true; | ||
166 | default: | ||
167 | return false; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static bool da9052_reg_writeable(struct device *dev, unsigned int reg) | ||
172 | { | ||
173 | switch (reg) { | ||
174 | case DA9052_PAGE0_CON_REG: | ||
175 | case DA9052_IRQ_MASK_A_REG: | ||
176 | case DA9052_IRQ_MASK_B_REG: | ||
177 | case DA9052_IRQ_MASK_C_REG: | ||
178 | case DA9052_IRQ_MASK_D_REG: | ||
179 | case DA9052_CONTROL_A_REG: | ||
180 | case DA9052_CONTROL_B_REG: | ||
181 | case DA9052_CONTROL_C_REG: | ||
182 | case DA9052_CONTROL_D_REG: | ||
183 | case DA9052_PDDIS_REG: | ||
184 | case DA9052_RESET_REG: | ||
185 | case DA9052_GPIO_0_1_REG: | ||
186 | case DA9052_GPIO_2_3_REG: | ||
187 | case DA9052_GPIO_4_5_REG: | ||
188 | case DA9052_GPIO_6_7_REG: | ||
189 | case DA9052_GPIO_14_15_REG: | ||
190 | case DA9052_ID_0_1_REG: | ||
191 | case DA9052_ID_2_3_REG: | ||
192 | case DA9052_ID_4_5_REG: | ||
193 | case DA9052_ID_6_7_REG: | ||
194 | case DA9052_ID_8_9_REG: | ||
195 | case DA9052_ID_10_11_REG: | ||
196 | case DA9052_ID_12_13_REG: | ||
197 | case DA9052_ID_14_15_REG: | ||
198 | case DA9052_ID_16_17_REG: | ||
199 | case DA9052_ID_18_19_REG: | ||
200 | case DA9052_ID_20_21_REG: | ||
201 | case DA9052_SEQ_STATUS_REG: | ||
202 | case DA9052_SEQ_A_REG: | ||
203 | case DA9052_SEQ_B_REG: | ||
204 | case DA9052_SEQ_TIMER_REG: | ||
205 | case DA9052_BUCKA_REG: | ||
206 | case DA9052_BUCKB_REG: | ||
207 | case DA9052_BUCKCORE_REG: | ||
208 | case DA9052_BUCKPRO_REG: | ||
209 | case DA9052_BUCKMEM_REG: | ||
210 | case DA9052_BUCKPERI_REG: | ||
211 | case DA9052_LDO1_REG: | ||
212 | case DA9052_LDO2_REG: | ||
213 | case DA9052_LDO3_REG: | ||
214 | case DA9052_LDO4_REG: | ||
215 | case DA9052_LDO5_REG: | ||
216 | case DA9052_LDO6_REG: | ||
217 | case DA9052_LDO7_REG: | ||
218 | case DA9052_LDO8_REG: | ||
219 | case DA9052_LDO9_REG: | ||
220 | case DA9052_LDO10_REG: | ||
221 | case DA9052_SUPPLY_REG: | ||
222 | case DA9052_PULLDOWN_REG: | ||
223 | case DA9052_CHGBUCK_REG: | ||
224 | case DA9052_WAITCONT_REG: | ||
225 | case DA9052_ISET_REG: | ||
226 | case DA9052_BATCHG_REG: | ||
227 | case DA9052_CHG_CONT_REG: | ||
228 | case DA9052_INPUT_CONT_REG: | ||
229 | case DA9052_BBAT_CONT_REG: | ||
230 | case DA9052_BOOST_REG: | ||
231 | case DA9052_LED_CONT_REG: | ||
232 | case DA9052_LEDMIN123_REG: | ||
233 | case DA9052_LED1_CONF_REG: | ||
234 | case DA9052_LED2_CONF_REG: | ||
235 | case DA9052_LED3_CONF_REG: | ||
236 | case DA9052_LED1CONT_REG: | ||
237 | case DA9052_LED2CONT_REG: | ||
238 | case DA9052_LED3CONT_REG: | ||
239 | case DA9052_LED_CONT_4_REG: | ||
240 | case DA9052_LED_CONT_5_REG: | ||
241 | case DA9052_ADC_MAN_REG: | ||
242 | case DA9052_ADC_CONT_REG: | ||
243 | case DA9052_ADC_RES_L_REG: | ||
244 | case DA9052_ADC_RES_H_REG: | ||
245 | case DA9052_VDD_RES_REG: | ||
246 | case DA9052_VDD_MON_REG: | ||
247 | case DA9052_ICHG_THD_REG: | ||
248 | case DA9052_ICHG_END_REG: | ||
249 | case DA9052_TBAT_HIGHP_REG: | ||
250 | case DA9052_TBAT_HIGHN_REG: | ||
251 | case DA9052_TBAT_LOW_REG: | ||
252 | case DA9052_T_OFFSET_REG: | ||
253 | case DA9052_AUTO4_HIGH_REG: | ||
254 | case DA9052_AUTO4_LOW_REG: | ||
255 | case DA9052_AUTO5_HIGH_REG: | ||
256 | case DA9052_AUTO5_LOW_REG: | ||
257 | case DA9052_AUTO6_HIGH_REG: | ||
258 | case DA9052_AUTO6_LOW_REG: | ||
259 | case DA9052_TSI_CONT_A_REG: | ||
260 | case DA9052_TSI_CONT_B_REG: | ||
261 | case DA9052_COUNT_S_REG: | ||
262 | case DA9052_COUNT_MI_REG: | ||
263 | case DA9052_COUNT_H_REG: | ||
264 | case DA9052_COUNT_D_REG: | ||
265 | case DA9052_COUNT_MO_REG: | ||
266 | case DA9052_COUNT_Y_REG: | ||
267 | case DA9052_ALARM_MI_REG: | ||
268 | case DA9052_ALARM_H_REG: | ||
269 | case DA9052_ALARM_D_REG: | ||
270 | case DA9052_ALARM_MO_REG: | ||
271 | case DA9052_ALARM_Y_REG: | ||
272 | case DA9052_PAGE1_CON_REG: | ||
273 | return true; | ||
274 | default: | ||
275 | return false; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | static bool da9052_reg_volatile(struct device *dev, unsigned int reg) | ||
280 | { | ||
281 | switch (reg) { | ||
282 | case DA9052_STATUS_A_REG: | ||
283 | case DA9052_STATUS_B_REG: | ||
284 | case DA9052_STATUS_C_REG: | ||
285 | case DA9052_STATUS_D_REG: | ||
286 | case DA9052_EVENT_A_REG: | ||
287 | case DA9052_EVENT_B_REG: | ||
288 | case DA9052_EVENT_C_REG: | ||
289 | case DA9052_EVENT_D_REG: | ||
290 | case DA9052_FAULTLOG_REG: | ||
291 | case DA9052_CHG_TIME_REG: | ||
292 | case DA9052_ADC_RES_L_REG: | ||
293 | case DA9052_ADC_RES_H_REG: | ||
294 | case DA9052_VDD_RES_REG: | ||
295 | case DA9052_ICHG_AV_REG: | ||
296 | case DA9052_TBAT_RES_REG: | ||
297 | case DA9052_ADCIN4_RES_REG: | ||
298 | case DA9052_ADCIN5_RES_REG: | ||
299 | case DA9052_ADCIN6_RES_REG: | ||
300 | case DA9052_TJUNC_RES_REG: | ||
301 | case DA9052_TSI_X_MSB_REG: | ||
302 | case DA9052_TSI_Y_MSB_REG: | ||
303 | case DA9052_TSI_LSB_REG: | ||
304 | case DA9052_TSI_Z_MSB_REG: | ||
305 | case DA9052_COUNT_S_REG: | ||
306 | case DA9052_COUNT_MI_REG: | ||
307 | case DA9052_COUNT_H_REG: | ||
308 | case DA9052_COUNT_D_REG: | ||
309 | case DA9052_COUNT_MO_REG: | ||
310 | case DA9052_COUNT_Y_REG: | ||
311 | case DA9052_ALARM_MI_REG: | ||
312 | return true; | ||
313 | default: | ||
314 | return false; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | static struct resource da9052_rtc_resource = { | ||
319 | .name = "ALM", | ||
320 | .start = DA9052_IRQ_ALARM, | ||
321 | .end = DA9052_IRQ_ALARM, | ||
322 | .flags = IORESOURCE_IRQ, | ||
323 | }; | ||
324 | |||
325 | static struct resource da9052_onkey_resource = { | ||
326 | .name = "ONKEY", | ||
327 | .start = DA9052_IRQ_NONKEY, | ||
328 | .end = DA9052_IRQ_NONKEY, | ||
329 | .flags = IORESOURCE_IRQ, | ||
330 | }; | ||
331 | |||
332 | static struct resource da9052_bat_resources[] = { | ||
333 | { | ||
334 | .name = "BATT TEMP", | ||
335 | .start = DA9052_IRQ_TBAT, | ||
336 | .end = DA9052_IRQ_TBAT, | ||
337 | .flags = IORESOURCE_IRQ, | ||
338 | }, | ||
339 | { | ||
340 | .name = "DCIN DET", | ||
341 | .start = DA9052_IRQ_DCIN, | ||
342 | .end = DA9052_IRQ_DCIN, | ||
343 | .flags = IORESOURCE_IRQ, | ||
344 | }, | ||
345 | { | ||
346 | .name = "DCIN REM", | ||
347 | .start = DA9052_IRQ_DCINREM, | ||
348 | .end = DA9052_IRQ_DCINREM, | ||
349 | .flags = IORESOURCE_IRQ, | ||
350 | }, | ||
351 | { | ||
352 | .name = "VBUS DET", | ||
353 | .start = DA9052_IRQ_VBUS, | ||
354 | .end = DA9052_IRQ_VBUS, | ||
355 | .flags = IORESOURCE_IRQ, | ||
356 | }, | ||
357 | { | ||
358 | .name = "VBUS REM", | ||
359 | .start = DA9052_IRQ_VBUSREM, | ||
360 | .end = DA9052_IRQ_VBUSREM, | ||
361 | .flags = IORESOURCE_IRQ, | ||
362 | }, | ||
363 | { | ||
364 | .name = "CHG END", | ||
365 | .start = DA9052_IRQ_CHGEND, | ||
366 | .end = DA9052_IRQ_CHGEND, | ||
367 | .flags = IORESOURCE_IRQ, | ||
368 | }, | ||
369 | }; | ||
370 | |||
371 | static struct resource da9052_tsi_resources[] = { | ||
372 | { | ||
373 | .name = "PENDWN", | ||
374 | .start = DA9052_IRQ_PENDOWN, | ||
375 | .end = DA9052_IRQ_PENDOWN, | ||
376 | .flags = IORESOURCE_IRQ, | ||
377 | }, | ||
378 | { | ||
379 | .name = "TSIRDY", | ||
380 | .start = DA9052_IRQ_TSIREADY, | ||
381 | .end = DA9052_IRQ_TSIREADY, | ||
382 | .flags = IORESOURCE_IRQ, | ||
383 | }, | ||
384 | }; | ||
385 | |||
386 | static struct mfd_cell __initdata da9052_subdev_info[] = { | ||
387 | { | ||
388 | .name = "da9052-regulator", | ||
389 | .id = 1, | ||
390 | }, | ||
391 | { | ||
392 | .name = "da9052-regulator", | ||
393 | .id = 2, | ||
394 | }, | ||
395 | { | ||
396 | .name = "da9052-regulator", | ||
397 | .id = 3, | ||
398 | }, | ||
399 | { | ||
400 | .name = "da9052-regulator", | ||
401 | .id = 4, | ||
402 | }, | ||
403 | { | ||
404 | .name = "da9052-regulator", | ||
405 | .id = 5, | ||
406 | }, | ||
407 | { | ||
408 | .name = "da9052-regulator", | ||
409 | .id = 6, | ||
410 | }, | ||
411 | { | ||
412 | .name = "da9052-regulator", | ||
413 | .id = 7, | ||
414 | }, | ||
415 | { | ||
416 | .name = "da9052-regulator", | ||
417 | .id = 8, | ||
418 | }, | ||
419 | { | ||
420 | .name = "da9052-regulator", | ||
421 | .id = 9, | ||
422 | }, | ||
423 | { | ||
424 | .name = "da9052-regulator", | ||
425 | .id = 10, | ||
426 | }, | ||
427 | { | ||
428 | .name = "da9052-regulator", | ||
429 | .id = 11, | ||
430 | }, | ||
431 | { | ||
432 | .name = "da9052-regulator", | ||
433 | .id = 12, | ||
434 | }, | ||
435 | { | ||
436 | .name = "da9052-regulator", | ||
437 | .id = 13, | ||
438 | }, | ||
439 | { | ||
440 | .name = "da9052-regulator", | ||
441 | .id = 14, | ||
442 | }, | ||
443 | { | ||
444 | .name = "da9052-onkey", | ||
445 | .resources = &da9052_onkey_resource, | ||
446 | .num_resources = 1, | ||
447 | }, | ||
448 | { | ||
449 | .name = "da9052-rtc", | ||
450 | .resources = &da9052_rtc_resource, | ||
451 | .num_resources = 1, | ||
452 | }, | ||
453 | { | ||
454 | .name = "da9052-gpio", | ||
455 | }, | ||
456 | { | ||
457 | .name = "da9052-hwmon", | ||
458 | }, | ||
459 | { | ||
460 | .name = "da9052-leds", | ||
461 | }, | ||
462 | { | ||
463 | .name = "da9052-wled1", | ||
464 | }, | ||
465 | { | ||
466 | .name = "da9052-wled2", | ||
467 | }, | ||
468 | { | ||
469 | .name = "da9052-wled3", | ||
470 | }, | ||
471 | { | ||
472 | .name = "da9052-tsi", | ||
473 | .resources = da9052_tsi_resources, | ||
474 | .num_resources = ARRAY_SIZE(da9052_tsi_resources), | ||
475 | }, | ||
476 | { | ||
477 | .name = "da9052-bat", | ||
478 | .resources = da9052_bat_resources, | ||
479 | .num_resources = ARRAY_SIZE(da9052_bat_resources), | ||
480 | }, | ||
481 | { | ||
482 | .name = "da9052-watchdog", | ||
483 | }, | ||
484 | }; | ||
485 | |||
486 | static struct regmap_irq da9052_irqs[] = { | ||
487 | [DA9052_IRQ_DCIN] = { | ||
488 | .reg_offset = 0, | ||
489 | .mask = DA9052_IRQ_MASK_POS_1, | ||
490 | }, | ||
491 | [DA9052_IRQ_VBUS] = { | ||
492 | .reg_offset = 0, | ||
493 | .mask = DA9052_IRQ_MASK_POS_2, | ||
494 | }, | ||
495 | [DA9052_IRQ_DCINREM] = { | ||
496 | .reg_offset = 0, | ||
497 | .mask = DA9052_IRQ_MASK_POS_3, | ||
498 | }, | ||
499 | [DA9052_IRQ_VBUSREM] = { | ||
500 | .reg_offset = 0, | ||
501 | .mask = DA9052_IRQ_MASK_POS_4, | ||
502 | }, | ||
503 | [DA9052_IRQ_VDDLOW] = { | ||
504 | .reg_offset = 0, | ||
505 | .mask = DA9052_IRQ_MASK_POS_5, | ||
506 | }, | ||
507 | [DA9052_IRQ_ALARM] = { | ||
508 | .reg_offset = 0, | ||
509 | .mask = DA9052_IRQ_MASK_POS_6, | ||
510 | }, | ||
511 | [DA9052_IRQ_SEQRDY] = { | ||
512 | .reg_offset = 0, | ||
513 | .mask = DA9052_IRQ_MASK_POS_7, | ||
514 | }, | ||
515 | [DA9052_IRQ_COMP1V2] = { | ||
516 | .reg_offset = 0, | ||
517 | .mask = DA9052_IRQ_MASK_POS_8, | ||
518 | }, | ||
519 | [DA9052_IRQ_NONKEY] = { | ||
520 | .reg_offset = 1, | ||
521 | .mask = DA9052_IRQ_MASK_POS_1, | ||
522 | }, | ||
523 | [DA9052_IRQ_IDFLOAT] = { | ||
524 | .reg_offset = 1, | ||
525 | .mask = DA9052_IRQ_MASK_POS_2, | ||
526 | }, | ||
527 | [DA9052_IRQ_IDGND] = { | ||
528 | .reg_offset = 1, | ||
529 | .mask = DA9052_IRQ_MASK_POS_3, | ||
530 | }, | ||
531 | [DA9052_IRQ_CHGEND] = { | ||
532 | .reg_offset = 1, | ||
533 | .mask = DA9052_IRQ_MASK_POS_4, | ||
534 | }, | ||
535 | [DA9052_IRQ_TBAT] = { | ||
536 | .reg_offset = 1, | ||
537 | .mask = DA9052_IRQ_MASK_POS_5, | ||
538 | }, | ||
539 | [DA9052_IRQ_ADC_EOM] = { | ||
540 | .reg_offset = 1, | ||
541 | .mask = DA9052_IRQ_MASK_POS_6, | ||
542 | }, | ||
543 | [DA9052_IRQ_PENDOWN] = { | ||
544 | .reg_offset = 1, | ||
545 | .mask = DA9052_IRQ_MASK_POS_7, | ||
546 | }, | ||
547 | [DA9052_IRQ_TSIREADY] = { | ||
548 | .reg_offset = 1, | ||
549 | .mask = DA9052_IRQ_MASK_POS_8, | ||
550 | }, | ||
551 | [DA9052_IRQ_GPI0] = { | ||
552 | .reg_offset = 2, | ||
553 | .mask = DA9052_IRQ_MASK_POS_1, | ||
554 | }, | ||
555 | [DA9052_IRQ_GPI1] = { | ||
556 | .reg_offset = 2, | ||
557 | .mask = DA9052_IRQ_MASK_POS_2, | ||
558 | }, | ||
559 | [DA9052_IRQ_GPI2] = { | ||
560 | .reg_offset = 2, | ||
561 | .mask = DA9052_IRQ_MASK_POS_3, | ||
562 | }, | ||
563 | [DA9052_IRQ_GPI3] = { | ||
564 | .reg_offset = 2, | ||
565 | .mask = DA9052_IRQ_MASK_POS_4, | ||
566 | }, | ||
567 | [DA9052_IRQ_GPI4] = { | ||
568 | .reg_offset = 2, | ||
569 | .mask = DA9052_IRQ_MASK_POS_5, | ||
570 | }, | ||
571 | [DA9052_IRQ_GPI5] = { | ||
572 | .reg_offset = 2, | ||
573 | .mask = DA9052_IRQ_MASK_POS_6, | ||
574 | }, | ||
575 | [DA9052_IRQ_GPI6] = { | ||
576 | .reg_offset = 2, | ||
577 | .mask = DA9052_IRQ_MASK_POS_7, | ||
578 | }, | ||
579 | [DA9052_IRQ_GPI7] = { | ||
580 | .reg_offset = 2, | ||
581 | .mask = DA9052_IRQ_MASK_POS_8, | ||
582 | }, | ||
583 | [DA9052_IRQ_GPI8] = { | ||
584 | .reg_offset = 3, | ||
585 | .mask = DA9052_IRQ_MASK_POS_1, | ||
586 | }, | ||
587 | [DA9052_IRQ_GPI9] = { | ||
588 | .reg_offset = 3, | ||
589 | .mask = DA9052_IRQ_MASK_POS_2, | ||
590 | }, | ||
591 | [DA9052_IRQ_GPI10] = { | ||
592 | .reg_offset = 3, | ||
593 | .mask = DA9052_IRQ_MASK_POS_3, | ||
594 | }, | ||
595 | [DA9052_IRQ_GPI11] = { | ||
596 | .reg_offset = 3, | ||
597 | .mask = DA9052_IRQ_MASK_POS_4, | ||
598 | }, | ||
599 | [DA9052_IRQ_GPI12] = { | ||
600 | .reg_offset = 3, | ||
601 | .mask = DA9052_IRQ_MASK_POS_5, | ||
602 | }, | ||
603 | [DA9052_IRQ_GPI13] = { | ||
604 | .reg_offset = 3, | ||
605 | .mask = DA9052_IRQ_MASK_POS_6, | ||
606 | }, | ||
607 | [DA9052_IRQ_GPI14] = { | ||
608 | .reg_offset = 3, | ||
609 | .mask = DA9052_IRQ_MASK_POS_7, | ||
610 | }, | ||
611 | [DA9052_IRQ_GPI15] = { | ||
612 | .reg_offset = 3, | ||
613 | .mask = DA9052_IRQ_MASK_POS_8, | ||
614 | }, | ||
615 | }; | ||
616 | |||
617 | static struct regmap_irq_chip da9052_regmap_irq_chip = { | ||
618 | .name = "da9052_irq", | ||
619 | .status_base = DA9052_EVENT_A_REG, | ||
620 | .mask_base = DA9052_IRQ_MASK_A_REG, | ||
621 | .ack_base = DA9052_EVENT_A_REG, | ||
622 | .num_regs = DA9052_NUM_IRQ_REGS, | ||
623 | .irqs = da9052_irqs, | ||
624 | .num_irqs = ARRAY_SIZE(da9052_irqs), | ||
625 | }; | ||
626 | |||
627 | struct regmap_config da9052_regmap_config = { | ||
628 | .reg_bits = 8, | ||
629 | .val_bits = 8, | ||
630 | |||
631 | .cache_type = REGCACHE_RBTREE, | ||
632 | |||
633 | .max_register = DA9052_PAGE1_CON_REG, | ||
634 | .readable_reg = da9052_reg_readable, | ||
635 | .writeable_reg = da9052_reg_writeable, | ||
636 | .volatile_reg = da9052_reg_volatile, | ||
637 | }; | ||
638 | EXPORT_SYMBOL_GPL(da9052_regmap_config); | ||
639 | |||
640 | int da9052_device_init(struct da9052 *da9052, u8 chip_id) | ||
641 | { | ||
642 | struct da9052_pdata *pdata = da9052->dev->platform_data; | ||
643 | struct irq_desc *desc; | ||
644 | int ret; | ||
645 | |||
646 | mutex_init(&da9052->io_lock); | ||
647 | |||
648 | if (pdata && pdata->init != NULL) | ||
649 | pdata->init(da9052); | ||
650 | |||
651 | da9052->chip_id = chip_id; | ||
652 | |||
653 | if (!pdata || !pdata->irq_base) | ||
654 | da9052->irq_base = -1; | ||
655 | else | ||
656 | da9052->irq_base = pdata->irq_base; | ||
657 | |||
658 | ret = regmap_add_irq_chip(da9052->regmap, da9052->chip_irq, | ||
659 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
660 | da9052->irq_base, &da9052_regmap_irq_chip, | ||
661 | NULL); | ||
662 | if (ret < 0) | ||
663 | goto regmap_err; | ||
664 | |||
665 | desc = irq_to_desc(da9052->chip_irq); | ||
666 | da9052->irq_base = regmap_irq_chip_get_base(desc->action->dev_id); | ||
667 | |||
668 | ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info, | ||
669 | ARRAY_SIZE(da9052_subdev_info), NULL, 0); | ||
670 | if (ret) | ||
671 | goto err; | ||
672 | |||
673 | return 0; | ||
674 | |||
675 | err: | ||
676 | mfd_remove_devices(da9052->dev); | ||
677 | regmap_err: | ||
678 | return ret; | ||
679 | } | ||
680 | |||
681 | void da9052_device_exit(struct da9052 *da9052) | ||
682 | { | ||
683 | regmap_del_irq_chip(da9052->chip_irq, | ||
684 | irq_get_irq_data(da9052->irq_base)->chip_data); | ||
685 | mfd_remove_devices(da9052->dev); | ||
686 | } | ||
687 | |||
688 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); | ||
689 | MODULE_DESCRIPTION("DA9052 MFD Core"); | ||
690 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c new file mode 100644 index 000000000000..44b97c70a61f --- /dev/null +++ b/drivers/mfd/da9052-i2c.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * I2C access for DA9052 PMICs. | ||
3 | * | ||
4 | * Copyright(c) 2011 Dialog Semiconductor Ltd. | ||
5 | * | ||
6 | * Author: David Dajun Chen <dchen@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/mfd/core.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/err.h> | ||
21 | |||
22 | #include <linux/mfd/da9052/da9052.h> | ||
23 | #include <linux/mfd/da9052/reg.h> | ||
24 | |||
25 | static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) | ||
26 | { | ||
27 | int reg_val, ret; | ||
28 | |||
29 | ret = regmap_read(da9052->regmap, DA9052_CONTROL_B_REG, ®_val); | ||
30 | if (ret < 0) | ||
31 | return ret; | ||
32 | |||
33 | if (reg_val & DA9052_CONTROL_B_WRITEMODE) { | ||
34 | reg_val &= ~DA9052_CONTROL_B_WRITEMODE; | ||
35 | ret = regmap_write(da9052->regmap, DA9052_CONTROL_B_REG, | ||
36 | reg_val); | ||
37 | if (ret < 0) | ||
38 | return ret; | ||
39 | } | ||
40 | |||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | static int __devinit da9052_i2c_probe(struct i2c_client *client, | ||
45 | const struct i2c_device_id *id) | ||
46 | { | ||
47 | struct da9052 *da9052; | ||
48 | int ret; | ||
49 | |||
50 | da9052 = kzalloc(sizeof(struct da9052), GFP_KERNEL); | ||
51 | if (!da9052) | ||
52 | return -ENOMEM; | ||
53 | |||
54 | if (!i2c_check_functionality(client->adapter, | ||
55 | I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
56 | dev_info(&client->dev, "Error in %s:i2c_check_functionality\n", | ||
57 | __func__); | ||
58 | ret = -ENODEV; | ||
59 | goto err; | ||
60 | } | ||
61 | |||
62 | da9052->dev = &client->dev; | ||
63 | da9052->chip_irq = client->irq; | ||
64 | |||
65 | i2c_set_clientdata(client, da9052); | ||
66 | |||
67 | da9052->regmap = regmap_init_i2c(client, &da9052_regmap_config); | ||
68 | if (IS_ERR(da9052->regmap)) { | ||
69 | ret = PTR_ERR(da9052->regmap); | ||
70 | dev_err(&client->dev, "Failed to allocate register map: %d\n", | ||
71 | ret); | ||
72 | goto err; | ||
73 | } | ||
74 | |||
75 | ret = da9052_i2c_enable_multiwrite(da9052); | ||
76 | if (ret < 0) | ||
77 | goto err; | ||
78 | |||
79 | ret = da9052_device_init(da9052, id->driver_data); | ||
80 | if (ret != 0) | ||
81 | goto err; | ||
82 | |||
83 | return 0; | ||
84 | |||
85 | err: | ||
86 | kfree(da9052); | ||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | static int da9052_i2c_remove(struct i2c_client *client) | ||
91 | { | ||
92 | struct da9052 *da9052 = i2c_get_clientdata(client); | ||
93 | |||
94 | da9052_device_exit(da9052); | ||
95 | kfree(da9052); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static struct i2c_device_id da9052_i2c_id[] = { | ||
101 | {"da9052", DA9052}, | ||
102 | {"da9053-aa", DA9053_AA}, | ||
103 | {"da9053-ba", DA9053_BA}, | ||
104 | {"da9053-bb", DA9053_BB}, | ||
105 | {} | ||
106 | }; | ||
107 | |||
108 | static struct i2c_driver da9052_i2c_driver = { | ||
109 | .probe = da9052_i2c_probe, | ||
110 | .remove = da9052_i2c_remove, | ||
111 | .id_table = da9052_i2c_id, | ||
112 | .driver = { | ||
113 | .name = "da9052", | ||
114 | .owner = THIS_MODULE, | ||
115 | }, | ||
116 | }; | ||
117 | |||
118 | static int __init da9052_i2c_init(void) | ||
119 | { | ||
120 | int ret; | ||
121 | |||
122 | ret = i2c_add_driver(&da9052_i2c_driver); | ||
123 | if (ret != 0) { | ||
124 | pr_err("DA9052 I2C registration failed %d\n", ret); | ||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | subsys_initcall(da9052_i2c_init); | ||
131 | |||
132 | static void __exit da9052_i2c_exit(void) | ||
133 | { | ||
134 | i2c_del_driver(&da9052_i2c_driver); | ||
135 | } | ||
136 | module_exit(da9052_i2c_exit); | ||
137 | |||
138 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); | ||
139 | MODULE_DESCRIPTION("I2C driver for Dialog DA9052 PMIC"); | ||
140 | MODULE_LICENSE("GPL"); | ||