1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * (C) Copyright 2020 Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <dm.h>
9*4882a593Smuzhiyun #include <i2c.h>
10*4882a593Smuzhiyun #include <power/fuel_gauge.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #define DIV(div) ((div) ? (div) : 1)
13*4882a593Smuzhiyun #define BAT_VOL_H 0x0078
14*4882a593Smuzhiyun #define BAT_VOL_L 0x0079
15*4882a593Smuzhiyun #define VCALIB0_H 0x0093
16*4882a593Smuzhiyun #define VCALIB0_L 0x0094
17*4882a593Smuzhiyun #define VCALIB1_H 0x0095
18*4882a593Smuzhiyun #define VCALIB1_L 0x0096
19*4882a593Smuzhiyun #define GG_CON 0x0056
20*4882a593Smuzhiyun #define VIRTUAL_POWER_VOL 3600
21*4882a593Smuzhiyun #define INSTANT_MODE 0x02
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun struct rk817_battery_device {
24*4882a593Smuzhiyun struct udevice *dev;
25*4882a593Smuzhiyun int voltage_k;
26*4882a593Smuzhiyun int voltage_b;
27*4882a593Smuzhiyun u32 virtual_power;
28*4882a593Smuzhiyun u32 bat_res_up;
29*4882a593Smuzhiyun u32 bat_res_down;
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun
rk817_bat_read(struct rk817_battery_device * battery,u8 reg)32*4882a593Smuzhiyun static u8 rk817_bat_read(struct rk817_battery_device *battery, u8 reg)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun int ret;
35*4882a593Smuzhiyun u8 buf;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun ret = dm_i2c_read(battery->dev, reg, &buf, 1);
38*4882a593Smuzhiyun if (ret) {
39*4882a593Smuzhiyun printf("%s: read reg 0x%02x failed, ret=%d\n",
40*4882a593Smuzhiyun __func__, reg, ret);
41*4882a593Smuzhiyun return ret;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun return buf;
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun
rk817_bat_write(struct rk817_battery_device * battery,u8 reg,u8 buf)47*4882a593Smuzhiyun static int rk817_bat_write(struct rk817_battery_device *battery,
48*4882a593Smuzhiyun u8 reg, u8 buf)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun int ret;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun ret = dm_i2c_write(battery->dev, reg, &buf, 1);
53*4882a593Smuzhiyun if (ret) {
54*4882a593Smuzhiyun printf("%s: write reg 0x%02x failed, ret=%d\n",
55*4882a593Smuzhiyun __func__, reg, ret);
56*4882a593Smuzhiyun return ret;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun return 0;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
rk817_bat_get_vaclib0(struct rk817_battery_device * battery)62*4882a593Smuzhiyun static int rk817_bat_get_vaclib0(struct rk817_battery_device *battery)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun int val = 0;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun val |= rk817_bat_read(battery, VCALIB0_L) << 0;
67*4882a593Smuzhiyun val |= rk817_bat_read(battery, VCALIB0_H) << 8;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun return val;
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
rk817_bat_get_vaclib1(struct rk817_battery_device * battery)72*4882a593Smuzhiyun static int rk817_bat_get_vaclib1(struct rk817_battery_device *battery)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun int val = 0;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun val |= rk817_bat_read(battery, VCALIB1_L) << 0;
77*4882a593Smuzhiyun val |= rk817_bat_read(battery, VCALIB1_H) << 8;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun return val;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
rk817_bat_init_voltage_kb(struct rk817_battery_device * battery)82*4882a593Smuzhiyun static void rk817_bat_init_voltage_kb(struct rk817_battery_device *battery)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun int vcalib0, vcalib1;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun vcalib0 = rk817_bat_get_vaclib0(battery);
87*4882a593Smuzhiyun vcalib1 = rk817_bat_get_vaclib1(battery);
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun battery->voltage_k = (1050 - 600) * 1000 / DIV(vcalib1 - vcalib0);
90*4882a593Smuzhiyun battery->voltage_b = 1050 - (battery->voltage_k * vcalib1) / 1000;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
rk817_bat_get_battery_voltage(struct rk817_battery_device * battery)93*4882a593Smuzhiyun static int rk817_bat_get_battery_voltage(struct rk817_battery_device *battery)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun int vol, val = 0;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun val |= rk817_bat_read(battery, BAT_VOL_L) << 0;
98*4882a593Smuzhiyun val |= rk817_bat_read(battery, BAT_VOL_H) << 8;
99*4882a593Smuzhiyun vol = battery->voltage_k * val / 1000 + battery->voltage_b;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun return (vol * battery->bat_res_up / battery->bat_res_down + vol);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
rk817_bat_update_get_voltage(struct udevice * dev)104*4882a593Smuzhiyun static int rk817_bat_update_get_voltage(struct udevice *dev)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun struct rk817_battery_device *battery = dev_get_priv(dev);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun if (!battery->virtual_power && battery->voltage_k)
109*4882a593Smuzhiyun return rk817_bat_get_battery_voltage(battery);
110*4882a593Smuzhiyun else
111*4882a593Smuzhiyun return VIRTUAL_POWER_VOL;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun static struct dm_fuel_gauge_ops fg_ops = {
115*4882a593Smuzhiyun .get_voltage = rk817_bat_update_get_voltage,
116*4882a593Smuzhiyun };
117*4882a593Smuzhiyun
rk817_fg_ofdata_to_platdata(struct udevice * dev)118*4882a593Smuzhiyun static int rk817_fg_ofdata_to_platdata(struct udevice *dev)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun struct rk817_battery_device *battery = dev_get_priv(dev);
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun battery->dev = dev;
123*4882a593Smuzhiyun battery->bat_res_up = dev_read_u32_default(dev, "bat_res_up", -1);
124*4882a593Smuzhiyun if (battery->bat_res_up < 0) {
125*4882a593Smuzhiyun printf("can't read bat_res_up\n");
126*4882a593Smuzhiyun return -EINVAL;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun battery->bat_res_down = dev_read_u32_default(dev, "bat_res_down", -1);
130*4882a593Smuzhiyun if (battery->bat_res_down < 0) {
131*4882a593Smuzhiyun printf("can't read bat_res_down\n");
132*4882a593Smuzhiyun return -EINVAL;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun battery->virtual_power = dev_read_u32_default(dev, "virtual_power", -1);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun return 0;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
rk817_fg_init(struct rk817_battery_device * battery)140*4882a593Smuzhiyun static int rk817_fg_init(struct rk817_battery_device *battery)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun u8 val;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun val = rk817_bat_read(battery, GG_CON);
145*4882a593Smuzhiyun if (!(val & INSTANT_MODE)) {
146*4882a593Smuzhiyun val |= INSTANT_MODE;
147*4882a593Smuzhiyun rk817_bat_write(battery, GG_CON, val);
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun rk817_bat_init_voltage_kb(battery);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun return 0;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
rk817_fg_probe(struct udevice * dev)155*4882a593Smuzhiyun static int rk817_fg_probe(struct udevice *dev)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun return rk817_fg_init(dev_get_priv(dev));
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun static const struct udevice_id rk817_battery_ids[] = {
161*4882a593Smuzhiyun { .compatible = "rk817,battery" },
162*4882a593Smuzhiyun { }
163*4882a593Smuzhiyun };
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun U_BOOT_DRIVER(rk817_fg) = {
166*4882a593Smuzhiyun .name = "rk817_fg",
167*4882a593Smuzhiyun .id = UCLASS_FG,
168*4882a593Smuzhiyun .of_match = rk817_battery_ids,
169*4882a593Smuzhiyun .probe = rk817_fg_probe,
170*4882a593Smuzhiyun .ops = &fg_ops,
171*4882a593Smuzhiyun .ofdata_to_platdata = rk817_fg_ofdata_to_platdata,
172*4882a593Smuzhiyun .priv_auto_alloc_size = sizeof(struct rk817_battery_device),
173*4882a593Smuzhiyun };
174