blob: 719cfec29fb20a416bcdf648e9ab79d9a9279a1b [file] [log] [blame]
Jay Chokshi89489c32011-11-16 16:55:26 -08001/*
Duy Truong790f06d2013-02-13 16:38:12 -08002 * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
Jay Chokshi89489c32011-11-16 16:55:26 -08003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13#define pr_fmt(fmt) "%s: " fmt, __func__
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/errno.h>
19#include <linux/power_supply.h>
20#include <linux/slab.h>
21#include <linux/gpio.h>
22#include <linux/power/ltc4088-charger.h>
23
24#define MAX_CURRENT_UA(n) (n)
25#define MAX_CURRENT_MA(n) (n * MAX_CURRENT_UA(1000))
26
27/**
28 * ltc4088_max_current - A typical current values supported by the charger
29 * @LTC4088_MAX_CURRENT_100mA: 100mA current
30 * @LTC4088_MAX_CURRENT_500mA: 500mA current
31 * @LTC4088_MAX_CURRENT_1A: 1A current
32 */
33enum ltc4088_max_current {
34 LTC4088_MAX_CURRENT_100mA = 100,
35 LTC4088_MAX_CURRENT_500mA = 500,
36 LTC4088_MAX_CURRENT_1A = 1000,
37};
38
39/**
40 * struct ltc4088_chg_chip - Device information
41 * @dev: Device pointer to access the parent
42 * @lock: Enable mutual exclusion
43 * @usb_psy: USB device information
44 * @gpio_mode_select_d0: GPIO #pin for D0 charger line
45 * @gpio_mode_select_d1: GPIO #pin for D1 charger line
46 * @gpio_mode_select_d2: GPIO #pin for D2 charger line
47 * @max_current: Maximum current that is supplied at this time
48 */
49struct ltc4088_chg_chip {
50 struct device *dev;
51 struct mutex lock;
52 struct power_supply usb_psy;
53 unsigned int gpio_mode_select_d0;
54 unsigned int gpio_mode_select_d1;
55 unsigned int gpio_mode_select_d2;
56 unsigned int max_current;
57};
58
59static enum power_supply_property pm_power_props[] = {
60 POWER_SUPPLY_PROP_CURRENT_MAX,
61 POWER_SUPPLY_PROP_ONLINE,
62};
63
64static char *pm_power_supplied_to[] = {
65 "battery",
66};
67
68static int ltc4088_set_charging(struct ltc4088_chg_chip *chip, bool enable)
69{
70 mutex_lock(&chip->lock);
71
72 if (enable) {
73 gpio_set_value_cansleep(chip->gpio_mode_select_d2, 0);
74 } else {
75 /* When disabling charger, set the max current to 0 also */
76 chip->max_current = 0;
77 gpio_set_value_cansleep(chip->gpio_mode_select_d0, 1);
78 gpio_set_value_cansleep(chip->gpio_mode_select_d1, 1);
79 gpio_set_value_cansleep(chip->gpio_mode_select_d2, 1);
80 }
81
82 mutex_unlock(&chip->lock);
83
84 return 0;
85}
86
87static void ltc4088_set_max_current(struct ltc4088_chg_chip *chip, int value)
88{
89 mutex_lock(&chip->lock);
90
91 /* If current is less than 100mA, we can not support that granularity */
92 if (value < MAX_CURRENT_MA(LTC4088_MAX_CURRENT_100mA)) {
93 chip->max_current = 0;
94 gpio_set_value_cansleep(chip->gpio_mode_select_d0, 1);
95 gpio_set_value_cansleep(chip->gpio_mode_select_d1, 1);
96 } else if (value < MAX_CURRENT_MA(LTC4088_MAX_CURRENT_500mA)) {
97 chip->max_current = MAX_CURRENT_MA(LTC4088_MAX_CURRENT_100mA);
98 gpio_set_value_cansleep(chip->gpio_mode_select_d0, 0);
99 gpio_set_value_cansleep(chip->gpio_mode_select_d1, 0);
100 } else if (value < MAX_CURRENT_MA(LTC4088_MAX_CURRENT_1A)) {
101 chip->max_current = MAX_CURRENT_MA(LTC4088_MAX_CURRENT_500mA);
102 gpio_set_value_cansleep(chip->gpio_mode_select_d0, 0);
103 gpio_set_value_cansleep(chip->gpio_mode_select_d1, 1);
104 } else {
105 chip->max_current = MAX_CURRENT_MA(LTC4088_MAX_CURRENT_1A);
106 gpio_set_value_cansleep(chip->gpio_mode_select_d0, 1);
107 gpio_set_value_cansleep(chip->gpio_mode_select_d1, 0);
108 }
109
110 mutex_unlock(&chip->lock);
111}
112
113static void ltc4088_set_charging_off(struct ltc4088_chg_chip *chip)
114{
115 gpio_set_value_cansleep(chip->gpio_mode_select_d0, 1);
116 gpio_set_value_cansleep(chip->gpio_mode_select_d1, 1);
117}
118
119static int ltc4088_set_initial_state(struct ltc4088_chg_chip *chip)
120{
121 int rc;
122
123 rc = gpio_request(chip->gpio_mode_select_d0, "ltc4088_D0");
124 if (rc) {
125 pr_err("gpio request failed for GPIO %d\n",
126 chip->gpio_mode_select_d0);
127 return rc;
128 }
129
130 rc = gpio_request(chip->gpio_mode_select_d1, "ltc4088_D1");
131 if (rc) {
132 pr_err("gpio request failed for GPIO %d\n",
133 chip->gpio_mode_select_d1);
134 goto gpio_err_d0;
135 }
136
137 rc = gpio_request(chip->gpio_mode_select_d2, "ltc4088_D2");
138 if (rc) {
139 pr_err("gpio request failed for GPIO %d\n",
140 chip->gpio_mode_select_d2);
141 goto gpio_err_d1;
142 }
143
144 rc = gpio_direction_output(chip->gpio_mode_select_d0, 0);
145 if (rc) {
146 pr_err("failed to set direction for GPIO %d\n",
147 chip->gpio_mode_select_d0);
148 goto gpio_err_d2;
149 }
150
151 rc = gpio_direction_output(chip->gpio_mode_select_d1, 0);
152 if (rc) {
153 pr_err("failed to set direction for GPIO %d\n",
154 chip->gpio_mode_select_d1);
155 goto gpio_err_d2;
156 }
157
158 rc = gpio_direction_output(chip->gpio_mode_select_d2, 1);
159 if (rc) {
160 pr_err("failed to set direction for GPIO %d\n",
161 chip->gpio_mode_select_d2);
162 goto gpio_err_d2;
163 }
164
165 return 0;
166
167gpio_err_d2:
168 gpio_free(chip->gpio_mode_select_d2);
169gpio_err_d1:
170 gpio_free(chip->gpio_mode_select_d1);
171gpio_err_d0:
172 gpio_free(chip->gpio_mode_select_d0);
173 return rc;
174}
175
176static int pm_power_get_property(struct power_supply *psy,
177 enum power_supply_property psp,
178 union power_supply_propval *val)
179{
180 struct ltc4088_chg_chip *chip;
181
182 if (psy->type == POWER_SUPPLY_TYPE_USB) {
183 chip = container_of(psy, struct ltc4088_chg_chip,
184 usb_psy);
185 switch (psp) {
186 case POWER_SUPPLY_PROP_ONLINE:
187 if (chip->max_current)
188 val->intval = 1;
189 else
190 val->intval = 0;
191 break;
192 case POWER_SUPPLY_PROP_CURRENT_MAX:
193 val->intval = chip->max_current;
194 break;
195 default:
196 return -EINVAL;
197 }
198 }
199 return 0;
200}
201
202static int pm_power_set_property(struct power_supply *psy,
203 enum power_supply_property psp,
204 const union power_supply_propval *val)
205{
206 struct ltc4088_chg_chip *chip;
207
208 if (psy->type == POWER_SUPPLY_TYPE_USB) {
David Keitel0e651472012-06-06 14:44:38 -0700209 chip = container_of(psy, struct ltc4088_chg_chip, usb_psy);
Jay Chokshi89489c32011-11-16 16:55:26 -0800210 switch (psp) {
David Keitel0e651472012-06-06 14:44:38 -0700211 case POWER_SUPPLY_PROP_TYPE:
212 psy.type = val->intval;
213 break;
Jay Chokshi89489c32011-11-16 16:55:26 -0800214 case POWER_SUPPLY_PROP_ONLINE:
215 ltc4088_set_charging(chip, val->intval);
216 break;
217 case POWER_SUPPLY_PROP_CURRENT_MAX:
218 ltc4088_set_max_current(chip, val->intval);
219 break;
220 default:
221 return -EINVAL;
222 }
223 }
224 return 0;
225}
226
227static int __devinit ltc4088_charger_probe(struct platform_device *pdev)
228{
229 int rc;
230 struct ltc4088_chg_chip *chip;
231 const struct ltc4088_charger_platform_data *pdata
232 = pdev->dev.platform_data;
233
234 if (!pdata) {
235 pr_err("missing platform data\n");
236 return -EINVAL;
237 }
238
239 chip = kzalloc(sizeof(struct ltc4088_chg_chip),
240 GFP_KERNEL);
241 if (!chip) {
242 pr_err("Cannot allocate pm_chg_chip\n");
243 return -ENOMEM;
244 }
245
246 chip->dev = &pdev->dev;
247
248 if (pdata->gpio_mode_select_d0 < 0 ||
249 pdata->gpio_mode_select_d1 < 0 ||
250 pdata->gpio_mode_select_d2 < 0) {
251 pr_err("Invalid platform data supplied\n");
252 rc = -EINVAL;
253 goto free_chip;
254 }
255
256 mutex_init(&chip->lock);
257
258 chip->gpio_mode_select_d0 = pdata->gpio_mode_select_d0;
259 chip->gpio_mode_select_d1 = pdata->gpio_mode_select_d1;
260 chip->gpio_mode_select_d2 = pdata->gpio_mode_select_d2;
261
262 chip->usb_psy.name = "usb",
263 chip->usb_psy.type = POWER_SUPPLY_TYPE_USB,
264 chip->usb_psy.supplied_to = pm_power_supplied_to,
265 chip->usb_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to),
266 chip->usb_psy.properties = pm_power_props,
267 chip->usb_psy.num_properties = ARRAY_SIZE(pm_power_props),
268 chip->usb_psy.get_property = pm_power_get_property,
269 chip->usb_psy.set_property = pm_power_set_property,
270
271 rc = power_supply_register(chip->dev, &chip->usb_psy);
272 if (rc < 0) {
273 pr_err("power_supply_register usb failed rc = %d\n", rc);
274 goto free_chip;
275 }
276
277 platform_set_drvdata(pdev, chip);
278
279 rc = ltc4088_set_initial_state(chip);
280 if (rc < 0) {
281 pr_err("setting initial state failed rc = %d\n", rc);
282 goto unregister_usb;
283 }
284
285 return 0;
286
287unregister_usb:
288 platform_set_drvdata(pdev, NULL);
289 power_supply_unregister(&chip->usb_psy);
290free_chip:
291 kfree(chip);
292
293 return rc;
294}
295
296static int __devexit ltc4088_charger_remove(struct platform_device *pdev)
297{
298 struct ltc4088_chg_chip *chip = platform_get_drvdata(pdev);
299
300 ltc4088_set_charging_off(chip);
301
302 gpio_free(chip->gpio_mode_select_d2);
303 gpio_free(chip->gpio_mode_select_d1);
304 gpio_free(chip->gpio_mode_select_d0);
305
306 power_supply_unregister(&chip->usb_psy);
307
308 platform_set_drvdata(pdev, NULL);
309 mutex_destroy(&chip->lock);
310 kfree(chip);
311
312 return 0;
313}
314
315static struct platform_driver ltc4088_charger_driver = {
316 .probe = ltc4088_charger_probe,
317 .remove = __devexit_p(ltc4088_charger_remove),
318 .driver = {
319 .name = LTC4088_CHARGER_DEV_NAME,
320 .owner = THIS_MODULE,
321 },
322};
323
324static int __init ltc4088_charger_init(void)
325{
326 return platform_driver_register(&ltc4088_charger_driver);
327}
328
329static void __exit ltc4088_charger_exit(void)
330{
331 platform_driver_unregister(&ltc4088_charger_driver);
332}
333
334subsys_initcall(ltc4088_charger_init);
335module_exit(ltc4088_charger_exit);
336
337MODULE_LICENSE("GPL v2");
338MODULE_DESCRIPTION("LTC4088 charger/battery driver");
339MODULE_VERSION("1.0");
340MODULE_ALIAS("platform:" LTC4088_CHARGER_DEV_NAME);