2 * Generic battery driver code using IIO
3 * Copyright (C) 2012, Anish Kumar <anish198519851985@gmail.com>
4 * based on jz4740-battery.c
5 * based on s3c_adc_battery.c
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive for
12 #include <linux/interrupt.h>
13 #include <linux/platform_device.h>
14 #include <linux/power_supply.h>
15 #include <linux/gpio.h>
16 #include <linux/err.h>
17 #include <linux/timer.h>
18 #include <linux/jiffies.h>
19 #include <linux/errno.h>
20 #include <linux/init.h>
21 #include <linux/module.h>
22 #include <linux/slab.h>
23 #include <linux/iio/consumer.h>
24 #include <linux/iio/types.h>
25 #include <linux/power/generic-adc-battery.h>
27 #define JITTER_DEFAULT 10 /* hope 10ms is enough */
37 * gab_chan_name suggests the standard channel names for commonly used
40 static const char *const gab_chan_name
[] = {
41 [GAB_VOLTAGE
] = "voltage",
42 [GAB_CURRENT
] = "current",
43 [GAB_POWER
] = "power",
47 struct power_supply
*psy
;
48 struct power_supply_desc psy_desc
;
49 struct iio_channel
*channel
[GAB_MAX_CHAN_TYPE
];
50 struct gab_platform_data
*pdata
;
51 struct delayed_work bat_work
;
57 static struct gab
*to_generic_bat(struct power_supply
*psy
)
59 return power_supply_get_drvdata(psy
);
62 static void gab_ext_power_changed(struct power_supply
*psy
)
64 struct gab
*adc_bat
= to_generic_bat(psy
);
66 schedule_delayed_work(&adc_bat
->bat_work
, msecs_to_jiffies(0));
69 static const enum power_supply_property gab_props
[] = {
70 POWER_SUPPLY_PROP_STATUS
,
71 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN
,
72 POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN
,
73 POWER_SUPPLY_PROP_CHARGE_NOW
,
74 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
75 POWER_SUPPLY_PROP_CURRENT_NOW
,
76 POWER_SUPPLY_PROP_TECHNOLOGY
,
77 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
,
78 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
,
79 POWER_SUPPLY_PROP_MODEL_NAME
,
83 * This properties are set based on the received platform data and this
84 * should correspond one-to-one with enum chan_type.
86 static const enum power_supply_property gab_dyn_props
[] = {
87 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
88 POWER_SUPPLY_PROP_CURRENT_NOW
,
89 POWER_SUPPLY_PROP_POWER_NOW
,
92 static bool gab_charge_finished(struct gab
*adc_bat
)
94 struct gab_platform_data
*pdata
= adc_bat
->pdata
;
95 bool ret
= gpio_get_value(pdata
->gpio_charge_finished
);
96 bool inv
= pdata
->gpio_inverted
;
98 if (!gpio_is_valid(pdata
->gpio_charge_finished
))
103 static int gab_get_status(struct gab
*adc_bat
)
105 struct gab_platform_data
*pdata
= adc_bat
->pdata
;
106 struct power_supply_info
*bat_info
;
108 bat_info
= &pdata
->battery_info
;
109 if (adc_bat
->level
== bat_info
->charge_full_design
)
110 return POWER_SUPPLY_STATUS_FULL
;
111 return adc_bat
->status
;
114 static enum gab_chan_type
gab_prop_to_chan(enum power_supply_property psp
)
117 case POWER_SUPPLY_PROP_POWER_NOW
:
119 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
121 case POWER_SUPPLY_PROP_CURRENT_NOW
:
130 static int read_channel(struct gab
*adc_bat
, enum power_supply_property psp
,
136 chan_index
= gab_prop_to_chan(psp
);
137 ret
= iio_read_channel_processed(adc_bat
->channel
[chan_index
],
140 pr_err("read channel error\n");
144 static int gab_get_property(struct power_supply
*psy
,
145 enum power_supply_property psp
, union power_supply_propval
*val
)
148 struct gab_platform_data
*pdata
;
149 struct power_supply_info
*bat_info
;
153 adc_bat
= to_generic_bat(psy
);
155 dev_err(&psy
->dev
, "no battery infos ?!\n");
158 pdata
= adc_bat
->pdata
;
159 bat_info
= &pdata
->battery_info
;
162 case POWER_SUPPLY_PROP_STATUS
:
163 val
->intval
= gab_get_status(adc_bat
);
165 case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN
:
168 case POWER_SUPPLY_PROP_CHARGE_NOW
:
169 val
->intval
= pdata
->cal_charge(result
);
171 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
172 case POWER_SUPPLY_PROP_CURRENT_NOW
:
173 case POWER_SUPPLY_PROP_POWER_NOW
:
174 ret
= read_channel(adc_bat
, psp
, &result
);
177 val
->intval
= result
;
179 case POWER_SUPPLY_PROP_TECHNOLOGY
:
180 val
->intval
= bat_info
->technology
;
182 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN
:
183 val
->intval
= bat_info
->voltage_min_design
;
185 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
:
186 val
->intval
= bat_info
->voltage_max_design
;
188 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN
:
189 val
->intval
= bat_info
->charge_full_design
;
191 case POWER_SUPPLY_PROP_MODEL_NAME
:
192 val
->strval
= bat_info
->name
;
201 static void gab_work(struct work_struct
*work
)
204 struct gab_platform_data
*pdata
;
205 struct delayed_work
*delayed_work
;
209 delayed_work
= container_of(work
, struct delayed_work
, work
);
210 adc_bat
= container_of(delayed_work
, struct gab
, bat_work
);
211 pdata
= adc_bat
->pdata
;
212 status
= adc_bat
->status
;
214 is_plugged
= power_supply_am_i_supplied(adc_bat
->psy
);
215 adc_bat
->cable_plugged
= is_plugged
;
218 adc_bat
->status
= POWER_SUPPLY_STATUS_DISCHARGING
;
219 else if (gab_charge_finished(adc_bat
))
220 adc_bat
->status
= POWER_SUPPLY_STATUS_NOT_CHARGING
;
222 adc_bat
->status
= POWER_SUPPLY_STATUS_CHARGING
;
224 if (status
!= adc_bat
->status
)
225 power_supply_changed(adc_bat
->psy
);
228 static irqreturn_t
gab_charged(int irq
, void *dev_id
)
230 struct gab
*adc_bat
= dev_id
;
231 struct gab_platform_data
*pdata
= adc_bat
->pdata
;
234 delay
= pdata
->jitter_delay
? pdata
->jitter_delay
: JITTER_DEFAULT
;
235 schedule_delayed_work(&adc_bat
->bat_work
,
236 msecs_to_jiffies(delay
));
240 static int gab_probe(struct platform_device
*pdev
)
243 struct power_supply_desc
*psy_desc
;
244 struct power_supply_config psy_cfg
= {};
245 struct gab_platform_data
*pdata
= pdev
->dev
.platform_data
;
246 enum power_supply_property
*properties
;
251 adc_bat
= devm_kzalloc(&pdev
->dev
, sizeof(*adc_bat
), GFP_KERNEL
);
253 dev_err(&pdev
->dev
, "failed to allocate memory\n");
257 psy_cfg
.drv_data
= adc_bat
;
258 psy_desc
= &adc_bat
->psy_desc
;
259 psy_desc
->name
= pdata
->battery_info
.name
;
261 /* bootup default values for the battery */
262 adc_bat
->cable_plugged
= false;
263 adc_bat
->status
= POWER_SUPPLY_STATUS_DISCHARGING
;
264 psy_desc
->type
= POWER_SUPPLY_TYPE_BATTERY
;
265 psy_desc
->get_property
= gab_get_property
;
266 psy_desc
->external_power_changed
= gab_ext_power_changed
;
267 adc_bat
->pdata
= pdata
;
270 * copying the static properties and allocating extra memory for holding
271 * the extra configurable properties received from platform data.
273 psy_desc
->properties
= kcalloc(ARRAY_SIZE(gab_props
) +
274 ARRAY_SIZE(gab_chan_name
),
275 sizeof(*psy_desc
->properties
),
277 if (!psy_desc
->properties
) {
282 memcpy(psy_desc
->properties
, gab_props
, sizeof(gab_props
));
283 properties
= (enum power_supply_property
*)
284 ((char *)psy_desc
->properties
+ sizeof(gab_props
));
287 * getting channel from iio and copying the battery properties
288 * based on the channel supported by consumer device.
290 for (chan
= 0; chan
< ARRAY_SIZE(gab_chan_name
); chan
++) {
291 adc_bat
->channel
[chan
] = iio_channel_get(&pdev
->dev
,
292 gab_chan_name
[chan
]);
293 if (IS_ERR(adc_bat
->channel
[chan
])) {
294 ret
= PTR_ERR(adc_bat
->channel
[chan
]);
295 adc_bat
->channel
[chan
] = NULL
;
297 /* copying properties for supported channels only */
298 memcpy(properties
+ sizeof(*(psy_desc
->properties
)) * index
,
299 &gab_dyn_props
[chan
],
300 sizeof(gab_dyn_props
[chan
]));
305 /* none of the channels are supported so let's bail out */
308 goto second_mem_fail
;
312 * Total number of properties is equal to static properties
313 * plus the dynamic properties.Some properties may not be set
314 * as come channels may be not be supported by the device.So
315 * we need to take care of that.
317 psy_desc
->num_properties
= ARRAY_SIZE(gab_props
) + index
;
319 adc_bat
->psy
= power_supply_register(&pdev
->dev
, psy_desc
, &psy_cfg
);
320 if (IS_ERR(adc_bat
->psy
)) {
321 ret
= PTR_ERR(adc_bat
->psy
);
325 INIT_DELAYED_WORK(&adc_bat
->bat_work
, gab_work
);
327 if (gpio_is_valid(pdata
->gpio_charge_finished
)) {
329 ret
= gpio_request(pdata
->gpio_charge_finished
, "charged");
333 irq
= gpio_to_irq(pdata
->gpio_charge_finished
);
334 ret
= request_any_context_irq(irq
, gab_charged
,
335 IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING
,
336 "battery charged", adc_bat
);
341 platform_set_drvdata(pdev
, adc_bat
);
343 /* Schedule timer to check current status */
344 schedule_delayed_work(&adc_bat
->bat_work
,
345 msecs_to_jiffies(0));
349 gpio_free(pdata
->gpio_charge_finished
);
351 power_supply_unregister(adc_bat
->psy
);
353 for (chan
= 0; chan
< ARRAY_SIZE(gab_chan_name
); chan
++) {
354 if (adc_bat
->channel
[chan
])
355 iio_channel_release(adc_bat
->channel
[chan
]);
358 kfree(psy_desc
->properties
);
363 static int gab_remove(struct platform_device
*pdev
)
366 struct gab
*adc_bat
= platform_get_drvdata(pdev
);
367 struct gab_platform_data
*pdata
= adc_bat
->pdata
;
369 power_supply_unregister(adc_bat
->psy
);
371 if (gpio_is_valid(pdata
->gpio_charge_finished
)) {
372 free_irq(gpio_to_irq(pdata
->gpio_charge_finished
), adc_bat
);
373 gpio_free(pdata
->gpio_charge_finished
);
376 for (chan
= 0; chan
< ARRAY_SIZE(gab_chan_name
); chan
++) {
377 if (adc_bat
->channel
[chan
])
378 iio_channel_release(adc_bat
->channel
[chan
]);
381 kfree(adc_bat
->psy_desc
.properties
);
382 cancel_delayed_work(&adc_bat
->bat_work
);
387 static int gab_suspend(struct device
*dev
)
389 struct gab
*adc_bat
= dev_get_drvdata(dev
);
391 cancel_delayed_work_sync(&adc_bat
->bat_work
);
392 adc_bat
->status
= POWER_SUPPLY_STATUS_UNKNOWN
;
396 static int gab_resume(struct device
*dev
)
398 struct gab
*adc_bat
= dev_get_drvdata(dev
);
399 struct gab_platform_data
*pdata
= adc_bat
->pdata
;
402 delay
= pdata
->jitter_delay
? pdata
->jitter_delay
: JITTER_DEFAULT
;
404 /* Schedule timer to check current status */
405 schedule_delayed_work(&adc_bat
->bat_work
,
406 msecs_to_jiffies(delay
));
410 static const struct dev_pm_ops gab_pm_ops
= {
411 .suspend
= gab_suspend
,
412 .resume
= gab_resume
,
415 #define GAB_PM_OPS (&gab_pm_ops)
417 #define GAB_PM_OPS (NULL)
420 static struct platform_driver gab_driver
= {
422 .name
= "generic-adc-battery",
426 .remove
= gab_remove
,
428 module_platform_driver(gab_driver
);
430 MODULE_AUTHOR("anish kumar <anish198519851985@gmail.com>");
431 MODULE_DESCRIPTION("generic battery driver using IIO");
432 MODULE_LICENSE("GPL");