xref: /OK3568_Linux_fs/u-boot/drivers/power/charge/sc8551_charger.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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, &reg);
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