xref: /rk3399_rockchip-uboot/drivers/power/charge/sc8551_charger.c (revision da64a133f9da646cdd225274d6466b113bec8144)
1*da64a133Sshengfei Xu /*
2*da64a133Sshengfei Xu  * (C) Copyright 2022 Rockchip Electronics Co., Ltd
3*da64a133Sshengfei Xu  *
4*da64a133Sshengfei Xu  * SPDX-License-Identifier:	GPL-2.0+
5*da64a133Sshengfei Xu  */
6*da64a133Sshengfei Xu 
7*da64a133Sshengfei Xu #include <common.h>
8*da64a133Sshengfei Xu #include <dm.h>
9*da64a133Sshengfei Xu #include <i2c.h>
10*da64a133Sshengfei Xu #include <irq-generic.h>
11*da64a133Sshengfei Xu #include <power/fuel_gauge.h>
12*da64a133Sshengfei Xu #include <power/power_delivery/power_delivery.h>
13*da64a133Sshengfei Xu #include <linux/usb/phy-rockchip-usb2.h>
14*da64a133Sshengfei Xu 
15*da64a133Sshengfei Xu DECLARE_GLOBAL_DATA_PTR;
16*da64a133Sshengfei Xu 
17*da64a133Sshengfei Xu static int dbg_enable;
18*da64a133Sshengfei Xu 
19*da64a133Sshengfei Xu #define SC8551_DBG(args...) \
20*da64a133Sshengfei Xu 	do { \
21*da64a133Sshengfei Xu 		if (dbg_enable) { \
22*da64a133Sshengfei Xu 			printf(args); \
23*da64a133Sshengfei Xu 		} \
24*da64a133Sshengfei Xu 	} while (0)
25*da64a133Sshengfei Xu 
26*da64a133Sshengfei Xu struct sc8551 {
27*da64a133Sshengfei Xu 	struct udevice *dev;
28*da64a133Sshengfei Xu 	struct udevice *pd;
29*da64a133Sshengfei Xu 	bool pd_online;
30*da64a133Sshengfei Xu 	u32 init_count;
31*da64a133Sshengfei Xu 	u32 ichg;
32*da64a133Sshengfei Xu 	u32 vchg;
33*da64a133Sshengfei Xu 	int irq;
34*da64a133Sshengfei Xu };
35*da64a133Sshengfei Xu 
36*da64a133Sshengfei Xu enum charger_type {
37*da64a133Sshengfei Xu 	CHARGER_TYPE_NO = 0,
38*da64a133Sshengfei Xu 	CHARGER_TYPE_USB,
39*da64a133Sshengfei Xu 	CHARGER_TYPE_AC,
40*da64a133Sshengfei Xu 	CHARGER_TYPE_DC,
41*da64a133Sshengfei Xu 	CHARGER_TYPE_UNDEF,
42*da64a133Sshengfei Xu };
43*da64a133Sshengfei Xu 
44*da64a133Sshengfei Xu /* Register 05h */
45*da64a133Sshengfei Xu #define SC8551_REG_05				0x05
46*da64a133Sshengfei Xu #define SC8551_AC_OVP_STAT_MASK			0x80
47*da64a133Sshengfei Xu #define SC8551_AC_OVP_STAT_SHIFT		7
48*da64a133Sshengfei Xu 
49*da64a133Sshengfei Xu #define SC8551_AC_OVP_MASK			0x07
50*da64a133Sshengfei Xu #define SC8551_AC_OVP_SHIFT			0
51*da64a133Sshengfei Xu #define SC8551_AC_OVP_BASE			11
52*da64a133Sshengfei Xu #define SC8551_AC_OVP_LSB			1
53*da64a133Sshengfei Xu #define SC8551_AC_OVP_6P5V			65
54*da64a133Sshengfei Xu 
55*da64a133Sshengfei Xu /* Register 0Bh */
56*da64a133Sshengfei Xu #define SC8551_REG_0B				0x0B
57*da64a133Sshengfei Xu #define SC8551_REG_RST_MASK			0x80
58*da64a133Sshengfei Xu #define SC8551_REG_RST_SHIFT			7
59*da64a133Sshengfei Xu #define SC8551_REG_RST_ENABLE			1
60*da64a133Sshengfei Xu #define SC8551_REG_RST_DISABLE			0
61*da64a133Sshengfei Xu #define SC8551_AC_OVP_VOLTAGE			13
62*da64a133Sshengfei Xu 
sc8551_read(struct sc8551 * charger,uint reg,u8 * buffer)63*da64a133Sshengfei Xu static int sc8551_read(struct sc8551 *charger, uint reg, u8 *buffer)
64*da64a133Sshengfei Xu {
65*da64a133Sshengfei Xu 	u16 val;
66*da64a133Sshengfei Xu 	int ret;
67*da64a133Sshengfei Xu 
68*da64a133Sshengfei Xu 	ret = dm_i2c_read(charger->dev, reg, (u8 *)&val, 1);
69*da64a133Sshengfei Xu 	if (ret) {
70*da64a133Sshengfei Xu 		printf("sc8551: read %#x error, ret=%d", reg, ret);
71*da64a133Sshengfei Xu 		return ret;
72*da64a133Sshengfei Xu 	}
73*da64a133Sshengfei Xu 
74*da64a133Sshengfei Xu 	*buffer = val;
75*da64a133Sshengfei Xu 	return 0;
76*da64a133Sshengfei Xu }
77*da64a133Sshengfei Xu 
sc8551_write(struct sc8551 * charger,uint reg,u16 val)78*da64a133Sshengfei Xu static int sc8551_write(struct sc8551 *charger, uint reg, u16 val)
79*da64a133Sshengfei Xu {
80*da64a133Sshengfei Xu 	int ret;
81*da64a133Sshengfei Xu 
82*da64a133Sshengfei Xu 	ret = dm_i2c_write(charger->dev, reg, (u8 *)&val, 1);
83*da64a133Sshengfei Xu 	if (ret)
84*da64a133Sshengfei Xu 		printf("sc8551: write %#x error, ret=%d", reg, ret);
85*da64a133Sshengfei Xu 
86*da64a133Sshengfei Xu 	return ret;
87*da64a133Sshengfei Xu }
88*da64a133Sshengfei Xu 
sc8551_update_bits(struct sc8551 * charger,uint offset,uint mask,uint val)89*da64a133Sshengfei Xu static int sc8551_update_bits(struct sc8551 *charger,
90*da64a133Sshengfei Xu 			      uint offset,
91*da64a133Sshengfei Xu 			      uint mask,
92*da64a133Sshengfei Xu 			      uint val)
93*da64a133Sshengfei Xu {
94*da64a133Sshengfei Xu 	u8 reg;
95*da64a133Sshengfei Xu 	int ret;
96*da64a133Sshengfei Xu 
97*da64a133Sshengfei Xu 	ret = sc8551_read(charger, offset, &reg);
98*da64a133Sshengfei Xu 	if (ret)
99*da64a133Sshengfei Xu 		return ret;
100*da64a133Sshengfei Xu 
101*da64a133Sshengfei Xu 	reg &= ~mask;
102*da64a133Sshengfei Xu 
103*da64a133Sshengfei Xu 	return sc8551_write(charger, offset, reg | val);
104*da64a133Sshengfei Xu }
105*da64a133Sshengfei Xu 
sc8551_charger_capability(struct udevice * dev)106*da64a133Sshengfei Xu static int sc8551_charger_capability(struct udevice *dev)
107*da64a133Sshengfei Xu {
108*da64a133Sshengfei Xu 	return 0;
109*da64a133Sshengfei Xu }
110*da64a133Sshengfei Xu 
sc8551_dwc_otg_check_dpdm(void)111*da64a133Sshengfei Xu static int sc8551_dwc_otg_check_dpdm(void)
112*da64a133Sshengfei Xu {
113*da64a133Sshengfei Xu #if defined(CONFIG_PHY_ROCKCHIP_INNO_USB2) && !defined(CONFIG_SPL_BUILD)
114*da64a133Sshengfei Xu 	return rockchip_chg_get_type();
115*da64a133Sshengfei Xu #else
116*da64a133Sshengfei Xu 	debug("rockchip_chg_get_type() is not implement\n");
117*da64a133Sshengfei Xu 	return CHARGER_TYPE_NO;
118*da64a133Sshengfei Xu #endif
119*da64a133Sshengfei Xu }
120*da64a133Sshengfei Xu 
sc8551_get_usb_state(struct sc8551 * sc8551)121*da64a133Sshengfei Xu static int sc8551_get_usb_state(struct sc8551 *sc8551)
122*da64a133Sshengfei Xu {
123*da64a133Sshengfei Xu 	int charger_type;
124*da64a133Sshengfei Xu 
125*da64a133Sshengfei Xu 	switch (sc8551_dwc_otg_check_dpdm()) {
126*da64a133Sshengfei Xu 	case 0:
127*da64a133Sshengfei Xu 		charger_type = CHARGER_TYPE_NO;
128*da64a133Sshengfei Xu 		break;
129*da64a133Sshengfei Xu 	case 1:
130*da64a133Sshengfei Xu 	case 3:
131*da64a133Sshengfei Xu 		charger_type = CHARGER_TYPE_USB;
132*da64a133Sshengfei Xu 		break;
133*da64a133Sshengfei Xu 	case 2:
134*da64a133Sshengfei Xu 		charger_type = CHARGER_TYPE_AC;
135*da64a133Sshengfei Xu 		break;
136*da64a133Sshengfei Xu 	default:
137*da64a133Sshengfei Xu 		charger_type = CHARGER_TYPE_NO;
138*da64a133Sshengfei Xu 		break;
139*da64a133Sshengfei Xu 	}
140*da64a133Sshengfei Xu 
141*da64a133Sshengfei Xu 	return charger_type;
142*da64a133Sshengfei Xu }
143*da64a133Sshengfei Xu 
sc8551_check_charge(struct sc8551 * sc8551)144*da64a133Sshengfei Xu static bool sc8551_check_charge(struct sc8551 *sc8551)
145*da64a133Sshengfei Xu {
146*da64a133Sshengfei Xu 	if (sc8551_get_usb_state(sc8551) != CHARGER_TYPE_NO)
147*da64a133Sshengfei Xu 		return true;
148*da64a133Sshengfei Xu 
149*da64a133Sshengfei Xu 	return false;
150*da64a133Sshengfei Xu }
151*da64a133Sshengfei Xu 
sc8551_update_get_chrg_online(struct udevice * dev)152*da64a133Sshengfei Xu static bool sc8551_update_get_chrg_online(struct udevice *dev)
153*da64a133Sshengfei Xu {
154*da64a133Sshengfei Xu 	struct sc8551 *sc8551 = dev_get_priv(dev);
155*da64a133Sshengfei Xu 
156*da64a133Sshengfei Xu 	return sc8551_check_charge(sc8551);
157*da64a133Sshengfei Xu }
158*da64a133Sshengfei Xu 
sc8551_ofdata_to_platdata(struct udevice * dev)159*da64a133Sshengfei Xu static int sc8551_ofdata_to_platdata(struct udevice *dev)
160*da64a133Sshengfei Xu {
161*da64a133Sshengfei Xu 	return 0;
162*da64a133Sshengfei Xu }
163*da64a133Sshengfei Xu 
sc8551_set_acovp_th(struct sc8551 * sc,int threshold)164*da64a133Sshengfei Xu static int sc8551_set_acovp_th(struct sc8551 *sc, int threshold)
165*da64a133Sshengfei Xu {
166*da64a133Sshengfei Xu 	int ret;
167*da64a133Sshengfei Xu 	u8 val;
168*da64a133Sshengfei Xu 
169*da64a133Sshengfei Xu 	if (threshold < SC8551_AC_OVP_BASE)
170*da64a133Sshengfei Xu 		threshold = SC8551_AC_OVP_BASE;
171*da64a133Sshengfei Xu 
172*da64a133Sshengfei Xu 	if (threshold == SC8551_AC_OVP_6P5V)
173*da64a133Sshengfei Xu 		val = 0x07;
174*da64a133Sshengfei Xu 	else
175*da64a133Sshengfei Xu 		val = (threshold - SC8551_AC_OVP_BASE) / SC8551_AC_OVP_LSB;
176*da64a133Sshengfei Xu 
177*da64a133Sshengfei Xu 	val <<= SC8551_AC_OVP_SHIFT;
178*da64a133Sshengfei Xu 
179*da64a133Sshengfei Xu 	ret = sc8551_update_bits(sc, SC8551_REG_05,
180*da64a133Sshengfei Xu 				 SC8551_AC_OVP_MASK, val);
181*da64a133Sshengfei Xu 
182*da64a133Sshengfei Xu 	return ret;
183*da64a133Sshengfei Xu }
184*da64a133Sshengfei Xu 
sc8551_probe(struct udevice * dev)185*da64a133Sshengfei Xu static int sc8551_probe(struct udevice *dev)
186*da64a133Sshengfei Xu {
187*da64a133Sshengfei Xu 	struct sc8551 *charger = dev_get_priv(dev);
188*da64a133Sshengfei Xu 
189*da64a133Sshengfei Xu 	SC8551_DBG("sc8551: driver version-20220903\n");
190*da64a133Sshengfei Xu 
191*da64a133Sshengfei Xu 	charger->dev = dev;
192*da64a133Sshengfei Xu 
193*da64a133Sshengfei Xu 	SC8551_DBG("sc8551: not reset\n");
194*da64a133Sshengfei Xu 
195*da64a133Sshengfei Xu 	sc8551_set_acovp_th(charger, SC8551_AC_OVP_VOLTAGE);
196*da64a133Sshengfei Xu 
197*da64a133Sshengfei Xu 	return 0;
198*da64a133Sshengfei Xu }
199*da64a133Sshengfei Xu 
200*da64a133Sshengfei Xu static const struct udevice_id charger_ids[] = {
201*da64a133Sshengfei Xu 	{ .compatible = "sc,sc8551-standalone" },
202*da64a133Sshengfei Xu 	{ },
203*da64a133Sshengfei Xu };
204*da64a133Sshengfei Xu 
205*da64a133Sshengfei Xu static struct dm_fuel_gauge_ops charger_ops = {
206*da64a133Sshengfei Xu 	.get_chrg_online = sc8551_update_get_chrg_online,
207*da64a133Sshengfei Xu 	.capability = sc8551_charger_capability,
208*da64a133Sshengfei Xu };
209*da64a133Sshengfei Xu 
210*da64a133Sshengfei Xu U_BOOT_DRIVER(sc8551_charger) = {
211*da64a133Sshengfei Xu 	.name = "sc8551_charger",
212*da64a133Sshengfei Xu 	.id = UCLASS_FG,
213*da64a133Sshengfei Xu 	.probe = sc8551_probe,
214*da64a133Sshengfei Xu 	.of_match = charger_ids,
215*da64a133Sshengfei Xu 	.ops = &charger_ops,
216*da64a133Sshengfei Xu 	.ofdata_to_platdata = sc8551_ofdata_to_platdata,
217*da64a133Sshengfei Xu 	.priv_auto_alloc_size = sizeof(struct sc8551),
218*da64a133Sshengfei Xu };
219