xref: /rk3399_rockchip-uboot/drivers/power/charge/bq25700_charger.c (revision 5035821e25b4216a5f34d7a4da91c9a35822312e)
1d19b8cd2SShunqing Chen /*
2d19b8cd2SShunqing Chen  * (C) Copyright 2019 Fuzhou Rockchip Electronics Co., Ltd
3d19b8cd2SShunqing Chen  *
4d19b8cd2SShunqing Chen  * SPDX-License-Identifier:	GPL-2.0+
5d19b8cd2SShunqing Chen  */
6d19b8cd2SShunqing Chen 
7d19b8cd2SShunqing Chen #include <common.h>
8d19b8cd2SShunqing Chen #include <asm/gpio.h>
9d19b8cd2SShunqing Chen #include <dm/device.h>
10947a1b47SShunqing Chen #include <dm/uclass.h>
11d19b8cd2SShunqing Chen #include <power/fuel_gauge.h>
12d19b8cd2SShunqing Chen #include <power/pmic.h>
13947a1b47SShunqing Chen #include <power/power_delivery/power_delivery.h>
1486623982SJianing Ren #include <linux/usb/phy-rockchip-usb2.h>
15d19b8cd2SShunqing Chen 
16d19b8cd2SShunqing Chen DECLARE_GLOBAL_DATA_PTR;
17d19b8cd2SShunqing Chen 
18d19b8cd2SShunqing Chen #define BQ25700_ID				0x25700
19d19b8cd2SShunqing Chen #define BQ25703_ID				0x25703
20d19b8cd2SShunqing Chen 
21d19b8cd2SShunqing Chen #define COMPAT_BQ25700				"ti,bq25700"
22d19b8cd2SShunqing Chen #define COMPAT_BQ25703				"ti,bq25703"
23d19b8cd2SShunqing Chen 
24d19b8cd2SShunqing Chen #define BQ25700_I2C_SPEED			100000
25d19b8cd2SShunqing Chen #define BQ25700_CHARGE_CURRENT_1500MA		0x5C0
26d19b8cd2SShunqing Chen #define BQ25700_SDP_INPUT_CURRENT_500MA		0xA00
27d19b8cd2SShunqing Chen #define BQ25700_DCP_INPUT_CURRENT_1500MA	0x1E00
28d19b8cd2SShunqing Chen #define BQ25700_DCP_INPUT_CURRENT_2000MA	0x2800
29d19b8cd2SShunqing Chen #define BQ25700_DCP_INPUT_CURRENT_3000MA	0x3C00
30d19b8cd2SShunqing Chen 
31d19b8cd2SShunqing Chen #define WATCHDOG_ENSABLE			(0x03 << 13)
32d19b8cd2SShunqing Chen 
33d19b8cd2SShunqing Chen #define BQ25700_CHARGEOPTION0_REG		0x12
34d19b8cd2SShunqing Chen #define BQ25700_CHARGECURREN_REG		0x14
35d19b8cd2SShunqing Chen #define BQ25700_CHARGERSTAUS_REG		0x20
36d19b8cd2SShunqing Chen #define BQ25700_INPUTVOLTAGE_REG		0x3D
37d19b8cd2SShunqing Chen #define BQ25700_INPUTCURREN_REG			0x3F
38d19b8cd2SShunqing Chen 
39d19b8cd2SShunqing Chen #define BQ25703_CHARGEOPTION0_REG		0x00
40d19b8cd2SShunqing Chen #define BQ25703_CHARGECURREN_REG		0x02
41d19b8cd2SShunqing Chen #define BQ25703_CHARGERSTAUS_REG		0x20
42d19b8cd2SShunqing Chen #define BQ25703_INPUTVOLTAGE_REG		0x0A
43d19b8cd2SShunqing Chen #define BQ25703_INPUTCURREN_REG			0x0E
44d19b8cd2SShunqing Chen 
45d19b8cd2SShunqing Chen enum bq25700_table_ids {
46d19b8cd2SShunqing Chen 	/* range tables */
47d19b8cd2SShunqing Chen 	TBL_ICHG,
48d19b8cd2SShunqing Chen 	TBL_CHGMAX,
49d19b8cd2SShunqing Chen 	TBL_INPUTVOL,
50d19b8cd2SShunqing Chen 	TBL_INPUTCUR,
51d19b8cd2SShunqing Chen 	TBL_SYSVMIN,
52d19b8cd2SShunqing Chen 	TBL_OTGVOL,
53d19b8cd2SShunqing Chen 	TBL_OTGCUR,
54d19b8cd2SShunqing Chen 	TBL_EXTCON,
55d19b8cd2SShunqing Chen };
56d19b8cd2SShunqing Chen 
57d19b8cd2SShunqing Chen struct bq25700 {
58d19b8cd2SShunqing Chen 	struct udevice *dev;
59d19b8cd2SShunqing Chen 	u32 ichg;
60d19b8cd2SShunqing Chen 	u32 chip_id;
61947a1b47SShunqing Chen 	struct udevice *pd;
62d19b8cd2SShunqing Chen };
63d19b8cd2SShunqing Chen 
64d19b8cd2SShunqing Chen struct bq25700_range {
65d19b8cd2SShunqing Chen 	u32 min;
66d19b8cd2SShunqing Chen 	u32 max;
67d19b8cd2SShunqing Chen 	u32 step;
68d19b8cd2SShunqing Chen };
69d19b8cd2SShunqing Chen 
bq25700_read(struct bq25700 * charger,uint reg)70d19b8cd2SShunqing Chen static int bq25700_read(struct bq25700 *charger, uint reg)
71d19b8cd2SShunqing Chen {
72d19b8cd2SShunqing Chen 	u16 val;
73d19b8cd2SShunqing Chen 	int ret;
74d19b8cd2SShunqing Chen 
75d19b8cd2SShunqing Chen 	ret = dm_i2c_read(charger->dev, reg, (u8 *)&val, 2);
76d19b8cd2SShunqing Chen 	if (ret) {
77d19b8cd2SShunqing Chen 		debug("write error to device: %p register: %#x!",
78d19b8cd2SShunqing Chen 		      charger->dev, reg);
79d19b8cd2SShunqing Chen 		return ret;
80d19b8cd2SShunqing Chen 	}
81d19b8cd2SShunqing Chen 
82d19b8cd2SShunqing Chen 	return val;
83d19b8cd2SShunqing Chen }
84d19b8cd2SShunqing Chen 
bq25700_write(struct bq25700 * charger,uint reg,u16 val)85d19b8cd2SShunqing Chen static int bq25700_write(struct bq25700 *charger, uint reg, u16 val)
86d19b8cd2SShunqing Chen {
87d19b8cd2SShunqing Chen 	int ret;
88d19b8cd2SShunqing Chen 
89d19b8cd2SShunqing Chen 	ret = dm_i2c_write(charger->dev, reg, (u8 *)&val, 2);
90d19b8cd2SShunqing Chen 	if (ret) {
91d19b8cd2SShunqing Chen 		debug("write error to device: %p register: %#x!",
92d19b8cd2SShunqing Chen 		      charger->dev, reg);
93d19b8cd2SShunqing Chen 		return ret;
94d19b8cd2SShunqing Chen 	}
95d19b8cd2SShunqing Chen 
96d19b8cd2SShunqing Chen 	return 0;
97d19b8cd2SShunqing Chen }
98d19b8cd2SShunqing Chen 
99d19b8cd2SShunqing Chen static const union {
100d19b8cd2SShunqing Chen 	struct bq25700_range  rt;
101d19b8cd2SShunqing Chen } bq25700_tables[] = {
102d19b8cd2SShunqing Chen 	/* range tables */
103d19b8cd2SShunqing Chen 	[TBL_ICHG] = { .rt = {0, 8128000, 64000} },
104d19b8cd2SShunqing Chen 	/* uV */
105d19b8cd2SShunqing Chen 	[TBL_CHGMAX] = { .rt = {0, 19200000, 16000} },
106d19b8cd2SShunqing Chen 	/* uV  max charge voltage*/
107d19b8cd2SShunqing Chen 	[TBL_INPUTVOL] = { .rt = {3200000, 19520000, 64000} },
108d19b8cd2SShunqing Chen 	/* uV  input charge voltage*/
109d19b8cd2SShunqing Chen 	[TBL_INPUTCUR] = {.rt = {0, 6350000, 50000} },
110d19b8cd2SShunqing Chen 	/*uA input current*/
111d19b8cd2SShunqing Chen 	[TBL_SYSVMIN] = { .rt = {1024000, 16182000, 256000} },
112d19b8cd2SShunqing Chen 	/* uV min system voltage*/
113d19b8cd2SShunqing Chen 	[TBL_OTGVOL] = {.rt = {4480000, 20800000, 64000} },
114d19b8cd2SShunqing Chen 	/*uV OTG volage*/
115d19b8cd2SShunqing Chen 	[TBL_OTGCUR] = {.rt = {0, 6350000, 50000} },
116d19b8cd2SShunqing Chen };
117d19b8cd2SShunqing Chen 
bq25700_find_idx(u32 value,enum bq25700_table_ids id)118d19b8cd2SShunqing Chen static u32 bq25700_find_idx(u32 value, enum bq25700_table_ids id)
119d19b8cd2SShunqing Chen {
120d19b8cd2SShunqing Chen 	const struct bq25700_range *rtbl = &bq25700_tables[id].rt;
121d19b8cd2SShunqing Chen 	u32 rtbl_size;
122d19b8cd2SShunqing Chen 	u32 idx;
123d19b8cd2SShunqing Chen 
124d19b8cd2SShunqing Chen 	rtbl_size = (rtbl->max - rtbl->min) / rtbl->step + 1;
125d19b8cd2SShunqing Chen 
126d19b8cd2SShunqing Chen 	for (idx = 1;
127d19b8cd2SShunqing Chen 	     idx < rtbl_size && (idx * rtbl->step + rtbl->min <= value);
128d19b8cd2SShunqing Chen 	     idx++)
129d19b8cd2SShunqing Chen 		;
130d19b8cd2SShunqing Chen 
131d19b8cd2SShunqing Chen 	return idx - 1;
132d19b8cd2SShunqing Chen }
133d19b8cd2SShunqing Chen 
bq25700_charger_status(struct bq25700 * charger)134d19b8cd2SShunqing Chen static bool bq25700_charger_status(struct bq25700 *charger)
135d19b8cd2SShunqing Chen {
136d19b8cd2SShunqing Chen 	int state_of_charger;
137d19b8cd2SShunqing Chen 	u16 value;
138d19b8cd2SShunqing Chen 
139d19b8cd2SShunqing Chen 	value = bq25700_read(charger, BQ25700_CHARGERSTAUS_REG);
140d19b8cd2SShunqing Chen 	state_of_charger = value >> 15;
141d19b8cd2SShunqing Chen 
142d19b8cd2SShunqing Chen 	return state_of_charger;
143d19b8cd2SShunqing Chen }
144d19b8cd2SShunqing Chen 
bq25703_charger_status(struct bq25700 * charger)145d19b8cd2SShunqing Chen static bool bq25703_charger_status(struct bq25700 *charger)
146d19b8cd2SShunqing Chen {
147d19b8cd2SShunqing Chen 	int state_of_charger;
148d19b8cd2SShunqing Chen 	u16 value;
149d19b8cd2SShunqing Chen 
150d19b8cd2SShunqing Chen 	value = bq25700_read(charger, BQ25703_CHARGERSTAUS_REG);
151d19b8cd2SShunqing Chen 	state_of_charger = value >> 15;
152d19b8cd2SShunqing Chen 
153d19b8cd2SShunqing Chen 	return state_of_charger;
154d19b8cd2SShunqing Chen }
155d19b8cd2SShunqing Chen 
bq257xx_charger_status(struct udevice * dev)156d19b8cd2SShunqing Chen static bool bq257xx_charger_status(struct udevice *dev)
157d19b8cd2SShunqing Chen {
158d19b8cd2SShunqing Chen 	struct bq25700 *charger = dev_get_priv(dev);
159d19b8cd2SShunqing Chen 
160d19b8cd2SShunqing Chen 	if (charger->chip_id == BQ25700_ID)
161d19b8cd2SShunqing Chen 		return bq25700_charger_status(charger);
162d19b8cd2SShunqing Chen 	else
163d19b8cd2SShunqing Chen 		return bq25703_charger_status(charger);
164d19b8cd2SShunqing Chen }
165d19b8cd2SShunqing Chen 
bq25700_charger_capability(struct udevice * dev)166d19b8cd2SShunqing Chen static int bq25700_charger_capability(struct udevice *dev)
167d19b8cd2SShunqing Chen {
168d19b8cd2SShunqing Chen 	return FG_CAP_CHARGER;
169d19b8cd2SShunqing Chen }
170d19b8cd2SShunqing Chen 
bq25700_get_usb_type(void)171d19b8cd2SShunqing Chen static int bq25700_get_usb_type(void)
172d19b8cd2SShunqing Chen {
173d19b8cd2SShunqing Chen #ifdef CONFIG_PHY_ROCKCHIP_INNO_USB2
174d19b8cd2SShunqing Chen 	return rockchip_chg_get_type();
175d19b8cd2SShunqing Chen #else
176d19b8cd2SShunqing Chen 	return 0;
177d19b8cd2SShunqing Chen #endif
178d19b8cd2SShunqing Chen }
179d19b8cd2SShunqing Chen 
bq25700_get_pd_output_val(struct bq25700 * charger,int * vol,int * cur)180947a1b47SShunqing Chen static int bq25700_get_pd_output_val(struct bq25700 *charger,
181947a1b47SShunqing Chen 				     int *vol, int *cur)
182947a1b47SShunqing Chen {
183947a1b47SShunqing Chen 	struct power_delivery_data pd_data;
184*5035821eSChen Shunqing 	int ret;
185947a1b47SShunqing Chen 
186947a1b47SShunqing Chen 	if (!charger->pd)
187*5035821eSChen Shunqing 		return -EINVAL;
188947a1b47SShunqing Chen 
189947a1b47SShunqing Chen 	memset(&pd_data, 0, sizeof(pd_data));
190*5035821eSChen Shunqing 	ret = power_delivery_get_data(charger->pd, &pd_data);
191*5035821eSChen Shunqing 	if (ret)
192*5035821eSChen Shunqing 		return ret;
193947a1b47SShunqing Chen 	if (!pd_data.online || !pd_data.voltage || !pd_data.current)
194*5035821eSChen Shunqing 		return -EINVAL;
195947a1b47SShunqing Chen 
196947a1b47SShunqing Chen 	*vol = pd_data.voltage;
197947a1b47SShunqing Chen 	*cur = pd_data.current;
198947a1b47SShunqing Chen 
199947a1b47SShunqing Chen 	return 0;
200947a1b47SShunqing Chen }
201947a1b47SShunqing Chen 
bq25700_charger_current_init(struct bq25700 * charger)202d19b8cd2SShunqing Chen static void bq25700_charger_current_init(struct bq25700 *charger)
203d19b8cd2SShunqing Chen {
204d19b8cd2SShunqing Chen 	u16 charge_current = BQ25700_CHARGE_CURRENT_1500MA;
205d19b8cd2SShunqing Chen 	u16 sdp_inputcurrent = BQ25700_SDP_INPUT_CURRENT_500MA;
206d19b8cd2SShunqing Chen 	u16 dcp_inputcurrent = BQ25700_DCP_INPUT_CURRENT_1500MA;
207947a1b47SShunqing Chen 	int pd_inputvol, pd_inputcurrent;
208947a1b47SShunqing Chen 	u16 vol_idx = 0, cur_idx;
209d19b8cd2SShunqing Chen 	u16 temp;
210d19b8cd2SShunqing Chen 
211d19b8cd2SShunqing Chen 	temp = bq25700_read(charger, BQ25700_CHARGEOPTION0_REG);
212d19b8cd2SShunqing Chen 	temp &= (~WATCHDOG_ENSABLE);
213d19b8cd2SShunqing Chen 	bq25700_write(charger, BQ25700_CHARGEOPTION0_REG, temp);
214d19b8cd2SShunqing Chen 
215947a1b47SShunqing Chen 	if (!bq25700_get_pd_output_val(charger, &pd_inputvol,
216947a1b47SShunqing Chen 				       &pd_inputcurrent)) {
217947a1b47SShunqing Chen 		printf("%s pd charge input vol:%duv current:%dua\n",
218d19b8cd2SShunqing Chen 		       __func__, pd_inputvol, pd_inputcurrent);
219947a1b47SShunqing Chen 		if (pd_inputvol > 5000000) {
220947a1b47SShunqing Chen 			vol_idx = bq25700_find_idx((pd_inputvol - 1280000 - 3200000),
221d19b8cd2SShunqing Chen 						   TBL_INPUTVOL);
222947a1b47SShunqing Chen 			vol_idx = vol_idx << 6;
223947a1b47SShunqing Chen 		}
224947a1b47SShunqing Chen 		cur_idx = bq25700_find_idx(pd_inputcurrent,
225d19b8cd2SShunqing Chen 					   TBL_INPUTCUR);
226d19b8cd2SShunqing Chen 		cur_idx  = cur_idx << 8;
227d19b8cd2SShunqing Chen 		if (pd_inputcurrent != 0) {
228d19b8cd2SShunqing Chen 			bq25700_write(charger, BQ25700_INPUTCURREN_REG,
229d19b8cd2SShunqing Chen 				      cur_idx);
230947a1b47SShunqing Chen 			if (vol_idx)
231d19b8cd2SShunqing Chen 				bq25700_write(charger, BQ25700_INPUTVOLTAGE_REG,
232d19b8cd2SShunqing Chen 					      vol_idx);
233947a1b47SShunqing Chen 			charge_current = bq25700_find_idx(charger->ichg,
234d19b8cd2SShunqing Chen 							  TBL_ICHG);
235d19b8cd2SShunqing Chen 			charge_current = charge_current << 8;
236d19b8cd2SShunqing Chen 		}
237947a1b47SShunqing Chen 	} else {
238d19b8cd2SShunqing Chen 		if (bq25700_get_usb_type() > 1)
239d19b8cd2SShunqing Chen 			bq25700_write(charger, BQ25700_INPUTCURREN_REG,
240d19b8cd2SShunqing Chen 				      dcp_inputcurrent);
241d19b8cd2SShunqing Chen 		else
242d19b8cd2SShunqing Chen 			bq25700_write(charger, BQ25700_INPUTCURREN_REG,
243d19b8cd2SShunqing Chen 				      sdp_inputcurrent);
244d19b8cd2SShunqing Chen 	}
245d19b8cd2SShunqing Chen 
246d19b8cd2SShunqing Chen 	if (bq25700_charger_status(charger))
247d19b8cd2SShunqing Chen 		bq25700_write(charger, BQ25700_CHARGECURREN_REG,
248d19b8cd2SShunqing Chen 			      charge_current);
249d19b8cd2SShunqing Chen }
250d19b8cd2SShunqing Chen 
bq25703_charger_current_init(struct bq25700 * charger)251d19b8cd2SShunqing Chen static void bq25703_charger_current_init(struct bq25700 *charger)
252d19b8cd2SShunqing Chen {
253d19b8cd2SShunqing Chen 	u16 charge_current = BQ25700_CHARGE_CURRENT_1500MA;
254d19b8cd2SShunqing Chen 	u16 sdp_inputcurrent = BQ25700_SDP_INPUT_CURRENT_500MA;
255d19b8cd2SShunqing Chen 	u16 dcp_inputcurrent = BQ25700_DCP_INPUT_CURRENT_1500MA;
256947a1b47SShunqing Chen 	int pd_inputvol,  pd_inputcurrent;
257947a1b47SShunqing Chen 	u16 vol_idx = 0, cur_idx;
258d19b8cd2SShunqing Chen 	u16 temp;
259d19b8cd2SShunqing Chen 
260d19b8cd2SShunqing Chen 	temp = bq25700_read(charger, BQ25703_CHARGEOPTION0_REG);
261d19b8cd2SShunqing Chen 	temp &= (~WATCHDOG_ENSABLE);
262d19b8cd2SShunqing Chen 	bq25700_write(charger, BQ25703_CHARGEOPTION0_REG, temp);
263d19b8cd2SShunqing Chen 
264947a1b47SShunqing Chen 	if (!bq25700_get_pd_output_val(charger, &pd_inputvol,
265947a1b47SShunqing Chen 				       &pd_inputcurrent)) {
266947a1b47SShunqing Chen 		printf("%s pd charge input vol:%duv current:%dua\n",
267d19b8cd2SShunqing Chen 		       __func__, pd_inputvol, pd_inputcurrent);
268947a1b47SShunqing Chen 		if (pd_inputvol > 5000000) {
269947a1b47SShunqing Chen 			vol_idx = bq25700_find_idx(pd_inputvol - 1280000 - 3200000,
270d19b8cd2SShunqing Chen 						   TBL_INPUTVOL);
271947a1b47SShunqing Chen 			vol_idx = vol_idx << 6;
272947a1b47SShunqing Chen 		}
273947a1b47SShunqing Chen 		cur_idx = bq25700_find_idx(pd_inputcurrent,
274d19b8cd2SShunqing Chen 					   TBL_INPUTCUR);
275d19b8cd2SShunqing Chen 		cur_idx  = cur_idx << 8;
276d19b8cd2SShunqing Chen 		if (pd_inputcurrent != 0) {
277d19b8cd2SShunqing Chen 			bq25700_write(charger, BQ25703_INPUTCURREN_REG,
278d19b8cd2SShunqing Chen 				      cur_idx);
279947a1b47SShunqing Chen 			if (vol_idx)
280d19b8cd2SShunqing Chen 				bq25700_write(charger, BQ25703_INPUTVOLTAGE_REG,
281d19b8cd2SShunqing Chen 					      vol_idx);
282947a1b47SShunqing Chen 			charge_current = bq25700_find_idx(charger->ichg,
283d19b8cd2SShunqing Chen 							  TBL_ICHG);
284d19b8cd2SShunqing Chen 			charge_current = charge_current << 8;
285d19b8cd2SShunqing Chen 		}
286947a1b47SShunqing Chen 	} else {
287d19b8cd2SShunqing Chen 		if (bq25700_get_usb_type() > 1)
288d19b8cd2SShunqing Chen 			bq25700_write(charger, BQ25703_INPUTCURREN_REG,
289d19b8cd2SShunqing Chen 				      dcp_inputcurrent);
290d19b8cd2SShunqing Chen 		else
291d19b8cd2SShunqing Chen 			bq25700_write(charger, BQ25703_INPUTCURREN_REG,
292d19b8cd2SShunqing Chen 				      sdp_inputcurrent);
293d19b8cd2SShunqing Chen 	}
294d19b8cd2SShunqing Chen 
295d19b8cd2SShunqing Chen 	if (bq25703_charger_status(charger))
296d19b8cd2SShunqing Chen 		bq25700_write(charger, BQ25703_CHARGECURREN_REG,
297d19b8cd2SShunqing Chen 			      charge_current);
298d19b8cd2SShunqing Chen }
299d19b8cd2SShunqing Chen 
bq25700_ofdata_to_platdata(struct udevice * dev)300d19b8cd2SShunqing Chen static int bq25700_ofdata_to_platdata(struct udevice *dev)
301d19b8cd2SShunqing Chen {
302d19b8cd2SShunqing Chen 	struct bq25700 *charger = dev_get_priv(dev);
303d19b8cd2SShunqing Chen 	const void *blob = gd->fdt_blob;
304d19b8cd2SShunqing Chen 	int node, node1;
305d19b8cd2SShunqing Chen 
306d19b8cd2SShunqing Chen 	charger->dev = dev;
307d19b8cd2SShunqing Chen 
308d19b8cd2SShunqing Chen 	node = fdt_node_offset_by_compatible(blob, 0, COMPAT_BQ25700);
309d19b8cd2SShunqing Chen 	node1 = fdt_node_offset_by_compatible(blob, 0, COMPAT_BQ25703);
310d19b8cd2SShunqing Chen 	if ((node < 0) && (node1 < 0)) {
311d19b8cd2SShunqing Chen 		printf("Can't find dts node for charger bq25700\n");
312d19b8cd2SShunqing Chen 		return -ENODEV;
313d19b8cd2SShunqing Chen 	}
314d19b8cd2SShunqing Chen 
315d19b8cd2SShunqing Chen 	if (node < 0) {
316d19b8cd2SShunqing Chen 		node = node1;
317d19b8cd2SShunqing Chen 		charger->chip_id = BQ25703_ID;
318d19b8cd2SShunqing Chen 	} else {
319d19b8cd2SShunqing Chen 		charger->chip_id = BQ25700_ID;
320d19b8cd2SShunqing Chen 	}
321d19b8cd2SShunqing Chen 
322d19b8cd2SShunqing Chen 	charger->ichg = fdtdec_get_int(blob, node, "ti,charge-current", 0);
323d19b8cd2SShunqing Chen 
324d19b8cd2SShunqing Chen 	return 0;
325d19b8cd2SShunqing Chen }
326d19b8cd2SShunqing Chen 
bq25700_probe(struct udevice * dev)327d19b8cd2SShunqing Chen static int bq25700_probe(struct udevice *dev)
328d19b8cd2SShunqing Chen {
329d19b8cd2SShunqing Chen 	struct bq25700 *charger = dev_get_priv(dev);
330947a1b47SShunqing Chen 	int ret;
331947a1b47SShunqing Chen 
332947a1b47SShunqing Chen 	ret = uclass_get_device(UCLASS_PD, 0, &charger->pd);
333947a1b47SShunqing Chen 	if (ret) {
334947a1b47SShunqing Chen 		if (ret == -ENODEV)
335947a1b47SShunqing Chen 			printf("Can't find PMIC\n");
336947a1b47SShunqing Chen 		else
337947a1b47SShunqing Chen 			printf("Get UCLASS PMIC failed: %d\n", ret);
338947a1b47SShunqing Chen 
339947a1b47SShunqing Chen 		charger->pd = NULL;
340947a1b47SShunqing Chen 	}
341d19b8cd2SShunqing Chen 
342d19b8cd2SShunqing Chen 	if (charger->chip_id == BQ25700_ID)
343d19b8cd2SShunqing Chen 		bq25700_charger_current_init(charger);
344d19b8cd2SShunqing Chen 	else
345d19b8cd2SShunqing Chen 		bq25703_charger_current_init(charger);
346d19b8cd2SShunqing Chen 
347d19b8cd2SShunqing Chen 	return 0;
348d19b8cd2SShunqing Chen }
349d19b8cd2SShunqing Chen 
350d19b8cd2SShunqing Chen static const struct udevice_id charger_ids[] = {
351d19b8cd2SShunqing Chen 	{ .compatible = "ti,bq25700" },
352d19b8cd2SShunqing Chen 	{ .compatible = "ti,bq25703" },
353d19b8cd2SShunqing Chen 	{ },
354d19b8cd2SShunqing Chen };
355d19b8cd2SShunqing Chen 
356d19b8cd2SShunqing Chen static struct dm_fuel_gauge_ops charger_ops = {
357d19b8cd2SShunqing Chen 	.get_chrg_online = bq257xx_charger_status,
358d19b8cd2SShunqing Chen 	.capability = bq25700_charger_capability,
359d19b8cd2SShunqing Chen };
360d19b8cd2SShunqing Chen 
361d19b8cd2SShunqing Chen U_BOOT_DRIVER(bq25700_charger) = {
362d19b8cd2SShunqing Chen 	.name = "bq25700_charger",
363d19b8cd2SShunqing Chen 	.id = UCLASS_FG,
364d19b8cd2SShunqing Chen 	.probe = bq25700_probe,
365d19b8cd2SShunqing Chen 	.of_match = charger_ids,
366d19b8cd2SShunqing Chen 	.ops = &charger_ops,
367d19b8cd2SShunqing Chen 	.ofdata_to_platdata = bq25700_ofdata_to_platdata,
368d19b8cd2SShunqing Chen 	.priv_auto_alloc_size = sizeof(struct bq25700),
369d19b8cd2SShunqing Chen };
370