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