1 // SPDX-License-Identifier: GPL-2.0-only
3 * Fuel gauge driver for Richtek RT5033
5 * Copyright (C) 2014 Samsung Electronics, Co., Ltd.
6 * Author: Beomho Seo <beomho.seo@samsung.com>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/power_supply.h>
13 #include <linux/regmap.h>
14 #include <linux/mfd/rt5033-private.h>
16 struct rt5033_battery
{
17 struct i2c_client
*client
;
18 struct regmap
*regmap
;
19 struct power_supply
*psy
;
22 static int rt5033_battery_get_status(struct i2c_client
*client
)
24 struct rt5033_battery
*battery
= i2c_get_clientdata(client
);
25 union power_supply_propval val
;
28 ret
= power_supply_get_property_from_supplier(battery
->psy
,
29 POWER_SUPPLY_PROP_STATUS
,
32 val
.intval
= POWER_SUPPLY_STATUS_UNKNOWN
;
37 static int rt5033_battery_get_capacity(struct i2c_client
*client
)
39 struct rt5033_battery
*battery
= i2c_get_clientdata(client
);
42 regmap_read(battery
->regmap
, RT5033_FUEL_REG_SOC_H
, &msb
);
47 static int rt5033_battery_get_present(struct i2c_client
*client
)
49 struct rt5033_battery
*battery
= i2c_get_clientdata(client
);
52 regmap_read(battery
->regmap
, RT5033_FUEL_REG_CONFIG_L
, &val
);
54 return (val
& RT5033_FUEL_BAT_PRESENT
) ? true : false;
57 static int rt5033_battery_get_watt_prop(struct i2c_client
*client
,
58 enum power_supply_property psp
)
60 struct rt5033_battery
*battery
= i2c_get_clientdata(client
);
61 unsigned int regh
, regl
;
66 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
67 regh
= RT5033_FUEL_REG_VBAT_H
;
68 regl
= RT5033_FUEL_REG_VBAT_L
;
70 case POWER_SUPPLY_PROP_VOLTAGE_AVG
:
71 regh
= RT5033_FUEL_REG_AVG_VOLT_H
;
72 regl
= RT5033_FUEL_REG_AVG_VOLT_L
;
74 case POWER_SUPPLY_PROP_VOLTAGE_OCV
:
75 regh
= RT5033_FUEL_REG_OCV_H
;
76 regl
= RT5033_FUEL_REG_OCV_L
;
82 regmap_read(battery
->regmap
, regh
, &msb
);
83 regmap_read(battery
->regmap
, regl
, &lsb
);
85 ret
= ((msb
<< 4) + (lsb
>> 4)) * 1250;
90 static int rt5033_battery_get_property(struct power_supply
*psy
,
91 enum power_supply_property psp
,
92 union power_supply_propval
*val
)
94 struct rt5033_battery
*battery
= power_supply_get_drvdata(psy
);
97 case POWER_SUPPLY_PROP_VOLTAGE_NOW
:
98 case POWER_SUPPLY_PROP_VOLTAGE_AVG
:
99 case POWER_SUPPLY_PROP_VOLTAGE_OCV
:
100 val
->intval
= rt5033_battery_get_watt_prop(battery
->client
,
103 case POWER_SUPPLY_PROP_PRESENT
:
104 val
->intval
= rt5033_battery_get_present(battery
->client
);
106 case POWER_SUPPLY_PROP_CAPACITY
:
107 val
->intval
= rt5033_battery_get_capacity(battery
->client
);
109 case POWER_SUPPLY_PROP_STATUS
:
110 val
->intval
= rt5033_battery_get_status(battery
->client
);
118 static enum power_supply_property rt5033_battery_props
[] = {
119 POWER_SUPPLY_PROP_VOLTAGE_NOW
,
120 POWER_SUPPLY_PROP_VOLTAGE_AVG
,
121 POWER_SUPPLY_PROP_VOLTAGE_OCV
,
122 POWER_SUPPLY_PROP_PRESENT
,
123 POWER_SUPPLY_PROP_CAPACITY
,
124 POWER_SUPPLY_PROP_STATUS
,
127 static const struct regmap_config rt5033_battery_regmap_config
= {
130 .max_register
= RT5033_FUEL_REG_END
,
133 static const struct power_supply_desc rt5033_battery_desc
= {
134 .name
= "rt5033-battery",
135 .type
= POWER_SUPPLY_TYPE_BATTERY
,
136 .get_property
= rt5033_battery_get_property
,
137 .properties
= rt5033_battery_props
,
138 .num_properties
= ARRAY_SIZE(rt5033_battery_props
),
141 static int rt5033_battery_probe(struct i2c_client
*client
)
143 struct i2c_adapter
*adapter
= client
->adapter
;
144 struct power_supply_config psy_cfg
= {};
145 struct rt5033_battery
*battery
;
147 if (!i2c_check_functionality(adapter
, I2C_FUNC_SMBUS_BYTE
))
150 battery
= devm_kzalloc(&client
->dev
, sizeof(*battery
), GFP_KERNEL
);
154 battery
->client
= client
;
155 battery
->regmap
= devm_regmap_init_i2c(client
,
156 &rt5033_battery_regmap_config
);
157 if (IS_ERR(battery
->regmap
)) {
158 dev_err(&client
->dev
, "Failed to initialize regmap\n");
162 i2c_set_clientdata(client
, battery
);
163 psy_cfg
.of_node
= client
->dev
.of_node
;
164 psy_cfg
.drv_data
= battery
;
166 battery
->psy
= devm_power_supply_register(&client
->dev
,
167 &rt5033_battery_desc
,
169 if (IS_ERR(battery
->psy
))
170 return dev_err_probe(&client
->dev
, PTR_ERR(battery
->psy
),
171 "Failed to register power supply\n");
176 static const struct i2c_device_id rt5033_battery_id
[] = {
177 { "rt5033-battery", },
180 MODULE_DEVICE_TABLE(i2c
, rt5033_battery_id
);
182 static const struct of_device_id rt5033_battery_of_match
[] = {
183 { .compatible
= "richtek,rt5033-battery", },
186 MODULE_DEVICE_TABLE(of
, rt5033_battery_of_match
);
188 static struct i2c_driver rt5033_battery_driver
= {
190 .name
= "rt5033-battery",
191 .of_match_table
= rt5033_battery_of_match
,
193 .probe
= rt5033_battery_probe
,
194 .id_table
= rt5033_battery_id
,
196 module_i2c_driver(rt5033_battery_driver
);
198 MODULE_DESCRIPTION("Richtek RT5033 fuel gauge driver");
199 MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
200 MODULE_LICENSE("GPL");