1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
4 * Driver for chargers which report their online status through a GPIO pin
7 #include <linux/device.h>
8 #include <linux/init.h>
9 #include <linux/interrupt.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/power_supply.h>
14 #include <linux/slab.h>
16 #include <linux/gpio/consumer.h>
18 #include <linux/power/gpio-charger.h>
28 unsigned int charge_status_irq
;
31 struct power_supply
*charger
;
32 struct power_supply_desc charger_desc
;
33 struct gpio_desc
*gpiod
;
34 struct gpio_desc
*charge_status
;
36 struct gpio_descs
*current_limit_gpios
;
37 struct gpio_mapping
*current_limit_map
;
38 u32 current_limit_map_size
;
39 u32 charge_current_limit
;
42 static irqreturn_t
gpio_charger_irq(int irq
, void *devid
)
44 struct power_supply
*charger
= devid
;
46 power_supply_changed(charger
);
51 static inline struct gpio_charger
*psy_to_gpio_charger(struct power_supply
*psy
)
53 return power_supply_get_drvdata(psy
);
56 static int set_charge_current_limit(struct gpio_charger
*gpio_charger
, int val
)
58 struct gpio_mapping mapping
;
59 int ndescs
= gpio_charger
->current_limit_gpios
->ndescs
;
60 struct gpio_desc
**gpios
= gpio_charger
->current_limit_gpios
->desc
;
63 if (!gpio_charger
->current_limit_map_size
)
66 for (i
= 0; i
< gpio_charger
->current_limit_map_size
; i
++) {
67 if (gpio_charger
->current_limit_map
[i
].limit_ua
<= val
)
70 mapping
= gpio_charger
->current_limit_map
[i
];
72 for (i
= 0; i
< ndescs
; i
++) {
73 bool val
= (mapping
.gpiodata
>> i
) & 1;
74 gpiod_set_value_cansleep(gpios
[ndescs
-i
-1], val
);
77 gpio_charger
->charge_current_limit
= mapping
.limit_ua
;
79 dev_dbg(gpio_charger
->dev
, "set charge current limit to %d (requested: %d)\n",
80 gpio_charger
->charge_current_limit
, val
);
85 static int gpio_charger_get_property(struct power_supply
*psy
,
86 enum power_supply_property psp
, union power_supply_propval
*val
)
88 struct gpio_charger
*gpio_charger
= psy_to_gpio_charger(psy
);
91 case POWER_SUPPLY_PROP_ONLINE
:
92 val
->intval
= gpiod_get_value_cansleep(gpio_charger
->gpiod
);
94 case POWER_SUPPLY_PROP_STATUS
:
95 if (gpiod_get_value_cansleep(gpio_charger
->charge_status
))
96 val
->intval
= POWER_SUPPLY_STATUS_CHARGING
;
98 val
->intval
= POWER_SUPPLY_STATUS_NOT_CHARGING
;
100 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
:
101 val
->intval
= gpio_charger
->charge_current_limit
;
110 static int gpio_charger_set_property(struct power_supply
*psy
,
111 enum power_supply_property psp
, const union power_supply_propval
*val
)
113 struct gpio_charger
*gpio_charger
= psy_to_gpio_charger(psy
);
116 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
:
117 return set_charge_current_limit(gpio_charger
, val
->intval
);
125 static int gpio_charger_property_is_writeable(struct power_supply
*psy
,
126 enum power_supply_property psp
)
129 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
:
138 static enum power_supply_type
gpio_charger_get_type(struct device
*dev
)
140 const char *chargetype
;
142 if (!device_property_read_string(dev
, "charger-type", &chargetype
)) {
143 if (!strcmp("unknown", chargetype
))
144 return POWER_SUPPLY_TYPE_UNKNOWN
;
145 if (!strcmp("battery", chargetype
))
146 return POWER_SUPPLY_TYPE_BATTERY
;
147 if (!strcmp("ups", chargetype
))
148 return POWER_SUPPLY_TYPE_UPS
;
149 if (!strcmp("mains", chargetype
))
150 return POWER_SUPPLY_TYPE_MAINS
;
151 if (!strcmp("usb-sdp", chargetype
))
152 return POWER_SUPPLY_TYPE_USB
;
153 if (!strcmp("usb-dcp", chargetype
))
154 return POWER_SUPPLY_TYPE_USB
;
155 if (!strcmp("usb-cdp", chargetype
))
156 return POWER_SUPPLY_TYPE_USB
;
157 if (!strcmp("usb-aca", chargetype
))
158 return POWER_SUPPLY_TYPE_USB
;
160 dev_warn(dev
, "unknown charger type %s\n", chargetype
);
162 return POWER_SUPPLY_TYPE_UNKNOWN
;
165 static int gpio_charger_get_irq(struct device
*dev
, void *dev_id
,
166 struct gpio_desc
*gpio
)
168 int ret
, irq
= gpiod_to_irq(gpio
);
171 ret
= devm_request_any_context_irq(dev
, irq
, gpio_charger_irq
,
172 IRQF_TRIGGER_RISING
|
173 IRQF_TRIGGER_FALLING
,
177 dev_warn(dev
, "Failed to request irq: %d\n", ret
);
185 static int init_charge_current_limit(struct device
*dev
,
186 struct gpio_charger
*gpio_charger
)
189 u32 cur_limit
= U32_MAX
;
191 gpio_charger
->current_limit_gpios
= devm_gpiod_get_array_optional(dev
,
192 "charge-current-limit", GPIOD_OUT_LOW
);
193 if (IS_ERR(gpio_charger
->current_limit_gpios
)) {
194 dev_err(dev
, "error getting current-limit GPIOs\n");
195 return PTR_ERR(gpio_charger
->current_limit_gpios
);
198 if (!gpio_charger
->current_limit_gpios
)
201 len
= device_property_read_u32_array(dev
, "charge-current-limit-mapping",
206 if (len
== 0 || len
% 2) {
207 dev_err(dev
, "invalid charge-current-limit-mapping length\n");
211 gpio_charger
->current_limit_map
= devm_kmalloc_array(dev
,
212 len
/ 2, sizeof(*gpio_charger
->current_limit_map
), GFP_KERNEL
);
213 if (!gpio_charger
->current_limit_map
)
216 gpio_charger
->current_limit_map_size
= len
/ 2;
218 len
= device_property_read_u32_array(dev
, "charge-current-limit-mapping",
219 (u32
*) gpio_charger
->current_limit_map
, len
);
223 for (i
=0; i
< gpio_charger
->current_limit_map_size
; i
++) {
224 if (gpio_charger
->current_limit_map
[i
].limit_ua
> cur_limit
) {
225 dev_err(dev
, "charge-current-limit-mapping not sorted by current in descending order\n");
229 cur_limit
= gpio_charger
->current_limit_map
[i
].limit_ua
;
232 /* default to smallest current limitation for safety reasons */
233 len
= gpio_charger
->current_limit_map_size
- 1;
234 set_charge_current_limit(gpio_charger
,
235 gpio_charger
->current_limit_map
[len
].limit_ua
);
241 * The entries will be overwritten by driver's probe routine depending
242 * on the available features. This list ensures, that the array is big
243 * enough for all optional features.
245 static enum power_supply_property gpio_charger_properties
[] = {
246 POWER_SUPPLY_PROP_ONLINE
,
247 POWER_SUPPLY_PROP_STATUS
,
248 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
,
251 static int gpio_charger_probe(struct platform_device
*pdev
)
253 struct device
*dev
= &pdev
->dev
;
254 const struct gpio_charger_platform_data
*pdata
= dev
->platform_data
;
255 struct power_supply_config psy_cfg
= {};
256 struct gpio_charger
*gpio_charger
;
257 struct power_supply_desc
*charger_desc
;
258 struct gpio_desc
*charge_status
;
259 int charge_status_irq
;
263 if (!pdata
&& !dev
->of_node
) {
264 dev_err(dev
, "No platform data\n");
268 gpio_charger
= devm_kzalloc(dev
, sizeof(*gpio_charger
), GFP_KERNEL
);
271 gpio_charger
->dev
= dev
;
274 * This will fetch a GPIO descriptor from device tree, ACPI or
275 * boardfile descriptor tables. It's good to try this first.
277 gpio_charger
->gpiod
= devm_gpiod_get_optional(dev
, NULL
, GPIOD_IN
);
278 if (IS_ERR(gpio_charger
->gpiod
)) {
279 /* Just try again if this happens */
280 return dev_err_probe(dev
, PTR_ERR(gpio_charger
->gpiod
),
281 "error getting GPIO descriptor\n");
284 if (gpio_charger
->gpiod
) {
285 gpio_charger_properties
[num_props
] = POWER_SUPPLY_PROP_ONLINE
;
289 charge_status
= devm_gpiod_get_optional(dev
, "charge-status", GPIOD_IN
);
290 if (IS_ERR(charge_status
))
291 return PTR_ERR(charge_status
);
293 gpio_charger
->charge_status
= charge_status
;
294 gpio_charger_properties
[num_props
] = POWER_SUPPLY_PROP_STATUS
;
298 ret
= init_charge_current_limit(dev
, gpio_charger
);
301 if (gpio_charger
->current_limit_map
) {
302 gpio_charger_properties
[num_props
] =
303 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
;
307 charger_desc
= &gpio_charger
->charger_desc
;
308 charger_desc
->properties
= gpio_charger_properties
;
309 charger_desc
->num_properties
= num_props
;
310 charger_desc
->get_property
= gpio_charger_get_property
;
311 charger_desc
->set_property
= gpio_charger_set_property
;
312 charger_desc
->property_is_writeable
=
313 gpio_charger_property_is_writeable
;
315 psy_cfg
.of_node
= dev
->of_node
;
316 psy_cfg
.drv_data
= gpio_charger
;
319 charger_desc
->name
= pdata
->name
;
320 charger_desc
->type
= pdata
->type
;
321 psy_cfg
.supplied_to
= pdata
->supplied_to
;
322 psy_cfg
.num_supplicants
= pdata
->num_supplicants
;
324 charger_desc
->name
= dev
->of_node
->name
;
325 charger_desc
->type
= gpio_charger_get_type(dev
);
328 if (!charger_desc
->name
)
329 charger_desc
->name
= pdev
->name
;
331 gpio_charger
->charger
= devm_power_supply_register(dev
, charger_desc
,
333 if (IS_ERR(gpio_charger
->charger
)) {
334 ret
= PTR_ERR(gpio_charger
->charger
);
335 dev_err(dev
, "Failed to register power supply: %d\n", ret
);
339 gpio_charger
->irq
= gpio_charger_get_irq(dev
, gpio_charger
->charger
,
340 gpio_charger
->gpiod
);
342 charge_status_irq
= gpio_charger_get_irq(dev
, gpio_charger
->charger
,
343 gpio_charger
->charge_status
);
344 gpio_charger
->charge_status_irq
= charge_status_irq
;
346 platform_set_drvdata(pdev
, gpio_charger
);
348 device_init_wakeup(dev
, 1);
353 #ifdef CONFIG_PM_SLEEP
354 static int gpio_charger_suspend(struct device
*dev
)
356 struct gpio_charger
*gpio_charger
= dev_get_drvdata(dev
);
358 if (device_may_wakeup(dev
))
359 gpio_charger
->wakeup_enabled
=
360 !enable_irq_wake(gpio_charger
->irq
);
365 static int gpio_charger_resume(struct device
*dev
)
367 struct gpio_charger
*gpio_charger
= dev_get_drvdata(dev
);
369 if (device_may_wakeup(dev
) && gpio_charger
->wakeup_enabled
)
370 disable_irq_wake(gpio_charger
->irq
);
371 power_supply_changed(gpio_charger
->charger
);
377 static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops
,
378 gpio_charger_suspend
, gpio_charger_resume
);
380 static const struct of_device_id gpio_charger_match
[] = {
381 { .compatible
= "gpio-charger" },
384 MODULE_DEVICE_TABLE(of
, gpio_charger_match
);
386 static struct platform_driver gpio_charger_driver
= {
387 .probe
= gpio_charger_probe
,
389 .name
= "gpio-charger",
390 .pm
= &gpio_charger_pm_ops
,
391 .of_match_table
= gpio_charger_match
,
395 module_platform_driver(gpio_charger_driver
);
397 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
398 MODULE_DESCRIPTION("Driver for chargers only communicating via GPIO(s)");
399 MODULE_LICENSE("GPL");
400 MODULE_ALIAS("platform:gpio-charger");