1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2022 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <dm.h>
9*4882a593Smuzhiyun #include <i2c.h>
10*4882a593Smuzhiyun #include <irq-generic.h>
11*4882a593Smuzhiyun #include <power/fuel_gauge.h>
12*4882a593Smuzhiyun #include <linux/usb/phy-rockchip-usb2.h>
13*4882a593Smuzhiyun #include <power/power_delivery/power_delivery.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun static int dbg_enable;
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define SGM_DBG(args...) \
20*4882a593Smuzhiyun do { \
21*4882a593Smuzhiyun if (dbg_enable) { \
22*4882a593Smuzhiyun printf(args); \
23*4882a593Smuzhiyun } \
24*4882a593Smuzhiyun } while (0)
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /* define register */
27*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_0 0x00
28*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_1 0x01
29*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_2 0x02
30*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_3 0x03
31*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_4 0x04
32*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_5 0x05
33*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_6 0x06
34*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_7 0x07
35*4882a593Smuzhiyun #define SGM4154x_CHRG_STAT 0x08
36*4882a593Smuzhiyun #define SGM4154x_CHRG_FAULT 0x09
37*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_a 0x0a
38*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_b 0x0b
39*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_c 0x0c
40*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_d 0x0d
41*4882a593Smuzhiyun #define SGM4154x_INPUT_DET 0x0e
42*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_f 0x0f
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* charge status flags */
45*4882a593Smuzhiyun #define SGM4154x_CHRG_EN BIT(4)
46*4882a593Smuzhiyun #define SGM4154x_HIZ_EN BIT(7)
47*4882a593Smuzhiyun #define SGM4154x_TERM_EN BIT(7)
48*4882a593Smuzhiyun #define SGM4154x_VAC_OVP_MASK GENMASK(7, 6)
49*4882a593Smuzhiyun #define SGM4154x_DPDM_ONGOING BIT(7)
50*4882a593Smuzhiyun #define SGM4154x_VBUS_GOOD BIT(7)
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun #define SGM4154x_BOOSTV GENMASK(5, 4)
53*4882a593Smuzhiyun #define SGM4154x_BOOST_LIM BIT(7)
54*4882a593Smuzhiyun #define SGM4154x_OTG_EN BIT(5)
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* Part ID */
57*4882a593Smuzhiyun #define SGM4154x_PN_MASK GENMASK(6, 3)
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /* WDT TIMER SET */
60*4882a593Smuzhiyun #define SGM4154x_WDT_TIMER_MASK GENMASK(5, 4)
61*4882a593Smuzhiyun #define SGM4154x_WDT_TIMER_DISABLE 0
62*4882a593Smuzhiyun #define SGM4154x_WDT_TIMER_40S BIT(4)
63*4882a593Smuzhiyun #define SGM4154x_WDT_TIMER_80S BIT(5)
64*4882a593Smuzhiyun #define SGM4154x_WDT_TIMER_160S (BIT(4) | BIT(5))
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun #define SGM4154x_WDT_RST_MASK BIT(6)
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /* SAFETY TIMER SET */
69*4882a593Smuzhiyun #define SGM4154x_SAFETY_TIMER_MASK GENMASK(3, 3)
70*4882a593Smuzhiyun #define SGM4154x_SAFETY_TIMER_DISABLE 0
71*4882a593Smuzhiyun #define SGM4154x_SAFETY_TIMER_EN BIT(3)
72*4882a593Smuzhiyun #define SGM4154x_SAFETY_TIMER_5H 0
73*4882a593Smuzhiyun #define SGM4154x_SAFETY_TIMER_10H BIT(2)
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun /* recharge voltage */
76*4882a593Smuzhiyun #define SGM4154x_VRECHARGE BIT(0)
77*4882a593Smuzhiyun #define SGM4154x_VRECHRG_STEP_mV 100
78*4882a593Smuzhiyun #define SGM4154x_VRECHRG_OFFSET_mV 100
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun /* charge status */
81*4882a593Smuzhiyun #define SGM4154x_VSYS_STAT BIT(0)
82*4882a593Smuzhiyun #define SGM4154x_THERM_STAT BIT(1)
83*4882a593Smuzhiyun #define SGM4154x_PG_STAT BIT(2)
84*4882a593Smuzhiyun #define SGM4154x_CHG_STAT_MASK GENMASK(4, 3)
85*4882a593Smuzhiyun #define SGM4154x_PRECHRG BIT(3)
86*4882a593Smuzhiyun #define SGM4154x_FAST_CHRG BIT(4)
87*4882a593Smuzhiyun #define SGM4154x_TERM_CHRG (BIT(3) | BIT(4))
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /* charge type */
90*4882a593Smuzhiyun #define SGM4154x_VBUS_STAT_MASK GENMASK(7, 5)
91*4882a593Smuzhiyun #define SGM4154x_NOT_CHRGING 0
92*4882a593Smuzhiyun #define SGM4154x_USB_SDP BIT(5)
93*4882a593Smuzhiyun #define SGM4154x_USB_CDP BIT(6)
94*4882a593Smuzhiyun #define SGM4154x_USB_DCP (BIT(5) | BIT(6))
95*4882a593Smuzhiyun #define SGM4154x_UNKNOWN (BIT(7) | BIT(5))
96*4882a593Smuzhiyun #define SGM4154x_NON_STANDARD (BIT(7) | BIT(6))
97*4882a593Smuzhiyun #define SGM4154x_OTG_MODE (BIT(7) | BIT(6) | BIT(5))
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /* TEMP Status */
100*4882a593Smuzhiyun #define SGM4154x_TEMP_MASK GENMASK(2, 0)
101*4882a593Smuzhiyun #define SGM4154x_TEMP_NORMAL BIT(0)
102*4882a593Smuzhiyun #define SGM4154x_TEMP_WARM BIT(1)
103*4882a593Smuzhiyun #define SGM4154x_TEMP_COOL (BIT(0) | BIT(1))
104*4882a593Smuzhiyun #define SGM4154x_TEMP_COLD (BIT(0) | BIT(3))
105*4882a593Smuzhiyun #define SGM4154x_TEMP_HOT (BIT(2) | BIT(3))
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /* precharge current */
108*4882a593Smuzhiyun #define SGM4154x_PRECHRG_CUR_MASK GENMASK(7, 4)
109*4882a593Smuzhiyun #define SGM4154x_PRECHRG_CURRENT_STEP_uA 60000
110*4882a593Smuzhiyun #define SGM4154x_PRECHRG_I_MIN_uA 60000
111*4882a593Smuzhiyun #define SGM4154x_PRECHRG_I_MAX_uA 780000
112*4882a593Smuzhiyun #define SGM4154x_PRECHRG_I_DEF_uA 180000
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /* termination current */
115*4882a593Smuzhiyun #define SGM4154x_TERMCHRG_CUR_MASK GENMASK(3, 0)
116*4882a593Smuzhiyun #define SGM4154x_TERMCHRG_CURRENT_STEP_uA 60000
117*4882a593Smuzhiyun #define SGM4154x_TERMCHRG_I_MIN_uA 60000
118*4882a593Smuzhiyun #define SGM4154x_TERMCHRG_I_MAX_uA 960000
119*4882a593Smuzhiyun #define SGM4154x_TERMCHRG_I_DEF_uA 180000
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun /* charge current */
122*4882a593Smuzhiyun #define SGM4154x_ICHRG_CUR_MASK GENMASK(5, 0)
123*4882a593Smuzhiyun #define SGM4154x_ICHRG_I_STEP_uA 60000
124*4882a593Smuzhiyun #define SGM4154x_ICHRG_I_MIN_uA 0
125*4882a593Smuzhiyun #define SGM4154x_ICHRG_I_MAX_uA 3780000
126*4882a593Smuzhiyun #define SGM4154x_ICHRG_I_DEF_uA 2040000
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun /* charge voltage */
129*4882a593Smuzhiyun #define SGM4154x_VREG_V_MASK GENMASK(7, 3)
130*4882a593Smuzhiyun #define SGM4154x_VREG_V_MAX_uV 4624000
131*4882a593Smuzhiyun #define SGM4154x_VREG_V_MIN_uV 3856000
132*4882a593Smuzhiyun #define SGM4154x_VREG_V_DEF_uV 4208000
133*4882a593Smuzhiyun #define SGM4154x_VREG_V_STEP_uV 32000
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun /* VREG Fine Tuning */
136*4882a593Smuzhiyun #define SGM4154x_VREG_FT_MASK GENMASK(7, 6)
137*4882a593Smuzhiyun #define SGM4154x_VREG_FT_UP_8mV BIT(6)
138*4882a593Smuzhiyun #define SGM4154x_VREG_FT_DN_8mV BIT(7)
139*4882a593Smuzhiyun #define SGM4154x_VREG_FT_DN_16mV (BIT(7) | BIT(6))
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun /* iindpm current */
142*4882a593Smuzhiyun #define SGM4154x_IINDPM_I_MASK GENMASK(4, 0)
143*4882a593Smuzhiyun #define SGM4154x_IINDPM_I_MIN_uA 100000
144*4882a593Smuzhiyun #define SGM4154x_IINDPM_I_MAX_uA 2000000
145*4882a593Smuzhiyun #define SGM4154x_IINDPM_STEP_uA 100000
146*4882a593Smuzhiyun #define SGM4154x_IINDPM_DEF_uA 2400000
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun #define SGM4154x_VINDPM_INT_MASK BIT(1)
149*4882a593Smuzhiyun #define SGM4154x_VINDPM_INT_DIS BIT(1)
150*4882a593Smuzhiyun #define SGM4154x_IINDPM_INT_MASK BIT(0)
151*4882a593Smuzhiyun #define SGM4154x_IINDPM_INT_DIS BIT(0)
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /* vindpm voltage */
154*4882a593Smuzhiyun #define SGM4154x_VINDPM_V_MASK GENMASK(3, 0)
155*4882a593Smuzhiyun #define SGM4154x_VINDPM_V_MIN_uV 3900000
156*4882a593Smuzhiyun #define SGM4154x_VINDPM_V_MAX_uV 12000000
157*4882a593Smuzhiyun #define SGM4154x_VINDPM_STEP_uV 100000
158*4882a593Smuzhiyun #define SGM4154x_VINDPM_DEF_uV 4500000
159*4882a593Smuzhiyun #define SGM4154x_VINDPM_OS_MASK GENMASK(1, 0)
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /* DP DM SEL */
162*4882a593Smuzhiyun #define SGM4154x_DP_VSEL_MASK GENMASK(4, 3)
163*4882a593Smuzhiyun #define SGM4154x_DM_VSEL_MASK GENMASK(2, 1)
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* PUMPX SET */
166*4882a593Smuzhiyun #define SGM4154x_EN_PUMPX BIT(7)
167*4882a593Smuzhiyun #define SGM4154x_PUMPX_UP BIT(6)
168*4882a593Smuzhiyun #define SGM4154x_PUMPX_DN BIT(5)
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun struct sgm41542 {
171*4882a593Smuzhiyun struct udevice *dev;
172*4882a593Smuzhiyun struct udevice *pd;
173*4882a593Smuzhiyun bool pd_online;
174*4882a593Smuzhiyun u32 init_count;
175*4882a593Smuzhiyun u32 ichg;
176*4882a593Smuzhiyun u32 vchg;
177*4882a593Smuzhiyun int irq;
178*4882a593Smuzhiyun };
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun enum power_supply_type {
181*4882a593Smuzhiyun POWER_SUPPLY_TYPE_UNKNOWN = 0,
182*4882a593Smuzhiyun POWER_SUPPLY_TYPE_USB, /* Standard Downstream Port */
183*4882a593Smuzhiyun POWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */
184*4882a593Smuzhiyun POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */
185*4882a593Smuzhiyun POWER_SUPPLY_TYPE_USB_FLOATING, /* DCP without shorting D+/D- */
186*4882a593Smuzhiyun };
187*4882a593Smuzhiyun
sgm41542_read(struct sgm41542 * charger,uint reg,u8 * buffer)188*4882a593Smuzhiyun static int sgm41542_read(struct sgm41542 *charger, uint reg, u8 *buffer)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun u8 val;
191*4882a593Smuzhiyun int ret;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun ret = dm_i2c_read(charger->dev, reg, &val, 1);
194*4882a593Smuzhiyun if (ret) {
195*4882a593Smuzhiyun printf("sgm41542: read %#x error, ret=%d", reg, ret);
196*4882a593Smuzhiyun return ret;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun *buffer = val;
200*4882a593Smuzhiyun return 0;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
sgm41542_write(struct sgm41542 * charger,uint reg,u8 val)203*4882a593Smuzhiyun static int sgm41542_write(struct sgm41542 *charger, uint reg, u8 val)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun int ret;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun ret = dm_i2c_write(charger->dev, reg, &val, 1);
208*4882a593Smuzhiyun if (ret)
209*4882a593Smuzhiyun printf("sgm41542: write %#x error, ret=%d", reg, ret);
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun return ret;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
sgm41542_update_bits(struct sgm41542 * charger,u8 offset,u8 mask,u8 val)214*4882a593Smuzhiyun static int sgm41542_update_bits(struct sgm41542 *charger,
215*4882a593Smuzhiyun u8 offset,
216*4882a593Smuzhiyun u8 mask,
217*4882a593Smuzhiyun u8 val)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun u8 reg;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun sgm41542_read(charger, offset, ®);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun reg &= ~mask;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun return sgm41542_write(charger, offset, reg | val);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
sgm4154x_set_input_curr_lim(struct sgm41542 * charger,int iindpm)228*4882a593Smuzhiyun static int sgm4154x_set_input_curr_lim(struct sgm41542 *charger, int iindpm)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun u8 reg_val;
231*4882a593Smuzhiyun int ret;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun if (iindpm < SGM4154x_IINDPM_I_MIN_uA)
234*4882a593Smuzhiyun iindpm = SGM4154x_IINDPM_I_MIN_uA;
235*4882a593Smuzhiyun if (iindpm >= SGM4154x_IINDPM_I_MAX_uA)
236*4882a593Smuzhiyun iindpm = SGM4154x_IINDPM_I_MAX_uA;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun if (iindpm >= SGM4154x_IINDPM_I_MIN_uA &&
239*4882a593Smuzhiyun iindpm <= SGM4154x_IINDPM_I_MAX_uA)
240*4882a593Smuzhiyun reg_val = (iindpm - SGM4154x_IINDPM_I_MIN_uA) / SGM4154x_IINDPM_STEP_uA;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun ret = sgm41542_update_bits(charger,
243*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_0,
244*4882a593Smuzhiyun SGM4154x_IINDPM_I_MASK,
245*4882a593Smuzhiyun reg_val);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun return ret;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
sgm41542_get_usb_type(void)250*4882a593Smuzhiyun static int sgm41542_get_usb_type(void)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun #ifdef CONFIG_PHY_ROCKCHIP_INNO_USB2
253*4882a593Smuzhiyun return rockchip_chg_get_type();
254*4882a593Smuzhiyun #else
255*4882a593Smuzhiyun return 0;
256*4882a593Smuzhiyun #endif
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
sgm41542_charger_capability(struct udevice * dev)259*4882a593Smuzhiyun static int sgm41542_charger_capability(struct udevice *dev)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun return FG_CAP_CHARGER;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
sgm4154x_set_ichrg_curr(struct sgm41542 * charger,int uA)264*4882a593Smuzhiyun static int sgm4154x_set_ichrg_curr(struct sgm41542 *charger, int uA)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun u8 reg_val;
267*4882a593Smuzhiyun int ret;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun if (uA < SGM4154x_ICHRG_I_MIN_uA)
270*4882a593Smuzhiyun uA = SGM4154x_ICHRG_I_MIN_uA;
271*4882a593Smuzhiyun else if (uA > charger->ichg)
272*4882a593Smuzhiyun uA = uA > charger->ichg;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun reg_val = uA / SGM4154x_ICHRG_I_STEP_uA;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun ret = sgm41542_update_bits(charger,
277*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_2,
278*4882a593Smuzhiyun SGM4154x_ICHRG_CUR_MASK,
279*4882a593Smuzhiyun reg_val);
280*4882a593Smuzhiyun if (ret)
281*4882a593Smuzhiyun printf("sgm41542: set icharge current error!\n");
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun return ret;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
sgm4154x_set_prechrg_curr(struct sgm41542 * charger,int uA)286*4882a593Smuzhiyun static int sgm4154x_set_prechrg_curr(struct sgm41542 *charger, int uA)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun u8 reg_val;
289*4882a593Smuzhiyun int ret;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun if (uA < SGM4154x_PRECHRG_I_MIN_uA)
292*4882a593Smuzhiyun uA = SGM4154x_PRECHRG_I_MIN_uA;
293*4882a593Smuzhiyun else if (uA > SGM4154x_PRECHRG_I_MAX_uA)
294*4882a593Smuzhiyun uA = SGM4154x_PRECHRG_I_MAX_uA;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun reg_val = (uA - SGM4154x_PRECHRG_I_MIN_uA) / SGM4154x_PRECHRG_CURRENT_STEP_uA;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun reg_val = reg_val << 4;
299*4882a593Smuzhiyun ret = sgm41542_update_bits(charger,
300*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_3,
301*4882a593Smuzhiyun SGM4154x_PRECHRG_CUR_MASK,
302*4882a593Smuzhiyun reg_val);
303*4882a593Smuzhiyun if (ret)
304*4882a593Smuzhiyun printf("sgm41542: set icharge current error!\n");
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun return ret;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
sgm4154x_set_chrg_volt(struct sgm41542 * charger,int chrg_volt)309*4882a593Smuzhiyun static int sgm4154x_set_chrg_volt(struct sgm41542 *charger, int chrg_volt)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun u8 reg_val;
312*4882a593Smuzhiyun int ret;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun if (chrg_volt < SGM4154x_VREG_V_MIN_uV)
315*4882a593Smuzhiyun chrg_volt = SGM4154x_VREG_V_MIN_uV;
316*4882a593Smuzhiyun else if (chrg_volt > SGM4154x_VREG_V_MAX_uV)
317*4882a593Smuzhiyun chrg_volt = SGM4154x_VREG_V_MAX_uV;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun reg_val = (chrg_volt - SGM4154x_VREG_V_MIN_uV) / SGM4154x_VREG_V_STEP_uV;
320*4882a593Smuzhiyun reg_val = reg_val << 3;
321*4882a593Smuzhiyun SGM_DBG("reg_val: 0x%x\n", reg_val);
322*4882a593Smuzhiyun ret = sgm41542_update_bits(charger,
323*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_4,
324*4882a593Smuzhiyun SGM4154x_VREG_V_MASK,
325*4882a593Smuzhiyun reg_val);
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun return ret;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
sgm41542_set_charger_voltage(struct udevice * dev,int uV)330*4882a593Smuzhiyun static int sgm41542_set_charger_voltage(struct udevice *dev, int uV)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun struct sgm41542 *charger = dev_get_priv(dev);
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun SGM_DBG("SGM41542: charger voltage %d\n", uV);
335*4882a593Smuzhiyun return sgm4154x_set_chrg_volt(charger, uV);
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun
sgm41542_charger_enable(struct udevice * dev)338*4882a593Smuzhiyun static int sgm41542_charger_enable(struct udevice *dev)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun struct sgm41542 *charger = dev_get_priv(dev);
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun SGM_DBG("SGM41542: charger enable\n");
343*4882a593Smuzhiyun sgm41542_update_bits(charger, SGM4154x_CHRG_CTRL_1,
344*4882a593Smuzhiyun SGM4154x_CHRG_EN,
345*4882a593Smuzhiyun SGM4154x_CHRG_EN);
346*4882a593Smuzhiyun return 0;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
sgm41542_charger_disable(struct udevice * dev)349*4882a593Smuzhiyun static int sgm41542_charger_disable(struct udevice *dev)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun struct sgm41542 *charger = dev_get_priv(dev);
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun SGM_DBG("SGM41542: charger disable\n");
354*4882a593Smuzhiyun sgm41542_update_bits(charger, SGM4154x_CHRG_CTRL_1,
355*4882a593Smuzhiyun SGM4154x_CHRG_EN,
356*4882a593Smuzhiyun 0);
357*4882a593Smuzhiyun return 0;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun
sgm41542_iprechg_current(struct udevice * dev,int iprechrg_uA)360*4882a593Smuzhiyun static int sgm41542_iprechg_current(struct udevice *dev, int iprechrg_uA)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun struct sgm41542 *charger = dev_get_priv(dev);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun SGM_DBG("SGM41542: charger current:iprechrg_uA: %d\n",
365*4882a593Smuzhiyun iprechrg_uA);
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun return sgm4154x_set_prechrg_curr(charger, iprechrg_uA);
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
sgm41542_charger_current(struct udevice * dev,int ichrg_uA)370*4882a593Smuzhiyun static int sgm41542_charger_current(struct udevice *dev, int ichrg_uA)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun struct sgm41542 *charger = dev_get_priv(dev);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun SGM_DBG("SGM41542: charger current:ichrg_uA%d\n",
375*4882a593Smuzhiyun ichrg_uA);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun return sgm4154x_set_ichrg_curr(charger, ichrg_uA);
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
sgm41542_get_pd_output_val(struct sgm41542 * charger,int * vol,int * cur)380*4882a593Smuzhiyun static int sgm41542_get_pd_output_val(struct sgm41542 *charger,
381*4882a593Smuzhiyun int *vol,
382*4882a593Smuzhiyun int *cur)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun struct power_delivery_data pd_data;
385*4882a593Smuzhiyun int ret;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun if (!charger->pd)
388*4882a593Smuzhiyun return -EINVAL;
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun memset(&pd_data, 0, sizeof(pd_data));
391*4882a593Smuzhiyun ret = power_delivery_get_data(charger->pd, &pd_data);
392*4882a593Smuzhiyun if (ret)
393*4882a593Smuzhiyun return ret;
394*4882a593Smuzhiyun if (!pd_data.online || !pd_data.voltage || !pd_data.current)
395*4882a593Smuzhiyun return -EINVAL;
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun *vol = pd_data.voltage;
398*4882a593Smuzhiyun *cur = pd_data.current;
399*4882a593Smuzhiyun charger->pd_online = pd_data.online;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun return 0;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
sgm41542_charger_input_current_init(struct sgm41542 * charger)404*4882a593Smuzhiyun static void sgm41542_charger_input_current_init(struct sgm41542 *charger)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun int sdp_inputcurrent = 500 * 1000;
407*4882a593Smuzhiyun int dcp_inputcurrent = 2000 * 1000;
408*4882a593Smuzhiyun int pd_inputvol, pd_inputcurrent;
409*4882a593Smuzhiyun int ret;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun if (!charger->pd) {
412*4882a593Smuzhiyun ret = uclass_get_device(UCLASS_PD, 0, &charger->pd);
413*4882a593Smuzhiyun if (ret) {
414*4882a593Smuzhiyun if (ret == -ENODEV)
415*4882a593Smuzhiyun printf("sgm41542: Can't find PD\n");
416*4882a593Smuzhiyun else
417*4882a593Smuzhiyun printf("sgm41542: Get UCLASS PD failed: %d\n", ret);
418*4882a593Smuzhiyun charger->pd = NULL;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun if (!sgm41542_get_pd_output_val(charger, &pd_inputvol, &pd_inputcurrent)) {
423*4882a593Smuzhiyun SGM_DBG("pd adapter\n");
424*4882a593Smuzhiyun sgm4154x_set_input_curr_lim(charger, pd_inputcurrent);
425*4882a593Smuzhiyun } else {
426*4882a593Smuzhiyun SGM_DBG("normal adapter: %d\n", sgm41542_get_usb_type());
427*4882a593Smuzhiyun if (sgm41542_get_usb_type() == POWER_SUPPLY_TYPE_USB_DCP)
428*4882a593Smuzhiyun sgm4154x_set_input_curr_lim(charger, dcp_inputcurrent);
429*4882a593Smuzhiyun else if (sgm41542_get_usb_type() == POWER_SUPPLY_TYPE_USB_CDP)
430*4882a593Smuzhiyun sgm4154x_set_input_curr_lim(charger, dcp_inputcurrent);
431*4882a593Smuzhiyun else if (sgm41542_get_usb_type() == POWER_SUPPLY_TYPE_USB_FLOATING)
432*4882a593Smuzhiyun sgm4154x_set_input_curr_lim(charger, dcp_inputcurrent);
433*4882a593Smuzhiyun else
434*4882a593Smuzhiyun sgm4154x_set_input_curr_lim(charger, sdp_inputcurrent);
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
sgm41542_charger_status(struct udevice * dev)438*4882a593Smuzhiyun static bool sgm41542_charger_status(struct udevice *dev)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun struct sgm41542 *charger = dev_get_priv(dev);
441*4882a593Smuzhiyun int state_of_charger;
442*4882a593Smuzhiyun u8 value;
443*4882a593Smuzhiyun int i = 0;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun __retry:
446*4882a593Smuzhiyun sgm41542_read(charger, SGM4154x_CHRG_STAT, &value);
447*4882a593Smuzhiyun state_of_charger = !!(value & SGM4154x_PG_STAT);
448*4882a593Smuzhiyun if (!state_of_charger && charger->pd_online) {
449*4882a593Smuzhiyun if (i < 3) {
450*4882a593Smuzhiyun i++;
451*4882a593Smuzhiyun mdelay(20);
452*4882a593Smuzhiyun goto __retry;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun if ((state_of_charger) && (charger->init_count < 5)) {
457*4882a593Smuzhiyun sgm41542_charger_input_current_init(charger);
458*4882a593Smuzhiyun sgm41542_update_bits(charger,
459*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_1,
460*4882a593Smuzhiyun SGM4154x_CHRG_EN,
461*4882a593Smuzhiyun SGM4154x_CHRG_EN);
462*4882a593Smuzhiyun charger->init_count++;
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun if (!state_of_charger)
466*4882a593Smuzhiyun sgm4154x_set_prechrg_curr(charger, SGM4154x_PRECHRG_I_DEF_uA);
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun SGM_DBG("dump register:\n");
469*4882a593Smuzhiyun for (i = SGM4154x_CHRG_CTRL_0; i < SGM4154x_CHRG_CTRL_f; i++) {
470*4882a593Smuzhiyun sgm41542_read(charger, i, &value);
471*4882a593Smuzhiyun SGM_DBG("[%d]: 0x%x\n", i, value);
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun return state_of_charger;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
sgm41542_irq_handler(int irq,void * data)476*4882a593Smuzhiyun static void sgm41542_irq_handler(int irq, void *data)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun
sgm41542_ofdata_to_platdata(struct udevice * dev)480*4882a593Smuzhiyun static int sgm41542_ofdata_to_platdata(struct udevice *dev)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun struct sgm41542 *charger = dev_get_priv(dev);
483*4882a593Smuzhiyun u32 interrupt, phandle;
484*4882a593Smuzhiyun int ret;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun charger->dev = dev;
487*4882a593Smuzhiyun charger->ichg = dev_read_u32_default(dev,
488*4882a593Smuzhiyun "vbat-current-limit-microamp",
489*4882a593Smuzhiyun 0);
490*4882a593Smuzhiyun if (charger->ichg == 0)
491*4882a593Smuzhiyun charger->ichg = 3000 * 1000;
492*4882a593Smuzhiyun charger->vchg = dev_read_u32_default(dev,
493*4882a593Smuzhiyun "vbat-voltage-limit-microamp",
494*4882a593Smuzhiyun 0);
495*4882a593Smuzhiyun if (charger->vchg == 0)
496*4882a593Smuzhiyun charger->vchg = 4400 * 1000;
497*4882a593Smuzhiyun SGM_DBG("charger->ichg: %d\n", charger->ichg);
498*4882a593Smuzhiyun SGM_DBG("charger->vchg: %d\n", charger->vchg);
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun phandle = dev_read_u32_default(dev, "interrupt-parent", -ENODATA);
501*4882a593Smuzhiyun if (phandle == -ENODATA) {
502*4882a593Smuzhiyun printf("sgm41542: read 'interrupt-parent' failed, ret=%d\n",
503*4882a593Smuzhiyun phandle);
504*4882a593Smuzhiyun return phandle;
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun ret = dev_read_u32_array(dev, "interrupts", &interrupt, 1);
508*4882a593Smuzhiyun if (ret) {
509*4882a593Smuzhiyun printf("sgm41542: read 'interrupts' failed, ret=%d\n", ret);
510*4882a593Smuzhiyun return ret;
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun charger->irq = phandle_gpio_to_irq(phandle, interrupt);
514*4882a593Smuzhiyun if (charger->irq < 0)
515*4882a593Smuzhiyun printf("sgm41542: failed to request irq: %d\n", charger->irq);
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun return 0;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun
sgm41542_probe(struct udevice * dev)520*4882a593Smuzhiyun static int sgm41542_probe(struct udevice *dev)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun struct sgm41542 *charger = dev_get_priv(dev);
523*4882a593Smuzhiyun u8 value;
524*4882a593Smuzhiyun int i;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun SGM_DBG("sgm41542: driver version-20220903\n");
527*4882a593Smuzhiyun SGM_DBG("sgm41542: dump register:\n");
528*4882a593Smuzhiyun for (i = SGM4154x_CHRG_CTRL_0; i < SGM4154x_CHRG_CTRL_f; i++) {
529*4882a593Smuzhiyun sgm41542_read(charger, i, &value);
530*4882a593Smuzhiyun SGM_DBG("gm41542: [%d]: 0x%x\n", i, value);
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun charger->dev = dev;
534*4882a593Smuzhiyun /* disable watchdog */
535*4882a593Smuzhiyun sgm41542_update_bits(charger, SGM4154x_CHRG_CTRL_5,
536*4882a593Smuzhiyun SGM4154x_WDT_TIMER_MASK,
537*4882a593Smuzhiyun SGM4154x_WDT_TIMER_DISABLE);
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun sgm41542_update_bits(charger, SGM4154x_CHRG_CTRL_a,
540*4882a593Smuzhiyun SGM4154x_VINDPM_INT_MASK | SGM4154x_IINDPM_INT_MASK,
541*4882a593Smuzhiyun SGM4154x_VINDPM_INT_DIS | SGM4154x_IINDPM_INT_DIS);
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun sgm4154x_set_ichrg_curr(charger, charger->ichg);
544*4882a593Smuzhiyun sgm4154x_set_chrg_volt(charger, charger->vchg);
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun if (0 && charger->irq) {
547*4882a593Smuzhiyun SGM_DBG("sgm41542: enable sgm42542 irq\n");
548*4882a593Smuzhiyun irq_install_handler(charger->irq, sgm41542_irq_handler, dev);
549*4882a593Smuzhiyun irq_handler_enable(charger->irq);
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun return 0;
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun static const struct udevice_id charger_ids[] = {
556*4882a593Smuzhiyun { .compatible = "sgm,sgm41542" },
557*4882a593Smuzhiyun { },
558*4882a593Smuzhiyun };
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun static struct dm_fuel_gauge_ops charger_ops = {
561*4882a593Smuzhiyun .get_chrg_online = sgm41542_charger_status,
562*4882a593Smuzhiyun .capability = sgm41542_charger_capability,
563*4882a593Smuzhiyun .set_charger_voltage = sgm41542_set_charger_voltage,
564*4882a593Smuzhiyun .set_charger_enable = sgm41542_charger_enable,
565*4882a593Smuzhiyun .set_charger_disable = sgm41542_charger_disable,
566*4882a593Smuzhiyun .set_charger_current = sgm41542_charger_current,
567*4882a593Smuzhiyun .set_iprechg_current = sgm41542_iprechg_current,
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun };
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun U_BOOT_DRIVER(sgm41542_charger) = {
572*4882a593Smuzhiyun .name = "sgm41542_charger",
573*4882a593Smuzhiyun .id = UCLASS_FG,
574*4882a593Smuzhiyun .probe = sgm41542_probe,
575*4882a593Smuzhiyun .of_match = charger_ids,
576*4882a593Smuzhiyun .ops = &charger_ops,
577*4882a593Smuzhiyun .ofdata_to_platdata = sgm41542_ofdata_to_platdata,
578*4882a593Smuzhiyun .priv_auto_alloc_size = sizeof(struct sgm41542),
579*4882a593Smuzhiyun };
580