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