1 /* drivers/power/rt5025-power.c
2 * I2C Driver for Richtek RT5025 PMIC
3 * Multi function device - multi functional baseband PMIC Power part
6 * Author: CY Huang <cy_huang@richtek.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/i2c.h>
17 #include <linux/power_supply.h>
18 #include <linux/platform_device.h>
19 #include <linux/err.h>
20 #include <linux/version.h>
21 #include <linux/slab.h>
22 #include <linux/mfd/rt5025.h>
23 #include <linux/power/rt5025-power.h>
24 #include <linux/power/rt5025-gauge.h>
25 #include <linux/delay.h>
28 static enum power_supply_property rt5025_adap_props[] = {
29 POWER_SUPPLY_PROP_ONLINE,
32 static char *rt5025_supply_list[] = {
36 static int rt5025_set_charging_current_switch (struct i2c_client *i2c, int onoff)
40 ret = rt5025_set_bits(i2c, RT5025_REG_CHGCTL7, RT5025_CHGCEN_MASK);
42 ret = rt5025_clr_bits(i2c, RT5025_REG_CHGCTL7, RT5025_CHGCEN_MASK);
46 static int rt5025_set_charging_buck(struct i2c_client *i2c, int onoff)
50 ret = rt5025_set_bits(i2c, RT5025_REG_CHGCTL2, RT5025_CHGBUCKEN_MASK);
52 ret = rt5025_clr_bits(i2c, RT5025_REG_CHGCTL2, RT5025_CHGBUCKEN_MASK);
56 static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_val)
62 rt5025_set_charging_current_switch(info->i2c, 1);
63 rt5025_set_charging_buck(info->i2c, 1);
64 info->chg_stat = 0x00;
65 if (info->event_callback)
66 info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_CHARGING);
69 //rt5025_set_charging_current_switch(info->i2c, 1);
70 info->chg_stat = 0x01;
71 if (info->event_callback)
72 info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_CHARGING);
75 rt5025_set_charging_current_switch(info->i2c, 0);
76 info->chg_stat = 0x02;
77 if (info->event_callback)
78 info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_FULL);
81 rt5025_set_charging_buck(info->i2c, 0);
82 rt5025_set_charging_current_switch(info->i2c, 0);
83 info->chg_stat = 0x03;
84 if (info->event_callback)
85 info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_DISCHARGING);
93 int rt5025_power_passirq_to_gauge(struct rt5025_power_info *info)
95 if (info->event_callback)
96 info->event_callback->rt5025_gauge_irq_handler();
99 EXPORT_SYMBOL(rt5025_power_passirq_to_gauge);
101 int rt5025_power_charge_detect(struct rt5025_power_info *info)
104 unsigned char chgstatval = 0;
105 unsigned old_usbval, old_acval, old_chgval, new_usbval, new_acval, new_chgval;
107 old_acval = info->ac_online;
108 old_usbval = info->usb_online;
109 old_chgval = info->chg_stat;
111 ret = rt5025_reg_read(info->i2c, RT5025_REG_CHGSTAT);
114 dev_err(info->dev, "read chg stat reg fail\n");
119 new_acval = (chgstatval&RT5025_CHG_ACONLINE)>>RT5025_CHG_ACSHIFT;
120 if (old_acval != new_acval)
122 info->ac_online = new_acval;
123 power_supply_changed(&info->ac);
125 new_usbval = (chgstatval&RT5025_CHG_USBONLINE)>>RT5025_CHG_USBSHIFT;
126 if (old_usbval != new_usbval)
128 info->usb_online = new_usbval;
129 power_supply_changed(&info->usb);
132 new_chgval = (chgstatval&RT5025_CHGSTAT_MASK)>>RT5025_CHGSTAT_SHIFT;
133 if (new_acval || new_usbval)
135 if (old_chgval != new_chgval)
137 ret = rt5025_chgstat_changed(info, new_chgval);
142 rt5025_set_charging_buck(info->i2c, 0);
143 rt5025_set_charging_current_switch(info->i2c, 0);
144 info->chg_stat = RT5025_CHGSTAT_UNKNOWN;
145 if (info->event_callback)
146 info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_NOT_CHARGING);
151 EXPORT_SYMBOL(rt5025_power_charge_detect);
153 static int rt5025_adap_get_props(struct power_supply *psy,
154 enum power_supply_property psp,
155 union power_supply_propval *val)
157 struct rt5025_power_info *info = dev_get_drvdata(psy->dev->parent);
160 case POWER_SUPPLY_PROP_ONLINE:
161 if (psy->type == POWER_SUPPLY_TYPE_MAINS)
162 val->intval = info->ac_online;
163 else if (psy->type == POWER_SUPPLY_TYPE_USB)
164 val->intval = info->usb_online;
174 static int __devinit rt5025_init_charger(struct rt5025_power_info *info, struct rt5025_power_data* pd)
178 //init charger buckck & charger current en to disable stat
179 info->chg_stat = RT5025_CHGSTAT_UNKNOWN;
180 if (info->event_callback)
181 info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_DISCHARGING);
182 rt5025_set_bits(info->i2c, RT5025_REG_CHGCTL4, RT5025_CHGRST_MASK);
184 //init register setting
185 rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL2, pd->CHGControl2.val);
186 rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL3, pd->CHGControl3.val);
187 rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL4, pd->CHGControl4.val);
188 rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL5, pd->CHGControl5.val);
189 rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL6, pd->CHGControl6.val);
190 rt5025_reg_write(info->i2c, RT5025_REG_CHGCTL7, pd->CHGControl7.val);
192 rt5025_power_charge_detect(info);
197 static int __devinit rt5025_power_probe(struct platform_device *pdev)
199 struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
200 struct rt5025_platform_data *pdata = chip->dev->platform_data;
201 struct rt5025_power_info *pi;
203 printk("%s,line=%d\n", __func__,__LINE__);
205 pi = kzalloc(sizeof(*pi), GFP_KERNEL);
210 pi->dev = &pdev->dev;
212 ret = rt5025_gauge_init(pi);
216 platform_set_drvdata(pdev, pi);
218 pi->ac.name = "rt5025-ac";
219 pi->ac.type = POWER_SUPPLY_TYPE_MAINS;
220 pi->ac.supplied_to = rt5025_supply_list;
221 pi->ac.properties = rt5025_adap_props;
222 pi->ac.num_properties = ARRAY_SIZE(rt5025_adap_props);
223 pi->ac.get_property = rt5025_adap_get_props;
224 ret = power_supply_register(&pdev->dev, &pi->ac);
228 pi->usb.name = "rt5025-usb";
229 pi->usb.type = POWER_SUPPLY_TYPE_USB;
230 pi->ac.supplied_to = rt5025_supply_list;
231 pi->usb.properties = rt5025_adap_props;
232 pi->usb.num_properties = ARRAY_SIZE(rt5025_adap_props);
233 pi->usb.get_property = rt5025_adap_get_props;
234 ret = power_supply_register(&pdev->dev, &pi->usb);
238 rt5025_init_charger(pi, pdata->power_data);
239 chip->power_info = pi;
243 power_supply_unregister(&pi->ac);
250 static int rt5025_power_suspend(struct platform_device *pdev, pm_message_t state)
252 struct rt5025_power_info *pi = platform_get_drvdata(pdev);
254 if (pi->event_callback)
255 pi->event_callback->rt5025_gauge_suspend();
259 static int rt5025_power_resume(struct platform_device *pdev)
261 struct rt5025_power_info *pi = platform_get_drvdata(pdev);
262 if (pi->event_callback)
263 pi->event_callback->rt5025_gauge_resume();
267 static int __devexit rt5025_power_remove(struct platform_device *pdev)
269 struct rt5025_power_info *pi = platform_get_drvdata(pdev);
270 struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
272 if (pi->event_callback)
273 pi->event_callback->rt5025_gauge_remove();
274 power_supply_unregister(&pi->usb);
275 power_supply_unregister(&pi->ac);
276 chip->power_info = NULL;
282 static struct platform_driver rt5025_power_driver =
285 .name = RT5025_DEVICE_NAME "-power",
286 .owner = THIS_MODULE,
288 .probe = rt5025_power_probe,
289 .remove = __devexit_p(rt5025_power_remove),
290 .suspend = rt5025_power_suspend,
291 .resume = rt5025_power_resume,
294 static int __init rt5025_power_init(void)
296 return platform_driver_register(&rt5025_power_driver);
298 subsys_initcall_sync(rt5025_power_init);
300 static void __exit rt5025_power_exit(void)
302 platform_driver_unregister(&rt5025_power_driver);
304 module_exit(rt5025_power_exit);
307 MODULE_LICENSE("GPL v2");
308 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
309 MODULE_DESCRIPTION("Power/Gauge driver for RT5025");
310 MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-power");