aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/tps80031-charger.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/tps80031-charger.c')
-rw-r--r--drivers/power/tps80031-charger.c476
1 files changed, 476 insertions, 0 deletions
diff --git a/drivers/power/tps80031-charger.c b/drivers/power/tps80031-charger.c
new file mode 100644
index 00000000000..93b283e0b04
--- /dev/null
+++ b/drivers/power/tps80031-charger.c
@@ -0,0 +1,476 @@
1/*
2 * drivers/power/tps80031_charger.c
3 *
4 * Battery charger driver for TI's tps80031
5 *
6 * Copyright (c) 2011, NVIDIA Corporation.
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 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22#include <linux/kernel.h>
23#include <linux/delay.h>
24#include <linux/init.h>
25#include <linux/err.h>
26#include <linux/slab.h>
27#include <linux/platform_device.h>
28#include <linux/regulator/driver.h>
29#include <linux/regulator/machine.h>
30#include <linux/mfd/tps80031.h>
31#include <linux/tps80031-charger.h>
32
33#define CONTROLLER_CTRL1 0xe1
34#define CONTROLLER_STAT1 0xe3
35#define CHARGERUSB_CTRL2 0xe9
36#define CHARGERUSB_CTRL3 0xea
37#define CHARGERUSB_VOREG 0xec
38#define CHARGERUSB_VICHRG 0xed
39#define CHARGERUSB_CINLIMIT 0xee
40#define CHARGERUSB_CTRLLIMIT2 0xf0
41#define CHARGERUSB_CTRLLIMIT1 0xef
42#define CHARGERUSB_VICHRG_PC 0xdd
43#define CONTROLLER_WDG 0xe2
44#define LINEAR_CHRG_STS 0xde
45
46#define TPS80031_VBUS_DET BIT(2)
47#define TPS80031_VAC_DET BIT(3)
48
49struct tps80031_charger {
50 int max_charge_current_mA;
51 int max_charge_volt_mV;
52 struct device *dev;
53 struct regulator_dev *rdev;
54 struct regulator_desc reg_desc;
55 struct regulator_init_data reg_init_data;
56 struct tps80031_charger_platform_data *pdata;
57 int (*board_init)(void *board_data);
58 void *board_data;
59 int irq_base;
60 int watch_time_sec;
61 enum charging_states state;
62 int charging_term_current_mA;
63 charging_callback_t charger_cb;
64 void *charger_cb_data;
65};
66
67static struct tps80031_charger *charger_data;
68static uint8_t charging_current_val_code[] = {
69 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0x27,
70 0x37, 0x28, 0x38, 0x29, 0x39, 0x2A, 0x3A, 0x2B, 0x3B, 0x2C,
71 0x3C, 0x2D, 0x3D, 0x2E,
72};
73
74static int set_charge_current_limit(struct regulator_dev *rdev,
75 int min_uA, int max_uA)
76{
77 struct tps80031_charger *charger = rdev_get_drvdata(rdev);
78 int max_vbus_current = 1500;
79 int max_charge_current = 1500;
80 int ret;
81
82 dev_info(charger->dev, "%s(): Min curr %dmA and max current %dmA\n",
83 __func__, min_uA/1000, max_uA/1000);
84
85 if (!max_uA) {
86 ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
87 CONTROLLER_CTRL1, 0x0);
88 if (ret < 0)
89 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
90 __func__, CONTROLLER_CTRL1);
91
92 ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
93 CONTROLLER_WDG, 0x0);
94 if (ret < 0)
95 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
96 __func__, CONTROLLER_WDG);
97 charger->state = charging_state_charging_stopped;
98 if (charger->charger_cb)
99 charger->charger_cb(charger->state,
100 charger->charger_cb_data);
101 return ret;
102 }
103
104 max_vbus_current = min(max_uA/1000, max_vbus_current);
105 max_vbus_current = max_vbus_current/50;
106 if (max_vbus_current)
107 max_vbus_current--;
108 ret = tps80031_update(charger->dev->parent, SLAVE_ID2,
109 CHARGERUSB_CINLIMIT,
110 charging_current_val_code[max_vbus_current], 0x3F);
111 if (ret < 0) {
112 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
113 __func__, CHARGERUSB_CINLIMIT);
114 return ret;
115 }
116
117 max_charge_current = min(max_uA/1000, max_charge_current);
118 if (max_charge_current <= 300)
119 max_charge_current = 0;
120 else if ((max_charge_current > 300) && (max_charge_current <= 500))
121 max_charge_current = (max_charge_current - 300)/50;
122 else
123 max_charge_current = (max_charge_current - 500) / 100 + 4;
124 ret = tps80031_update(charger->dev->parent, SLAVE_ID2,
125 CHARGERUSB_VICHRG, (uint8_t)max_charge_current, 0xF);
126 if (ret < 0) {
127 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
128 __func__, CHARGERUSB_VICHRG);
129 return ret;
130 }
131
132 /* Enable watchdog timer */
133 ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
134 CONTROLLER_WDG, charger->watch_time_sec);
135 if (ret < 0) {
136 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
137 __func__, CONTROLLER_WDG);
138 return ret;
139 }
140
141 /* Enable the charging */
142 ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
143 CONTROLLER_CTRL1, 0x30);
144 if (ret < 0) {
145 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
146 __func__, CONTROLLER_CTRL1);
147 return ret;
148 }
149 charger->state = charging_state_charging_in_progress;
150 if (charger->charger_cb)
151 charger->charger_cb(charger->state,
152 charger->charger_cb_data);
153 return 0;
154}
155
156static struct regulator_ops tegra_regulator_ops = {
157 .set_current_limit = set_charge_current_limit,
158};
159
160int register_charging_state_callback(charging_callback_t cb, void *args)
161{
162 struct tps80031_charger *charger = charger_data;
163 if (!charger_data)
164 return -ENODEV;
165
166 charger->charger_cb = cb;
167 charger->charger_cb_data = args;
168 return 0;
169}
170EXPORT_SYMBOL_GPL(register_charging_state_callback);
171
172static int configure_charging_parameter(struct tps80031_charger *charger)
173{
174 int ret;
175 int max_charge_current;
176 int max_charge_volt;
177 int term_current;
178
179 /* Disable watchdog timer */
180 ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
181 CONTROLLER_WDG, 0x0);
182 if (ret < 0) {
183 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
184 __func__, CONTROLLER_WDG);
185 return ret;
186 }
187
188 /* Disable the charging if any */
189 ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
190 CONTROLLER_CTRL1, 0x0);
191 if (ret < 0) {
192 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
193 __func__, CONTROLLER_CTRL1);
194 return ret;
195 }
196
197 if (charger->board_init) {
198 ret = charger->board_init(charger->board_data);
199 if (ret < 0) {
200 dev_err(charger->dev, "%s(): Failed in board init\n",
201 __func__);
202 return ret;
203 }
204 }
205
206 /* Unlock value */
207 ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
208 CHARGERUSB_CTRLLIMIT2, 0);
209 if (ret < 0) {
210 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
211 __func__, CHARGERUSB_CTRLLIMIT2);
212 return ret;
213 }
214
215 /* Set max current limit */
216 max_charge_current = min(1500, charger->max_charge_current_mA);
217 if (max_charge_current < 100)
218 max_charge_current = 0;
219 else
220 max_charge_current = (max_charge_current - 100)/100;
221 max_charge_current &= 0xF;
222 ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
223 CHARGERUSB_CTRLLIMIT2, (uint8_t)max_charge_current);
224 if (ret < 0) {
225 dev_err(charger->dev, "%s(): Failed in writing register "
226 "0x%02x\n", __func__, CHARGERUSB_CTRLLIMIT2);
227 return ret;
228 }
229
230 /* Set max voltage limit */
231 max_charge_volt = min(4760, charger->max_charge_volt_mV);
232 max_charge_volt = max(3500, max_charge_volt);
233 max_charge_volt -= 3500;
234 max_charge_volt = max_charge_volt/20;
235 ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
236 CHARGERUSB_CTRLLIMIT1, (uint8_t)max_charge_volt);
237 if (ret < 0) {
238 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
239 __func__, CHARGERUSB_CTRLLIMIT1);
240 return ret;
241 }
242
243 /* Lock value */
244 ret = tps80031_set_bits(charger->dev->parent, SLAVE_ID2,
245 CHARGERUSB_CTRLLIMIT2, (1 << 4));
246 if (ret < 0) {
247 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
248 __func__, CHARGERUSB_CTRLLIMIT2);
249 return ret;
250 }
251
252 /* set Pre Charge current to 400mA */
253 ret = tps80031_write(charger->dev->parent, SLAVE_ID2, 0xDE, 0x3);
254 if (ret < 0) {
255 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
256 __func__, 0xDD);
257 return ret;
258 }
259
260 /* set charging termination current*/
261 if (charger->charging_term_current_mA > 400)
262 term_current = 7;
263 else
264 term_current = (charger->charging_term_current_mA - 50)/50;
265 term_current = term_current << 5;
266 ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
267 CHARGERUSB_CTRL2, term_current);
268 if (ret < 0) {
269 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
270 __func__, CHARGERUSB_CTRL2);
271 return ret;
272 }
273
274 return 0;
275}
276
277static irqreturn_t linch_status_isr(int irq, void *dev_id)
278{
279 struct tps80031_charger *charger = dev_id;
280 uint8_t linch_status;
281 int ret;
282 dev_info(charger->dev, "%s() got called\n", __func__);
283
284 ret = tps80031_read(charger->dev->parent, SLAVE_ID2,
285 LINEAR_CHRG_STS, &linch_status);
286 if (ret < 0) {
287 dev_err(charger->dev, "%s(): Failed in reading register 0x%02x\n",
288 __func__, LINEAR_CHRG_STS);
289 } else {
290 dev_info(charger->dev, "%s():The status of LINEAR_CHRG_STS is 0x%02x\n",
291 __func__, linch_status);
292 if (linch_status & 0x20) {
293 charger->state = charging_state_charging_completed;
294 if (charger->charger_cb)
295 charger->charger_cb(charger->state,
296 charger->charger_cb_data);
297 }
298 }
299
300 return IRQ_HANDLED;
301}
302
303static irqreturn_t watchdog_expire_isr(int irq, void *dev_id)
304{
305 struct tps80031_charger *charger = dev_id;
306 int ret;
307
308 dev_info(charger->dev, "%s()\n", __func__);
309 if (charger->state != charging_state_charging_in_progress)
310 return IRQ_HANDLED;
311
312 /* Enable watchdog timer again*/
313 ret = tps80031_write(charger->dev->parent, SLAVE_ID2, CONTROLLER_WDG,
314 charger->watch_time_sec);
315 if (ret < 0)
316 dev_err(charger->dev, "%s(): Failed in writing register 0x%02x\n",
317 __func__, CONTROLLER_WDG);
318
319 /* Rewrite to enable the charging */
320 if (!ret) {
321 ret = tps80031_write(charger->dev->parent, SLAVE_ID2,
322 CONTROLLER_CTRL1, 0x30);
323 if (ret < 0)
324 dev_err(charger->dev, "%s(): Failed in writing "
325 "register 0x%02x\n",
326 __func__, CONTROLLER_CTRL1);
327 }
328 return IRQ_HANDLED;
329}
330
331static int tps80031_charger_probe(struct platform_device *pdev)
332{
333 int ret = 0;
334 struct device *dev = &pdev->dev;
335 struct tps80031_charger *charger;
336 struct tps80031_charger_platform_data *pdata = pdev->dev.platform_data;
337
338 dev_info(dev, "%s()\n", __func__);
339
340 if (!pdata) {
341 dev_err(dev, "%s() No platform data, exiting..\n", __func__);
342 return -ENODEV;
343 }
344
345 if (!pdata->num_consumer_supplies) {
346 dev_err(dev, "%s() No consumer supply list, exiting..\n",
347 __func__);
348 return -ENODEV;
349 }
350
351 charger = kzalloc(sizeof(*charger), GFP_KERNEL);
352 if (!charger) {
353 dev_err(dev, "failed to allocate memory status\n");
354 return -ENOMEM;
355 }
356
357 charger->dev = &pdev->dev;
358
359 charger->max_charge_current_mA = (pdata->max_charge_current_mA) ?
360 pdata->max_charge_current_mA : 1000;
361 charger->max_charge_volt_mV = (pdata->max_charge_volt_mV) ?
362 pdata->max_charge_volt_mV : 4200;
363 charger->irq_base = pdata->irq_base;
364 charger->watch_time_sec = min(pdata->watch_time_sec, 127);
365 if (!charger->watch_time_sec)
366 charger->watch_time_sec = 127;
367 charger->charging_term_current_mA =
368 min(50, pdata->charging_term_current_mA);
369 if (charger->charging_term_current_mA < 50)
370 charger->charging_term_current_mA = 50;
371
372 charger->reg_desc.name = "vbus_charger";
373 charger->reg_desc.id = pdata->regulator_id;
374 charger->reg_desc.ops = &tegra_regulator_ops;
375 charger->reg_desc.type = REGULATOR_CURRENT;
376 charger->reg_desc.owner = THIS_MODULE;
377
378 charger->reg_init_data.supply_regulator = NULL;
379 charger->reg_init_data.num_consumer_supplies =
380 pdata->num_consumer_supplies;
381 charger->reg_init_data.consumer_supplies = pdata->consumer_supplies;
382 charger->reg_init_data.regulator_init = NULL;
383 charger->reg_init_data.driver_data = charger;
384 charger->reg_init_data.constraints.name = "vbus_charger";
385 charger->reg_init_data.constraints.min_uA = 0;
386 charger->reg_init_data.constraints.max_uA =
387 pdata->max_charge_current_mA * 1000;
388 charger->reg_init_data.constraints.valid_modes_mask =
389 REGULATOR_MODE_NORMAL |
390 REGULATOR_MODE_STANDBY;
391 charger->reg_init_data.constraints.valid_ops_mask =
392 REGULATOR_CHANGE_MODE |
393 REGULATOR_CHANGE_STATUS |
394 REGULATOR_CHANGE_CURRENT;
395
396 charger->board_init = pdata->board_init;
397 charger->board_data = pdata->board_data;
398 charger->state = charging_state_idle;
399
400 charger->rdev = regulator_register(&charger->reg_desc, &pdev->dev,
401 &charger->reg_init_data, charger);
402 if (IS_ERR(charger->rdev)) {
403 dev_err(&pdev->dev, "failed to register %s\n",
404 charger->reg_desc.name);
405 ret = PTR_ERR(charger->rdev);
406 goto regulator_fail;
407 }
408
409 ret = request_threaded_irq(charger->irq_base + TPS80031_INT_LINCH_GATED,
410 NULL, linch_status_isr, 0, "tps80031-linch", charger);
411 if (ret) {
412 dev_err(&pdev->dev, "Unable to register irq %d; error %d\n",
413 charger->irq_base + TPS80031_INT_LINCH_GATED, ret);
414 goto irq_linch_fail;
415 }
416
417 ret = request_threaded_irq(charger->irq_base + TPS80031_INT_FAULT_WDG,
418 NULL, watchdog_expire_isr, 0, "tps80031-wdg", charger);
419 if (ret) {
420 dev_err(&pdev->dev, "Unable to register irq %d; error %d\n",
421 charger->irq_base + TPS80031_INT_FAULT_WDG, ret);
422 goto irq_wdg_fail;
423 }
424
425 ret = configure_charging_parameter(charger);
426 if (ret)
427 goto config_fail;
428
429 dev_set_drvdata(&pdev->dev, charger);
430 charger_data = charger;
431 return ret;
432
433config_fail:
434 free_irq(charger->irq_base + TPS80031_INT_FAULT_WDG, charger);
435irq_wdg_fail:
436 free_irq(charger->irq_base + TPS80031_INT_LINCH_GATED, charger);
437irq_linch_fail:
438 regulator_unregister(charger->rdev);
439regulator_fail:
440 kfree(charger);
441 return ret;
442}
443
444static int tps80031_charger_remove(struct platform_device *pdev)
445{
446 struct tps80031_charger *charger = dev_get_drvdata(&pdev->dev);
447
448 regulator_unregister(charger->rdev);
449 kfree(charger);
450 return 0;
451}
452
453static struct platform_driver tps80031_charger_driver = {
454 .driver = {
455 .name = "tps80031-charger",
456 .owner = THIS_MODULE,
457 },
458 .probe = tps80031_charger_probe,
459 .remove = tps80031_charger_remove,
460};
461
462static int __init tps80031_charger_init(void)
463{
464 return platform_driver_register(&tps80031_charger_driver);
465}
466
467static void __exit tps80031_charger_exit(void)
468{
469 platform_driver_unregister(&tps80031_charger_driver);
470}
471
472subsys_initcall(tps80031_charger_init);
473module_exit(tps80031_charger_exit);
474
475MODULE_LICENSE("GPL");
476MODULE_DESCRIPTION("tps80031 battery charger driver");