xref: /linux/drivers/power/supply/max8903_charger.c (revision bfd5bb6f90af092aa345b15cd78143956a13c2a8)
1 /*
2  * max8903_charger.c - Maxim 8903 USB/Adapter Charger Driver
3  *
4  * Copyright (C) 2011 Samsung Electronics
5  * MyungJoo Ham <myungjoo.ham@samsung.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22 
23 #include <linux/gpio.h>
24 #include <linux/interrupt.h>
25 #include <linux/module.h>
26 #include <linux/of.h>
27 #include <linux/of_device.h>
28 #include <linux/of_gpio.h>
29 #include <linux/slab.h>
30 #include <linux/power_supply.h>
31 #include <linux/platform_device.h>
32 #include <linux/power/max8903_charger.h>
33 
34 struct max8903_data {
35 	struct max8903_pdata *pdata;
36 	struct device *dev;
37 	struct power_supply *psy;
38 	struct power_supply_desc psy_desc;
39 	bool fault;
40 	bool usb_in;
41 	bool ta_in;
42 };
43 
44 static enum power_supply_property max8903_charger_props[] = {
45 	POWER_SUPPLY_PROP_STATUS, /* Charger status output */
46 	POWER_SUPPLY_PROP_ONLINE, /* External power source */
47 	POWER_SUPPLY_PROP_HEALTH, /* Fault or OK */
48 };
49 
50 static int max8903_get_property(struct power_supply *psy,
51 		enum power_supply_property psp,
52 		union power_supply_propval *val)
53 {
54 	struct max8903_data *data = power_supply_get_drvdata(psy);
55 
56 	switch (psp) {
57 	case POWER_SUPPLY_PROP_STATUS:
58 		val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
59 		if (gpio_is_valid(data->pdata->chg)) {
60 			if (gpio_get_value(data->pdata->chg) == 0)
61 				val->intval = POWER_SUPPLY_STATUS_CHARGING;
62 			else if (data->usb_in || data->ta_in)
63 				val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
64 			else
65 				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
66 		}
67 		break;
68 	case POWER_SUPPLY_PROP_ONLINE:
69 		val->intval = 0;
70 		if (data->usb_in || data->ta_in)
71 			val->intval = 1;
72 		break;
73 	case POWER_SUPPLY_PROP_HEALTH:
74 		val->intval = POWER_SUPPLY_HEALTH_GOOD;
75 		if (data->fault)
76 			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
77 		break;
78 	default:
79 		return -EINVAL;
80 	}
81 
82 	return 0;
83 }
84 
85 static irqreturn_t max8903_dcin(int irq, void *_data)
86 {
87 	struct max8903_data *data = _data;
88 	struct max8903_pdata *pdata = data->pdata;
89 	bool ta_in;
90 	enum power_supply_type old_type;
91 
92 	ta_in = gpio_get_value(pdata->dok) ? false : true;
93 
94 	if (ta_in == data->ta_in)
95 		return IRQ_HANDLED;
96 
97 	data->ta_in = ta_in;
98 
99 	/* Set Current-Limit-Mode 1:DC 0:USB */
100 	if (gpio_is_valid(pdata->dcm))
101 		gpio_set_value(pdata->dcm, ta_in ? 1 : 0);
102 
103 	/* Charger Enable / Disable (cen is negated) */
104 	if (gpio_is_valid(pdata->cen))
105 		gpio_set_value(pdata->cen, ta_in ? 0 :
106 				(data->usb_in ? 0 : 1));
107 
108 	dev_dbg(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ?
109 			"Connected" : "Disconnected");
110 
111 	old_type = data->psy_desc.type;
112 
113 	if (data->ta_in)
114 		data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
115 	else if (data->usb_in)
116 		data->psy_desc.type = POWER_SUPPLY_TYPE_USB;
117 	else
118 		data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
119 
120 	if (old_type != data->psy_desc.type)
121 		power_supply_changed(data->psy);
122 
123 	return IRQ_HANDLED;
124 }
125 
126 static irqreturn_t max8903_usbin(int irq, void *_data)
127 {
128 	struct max8903_data *data = _data;
129 	struct max8903_pdata *pdata = data->pdata;
130 	bool usb_in;
131 	enum power_supply_type old_type;
132 
133 	usb_in = gpio_get_value(pdata->uok) ? false : true;
134 
135 	if (usb_in == data->usb_in)
136 		return IRQ_HANDLED;
137 
138 	data->usb_in = usb_in;
139 
140 	/* Do not touch Current-Limit-Mode */
141 
142 	/* Charger Enable / Disable (cen is negated) */
143 	if (gpio_is_valid(pdata->cen))
144 		gpio_set_value(pdata->cen, usb_in ? 0 :
145 				(data->ta_in ? 0 : 1));
146 
147 	dev_dbg(data->dev, "USB Charger %s.\n", usb_in ?
148 			"Connected" : "Disconnected");
149 
150 	old_type = data->psy_desc.type;
151 
152 	if (data->ta_in)
153 		data->psy_desc.type = POWER_SUPPLY_TYPE_MAINS;
154 	else if (data->usb_in)
155 		data->psy_desc.type = POWER_SUPPLY_TYPE_USB;
156 	else
157 		data->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY;
158 
159 	if (old_type != data->psy_desc.type)
160 		power_supply_changed(data->psy);
161 
162 	return IRQ_HANDLED;
163 }
164 
165 static irqreturn_t max8903_fault(int irq, void *_data)
166 {
167 	struct max8903_data *data = _data;
168 	struct max8903_pdata *pdata = data->pdata;
169 	bool fault;
170 
171 	fault = gpio_get_value(pdata->flt) ? false : true;
172 
173 	if (fault == data->fault)
174 		return IRQ_HANDLED;
175 
176 	data->fault = fault;
177 
178 	if (fault)
179 		dev_err(data->dev, "Charger suffers a fault and stops.\n");
180 	else
181 		dev_err(data->dev, "Charger recovered from a fault.\n");
182 
183 	return IRQ_HANDLED;
184 }
185 
186 static struct max8903_pdata *max8903_parse_dt_data(struct device *dev)
187 {
188 	struct device_node *np = dev->of_node;
189 	struct max8903_pdata *pdata = NULL;
190 
191 	if (!np)
192 		return NULL;
193 
194 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
195 	if (!pdata)
196 		return NULL;
197 
198 	pdata->dc_valid = false;
199 	pdata->usb_valid = false;
200 
201 	pdata->cen = of_get_named_gpio(np, "cen-gpios", 0);
202 	if (!gpio_is_valid(pdata->cen))
203 		pdata->cen = -EINVAL;
204 
205 	pdata->chg = of_get_named_gpio(np, "chg-gpios", 0);
206 	if (!gpio_is_valid(pdata->chg))
207 		pdata->chg = -EINVAL;
208 
209 	pdata->flt = of_get_named_gpio(np, "flt-gpios", 0);
210 	if (!gpio_is_valid(pdata->flt))
211 		pdata->flt = -EINVAL;
212 
213 	pdata->usus = of_get_named_gpio(np, "usus-gpios", 0);
214 	if (!gpio_is_valid(pdata->usus))
215 		pdata->usus = -EINVAL;
216 
217 	pdata->dcm = of_get_named_gpio(np, "dcm-gpios", 0);
218 	if (!gpio_is_valid(pdata->dcm))
219 		pdata->dcm = -EINVAL;
220 
221 	pdata->dok = of_get_named_gpio(np, "dok-gpios", 0);
222 	if (!gpio_is_valid(pdata->dok))
223 		pdata->dok = -EINVAL;
224 	else
225 		pdata->dc_valid = true;
226 
227 	pdata->uok = of_get_named_gpio(np, "uok-gpios", 0);
228 	if (!gpio_is_valid(pdata->uok))
229 		pdata->uok = -EINVAL;
230 	else
231 		pdata->usb_valid = true;
232 
233 	return pdata;
234 }
235 
236 static int max8903_setup_gpios(struct platform_device *pdev)
237 {
238 	struct max8903_data *data = platform_get_drvdata(pdev);
239 	struct device *dev = &pdev->dev;
240 	struct max8903_pdata *pdata = pdev->dev.platform_data;
241 	int ret = 0;
242 	int gpio;
243 	int ta_in = 0;
244 	int usb_in = 0;
245 
246 	if (pdata->dc_valid) {
247 		if (gpio_is_valid(pdata->dok)) {
248 			ret = devm_gpio_request(dev, pdata->dok,
249 						data->psy_desc.name);
250 			if (ret) {
251 				dev_err(dev,
252 					"Failed GPIO request for dok: %d err %d\n",
253 					pdata->dok, ret);
254 				return ret;
255 			}
256 
257 			gpio = pdata->dok; /* PULL_UPed Interrupt */
258 			ta_in = gpio_get_value(gpio) ? 0 : 1;
259 		} else {
260 			dev_err(dev, "When DC is wired, DOK should be wired as well.\n");
261 			return -EINVAL;
262 		}
263 	}
264 
265 	if (gpio_is_valid(pdata->dcm)) {
266 		ret = devm_gpio_request(dev, pdata->dcm, data->psy_desc.name);
267 		if (ret) {
268 			dev_err(dev,
269 				"Failed GPIO request for dcm: %d err %d\n",
270 				pdata->dcm, ret);
271 			return ret;
272 		}
273 
274 		gpio = pdata->dcm; /* Output */
275 		gpio_set_value(gpio, ta_in);
276 	}
277 
278 	if (pdata->usb_valid) {
279 		if (gpio_is_valid(pdata->uok)) {
280 			ret = devm_gpio_request(dev, pdata->uok,
281 						data->psy_desc.name);
282 			if (ret) {
283 				dev_err(dev,
284 					"Failed GPIO request for uok: %d err %d\n",
285 					pdata->uok, ret);
286 				return ret;
287 			}
288 
289 			gpio = pdata->uok;
290 			usb_in = gpio_get_value(gpio) ? 0 : 1;
291 		} else {
292 			dev_err(dev, "When USB is wired, UOK should be wired."
293 					"as well.\n");
294 			return -EINVAL;
295 		}
296 	}
297 
298 	if (gpio_is_valid(pdata->cen)) {
299 		ret = devm_gpio_request(dev, pdata->cen, data->psy_desc.name);
300 		if (ret) {
301 			dev_err(dev,
302 				"Failed GPIO request for cen: %d err %d\n",
303 				pdata->cen, ret);
304 			return ret;
305 		}
306 
307 		gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1);
308 	}
309 
310 	if (gpio_is_valid(pdata->chg)) {
311 		ret = devm_gpio_request(dev, pdata->chg, data->psy_desc.name);
312 		if (ret) {
313 			dev_err(dev,
314 				"Failed GPIO request for chg: %d err %d\n",
315 				pdata->chg, ret);
316 			return ret;
317 		}
318 	}
319 
320 	if (gpio_is_valid(pdata->flt)) {
321 		ret = devm_gpio_request(dev, pdata->flt, data->psy_desc.name);
322 		if (ret) {
323 			dev_err(dev,
324 				"Failed GPIO request for flt: %d err %d\n",
325 				pdata->flt, ret);
326 			return ret;
327 		}
328 	}
329 
330 	if (gpio_is_valid(pdata->usus)) {
331 		ret = devm_gpio_request(dev, pdata->usus, data->psy_desc.name);
332 		if (ret) {
333 			dev_err(dev,
334 				"Failed GPIO request for usus: %d err %d\n",
335 				pdata->usus, ret);
336 			return ret;
337 		}
338 	}
339 
340 	data->fault = false;
341 	data->ta_in = ta_in;
342 	data->usb_in = usb_in;
343 
344 	return 0;
345 }
346 
347 static int max8903_probe(struct platform_device *pdev)
348 {
349 	struct max8903_data *data;
350 	struct device *dev = &pdev->dev;
351 	struct max8903_pdata *pdata = pdev->dev.platform_data;
352 	struct power_supply_config psy_cfg = {};
353 	int ret = 0;
354 
355 	data = devm_kzalloc(dev, sizeof(struct max8903_data), GFP_KERNEL);
356 	if (!data)
357 		return -ENOMEM;
358 
359 	if (IS_ENABLED(CONFIG_OF) && !pdata && dev->of_node)
360 		pdata = max8903_parse_dt_data(dev);
361 
362 	if (!pdata) {
363 		dev_err(dev, "No platform data.\n");
364 		return -EINVAL;
365 	}
366 
367 	pdev->dev.platform_data = pdata;
368 	data->pdata = pdata;
369 	data->dev = dev;
370 	platform_set_drvdata(pdev, data);
371 
372 	if (pdata->dc_valid == false && pdata->usb_valid == false) {
373 		dev_err(dev, "No valid power sources.\n");
374 		return -EINVAL;
375 	}
376 
377 	ret = max8903_setup_gpios(pdev);
378 	if (ret)
379 		return ret;
380 
381 	data->psy_desc.name = "max8903_charger";
382 	data->psy_desc.type = (data->ta_in) ? POWER_SUPPLY_TYPE_MAINS :
383 			((data->usb_in) ? POWER_SUPPLY_TYPE_USB :
384 			 POWER_SUPPLY_TYPE_BATTERY);
385 	data->psy_desc.get_property = max8903_get_property;
386 	data->psy_desc.properties = max8903_charger_props;
387 	data->psy_desc.num_properties = ARRAY_SIZE(max8903_charger_props);
388 
389 	psy_cfg.of_node = dev->of_node;
390 	psy_cfg.drv_data = data;
391 
392 	data->psy = devm_power_supply_register(dev, &data->psy_desc, &psy_cfg);
393 	if (IS_ERR(data->psy)) {
394 		dev_err(dev, "failed: power supply register.\n");
395 		return PTR_ERR(data->psy);
396 	}
397 
398 	if (pdata->dc_valid) {
399 		ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->dok),
400 					NULL, max8903_dcin,
401 					IRQF_TRIGGER_FALLING |
402 					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
403 					"MAX8903 DC IN", data);
404 		if (ret) {
405 			dev_err(dev, "Cannot request irq %d for DC (%d)\n",
406 					gpio_to_irq(pdata->dok), ret);
407 			return ret;
408 		}
409 	}
410 
411 	if (pdata->usb_valid) {
412 		ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->uok),
413 					NULL, max8903_usbin,
414 					IRQF_TRIGGER_FALLING |
415 					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
416 					"MAX8903 USB IN", data);
417 		if (ret) {
418 			dev_err(dev, "Cannot request irq %d for USB (%d)\n",
419 					gpio_to_irq(pdata->uok), ret);
420 			return ret;
421 		}
422 	}
423 
424 	if (gpio_is_valid(pdata->flt)) {
425 		ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->flt),
426 					NULL, max8903_fault,
427 					IRQF_TRIGGER_FALLING |
428 					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
429 					"MAX8903 Fault", data);
430 		if (ret) {
431 			dev_err(dev, "Cannot request irq %d for Fault (%d)\n",
432 					gpio_to_irq(pdata->flt), ret);
433 			return ret;
434 		}
435 	}
436 
437 	return 0;
438 }
439 
440 static const struct of_device_id max8903_match_ids[] = {
441 	{ .compatible = "maxim,max8903", },
442 	{ /* sentinel */ }
443 };
444 MODULE_DEVICE_TABLE(of, max8903_match_ids);
445 
446 static struct platform_driver max8903_driver = {
447 	.probe	= max8903_probe,
448 	.driver = {
449 		.name	= "max8903-charger",
450 		.of_match_table = max8903_match_ids
451 	},
452 };
453 
454 module_platform_driver(max8903_driver);
455 
456 MODULE_LICENSE("GPL");
457 MODULE_DESCRIPTION("MAX8903 Charger Driver");
458 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
459 MODULE_ALIAS("platform:max8903-charger");
460