]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/power/rt5033_battery.c
Merge tag 'vfio-v3.20-rc1' of git://github.com/awilliam/linux-vfio
[karo-tx-linux.git] / drivers / power / rt5033_battery.c
1 /*
2  * Fuel gauge driver for Richtek RT5033
3  *
4  * Copyright (C) 2014 Samsung Electronics, Co., Ltd.
5  * Author: Beomho Seo <beomho.seo@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 version 2 as
9  * published bythe Free Software Foundation.
10  */
11
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/power_supply.h>
15 #include <linux/mfd/rt5033-private.h>
16 #include <linux/mfd/rt5033.h>
17
18 static int rt5033_battery_get_capacity(struct i2c_client *client)
19 {
20         struct rt5033_battery *battery = i2c_get_clientdata(client);
21         u32 msb;
22
23         regmap_read(battery->regmap, RT5033_FUEL_REG_SOC_H, &msb);
24
25         return msb;
26 }
27
28 static int rt5033_battery_get_present(struct i2c_client *client)
29 {
30         struct rt5033_battery *battery = i2c_get_clientdata(client);
31         u32 val;
32
33         regmap_read(battery->regmap, RT5033_FUEL_REG_CONFIG_L, &val);
34
35         return (val & RT5033_FUEL_BAT_PRESENT) ? true : false;
36 }
37
38 static int rt5033_battery_get_watt_prop(struct i2c_client *client,
39                 enum power_supply_property psp)
40 {
41         struct rt5033_battery *battery = i2c_get_clientdata(client);
42         unsigned int regh, regl;
43         int ret;
44         u32 msb, lsb;
45
46         switch (psp) {
47         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
48                 regh = RT5033_FUEL_REG_VBAT_H;
49                 regl = RT5033_FUEL_REG_VBAT_L;
50                 break;
51         case POWER_SUPPLY_PROP_VOLTAGE_AVG:
52                 regh = RT5033_FUEL_REG_AVG_VOLT_H;
53                 regl = RT5033_FUEL_REG_AVG_VOLT_L;
54                 break;
55         case POWER_SUPPLY_PROP_VOLTAGE_OCV:
56                 regh = RT5033_FUEL_REG_OCV_H;
57                 regl = RT5033_FUEL_REG_OCV_L;
58                 break;
59         default:
60                 return -EINVAL;
61         }
62
63         regmap_read(battery->regmap, regh, &msb);
64         regmap_read(battery->regmap, regl, &lsb);
65
66         ret = ((msb << 4) + (lsb >> 4)) * 1250 / 1000;
67
68         return ret;
69 }
70
71 static int rt5033_battery_get_property(struct power_supply *psy,
72                 enum power_supply_property psp,
73                 union power_supply_propval *val)
74 {
75         struct rt5033_battery *battery = container_of(psy,
76                                 struct rt5033_battery, psy);
77
78         switch (psp) {
79         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
80         case POWER_SUPPLY_PROP_VOLTAGE_AVG:
81         case POWER_SUPPLY_PROP_VOLTAGE_OCV:
82                 val->intval = rt5033_battery_get_watt_prop(battery->client,
83                                                                         psp);
84                 break;
85         case POWER_SUPPLY_PROP_PRESENT:
86                 val->intval = rt5033_battery_get_present(battery->client);
87                 break;
88         case POWER_SUPPLY_PROP_CAPACITY:
89                 val->intval = rt5033_battery_get_capacity(battery->client);
90                 break;
91         default:
92                 return -EINVAL;
93         }
94         return 0;
95 }
96
97 static enum power_supply_property rt5033_battery_props[] = {
98         POWER_SUPPLY_PROP_VOLTAGE_NOW,
99         POWER_SUPPLY_PROP_VOLTAGE_AVG,
100         POWER_SUPPLY_PROP_VOLTAGE_OCV,
101         POWER_SUPPLY_PROP_PRESENT,
102         POWER_SUPPLY_PROP_CAPACITY,
103 };
104
105 static struct regmap_config rt5033_battery_regmap_config = {
106         .reg_bits       = 8,
107         .val_bits       = 8,
108         .max_register   = RT5033_FUEL_REG_END,
109 };
110
111 static int rt5033_battery_probe(struct i2c_client *client,
112                 const struct i2c_device_id *id)
113 {
114         struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
115         struct rt5033_battery *battery;
116         u32 ret;
117
118         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
119                 return -EIO;
120
121         battery = devm_kzalloc(&client->dev, sizeof(*battery), GFP_KERNEL);
122         if (!battery)
123                 return -EINVAL;
124
125         battery->client = client;
126         battery->regmap = devm_regmap_init_i2c(client,
127                         &rt5033_battery_regmap_config);
128         if (IS_ERR(battery->regmap)) {
129                 dev_err(&client->dev, "Failed to initialize regmap\n");
130                 return -EINVAL;
131         }
132
133         i2c_set_clientdata(client, battery);
134
135         battery->psy.name               = "rt5033-battery";
136         battery->psy.type               = POWER_SUPPLY_TYPE_BATTERY;
137         battery->psy.get_property       = rt5033_battery_get_property;
138         battery->psy.properties         = rt5033_battery_props;
139         battery->psy.num_properties     = ARRAY_SIZE(rt5033_battery_props);
140
141         ret = power_supply_register(&client->dev, &battery->psy);
142         if (ret) {
143                 dev_err(&client->dev, "Failed to register power supply\n");
144                 return ret;
145         }
146
147         return 0;
148 }
149
150 static int rt5033_battery_remove(struct i2c_client *client)
151 {
152         struct rt5033_battery *battery = i2c_get_clientdata(client);
153
154         power_supply_unregister(&battery->psy);
155
156         return 0;
157 }
158
159 static const struct i2c_device_id rt5033_battery_id[] = {
160         { "rt5033-battery", },
161         { }
162 };
163 MODULE_DEVICE_TABLE(platform, rt5033_battery_id);
164
165 static struct i2c_driver rt5033_battery_driver = {
166         .driver = {
167                 .name = "rt5033-battery",
168         },
169         .probe = rt5033_battery_probe,
170         .remove = rt5033_battery_remove,
171         .id_table = rt5033_battery_id,
172 };
173 module_i2c_driver(rt5033_battery_driver);
174
175 MODULE_DESCRIPTION("Richtek RT5033 fuel gauge driver");
176 MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
177 MODULE_LICENSE("GPL");