2 * Battery charger driver for TI's tps65090
4 * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include <linux/delay.h>
19 #include <linux/err.h>
20 #include <linux/init.h>
21 #include <linux/interrupt.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/of_device.h>
25 #include <linux/platform_device.h>
26 #include <linux/power_supply.h>
27 #include <linux/slab.h>
29 #include <linux/mfd/tps65090.h>
31 #define TPS65090_REG_INTR_STS 0x00
32 #define TPS65090_REG_INTR_MASK 0x02
33 #define TPS65090_REG_CG_CTRL0 0x04
34 #define TPS65090_REG_CG_CTRL1 0x05
35 #define TPS65090_REG_CG_CTRL2 0x06
36 #define TPS65090_REG_CG_CTRL3 0x07
37 #define TPS65090_REG_CG_CTRL4 0x08
38 #define TPS65090_REG_CG_CTRL5 0x09
39 #define TPS65090_REG_CG_STATUS1 0x0a
40 #define TPS65090_REG_CG_STATUS2 0x0b
42 #define TPS65090_CHARGER_ENABLE BIT(0)
43 #define TPS65090_VACG BIT(1)
44 #define TPS65090_NOITERM BIT(5)
46 struct tps65090_charger
{
51 struct power_supply ac
;
52 struct tps65090_platform_data
*pdata
;
55 static enum power_supply_property tps65090_ac_props
[] = {
56 POWER_SUPPLY_PROP_ONLINE
,
59 static int tps65090_low_chrg_current(struct tps65090_charger
*charger
)
63 ret
= tps65090_write(charger
->dev
->parent
, TPS65090_REG_CG_CTRL5
,
66 dev_err(charger
->dev
, "%s(): error reading in register 0x%x\n",
67 __func__
, TPS65090_REG_CG_CTRL5
);
73 static int tps65090_enable_charging(struct tps65090_charger
*charger
)
78 ret
= tps65090_read(charger
->dev
->parent
, TPS65090_REG_CG_CTRL0
,
81 dev_err(charger
->dev
, "%s(): error reading in register 0x%x\n",
82 __func__
, TPS65090_REG_CG_CTRL0
);
86 ret
= tps65090_write(charger
->dev
->parent
, TPS65090_REG_CG_CTRL0
,
87 (ctrl0
| TPS65090_CHARGER_ENABLE
));
89 dev_err(charger
->dev
, "%s(): error writing in register 0x%x\n",
90 __func__
, TPS65090_REG_CG_CTRL0
);
96 static int tps65090_config_charger(struct tps65090_charger
*charger
)
101 if (charger
->pdata
->enable_low_current_chrg
) {
102 ret
= tps65090_low_chrg_current(charger
);
104 dev_err(charger
->dev
,
105 "error configuring low charge current\n");
110 /* Enable the VACG interrupt for AC power detect */
111 ret
= tps65090_read(charger
->dev
->parent
, TPS65090_REG_INTR_MASK
,
114 dev_err(charger
->dev
, "%s(): error reading in register 0x%x\n",
115 __func__
, TPS65090_REG_INTR_MASK
);
119 ret
= tps65090_write(charger
->dev
->parent
, TPS65090_REG_INTR_MASK
,
120 (intrmask
| TPS65090_VACG
));
122 dev_err(charger
->dev
, "%s(): error writing in register 0x%x\n",
123 __func__
, TPS65090_REG_CG_CTRL0
);
130 static int tps65090_ac_get_property(struct power_supply
*psy
,
131 enum power_supply_property psp
,
132 union power_supply_propval
*val
)
134 struct tps65090_charger
*charger
= container_of(psy
,
135 struct tps65090_charger
, ac
);
137 if (psp
== POWER_SUPPLY_PROP_ONLINE
) {
138 val
->intval
= charger
->ac_online
;
139 charger
->prev_ac_online
= charger
->ac_online
;
145 static irqreturn_t
tps65090_charger_isr(int irq
, void *dev_id
)
147 struct tps65090_charger
*charger
= dev_id
;
152 ret
= tps65090_read(charger
->dev
->parent
, TPS65090_REG_CG_STATUS1
,
155 dev_err(charger
->dev
, "%s(): Error in reading reg 0x%x\n",
156 __func__
, TPS65090_REG_CG_STATUS1
);
160 ret
= tps65090_read(charger
->dev
->parent
, TPS65090_REG_INTR_STS
,
163 dev_err(charger
->dev
, "%s(): Error in reading reg 0x%x\n",
164 __func__
, TPS65090_REG_INTR_STS
);
168 if (intrsts
& TPS65090_VACG
) {
169 ret
= tps65090_enable_charging(charger
);
172 charger
->ac_online
= 1;
174 charger
->ac_online
= 0;
177 /* Clear interrupts. */
178 ret
= tps65090_write(charger
->dev
->parent
, TPS65090_REG_INTR_STS
, 0x00);
180 dev_err(charger
->dev
, "%s(): Error in writing reg 0x%x\n",
181 __func__
, TPS65090_REG_INTR_STS
);
184 if (charger
->prev_ac_online
!= charger
->ac_online
)
185 power_supply_changed(&charger
->ac
);
190 static struct tps65090_platform_data
*
191 tps65090_parse_dt_charger_data(struct platform_device
*pdev
)
193 struct tps65090_platform_data
*pdata
;
194 struct device_node
*np
= pdev
->dev
.of_node
;
197 pdata
= devm_kzalloc(&pdev
->dev
, sizeof(*pdata
), GFP_KERNEL
);
199 dev_err(&pdev
->dev
, "Memory alloc for tps65090_pdata failed\n");
203 prop
= of_property_read_bool(np
, "ti,enable-low-current-chrg");
204 pdata
->enable_low_current_chrg
= prop
;
206 pdata
->irq_base
= -1;
212 static int tps65090_charger_probe(struct platform_device
*pdev
)
214 struct tps65090_charger
*cdata
;
215 struct tps65090_platform_data
*pdata
;
220 pdata
= dev_get_platdata(pdev
->dev
.parent
);
222 if (IS_ENABLED(CONFIG_OF
) && !pdata
&& pdev
->dev
.of_node
)
223 pdata
= tps65090_parse_dt_charger_data(pdev
);
226 dev_err(&pdev
->dev
, "%s():no platform data available\n",
231 cdata
= devm_kzalloc(&pdev
->dev
, sizeof(*cdata
), GFP_KERNEL
);
233 dev_err(&pdev
->dev
, "failed to allocate memory status\n");
237 platform_set_drvdata(pdev
, cdata
);
239 cdata
->dev
= &pdev
->dev
;
240 cdata
->pdata
= pdata
;
242 cdata
->ac
.name
= "tps65090-ac";
243 cdata
->ac
.type
= POWER_SUPPLY_TYPE_MAINS
;
244 cdata
->ac
.get_property
= tps65090_ac_get_property
;
245 cdata
->ac
.properties
= tps65090_ac_props
;
246 cdata
->ac
.num_properties
= ARRAY_SIZE(tps65090_ac_props
);
247 cdata
->ac
.supplied_to
= pdata
->supplied_to
;
248 cdata
->ac
.num_supplicants
= pdata
->num_supplicants
;
249 cdata
->ac
.of_node
= pdev
->dev
.of_node
;
251 ret
= power_supply_register(&pdev
->dev
, &cdata
->ac
);
253 dev_err(&pdev
->dev
, "failed: power supply register\n");
257 irq
= platform_get_irq(pdev
, 0);
259 dev_warn(&pdev
->dev
, "Unable to get charger irq = %d\n", irq
);
261 goto fail_unregister_supply
;
266 ret
= devm_request_threaded_irq(&pdev
->dev
, irq
, NULL
,
267 tps65090_charger_isr
, 0, "tps65090-charger", cdata
);
269 dev_err(cdata
->dev
, "Unable to register irq %d err %d\n", irq
,
271 goto fail_unregister_supply
;
274 ret
= tps65090_config_charger(cdata
);
276 dev_err(&pdev
->dev
, "charger config failed, err %d\n", ret
);
277 goto fail_unregister_supply
;
280 /* Check for charger presence */
281 ret
= tps65090_read(cdata
->dev
->parent
, TPS65090_REG_CG_STATUS1
,
284 dev_err(cdata
->dev
, "%s(): Error in reading reg 0x%x", __func__
,
285 TPS65090_REG_CG_STATUS1
);
286 goto fail_unregister_supply
;
290 ret
= tps65090_enable_charging(cdata
);
292 dev_err(cdata
->dev
, "error enabling charger\n");
293 goto fail_unregister_supply
;
295 cdata
->ac_online
= 1;
296 power_supply_changed(&cdata
->ac
);
301 fail_unregister_supply
:
302 power_supply_unregister(&cdata
->ac
);
307 static int tps65090_charger_remove(struct platform_device
*pdev
)
309 struct tps65090_charger
*cdata
= platform_get_drvdata(pdev
);
311 power_supply_unregister(&cdata
->ac
);
316 static struct of_device_id of_tps65090_charger_match
[] = {
317 { .compatible
= "ti,tps65090-charger", },
321 static struct platform_driver tps65090_charger_driver
= {
323 .name
= "tps65090-charger",
324 .of_match_table
= of_tps65090_charger_match
,
325 .owner
= THIS_MODULE
,
327 .probe
= tps65090_charger_probe
,
328 .remove
= tps65090_charger_remove
,
330 module_platform_driver(tps65090_charger_driver
);
332 MODULE_LICENSE("GPL v2");
333 MODULE_AUTHOR("Syed Rafiuddin <srafiuddin@nvidia.com>");
334 MODULE_DESCRIPTION("tps65090 battery charger driver");