xref: /OK3568_Linux_fs/u-boot/drivers/power/fuel_gauge/spl_fg_rk817.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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