xref: /OK3568_Linux_fs/kernel/drivers/power/supply/bq25700_charger.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * TI BQ257000 charger driver
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun  * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Author: shengfeixu <xsf@rock-chips.com>
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/power/bq25700-charge.h>
11*4882a593Smuzhiyun #include <linux/i2c.h>
12*4882a593Smuzhiyun #include <linux/interrupt.h>
13*4882a593Smuzhiyun #include <linux/irq.h>
14*4882a593Smuzhiyun #include <linux/mfd/core.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/regmap.h>
17*4882a593Smuzhiyun #include <linux/regulator/driver.h>
18*4882a593Smuzhiyun #include <linux/of_device.h>
19*4882a593Smuzhiyun #include <linux/delay.h>
20*4882a593Smuzhiyun #include <linux/usb/phy.h>
21*4882a593Smuzhiyun #include <linux/power/rk_usbbc.h>
22*4882a593Smuzhiyun #include <linux/extcon.h>
23*4882a593Smuzhiyun #include <linux/delay.h>
24*4882a593Smuzhiyun #include <linux/power_supply.h>
25*4882a593Smuzhiyun #include <linux/gpio.h>
26*4882a593Smuzhiyun #include <linux/of_gpio.h>
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun static int dbg_enable;
29*4882a593Smuzhiyun module_param_named(dbg_level, dbg_enable, int, 0644);
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define DBG(args...) \
32*4882a593Smuzhiyun 	do { \
33*4882a593Smuzhiyun 		if (dbg_enable) { \
34*4882a593Smuzhiyun 			pr_info(args); \
35*4882a593Smuzhiyun 		} \
36*4882a593Smuzhiyun 	} while (0)
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #define bq25700_info(fmt, args...) pr_info("bq25700: "fmt, ##args)
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #define BQ25700_MANUFACTURER		"Texas Instruments"
41*4882a593Smuzhiyun #define BQ25700_ID			0x59
42*4882a593Smuzhiyun #define BQ25703_ID			0x58
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #define DEFAULT_INPUTVOL		((5000 - 1280) * 1000)
45*4882a593Smuzhiyun #define MAX_INPUTVOLTAGE		24000000
46*4882a593Smuzhiyun #define MAX_INPUTCURRENT		6350000
47*4882a593Smuzhiyun #define MAX_CHARGEVOLTAGE		16800000
48*4882a593Smuzhiyun #define MAX_CHARGECURRETNT		8128000
49*4882a593Smuzhiyun #define MAX_OTGVOLTAGE			20800000
50*4882a593Smuzhiyun #define MIN_OTGVOLTAGE			4280000
51*4882a593Smuzhiyun #define MAX_OTGCURRENT			6350000
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun enum bq25700_fields {
54*4882a593Smuzhiyun 	EN_LWPWR, WDTWR_ADJ, IDPM_AUTO_DISABLE,
55*4882a593Smuzhiyun 	EN_OOA, PWM_FREQ, EN_LEARN, IADP_GAIN, IBAT_GAIN,
56*4882a593Smuzhiyun 	EN_LDO, EN_IDPM, CHRG_INHIBIT,/*reg12h*/
57*4882a593Smuzhiyun 	CHARGE_CURRENT,/*reg14h*/
58*4882a593Smuzhiyun 	MAX_CHARGE_VOLTAGE,/*reg15h*/
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	AC_STAT, ICO_DONE, IN_VINDPM, IN_IINDPM, IN_FCHRG, IN_PCHRG, IN_OTG,
61*4882a593Smuzhiyun 	F_ACOV, F_BATOC, F_ACOC, SYSOVP_STAT, F_LATCHOFF, F_OTG_OVP, F_OTG_OCP,
62*4882a593Smuzhiyun 	/*reg20h*/
63*4882a593Smuzhiyun 	STAT_COMP, STAT_ICRIT, STAT_INOM, STAT_IDCHG, STAT_VSYS, STAT_BAT_REMOV,
64*4882a593Smuzhiyun 	STAT_ADP_REMOV,/*reg21h*/
65*4882a593Smuzhiyun 	INPUT_CURRENT_DPM,/*reg22h*/
66*4882a593Smuzhiyun 	OUTPUT_INPUT_VOL, OUTPUT_SYS_POWER,/*reg23h*/
67*4882a593Smuzhiyun 	OUTPUT_DSG_CUR,	OUTPUT_CHG_CUR,/*reg24h*/
68*4882a593Smuzhiyun 	OUTPUT_INPUT_CUR, OUTPUT_CMPIN_VOL,/*reg25h*/
69*4882a593Smuzhiyun 	OUTPUT_SYS_VOL, OUTPUT_BAT_VOL,/*reg26h*/
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	EN_IBAT, EN_PROCHOT_LPWR, EN_PSYS, RSNS_RAC, RSNS_RSR,
72*4882a593Smuzhiyun 	PSYS_RATIO, CMP_REF,	CMP_POL, CMP_DEG, FORCE_LATCHOFF,
73*4882a593Smuzhiyun 	EN_SHIP_DCHG, AUTO_WAKEUP_EN, /*reg30h*/
74*4882a593Smuzhiyun 	PKPWR_TOVLD_REG, EN_PKPWR_IDPM, EN_PKPWR_VSYS, PKPWER_OVLD_STAT,
75*4882a593Smuzhiyun 	PKPWR_RELAX_STAT, PKPWER_TMAX,	EN_EXTILIM, EN_ICHG_IDCHG, Q2_OCP,
76*4882a593Smuzhiyun 	ACX_OCP, EN_ACOC, ACOC_VTH, EN_BATOC, BATCOC_VTH,/*reg31h*/
77*4882a593Smuzhiyun 	EN_HIZ, RESET_REG, RESET_VINDPM, EN_OTG, EN_ICO_MODE, BATFETOFF_HIZ,
78*4882a593Smuzhiyun 	PSYS_OTG_IDCHG,/*reg32h*/
79*4882a593Smuzhiyun 	ILIM2_VTH, ICRIT_DEG, VSYS_VTH, EN_PROCHOT_EXT, PROCHOT_WIDTH,
80*4882a593Smuzhiyun 	PROCHOT_CLEAR, INOM_DEG,/*reg33h*/
81*4882a593Smuzhiyun 	IDCHG_VTH, IDCHG_DEG, PROCHOT_PROFILE_COMP, PROCHOT_PROFILE_ICRIT,
82*4882a593Smuzhiyun 	PROCHOT_PROFILE_INOM, PROCHOT_PROFILE_IDCHG,
83*4882a593Smuzhiyun 	PROCHOT_PROFILE_VSYS, PROCHOT_PROFILE_BATPRES, PROCHOT_PROFILE_ACOK,
84*4882a593Smuzhiyun 	/*reg34h*/
85*4882a593Smuzhiyun 	ADC_CONV, ADC_START, ADC_FULLSCALE, EN_ADC_CMPIN, EN_ADC_VBUS,
86*4882a593Smuzhiyun 	EN_ADC_PSYS, EN_ADC_IIN, EN_ADC_IDCHG, EN_ADC_ICHG, EN_ADC_VSYS,
87*4882a593Smuzhiyun 	EN_ADC_VBAT,/*reg35h*/
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	OTG_VOLTAGE,/*reg3bh*/
90*4882a593Smuzhiyun 	OTG_CURRENT,/*reg3ch*/
91*4882a593Smuzhiyun 	INPUT_VOLTAGE,/*reg3dh*/
92*4882a593Smuzhiyun 	MIN_SYS_VOTAGE,/*reg3eh*/
93*4882a593Smuzhiyun 	INPUT_CURRENT,/*reg3fh*/
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	MANUFACTURE_ID,/*regfeh*/
96*4882a593Smuzhiyun 	DEVICE_ID,/*regffh*/
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	F_MAX_FIELDS
99*4882a593Smuzhiyun };
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun enum charger_t {
102*4882a593Smuzhiyun 	USB_TYPE_UNKNOWN_CHARGER,
103*4882a593Smuzhiyun 	USB_TYPE_NONE_CHARGER,
104*4882a593Smuzhiyun 	USB_TYPE_USB_CHARGER,
105*4882a593Smuzhiyun 	USB_TYPE_AC_CHARGER,
106*4882a593Smuzhiyun 	USB_TYPE_CDP_CHARGER,
107*4882a593Smuzhiyun 	DC_TYPE_DC_CHARGER,
108*4882a593Smuzhiyun 	DC_TYPE_NONE_CHARGER,
109*4882a593Smuzhiyun };
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun enum usb_status_t {
112*4882a593Smuzhiyun 	USB_STATUS_NONE,
113*4882a593Smuzhiyun 	USB_STATUS_USB,
114*4882a593Smuzhiyun 	USB_STATUS_AC,
115*4882a593Smuzhiyun 	USB_STATUS_PD,
116*4882a593Smuzhiyun 	USB_STATUS_OTG,
117*4882a593Smuzhiyun };
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun enum tpyec_port_t {
120*4882a593Smuzhiyun 	USB_TYPEC_0,
121*4882a593Smuzhiyun 	USB_TYPEC_1,
122*4882a593Smuzhiyun };
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun /* initial field values, converted to register values */
125*4882a593Smuzhiyun struct bq25700_init_data {
126*4882a593Smuzhiyun 	u32 ichg;	/* charge current		*/
127*4882a593Smuzhiyun 	u32 max_chg_vol;	/*max charge voltage*/
128*4882a593Smuzhiyun 	u32 input_voltage;	/*input voltage*/
129*4882a593Smuzhiyun 	u32 input_current;	/*input current*/
130*4882a593Smuzhiyun 	u32 input_current_sdp;
131*4882a593Smuzhiyun 	u32 input_current_dcp;
132*4882a593Smuzhiyun 	u32 input_current_cdp;
133*4882a593Smuzhiyun 	u32 sys_min_voltage;	/*mininum system voltage*/
134*4882a593Smuzhiyun 	u32 otg_voltage;	/*OTG voltage*/
135*4882a593Smuzhiyun 	u32 otg_current;	/*OTG current*/
136*4882a593Smuzhiyun };
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun struct bq25700_state {
139*4882a593Smuzhiyun 	u8 ac_stat;
140*4882a593Smuzhiyun 	u8 ico_done;
141*4882a593Smuzhiyun 	u8 in_vindpm;
142*4882a593Smuzhiyun 	u8 in_iindpm;
143*4882a593Smuzhiyun 	u8 in_fchrg;
144*4882a593Smuzhiyun 	u8 in_pchrg;
145*4882a593Smuzhiyun 	u8 in_otg;
146*4882a593Smuzhiyun 	u8 fault_acov;
147*4882a593Smuzhiyun 	u8 fault_batoc;
148*4882a593Smuzhiyun 	u8 fault_acoc;
149*4882a593Smuzhiyun 	u8 sysovp_stat;
150*4882a593Smuzhiyun 	u8 fault_latchoff;
151*4882a593Smuzhiyun 	u8 fault_otg_ovp;
152*4882a593Smuzhiyun 	u8 fault_otg_ocp;
153*4882a593Smuzhiyun };
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun struct bq25700_device {
156*4882a593Smuzhiyun 	struct i2c_client			*client;
157*4882a593Smuzhiyun 	struct device				*dev;
158*4882a593Smuzhiyun 	struct power_supply			*supply_charger;
159*4882a593Smuzhiyun 	char				model_name[I2C_NAME_SIZE];
160*4882a593Smuzhiyun 	unsigned int			irq;
161*4882a593Smuzhiyun 	bool				first_time;
162*4882a593Smuzhiyun 	bool				charger_health_valid;
163*4882a593Smuzhiyun 	bool				battery_health_valid;
164*4882a593Smuzhiyun 	bool				battery_status_valid;
165*4882a593Smuzhiyun 	int				automode;
166*4882a593Smuzhiyun 	struct notifier_block		nb;
167*4882a593Smuzhiyun 	struct bq2570x_platform_data	plat_data;
168*4882a593Smuzhiyun 	struct device_node		*notify_node;
169*4882a593Smuzhiyun 	struct workqueue_struct		*usb_charger_wq;
170*4882a593Smuzhiyun 	struct workqueue_struct		*dc_charger_wq;
171*4882a593Smuzhiyun 	struct workqueue_struct		*finish_sig_wq;
172*4882a593Smuzhiyun 	struct delayed_work		usb_work;
173*4882a593Smuzhiyun 	struct delayed_work		host_work;
174*4882a593Smuzhiyun 	struct delayed_work		discnt_work;
175*4882a593Smuzhiyun 	struct delayed_work		usb_work1;
176*4882a593Smuzhiyun 	struct delayed_work		host_work1;
177*4882a593Smuzhiyun 	struct delayed_work		discnt_work1;
178*4882a593Smuzhiyun 	struct delayed_work		irq_work;
179*4882a593Smuzhiyun 	struct notifier_block		cable_cg_nb;
180*4882a593Smuzhiyun 	struct notifier_block		cable_host_nb;
181*4882a593Smuzhiyun 	struct notifier_block		cable_cg_nb1;
182*4882a593Smuzhiyun 	struct notifier_block		cable_host_nb1;
183*4882a593Smuzhiyun 	struct extcon_dev		*cable_edev;
184*4882a593Smuzhiyun 	struct extcon_dev		*cable_edev_1;
185*4882a593Smuzhiyun 	int				typec0_status;
186*4882a593Smuzhiyun 	int				typec1_status;
187*4882a593Smuzhiyun 	struct gpio_desc		*typec0_enable_io;
188*4882a593Smuzhiyun 	struct gpio_desc		*typec1_enable_io;
189*4882a593Smuzhiyun 	struct gpio_desc		*typec0_discharge_io;
190*4882a593Smuzhiyun 	struct gpio_desc		*typec1_discharge_io;
191*4882a593Smuzhiyun 	struct gpio_desc		*otg_mode_en_io;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	struct regulator_dev		*otg_vbus_reg;
194*4882a593Smuzhiyun 	struct regmap			*regmap;
195*4882a593Smuzhiyun 	struct regmap_field		*rmap_fields[F_MAX_FIELDS];
196*4882a593Smuzhiyun 	int				chip_id;
197*4882a593Smuzhiyun 	struct bq25700_init_data	init_data;
198*4882a593Smuzhiyun 	struct bq25700_state		state;
199*4882a593Smuzhiyun 	int				pd_charge_only;
200*4882a593Smuzhiyun 	unsigned int			bc_event;
201*4882a593Smuzhiyun 	bool				usb_bc;
202*4882a593Smuzhiyun };
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun static const struct reg_field bq25700_reg_fields[] = {
205*4882a593Smuzhiyun 	/*REG12*/
206*4882a593Smuzhiyun 	[EN_LWPWR] = REG_FIELD(0x12, 15, 15),
207*4882a593Smuzhiyun 	[WDTWR_ADJ] = REG_FIELD(0x12, 13, 14),
208*4882a593Smuzhiyun 	[IDPM_AUTO_DISABLE] = REG_FIELD(0x12, 12, 12),
209*4882a593Smuzhiyun 	[EN_OOA] = REG_FIELD(0x12, 10, 10),
210*4882a593Smuzhiyun 	[PWM_FREQ] = REG_FIELD(0x12, 9, 9),
211*4882a593Smuzhiyun 	[EN_LEARN] = REG_FIELD(0x12, 5, 5),
212*4882a593Smuzhiyun 	[IADP_GAIN] = REG_FIELD(0x12, 4, 4),
213*4882a593Smuzhiyun 	[IBAT_GAIN] = REG_FIELD(0x12, 3, 3),
214*4882a593Smuzhiyun 	[EN_LDO] = REG_FIELD(0x12, 2, 2),
215*4882a593Smuzhiyun 	[EN_IDPM] = REG_FIELD(0x12, 1, 1),
216*4882a593Smuzhiyun 	[CHRG_INHIBIT] = REG_FIELD(0x12, 0, 0),
217*4882a593Smuzhiyun 	/*REG0x14*/
218*4882a593Smuzhiyun 	[CHARGE_CURRENT] = REG_FIELD(0x14, 6, 12),
219*4882a593Smuzhiyun 	/*REG0x15*/
220*4882a593Smuzhiyun 	[MAX_CHARGE_VOLTAGE] = REG_FIELD(0x15, 4, 14),
221*4882a593Smuzhiyun 	/*REG20*/
222*4882a593Smuzhiyun 	[AC_STAT] = REG_FIELD(0x20, 15, 15),
223*4882a593Smuzhiyun 	[ICO_DONE] = REG_FIELD(0x20, 14, 14),
224*4882a593Smuzhiyun 	[IN_VINDPM] = REG_FIELD(0x20, 12, 12),
225*4882a593Smuzhiyun 	[IN_IINDPM] = REG_FIELD(0x20, 11, 11),
226*4882a593Smuzhiyun 	[IN_FCHRG] = REG_FIELD(0x20, 10, 10),
227*4882a593Smuzhiyun 	[IN_PCHRG] = REG_FIELD(0x20, 9, 9),
228*4882a593Smuzhiyun 	[IN_OTG] = REG_FIELD(0x20, 8, 8),
229*4882a593Smuzhiyun 	[F_ACOV] = REG_FIELD(0x20, 7, 7),
230*4882a593Smuzhiyun 	[F_BATOC] = REG_FIELD(0x20, 6, 6),
231*4882a593Smuzhiyun 	[F_ACOC] = REG_FIELD(0x20, 5, 5),
232*4882a593Smuzhiyun 	[SYSOVP_STAT] = REG_FIELD(0x20, 4, 4),
233*4882a593Smuzhiyun 	[F_LATCHOFF] = REG_FIELD(0x20, 2, 2),
234*4882a593Smuzhiyun 	[F_OTG_OVP] = REG_FIELD(0x20, 1, 1),
235*4882a593Smuzhiyun 	[F_OTG_OCP] = REG_FIELD(0x20, 0, 0),
236*4882a593Smuzhiyun 	/*REG21*/
237*4882a593Smuzhiyun 	[STAT_COMP] = REG_FIELD(0x21, 6, 6),
238*4882a593Smuzhiyun 	[STAT_ICRIT] = REG_FIELD(0x21, 5, 5),
239*4882a593Smuzhiyun 	[STAT_INOM] = REG_FIELD(0x21, 4, 4),
240*4882a593Smuzhiyun 	[STAT_IDCHG] = REG_FIELD(0x21, 3, 3),
241*4882a593Smuzhiyun 	[STAT_VSYS] = REG_FIELD(0x21, 2, 2),
242*4882a593Smuzhiyun 	[STAT_BAT_REMOV] = REG_FIELD(0x21, 1, 1),
243*4882a593Smuzhiyun 	[STAT_ADP_REMOV] = REG_FIELD(0x21, 0, 0),
244*4882a593Smuzhiyun 	/*REG22*/
245*4882a593Smuzhiyun 	[INPUT_CURRENT_DPM] = REG_FIELD(0x22, 8, 14),
246*4882a593Smuzhiyun 	/*REG23H*/
247*4882a593Smuzhiyun 	[OUTPUT_INPUT_VOL] = REG_FIELD(0x23, 8, 15),
248*4882a593Smuzhiyun 	[OUTPUT_SYS_POWER] = REG_FIELD(0x23, 0, 7),
249*4882a593Smuzhiyun 	/*REG24H*/
250*4882a593Smuzhiyun 	[OUTPUT_DSG_CUR] = REG_FIELD(0x24, 8, 14),
251*4882a593Smuzhiyun 	[OUTPUT_CHG_CUR] = REG_FIELD(0x24, 0, 6),
252*4882a593Smuzhiyun 	/*REG25H*/
253*4882a593Smuzhiyun 	[OUTPUT_INPUT_CUR] = REG_FIELD(0x25, 8, 15),
254*4882a593Smuzhiyun 	[OUTPUT_CMPIN_VOL] = REG_FIELD(0x25, 0, 7),
255*4882a593Smuzhiyun 	/*REG26H*/
256*4882a593Smuzhiyun 	[OUTPUT_SYS_VOL] = REG_FIELD(0x26, 8, 15),
257*4882a593Smuzhiyun 	[OUTPUT_BAT_VOL] = REG_FIELD(0x26, 0, 6),
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	/*REG30*/
260*4882a593Smuzhiyun 	[EN_IBAT] = REG_FIELD(0x30, 15, 15),
261*4882a593Smuzhiyun 	[EN_PROCHOT_LPWR] = REG_FIELD(0x30, 13, 14),
262*4882a593Smuzhiyun 	[EN_PSYS] = REG_FIELD(0x30, 12, 12),
263*4882a593Smuzhiyun 	[RSNS_RAC] = REG_FIELD(0x30, 11, 11),
264*4882a593Smuzhiyun 	[RSNS_RSR] = REG_FIELD(0x30, 10, 10),
265*4882a593Smuzhiyun 	[PSYS_RATIO] = REG_FIELD(0x30, 9, 9),
266*4882a593Smuzhiyun 	[CMP_REF] = REG_FIELD(0x30, 7, 7),
267*4882a593Smuzhiyun 	[CMP_POL] = REG_FIELD(0x30, 6, 6),
268*4882a593Smuzhiyun 	[CMP_DEG] = REG_FIELD(0x30, 4, 5),
269*4882a593Smuzhiyun 	[FORCE_LATCHOFF] = REG_FIELD(0x30, 3, 3),
270*4882a593Smuzhiyun 	[EN_SHIP_DCHG] = REG_FIELD(0x30, 1, 1),
271*4882a593Smuzhiyun 	[AUTO_WAKEUP_EN] = REG_FIELD(0x30, 0, 0),
272*4882a593Smuzhiyun 	/*REG31*/
273*4882a593Smuzhiyun 	[PKPWR_TOVLD_REG] = REG_FIELD(0x31, 14, 15),
274*4882a593Smuzhiyun 	[EN_PKPWR_IDPM] = REG_FIELD(0x31, 13, 13),
275*4882a593Smuzhiyun 	[EN_PKPWR_VSYS] = REG_FIELD(0x31, 12, 12),
276*4882a593Smuzhiyun 	[PKPWER_OVLD_STAT] = REG_FIELD(0x31, 11, 11),
277*4882a593Smuzhiyun 	[PKPWR_RELAX_STAT] = REG_FIELD(0x31, 10, 10),
278*4882a593Smuzhiyun 	[PKPWER_TMAX] = REG_FIELD(0x31, 8, 9),
279*4882a593Smuzhiyun 	[EN_EXTILIM] = REG_FIELD(0x31, 7, 7),
280*4882a593Smuzhiyun 	[EN_ICHG_IDCHG] = REG_FIELD(0x31, 6, 6),
281*4882a593Smuzhiyun 	[Q2_OCP] = REG_FIELD(0x31, 5, 5),
282*4882a593Smuzhiyun 	[ACX_OCP] = REG_FIELD(0x31, 4, 4),
283*4882a593Smuzhiyun 	[EN_ACOC] = REG_FIELD(0x31, 3, 3),
284*4882a593Smuzhiyun 	[ACOC_VTH] = REG_FIELD(0x31, 2, 2),
285*4882a593Smuzhiyun 	[EN_BATOC] = REG_FIELD(0x31, 1, 1),
286*4882a593Smuzhiyun 	[BATCOC_VTH] = REG_FIELD(0x31, 0, 0),
287*4882a593Smuzhiyun 	/*REG32*/
288*4882a593Smuzhiyun 	[EN_HIZ] = REG_FIELD(0x32, 15, 15),
289*4882a593Smuzhiyun 	[RESET_REG] = REG_FIELD(0x32, 14, 14),
290*4882a593Smuzhiyun 	[RESET_VINDPM] = REG_FIELD(0x32, 13, 13),
291*4882a593Smuzhiyun 	[EN_OTG] = REG_FIELD(0x32, 12, 12),
292*4882a593Smuzhiyun 	[EN_ICO_MODE] = REG_FIELD(0x32, 11, 11),
293*4882a593Smuzhiyun 	[BATFETOFF_HIZ] = REG_FIELD(0x32, 1, 1),
294*4882a593Smuzhiyun 	[PSYS_OTG_IDCHG] = REG_FIELD(0x32, 0, 0),
295*4882a593Smuzhiyun 	/*REG33*/
296*4882a593Smuzhiyun 	[ILIM2_VTH] = REG_FIELD(0x33, 11, 15),
297*4882a593Smuzhiyun 	[ICRIT_DEG] = REG_FIELD(0x33, 9, 10),
298*4882a593Smuzhiyun 	[VSYS_VTH] = REG_FIELD(0x33, 6, 7),
299*4882a593Smuzhiyun 	[EN_PROCHOT_EXT] = REG_FIELD(0x33, 5, 5),
300*4882a593Smuzhiyun 	[PROCHOT_WIDTH] = REG_FIELD(0x33, 3, 4),
301*4882a593Smuzhiyun 	[PROCHOT_CLEAR] = REG_FIELD(0x33, 2, 2),
302*4882a593Smuzhiyun 	[INOM_DEG] = REG_FIELD(0x33, 1, 1),
303*4882a593Smuzhiyun 	/*REG34*/
304*4882a593Smuzhiyun 	[IDCHG_VTH] = REG_FIELD(0x34, 10, 15),
305*4882a593Smuzhiyun 	[IDCHG_DEG] = REG_FIELD(0x34, 8, 9),
306*4882a593Smuzhiyun 	[PROCHOT_PROFILE_COMP] = REG_FIELD(0x34, 6, 6),
307*4882a593Smuzhiyun 	[PROCHOT_PROFILE_ICRIT] = REG_FIELD(0x34, 5, 5),
308*4882a593Smuzhiyun 	[PROCHOT_PROFILE_INOM] = REG_FIELD(0x34, 4, 4),
309*4882a593Smuzhiyun 	[PROCHOT_PROFILE_IDCHG] = REG_FIELD(0x34, 3, 3),
310*4882a593Smuzhiyun 	[PROCHOT_PROFILE_VSYS] = REG_FIELD(0x34, 2, 2),
311*4882a593Smuzhiyun 	[PROCHOT_PROFILE_BATPRES] = REG_FIELD(0x34, 1, 1),
312*4882a593Smuzhiyun 	[PROCHOT_PROFILE_ACOK] = REG_FIELD(0x34, 0, 0),
313*4882a593Smuzhiyun 	/*REG35*/
314*4882a593Smuzhiyun 	[ADC_CONV] = REG_FIELD(0x35, 15, 15),
315*4882a593Smuzhiyun 	[ADC_START] = REG_FIELD(0x35, 14, 14),
316*4882a593Smuzhiyun 	[ADC_FULLSCALE] = REG_FIELD(0x35, 13, 13),
317*4882a593Smuzhiyun 	[EN_ADC_CMPIN] = REG_FIELD(0x35, 7, 7),
318*4882a593Smuzhiyun 	[EN_ADC_VBUS] = REG_FIELD(0x35, 6, 6),
319*4882a593Smuzhiyun 	[EN_ADC_PSYS] = REG_FIELD(0x35, 5, 5),
320*4882a593Smuzhiyun 	[EN_ADC_IIN] = REG_FIELD(0x35, 4, 4),
321*4882a593Smuzhiyun 	[EN_ADC_IDCHG] = REG_FIELD(0x35, 3, 3),
322*4882a593Smuzhiyun 	[EN_ADC_ICHG] = REG_FIELD(0x35, 2, 2),
323*4882a593Smuzhiyun 	[EN_ADC_VSYS] = REG_FIELD(0x35, 1, 1),
324*4882a593Smuzhiyun 	[EN_ADC_VBAT] = REG_FIELD(0x35, 0, 0),
325*4882a593Smuzhiyun 	/*REG3B*/
326*4882a593Smuzhiyun 	[OTG_VOLTAGE] = REG_FIELD(0x3B, 6, 13),
327*4882a593Smuzhiyun 	/*REG3C*/
328*4882a593Smuzhiyun 	[OTG_CURRENT] = REG_FIELD(0x3C, 8, 14),
329*4882a593Smuzhiyun 	/*REG3D*/
330*4882a593Smuzhiyun 	[INPUT_VOLTAGE] = REG_FIELD(0x3D, 6, 13),
331*4882a593Smuzhiyun 	/*REG3E*/
332*4882a593Smuzhiyun 	[MIN_SYS_VOTAGE] = REG_FIELD(0x3E, 8, 13),
333*4882a593Smuzhiyun 	/*REG3F*/
334*4882a593Smuzhiyun 	[INPUT_CURRENT] = REG_FIELD(0x3F, 8, 14),
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	/*REGFE*/
337*4882a593Smuzhiyun 	[MANUFACTURE_ID] = REG_FIELD(0xFE, 0, 7),
338*4882a593Smuzhiyun 	/*REFFF*/
339*4882a593Smuzhiyun 	[DEVICE_ID] = REG_FIELD(0xFF, 0, 7),
340*4882a593Smuzhiyun };
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun static const struct reg_field bq25703_reg_fields[] = {
343*4882a593Smuzhiyun 	/*REG00*/
344*4882a593Smuzhiyun 	[EN_LWPWR] = REG_FIELD(0x00, 15, 15),
345*4882a593Smuzhiyun 	[WDTWR_ADJ] = REG_FIELD(0x00, 13, 14),
346*4882a593Smuzhiyun 	[IDPM_AUTO_DISABLE] = REG_FIELD(0x00, 12, 12),
347*4882a593Smuzhiyun 	[EN_OOA] = REG_FIELD(0x00, 10, 10),
348*4882a593Smuzhiyun 	[PWM_FREQ] = REG_FIELD(0x00, 9, 9),
349*4882a593Smuzhiyun 	[EN_LEARN] = REG_FIELD(0x00, 5, 5),
350*4882a593Smuzhiyun 	[IADP_GAIN] = REG_FIELD(0x00, 4, 4),
351*4882a593Smuzhiyun 	[IBAT_GAIN] = REG_FIELD(0x00, 3, 3),
352*4882a593Smuzhiyun 	[EN_LDO] = REG_FIELD(0x00, 2, 2),
353*4882a593Smuzhiyun 	[EN_IDPM] = REG_FIELD(0x00, 1, 1),
354*4882a593Smuzhiyun 	[CHRG_INHIBIT] = REG_FIELD(0x00, 0, 0),
355*4882a593Smuzhiyun 	/*REG0x02*/
356*4882a593Smuzhiyun 	[CHARGE_CURRENT] = REG_FIELD(0x02, 6, 12),
357*4882a593Smuzhiyun 	/*REG0x04*/
358*4882a593Smuzhiyun 	[MAX_CHARGE_VOLTAGE] = REG_FIELD(0x04, 4, 14),
359*4882a593Smuzhiyun 	/*REG20*/
360*4882a593Smuzhiyun 	[AC_STAT] = REG_FIELD(0x20, 15, 15),
361*4882a593Smuzhiyun 	[ICO_DONE] = REG_FIELD(0x20, 14, 14),
362*4882a593Smuzhiyun 	[IN_VINDPM] = REG_FIELD(0x20, 12, 12),
363*4882a593Smuzhiyun 	[IN_IINDPM] = REG_FIELD(0x20, 11, 11),
364*4882a593Smuzhiyun 	[IN_FCHRG] = REG_FIELD(0x20, 10, 10),
365*4882a593Smuzhiyun 	[IN_PCHRG] = REG_FIELD(0x20, 9, 9),
366*4882a593Smuzhiyun 	[IN_OTG] = REG_FIELD(0x20, 8, 8),
367*4882a593Smuzhiyun 	[F_ACOV] = REG_FIELD(0x20, 7, 7),
368*4882a593Smuzhiyun 	[F_BATOC] = REG_FIELD(0x20, 6, 6),
369*4882a593Smuzhiyun 	[F_ACOC] = REG_FIELD(0x20, 5, 5),
370*4882a593Smuzhiyun 	[SYSOVP_STAT] = REG_FIELD(0x20, 4, 4),
371*4882a593Smuzhiyun 	[F_LATCHOFF] = REG_FIELD(0x20, 2, 2),
372*4882a593Smuzhiyun 	[F_OTG_OVP] = REG_FIELD(0x20, 1, 1),
373*4882a593Smuzhiyun 	[F_OTG_OCP] = REG_FIELD(0x20, 0, 0),
374*4882a593Smuzhiyun 	/*REG22*/
375*4882a593Smuzhiyun 	[STAT_COMP] = REG_FIELD(0x22, 6, 6),
376*4882a593Smuzhiyun 	[STAT_ICRIT] = REG_FIELD(0x22, 5, 5),
377*4882a593Smuzhiyun 	[STAT_INOM] = REG_FIELD(0x22, 4, 4),
378*4882a593Smuzhiyun 	[STAT_IDCHG] = REG_FIELD(0x22, 3, 3),
379*4882a593Smuzhiyun 	[STAT_VSYS] = REG_FIELD(0x22, 2, 2),
380*4882a593Smuzhiyun 	[STAT_BAT_REMOV] = REG_FIELD(0x22, 1, 1),
381*4882a593Smuzhiyun 	[STAT_ADP_REMOV] = REG_FIELD(0x22, 0, 0),
382*4882a593Smuzhiyun 	/*REG24*/
383*4882a593Smuzhiyun 	[INPUT_CURRENT_DPM] = REG_FIELD(0x24, 8, 14),
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	/*REG26H*/
386*4882a593Smuzhiyun 	[OUTPUT_INPUT_VOL] = REG_FIELD(0x26, 8, 15),
387*4882a593Smuzhiyun 	[OUTPUT_SYS_POWER] = REG_FIELD(0x26, 0, 7),
388*4882a593Smuzhiyun 	/*REG28H*/
389*4882a593Smuzhiyun 	[OUTPUT_DSG_CUR] = REG_FIELD(0x28, 8, 14),
390*4882a593Smuzhiyun 	[OUTPUT_CHG_CUR] = REG_FIELD(0x28, 0, 6),
391*4882a593Smuzhiyun 	/*REG2aH*/
392*4882a593Smuzhiyun 	[OUTPUT_INPUT_CUR] = REG_FIELD(0x2a, 8, 15),
393*4882a593Smuzhiyun 	[OUTPUT_CMPIN_VOL] = REG_FIELD(0x2a, 0, 7),
394*4882a593Smuzhiyun 	/*REG2cH*/
395*4882a593Smuzhiyun 	[OUTPUT_SYS_VOL] = REG_FIELD(0x2c, 8, 15),
396*4882a593Smuzhiyun 	[OUTPUT_BAT_VOL] = REG_FIELD(0x2c, 0, 6),
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	/*REG30*/
399*4882a593Smuzhiyun 	[EN_IBAT] = REG_FIELD(0x30, 15, 15),
400*4882a593Smuzhiyun 	[EN_PROCHOT_LPWR] = REG_FIELD(0x30, 13, 14),
401*4882a593Smuzhiyun 	[EN_PSYS] = REG_FIELD(0x30, 12, 12),
402*4882a593Smuzhiyun 	[RSNS_RAC] = REG_FIELD(0x30, 11, 11),
403*4882a593Smuzhiyun 	[RSNS_RSR] = REG_FIELD(0x30, 10, 10),
404*4882a593Smuzhiyun 	[PSYS_RATIO] = REG_FIELD(0x30, 9, 9),
405*4882a593Smuzhiyun 	[CMP_REF] = REG_FIELD(0x30, 7, 7),
406*4882a593Smuzhiyun 	[CMP_POL] = REG_FIELD(0x30, 6, 6),
407*4882a593Smuzhiyun 	[CMP_DEG] = REG_FIELD(0x30, 4, 5),
408*4882a593Smuzhiyun 	[FORCE_LATCHOFF] = REG_FIELD(0x30, 3, 3),
409*4882a593Smuzhiyun 	[EN_SHIP_DCHG] = REG_FIELD(0x30, 1, 1),
410*4882a593Smuzhiyun 	[AUTO_WAKEUP_EN] = REG_FIELD(0x30, 0, 0),
411*4882a593Smuzhiyun 	/*REG32*/
412*4882a593Smuzhiyun 	[PKPWR_TOVLD_REG] = REG_FIELD(0x32, 14, 15),
413*4882a593Smuzhiyun 	[EN_PKPWR_IDPM] = REG_FIELD(0x32, 13, 13),
414*4882a593Smuzhiyun 	[EN_PKPWR_VSYS] = REG_FIELD(0x32, 12, 12),
415*4882a593Smuzhiyun 	[PKPWER_OVLD_STAT] = REG_FIELD(0x32, 11, 11),
416*4882a593Smuzhiyun 	[PKPWR_RELAX_STAT] = REG_FIELD(0x32, 10, 10),
417*4882a593Smuzhiyun 	[PKPWER_TMAX] = REG_FIELD(0x32, 8, 9),
418*4882a593Smuzhiyun 	[EN_EXTILIM] = REG_FIELD(0x32, 7, 7),
419*4882a593Smuzhiyun 	[EN_ICHG_IDCHG] = REG_FIELD(0x32, 6, 6),
420*4882a593Smuzhiyun 	[Q2_OCP] = REG_FIELD(0x32, 5, 5),
421*4882a593Smuzhiyun 	[ACX_OCP] = REG_FIELD(0x32, 4, 4),
422*4882a593Smuzhiyun 	[EN_ACOC] = REG_FIELD(0x32, 3, 3),
423*4882a593Smuzhiyun 	[ACOC_VTH] = REG_FIELD(0x32, 2, 2),
424*4882a593Smuzhiyun 	[EN_BATOC] = REG_FIELD(0x32, 1, 1),
425*4882a593Smuzhiyun 	[BATCOC_VTH] = REG_FIELD(0x32, 0, 0),
426*4882a593Smuzhiyun 	/*REG34*/
427*4882a593Smuzhiyun 	[EN_HIZ] = REG_FIELD(0x34, 15, 15),
428*4882a593Smuzhiyun 	[RESET_REG] = REG_FIELD(0x34, 14, 14),
429*4882a593Smuzhiyun 	[RESET_VINDPM] = REG_FIELD(0x34, 13, 13),
430*4882a593Smuzhiyun 	[EN_OTG] = REG_FIELD(0x34, 12, 12),
431*4882a593Smuzhiyun 	[EN_ICO_MODE] = REG_FIELD(0x34, 11, 11),
432*4882a593Smuzhiyun 	[BATFETOFF_HIZ] = REG_FIELD(0x34, 1, 1),
433*4882a593Smuzhiyun 	[PSYS_OTG_IDCHG] = REG_FIELD(0x34, 0, 0),
434*4882a593Smuzhiyun 	/*REG36*/
435*4882a593Smuzhiyun 	[ILIM2_VTH] = REG_FIELD(0x36, 11, 15),
436*4882a593Smuzhiyun 	[ICRIT_DEG] = REG_FIELD(0x36, 9, 10),
437*4882a593Smuzhiyun 	[VSYS_VTH] = REG_FIELD(0x36, 6, 7),
438*4882a593Smuzhiyun 	[EN_PROCHOT_EXT] = REG_FIELD(0x36, 5, 5),
439*4882a593Smuzhiyun 	[PROCHOT_WIDTH] = REG_FIELD(0x36, 3, 4),
440*4882a593Smuzhiyun 	[PROCHOT_CLEAR] = REG_FIELD(0x36, 2, 2),
441*4882a593Smuzhiyun 	[INOM_DEG] = REG_FIELD(0x36, 1, 1),
442*4882a593Smuzhiyun 	/*REG38*/
443*4882a593Smuzhiyun 	[IDCHG_VTH] = REG_FIELD(0x38, 10, 15),
444*4882a593Smuzhiyun 	[IDCHG_DEG] = REG_FIELD(0x38, 8, 9),
445*4882a593Smuzhiyun 	[PROCHOT_PROFILE_COMP] = REG_FIELD(0x38, 6, 6),
446*4882a593Smuzhiyun 	[PROCHOT_PROFILE_ICRIT] = REG_FIELD(0x38, 5, 5),
447*4882a593Smuzhiyun 	[PROCHOT_PROFILE_INOM] = REG_FIELD(0x38, 4, 4),
448*4882a593Smuzhiyun 	[PROCHOT_PROFILE_IDCHG] = REG_FIELD(0x38, 3, 3),
449*4882a593Smuzhiyun 	[PROCHOT_PROFILE_VSYS] = REG_FIELD(0x38, 2, 2),
450*4882a593Smuzhiyun 	[PROCHOT_PROFILE_BATPRES] = REG_FIELD(0x38, 1, 1),
451*4882a593Smuzhiyun 	[PROCHOT_PROFILE_ACOK] = REG_FIELD(0x38, 0, 0),
452*4882a593Smuzhiyun 	/*REG3a*/
453*4882a593Smuzhiyun 	[ADC_CONV] = REG_FIELD(0x3a, 15, 15),
454*4882a593Smuzhiyun 	[ADC_START] = REG_FIELD(0x3a, 14, 14),
455*4882a593Smuzhiyun 	[ADC_FULLSCALE] = REG_FIELD(0x3a, 13, 13),
456*4882a593Smuzhiyun 	[EN_ADC_CMPIN] = REG_FIELD(0x3a, 7, 7),
457*4882a593Smuzhiyun 	[EN_ADC_VBUS] = REG_FIELD(0x3a, 6, 6),
458*4882a593Smuzhiyun 	[EN_ADC_PSYS] = REG_FIELD(0x3a, 5, 5),
459*4882a593Smuzhiyun 	[EN_ADC_IIN] = REG_FIELD(0x3a, 4, 4),
460*4882a593Smuzhiyun 	[EN_ADC_IDCHG] = REG_FIELD(0x3a, 3, 3),
461*4882a593Smuzhiyun 	[EN_ADC_ICHG] = REG_FIELD(0x3a, 2, 2),
462*4882a593Smuzhiyun 	[EN_ADC_VSYS] = REG_FIELD(0x3a, 1, 1),
463*4882a593Smuzhiyun 	[EN_ADC_VBAT] = REG_FIELD(0x3a, 0, 0),
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	/*REG06*/
466*4882a593Smuzhiyun 	[OTG_VOLTAGE] = REG_FIELD(0x06, 6, 13),
467*4882a593Smuzhiyun 	/*REG08*/
468*4882a593Smuzhiyun 	[OTG_CURRENT] = REG_FIELD(0x08, 8, 14),
469*4882a593Smuzhiyun 	/*REG0a*/
470*4882a593Smuzhiyun 	[INPUT_VOLTAGE] = REG_FIELD(0x0a, 6, 13),
471*4882a593Smuzhiyun 	/*REG0C*/
472*4882a593Smuzhiyun 	[MIN_SYS_VOTAGE] = REG_FIELD(0x0c, 8, 13),
473*4882a593Smuzhiyun 	/*REG0e*/
474*4882a593Smuzhiyun 	[INPUT_CURRENT] = REG_FIELD(0x0e, 8, 14),
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	/*REG2E*/
477*4882a593Smuzhiyun 	[MANUFACTURE_ID] = REG_FIELD(0x2E, 0, 7),
478*4882a593Smuzhiyun 	/*REF2F*/
479*4882a593Smuzhiyun 	[DEVICE_ID] = REG_FIELD(0x2F, 0, 7),
480*4882a593Smuzhiyun };
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun /*
483*4882a593Smuzhiyun  * Most of the val -> idx conversions can be computed, given the minimum,
484*4882a593Smuzhiyun  * maximum and the step between values. For the rest of conversions, we use
485*4882a593Smuzhiyun  * lookup tables.
486*4882a593Smuzhiyun  */
487*4882a593Smuzhiyun enum bq25700_table_ids {
488*4882a593Smuzhiyun 	/* range tables */
489*4882a593Smuzhiyun 	TBL_ICHG,
490*4882a593Smuzhiyun 	TBL_CHGMAX,
491*4882a593Smuzhiyun 	TBL_INPUTVOL,
492*4882a593Smuzhiyun 	TBL_INPUTCUR,
493*4882a593Smuzhiyun 	TBL_SYSVMIN,
494*4882a593Smuzhiyun 	TBL_OTGVOL,
495*4882a593Smuzhiyun 	TBL_OTGCUR,
496*4882a593Smuzhiyun 	TBL_EXTCON,
497*4882a593Smuzhiyun };
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun struct bq25700_range {
500*4882a593Smuzhiyun 	u32 min;
501*4882a593Smuzhiyun 	u32 max;
502*4882a593Smuzhiyun 	u32 step;
503*4882a593Smuzhiyun };
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun struct bq25700_lookup {
506*4882a593Smuzhiyun 	const u32 *tbl;
507*4882a593Smuzhiyun 	u32 size;
508*4882a593Smuzhiyun };
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun static const struct bq25700_range sc8886_otg_range = {
511*4882a593Smuzhiyun 	.min = 1280000,
512*4882a593Smuzhiyun 	.max = 20800000,
513*4882a593Smuzhiyun 	.step = 128000,
514*4882a593Smuzhiyun };
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun static union {
517*4882a593Smuzhiyun 	struct bq25700_range  rt;
518*4882a593Smuzhiyun 	struct bq25700_lookup lt;
519*4882a593Smuzhiyun } bq25700_tables[] = {
520*4882a593Smuzhiyun 	/* range tables */
521*4882a593Smuzhiyun 	[TBL_ICHG] =	{ .rt = {0,	  8128000, 64000} },
522*4882a593Smuzhiyun 	/* uV */
523*4882a593Smuzhiyun 	[TBL_CHGMAX] = { .rt = {0, 19200000, 16000} },
524*4882a593Smuzhiyun 	/* uV  max charge voltage*/
525*4882a593Smuzhiyun 	[TBL_INPUTVOL] = { .rt = {3200000, 19520000, 64000} },
526*4882a593Smuzhiyun 	/* uV  input charge voltage*/
527*4882a593Smuzhiyun 	[TBL_INPUTCUR] = {.rt = {0, 6350000, 50000} },
528*4882a593Smuzhiyun 	/*uA input current*/
529*4882a593Smuzhiyun 	[TBL_SYSVMIN] = { .rt = {1024000, 16182000, 256000} },
530*4882a593Smuzhiyun 	/* uV min system voltage*/
531*4882a593Smuzhiyun 	[TBL_OTGVOL] = {.rt = {4480000, 20800000, 64000} },
532*4882a593Smuzhiyun 	/*uV OTG volage*/
533*4882a593Smuzhiyun 	[TBL_OTGCUR] = {.rt = {0, 6350000, 50000} },
534*4882a593Smuzhiyun };
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun static const struct regmap_range bq25700_readonly_reg_ranges[] = {
537*4882a593Smuzhiyun 	regmap_reg_range(0x20, 0x26),
538*4882a593Smuzhiyun 	regmap_reg_range(0xFE, 0xFF),
539*4882a593Smuzhiyun };
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun static const struct regmap_access_table bq25700_writeable_regs = {
542*4882a593Smuzhiyun 	.no_ranges = bq25700_readonly_reg_ranges,
543*4882a593Smuzhiyun 	.n_no_ranges = ARRAY_SIZE(bq25700_readonly_reg_ranges),
544*4882a593Smuzhiyun };
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun static const struct regmap_range bq25700_volatile_reg_ranges[] = {
547*4882a593Smuzhiyun 	regmap_reg_range(0x12, 0x12),
548*4882a593Smuzhiyun 	regmap_reg_range(0x14, 0x15),
549*4882a593Smuzhiyun 	regmap_reg_range(0x20, 0x26),
550*4882a593Smuzhiyun 	regmap_reg_range(0x30, 0x35),
551*4882a593Smuzhiyun 	regmap_reg_range(0x3B, 0x3F),
552*4882a593Smuzhiyun 	regmap_reg_range(0xFE, 0xFF),
553*4882a593Smuzhiyun };
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun static const struct regmap_access_table bq25700_volatile_regs = {
556*4882a593Smuzhiyun 	.yes_ranges = bq25700_volatile_reg_ranges,
557*4882a593Smuzhiyun 	.n_yes_ranges = ARRAY_SIZE(bq25700_volatile_reg_ranges),
558*4882a593Smuzhiyun };
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun static const struct regmap_config bq25700_regmap_config = {
561*4882a593Smuzhiyun 	.reg_bits = 8,
562*4882a593Smuzhiyun 	.val_bits = 16,
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	.max_register = 0xFF,
565*4882a593Smuzhiyun 	.cache_type = REGCACHE_RBTREE,
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	.wr_table = &bq25700_writeable_regs,
568*4882a593Smuzhiyun 	.volatile_table = &bq25700_volatile_regs,
569*4882a593Smuzhiyun 	.val_format_endian = REGMAP_ENDIAN_LITTLE,
570*4882a593Smuzhiyun };
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun static const struct regmap_range bq25703_readonly_reg_ranges[] = {
573*4882a593Smuzhiyun 	regmap_reg_range(0x20, 0x2F),
574*4882a593Smuzhiyun };
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun static const struct regmap_access_table bq25703_writeable_regs = {
577*4882a593Smuzhiyun 	.no_ranges = bq25703_readonly_reg_ranges,
578*4882a593Smuzhiyun 	.n_no_ranges = ARRAY_SIZE(bq25703_readonly_reg_ranges),
579*4882a593Smuzhiyun };
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun static const struct regmap_range bq25703_volatile_reg_ranges[] = {
582*4882a593Smuzhiyun 	regmap_reg_range(0x00, 0x0F),
583*4882a593Smuzhiyun 	regmap_reg_range(0x20, 0x3B),
584*4882a593Smuzhiyun };
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun static const struct regmap_access_table bq25703_volatile_regs = {
587*4882a593Smuzhiyun 	.yes_ranges = bq25703_volatile_reg_ranges,
588*4882a593Smuzhiyun 	.n_yes_ranges = ARRAY_SIZE(bq25703_volatile_reg_ranges),
589*4882a593Smuzhiyun };
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun static const struct regmap_config bq25703_regmap_config = {
592*4882a593Smuzhiyun 	.reg_bits = 8,
593*4882a593Smuzhiyun 	.val_bits = 16,
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	.max_register = 0x3B,
596*4882a593Smuzhiyun 	.cache_type = REGCACHE_RBTREE,
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	.wr_table = &bq25703_writeable_regs,
599*4882a593Smuzhiyun 	.volatile_table = &bq25703_volatile_regs,
600*4882a593Smuzhiyun 	.val_format_endian = REGMAP_ENDIAN_LITTLE,
601*4882a593Smuzhiyun };
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun static void bq25700_disable_charge(struct bq25700_device *charger);
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun static struct bq25700_device *bq25700_charger;
606*4882a593Smuzhiyun 
bq25700_field_read(struct bq25700_device * charger,enum bq25700_fields field_id)607*4882a593Smuzhiyun static int bq25700_field_read(struct bq25700_device *charger,
608*4882a593Smuzhiyun 			      enum bq25700_fields field_id)
609*4882a593Smuzhiyun {
610*4882a593Smuzhiyun 	int ret;
611*4882a593Smuzhiyun 	int val;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	ret = regmap_field_read(charger->rmap_fields[field_id], &val);
614*4882a593Smuzhiyun 	if (ret < 0)
615*4882a593Smuzhiyun 		return ret;
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 	return val;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun 
bq25700_field_write(struct bq25700_device * charger,enum bq25700_fields field_id,unsigned int val)620*4882a593Smuzhiyun static int bq25700_field_write(struct bq25700_device *charger,
621*4882a593Smuzhiyun 			       enum bq25700_fields field_id, unsigned int val)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun 	return regmap_field_write(charger->rmap_fields[field_id], val);
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun 
bq25700_get_chip_state(struct bq25700_device * charger,struct bq25700_state * state)626*4882a593Smuzhiyun static int bq25700_get_chip_state(struct bq25700_device *charger,
627*4882a593Smuzhiyun 				  struct bq25700_state *state)
628*4882a593Smuzhiyun {
629*4882a593Smuzhiyun 	int i, ret;
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	struct {
632*4882a593Smuzhiyun 		enum bq25700_fields id;
633*4882a593Smuzhiyun 		u8 *data;
634*4882a593Smuzhiyun 	} state_fields[] = {
635*4882a593Smuzhiyun 		{AC_STAT,	&state->ac_stat},
636*4882a593Smuzhiyun 		{ICO_DONE,	&state->ico_done},
637*4882a593Smuzhiyun 		{IN_VINDPM,	&state->in_vindpm},
638*4882a593Smuzhiyun 		{IN_IINDPM, &state->in_iindpm},
639*4882a593Smuzhiyun 		{IN_FCHRG,	&state->in_fchrg},
640*4882a593Smuzhiyun 		{IN_PCHRG,	&state->in_pchrg},
641*4882a593Smuzhiyun 		{IN_OTG,	&state->in_otg},
642*4882a593Smuzhiyun 		{F_ACOV,	&state->fault_acov},
643*4882a593Smuzhiyun 		{F_BATOC,	&state->fault_batoc},
644*4882a593Smuzhiyun 		{F_ACOC,	&state->fault_acoc},
645*4882a593Smuzhiyun 		{SYSOVP_STAT,	&state->sysovp_stat},
646*4882a593Smuzhiyun 		{F_LATCHOFF,	&state->fault_latchoff},
647*4882a593Smuzhiyun 		{F_OTG_OVP,	&state->fault_otg_ovp},
648*4882a593Smuzhiyun 		{F_OTG_OCP,	&state->fault_otg_ocp},
649*4882a593Smuzhiyun 	};
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(state_fields); i++) {
652*4882a593Smuzhiyun 		ret = bq25700_field_read(charger, state_fields[i].id);
653*4882a593Smuzhiyun 		if (ret < 0)
654*4882a593Smuzhiyun 			return ret;
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun 		*state_fields[i].data = ret;
657*4882a593Smuzhiyun 	}
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	return 0;
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun 
bq25700_dump_regs(struct bq25700_device * charger)662*4882a593Smuzhiyun static int bq25700_dump_regs(struct bq25700_device *charger)
663*4882a593Smuzhiyun {
664*4882a593Smuzhiyun 	u32 val = 0;
665*4882a593Smuzhiyun 	struct bq25700_state state;
666*4882a593Smuzhiyun 	int ret = 0;
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, ADC_START, 1);
669*4882a593Smuzhiyun 	if (ret < 0) {
670*4882a593Smuzhiyun 		DBG("error: ADC_START\n");
671*4882a593Smuzhiyun 		return ret;
672*4882a593Smuzhiyun 	}
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	DBG("\n==================================\n");
675*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x12, &val);
676*4882a593Smuzhiyun 	DBG("REG0x12 : 0x%x\n", val);
677*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x14, &val);
678*4882a593Smuzhiyun 	DBG("REG0x14 : 0x%x\n", val);
679*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x15, &val);
680*4882a593Smuzhiyun 	DBG("REG0x15 : 0x%x\n", val);
681*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x30, &val);
682*4882a593Smuzhiyun 	DBG("REG0x30 : 0x%x\n", val);
683*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x31, &val);
684*4882a593Smuzhiyun 	DBG("REG0x31 : 0x%x\n", val);
685*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x32, &val);
686*4882a593Smuzhiyun 	DBG("REG0x32 : 0x%x\n", val);
687*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x33, &val);
688*4882a593Smuzhiyun 	DBG("REG0x33 : 0x%x\n", val);
689*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x34, &val);
690*4882a593Smuzhiyun 	DBG("REG0x34 : 0x%x\n", val);
691*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x35, &val);
692*4882a593Smuzhiyun 	DBG("REG0x35 : 0x%x\n", val);
693*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x20, &val);
694*4882a593Smuzhiyun 	DBG("REG0x20 : 0x%x\n", val);
695*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x21, &val);
696*4882a593Smuzhiyun 	DBG("REG0x21 : 0x%x\n", val);
697*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x22, &val);
698*4882a593Smuzhiyun 	DBG("REG0x22 : 0x%x\n", val);
699*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x23, &val);
700*4882a593Smuzhiyun 	DBG("REG0x23 : 0x%x\n", val);
701*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x24, &val);
702*4882a593Smuzhiyun 	DBG("REG0x24 : 0x%x\n", val);
703*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x25, &val);
704*4882a593Smuzhiyun 	DBG("REG0x25 : 0x%x\n", val);
705*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x26, &val);
706*4882a593Smuzhiyun 	DBG("REG0x26 : 0x%x\n", val);
707*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x3b, &val);
708*4882a593Smuzhiyun 	DBG("REG0x3b : 0x%x\n", val);
709*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x3c, &val);
710*4882a593Smuzhiyun 	DBG("REG0x3c : 0x%x\n", val);
711*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x3d, &val);
712*4882a593Smuzhiyun 	DBG("REG0x3d : 0x%x\n", val);
713*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x3e, &val);
714*4882a593Smuzhiyun 	DBG("REG0x3e : 0x%x\n", val);
715*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0x3f, &val);
716*4882a593Smuzhiyun 	DBG("REG0x3f : 0x%x\n", val);
717*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0xfe, &val);
718*4882a593Smuzhiyun 	DBG("REG0xfe : 0x%x\n", val);
719*4882a593Smuzhiyun 	regmap_read(charger->regmap, 0xff, &val);
720*4882a593Smuzhiyun 	DBG("REG0xff : 0x%x\n", val);
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	DBG("battery charge current: %dmA\n",
723*4882a593Smuzhiyun 	    bq25700_field_read(charger, OUTPUT_DSG_CUR) * 64);
724*4882a593Smuzhiyun 	DBG("battery discharge current: %dmA\n",
725*4882a593Smuzhiyun 	    bq25700_field_read(charger, OUTPUT_CHG_CUR) * 256);
726*4882a593Smuzhiyun 	DBG("VSYS volatge: %dmV\n",
727*4882a593Smuzhiyun 	    2880 + bq25700_field_read(charger, OUTPUT_SYS_VOL) * 64);
728*4882a593Smuzhiyun 	DBG("BAT volatge: %dmV\n",
729*4882a593Smuzhiyun 	    2880 + bq25700_field_read(charger, OUTPUT_BAT_VOL) * 64);
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	DBG("SET CHARGE_CURRENT: %dmA\n",
732*4882a593Smuzhiyun 	    bq25700_field_read(charger, CHARGE_CURRENT) * 64);
733*4882a593Smuzhiyun 	DBG("MAX_CHARGE_VOLTAGE: %dmV\n",
734*4882a593Smuzhiyun 	    bq25700_field_read(charger, MAX_CHARGE_VOLTAGE) * 16);
735*4882a593Smuzhiyun 	DBG("	  INPUT_VOLTAGE: %dmV\n",
736*4882a593Smuzhiyun 	    3200 + bq25700_field_read(charger, INPUT_VOLTAGE) * 64);
737*4882a593Smuzhiyun 	DBG("	  INPUT_CURRENT: %dmA\n",
738*4882a593Smuzhiyun 	    bq25700_field_read(charger, INPUT_CURRENT) * 50);
739*4882a593Smuzhiyun 	DBG("	 MIN_SYS_VOTAGE: %dmV\n",
740*4882a593Smuzhiyun 	    1024 + bq25700_field_read(charger, MIN_SYS_VOTAGE) * 256);
741*4882a593Smuzhiyun 	bq25700_get_chip_state(charger, &state);
742*4882a593Smuzhiyun 	DBG("status:\n");
743*4882a593Smuzhiyun 	DBG("AC_STAT:  %d\n", state.ac_stat);
744*4882a593Smuzhiyun 	DBG("ICO_DONE: %d\n", state.ico_done);
745*4882a593Smuzhiyun 	DBG("IN_VINDPM: %d\n", state.in_vindpm);
746*4882a593Smuzhiyun 	DBG("IN_IINDPM: %d\n", state.in_iindpm);
747*4882a593Smuzhiyun 	DBG("IN_FCHRG: %d\n", state.in_fchrg);
748*4882a593Smuzhiyun 	DBG("IN_PCHRG: %d\n", state.in_pchrg);
749*4882a593Smuzhiyun 	DBG("IN_OTG: %d\n", state.in_otg);
750*4882a593Smuzhiyun 	DBG("F_ACOV: %d\n", state.fault_acov);
751*4882a593Smuzhiyun 	DBG("F_BATOC: %d\n", state.fault_batoc);
752*4882a593Smuzhiyun 	DBG("F_ACOC: %d\n", state.fault_acoc);
753*4882a593Smuzhiyun 	DBG("SYSOVP_STAT: %d\n", state.sysovp_stat);
754*4882a593Smuzhiyun 	DBG("F_LATCHOFF: %d\n", state.fault_latchoff);
755*4882a593Smuzhiyun 	DBG("F_OTGOVP: %d\n", state.fault_otg_ovp);
756*4882a593Smuzhiyun 	DBG("F_OTGOCP: %d\n", state.fault_otg_ocp);
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 	DBG("\n+++++++++++++++++++++++++++++++++++++++++++++++++\n");
759*4882a593Smuzhiyun 	return 0;
760*4882a593Smuzhiyun }
761*4882a593Smuzhiyun 
bq25703_dump_regs(struct bq25700_device * charger)762*4882a593Smuzhiyun static int bq25703_dump_regs(struct bq25700_device *charger)
763*4882a593Smuzhiyun {
764*4882a593Smuzhiyun 	int i = 0;
765*4882a593Smuzhiyun 	u32 val = 0;
766*4882a593Smuzhiyun 	struct bq25700_state state;
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	for (i = 0; i < 0x10; i += 0x02) {
769*4882a593Smuzhiyun 		regmap_read(charger->regmap, i, &val);
770*4882a593Smuzhiyun 		DBG("REG0x%x : 0x%x\n", i, val);
771*4882a593Smuzhiyun 	}
772*4882a593Smuzhiyun 	for (i = 0x20; i < 0x3C; i += 0x02) {
773*4882a593Smuzhiyun 		regmap_read(charger->regmap, i, &val);
774*4882a593Smuzhiyun 		DBG("REG0x%x : 0x%x\n", i, val);
775*4882a593Smuzhiyun 	}
776*4882a593Smuzhiyun 
777*4882a593Smuzhiyun 	DBG("battery charge current: %dmA\n",
778*4882a593Smuzhiyun 	    bq25700_field_read(charger, OUTPUT_DSG_CUR) * 64);
779*4882a593Smuzhiyun 	DBG("battery discharge current: %dmA\n",
780*4882a593Smuzhiyun 	    bq25700_field_read(charger, OUTPUT_CHG_CUR) * 256);
781*4882a593Smuzhiyun 	DBG("VSYS volatge: %dmV\n",
782*4882a593Smuzhiyun 	    2880 + bq25700_field_read(charger, OUTPUT_SYS_VOL) * 64);
783*4882a593Smuzhiyun 	DBG("BAT volatge: %dmV\n",
784*4882a593Smuzhiyun 	    2880 + bq25700_field_read(charger, OUTPUT_BAT_VOL) * 64);
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	DBG("SET CHARGE_CURRENT: %dmA\n",
787*4882a593Smuzhiyun 	    bq25700_field_read(charger, CHARGE_CURRENT) * 64);
788*4882a593Smuzhiyun 	DBG("MAX_CHARGE_VOLTAGE: %dmV\n",
789*4882a593Smuzhiyun 	    bq25700_field_read(charger, MAX_CHARGE_VOLTAGE) * 16);
790*4882a593Smuzhiyun 	DBG("	  INPUT_VOLTAGE: %dmV\n",
791*4882a593Smuzhiyun 	    3200 + bq25700_field_read(charger, INPUT_VOLTAGE) * 64);
792*4882a593Smuzhiyun 	DBG("	  INPUT_CURRENT: %dmA\n",
793*4882a593Smuzhiyun 	    bq25700_field_read(charger, INPUT_CURRENT) * 50);
794*4882a593Smuzhiyun 	DBG("	 MIN_SYS_VOTAGE: %dmV\n",
795*4882a593Smuzhiyun 	    1024 + bq25700_field_read(charger, MIN_SYS_VOTAGE) * 256);
796*4882a593Smuzhiyun 	bq25700_get_chip_state(charger, &state);
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 	DBG("status:\n");
799*4882a593Smuzhiyun 	DBG("AC_STAT:  %d\n", state.ac_stat);
800*4882a593Smuzhiyun 	DBG("ICO_DONE: %d\n", state.ico_done);
801*4882a593Smuzhiyun 	DBG("IN_VINDPM: %d\n", state.in_vindpm);
802*4882a593Smuzhiyun 	DBG("IN_IINDPM: %d\n", state.in_iindpm);
803*4882a593Smuzhiyun 	DBG("IN_FCHRG: %d\n", state.in_fchrg);
804*4882a593Smuzhiyun 	DBG("IN_PCHRG: %d\n", state.in_pchrg);
805*4882a593Smuzhiyun 	DBG("IN_OTG: %d\n", state.in_otg);
806*4882a593Smuzhiyun 	DBG("F_ACOV: %d\n", state.fault_acov);
807*4882a593Smuzhiyun 	DBG("F_BATOC: %d\n", state.fault_batoc);
808*4882a593Smuzhiyun 	DBG("F_ACOC: %d\n", state.fault_acoc);
809*4882a593Smuzhiyun 	DBG("SYSOVP_STAT: %d\n", state.sysovp_stat);
810*4882a593Smuzhiyun 	DBG("F_LATCHOFF: %d\n", state.fault_latchoff);
811*4882a593Smuzhiyun 	DBG("F_OTGOVP: %d\n", state.fault_otg_ovp);
812*4882a593Smuzhiyun 	DBG("F_OTGOCP: %d\n", state.fault_otg_ocp);
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 	return 0;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun 
bq25700_charge_info_show(struct device * dev,struct device_attribute * attr,char * buf)817*4882a593Smuzhiyun static ssize_t bq25700_charge_info_show(struct device *dev,
818*4882a593Smuzhiyun 				 struct device_attribute *attr, char *buf)
819*4882a593Smuzhiyun {
820*4882a593Smuzhiyun 	struct bq25700_device *charger = dev_get_drvdata(dev);
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun 	if ((charger->chip_id & 0xff) == BQ25700_ID)
823*4882a593Smuzhiyun 		bq25700_dump_regs(charger);
824*4882a593Smuzhiyun 	if ((charger->chip_id & 0xff) == BQ25703_ID)
825*4882a593Smuzhiyun 		bq25703_dump_regs(charger);
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	return 0;
828*4882a593Smuzhiyun }
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun static struct device_attribute bq25700_charger_attr[] = {
831*4882a593Smuzhiyun 	__ATTR(charge_info, 0664, bq25700_charge_info_show, NULL),
832*4882a593Smuzhiyun };
833*4882a593Smuzhiyun 
bq25700_init_sysfs(struct bq25700_device * charger)834*4882a593Smuzhiyun static void bq25700_init_sysfs(struct bq25700_device *charger)
835*4882a593Smuzhiyun {
836*4882a593Smuzhiyun 	int i, ret;
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(bq25700_charger_attr); i++) {
839*4882a593Smuzhiyun 		ret = sysfs_create_file(&charger->dev->kobj,
840*4882a593Smuzhiyun 					&bq25700_charger_attr[i].attr);
841*4882a593Smuzhiyun 		if (ret)
842*4882a593Smuzhiyun 			dev_err(charger->dev, "create charger node(%s) error\n",
843*4882a593Smuzhiyun 				bq25700_charger_attr[i].attr.name);
844*4882a593Smuzhiyun 	}
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun 
bq25700_find_idx(u32 value,enum bq25700_table_ids id)847*4882a593Smuzhiyun static u32 bq25700_find_idx(u32 value, enum bq25700_table_ids id)
848*4882a593Smuzhiyun {
849*4882a593Smuzhiyun 	u32 idx;
850*4882a593Smuzhiyun 	u32 rtbl_size;
851*4882a593Smuzhiyun 	const struct bq25700_range *rtbl = &bq25700_tables[id].rt;
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	rtbl_size = (rtbl->max - rtbl->min) / rtbl->step + 1;
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	for (idx = 1;
856*4882a593Smuzhiyun 	     idx < rtbl_size && (idx * rtbl->step + rtbl->min <= value);
857*4882a593Smuzhiyun 	     idx++)
858*4882a593Smuzhiyun 		;
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	return idx - 1;
861*4882a593Smuzhiyun }
862*4882a593Smuzhiyun 
bq25700_charger_set_current(unsigned long event,int current_value)863*4882a593Smuzhiyun void bq25700_charger_set_current(unsigned long event,
864*4882a593Smuzhiyun 				 int current_value)
865*4882a593Smuzhiyun {
866*4882a593Smuzhiyun 	int idx;
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun 	if (!bq25700_charger) {
869*4882a593Smuzhiyun 		pr_err("[%s,%d] bq25700_charger is null\n", __func__, __LINE__);
870*4882a593Smuzhiyun 		return;
871*4882a593Smuzhiyun 	}
872*4882a593Smuzhiyun 	switch (event) {
873*4882a593Smuzhiyun 	case CHARGER_CURRENT_EVENT:
874*4882a593Smuzhiyun 		idx = bq25700_find_idx(current_value, TBL_ICHG);
875*4882a593Smuzhiyun 		bq25700_field_write(bq25700_charger, CHARGE_CURRENT, idx);
876*4882a593Smuzhiyun 		break;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	case INPUT_CURRENT_EVENT:
879*4882a593Smuzhiyun 		idx = bq25700_find_idx(current_value, TBL_INPUTCUR);
880*4882a593Smuzhiyun 		bq25700_field_write(bq25700_charger, INPUT_CURRENT, idx);
881*4882a593Smuzhiyun 		break;
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun 	default:
884*4882a593Smuzhiyun 		return;
885*4882a593Smuzhiyun 	}
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun 
bq25700_fw_read_u32_props(struct bq25700_device * charger)888*4882a593Smuzhiyun static int bq25700_fw_read_u32_props(struct bq25700_device *charger)
889*4882a593Smuzhiyun {
890*4882a593Smuzhiyun 	int ret;
891*4882a593Smuzhiyun 	u32 property;
892*4882a593Smuzhiyun 	int i;
893*4882a593Smuzhiyun 	struct bq25700_init_data *init = &charger->init_data;
894*4882a593Smuzhiyun 	struct {
895*4882a593Smuzhiyun 		char *name;
896*4882a593Smuzhiyun 		bool optional;
897*4882a593Smuzhiyun 		enum bq25700_table_ids tbl_id;
898*4882a593Smuzhiyun 		u32 *conv_data; /* holds converted value from given property */
899*4882a593Smuzhiyun 	} props[] = {
900*4882a593Smuzhiyun 		/* required properties */
901*4882a593Smuzhiyun 		{"ti,charge-current", false, TBL_ICHG,
902*4882a593Smuzhiyun 		 &init->ichg},
903*4882a593Smuzhiyun 		{"ti,max-charge-voltage", false, TBL_CHGMAX,
904*4882a593Smuzhiyun 		 &init->max_chg_vol},
905*4882a593Smuzhiyun 		{"ti,input-current-sdp", false, TBL_INPUTCUR,
906*4882a593Smuzhiyun 		 &init->input_current_sdp},
907*4882a593Smuzhiyun 		{"ti,input-current-dcp", false, TBL_INPUTCUR,
908*4882a593Smuzhiyun 		 &init->input_current_dcp},
909*4882a593Smuzhiyun 		{"ti,input-current-cdp", false, TBL_INPUTCUR,
910*4882a593Smuzhiyun 		 &init->input_current_cdp},
911*4882a593Smuzhiyun 		{"ti,minimum-sys-voltage", false, TBL_SYSVMIN,
912*4882a593Smuzhiyun 		 &init->sys_min_voltage},
913*4882a593Smuzhiyun 		{"ti,otg-voltage", false, TBL_OTGVOL,
914*4882a593Smuzhiyun 		 &init->otg_voltage},
915*4882a593Smuzhiyun 		{"ti,otg-current", false, TBL_OTGCUR,
916*4882a593Smuzhiyun 		 &init->otg_current},
917*4882a593Smuzhiyun 	};
918*4882a593Smuzhiyun 
919*4882a593Smuzhiyun 	/* initialize data for optional properties */
920*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(props); i++) {
921*4882a593Smuzhiyun 		ret = device_property_read_u32(charger->dev, props[i].name,
922*4882a593Smuzhiyun 					       &property);
923*4882a593Smuzhiyun 		if (ret < 0) {
924*4882a593Smuzhiyun 			if (props[i].optional)
925*4882a593Smuzhiyun 				continue;
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun 			return ret;
928*4882a593Smuzhiyun 		}
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 		if ((props[i].tbl_id == TBL_ICHG) &&
931*4882a593Smuzhiyun 		    (property > MAX_CHARGECURRETNT)) {
932*4882a593Smuzhiyun 			dev_err(charger->dev, "ti,charge-current is error\n");
933*4882a593Smuzhiyun 			return -ENODEV;
934*4882a593Smuzhiyun 		}
935*4882a593Smuzhiyun 		if ((props[i].tbl_id == TBL_CHGMAX) &&
936*4882a593Smuzhiyun 		    (property > MAX_CHARGEVOLTAGE)) {
937*4882a593Smuzhiyun 			dev_err(charger->dev, "ti,max-charge-voltage is error\n");
938*4882a593Smuzhiyun 			return -ENODEV;
939*4882a593Smuzhiyun 		}
940*4882a593Smuzhiyun 		if ((props[i].tbl_id == TBL_INPUTCUR) &&
941*4882a593Smuzhiyun 		    (property > MAX_INPUTCURRENT)) {
942*4882a593Smuzhiyun 			dev_err(charger->dev, "ti,input-current is error\n");
943*4882a593Smuzhiyun 			return -ENODEV;
944*4882a593Smuzhiyun 		}
945*4882a593Smuzhiyun 		if (props[i].tbl_id == TBL_OTGVOL) {
946*4882a593Smuzhiyun 			if (of_device_is_compatible(charger->dev->of_node,
947*4882a593Smuzhiyun 						    "southchip,sc8886")) {
948*4882a593Smuzhiyun 				bq25700_tables[TBL_OTGVOL].rt = sc8886_otg_range;
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 				if (property < MIN_OTGVOLTAGE) {
951*4882a593Smuzhiyun 					dev_err(charger->dev,
952*4882a593Smuzhiyun 						"ti,otg-voltage is error");
953*4882a593Smuzhiyun 					return -ENODEV;
954*4882a593Smuzhiyun 				}
955*4882a593Smuzhiyun 			}
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun 			if (property > MAX_OTGVOLTAGE) {
958*4882a593Smuzhiyun 				dev_err(charger->dev, "ti,otg-voltage is error\n");
959*4882a593Smuzhiyun 				return -ENODEV;
960*4882a593Smuzhiyun 			};
961*4882a593Smuzhiyun 		}
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 		if ((props[i].tbl_id == TBL_OTGCUR) &&
964*4882a593Smuzhiyun 		    (property > MAX_OTGCURRENT)) {
965*4882a593Smuzhiyun 			dev_err(charger->dev, "ti,otg-current is error\n");
966*4882a593Smuzhiyun 			return -ENODEV;
967*4882a593Smuzhiyun 		}
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 		*props[i].conv_data = bq25700_find_idx(property,
970*4882a593Smuzhiyun 						       props[i].tbl_id);
971*4882a593Smuzhiyun 		DBG("%s, val: %d, tbl_id =%d\n", props[i].name, property,
972*4882a593Smuzhiyun 		    *props[i].conv_data);
973*4882a593Smuzhiyun 	}
974*4882a593Smuzhiyun 
975*4882a593Smuzhiyun 	return 0;
976*4882a593Smuzhiyun }
977*4882a593Smuzhiyun 
bq25700_hw_init(struct bq25700_device * charger)978*4882a593Smuzhiyun static int bq25700_hw_init(struct bq25700_device *charger)
979*4882a593Smuzhiyun {
980*4882a593Smuzhiyun 	int ret;
981*4882a593Smuzhiyun 	int i;
982*4882a593Smuzhiyun 	struct bq25700_state state;
983*4882a593Smuzhiyun 
984*4882a593Smuzhiyun 	const struct {
985*4882a593Smuzhiyun 		enum bq25700_fields id;
986*4882a593Smuzhiyun 		u32 value;
987*4882a593Smuzhiyun 	} init_data[] = {
988*4882a593Smuzhiyun 		{CHARGE_CURRENT,	 charger->init_data.ichg},
989*4882a593Smuzhiyun 		{MAX_CHARGE_VOLTAGE,	 charger->init_data.max_chg_vol},
990*4882a593Smuzhiyun 		{MIN_SYS_VOTAGE,	 charger->init_data.sys_min_voltage},
991*4882a593Smuzhiyun 		{OTG_VOLTAGE,	 charger->init_data.otg_voltage},
992*4882a593Smuzhiyun 		{OTG_CURRENT,	 charger->init_data.otg_current},
993*4882a593Smuzhiyun 	};
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun 	/* disable watchdog */
996*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, WDTWR_ADJ, 0);
997*4882a593Smuzhiyun 	if (ret < 0)
998*4882a593Smuzhiyun 		return ret;
999*4882a593Smuzhiyun 
1000*4882a593Smuzhiyun 	/* initialize currents/voltages and other parameters */
1001*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(init_data); i++) {
1002*4882a593Smuzhiyun 		ret = bq25700_field_write(charger, init_data[i].id,
1003*4882a593Smuzhiyun 					  init_data[i].value);
1004*4882a593Smuzhiyun 		if (ret < 0)
1005*4882a593Smuzhiyun 			return ret;
1006*4882a593Smuzhiyun 	}
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun 	DBG("	 CHARGE_CURRENT: %dmA\n",
1009*4882a593Smuzhiyun 	    bq25700_field_read(charger, CHARGE_CURRENT) * 64);
1010*4882a593Smuzhiyun 	DBG("MAX_CHARGE_VOLTAGE: %dmV\n",
1011*4882a593Smuzhiyun 	    bq25700_field_read(charger, MAX_CHARGE_VOLTAGE) * 16);
1012*4882a593Smuzhiyun 	DBG("	  INPUT_VOLTAGE: %dmV\n",
1013*4882a593Smuzhiyun 	    3200 + bq25700_field_read(charger, INPUT_VOLTAGE) * 64);
1014*4882a593Smuzhiyun 	DBG("	  INPUT_CURRENT: %dmA\n",
1015*4882a593Smuzhiyun 	    bq25700_field_read(charger, INPUT_CURRENT) * 50);
1016*4882a593Smuzhiyun 	DBG("	 MIN_SYS_VOTAGE: %dmV\n",
1017*4882a593Smuzhiyun 	    1024 + bq25700_field_read(charger, MIN_SYS_VOTAGE) * 256);
1018*4882a593Smuzhiyun 
1019*4882a593Smuzhiyun 	/* Configure ADC for continuous conversions. This does not enable it. */
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, EN_LWPWR, 0);
1022*4882a593Smuzhiyun 	if (ret < 0) {
1023*4882a593Smuzhiyun 		DBG("error: EN_LWPWR\n");
1024*4882a593Smuzhiyun 		return ret;
1025*4882a593Smuzhiyun 	}
1026*4882a593Smuzhiyun 
1027*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, ADC_CONV, 1);
1028*4882a593Smuzhiyun 	if (ret < 0) {
1029*4882a593Smuzhiyun 		DBG("error: ADC_CONV\n");
1030*4882a593Smuzhiyun 		return ret;
1031*4882a593Smuzhiyun 	}
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, ADC_START, 1);
1034*4882a593Smuzhiyun 	if (ret < 0) {
1035*4882a593Smuzhiyun 		DBG("error: ADC_START\n");
1036*4882a593Smuzhiyun 		return ret;
1037*4882a593Smuzhiyun 	}
1038*4882a593Smuzhiyun 
1039*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, ADC_FULLSCALE, 1);
1040*4882a593Smuzhiyun 	if (ret < 0) {
1041*4882a593Smuzhiyun 		DBG("error: ADC_FULLSCALE\n");
1042*4882a593Smuzhiyun 		return ret;
1043*4882a593Smuzhiyun 	}
1044*4882a593Smuzhiyun 
1045*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, EN_ADC_CMPIN, 1);
1046*4882a593Smuzhiyun 	if (ret < 0) {
1047*4882a593Smuzhiyun 		DBG("error: EN_ADC_CMPIN\n");
1048*4882a593Smuzhiyun 		return ret;
1049*4882a593Smuzhiyun 	}
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, EN_ADC_VBUS, 1);
1052*4882a593Smuzhiyun 	if (ret < 0) {
1053*4882a593Smuzhiyun 		DBG("error: EN_ADC_VBUS\n");
1054*4882a593Smuzhiyun 		return ret;
1055*4882a593Smuzhiyun 	}
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, EN_ADC_PSYS, 1);
1058*4882a593Smuzhiyun 	if (ret < 0) {
1059*4882a593Smuzhiyun 		DBG("error: EN_ADC_PSYS\n");
1060*4882a593Smuzhiyun 		return ret;
1061*4882a593Smuzhiyun 	}
1062*4882a593Smuzhiyun 
1063*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, EN_ADC_IIN, 1);
1064*4882a593Smuzhiyun 	if (ret < 0) {
1065*4882a593Smuzhiyun 		DBG("error: EN_ADC_IIN\n");
1066*4882a593Smuzhiyun 		return ret;
1067*4882a593Smuzhiyun 	}
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, EN_ADC_IDCHG, 1);
1070*4882a593Smuzhiyun 	if (ret < 0) {
1071*4882a593Smuzhiyun 		DBG("error: EN_ADC_IDCHG\n");
1072*4882a593Smuzhiyun 		return ret;
1073*4882a593Smuzhiyun 	}
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, EN_ADC_ICHG, 1);
1076*4882a593Smuzhiyun 	if (ret < 0) {
1077*4882a593Smuzhiyun 		DBG("error: EN_ADC_ICHG\n");
1078*4882a593Smuzhiyun 		return ret;
1079*4882a593Smuzhiyun 	}
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, EN_ADC_VSYS, 1);
1082*4882a593Smuzhiyun 	if (ret < 0) {
1083*4882a593Smuzhiyun 		DBG("error: EN_ADC_VSYS\n");
1084*4882a593Smuzhiyun 		return ret;
1085*4882a593Smuzhiyun 	}
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 	ret = bq25700_field_write(charger, EN_ADC_VBAT, 1);
1088*4882a593Smuzhiyun 	if (ret < 0) {
1089*4882a593Smuzhiyun 		DBG("error: EN_ADC_VBAT\n");
1090*4882a593Smuzhiyun 		return ret;
1091*4882a593Smuzhiyun 	}
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun 	bq25700_get_chip_state(charger, &state);
1094*4882a593Smuzhiyun 	charger->state = state;
1095*4882a593Smuzhiyun 
1096*4882a593Smuzhiyun 	return 0;
1097*4882a593Smuzhiyun }
1098*4882a593Smuzhiyun 
bq25700_fw_probe(struct bq25700_device * charger)1099*4882a593Smuzhiyun static int bq25700_fw_probe(struct bq25700_device *charger)
1100*4882a593Smuzhiyun {
1101*4882a593Smuzhiyun 	int ret;
1102*4882a593Smuzhiyun 
1103*4882a593Smuzhiyun 	ret = bq25700_fw_read_u32_props(charger);
1104*4882a593Smuzhiyun 	if (ret < 0)
1105*4882a593Smuzhiyun 		return ret;
1106*4882a593Smuzhiyun 
1107*4882a593Smuzhiyun 	return 0;
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun 
bq25700_enable_charger(struct bq25700_device * charger,u32 input_current)1110*4882a593Smuzhiyun static void bq25700_enable_charger(struct bq25700_device *charger,
1111*4882a593Smuzhiyun 				   u32 input_current)
1112*4882a593Smuzhiyun {
1113*4882a593Smuzhiyun 	bq25700_field_write(charger, INPUT_CURRENT, input_current);
1114*4882a593Smuzhiyun 	bq25700_field_write(charger, CHARGE_CURRENT, charger->init_data.ichg);
1115*4882a593Smuzhiyun }
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun static enum power_supply_property bq25700_power_supply_props[] = {
1118*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_MANUFACTURER,
1119*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_STATUS,
1120*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_ONLINE,
1121*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_HEALTH,
1122*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
1123*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
1124*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
1125*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
1126*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
1127*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
1128*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_VOLTAGE_MAX,
1129*4882a593Smuzhiyun 	POWER_SUPPLY_PROP_CURRENT_MAX,
1130*4882a593Smuzhiyun };
1131*4882a593Smuzhiyun 
bq25700_power_supply_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)1132*4882a593Smuzhiyun static int bq25700_power_supply_get_property(struct power_supply *psy,
1133*4882a593Smuzhiyun 					     enum power_supply_property psp,
1134*4882a593Smuzhiyun 					     union power_supply_propval *val)
1135*4882a593Smuzhiyun {
1136*4882a593Smuzhiyun 	int ret;
1137*4882a593Smuzhiyun 	struct bq25700_device *bq = power_supply_get_drvdata(psy);
1138*4882a593Smuzhiyun 	struct bq25700_state state;
1139*4882a593Smuzhiyun 
1140*4882a593Smuzhiyun 	state = bq->state;
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun 	switch (psp) {
1143*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_STATUS:
1144*4882a593Smuzhiyun 		if (!state.ac_stat)
1145*4882a593Smuzhiyun 			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
1146*4882a593Smuzhiyun 		else if (state.in_fchrg == 1 ||
1147*4882a593Smuzhiyun 			 state.in_pchrg == 1)
1148*4882a593Smuzhiyun 			val->intval = POWER_SUPPLY_STATUS_CHARGING;
1149*4882a593Smuzhiyun 		else
1150*4882a593Smuzhiyun 			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
1151*4882a593Smuzhiyun 		break;
1152*4882a593Smuzhiyun 
1153*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_MANUFACTURER:
1154*4882a593Smuzhiyun 		val->strval = BQ25700_MANUFACTURER;
1155*4882a593Smuzhiyun 		break;
1156*4882a593Smuzhiyun 
1157*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_ONLINE:
1158*4882a593Smuzhiyun 		val->intval = state.ac_stat;
1159*4882a593Smuzhiyun 		break;
1160*4882a593Smuzhiyun 
1161*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_HEALTH:
1162*4882a593Smuzhiyun 		if (!state.fault_acoc &&
1163*4882a593Smuzhiyun 		    !state.fault_acov && !state.fault_batoc)
1164*4882a593Smuzhiyun 			val->intval = POWER_SUPPLY_HEALTH_GOOD;
1165*4882a593Smuzhiyun 		else if (state.fault_batoc)
1166*4882a593Smuzhiyun 			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1167*4882a593Smuzhiyun 		break;
1168*4882a593Smuzhiyun 
1169*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
1170*4882a593Smuzhiyun 		/* read measured value */
1171*4882a593Smuzhiyun 		ret = bq25700_field_read(bq, OUTPUT_CHG_CUR);
1172*4882a593Smuzhiyun 		if (ret < 0)
1173*4882a593Smuzhiyun 			return ret;
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun 		/* converted_val = ADC_val * 64mA  */
1176*4882a593Smuzhiyun 		val->intval = ret * 64000;
1177*4882a593Smuzhiyun 		break;
1178*4882a593Smuzhiyun 
1179*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
1180*4882a593Smuzhiyun 		val->intval = bq25700_tables[TBL_ICHG].rt.max;
1181*4882a593Smuzhiyun 		break;
1182*4882a593Smuzhiyun 
1183*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
1184*4882a593Smuzhiyun 		if (!state.ac_stat) {
1185*4882a593Smuzhiyun 			val->intval = 0;
1186*4882a593Smuzhiyun 			break;
1187*4882a593Smuzhiyun 		}
1188*4882a593Smuzhiyun 
1189*4882a593Smuzhiyun 		/* read measured value */
1190*4882a593Smuzhiyun 		ret = bq25700_field_read(bq, OUTPUT_BAT_VOL);
1191*4882a593Smuzhiyun 		if (ret < 0)
1192*4882a593Smuzhiyun 			return ret;
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun 		/* converted_val = 2.88V + ADC_val * 64mV */
1195*4882a593Smuzhiyun 		val->intval = 2880000 + ret * 64000;
1196*4882a593Smuzhiyun 		break;
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
1199*4882a593Smuzhiyun 		val->intval = bq25700_tables[TBL_CHGMAX].rt.max;
1200*4882a593Smuzhiyun 		break;
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
1203*4882a593Smuzhiyun 		val->intval = bq25700_tables[TBL_INPUTVOL].rt.max;
1204*4882a593Smuzhiyun 		break;
1205*4882a593Smuzhiyun 
1206*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
1207*4882a593Smuzhiyun 		val->intval = bq25700_tables[TBL_INPUTCUR].rt.max;
1208*4882a593Smuzhiyun 		break;
1209*4882a593Smuzhiyun 
1210*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
1211*4882a593Smuzhiyun 		ret = bq25700_field_read(bq, MAX_CHARGE_VOLTAGE);
1212*4882a593Smuzhiyun 		val->intval = ret * 16;
1213*4882a593Smuzhiyun 		break;
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun 	case POWER_SUPPLY_PROP_CURRENT_MAX:
1216*4882a593Smuzhiyun 		ret = bq25700_field_read(bq, CHARGE_CURRENT);
1217*4882a593Smuzhiyun 		val->intval = ret * 64;
1218*4882a593Smuzhiyun 		break;
1219*4882a593Smuzhiyun 
1220*4882a593Smuzhiyun 	default:
1221*4882a593Smuzhiyun 		return -EINVAL;
1222*4882a593Smuzhiyun 	}
1223*4882a593Smuzhiyun 
1224*4882a593Smuzhiyun 	return 0;
1225*4882a593Smuzhiyun }
1226*4882a593Smuzhiyun 
1227*4882a593Smuzhiyun static char *bq25700_charger_supplied_to[] = {
1228*4882a593Smuzhiyun 	"charger",
1229*4882a593Smuzhiyun };
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun static const struct power_supply_desc bq25700_power_supply_desc = {
1232*4882a593Smuzhiyun 	.name = "bq25700-charger",
1233*4882a593Smuzhiyun 	.type = POWER_SUPPLY_TYPE_USB,
1234*4882a593Smuzhiyun 	.properties = bq25700_power_supply_props,
1235*4882a593Smuzhiyun 	.num_properties = ARRAY_SIZE(bq25700_power_supply_props),
1236*4882a593Smuzhiyun 	.get_property = bq25700_power_supply_get_property,
1237*4882a593Smuzhiyun };
1238*4882a593Smuzhiyun 
bq25700_power_supply_init(struct bq25700_device * charger)1239*4882a593Smuzhiyun static int bq25700_power_supply_init(struct bq25700_device *charger)
1240*4882a593Smuzhiyun {
1241*4882a593Smuzhiyun 	struct power_supply_config psy_cfg = { .drv_data = charger, };
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun 	psy_cfg.supplied_to = bq25700_charger_supplied_to;
1244*4882a593Smuzhiyun 	psy_cfg.num_supplicants = ARRAY_SIZE(bq25700_charger_supplied_to);
1245*4882a593Smuzhiyun 	psy_cfg.of_node = charger->dev->of_node;
1246*4882a593Smuzhiyun 
1247*4882a593Smuzhiyun 	charger->supply_charger =
1248*4882a593Smuzhiyun 		power_supply_register(charger->dev,
1249*4882a593Smuzhiyun 				      &bq25700_power_supply_desc,
1250*4882a593Smuzhiyun 				      &psy_cfg);
1251*4882a593Smuzhiyun 
1252*4882a593Smuzhiyun 	return PTR_ERR_OR_ZERO(charger->supply_charger);
1253*4882a593Smuzhiyun }
1254*4882a593Smuzhiyun 
1255*4882a593Smuzhiyun static void bq25700_discnt(struct bq25700_device *charger, enum tpyec_port_t port);
1256*4882a593Smuzhiyun 
bq2570x_pd_notifier_call(struct notifier_block * nb,unsigned long val,void * v)1257*4882a593Smuzhiyun static int bq2570x_pd_notifier_call(struct notifier_block *nb,
1258*4882a593Smuzhiyun 		unsigned long val, void *v)
1259*4882a593Smuzhiyun {
1260*4882a593Smuzhiyun 	struct bq25700_device *bq =
1261*4882a593Smuzhiyun 		container_of(nb, struct bq25700_device, nb);
1262*4882a593Smuzhiyun 	struct power_supply *psy = v;
1263*4882a593Smuzhiyun 	union power_supply_propval prop;
1264*4882a593Smuzhiyun 	struct bq25700_state state;
1265*4882a593Smuzhiyun 	int ret;
1266*4882a593Smuzhiyun 	int vol_idx, cur_idx, chr_idx;
1267*4882a593Smuzhiyun 
1268*4882a593Smuzhiyun 	if (val != PSY_EVENT_PROP_CHANGED)
1269*4882a593Smuzhiyun 		return NOTIFY_OK;
1270*4882a593Smuzhiyun 
1271*4882a593Smuzhiyun 	/* Ignore event if it was not send by notify_node/notify_device */
1272*4882a593Smuzhiyun 	if (bq->notify_node) {
1273*4882a593Smuzhiyun 		if (!psy->dev.parent ||
1274*4882a593Smuzhiyun 		    psy->dev.parent->of_node != bq->notify_node)
1275*4882a593Smuzhiyun 			return NOTIFY_OK;
1276*4882a593Smuzhiyun 	} else if (bq->plat_data.notify_device) {
1277*4882a593Smuzhiyun 		if (strcmp(psy->desc->name, bq->plat_data.notify_device) != 0)
1278*4882a593Smuzhiyun 			return NOTIFY_OK;
1279*4882a593Smuzhiyun 	}
1280*4882a593Smuzhiyun 
1281*4882a593Smuzhiyun 	ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE, &prop);
1282*4882a593Smuzhiyun 	if (ret != 0)
1283*4882a593Smuzhiyun 		return NOTIFY_OK;
1284*4882a593Smuzhiyun 	/* online=0: USB out */
1285*4882a593Smuzhiyun 	if (prop.intval == 0) {
1286*4882a593Smuzhiyun 		queue_delayed_work(bq->usb_charger_wq, &bq->discnt_work,
1287*4882a593Smuzhiyun 				   msecs_to_jiffies(10));
1288*4882a593Smuzhiyun 		return NOTIFY_OK;
1289*4882a593Smuzhiyun 	}
1290*4882a593Smuzhiyun 
1291*4882a593Smuzhiyun 	ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &prop);
1292*4882a593Smuzhiyun 	if (ret != 0)
1293*4882a593Smuzhiyun 		return NOTIFY_OK;
1294*4882a593Smuzhiyun 	if (prop.intval > 0) {
1295*4882a593Smuzhiyun 		cur_idx = bq25700_find_idx(prop.intval, TBL_INPUTCUR);
1296*4882a593Smuzhiyun 		ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,
1297*4882a593Smuzhiyun 						&prop);
1298*4882a593Smuzhiyun 		if (ret != 0)
1299*4882a593Smuzhiyun 			return NOTIFY_OK;
1300*4882a593Smuzhiyun 		vol_idx = bq25700_find_idx((prop.intval - 1280000 - 3200000), TBL_INPUTVOL);
1301*4882a593Smuzhiyun 		ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW,
1302*4882a593Smuzhiyun 						&prop);
1303*4882a593Smuzhiyun 		if (ret != 0)
1304*4882a593Smuzhiyun 			return NOTIFY_OK;
1305*4882a593Smuzhiyun 		chr_idx = bq25700_find_idx(prop.intval, TBL_ICHG);
1306*4882a593Smuzhiyun 
1307*4882a593Smuzhiyun 		bq25700_field_write(bq, INPUT_CURRENT, cur_idx);
1308*4882a593Smuzhiyun 		bq25700_field_write(bq, INPUT_VOLTAGE, vol_idx);
1309*4882a593Smuzhiyun 		bq25700_field_write(bq, CHARGE_CURRENT, chr_idx);
1310*4882a593Smuzhiyun 		dev_info(bq->dev, "INPUT_CURRENT:%d, INPUT_VOLTAGE:%d, CHARGE_CURRENT:%d\n",
1311*4882a593Smuzhiyun 			 cur_idx, vol_idx, chr_idx);
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun 		bq25700_get_chip_state(bq, &state);
1314*4882a593Smuzhiyun 		bq->state = state;
1315*4882a593Smuzhiyun 		power_supply_changed(bq->supply_charger);
1316*4882a593Smuzhiyun 	}
1317*4882a593Smuzhiyun 	return NOTIFY_OK;
1318*4882a593Smuzhiyun }
1319*4882a593Smuzhiyun 
bq25700_irq_handler_thread(int irq,void * private)1320*4882a593Smuzhiyun static irqreturn_t bq25700_irq_handler_thread(int irq, void *private)
1321*4882a593Smuzhiyun {
1322*4882a593Smuzhiyun 	struct bq25700_device *charger = private;
1323*4882a593Smuzhiyun 	int irq_flag;
1324*4882a593Smuzhiyun 	struct bq25700_state state;
1325*4882a593Smuzhiyun 
1326*4882a593Smuzhiyun 	if (bq25700_field_read(charger, AC_STAT)) {
1327*4882a593Smuzhiyun 		irq_flag = IRQF_TRIGGER_LOW;
1328*4882a593Smuzhiyun 	} else {
1329*4882a593Smuzhiyun 		irq_flag = IRQF_TRIGGER_HIGH;
1330*4882a593Smuzhiyun 		bq25700_field_write(charger, INPUT_CURRENT,
1331*4882a593Smuzhiyun 				    charger->init_data.input_current_sdp);
1332*4882a593Smuzhiyun 		bq25700_disable_charge(charger);
1333*4882a593Smuzhiyun 		bq25700_get_chip_state(charger, &state);
1334*4882a593Smuzhiyun 		charger->state = state;
1335*4882a593Smuzhiyun 		power_supply_changed(charger->supply_charger);
1336*4882a593Smuzhiyun 		charger->typec0_status = USB_STATUS_NONE;
1337*4882a593Smuzhiyun 		charger->typec1_status = USB_STATUS_NONE;
1338*4882a593Smuzhiyun 	}
1339*4882a593Smuzhiyun 	irq_set_irq_type(irq, irq_flag | IRQF_ONESHOT);
1340*4882a593Smuzhiyun 
1341*4882a593Smuzhiyun 	return IRQ_HANDLED;
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun 
bq25700_enable_typec0(struct bq25700_device * charger)1344*4882a593Smuzhiyun static void bq25700_enable_typec0(struct bq25700_device *charger)
1345*4882a593Smuzhiyun {
1346*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec0_enable_io))
1347*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec0_enable_io, 1);
1348*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec1_enable_io))
1349*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec1_enable_io, 0);
1350*4882a593Smuzhiyun }
1351*4882a593Smuzhiyun 
bq25700_enable_typec1(struct bq25700_device * charger)1352*4882a593Smuzhiyun static void bq25700_enable_typec1(struct bq25700_device *charger)
1353*4882a593Smuzhiyun {
1354*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec0_enable_io))
1355*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec0_enable_io, 0);
1356*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec1_enable_io))
1357*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec1_enable_io, 1);
1358*4882a593Smuzhiyun }
1359*4882a593Smuzhiyun 
bq25700_disable_charge(struct bq25700_device * charger)1360*4882a593Smuzhiyun static void bq25700_disable_charge(struct bq25700_device *charger)
1361*4882a593Smuzhiyun {
1362*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec0_enable_io))
1363*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec0_enable_io, 0);
1364*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec1_enable_io))
1365*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec1_enable_io, 0);
1366*4882a593Smuzhiyun }
1367*4882a593Smuzhiyun 
bq25700_typec0_discharge(struct bq25700_device * charger)1368*4882a593Smuzhiyun static void bq25700_typec0_discharge(struct bq25700_device *charger)
1369*4882a593Smuzhiyun {
1370*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec0_discharge_io))
1371*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec0_discharge_io, 1);
1372*4882a593Smuzhiyun 	msleep(20);
1373*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec0_discharge_io))
1374*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec0_discharge_io, 0);
1375*4882a593Smuzhiyun }
1376*4882a593Smuzhiyun 
bq25700_typec1_discharge(struct bq25700_device * charger)1377*4882a593Smuzhiyun static void bq25700_typec1_discharge(struct bq25700_device *charger)
1378*4882a593Smuzhiyun {
1379*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec1_discharge_io))
1380*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec1_discharge_io, 1);
1381*4882a593Smuzhiyun 	msleep(20);
1382*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec1_discharge_io))
1383*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec1_discharge_io, 0);
1384*4882a593Smuzhiyun }
1385*4882a593Smuzhiyun 
bq25700_charger_evt_handel(struct bq25700_device * charger,struct extcon_dev * edev,enum tpyec_port_t port)1386*4882a593Smuzhiyun static void bq25700_charger_evt_handel(struct bq25700_device *charger,
1387*4882a593Smuzhiyun 				       struct extcon_dev *edev,
1388*4882a593Smuzhiyun 				       enum tpyec_port_t port)
1389*4882a593Smuzhiyun {
1390*4882a593Smuzhiyun 	struct bq25700_state state;
1391*4882a593Smuzhiyun 	enum charger_t charger_state = USB_TYPE_UNKNOWN_CHARGER;
1392*4882a593Smuzhiyun 
1393*4882a593Smuzhiyun 	if (charger->typec0_status == USB_STATUS_PD ||
1394*4882a593Smuzhiyun 	    charger->typec1_status == USB_STATUS_PD)
1395*4882a593Smuzhiyun 		return;
1396*4882a593Smuzhiyun 
1397*4882a593Smuzhiyun 	/* Determine cable/charger type */
1398*4882a593Smuzhiyun 	if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
1399*4882a593Smuzhiyun 		charger_state = USB_TYPE_USB_CHARGER;
1400*4882a593Smuzhiyun 
1401*4882a593Smuzhiyun 		bq25700_enable_charger(charger,
1402*4882a593Smuzhiyun 				       charger->init_data.input_current_sdp);
1403*4882a593Smuzhiyun 		DBG("USB_TYPE_USB_CHARGER\n");
1404*4882a593Smuzhiyun 	} else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {
1405*4882a593Smuzhiyun 		charger_state = USB_TYPE_AC_CHARGER;
1406*4882a593Smuzhiyun 		bq25700_enable_charger(charger,
1407*4882a593Smuzhiyun 				       charger->init_data.input_current_dcp);
1408*4882a593Smuzhiyun 		DBG("USB_TYPE_AC_CHARGER\n");
1409*4882a593Smuzhiyun 	} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
1410*4882a593Smuzhiyun 		charger_state = USB_TYPE_CDP_CHARGER;
1411*4882a593Smuzhiyun 		bq25700_enable_charger(charger,
1412*4882a593Smuzhiyun 				       charger->init_data.input_current_cdp);
1413*4882a593Smuzhiyun 		DBG("USB_TYPE_CDP_CHARGER\n");
1414*4882a593Smuzhiyun 	}
1415*4882a593Smuzhiyun 	if (port == USB_TYPEC_0) {
1416*4882a593Smuzhiyun 		if (charger_state == USB_TYPE_USB_CHARGER)
1417*4882a593Smuzhiyun 			charger->typec0_status = USB_STATUS_USB;
1418*4882a593Smuzhiyun 		else
1419*4882a593Smuzhiyun 			charger->typec0_status = USB_STATUS_AC;
1420*4882a593Smuzhiyun 		bq25700_enable_typec0(charger);
1421*4882a593Smuzhiyun 	} else {
1422*4882a593Smuzhiyun 		if (charger_state == USB_TYPE_USB_CHARGER)
1423*4882a593Smuzhiyun 			charger->typec1_status = USB_STATUS_USB;
1424*4882a593Smuzhiyun 		else
1425*4882a593Smuzhiyun 			charger->typec1_status = USB_STATUS_AC;
1426*4882a593Smuzhiyun 		bq25700_enable_typec1(charger);
1427*4882a593Smuzhiyun 	}
1428*4882a593Smuzhiyun 
1429*4882a593Smuzhiyun 	bq25700_get_chip_state(charger, &state);
1430*4882a593Smuzhiyun 	charger->state = state;
1431*4882a593Smuzhiyun 	power_supply_changed(charger->supply_charger);
1432*4882a593Smuzhiyun }
1433*4882a593Smuzhiyun 
bq25700_charger_usb_bc_handel(struct bq25700_device * charger)1434*4882a593Smuzhiyun static void bq25700_charger_usb_bc_handel(struct bq25700_device *charger)
1435*4882a593Smuzhiyun {
1436*4882a593Smuzhiyun 	struct bq25700_state state;
1437*4882a593Smuzhiyun 
1438*4882a593Smuzhiyun 	switch (charger->bc_event) {
1439*4882a593Smuzhiyun 	case USB_BC_TYPE_SDP:
1440*4882a593Smuzhiyun 		bq25700_enable_charger(charger,
1441*4882a593Smuzhiyun 				       charger->init_data.input_current_sdp);
1442*4882a593Smuzhiyun 		DBG("USB_TYPE_USB_CHARGER\n");
1443*4882a593Smuzhiyun 		break;
1444*4882a593Smuzhiyun 	case USB_BC_TYPE_DCP:
1445*4882a593Smuzhiyun 		bq25700_enable_charger(charger,
1446*4882a593Smuzhiyun 				       charger->init_data.input_current_dcp);
1447*4882a593Smuzhiyun 		break;
1448*4882a593Smuzhiyun 	case USB_BC_TYPE_CDP:
1449*4882a593Smuzhiyun 		bq25700_enable_charger(charger,
1450*4882a593Smuzhiyun 				       charger->init_data.input_current_cdp);
1451*4882a593Smuzhiyun 		DBG("USB_TYPE_CDP_CHARGER\n");
1452*4882a593Smuzhiyun 		break;
1453*4882a593Smuzhiyun 	default:
1454*4882a593Smuzhiyun 		break;
1455*4882a593Smuzhiyun 	}
1456*4882a593Smuzhiyun 	bq25700_get_chip_state(charger, &state);
1457*4882a593Smuzhiyun 	charger->state = state;
1458*4882a593Smuzhiyun 	power_supply_changed(charger->supply_charger);
1459*4882a593Smuzhiyun }
1460*4882a593Smuzhiyun 
bq25700_charger_evt_worker(struct work_struct * work)1461*4882a593Smuzhiyun static void bq25700_charger_evt_worker(struct work_struct *work)
1462*4882a593Smuzhiyun {
1463*4882a593Smuzhiyun 	struct bq25700_device *charger = container_of(work,
1464*4882a593Smuzhiyun 				struct bq25700_device, usb_work.work);
1465*4882a593Smuzhiyun 	struct extcon_dev *edev = charger->cable_edev;
1466*4882a593Smuzhiyun 
1467*4882a593Smuzhiyun 	if (charger->usb_bc == 0)
1468*4882a593Smuzhiyun 		bq25700_charger_evt_handel(charger, edev, USB_TYPEC_0);
1469*4882a593Smuzhiyun 	else
1470*4882a593Smuzhiyun 		bq25700_charger_usb_bc_handel(charger);
1471*4882a593Smuzhiyun }
1472*4882a593Smuzhiyun 
bq25700_charger_evt_worker1(struct work_struct * work)1473*4882a593Smuzhiyun static void bq25700_charger_evt_worker1(struct work_struct *work)
1474*4882a593Smuzhiyun {
1475*4882a593Smuzhiyun 	struct bq25700_device *charger = container_of(work,
1476*4882a593Smuzhiyun 				struct bq25700_device, usb_work1.work);
1477*4882a593Smuzhiyun 	struct extcon_dev *edev = charger->cable_edev_1;
1478*4882a593Smuzhiyun 
1479*4882a593Smuzhiyun 	bq25700_charger_evt_handel(charger, edev, USB_TYPEC_1);
1480*4882a593Smuzhiyun }
1481*4882a593Smuzhiyun 
bq25700_charger_evt_notifier(struct notifier_block * nb,unsigned long event,void * ptr)1482*4882a593Smuzhiyun static int bq25700_charger_evt_notifier(struct notifier_block *nb,
1483*4882a593Smuzhiyun 					unsigned long event,
1484*4882a593Smuzhiyun 					void *ptr)
1485*4882a593Smuzhiyun {
1486*4882a593Smuzhiyun 	struct bq25700_device *charger =
1487*4882a593Smuzhiyun 		container_of(nb, struct bq25700_device, cable_cg_nb);
1488*4882a593Smuzhiyun 	charger->bc_event = event;
1489*4882a593Smuzhiyun 	queue_delayed_work(charger->usb_charger_wq, &charger->usb_work,
1490*4882a593Smuzhiyun 			   msecs_to_jiffies(10));
1491*4882a593Smuzhiyun 
1492*4882a593Smuzhiyun 	return NOTIFY_DONE;
1493*4882a593Smuzhiyun }
1494*4882a593Smuzhiyun 
bq25700_charger_evt_notifier1(struct notifier_block * nb,unsigned long event,void * ptr)1495*4882a593Smuzhiyun static int bq25700_charger_evt_notifier1(struct notifier_block *nb,
1496*4882a593Smuzhiyun 					 unsigned long event,
1497*4882a593Smuzhiyun 					 void *ptr)
1498*4882a593Smuzhiyun {
1499*4882a593Smuzhiyun 	struct bq25700_device *charger =
1500*4882a593Smuzhiyun 		container_of(nb, struct bq25700_device, cable_cg_nb1);
1501*4882a593Smuzhiyun 
1502*4882a593Smuzhiyun 	queue_delayed_work(charger->usb_charger_wq, &charger->usb_work1,
1503*4882a593Smuzhiyun 			   msecs_to_jiffies(10));
1504*4882a593Smuzhiyun 
1505*4882a593Smuzhiyun 	return NOTIFY_DONE;
1506*4882a593Smuzhiyun }
1507*4882a593Smuzhiyun 
bq25700_set_otg_vbus(struct bq25700_device * charger,bool enable)1508*4882a593Smuzhiyun static void bq25700_set_otg_vbus(struct bq25700_device *charger, bool enable)
1509*4882a593Smuzhiyun {
1510*4882a593Smuzhiyun 	DBG("OTG %s\n", enable ? "enable" : "disable");
1511*4882a593Smuzhiyun 
1512*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->otg_mode_en_io))
1513*4882a593Smuzhiyun 		gpiod_direction_output(charger->otg_mode_en_io, enable);
1514*4882a593Smuzhiyun 	bq25700_field_write(charger, EN_OTG, enable);
1515*4882a593Smuzhiyun }
1516*4882a593Smuzhiyun 
bq25700_host_evt_worker(struct work_struct * work)1517*4882a593Smuzhiyun static void bq25700_host_evt_worker(struct work_struct *work)
1518*4882a593Smuzhiyun {
1519*4882a593Smuzhiyun 	struct bq25700_device *charger =
1520*4882a593Smuzhiyun 		container_of(work, struct bq25700_device, host_work.work);
1521*4882a593Smuzhiyun 	struct extcon_dev *edev = charger->cable_edev;
1522*4882a593Smuzhiyun 
1523*4882a593Smuzhiyun 	if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) > 0)
1524*4882a593Smuzhiyun 		bq25700_set_otg_vbus(charger, true);
1525*4882a593Smuzhiyun 	else if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) == 0)
1526*4882a593Smuzhiyun 		bq25700_set_otg_vbus(charger, false);
1527*4882a593Smuzhiyun }
1528*4882a593Smuzhiyun 
bq25700_host_evt_worker1(struct work_struct * work)1529*4882a593Smuzhiyun static void bq25700_host_evt_worker1(struct work_struct *work)
1530*4882a593Smuzhiyun {
1531*4882a593Smuzhiyun 	struct bq25700_device *charger =
1532*4882a593Smuzhiyun 		container_of(work, struct bq25700_device, host_work1.work);
1533*4882a593Smuzhiyun 	struct extcon_dev *edev = charger->cable_edev_1;
1534*4882a593Smuzhiyun 
1535*4882a593Smuzhiyun 	if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) > 0)
1536*4882a593Smuzhiyun 		bq25700_set_otg_vbus(charger, true);
1537*4882a593Smuzhiyun 	else if (extcon_get_state(edev, EXTCON_USB_VBUS_EN) == 0)
1538*4882a593Smuzhiyun 		bq25700_set_otg_vbus(charger, false);
1539*4882a593Smuzhiyun }
1540*4882a593Smuzhiyun 
bq25700_host_evt_notifier(struct notifier_block * nb,unsigned long event,void * ptr)1541*4882a593Smuzhiyun static int bq25700_host_evt_notifier(struct notifier_block *nb,
1542*4882a593Smuzhiyun 				     unsigned long event, void *ptr)
1543*4882a593Smuzhiyun {
1544*4882a593Smuzhiyun 	struct bq25700_device *charger =
1545*4882a593Smuzhiyun 		container_of(nb, struct bq25700_device, cable_host_nb);
1546*4882a593Smuzhiyun 
1547*4882a593Smuzhiyun 	queue_delayed_work(charger->usb_charger_wq, &charger->host_work,
1548*4882a593Smuzhiyun 			   msecs_to_jiffies(10));
1549*4882a593Smuzhiyun 
1550*4882a593Smuzhiyun 	return NOTIFY_DONE;
1551*4882a593Smuzhiyun }
1552*4882a593Smuzhiyun 
bq25700_host_evt_notifier1(struct notifier_block * nb,unsigned long event,void * ptr)1553*4882a593Smuzhiyun static int bq25700_host_evt_notifier1(struct notifier_block *nb,
1554*4882a593Smuzhiyun 				      unsigned long event, void *ptr)
1555*4882a593Smuzhiyun {
1556*4882a593Smuzhiyun 	struct bq25700_device *charger =
1557*4882a593Smuzhiyun 		container_of(nb, struct bq25700_device, cable_host_nb1);
1558*4882a593Smuzhiyun 
1559*4882a593Smuzhiyun 	queue_delayed_work(charger->usb_charger_wq, &charger->host_work1,
1560*4882a593Smuzhiyun 			   msecs_to_jiffies(10));
1561*4882a593Smuzhiyun 
1562*4882a593Smuzhiyun 	return NOTIFY_DONE;
1563*4882a593Smuzhiyun }
1564*4882a593Smuzhiyun 
bq25700_discnt(struct bq25700_device * charger,enum tpyec_port_t port)1565*4882a593Smuzhiyun static void bq25700_discnt(struct bq25700_device *charger,
1566*4882a593Smuzhiyun 			   enum tpyec_port_t port)
1567*4882a593Smuzhiyun {
1568*4882a593Smuzhiyun 	int vol_idx;
1569*4882a593Smuzhiyun 	struct bq25700_state state;
1570*4882a593Smuzhiyun 
1571*4882a593Smuzhiyun 	if (bq25700_field_read(charger, AC_STAT) == 0) {
1572*4882a593Smuzhiyun 		bq25700_disable_charge(charger);
1573*4882a593Smuzhiyun 		if (port == USB_TYPEC_0) {
1574*4882a593Smuzhiyun 			bq25700_typec0_discharge(charger);
1575*4882a593Smuzhiyun 			charger->typec0_status = USB_STATUS_NONE;
1576*4882a593Smuzhiyun 		} else {
1577*4882a593Smuzhiyun 			bq25700_typec1_discharge(charger);
1578*4882a593Smuzhiyun 			charger->typec1_status = USB_STATUS_NONE;
1579*4882a593Smuzhiyun 		}
1580*4882a593Smuzhiyun 
1581*4882a593Smuzhiyun 		vol_idx = bq25700_find_idx(DEFAULT_INPUTVOL, TBL_INPUTVOL);
1582*4882a593Smuzhiyun 		bq25700_field_write(charger, INPUT_VOLTAGE, vol_idx);
1583*4882a593Smuzhiyun 		bq25700_field_write(charger, INPUT_CURRENT,
1584*4882a593Smuzhiyun 				    charger->init_data.input_current_sdp);
1585*4882a593Smuzhiyun 		bq25700_get_chip_state(charger, &state);
1586*4882a593Smuzhiyun 		charger->state = state;
1587*4882a593Smuzhiyun 		power_supply_changed(charger->supply_charger);
1588*4882a593Smuzhiyun 	}
1589*4882a593Smuzhiyun }
1590*4882a593Smuzhiyun 
bq25700_discnt_evt_worker(struct work_struct * work)1591*4882a593Smuzhiyun static void bq25700_discnt_evt_worker(struct work_struct *work)
1592*4882a593Smuzhiyun {
1593*4882a593Smuzhiyun 	struct bq25700_device *charger = container_of(work,
1594*4882a593Smuzhiyun 						      struct bq25700_device,
1595*4882a593Smuzhiyun 						      discnt_work.work);
1596*4882a593Smuzhiyun 
1597*4882a593Smuzhiyun 	bq25700_discnt(charger, USB_TYPEC_0);
1598*4882a593Smuzhiyun }
1599*4882a593Smuzhiyun 
bq25700_register_cg_extcon(struct bq25700_device * charger,struct extcon_dev * edev,struct notifier_block * able_cg_nb)1600*4882a593Smuzhiyun static int bq25700_register_cg_extcon(struct bq25700_device *charger,
1601*4882a593Smuzhiyun 				      struct extcon_dev *edev,
1602*4882a593Smuzhiyun 				      struct notifier_block *able_cg_nb)
1603*4882a593Smuzhiyun {
1604*4882a593Smuzhiyun 	int ret;
1605*4882a593Smuzhiyun 
1606*4882a593Smuzhiyun 	ret = extcon_register_notifier(edev,
1607*4882a593Smuzhiyun 				       EXTCON_CHG_USB_SDP,
1608*4882a593Smuzhiyun 				       able_cg_nb);
1609*4882a593Smuzhiyun 	if (ret < 0) {
1610*4882a593Smuzhiyun 		dev_err(charger->dev, "failed to register notifier for SDP\n");
1611*4882a593Smuzhiyun 		return -1;
1612*4882a593Smuzhiyun 	}
1613*4882a593Smuzhiyun 
1614*4882a593Smuzhiyun 	ret = extcon_register_notifier(edev,
1615*4882a593Smuzhiyun 				       EXTCON_CHG_USB_DCP,
1616*4882a593Smuzhiyun 				       able_cg_nb);
1617*4882a593Smuzhiyun 	if (ret < 0) {
1618*4882a593Smuzhiyun 		dev_err(charger->dev, "failed to register notifier for DCP\n");
1619*4882a593Smuzhiyun 		return -1;
1620*4882a593Smuzhiyun 	}
1621*4882a593Smuzhiyun 
1622*4882a593Smuzhiyun 	ret = extcon_register_notifier(edev,
1623*4882a593Smuzhiyun 				       EXTCON_CHG_USB_CDP,
1624*4882a593Smuzhiyun 				       able_cg_nb);
1625*4882a593Smuzhiyun 	if (ret < 0) {
1626*4882a593Smuzhiyun 		dev_err(charger->dev, "failed to register notifier for CDP\n");
1627*4882a593Smuzhiyun 		return -1;
1628*4882a593Smuzhiyun 	}
1629*4882a593Smuzhiyun 
1630*4882a593Smuzhiyun 	return 0;
1631*4882a593Smuzhiyun }
1632*4882a593Smuzhiyun 
bq25700_register_cg_nb(struct bq25700_device * charger)1633*4882a593Smuzhiyun static int bq25700_register_cg_nb(struct bq25700_device *charger)
1634*4882a593Smuzhiyun {
1635*4882a593Smuzhiyun 	enum bc_port_type bc_type;
1636*4882a593Smuzhiyun 	int ret;
1637*4882a593Smuzhiyun 
1638*4882a593Smuzhiyun 	if (charger->usb_bc == 0) {
1639*4882a593Smuzhiyun 		if (charger->cable_edev) {
1640*4882a593Smuzhiyun 			/* Register chargers  */
1641*4882a593Smuzhiyun 			INIT_DELAYED_WORK(&charger->usb_work,
1642*4882a593Smuzhiyun 					  bq25700_charger_evt_worker);
1643*4882a593Smuzhiyun 			charger->cable_cg_nb.notifier_call =
1644*4882a593Smuzhiyun 				bq25700_charger_evt_notifier;
1645*4882a593Smuzhiyun 			bq25700_register_cg_extcon(charger, charger->cable_edev,
1646*4882a593Smuzhiyun 						   &charger->cable_cg_nb);
1647*4882a593Smuzhiyun 		}
1648*4882a593Smuzhiyun 
1649*4882a593Smuzhiyun 		if (charger->cable_edev_1) {
1650*4882a593Smuzhiyun 			INIT_DELAYED_WORK(&charger->usb_work1,
1651*4882a593Smuzhiyun 					  bq25700_charger_evt_worker1);
1652*4882a593Smuzhiyun 			charger->cable_cg_nb1.notifier_call =
1653*4882a593Smuzhiyun 				bq25700_charger_evt_notifier1;
1654*4882a593Smuzhiyun 			bq25700_register_cg_extcon(charger,
1655*4882a593Smuzhiyun 						   charger->cable_edev_1,
1656*4882a593Smuzhiyun 						   &charger->cable_cg_nb1);
1657*4882a593Smuzhiyun 		}
1658*4882a593Smuzhiyun 	} else {
1659*4882a593Smuzhiyun 		INIT_DELAYED_WORK(&charger->usb_work,
1660*4882a593Smuzhiyun 				  bq25700_charger_evt_worker);
1661*4882a593Smuzhiyun 		charger->cable_cg_nb.notifier_call =
1662*4882a593Smuzhiyun 			bq25700_charger_evt_notifier;
1663*4882a593Smuzhiyun 
1664*4882a593Smuzhiyun 		ret = rk_bc_detect_notifier_register(&charger->cable_cg_nb,
1665*4882a593Smuzhiyun 						     &bc_type);
1666*4882a593Smuzhiyun 		if (ret) {
1667*4882a593Smuzhiyun 			dev_err(charger->dev, "failed to register notifier for bc\n");
1668*4882a593Smuzhiyun 			return -EINVAL;
1669*4882a593Smuzhiyun 		}
1670*4882a593Smuzhiyun 	}
1671*4882a593Smuzhiyun 	return 0;
1672*4882a593Smuzhiyun }
1673*4882a593Smuzhiyun 
bq25700_register_pd_nb(struct bq25700_device * charger)1674*4882a593Smuzhiyun static int bq25700_register_pd_nb(struct bq25700_device *charger)
1675*4882a593Smuzhiyun {
1676*4882a593Smuzhiyun 	struct power_supply *notify_psy = NULL;
1677*4882a593Smuzhiyun 	int vol_idx, cur_idx;
1678*4882a593Smuzhiyun 	int ret;
1679*4882a593Smuzhiyun 	union power_supply_propval prop;
1680*4882a593Smuzhiyun 
1681*4882a593Smuzhiyun 	if (charger->notify_node || charger->plat_data.notify_device) {
1682*4882a593Smuzhiyun 		INIT_DELAYED_WORK(&charger->discnt_work,
1683*4882a593Smuzhiyun 				  bq25700_discnt_evt_worker);
1684*4882a593Smuzhiyun 		charger->nb.notifier_call = bq2570x_pd_notifier_call;
1685*4882a593Smuzhiyun 		ret = power_supply_reg_notifier(&charger->nb);
1686*4882a593Smuzhiyun 		if (ret) {
1687*4882a593Smuzhiyun 			dev_err(charger->dev, "failed to reg notifier: %d\n", ret);
1688*4882a593Smuzhiyun 			return ret;
1689*4882a593Smuzhiyun 		}
1690*4882a593Smuzhiyun 		charger->automode = 1;
1691*4882a593Smuzhiyun 		dev_info(charger->dev, "automode supported, waiting for events\n");
1692*4882a593Smuzhiyun 	} else {
1693*4882a593Smuzhiyun 		charger->automode = -1;
1694*4882a593Smuzhiyun 		dev_info(charger->dev, "automode not supported\n");
1695*4882a593Smuzhiyun 	}
1696*4882a593Smuzhiyun 
1697*4882a593Smuzhiyun 	if (charger->nb.notifier_call) {
1698*4882a593Smuzhiyun 		if (charger->dev->of_node) {
1699*4882a593Smuzhiyun 			notify_psy = power_supply_get_by_phandle(charger->dev->of_node,
1700*4882a593Smuzhiyun 							"ti,usb-charger-detection");
1701*4882a593Smuzhiyun 			if (IS_ERR_OR_NULL(notify_psy)) {
1702*4882a593Smuzhiyun 				dev_info(charger->dev, "bq25700 notify_psy is error\n");
1703*4882a593Smuzhiyun 				notify_psy = NULL;
1704*4882a593Smuzhiyun 			}
1705*4882a593Smuzhiyun 		} else if (charger->plat_data.notify_device) {
1706*4882a593Smuzhiyun 			notify_psy = power_supply_get_by_name(
1707*4882a593Smuzhiyun 						charger->plat_data.notify_device);
1708*4882a593Smuzhiyun 		}
1709*4882a593Smuzhiyun 	}
1710*4882a593Smuzhiyun 
1711*4882a593Smuzhiyun 	if (notify_psy) {
1712*4882a593Smuzhiyun 		ret = power_supply_get_property(notify_psy,
1713*4882a593Smuzhiyun 					POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
1714*4882a593Smuzhiyun 		if (ret != 0)
1715*4882a593Smuzhiyun 			return ret;
1716*4882a593Smuzhiyun 		ret = power_supply_get_property(notify_psy,
1717*4882a593Smuzhiyun 					POWER_SUPPLY_PROP_VOLTAGE_MAX, &prop);
1718*4882a593Smuzhiyun 		if (ret != 0)
1719*4882a593Smuzhiyun 			return ret;
1720*4882a593Smuzhiyun 
1721*4882a593Smuzhiyun 		cur_idx = bq25700_find_idx(prop.intval, TBL_INPUTCUR);
1722*4882a593Smuzhiyun 		vol_idx = bq25700_find_idx((prop.intval - 1280000 - 3200000), TBL_INPUTVOL);
1723*4882a593Smuzhiyun 		bq25700_field_write(charger, INPUT_CURRENT, cur_idx);
1724*4882a593Smuzhiyun 		bq25700_field_write(charger, INPUT_VOLTAGE, vol_idx);
1725*4882a593Smuzhiyun 		bq25700_field_write(charger, CHARGE_CURRENT,
1726*4882a593Smuzhiyun 				    charger->init_data.ichg);
1727*4882a593Smuzhiyun 		dev_info(charger->dev, "INPUT_CURRENT:%d, INPUT_VOLTAGE:%d, CHARGE_CURRENT:%d\n",
1728*4882a593Smuzhiyun 				 cur_idx, vol_idx, charger->init_data.ichg);
1729*4882a593Smuzhiyun 	}
1730*4882a593Smuzhiyun 
1731*4882a593Smuzhiyun 	return 0;
1732*4882a593Smuzhiyun }
1733*4882a593Smuzhiyun 
bq25700_register_host_nb(struct bq25700_device * charger)1734*4882a593Smuzhiyun static int bq25700_register_host_nb(struct bq25700_device *charger)
1735*4882a593Smuzhiyun {
1736*4882a593Smuzhiyun 	int ret;
1737*4882a593Smuzhiyun 
1738*4882a593Smuzhiyun 	/* Register host */
1739*4882a593Smuzhiyun 	if (charger->cable_edev) {
1740*4882a593Smuzhiyun 		INIT_DELAYED_WORK(&charger->host_work, bq25700_host_evt_worker);
1741*4882a593Smuzhiyun 		charger->cable_host_nb.notifier_call =
1742*4882a593Smuzhiyun 			bq25700_host_evt_notifier;
1743*4882a593Smuzhiyun 		ret = extcon_register_notifier(charger->cable_edev,
1744*4882a593Smuzhiyun 					       EXTCON_USB_VBUS_EN,
1745*4882a593Smuzhiyun 					       &charger->cable_host_nb);
1746*4882a593Smuzhiyun 		if (ret < 0) {
1747*4882a593Smuzhiyun 			dev_err(charger->dev,
1748*4882a593Smuzhiyun 				"failed to register notifier for HOST\n");
1749*4882a593Smuzhiyun 			return -1;
1750*4882a593Smuzhiyun 		}
1751*4882a593Smuzhiyun 	}
1752*4882a593Smuzhiyun 
1753*4882a593Smuzhiyun 	if (charger->cable_edev_1) {
1754*4882a593Smuzhiyun 		INIT_DELAYED_WORK(&charger->host_work1,
1755*4882a593Smuzhiyun 				  bq25700_host_evt_worker1);
1756*4882a593Smuzhiyun 		charger->cable_host_nb1.notifier_call =
1757*4882a593Smuzhiyun 			bq25700_host_evt_notifier1;
1758*4882a593Smuzhiyun 		ret = extcon_register_notifier(charger->cable_edev_1,
1759*4882a593Smuzhiyun 					       EXTCON_USB_VBUS_EN,
1760*4882a593Smuzhiyun 					       &charger->cable_host_nb1);
1761*4882a593Smuzhiyun 		if (ret < 0) {
1762*4882a593Smuzhiyun 			dev_err(charger->dev,
1763*4882a593Smuzhiyun 				"failed to register notifier for HOST\n");
1764*4882a593Smuzhiyun 			return -1;
1765*4882a593Smuzhiyun 		}
1766*4882a593Smuzhiyun 	}
1767*4882a593Smuzhiyun 
1768*4882a593Smuzhiyun 	return 0;
1769*4882a593Smuzhiyun }
1770*4882a593Smuzhiyun 
bq25700_otg_vbus_enable(struct regulator_dev * dev)1771*4882a593Smuzhiyun static int bq25700_otg_vbus_enable(struct regulator_dev *dev)
1772*4882a593Smuzhiyun {
1773*4882a593Smuzhiyun 	struct bq25700_device *charger = rdev_get_drvdata(dev);
1774*4882a593Smuzhiyun 
1775*4882a593Smuzhiyun 	bq25700_set_otg_vbus(charger, true);
1776*4882a593Smuzhiyun 
1777*4882a593Smuzhiyun 	return 0;
1778*4882a593Smuzhiyun }
1779*4882a593Smuzhiyun 
bq25700_otg_vbus_disable(struct regulator_dev * dev)1780*4882a593Smuzhiyun static int bq25700_otg_vbus_disable(struct regulator_dev *dev)
1781*4882a593Smuzhiyun {
1782*4882a593Smuzhiyun 	struct bq25700_device *charger = rdev_get_drvdata(dev);
1783*4882a593Smuzhiyun 
1784*4882a593Smuzhiyun 	bq25700_set_otg_vbus(charger, false);
1785*4882a593Smuzhiyun 
1786*4882a593Smuzhiyun 	return 0;
1787*4882a593Smuzhiyun }
1788*4882a593Smuzhiyun 
bq25700_otg_vbus_is_enabled(struct regulator_dev * dev)1789*4882a593Smuzhiyun static int bq25700_otg_vbus_is_enabled(struct regulator_dev *dev)
1790*4882a593Smuzhiyun {
1791*4882a593Smuzhiyun 	struct bq25700_device *charger = rdev_get_drvdata(dev);
1792*4882a593Smuzhiyun 	u8 val;
1793*4882a593Smuzhiyun 	int gpio_status = 1;
1794*4882a593Smuzhiyun 
1795*4882a593Smuzhiyun 	val = bq25700_field_read(charger, EN_OTG);
1796*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->otg_mode_en_io))
1797*4882a593Smuzhiyun 		gpio_status = gpiod_get_value(charger->otg_mode_en_io);
1798*4882a593Smuzhiyun 
1799*4882a593Smuzhiyun 	return val && gpio_status ? 1 : 0;
1800*4882a593Smuzhiyun }
1801*4882a593Smuzhiyun 
1802*4882a593Smuzhiyun static const struct regulator_ops bq25700_otg_vbus_ops = {
1803*4882a593Smuzhiyun 	.enable = bq25700_otg_vbus_enable,
1804*4882a593Smuzhiyun 	.disable = bq25700_otg_vbus_disable,
1805*4882a593Smuzhiyun 	.is_enabled = bq25700_otg_vbus_is_enabled,
1806*4882a593Smuzhiyun };
1807*4882a593Smuzhiyun 
1808*4882a593Smuzhiyun static const struct regulator_desc bq25700_otg_vbus_desc = {
1809*4882a593Smuzhiyun 	.name = "otg-vbus",
1810*4882a593Smuzhiyun 	.of_match = "otg-vbus",
1811*4882a593Smuzhiyun 	.regulators_node = of_match_ptr("regulators"),
1812*4882a593Smuzhiyun 	.owner = THIS_MODULE,
1813*4882a593Smuzhiyun 	.ops = &bq25700_otg_vbus_ops,
1814*4882a593Smuzhiyun 	.type = REGULATOR_VOLTAGE,
1815*4882a593Smuzhiyun 	.fixed_uV = 5000000,
1816*4882a593Smuzhiyun 	.n_voltages = 1,
1817*4882a593Smuzhiyun };
1818*4882a593Smuzhiyun 
bq25700_register_otg_vbus_regulator(struct bq25700_device * charger)1819*4882a593Smuzhiyun static int bq25700_register_otg_vbus_regulator(struct bq25700_device *charger)
1820*4882a593Smuzhiyun {
1821*4882a593Smuzhiyun 	struct device_node *np;
1822*4882a593Smuzhiyun 	struct regulator_config config = { };
1823*4882a593Smuzhiyun 
1824*4882a593Smuzhiyun 	np = of_get_child_by_name(charger->dev->of_node, "regulators");
1825*4882a593Smuzhiyun 	if (!np) {
1826*4882a593Smuzhiyun 		dev_warn(charger->dev, "cannot find regulators node\n");
1827*4882a593Smuzhiyun 		return -ENXIO;
1828*4882a593Smuzhiyun 	}
1829*4882a593Smuzhiyun 
1830*4882a593Smuzhiyun 	config.dev = charger->dev;
1831*4882a593Smuzhiyun 	config.driver_data = charger;
1832*4882a593Smuzhiyun 
1833*4882a593Smuzhiyun 	charger->otg_vbus_reg = devm_regulator_register(charger->dev,
1834*4882a593Smuzhiyun 							&bq25700_otg_vbus_desc,
1835*4882a593Smuzhiyun 							&config);
1836*4882a593Smuzhiyun 	if (IS_ERR(charger->otg_vbus_reg))
1837*4882a593Smuzhiyun 		return PTR_ERR(charger->otg_vbus_reg);
1838*4882a593Smuzhiyun 
1839*4882a593Smuzhiyun 	return 0;
1840*4882a593Smuzhiyun }
1841*4882a593Smuzhiyun 
bq25700_init_usb(struct bq25700_device * charger)1842*4882a593Smuzhiyun static long bq25700_init_usb(struct bq25700_device *charger)
1843*4882a593Smuzhiyun {
1844*4882a593Smuzhiyun 	struct extcon_dev *edev, *edev1;
1845*4882a593Smuzhiyun 	struct device *dev = charger->dev;
1846*4882a593Smuzhiyun 
1847*4882a593Smuzhiyun 	charger->usb_charger_wq = alloc_ordered_workqueue("%s",
1848*4882a593Smuzhiyun 							  WQ_MEM_RECLAIM |
1849*4882a593Smuzhiyun 							  WQ_FREEZABLE,
1850*4882a593Smuzhiyun 							  "bq25700-usb-wq");
1851*4882a593Smuzhiyun 	/* type-C */
1852*4882a593Smuzhiyun 	edev = extcon_get_edev_by_phandle(dev, 0);
1853*4882a593Smuzhiyun 	if (IS_ERR(edev)) {
1854*4882a593Smuzhiyun 		if (PTR_ERR(edev) != -EPROBE_DEFER)
1855*4882a593Smuzhiyun 			dev_err(dev, "Invalid or missing extcon dev0\n");
1856*4882a593Smuzhiyun 		charger->cable_edev = NULL;
1857*4882a593Smuzhiyun 	} else {
1858*4882a593Smuzhiyun 		charger->cable_edev = edev;
1859*4882a593Smuzhiyun 	}
1860*4882a593Smuzhiyun 
1861*4882a593Smuzhiyun 	edev1 = extcon_get_edev_by_phandle(dev, 1);
1862*4882a593Smuzhiyun 	if (IS_ERR(edev1)) {
1863*4882a593Smuzhiyun 		if (PTR_ERR(edev1) != -EPROBE_DEFER)
1864*4882a593Smuzhiyun 			dev_err(dev, "Invalid or missing extcon dev1\n");
1865*4882a593Smuzhiyun 		charger->cable_edev_1 = NULL;
1866*4882a593Smuzhiyun 	} else {
1867*4882a593Smuzhiyun 		charger->cable_edev_1 = edev1;
1868*4882a593Smuzhiyun 	}
1869*4882a593Smuzhiyun 	/*set power_on input current*/
1870*4882a593Smuzhiyun 	bq25700_field_write(charger, INPUT_CURRENT,
1871*4882a593Smuzhiyun 			    charger->init_data.input_current_sdp);
1872*4882a593Smuzhiyun 
1873*4882a593Smuzhiyun 	if (!charger->pd_charge_only)
1874*4882a593Smuzhiyun 		bq25700_register_cg_nb(charger);
1875*4882a593Smuzhiyun 
1876*4882a593Smuzhiyun 	if (bq25700_register_otg_vbus_regulator(charger) < 0) {
1877*4882a593Smuzhiyun 		dev_warn(charger->dev,
1878*4882a593Smuzhiyun 			 "Cannot register otg vbus regulator\n");
1879*4882a593Smuzhiyun 		charger->otg_vbus_reg = NULL;
1880*4882a593Smuzhiyun 		bq25700_register_host_nb(charger);
1881*4882a593Smuzhiyun 	}
1882*4882a593Smuzhiyun 
1883*4882a593Smuzhiyun 	bq25700_register_pd_nb(charger);
1884*4882a593Smuzhiyun 
1885*4882a593Smuzhiyun 	if (charger->cable_edev) {
1886*4882a593Smuzhiyun 		if (!charger->otg_vbus_reg)
1887*4882a593Smuzhiyun 			schedule_delayed_work(&charger->host_work, 0);
1888*4882a593Smuzhiyun 		if (!charger->pd_charge_only)
1889*4882a593Smuzhiyun 			schedule_delayed_work(&charger->usb_work, 0);
1890*4882a593Smuzhiyun 	}
1891*4882a593Smuzhiyun 	if (charger->cable_edev_1) {
1892*4882a593Smuzhiyun 		if (!charger->otg_vbus_reg)
1893*4882a593Smuzhiyun 			schedule_delayed_work(&charger->host_work1, 0);
1894*4882a593Smuzhiyun 		if (!charger->pd_charge_only)
1895*4882a593Smuzhiyun 			schedule_delayed_work(&charger->usb_work1, 0);
1896*4882a593Smuzhiyun 	}
1897*4882a593Smuzhiyun 
1898*4882a593Smuzhiyun 	return 0;
1899*4882a593Smuzhiyun }
1900*4882a593Smuzhiyun 
bq25700_parse_dt(struct bq25700_device * charger)1901*4882a593Smuzhiyun static int bq25700_parse_dt(struct bq25700_device *charger)
1902*4882a593Smuzhiyun {
1903*4882a593Smuzhiyun 	int ret;
1904*4882a593Smuzhiyun 	struct device_node *np = charger->dev->of_node;
1905*4882a593Smuzhiyun 	struct device_node *temp_np = NULL;
1906*4882a593Smuzhiyun 
1907*4882a593Smuzhiyun 	charger->typec0_enable_io = devm_gpiod_get_optional(charger->dev,
1908*4882a593Smuzhiyun 							    "typec0-enable",
1909*4882a593Smuzhiyun 							    GPIOD_IN);
1910*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec0_enable_io))
1911*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec0_enable_io, 0);
1912*4882a593Smuzhiyun 
1913*4882a593Smuzhiyun 	charger->typec1_enable_io = devm_gpiod_get_optional(charger->dev,
1914*4882a593Smuzhiyun 							    "typec1-enable",
1915*4882a593Smuzhiyun 							    GPIOD_IN);
1916*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->typec1_enable_io))
1917*4882a593Smuzhiyun 		gpiod_direction_output(charger->typec1_enable_io, 0);
1918*4882a593Smuzhiyun 
1919*4882a593Smuzhiyun 	charger->typec0_discharge_io =
1920*4882a593Smuzhiyun 		devm_gpiod_get_optional(charger->dev, "typec0-discharge",
1921*4882a593Smuzhiyun 					GPIOD_IN);
1922*4882a593Smuzhiyun 
1923*4882a593Smuzhiyun 	charger->typec1_discharge_io =
1924*4882a593Smuzhiyun 		devm_gpiod_get_optional(charger->dev, "typec1-discharge",
1925*4882a593Smuzhiyun 					GPIOD_IN);
1926*4882a593Smuzhiyun 
1927*4882a593Smuzhiyun 	charger->otg_mode_en_io =  devm_gpiod_get_optional(charger->dev,
1928*4882a593Smuzhiyun 							    "otg-mode-en",
1929*4882a593Smuzhiyun 							    GPIOD_IN);
1930*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(charger->otg_mode_en_io))
1931*4882a593Smuzhiyun 		gpiod_direction_output(charger->otg_mode_en_io, 0);
1932*4882a593Smuzhiyun 
1933*4882a593Smuzhiyun 	ret = of_property_read_u32(np, "pd-charge-only",
1934*4882a593Smuzhiyun 				   &charger->pd_charge_only);
1935*4882a593Smuzhiyun 	if (ret < 0)
1936*4882a593Smuzhiyun 		dev_err(charger->dev, "pd-charge-only!\n");
1937*4882a593Smuzhiyun 
1938*4882a593Smuzhiyun 	temp_np = of_find_node_by_name(NULL, "usb_bc");
1939*4882a593Smuzhiyun 	if (!temp_np)
1940*4882a593Smuzhiyun 		charger->usb_bc = 0;
1941*4882a593Smuzhiyun 	else
1942*4882a593Smuzhiyun 		charger->usb_bc = 1;
1943*4882a593Smuzhiyun 	of_node_put(temp_np);
1944*4882a593Smuzhiyun 
1945*4882a593Smuzhiyun 	if (np)
1946*4882a593Smuzhiyun 		charger->notify_node = of_parse_phandle(np,
1947*4882a593Smuzhiyun 						"ti,usb-charger-detection", 0);
1948*4882a593Smuzhiyun 	return 0;
1949*4882a593Smuzhiyun }
1950*4882a593Smuzhiyun 
bq25700_probe(struct i2c_client * client,const struct i2c_device_id * id)1951*4882a593Smuzhiyun static int bq25700_probe(struct i2c_client *client,
1952*4882a593Smuzhiyun 			 const struct i2c_device_id *id)
1953*4882a593Smuzhiyun {
1954*4882a593Smuzhiyun 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
1955*4882a593Smuzhiyun 	struct device *dev = &client->dev;
1956*4882a593Smuzhiyun 	struct bq25700_device *charger;
1957*4882a593Smuzhiyun 	struct device_node *charger_np;
1958*4882a593Smuzhiyun 	int ret = 0;
1959*4882a593Smuzhiyun 	u32 i = 0;
1960*4882a593Smuzhiyun 	int irq_flag;
1961*4882a593Smuzhiyun 
1962*4882a593Smuzhiyun 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
1963*4882a593Smuzhiyun 		return -EIO;
1964*4882a593Smuzhiyun 
1965*4882a593Smuzhiyun 	charger = devm_kzalloc(&client->dev, sizeof(*charger), GFP_KERNEL);
1966*4882a593Smuzhiyun 	if (!charger)
1967*4882a593Smuzhiyun 		return -EINVAL;
1968*4882a593Smuzhiyun 
1969*4882a593Smuzhiyun 	charger->client = client;
1970*4882a593Smuzhiyun 	charger->dev = dev;
1971*4882a593Smuzhiyun 
1972*4882a593Smuzhiyun 	charger_np = of_find_compatible_node(NULL, NULL, "ti,bq25700");
1973*4882a593Smuzhiyun 	if (!charger_np)
1974*4882a593Smuzhiyun 		charger_np = of_find_compatible_node(NULL, NULL, "southchip,sc8885");
1975*4882a593Smuzhiyun 	if (charger_np) {
1976*4882a593Smuzhiyun 		charger->regmap = devm_regmap_init_i2c(client,
1977*4882a593Smuzhiyun 						       &bq25700_regmap_config);
1978*4882a593Smuzhiyun 		if (IS_ERR(charger->regmap)) {
1979*4882a593Smuzhiyun 			dev_err(&client->dev, "Failed to initialize regmap\n");
1980*4882a593Smuzhiyun 			return -EINVAL;
1981*4882a593Smuzhiyun 		}
1982*4882a593Smuzhiyun 
1983*4882a593Smuzhiyun 		for (i = 0; i < ARRAY_SIZE(bq25700_reg_fields); i++) {
1984*4882a593Smuzhiyun 			const struct reg_field *reg_fields = bq25700_reg_fields;
1985*4882a593Smuzhiyun 
1986*4882a593Smuzhiyun 			charger->rmap_fields[i] =
1987*4882a593Smuzhiyun 				devm_regmap_field_alloc(dev,
1988*4882a593Smuzhiyun 							charger->regmap,
1989*4882a593Smuzhiyun 							reg_fields[i]);
1990*4882a593Smuzhiyun 			if (IS_ERR(charger->rmap_fields[i])) {
1991*4882a593Smuzhiyun 				dev_err(dev, "cannot allocate regmap field\n");
1992*4882a593Smuzhiyun 				return PTR_ERR(charger->rmap_fields[i]);
1993*4882a593Smuzhiyun 			}
1994*4882a593Smuzhiyun 		}
1995*4882a593Smuzhiyun 	} else {
1996*4882a593Smuzhiyun 		charger->regmap = devm_regmap_init_i2c(client,
1997*4882a593Smuzhiyun 						       &bq25703_regmap_config);
1998*4882a593Smuzhiyun 
1999*4882a593Smuzhiyun 		if (IS_ERR(charger->regmap)) {
2000*4882a593Smuzhiyun 			dev_err(&client->dev, "Failed to initialize regmap\n");
2001*4882a593Smuzhiyun 			return -EINVAL;
2002*4882a593Smuzhiyun 		}
2003*4882a593Smuzhiyun 
2004*4882a593Smuzhiyun 		for (i = 0; i < ARRAY_SIZE(bq25703_reg_fields); i++) {
2005*4882a593Smuzhiyun 			const struct reg_field *reg_fields = bq25703_reg_fields;
2006*4882a593Smuzhiyun 
2007*4882a593Smuzhiyun 			charger->rmap_fields[i] =
2008*4882a593Smuzhiyun 				devm_regmap_field_alloc(dev,
2009*4882a593Smuzhiyun 							charger->regmap,
2010*4882a593Smuzhiyun 							reg_fields[i]);
2011*4882a593Smuzhiyun 			if (IS_ERR(charger->rmap_fields[i])) {
2012*4882a593Smuzhiyun 				dev_err(dev, "cannot allocate regmap field\n");
2013*4882a593Smuzhiyun 				return PTR_ERR(charger->rmap_fields[i]);
2014*4882a593Smuzhiyun 			}
2015*4882a593Smuzhiyun 		}
2016*4882a593Smuzhiyun 	}
2017*4882a593Smuzhiyun 	i2c_set_clientdata(client, charger);
2018*4882a593Smuzhiyun 
2019*4882a593Smuzhiyun 	/*read chip id. Confirm whether to support the chip*/
2020*4882a593Smuzhiyun 	charger->chip_id = bq25700_field_read(charger, DEVICE_ID);
2021*4882a593Smuzhiyun 
2022*4882a593Smuzhiyun 	if (charger->chip_id < 0) {
2023*4882a593Smuzhiyun 		dev_err(dev, "Cannot read chip ID.\n");
2024*4882a593Smuzhiyun 		return charger->chip_id;
2025*4882a593Smuzhiyun 	}
2026*4882a593Smuzhiyun 
2027*4882a593Smuzhiyun 	if (!dev->platform_data) {
2028*4882a593Smuzhiyun 		ret = bq25700_fw_probe(charger);
2029*4882a593Smuzhiyun 		if (ret < 0) {
2030*4882a593Smuzhiyun 			dev_err(dev, "Cannot read device properties.\n");
2031*4882a593Smuzhiyun 			return ret;
2032*4882a593Smuzhiyun 		}
2033*4882a593Smuzhiyun 	} else {
2034*4882a593Smuzhiyun 		return -ENODEV;
2035*4882a593Smuzhiyun 	}
2036*4882a593Smuzhiyun 
2037*4882a593Smuzhiyun 	/*
2038*4882a593Smuzhiyun 	 * Make sure battery online, otherwise, writing INPUT_CURRENT and
2039*4882a593Smuzhiyun 	 * CHARGE_CURRENT would make system power off
2040*4882a593Smuzhiyun 	 */
2041*4882a593Smuzhiyun 	if (of_parse_phandle(charger->dev->of_node, "ti,battery", 0)) {
2042*4882a593Smuzhiyun 		if (IS_ERR_OR_NULL(power_supply_get_by_phandle(
2043*4882a593Smuzhiyun 						charger->dev->of_node,
2044*4882a593Smuzhiyun 						"ti,battery"))) {
2045*4882a593Smuzhiyun 			dev_info(charger->dev, "No battery found\n");
2046*4882a593Smuzhiyun 			return -EPROBE_DEFER;
2047*4882a593Smuzhiyun 		}
2048*4882a593Smuzhiyun 		dev_info(charger->dev, "Battery found\n");
2049*4882a593Smuzhiyun 	}
2050*4882a593Smuzhiyun 
2051*4882a593Smuzhiyun 	ret = bq25700_hw_init(charger);
2052*4882a593Smuzhiyun 	if (ret < 0) {
2053*4882a593Smuzhiyun 		dev_err(dev, "Cannot initialize the chip.\n");
2054*4882a593Smuzhiyun 		return ret;
2055*4882a593Smuzhiyun 	}
2056*4882a593Smuzhiyun 
2057*4882a593Smuzhiyun 	bq25700_parse_dt(charger);
2058*4882a593Smuzhiyun 	bq25700_init_sysfs(charger);
2059*4882a593Smuzhiyun 
2060*4882a593Smuzhiyun 	bq25700_power_supply_init(charger);
2061*4882a593Smuzhiyun 	bq25700_init_usb(charger);
2062*4882a593Smuzhiyun 
2063*4882a593Smuzhiyun 	if (client->irq < 0) {
2064*4882a593Smuzhiyun 		dev_err(dev, "No irq resource found.\n");
2065*4882a593Smuzhiyun 		return client->irq;
2066*4882a593Smuzhiyun 	}
2067*4882a593Smuzhiyun 
2068*4882a593Smuzhiyun 	if (bq25700_field_read(charger, AC_STAT))
2069*4882a593Smuzhiyun 		irq_flag = IRQF_TRIGGER_LOW;
2070*4882a593Smuzhiyun 	else
2071*4882a593Smuzhiyun 		irq_flag = IRQF_TRIGGER_HIGH;
2072*4882a593Smuzhiyun 
2073*4882a593Smuzhiyun 	device_init_wakeup(dev, 1);
2074*4882a593Smuzhiyun 
2075*4882a593Smuzhiyun 	ret = devm_request_threaded_irq(dev, client->irq, NULL,
2076*4882a593Smuzhiyun 					bq25700_irq_handler_thread,
2077*4882a593Smuzhiyun 					irq_flag | IRQF_ONESHOT,
2078*4882a593Smuzhiyun 					"bq25700_irq", charger);
2079*4882a593Smuzhiyun 	if (ret)
2080*4882a593Smuzhiyun 		goto irq_fail;
2081*4882a593Smuzhiyun 	enable_irq_wake(client->irq);
2082*4882a593Smuzhiyun 
2083*4882a593Smuzhiyun 	bq25700_charger = charger;
2084*4882a593Smuzhiyun 
2085*4882a593Smuzhiyun irq_fail:
2086*4882a593Smuzhiyun 	return ret;
2087*4882a593Smuzhiyun }
2088*4882a593Smuzhiyun 
bq25700_shutdown(struct i2c_client * client)2089*4882a593Smuzhiyun static void bq25700_shutdown(struct i2c_client *client)
2090*4882a593Smuzhiyun {
2091*4882a593Smuzhiyun 	int vol_idx;
2092*4882a593Smuzhiyun 	struct bq25700_device *charger = i2c_get_clientdata(client);
2093*4882a593Smuzhiyun 
2094*4882a593Smuzhiyun 	vol_idx = bq25700_find_idx(DEFAULT_INPUTVOL, TBL_INPUTVOL);
2095*4882a593Smuzhiyun 	bq25700_field_write(charger, INPUT_VOLTAGE, vol_idx);
2096*4882a593Smuzhiyun 	bq25700_field_write(charger, INPUT_CURRENT,
2097*4882a593Smuzhiyun 			    charger->init_data.input_current_sdp);
2098*4882a593Smuzhiyun 
2099*4882a593Smuzhiyun 	if (!bq25700_field_read(charger, AC_STAT))
2100*4882a593Smuzhiyun 		bq25700_field_write(charger, EN_LWPWR, 1);
2101*4882a593Smuzhiyun }
2102*4882a593Smuzhiyun 
2103*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
bq25700_pm_suspend(struct device * dev)2104*4882a593Smuzhiyun static int bq25700_pm_suspend(struct device *dev)
2105*4882a593Smuzhiyun {
2106*4882a593Smuzhiyun 	struct bq25700_device *charger = dev_get_drvdata(dev);
2107*4882a593Smuzhiyun 
2108*4882a593Smuzhiyun 	if (!bq25700_field_read(charger, AC_STAT))
2109*4882a593Smuzhiyun 		bq25700_field_write(charger, EN_LWPWR, 1);
2110*4882a593Smuzhiyun 
2111*4882a593Smuzhiyun 	return 0;
2112*4882a593Smuzhiyun }
2113*4882a593Smuzhiyun 
bq25700_pm_resume(struct device * dev)2114*4882a593Smuzhiyun static int bq25700_pm_resume(struct device *dev)
2115*4882a593Smuzhiyun {
2116*4882a593Smuzhiyun 	struct bq25700_device *charger = dev_get_drvdata(dev);
2117*4882a593Smuzhiyun 
2118*4882a593Smuzhiyun 	bq25700_field_write(charger, EN_LWPWR, 0);
2119*4882a593Smuzhiyun 
2120*4882a593Smuzhiyun 	return 0;
2121*4882a593Smuzhiyun }
2122*4882a593Smuzhiyun #endif
2123*4882a593Smuzhiyun 
2124*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(bq25700_pm_ops, bq25700_pm_suspend, bq25700_pm_resume);
2125*4882a593Smuzhiyun 
2126*4882a593Smuzhiyun static const struct i2c_device_id bq25700_i2c_ids[] = {
2127*4882a593Smuzhiyun 	{ "bq25700"},
2128*4882a593Smuzhiyun 	{ },
2129*4882a593Smuzhiyun };
2130*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, bq25700_i2c_ids);
2131*4882a593Smuzhiyun 
2132*4882a593Smuzhiyun #ifdef CONFIG_OF
2133*4882a593Smuzhiyun static const struct of_device_id bq25700_of_match[] = {
2134*4882a593Smuzhiyun 	{ .compatible = "ti,bq25700", },
2135*4882a593Smuzhiyun 	{ .compatible = "ti,bq25703", },
2136*4882a593Smuzhiyun 	{ .compatible = "southchip,sc8885", },
2137*4882a593Smuzhiyun 	{ .compatible = "southchip,sc8886", },
2138*4882a593Smuzhiyun 	{ },
2139*4882a593Smuzhiyun };
2140*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, bq25700_of_match);
2141*4882a593Smuzhiyun #else
2142*4882a593Smuzhiyun static const struct of_device_id bq25700_of_match[] = {
2143*4882a593Smuzhiyun 	{ },
2144*4882a593Smuzhiyun };
2145*4882a593Smuzhiyun #endif
2146*4882a593Smuzhiyun 
2147*4882a593Smuzhiyun static struct i2c_driver bq25700_driver = {
2148*4882a593Smuzhiyun 	.probe		= bq25700_probe,
2149*4882a593Smuzhiyun 	.shutdown	= bq25700_shutdown,
2150*4882a593Smuzhiyun 	.id_table	= bq25700_i2c_ids,
2151*4882a593Smuzhiyun 	.driver = {
2152*4882a593Smuzhiyun 		.name		= "bq25700-charger",
2153*4882a593Smuzhiyun 		.pm		= &bq25700_pm_ops,
2154*4882a593Smuzhiyun 		.of_match_table	= of_match_ptr(bq25700_of_match),
2155*4882a593Smuzhiyun 	},
2156*4882a593Smuzhiyun };
2157*4882a593Smuzhiyun module_i2c_driver(bq25700_driver);
2158*4882a593Smuzhiyun 
2159*4882a593Smuzhiyun MODULE_LICENSE("GPL");
2160*4882a593Smuzhiyun MODULE_AUTHOR("shengfeixu <xsf@rock-chips.com>");
2161*4882a593Smuzhiyun MODULE_DESCRIPTION("TI bq25700 Charger Driver");
2162