diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2012-11-14 10:39:28 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-11-21 10:07:47 -0500 |
commit | edd7eabc85e2f8d76a933b9639bebfe7f98861e4 (patch) | |
tree | aedbc16b600b10177948bbca30cbe692e4a61146 /drivers/mfd/tps80031.c | |
parent | dbc4849db33307c72951e4bd4935fbb8d1fc7b8d (diff) |
mfd: Add TI TPS80031 mfd core driver
TPS80031/ TPS80032 Fully Integrated Power Management with Power
Path and Battery Charger. The device provides five configurable
step-down converters, 11 general purpose LDOs, USB OTG Module,
ADC, RTC, 2 PWM, System Voltage Regulator/Battery Charger with
Power Path from USB, 32K clock generator.
Add the mfd core driver for TPS80031/TPS80032.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviwed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/tps80031.c')
-rw-r--r-- | drivers/mfd/tps80031.c | 573 |
1 files changed, 573 insertions, 0 deletions
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c new file mode 100644 index 000000000000..f64005efa6fa --- /dev/null +++ b/drivers/mfd/tps80031.c | |||
@@ -0,0 +1,573 @@ | |||
1 | /* | ||
2 | * tps80031.c -- TI TPS80031/TPS80032 mfd core driver. | ||
3 | * | ||
4 | * MFD core driver for TI TPS80031/TPS80032 Fully Integrated | ||
5 | * Power Management with Power Path and Battery Charger | ||
6 | * | ||
7 | * Copyright (c) 2012, NVIDIA Corporation. | ||
8 | * | ||
9 | * Author: Laxman Dewangan <ldewangan@nvidia.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License as | ||
13 | * published by the Free Software Foundation version 2. | ||
14 | * | ||
15 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, | ||
16 | * whether express or implied; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
23 | * 02111-1307, USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/err.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/irq.h> | ||
31 | #include <linux/mfd/core.h> | ||
32 | #include <linux/mfd/tps80031.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/pm.h> | ||
35 | #include <linux/regmap.h> | ||
36 | #include <linux/slab.h> | ||
37 | |||
38 | static struct resource tps80031_rtc_resources[] = { | ||
39 | { | ||
40 | .start = TPS80031_INT_RTC_ALARM, | ||
41 | .end = TPS80031_INT_RTC_ALARM, | ||
42 | .flags = IORESOURCE_IRQ, | ||
43 | }, | ||
44 | }; | ||
45 | |||
46 | /* TPS80031 sub mfd devices */ | ||
47 | static struct mfd_cell tps80031_cell[] = { | ||
48 | { | ||
49 | .name = "tps80031-pmic", | ||
50 | }, | ||
51 | { | ||
52 | .name = "tps80031-clock", | ||
53 | }, | ||
54 | { | ||
55 | .name = "tps80031-rtc", | ||
56 | .num_resources = ARRAY_SIZE(tps80031_rtc_resources), | ||
57 | .resources = tps80031_rtc_resources, | ||
58 | }, | ||
59 | { | ||
60 | .name = "tps80031-gpadc", | ||
61 | }, | ||
62 | { | ||
63 | .name = "tps80031-fuel-gauge", | ||
64 | }, | ||
65 | { | ||
66 | .name = "tps80031-charger", | ||
67 | }, | ||
68 | }; | ||
69 | |||
70 | static int tps80031_slave_address[TPS80031_NUM_SLAVES] = { | ||
71 | TPS80031_I2C_ID0_ADDR, | ||
72 | TPS80031_I2C_ID1_ADDR, | ||
73 | TPS80031_I2C_ID2_ADDR, | ||
74 | TPS80031_I2C_ID3_ADDR, | ||
75 | }; | ||
76 | |||
77 | struct tps80031_pupd_data { | ||
78 | u8 reg; | ||
79 | u8 pullup_bit; | ||
80 | u8 pulldown_bit; | ||
81 | }; | ||
82 | |||
83 | #define TPS80031_IRQ(_reg, _mask) \ | ||
84 | { \ | ||
85 | .reg_offset = (TPS80031_INT_MSK_LINE_##_reg) - \ | ||
86 | TPS80031_INT_MSK_LINE_A, \ | ||
87 | .mask = BIT(_mask), \ | ||
88 | } | ||
89 | |||
90 | static const struct regmap_irq tps80031_main_irqs[] = { | ||
91 | [TPS80031_INT_PWRON] = TPS80031_IRQ(A, 0), | ||
92 | [TPS80031_INT_RPWRON] = TPS80031_IRQ(A, 1), | ||
93 | [TPS80031_INT_SYS_VLOW] = TPS80031_IRQ(A, 2), | ||
94 | [TPS80031_INT_RTC_ALARM] = TPS80031_IRQ(A, 3), | ||
95 | [TPS80031_INT_RTC_PERIOD] = TPS80031_IRQ(A, 4), | ||
96 | [TPS80031_INT_HOT_DIE] = TPS80031_IRQ(A, 5), | ||
97 | [TPS80031_INT_VXX_SHORT] = TPS80031_IRQ(A, 6), | ||
98 | [TPS80031_INT_SPDURATION] = TPS80031_IRQ(A, 7), | ||
99 | [TPS80031_INT_WATCHDOG] = TPS80031_IRQ(B, 0), | ||
100 | [TPS80031_INT_BAT] = TPS80031_IRQ(B, 1), | ||
101 | [TPS80031_INT_SIM] = TPS80031_IRQ(B, 2), | ||
102 | [TPS80031_INT_MMC] = TPS80031_IRQ(B, 3), | ||
103 | [TPS80031_INT_RES] = TPS80031_IRQ(B, 4), | ||
104 | [TPS80031_INT_GPADC_RT] = TPS80031_IRQ(B, 5), | ||
105 | [TPS80031_INT_GPADC_SW2_EOC] = TPS80031_IRQ(B, 6), | ||
106 | [TPS80031_INT_CC_AUTOCAL] = TPS80031_IRQ(B, 7), | ||
107 | [TPS80031_INT_ID_WKUP] = TPS80031_IRQ(C, 0), | ||
108 | [TPS80031_INT_VBUSS_WKUP] = TPS80031_IRQ(C, 1), | ||
109 | [TPS80031_INT_ID] = TPS80031_IRQ(C, 2), | ||
110 | [TPS80031_INT_VBUS] = TPS80031_IRQ(C, 3), | ||
111 | [TPS80031_INT_CHRG_CTRL] = TPS80031_IRQ(C, 4), | ||
112 | [TPS80031_INT_EXT_CHRG] = TPS80031_IRQ(C, 5), | ||
113 | [TPS80031_INT_INT_CHRG] = TPS80031_IRQ(C, 6), | ||
114 | [TPS80031_INT_RES2] = TPS80031_IRQ(C, 7), | ||
115 | }; | ||
116 | |||
117 | static struct regmap_irq_chip tps80031_irq_chip = { | ||
118 | .name = "tps80031", | ||
119 | .irqs = tps80031_main_irqs, | ||
120 | .num_irqs = ARRAY_SIZE(tps80031_main_irqs), | ||
121 | .num_regs = 3, | ||
122 | .status_base = TPS80031_INT_STS_A, | ||
123 | .mask_base = TPS80031_INT_MSK_LINE_A, | ||
124 | }; | ||
125 | |||
126 | #define PUPD_DATA(_reg, _pulldown_bit, _pullup_bit) \ | ||
127 | { \ | ||
128 | .reg = TPS80031_CFG_INPUT_PUPD##_reg, \ | ||
129 | .pulldown_bit = _pulldown_bit, \ | ||
130 | .pullup_bit = _pullup_bit, \ | ||
131 | } | ||
132 | |||
133 | static const struct tps80031_pupd_data tps80031_pupds[] = { | ||
134 | [TPS80031_PREQ1] = PUPD_DATA(1, BIT(0), BIT(1)), | ||
135 | [TPS80031_PREQ2A] = PUPD_DATA(1, BIT(2), BIT(3)), | ||
136 | [TPS80031_PREQ2B] = PUPD_DATA(1, BIT(4), BIT(5)), | ||
137 | [TPS80031_PREQ2C] = PUPD_DATA(1, BIT(6), BIT(7)), | ||
138 | [TPS80031_PREQ3] = PUPD_DATA(2, BIT(0), BIT(1)), | ||
139 | [TPS80031_NRES_WARM] = PUPD_DATA(2, 0, BIT(2)), | ||
140 | [TPS80031_PWM_FORCE] = PUPD_DATA(2, BIT(5), 0), | ||
141 | [TPS80031_CHRG_EXT_CHRG_STATZ] = PUPD_DATA(2, 0, BIT(6)), | ||
142 | [TPS80031_SIM] = PUPD_DATA(3, BIT(0), BIT(1)), | ||
143 | [TPS80031_MMC] = PUPD_DATA(3, BIT(2), BIT(3)), | ||
144 | [TPS80031_GPADC_START] = PUPD_DATA(3, BIT(4), 0), | ||
145 | [TPS80031_DVSI2C_SCL] = PUPD_DATA(4, 0, BIT(0)), | ||
146 | [TPS80031_DVSI2C_SDA] = PUPD_DATA(4, 0, BIT(1)), | ||
147 | [TPS80031_CTLI2C_SCL] = PUPD_DATA(4, 0, BIT(2)), | ||
148 | [TPS80031_CTLI2C_SDA] = PUPD_DATA(4, 0, BIT(3)), | ||
149 | }; | ||
150 | static struct tps80031 *tps80031_power_off_dev; | ||
151 | |||
152 | int tps80031_ext_power_req_config(struct device *dev, | ||
153 | unsigned long ext_ctrl_flag, int preq_bit, | ||
154 | int state_reg_add, int trans_reg_add) | ||
155 | { | ||
156 | u8 res_ass_reg = 0; | ||
157 | int preq_mask_bit = 0; | ||
158 | int ret; | ||
159 | |||
160 | if (!(ext_ctrl_flag & TPS80031_EXT_PWR_REQ)) | ||
161 | return 0; | ||
162 | |||
163 | if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ1) { | ||
164 | res_ass_reg = TPS80031_PREQ1_RES_ASS_A + (preq_bit >> 3); | ||
165 | preq_mask_bit = 5; | ||
166 | } else if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ2) { | ||
167 | res_ass_reg = TPS80031_PREQ2_RES_ASS_A + (preq_bit >> 3); | ||
168 | preq_mask_bit = 6; | ||
169 | } else if (ext_ctrl_flag & TPS80031_PWR_REQ_INPUT_PREQ3) { | ||
170 | res_ass_reg = TPS80031_PREQ3_RES_ASS_A + (preq_bit >> 3); | ||
171 | preq_mask_bit = 7; | ||
172 | } | ||
173 | |||
174 | /* Configure REQ_ASS registers */ | ||
175 | ret = tps80031_set_bits(dev, TPS80031_SLAVE_ID1, res_ass_reg, | ||
176 | BIT(preq_bit & 0x7)); | ||
177 | if (ret < 0) { | ||
178 | dev_err(dev, "reg 0x%02x setbit failed, err = %d\n", | ||
179 | res_ass_reg, ret); | ||
180 | return ret; | ||
181 | } | ||
182 | |||
183 | /* Unmask the PREQ */ | ||
184 | ret = tps80031_clr_bits(dev, TPS80031_SLAVE_ID1, | ||
185 | TPS80031_PHOENIX_MSK_TRANSITION, BIT(preq_mask_bit)); | ||
186 | if (ret < 0) { | ||
187 | dev_err(dev, "reg 0x%02x clrbit failed, err = %d\n", | ||
188 | TPS80031_PHOENIX_MSK_TRANSITION, ret); | ||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | /* Switch regulator control to resource now */ | ||
193 | if (ext_ctrl_flag & (TPS80031_PWR_REQ_INPUT_PREQ2 | | ||
194 | TPS80031_PWR_REQ_INPUT_PREQ3)) { | ||
195 | ret = tps80031_update(dev, TPS80031_SLAVE_ID1, state_reg_add, | ||
196 | 0x0, TPS80031_STATE_MASK); | ||
197 | if (ret < 0) | ||
198 | dev_err(dev, "reg 0x%02x update failed, err = %d\n", | ||
199 | state_reg_add, ret); | ||
200 | } else { | ||
201 | ret = tps80031_update(dev, TPS80031_SLAVE_ID1, trans_reg_add, | ||
202 | TPS80031_TRANS_SLEEP_OFF, | ||
203 | TPS80031_TRANS_SLEEP_MASK); | ||
204 | if (ret < 0) | ||
205 | dev_err(dev, "reg 0x%02x update failed, err = %d\n", | ||
206 | trans_reg_add, ret); | ||
207 | } | ||
208 | return ret; | ||
209 | } | ||
210 | EXPORT_SYMBOL_GPL(tps80031_ext_power_req_config); | ||
211 | |||
212 | static void tps80031_power_off(void) | ||
213 | { | ||
214 | dev_info(tps80031_power_off_dev->dev, "switching off PMU\n"); | ||
215 | tps80031_write(tps80031_power_off_dev->dev, TPS80031_SLAVE_ID1, | ||
216 | TPS80031_PHOENIX_DEV_ON, TPS80031_DEVOFF); | ||
217 | } | ||
218 | |||
219 | static void tps80031_pupd_init(struct tps80031 *tps80031, | ||
220 | struct tps80031_platform_data *pdata) | ||
221 | { | ||
222 | struct tps80031_pupd_init_data *pupd_init_data = pdata->pupd_init_data; | ||
223 | int data_size = pdata->pupd_init_data_size; | ||
224 | int i; | ||
225 | |||
226 | for (i = 0; i < data_size; ++i) { | ||
227 | struct tps80031_pupd_init_data *pupd_init = &pupd_init_data[i]; | ||
228 | const struct tps80031_pupd_data *pupd = | ||
229 | &tps80031_pupds[pupd_init->input_pin]; | ||
230 | u8 update_value = 0; | ||
231 | u8 update_mask = pupd->pulldown_bit | pupd->pullup_bit; | ||
232 | |||
233 | if (pupd_init->setting == TPS80031_PUPD_PULLDOWN) | ||
234 | update_value = pupd->pulldown_bit; | ||
235 | else if (pupd_init->setting == TPS80031_PUPD_PULLUP) | ||
236 | update_value = pupd->pullup_bit; | ||
237 | |||
238 | tps80031_update(tps80031->dev, TPS80031_SLAVE_ID1, pupd->reg, | ||
239 | update_value, update_mask); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | static int tps80031_init_ext_control(struct tps80031 *tps80031, | ||
244 | struct tps80031_platform_data *pdata) | ||
245 | { | ||
246 | struct device *dev = tps80031->dev; | ||
247 | int ret; | ||
248 | int i; | ||
249 | |||
250 | /* Clear all external control for this rail */ | ||
251 | for (i = 0; i < 9; ++i) { | ||
252 | ret = tps80031_write(dev, TPS80031_SLAVE_ID1, | ||
253 | TPS80031_PREQ1_RES_ASS_A + i, 0); | ||
254 | if (ret < 0) { | ||
255 | dev_err(dev, "reg 0x%02x write failed, err = %d\n", | ||
256 | TPS80031_PREQ1_RES_ASS_A + i, ret); | ||
257 | return ret; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | /* Mask the PREQ */ | ||
262 | ret = tps80031_set_bits(dev, TPS80031_SLAVE_ID1, | ||
263 | TPS80031_PHOENIX_MSK_TRANSITION, 0x7 << 5); | ||
264 | if (ret < 0) { | ||
265 | dev_err(dev, "reg 0x%02x set_bits failed, err = %d\n", | ||
266 | TPS80031_PHOENIX_MSK_TRANSITION, ret); | ||
267 | return ret; | ||
268 | } | ||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | static int __devinit tps80031_irq_init(struct tps80031 *tps80031, int irq, | ||
273 | int irq_base) | ||
274 | { | ||
275 | struct device *dev = tps80031->dev; | ||
276 | int i, ret; | ||
277 | |||
278 | /* | ||
279 | * The MASK register used for updating status register when | ||
280 | * interrupt occurs and LINE register used to pass the status | ||
281 | * to actual interrupt line. As per datasheet: | ||
282 | * When INT_MSK_LINE [i] is set to 1, the associated interrupt | ||
283 | * number i is INT line masked, which means that no interrupt is | ||
284 | * generated on the INT line. | ||
285 | * When INT_MSK_LINE [i] is set to 0, the associated interrupt | ||
286 | * number i is line enabled: An interrupt is generated on the | ||
287 | * INT line. | ||
288 | * In any case, the INT_STS [i] status bit may or may not be updated, | ||
289 | * only linked to the INT_MSK_STS [i] configuration register bit. | ||
290 | * | ||
291 | * When INT_MSK_STS [i] is set to 1, the associated interrupt number | ||
292 | * i is status masked, which means that no interrupt is stored in | ||
293 | * the INT_STS[i] status bit. Note that no interrupt number i is | ||
294 | * generated on the INT line, even if the INT_MSK_LINE [i] register | ||
295 | * bit is set to 0. | ||
296 | * When INT_MSK_STS [i] is set to 0, the associated interrupt number i | ||
297 | * is status enabled: An interrupt status is updated in the INT_STS [i] | ||
298 | * register. The interrupt may or may not be generated on the INT line, | ||
299 | * depending on the INT_MSK_LINE [i] configuration register bit. | ||
300 | */ | ||
301 | for (i = 0; i < 3; i++) | ||
302 | tps80031_write(dev, TPS80031_SLAVE_ID2, | ||
303 | TPS80031_INT_MSK_STS_A + i, 0x00); | ||
304 | |||
305 | ret = regmap_add_irq_chip(tps80031->regmap[TPS80031_SLAVE_ID2], irq, | ||
306 | IRQF_ONESHOT, irq_base, | ||
307 | &tps80031_irq_chip, &tps80031->irq_data); | ||
308 | if (ret < 0) { | ||
309 | dev_err(dev, "add irq failed, err = %d\n", ret); | ||
310 | return ret; | ||
311 | } | ||
312 | return ret; | ||
313 | } | ||
314 | |||
315 | static bool rd_wr_reg_id0(struct device *dev, unsigned int reg) | ||
316 | { | ||
317 | switch (reg) { | ||
318 | case TPS80031_SMPS1_CFG_FORCE ... TPS80031_SMPS2_CFG_VOLTAGE: | ||
319 | return true; | ||
320 | default: | ||
321 | return false; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | static bool rd_wr_reg_id1(struct device *dev, unsigned int reg) | ||
326 | { | ||
327 | switch (reg) { | ||
328 | case TPS80031_SECONDS_REG ... TPS80031_RTC_RESET_STATUS_REG: | ||
329 | case TPS80031_VALIDITY0 ... TPS80031_VALIDITY7: | ||
330 | case TPS80031_PHOENIX_START_CONDITION ... TPS80031_KEY_PRESS_DUR_CFG: | ||
331 | case TPS80031_SMPS4_CFG_TRANS ... TPS80031_SMPS3_CFG_VOLTAGE: | ||
332 | case TPS80031_BROADCAST_ADDR_ALL ... TPS80031_BROADCAST_ADDR_CLK_RST: | ||
333 | case TPS80031_VANA_CFG_TRANS ... TPS80031_LDO7_CFG_VOLTAGE: | ||
334 | case TPS80031_REGEN1_CFG_TRANS ... TPS80031_TMP_CFG_STATE: | ||
335 | case TPS80031_PREQ1_RES_ASS_A ... TPS80031_PREQ3_RES_ASS_C: | ||
336 | case TPS80031_SMPS_OFFSET ... TPS80031_BATDEBOUNCING: | ||
337 | case TPS80031_CFG_INPUT_PUPD1 ... TPS80031_CFG_SMPS_PD: | ||
338 | case TPS80031_BACKUP_REG: | ||
339 | return true; | ||
340 | default: | ||
341 | return false; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | static bool is_volatile_reg_id1(struct device *dev, unsigned int reg) | ||
346 | { | ||
347 | switch (reg) { | ||
348 | case TPS80031_SMPS4_CFG_TRANS ... TPS80031_SMPS3_CFG_VOLTAGE: | ||
349 | case TPS80031_VANA_CFG_TRANS ... TPS80031_LDO7_CFG_VOLTAGE: | ||
350 | case TPS80031_REGEN1_CFG_TRANS ... TPS80031_TMP_CFG_STATE: | ||
351 | case TPS80031_PREQ1_RES_ASS_A ... TPS80031_PREQ3_RES_ASS_C: | ||
352 | case TPS80031_SMPS_OFFSET ... TPS80031_BATDEBOUNCING: | ||
353 | case TPS80031_CFG_INPUT_PUPD1 ... TPS80031_CFG_SMPS_PD: | ||
354 | return true; | ||
355 | default: | ||
356 | return false; | ||
357 | } | ||
358 | } | ||
359 | |||
360 | static bool rd_wr_reg_id2(struct device *dev, unsigned int reg) | ||
361 | { | ||
362 | switch (reg) { | ||
363 | case TPS80031_USB_VENDOR_ID_LSB ... TPS80031_USB_OTG_REVISION: | ||
364 | case TPS80031_GPADC_CTRL ... TPS80031_CTRL_P1: | ||
365 | case TPS80031_RTCH0_LSB ... TPS80031_GPCH0_MSB: | ||
366 | case TPS80031_TOGGLE1 ... TPS80031_VIBMODE: | ||
367 | case TPS80031_PWM1ON ... TPS80031_PWM2OFF: | ||
368 | case TPS80031_FG_REG_00 ... TPS80031_FG_REG_11: | ||
369 | case TPS80031_INT_STS_A ... TPS80031_INT_MSK_STS_C: | ||
370 | case TPS80031_CONTROLLER_CTRL2 ... TPS80031_LED_PWM_CTRL2: | ||
371 | return true; | ||
372 | default: | ||
373 | return false; | ||
374 | } | ||
375 | } | ||
376 | |||
377 | static bool rd_wr_reg_id3(struct device *dev, unsigned int reg) | ||
378 | { | ||
379 | switch (reg) { | ||
380 | case TPS80031_GPADC_TRIM0 ... TPS80031_GPADC_TRIM18: | ||
381 | return true; | ||
382 | default: | ||
383 | return false; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | static const struct regmap_config tps80031_regmap_configs[] = { | ||
388 | { | ||
389 | .reg_bits = 8, | ||
390 | .val_bits = 8, | ||
391 | .writeable_reg = rd_wr_reg_id0, | ||
392 | .readable_reg = rd_wr_reg_id0, | ||
393 | .max_register = TPS80031_MAX_REGISTER, | ||
394 | }, | ||
395 | { | ||
396 | .reg_bits = 8, | ||
397 | .val_bits = 8, | ||
398 | .writeable_reg = rd_wr_reg_id1, | ||
399 | .readable_reg = rd_wr_reg_id1, | ||
400 | .volatile_reg = is_volatile_reg_id1, | ||
401 | .max_register = TPS80031_MAX_REGISTER, | ||
402 | }, | ||
403 | { | ||
404 | .reg_bits = 8, | ||
405 | .val_bits = 8, | ||
406 | .writeable_reg = rd_wr_reg_id2, | ||
407 | .readable_reg = rd_wr_reg_id2, | ||
408 | .max_register = TPS80031_MAX_REGISTER, | ||
409 | }, | ||
410 | { | ||
411 | .reg_bits = 8, | ||
412 | .val_bits = 8, | ||
413 | .writeable_reg = rd_wr_reg_id3, | ||
414 | .readable_reg = rd_wr_reg_id3, | ||
415 | .max_register = TPS80031_MAX_REGISTER, | ||
416 | }, | ||
417 | }; | ||
418 | |||
419 | static int __devinit tps80031_probe(struct i2c_client *client, | ||
420 | const struct i2c_device_id *id) | ||
421 | { | ||
422 | struct tps80031_platform_data *pdata = client->dev.platform_data; | ||
423 | struct tps80031 *tps80031; | ||
424 | int ret; | ||
425 | uint8_t es_version; | ||
426 | uint8_t ep_ver; | ||
427 | int i; | ||
428 | |||
429 | if (!pdata) { | ||
430 | dev_err(&client->dev, "tps80031 requires platform data\n"); | ||
431 | return -EINVAL; | ||
432 | } | ||
433 | |||
434 | tps80031 = devm_kzalloc(&client->dev, sizeof(*tps80031), GFP_KERNEL); | ||
435 | if (!tps80031) { | ||
436 | dev_err(&client->dev, "Malloc failed for tps80031\n"); | ||
437 | return -ENOMEM; | ||
438 | } | ||
439 | |||
440 | for (i = 0; i < TPS80031_NUM_SLAVES; i++) { | ||
441 | if (tps80031_slave_address[i] == client->addr) | ||
442 | tps80031->clients[i] = client; | ||
443 | else | ||
444 | tps80031->clients[i] = i2c_new_dummy(client->adapter, | ||
445 | tps80031_slave_address[i]); | ||
446 | if (!tps80031->clients[i]) { | ||
447 | dev_err(&client->dev, "can't attach client %d\n", i); | ||
448 | ret = -ENOMEM; | ||
449 | goto fail_client_reg; | ||
450 | } | ||
451 | |||
452 | i2c_set_clientdata(tps80031->clients[i], tps80031); | ||
453 | tps80031->regmap[i] = devm_regmap_init_i2c(tps80031->clients[i], | ||
454 | &tps80031_regmap_configs[i]); | ||
455 | if (IS_ERR(tps80031->regmap[i])) { | ||
456 | ret = PTR_ERR(tps80031->regmap[i]); | ||
457 | dev_err(&client->dev, | ||
458 | "regmap %d init failed, err %d\n", i, ret); | ||
459 | goto fail_client_reg; | ||
460 | } | ||
461 | } | ||
462 | |||
463 | ret = tps80031_read(&client->dev, TPS80031_SLAVE_ID3, | ||
464 | TPS80031_JTAGVERNUM, &es_version); | ||
465 | if (ret < 0) { | ||
466 | dev_err(&client->dev, | ||
467 | "Silicon version number read failed: %d\n", ret); | ||
468 | goto fail_client_reg; | ||
469 | } | ||
470 | |||
471 | ret = tps80031_read(&client->dev, TPS80031_SLAVE_ID3, | ||
472 | TPS80031_EPROM_REV, &ep_ver); | ||
473 | if (ret < 0) { | ||
474 | dev_err(&client->dev, | ||
475 | "Silicon eeprom version read failed: %d\n", ret); | ||
476 | goto fail_client_reg; | ||
477 | } | ||
478 | |||
479 | dev_info(&client->dev, "ES version 0x%02x and EPROM version 0x%02x\n", | ||
480 | es_version, ep_ver); | ||
481 | tps80031->es_version = es_version; | ||
482 | tps80031->dev = &client->dev; | ||
483 | i2c_set_clientdata(client, tps80031); | ||
484 | tps80031->chip_info = id->driver_data; | ||
485 | |||
486 | ret = tps80031_irq_init(tps80031, client->irq, pdata->irq_base); | ||
487 | if (ret) { | ||
488 | dev_err(&client->dev, "IRQ init failed: %d\n", ret); | ||
489 | goto fail_client_reg; | ||
490 | } | ||
491 | |||
492 | tps80031_pupd_init(tps80031, pdata); | ||
493 | |||
494 | tps80031_init_ext_control(tps80031, pdata); | ||
495 | |||
496 | ret = mfd_add_devices(tps80031->dev, -1, | ||
497 | tps80031_cell, ARRAY_SIZE(tps80031_cell), | ||
498 | NULL, 0, | ||
499 | regmap_irq_get_domain(tps80031->irq_data)); | ||
500 | if (ret < 0) { | ||
501 | dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret); | ||
502 | goto fail_mfd_add; | ||
503 | } | ||
504 | |||
505 | if (pdata->use_power_off && !pm_power_off) { | ||
506 | tps80031_power_off_dev = tps80031; | ||
507 | pm_power_off = tps80031_power_off; | ||
508 | } | ||
509 | return 0; | ||
510 | |||
511 | fail_mfd_add: | ||
512 | regmap_del_irq_chip(client->irq, tps80031->irq_data); | ||
513 | |||
514 | fail_client_reg: | ||
515 | for (i = 0; i < TPS80031_NUM_SLAVES; i++) { | ||
516 | if (tps80031->clients[i] && (tps80031->clients[i] != client)) | ||
517 | i2c_unregister_device(tps80031->clients[i]); | ||
518 | } | ||
519 | return ret; | ||
520 | } | ||
521 | |||
522 | static int __devexit tps80031_remove(struct i2c_client *client) | ||
523 | { | ||
524 | struct tps80031 *tps80031 = i2c_get_clientdata(client); | ||
525 | int i; | ||
526 | |||
527 | if (tps80031_power_off_dev == tps80031) { | ||
528 | tps80031_power_off_dev = NULL; | ||
529 | pm_power_off = NULL; | ||
530 | } | ||
531 | |||
532 | mfd_remove_devices(tps80031->dev); | ||
533 | |||
534 | regmap_del_irq_chip(client->irq, tps80031->irq_data); | ||
535 | |||
536 | for (i = 0; i < TPS80031_NUM_SLAVES; i++) { | ||
537 | if (tps80031->clients[i] != client) | ||
538 | i2c_unregister_device(tps80031->clients[i]); | ||
539 | } | ||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | static const struct i2c_device_id tps80031_id_table[] = { | ||
544 | { "tps80031", TPS80031 }, | ||
545 | { "tps80032", TPS80032 }, | ||
546 | }; | ||
547 | MODULE_DEVICE_TABLE(i2c, tps80031_id_table); | ||
548 | |||
549 | static struct i2c_driver tps80031_driver = { | ||
550 | .driver = { | ||
551 | .name = "tps80031", | ||
552 | .owner = THIS_MODULE, | ||
553 | }, | ||
554 | .probe = tps80031_probe, | ||
555 | .remove = __devexit_p(tps80031_remove), | ||
556 | .id_table = tps80031_id_table, | ||
557 | }; | ||
558 | |||
559 | static int __init tps80031_init(void) | ||
560 | { | ||
561 | return i2c_add_driver(&tps80031_driver); | ||
562 | } | ||
563 | subsys_initcall(tps80031_init); | ||
564 | |||
565 | static void __exit tps80031_exit(void) | ||
566 | { | ||
567 | i2c_del_driver(&tps80031_driver); | ||
568 | } | ||
569 | module_exit(tps80031_exit); | ||
570 | |||
571 | MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); | ||
572 | MODULE_DESCRIPTION("TPS80031 core driver"); | ||
573 | MODULE_LICENSE("GPL v2"); | ||