1*eb119257SChen Shunqing /*
2*eb119257SChen Shunqing * (C) Copyright 2025 Rockchip Electronics Co., Ltd
3*eb119257SChen Shunqing *
4*eb119257SChen Shunqing * SPDX-License-Identifier: GPL-2.0+
5*eb119257SChen Shunqing */
6*eb119257SChen Shunqing
7*eb119257SChen Shunqing #include <common.h>
8*eb119257SChen Shunqing #include <dm.h>
9*eb119257SChen Shunqing #include <i2c.h>
10*eb119257SChen Shunqing #include <irq-generic.h>
11*eb119257SChen Shunqing #include <power/fuel_gauge.h>
12*eb119257SChen Shunqing #include <linux/usb/phy-rockchip-usb2.h>
13*eb119257SChen Shunqing #include <power/power_delivery/power_delivery.h>
14*eb119257SChen Shunqing
15*eb119257SChen Shunqing DECLARE_GLOBAL_DATA_PTR;
16*eb119257SChen Shunqing
17*eb119257SChen Shunqing static int dbg_enable;
18*eb119257SChen Shunqing
19*eb119257SChen Shunqing #define CPS_DBG(args...) \
20*eb119257SChen Shunqing do { \
21*eb119257SChen Shunqing if (dbg_enable) { \
22*eb119257SChen Shunqing printf(args); \
23*eb119257SChen Shunqing } \
24*eb119257SChen Shunqing } while (0)
25*eb119257SChen Shunqing
26*eb119257SChen Shunqing #define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
27*eb119257SChen Shunqing
28*eb119257SChen Shunqing /* Register 00h */
29*eb119257SChen Shunqing #define CPS5601X_REG_00 0x00
30*eb119257SChen Shunqing #define CPS5601X_PRODUCT_ID_MASK GENMASK(7, 0)
31*eb119257SChen Shunqing /* default 0xA9=CPS5601 */
32*eb119257SChen Shunqing
33*eb119257SChen Shunqing /* Register 01h */
34*eb119257SChen Shunqing #define CPS5601X_REG_01 0x01
35*eb119257SChen Shunqing
36*eb119257SChen Shunqing /* Register 02h */
37*eb119257SChen Shunqing #define CPS5601X_REG_02 0x02
38*eb119257SChen Shunqing
39*eb119257SChen Shunqing /* Register 03h */
40*eb119257SChen Shunqing #define CPS5601X_REG_03 0x03
41*eb119257SChen Shunqing #define VREG_MASK GENMASK(6, 0)
42*eb119257SChen Shunqing #define VREG_BASE 3600000
43*eb119257SChen Shunqing #define VREG_LSB 10000
44*eb119257SChen Shunqing #define VREG_MAXVAL 0x6e
45*eb119257SChen Shunqing
46*eb119257SChen Shunqing /* Register 04h */
47*eb119257SChen Shunqing #define CPS5601X_REG_04 0x04
48*eb119257SChen Shunqing #define ICHG_MASK GENMASK(6, 0)
49*eb119257SChen Shunqing #define ICHG_BASE 0
50*eb119257SChen Shunqing #define ICHG_LSB 25000
51*eb119257SChen Shunqing #define ICHG_MINVAL 0x4
52*eb119257SChen Shunqing #define ICHG_MAXVAL 0x78
53*eb119257SChen Shunqing
54*eb119257SChen Shunqing /* Register 05h */
55*eb119257SChen Shunqing #define CPS5601X_REG_05 0x05
56*eb119257SChen Shunqing #define EN_TERM_MASK BIT(6)
57*eb119257SChen Shunqing #define EN_TERM_ENABLE(x) UPDATE(x, 6, 6)
58*eb119257SChen Shunqing #define IPRECHG_MASK GENMASK(5, 0)
59*eb119257SChen Shunqing #define IPRECHG_BASE 0
60*eb119257SChen Shunqing #define IPRECHG_LSB 12500
61*eb119257SChen Shunqing #define IPRECHG_MINVAL 0x1
62*eb119257SChen Shunqing #define IPRECHG_MAXVAL 0x3c
63*eb119257SChen Shunqing
64*eb119257SChen Shunqing /* Register 06h */
65*eb119257SChen Shunqing #define CPS5601X_REG_06 0x06
66*eb119257SChen Shunqing #define ITERM_MASK GENMASK(5, 0)
67*eb119257SChen Shunqing #define ITERM_BASE 0
68*eb119257SChen Shunqing #define ITERM_LSB 10000
69*eb119257SChen Shunqing #define ITERM_MINVAL 0x5
70*eb119257SChen Shunqing #define ITERM_MAXVAL 0x3c
71*eb119257SChen Shunqing
72*eb119257SChen Shunqing /* Register 07h */
73*eb119257SChen Shunqing #define CPS5601X_REG_07 0x07
74*eb119257SChen Shunqing #define VINDPM_MASK GENMASK(5, 0)
75*eb119257SChen Shunqing #define VINDPM_BASE 3400000
76*eb119257SChen Shunqing #define VINDPM_LSB 100000
77*eb119257SChen Shunqing #define VINDPM_MINVAL 0x4
78*eb119257SChen Shunqing #define VINDPM_MAXVAL 0x3e
79*eb119257SChen Shunqing
80*eb119257SChen Shunqing /* Register 08h */
81*eb119257SChen Shunqing #define CPS5601X_REG_08 0x08
82*eb119257SChen Shunqing #define IINDPM_MASK GENMASK(5, 0)
83*eb119257SChen Shunqing #define IINDPM_BASE 50000
84*eb119257SChen Shunqing #define IINDPM_LSB 50000
85*eb119257SChen Shunqing #define IINDPM_MINVAL 0x1
86*eb119257SChen Shunqing
87*eb119257SChen Shunqing /* Register 09h */
88*eb119257SChen Shunqing #define CPS5601X_REG_09 0x09
89*eb119257SChen Shunqing #define VOTG_MASK GENMASK(5, 0)
90*eb119257SChen Shunqing #define VOTG_BASE 3400000
91*eb119257SChen Shunqing #define VOTG_LSB 100000
92*eb119257SChen Shunqing #define VOTG_MAXVAL 0x3e
93*eb119257SChen Shunqing
94*eb119257SChen Shunqing /* Register 0Ah */
95*eb119257SChen Shunqing #define CPS5601X_REG_0A 0x0A
96*eb119257SChen Shunqing #define IOTG_MASK GENMASK(5, 0)
97*eb119257SChen Shunqing #define IOTG_BASE 50000
98*eb119257SChen Shunqing #define IOTG_LSB 50000
99*eb119257SChen Shunqing #define IOTG_MINVAL 0x1
100*eb119257SChen Shunqing
101*eb119257SChen Shunqing /* Register 0Bh */
102*eb119257SChen Shunqing #define CPS5601X_REG_0B 0x0B
103*eb119257SChen Shunqing #define WATCHDOG_MASK GENMASK(7, 6)
104*eb119257SChen Shunqing #define WATCHDOG_TIME(x) UPDATE(x, 7, 6)
105*eb119257SChen Shunqing #define WATCHDOG_BASE 0
106*eb119257SChen Shunqing #define WATCHDOG_LSB 40
107*eb119257SChen Shunqing #define WD_RST_MASK BIT(5)
108*eb119257SChen Shunqing #define WD_RST(x) UPDATE(x, 5, 5)
109*eb119257SChen Shunqing #define EN_CHG_MASK BIT(3)
110*eb119257SChen Shunqing #define EN_CHG(x) UPDATE(x, 3, 3)
111*eb119257SChen Shunqing
112*eb119257SChen Shunqing /* Register 0Ch */
113*eb119257SChen Shunqing #define CPS5601X_REG_0C 0x0C
114*eb119257SChen Shunqing #define EN_OTG_MASK BIT(3)
115*eb119257SChen Shunqing #define EN_OTG(x) UPDATE(x, 3, 3)
116*eb119257SChen Shunqing
117*eb119257SChen Shunqing /* Register 0Dh */
118*eb119257SChen Shunqing #define CPS5601X_REG_0D 0x0D
119*eb119257SChen Shunqing
120*eb119257SChen Shunqing /* Register 0Eh */
121*eb119257SChen Shunqing #define CPS5601X_REG_0E 0x0E
122*eb119257SChen Shunqing #define TS_IGNORE_MASK BIT(0)
123*eb119257SChen Shunqing #define EN_TS_IGNORE(x) UPDATE(x, 0, 0)
124*eb119257SChen Shunqing
125*eb119257SChen Shunqing /* Register 0Fh */
126*eb119257SChen Shunqing #define CPS5601X_REG_0F 0x0F
127*eb119257SChen Shunqing #define PG_STAT_MASK BIT(3)
128*eb119257SChen Shunqing
129*eb119257SChen Shunqing /* Register 10h */
130*eb119257SChen Shunqing #define CPS5601X_REG_10 0x10
131*eb119257SChen Shunqing #define CHG_STAT_MASK GENMASK(7, 5)
132*eb119257SChen Shunqing #define CHG_STAT_SHIFT 5
133*eb119257SChen Shunqing #define CHG_STAT_NOTCHG 0
134*eb119257SChen Shunqing #define CHG_STAT_TRICKLECHG 1
135*eb119257SChen Shunqing #define CHG_STAT_PRECHG 2
136*eb119257SChen Shunqing #define CHG_STAT_FASTCHG 3
137*eb119257SChen Shunqing #define CHG_STAT_TAPERCHG 4
138*eb119257SChen Shunqing #define CHG_STAT_RESERVED 5
139*eb119257SChen Shunqing #define CHG_STAT_TOTACHG 6
140*eb119257SChen Shunqing #define CHG_STAT_CHGTERM 7
141*eb119257SChen Shunqing #define VBUS_STAT_MASK GENMASK(4, 1)
142*eb119257SChen Shunqing #define VBUS_STAT_SHIFT 1
143*eb119257SChen Shunqing #define VBUS_STAT_NOT 0
144*eb119257SChen Shunqing #define VBUS_STAT_USBSDP 1
145*eb119257SChen Shunqing #define VBUS_STAT_USBCDP 2
146*eb119257SChen Shunqing #define VBUS_STAT_USBDCP 3
147*eb119257SChen Shunqing #define VBUS_STAT_HVDCP 4
148*eb119257SChen Shunqing #define VBUS_STAT_UNKNOWN 5
149*eb119257SChen Shunqing #define VBUS_STAT_NONSTANDARD 6
150*eb119257SChen Shunqing #define VBUS_STAT_OTGMODE 7
151*eb119257SChen Shunqing #define VBUS_STAT_NOTQUALIFIED 8
152*eb119257SChen Shunqing
153*eb119257SChen Shunqing /* Register 11h */
154*eb119257SChen Shunqing #define CPS5601X_REG_11 0x11
155*eb119257SChen Shunqing
156*eb119257SChen Shunqing /* Register 12h */
157*eb119257SChen Shunqing #define CPS5601X_REG_12 0x12
158*eb119257SChen Shunqing
159*eb119257SChen Shunqing /* Register 13h */
160*eb119257SChen Shunqing #define CPS5601X_REG_13 0x13
161*eb119257SChen Shunqing
162*eb119257SChen Shunqing /* Register 14h */
163*eb119257SChen Shunqing #define CPS5601X_REG_14 0x14
164*eb119257SChen Shunqing
165*eb119257SChen Shunqing /* Register 15h */
166*eb119257SChen Shunqing #define CPS5601X_REG_15 0x15
167*eb119257SChen Shunqing
168*eb119257SChen Shunqing /* Register 16h */
169*eb119257SChen Shunqing #define CPS5601X_REG_16 0x16
170*eb119257SChen Shunqing
171*eb119257SChen Shunqing /* Register 17h */
172*eb119257SChen Shunqing #define CPS5601X_REG_17 0x17
173*eb119257SChen Shunqing
174*eb119257SChen Shunqing /* Register 18h */
175*eb119257SChen Shunqing #define CPS5601X_REG_18 0x18
176*eb119257SChen Shunqing
177*eb119257SChen Shunqing /* Register 19h */
178*eb119257SChen Shunqing #define CPS5601X_REG_19 0x19
179*eb119257SChen Shunqing #define TREG_MK_MASK BIT(7)
180*eb119257SChen Shunqing
181*eb119257SChen Shunqing /* Register 1Ah */
182*eb119257SChen Shunqing #define CPS5601X_REG_1A 0x1A
183*eb119257SChen Shunqing
184*eb119257SChen Shunqing /* Register 1Bh */
185*eb119257SChen Shunqing #define CPS5601X_REG_1B 0x1B
186*eb119257SChen Shunqing
187*eb119257SChen Shunqing #define CPS5601X_ICHRG_I_DEF_uA 2040000
188*eb119257SChen Shunqing #define CPS5601X_VREG_V_DEF_uV 4208000
189*eb119257SChen Shunqing #define CPS5601X_PRECHRG_I_DEF_uA 180000
190*eb119257SChen Shunqing #define CPS5601X_TERMCHRG_I_DEF_uA 180000
191*eb119257SChen Shunqing #define CPS5601X_ICHRG_I_MIN_uA 100000
192*eb119257SChen Shunqing #define CPS5601X_ICHRG_I_MAX_uA 3000000
193*eb119257SChen Shunqing #define CPS5601X_VINDPM_DEF_uV 4500000
194*eb119257SChen Shunqing #define CPS5601X_VINDPM_V_MIN_uV 3800000
195*eb119257SChen Shunqing #define CPS5601X_VINDPM_V_MAX_uV 9600000
196*eb119257SChen Shunqing #define CPS5601X_IINDPM_DEF_uA 2400000
197*eb119257SChen Shunqing #define CPS5601X_IINDPM_I_MIN_uA 100000
198*eb119257SChen Shunqing #define CPS5601X_IINDPM_I_MAX_uA 3200000
199*eb119257SChen Shunqing #define DEFAULT_INPUT_CURRENT (500 * 1000)
200*eb119257SChen Shunqing
201*eb119257SChen Shunqing struct cps5601x {
202*eb119257SChen Shunqing struct udevice *dev;
203*eb119257SChen Shunqing struct udevice *pd;
204*eb119257SChen Shunqing bool pd_online;
205*eb119257SChen Shunqing u32 init_count;
206*eb119257SChen Shunqing u32 ichg;
207*eb119257SChen Shunqing u32 vchg;
208*eb119257SChen Shunqing int irq;
209*eb119257SChen Shunqing };
210*eb119257SChen Shunqing
211*eb119257SChen Shunqing enum power_supply_type {
212*eb119257SChen Shunqing POWER_SUPPLY_TYPE_UNKNOWN = 0,
213*eb119257SChen Shunqing POWER_SUPPLY_TYPE_USB, /* Standard Downstream Port */
214*eb119257SChen Shunqing POWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */
215*eb119257SChen Shunqing POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */
216*eb119257SChen Shunqing POWER_SUPPLY_TYPE_USB_FLOATING, /* DCP without shorting D+/D- */
217*eb119257SChen Shunqing };
218*eb119257SChen Shunqing
cps5601x_read(struct cps5601x * charger,uint reg,u8 * buffer)219*eb119257SChen Shunqing static int cps5601x_read(struct cps5601x *charger, uint reg, u8 *buffer)
220*eb119257SChen Shunqing {
221*eb119257SChen Shunqing u8 val;
222*eb119257SChen Shunqing int ret;
223*eb119257SChen Shunqing
224*eb119257SChen Shunqing ret = dm_i2c_read(charger->dev, reg, &val, 1);
225*eb119257SChen Shunqing if (ret) {
226*eb119257SChen Shunqing printf("cps5601x: read %#x error, ret=%d", reg, ret);
227*eb119257SChen Shunqing return ret;
228*eb119257SChen Shunqing }
229*eb119257SChen Shunqing
230*eb119257SChen Shunqing *buffer = val;
231*eb119257SChen Shunqing
232*eb119257SChen Shunqing return 0;
233*eb119257SChen Shunqing }
234*eb119257SChen Shunqing
cps5601x_write(struct cps5601x * charger,uint reg,u8 val)235*eb119257SChen Shunqing static int cps5601x_write(struct cps5601x *charger, uint reg, u8 val)
236*eb119257SChen Shunqing {
237*eb119257SChen Shunqing int ret;
238*eb119257SChen Shunqing
239*eb119257SChen Shunqing ret = dm_i2c_write(charger->dev, reg, &val, 1);
240*eb119257SChen Shunqing if (ret)
241*eb119257SChen Shunqing printf("cps5601x: write %#x error, ret=%d", reg, ret);
242*eb119257SChen Shunqing
243*eb119257SChen Shunqing return ret;
244*eb119257SChen Shunqing }
245*eb119257SChen Shunqing
cps5601x_update_bits(struct cps5601x * charger,u8 offset,u8 mask,u8 val)246*eb119257SChen Shunqing static int cps5601x_update_bits(struct cps5601x *charger,
247*eb119257SChen Shunqing u8 offset,
248*eb119257SChen Shunqing u8 mask,
249*eb119257SChen Shunqing u8 val)
250*eb119257SChen Shunqing {
251*eb119257SChen Shunqing u8 reg;
252*eb119257SChen Shunqing int ret;
253*eb119257SChen Shunqing
254*eb119257SChen Shunqing ret = cps5601x_read(charger, offset, ®);
255*eb119257SChen Shunqing if (ret)
256*eb119257SChen Shunqing return ret;
257*eb119257SChen Shunqing
258*eb119257SChen Shunqing reg &= ~mask;
259*eb119257SChen Shunqing
260*eb119257SChen Shunqing return cps5601x_write(charger, offset, reg | val);
261*eb119257SChen Shunqing }
262*eb119257SChen Shunqing
cps5601x_set_input_current_limit(struct cps5601x * cps,int curr)263*eb119257SChen Shunqing static int cps5601x_set_input_current_limit(struct cps5601x *cps, int curr)
264*eb119257SChen Shunqing {
265*eb119257SChen Shunqing u8 val;
266*eb119257SChen Shunqing
267*eb119257SChen Shunqing if (curr < IINDPM_BASE + (IINDPM_MINVAL * IINDPM_LSB))
268*eb119257SChen Shunqing curr = IINDPM_BASE + (IINDPM_MINVAL * IINDPM_LSB);
269*eb119257SChen Shunqing
270*eb119257SChen Shunqing val = (curr - IINDPM_BASE) / IINDPM_LSB;
271*eb119257SChen Shunqing
272*eb119257SChen Shunqing return cps5601x_update_bits(cps, CPS5601X_REG_08, IINDPM_MASK, val);
273*eb119257SChen Shunqing }
274*eb119257SChen Shunqing
cps5601x_get_usb_type(void)275*eb119257SChen Shunqing static int cps5601x_get_usb_type(void)
276*eb119257SChen Shunqing {
277*eb119257SChen Shunqing #ifdef CONFIG_PHY_ROCKCHIP_INNO_USB2
278*eb119257SChen Shunqing return rockchip_chg_get_type();
279*eb119257SChen Shunqing #else
280*eb119257SChen Shunqing return 0;
281*eb119257SChen Shunqing #endif
282*eb119257SChen Shunqing }
283*eb119257SChen Shunqing
cps5601x_charger_capability(struct udevice * dev)284*eb119257SChen Shunqing static int cps5601x_charger_capability(struct udevice *dev)
285*eb119257SChen Shunqing {
286*eb119257SChen Shunqing return FG_CAP_CHARGER;
287*eb119257SChen Shunqing }
288*eb119257SChen Shunqing
cps5601x_set_chargecurrent(struct cps5601x * cps,int curr)289*eb119257SChen Shunqing static int cps5601x_set_chargecurrent(struct cps5601x *cps, int curr)
290*eb119257SChen Shunqing {
291*eb119257SChen Shunqing u8 ichg;
292*eb119257SChen Shunqing
293*eb119257SChen Shunqing if (curr < (ICHG_BASE + (ICHG_MINVAL * ICHG_LSB)))
294*eb119257SChen Shunqing curr = ICHG_BASE + (ICHG_MINVAL * ICHG_LSB);
295*eb119257SChen Shunqing else if (curr > (ICHG_BASE + (ICHG_MAXVAL * ICHG_LSB)))
296*eb119257SChen Shunqing curr = ICHG_BASE + (ICHG_MAXVAL * ICHG_LSB);
297*eb119257SChen Shunqing
298*eb119257SChen Shunqing ichg = (curr - ICHG_BASE) / ICHG_LSB;
299*eb119257SChen Shunqing
300*eb119257SChen Shunqing return cps5601x_update_bits(cps, CPS5601X_REG_04, ICHG_MASK, ichg);
301*eb119257SChen Shunqing }
302*eb119257SChen Shunqing
cps5601x_set_iprechg(struct cps5601x * cps,int curr)303*eb119257SChen Shunqing static int cps5601x_set_iprechg(struct cps5601x *cps, int curr)
304*eb119257SChen Shunqing {
305*eb119257SChen Shunqing u8 iprechg;
306*eb119257SChen Shunqing
307*eb119257SChen Shunqing if (curr < (IPRECHG_BASE + (IPRECHG_MINVAL * IPRECHG_LSB)))
308*eb119257SChen Shunqing curr = IPRECHG_BASE + (IPRECHG_MINVAL * IPRECHG_LSB);
309*eb119257SChen Shunqing else if (curr > (IPRECHG_BASE + (IPRECHG_MAXVAL * IPRECHG_LSB)))
310*eb119257SChen Shunqing curr = IPRECHG_BASE + (IPRECHG_MAXVAL * IPRECHG_LSB);
311*eb119257SChen Shunqing
312*eb119257SChen Shunqing iprechg = (curr - IPRECHG_BASE) / IPRECHG_LSB;
313*eb119257SChen Shunqing
314*eb119257SChen Shunqing return cps5601x_update_bits(cps, CPS5601X_REG_05, IPRECHG_MASK,
315*eb119257SChen Shunqing iprechg);
316*eb119257SChen Shunqing }
317*eb119257SChen Shunqing
cps5601x_set_chargevolt(struct cps5601x * cps,int volt)318*eb119257SChen Shunqing static int cps5601x_set_chargevolt(struct cps5601x *cps, int volt)
319*eb119257SChen Shunqing {
320*eb119257SChen Shunqing u8 val;
321*eb119257SChen Shunqing
322*eb119257SChen Shunqing if (volt < VREG_BASE)
323*eb119257SChen Shunqing volt = VREG_BASE;
324*eb119257SChen Shunqing else if (volt > (VREG_BASE + (VREG_MAXVAL * VREG_LSB)))
325*eb119257SChen Shunqing volt = VREG_BASE + (VREG_MAXVAL * VREG_LSB);
326*eb119257SChen Shunqing
327*eb119257SChen Shunqing val = (volt - VREG_BASE) / VREG_LSB;
328*eb119257SChen Shunqing
329*eb119257SChen Shunqing return cps5601x_update_bits(cps, CPS5601X_REG_03, VREG_MASK, val);
330*eb119257SChen Shunqing }
331*eb119257SChen Shunqing
cps5601x_set_charger_voltage(struct udevice * dev,int uV)332*eb119257SChen Shunqing static int cps5601x_set_charger_voltage(struct udevice *dev, int uV)
333*eb119257SChen Shunqing {
334*eb119257SChen Shunqing struct cps5601x *charger = dev_get_priv(dev);
335*eb119257SChen Shunqing
336*eb119257SChen Shunqing CPS_DBG("CPS5601X: charger voltage %d\n", uV);
337*eb119257SChen Shunqing return cps5601x_set_chargevolt(charger, uV);
338*eb119257SChen Shunqing }
339*eb119257SChen Shunqing
cps5601x_charger_enable(struct udevice * dev)340*eb119257SChen Shunqing static int cps5601x_charger_enable(struct udevice *dev)
341*eb119257SChen Shunqing {
342*eb119257SChen Shunqing struct cps5601x *charger = dev_get_priv(dev);
343*eb119257SChen Shunqing
344*eb119257SChen Shunqing CPS_DBG("CPS5601X: charger enable\n");
345*eb119257SChen Shunqing return cps5601x_update_bits(charger, CPS5601X_REG_0B, EN_CHG_MASK,
346*eb119257SChen Shunqing EN_CHG(1));
347*eb119257SChen Shunqing }
348*eb119257SChen Shunqing
cps5601x_charger_disable(struct udevice * dev)349*eb119257SChen Shunqing static int cps5601x_charger_disable(struct udevice *dev)
350*eb119257SChen Shunqing {
351*eb119257SChen Shunqing struct cps5601x *charger = dev_get_priv(dev);
352*eb119257SChen Shunqing
353*eb119257SChen Shunqing CPS_DBG("CPS5601X: charger disable\n");
354*eb119257SChen Shunqing return cps5601x_update_bits(charger, CPS5601X_REG_0B, EN_CHG_MASK,
355*eb119257SChen Shunqing EN_CHG(0));
356*eb119257SChen Shunqing }
357*eb119257SChen Shunqing
cps5601x_iprechg_current(struct udevice * dev,int iprechrg_uA)358*eb119257SChen Shunqing static int cps5601x_iprechg_current(struct udevice *dev, int iprechrg_uA)
359*eb119257SChen Shunqing {
360*eb119257SChen Shunqing struct cps5601x *charger = dev_get_priv(dev);
361*eb119257SChen Shunqing
362*eb119257SChen Shunqing CPS_DBG("CPS5601x: charger current:iprechrg_uA: %d\n",
363*eb119257SChen Shunqing iprechrg_uA);
364*eb119257SChen Shunqing
365*eb119257SChen Shunqing return cps5601x_set_iprechg(charger, iprechrg_uA);
366*eb119257SChen Shunqing }
367*eb119257SChen Shunqing
cps5601x_charger_current(struct udevice * dev,int ichrg_uA)368*eb119257SChen Shunqing static int cps5601x_charger_current(struct udevice *dev, int ichrg_uA)
369*eb119257SChen Shunqing {
370*eb119257SChen Shunqing struct cps5601x *charger = dev_get_priv(dev);
371*eb119257SChen Shunqing
372*eb119257SChen Shunqing CPS_DBG("CPS5601X: charger current:ichrg_uA%d\n",
373*eb119257SChen Shunqing ichrg_uA);
374*eb119257SChen Shunqing
375*eb119257SChen Shunqing return cps5601x_set_chargecurrent(charger, ichrg_uA);
376*eb119257SChen Shunqing }
377*eb119257SChen Shunqing
cps5601x_get_pd_output_val(struct cps5601x * charger,int * vol,int * cur)378*eb119257SChen Shunqing static int cps5601x_get_pd_output_val(struct cps5601x *charger,
379*eb119257SChen Shunqing int *vol,
380*eb119257SChen Shunqing int *cur)
381*eb119257SChen Shunqing {
382*eb119257SChen Shunqing struct power_delivery_data pd_data;
383*eb119257SChen Shunqing int ret;
384*eb119257SChen Shunqing
385*eb119257SChen Shunqing if (!charger->pd)
386*eb119257SChen Shunqing return -EINVAL;
387*eb119257SChen Shunqing
388*eb119257SChen Shunqing memset(&pd_data, 0, sizeof(pd_data));
389*eb119257SChen Shunqing ret = power_delivery_get_data(charger->pd, &pd_data);
390*eb119257SChen Shunqing if (ret)
391*eb119257SChen Shunqing return ret;
392*eb119257SChen Shunqing if (!pd_data.online || !pd_data.voltage || !pd_data.current)
393*eb119257SChen Shunqing return -EINVAL;
394*eb119257SChen Shunqing
395*eb119257SChen Shunqing *vol = pd_data.voltage;
396*eb119257SChen Shunqing *cur = pd_data.current;
397*eb119257SChen Shunqing charger->pd_online = pd_data.online;
398*eb119257SChen Shunqing
399*eb119257SChen Shunqing return 0;
400*eb119257SChen Shunqing }
401*eb119257SChen Shunqing
cps5601x_charger_input_current_init(struct cps5601x * charger)402*eb119257SChen Shunqing static void cps5601x_charger_input_current_init(struct cps5601x *charger)
403*eb119257SChen Shunqing {
404*eb119257SChen Shunqing int sdp_inputcurrent = 500 * 1000;
405*eb119257SChen Shunqing int dcp_inputcurrent = 2000 * 1000;
406*eb119257SChen Shunqing int pd_inputvol, pd_inputcurrent;
407*eb119257SChen Shunqing int ret;
408*eb119257SChen Shunqing
409*eb119257SChen Shunqing if (!charger->pd) {
410*eb119257SChen Shunqing ret = uclass_get_device(UCLASS_PD, 0, &charger->pd);
411*eb119257SChen Shunqing if (ret) {
412*eb119257SChen Shunqing if (ret == -ENODEV)
413*eb119257SChen Shunqing printf("cps5601x: Can't find PD\n");
414*eb119257SChen Shunqing else
415*eb119257SChen Shunqing printf("cps5601x: Get UCLASS PD failed: %d\n", ret);
416*eb119257SChen Shunqing charger->pd = NULL;
417*eb119257SChen Shunqing }
418*eb119257SChen Shunqing }
419*eb119257SChen Shunqing
420*eb119257SChen Shunqing if (!cps5601x_get_pd_output_val(charger, &pd_inputvol, &pd_inputcurrent)) {
421*eb119257SChen Shunqing CPS_DBG("pd adapter\n");
422*eb119257SChen Shunqing cps5601x_set_input_current_limit(charger, pd_inputcurrent);
423*eb119257SChen Shunqing } else {
424*eb119257SChen Shunqing CPS_DBG("normal adapter: %d\n", cps5601x_get_usb_type());
425*eb119257SChen Shunqing if (cps5601x_get_usb_type() == POWER_SUPPLY_TYPE_USB_DCP)
426*eb119257SChen Shunqing cps5601x_set_input_current_limit(charger, dcp_inputcurrent);
427*eb119257SChen Shunqing else if (cps5601x_get_usb_type() == POWER_SUPPLY_TYPE_USB_CDP)
428*eb119257SChen Shunqing cps5601x_set_input_current_limit(charger, dcp_inputcurrent);
429*eb119257SChen Shunqing else if (cps5601x_get_usb_type() == POWER_SUPPLY_TYPE_USB_FLOATING)
430*eb119257SChen Shunqing cps5601x_set_input_current_limit(charger, dcp_inputcurrent);
431*eb119257SChen Shunqing else
432*eb119257SChen Shunqing cps5601x_set_input_current_limit(charger, sdp_inputcurrent);
433*eb119257SChen Shunqing }
434*eb119257SChen Shunqing }
435*eb119257SChen Shunqing
cps5601x_charger_status(struct udevice * dev)436*eb119257SChen Shunqing static bool cps5601x_charger_status(struct udevice *dev)
437*eb119257SChen Shunqing {
438*eb119257SChen Shunqing struct cps5601x *charger = dev_get_priv(dev);
439*eb119257SChen Shunqing int state_of_charger;
440*eb119257SChen Shunqing u8 value;
441*eb119257SChen Shunqing int i = 0;
442*eb119257SChen Shunqing
443*eb119257SChen Shunqing __retry:
444*eb119257SChen Shunqing cps5601x_read(charger, CPS5601X_REG_0F, &value);
445*eb119257SChen Shunqing state_of_charger = !!(value & PG_STAT_MASK);
446*eb119257SChen Shunqing if (!state_of_charger && charger->pd_online) {
447*eb119257SChen Shunqing if (i < 3) {
448*eb119257SChen Shunqing i++;
449*eb119257SChen Shunqing mdelay(20);
450*eb119257SChen Shunqing goto __retry;
451*eb119257SChen Shunqing }
452*eb119257SChen Shunqing }
453*eb119257SChen Shunqing
454*eb119257SChen Shunqing if ((state_of_charger) && (charger->init_count < 5)) {
455*eb119257SChen Shunqing cps5601x_charger_input_current_init(charger);
456*eb119257SChen Shunqing cps5601x_charger_enable(dev);
457*eb119257SChen Shunqing charger->init_count++;
458*eb119257SChen Shunqing }
459*eb119257SChen Shunqing
460*eb119257SChen Shunqing if (!state_of_charger)
461*eb119257SChen Shunqing cps5601x_set_iprechg(charger, CPS5601X_PRECHRG_I_DEF_uA);
462*eb119257SChen Shunqing
463*eb119257SChen Shunqing CPS_DBG("dump register:\n");
464*eb119257SChen Shunqing for (i = CPS5601X_REG_00; i < CPS5601X_REG_1B; i++) {
465*eb119257SChen Shunqing cps5601x_read(charger, i, &value);
466*eb119257SChen Shunqing CPS_DBG("[%d]: 0x%x\n", i, value);
467*eb119257SChen Shunqing }
468*eb119257SChen Shunqing return state_of_charger;
469*eb119257SChen Shunqing }
470*eb119257SChen Shunqing
cps5601x_irq_handler(int irq,void * data)471*eb119257SChen Shunqing static void cps5601x_irq_handler(int irq, void *data)
472*eb119257SChen Shunqing {
473*eb119257SChen Shunqing }
474*eb119257SChen Shunqing
cps5601x_ofdata_to_platdata(struct udevice * dev)475*eb119257SChen Shunqing static int cps5601x_ofdata_to_platdata(struct udevice *dev)
476*eb119257SChen Shunqing {
477*eb119257SChen Shunqing struct cps5601x *charger = dev_get_priv(dev);
478*eb119257SChen Shunqing u32 interrupt, phandle;
479*eb119257SChen Shunqing int ret;
480*eb119257SChen Shunqing
481*eb119257SChen Shunqing charger->dev = dev;
482*eb119257SChen Shunqing charger->ichg = dev_read_u32_default(dev,
483*eb119257SChen Shunqing "vbat-current-limit-microamp",
484*eb119257SChen Shunqing 0);
485*eb119257SChen Shunqing if (charger->ichg == 0)
486*eb119257SChen Shunqing charger->ichg = 3000 * 1000;
487*eb119257SChen Shunqing charger->vchg = dev_read_u32_default(dev,
488*eb119257SChen Shunqing "vbat-voltage-limit-microamp",
489*eb119257SChen Shunqing 0);
490*eb119257SChen Shunqing if (charger->vchg == 0)
491*eb119257SChen Shunqing charger->vchg = 4400 * 1000;
492*eb119257SChen Shunqing CPS_DBG("charger->ichg: %d\n", charger->ichg);
493*eb119257SChen Shunqing CPS_DBG("charger->vchg: %d\n", charger->vchg);
494*eb119257SChen Shunqing
495*eb119257SChen Shunqing phandle = dev_read_u32_default(dev, "interrupt-parent", -ENODATA);
496*eb119257SChen Shunqing if (phandle == -ENODATA) {
497*eb119257SChen Shunqing printf("cps5601x: read 'interrupt-parent' failed, ret=%d\n",
498*eb119257SChen Shunqing phandle);
499*eb119257SChen Shunqing return phandle;
500*eb119257SChen Shunqing }
501*eb119257SChen Shunqing
502*eb119257SChen Shunqing ret = dev_read_u32_array(dev, "interrupts", &interrupt, 1);
503*eb119257SChen Shunqing if (ret) {
504*eb119257SChen Shunqing printf("cps5601x: read 'interrupts' failed, ret=%d\n", ret);
505*eb119257SChen Shunqing return ret;
506*eb119257SChen Shunqing }
507*eb119257SChen Shunqing
508*eb119257SChen Shunqing charger->irq = phandle_gpio_to_irq(phandle, interrupt);
509*eb119257SChen Shunqing if (charger->irq < 0)
510*eb119257SChen Shunqing printf("cps5601x: failed to request irq: %d\n", charger->irq);
511*eb119257SChen Shunqing
512*eb119257SChen Shunqing return 0;
513*eb119257SChen Shunqing }
514*eb119257SChen Shunqing
cps5601x_probe(struct udevice * dev)515*eb119257SChen Shunqing static int cps5601x_probe(struct udevice *dev)
516*eb119257SChen Shunqing {
517*eb119257SChen Shunqing struct cps5601x *charger = dev_get_priv(dev);
518*eb119257SChen Shunqing u8 value;
519*eb119257SChen Shunqing int i;
520*eb119257SChen Shunqing
521*eb119257SChen Shunqing CPS_DBG("cps5601x: driver version-202502024\n");
522*eb119257SChen Shunqing CPS_DBG("cps5601x: dump register:\n");
523*eb119257SChen Shunqing for (i = CPS5601X_REG_00; i < CPS5601X_REG_1B; i++) {
524*eb119257SChen Shunqing cps5601x_read(charger, i, &value);
525*eb119257SChen Shunqing CPS_DBG("cps5601x: [%d]: 0x%x\n", i, value);
526*eb119257SChen Shunqing }
527*eb119257SChen Shunqing
528*eb119257SChen Shunqing charger->dev = dev;
529*eb119257SChen Shunqing /* disable watchdog */
530*eb119257SChen Shunqing cps5601x_update_bits(charger, CPS5601X_REG_0B, WATCHDOG_MASK, WATCHDOG_TIME(0));
531*eb119257SChen Shunqing
532*eb119257SChen Shunqing cps5601x_update_bits(charger, CPS5601X_REG_0E, TS_IGNORE_MASK, EN_TS_IGNORE(1));
533*eb119257SChen Shunqing
534*eb119257SChen Shunqing cps5601x_set_chargecurrent(charger, charger->ichg);
535*eb119257SChen Shunqing cps5601x_set_chargevolt(charger, charger->vchg);
536*eb119257SChen Shunqing
537*eb119257SChen Shunqing if (0 && charger->irq) {
538*eb119257SChen Shunqing CPS_DBG("cps5601x: enable cps5601x irq\n");
539*eb119257SChen Shunqing irq_install_handler(charger->irq, cps5601x_irq_handler, dev);
540*eb119257SChen Shunqing irq_handler_enable(charger->irq);
541*eb119257SChen Shunqing }
542*eb119257SChen Shunqing
543*eb119257SChen Shunqing return 0;
544*eb119257SChen Shunqing }
545*eb119257SChen Shunqing
546*eb119257SChen Shunqing static const struct udevice_id charger_ids[] = {
547*eb119257SChen Shunqing { .compatible = "cps,cps5601x" },
548*eb119257SChen Shunqing { },
549*eb119257SChen Shunqing };
550*eb119257SChen Shunqing
551*eb119257SChen Shunqing static struct dm_fuel_gauge_ops charger_ops = {
552*eb119257SChen Shunqing .get_chrg_online = cps5601x_charger_status,
553*eb119257SChen Shunqing .capability = cps5601x_charger_capability,
554*eb119257SChen Shunqing .set_charger_voltage = cps5601x_set_charger_voltage,
555*eb119257SChen Shunqing .set_charger_enable = cps5601x_charger_enable,
556*eb119257SChen Shunqing .set_charger_disable = cps5601x_charger_disable,
557*eb119257SChen Shunqing .set_charger_current = cps5601x_charger_current,
558*eb119257SChen Shunqing .set_iprechg_current = cps5601x_iprechg_current,
559*eb119257SChen Shunqing
560*eb119257SChen Shunqing };
561*eb119257SChen Shunqing
562*eb119257SChen Shunqing U_BOOT_DRIVER(cps5601x_charger) = {
563*eb119257SChen Shunqing .name = "cps5601x_charger",
564*eb119257SChen Shunqing .id = UCLASS_FG,
565*eb119257SChen Shunqing .probe = cps5601x_probe,
566*eb119257SChen Shunqing .of_match = charger_ids,
567*eb119257SChen Shunqing .ops = &charger_ops,
568*eb119257SChen Shunqing .ofdata_to_platdata = cps5601x_ofdata_to_platdata,
569*eb119257SChen Shunqing .priv_auto_alloc_size = sizeof(struct cps5601x),
570*eb119257SChen Shunqing };
571