1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Chrager driver for Sgm4154x
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Xu Shengfei <xsf@rock-chips.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/delay.h>
11*4882a593Smuzhiyun #include <linux/i2c.h>
12*4882a593Smuzhiyun #include <linux/interrupt.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/power_supply.h>
15*4882a593Smuzhiyun #include <linux/regmap.h>
16*4882a593Smuzhiyun #include <linux/regulator/driver.h>
17*4882a593Smuzhiyun #include <linux/regulator/of_regulator.h>
18*4882a593Smuzhiyun #include <linux/regulator/machine.h>
19*4882a593Smuzhiyun #include <linux/types.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun static int dbg_enable;
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun module_param_named(dbg_level, dbg_enable, int, 0644);
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #define DBG(args...) \
26*4882a593Smuzhiyun do { \
27*4882a593Smuzhiyun if (dbg_enable) { \
28*4882a593Smuzhiyun pr_info(args); \
29*4882a593Smuzhiyun } \
30*4882a593Smuzhiyun } while (0)
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define SGM4154x_MANUFACTURER "SGMICRO"
33*4882a593Smuzhiyun #define SGM4154x_NAME "sgm41542"
34*4882a593Smuzhiyun #define SGM4154x_PN_ID (BIT(6) | BIT(5) | BIT(3))
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /* define register */
37*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_0 0x00
38*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_1 0x01
39*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_2 0x02
40*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_3 0x03
41*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_4 0x04
42*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_5 0x05
43*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_6 0x06
44*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_7 0x07
45*4882a593Smuzhiyun #define SGM4154x_CHRG_STAT 0x08
46*4882a593Smuzhiyun #define SGM4154x_CHRG_FAULT 0x09
47*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_a 0x0a
48*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_b 0x0b
49*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_c 0x0c
50*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_d 0x0d
51*4882a593Smuzhiyun #define SGM4154x_INPUT_DET 0x0e
52*4882a593Smuzhiyun #define SGM4154x_CHRG_CTRL_f 0x0f
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /* charge status flags */
55*4882a593Smuzhiyun #define SGM4154x_CHRG_EN BIT(4)
56*4882a593Smuzhiyun #define SGM4154x_HIZ_EN BIT(7)
57*4882a593Smuzhiyun #define SGM4154x_TERM_EN BIT(7)
58*4882a593Smuzhiyun #define SGM4154x_VAC_OVP_MASK GENMASK(7, 6)
59*4882a593Smuzhiyun #define SGM4154x_DPDM_ONGOING BIT(7)
60*4882a593Smuzhiyun #define SGM4154x_VBUS_GOOD BIT(7)
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun #define SGM4154x_BOOSTV GENMASK(5, 4)
63*4882a593Smuzhiyun #define SGM4154x_BOOST_LIM BIT(7)
64*4882a593Smuzhiyun #define SGM4154x_OTG_EN BIT(5)
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun /* Part ID */
67*4882a593Smuzhiyun #define SGM4154x_PN_MASK GENMASK(6, 3)
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /* WDT TIMER SET */
70*4882a593Smuzhiyun #define SGM4154x_WDT_TIMER_MASK GENMASK(5, 4)
71*4882a593Smuzhiyun #define SGM4154x_WDT_TIMER_DISABLE 0
72*4882a593Smuzhiyun #define SGM4154x_WDT_TIMER_40S BIT(4)
73*4882a593Smuzhiyun #define SGM4154x_WDT_TIMER_80S BIT(5)
74*4882a593Smuzhiyun #define SGM4154x_WDT_TIMER_160S (BIT(4) | BIT(5))
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun #define SGM4154x_WDT_RST_MASK BIT(6)
77*4882a593Smuzhiyun #define SGM4154x_WDT_RST BIT(6)
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun /* SAFETY TIMER SET */
80*4882a593Smuzhiyun #define SGM4154x_SAFETY_TIMER_MASK GENMASK(3, 3)
81*4882a593Smuzhiyun #define SGM4154x_SAFETY_TIMER_DISABLE 0
82*4882a593Smuzhiyun #define SGM4154x_SAFETY_TIMER_EN BIT(3)
83*4882a593Smuzhiyun #define SGM4154x_SAFETY_TIMER_5H 0
84*4882a593Smuzhiyun #define SGM4154x_SAFETY_TIMER_10H BIT(2)
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun /* recharge voltage */
87*4882a593Smuzhiyun #define SGM4154x_VRECHARGE BIT(0)
88*4882a593Smuzhiyun #define SGM4154x_VRECHRG_STEP_mV 100
89*4882a593Smuzhiyun #define SGM4154x_VRECHRG_OFFSET_mV 100
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun /* charge status */
92*4882a593Smuzhiyun #define SGM4154x_VSYS_STAT BIT(0)
93*4882a593Smuzhiyun #define SGM4154x_THERM_STAT BIT(1)
94*4882a593Smuzhiyun #define SGM4154x_PG_STAT BIT(2)
95*4882a593Smuzhiyun #define SGM4154x_CHG_STAT_MASK GENMASK(4, 3)
96*4882a593Smuzhiyun #define SGM4154x_PRECHRG BIT(3)
97*4882a593Smuzhiyun #define SGM4154x_FAST_CHRG BIT(4)
98*4882a593Smuzhiyun #define SGM4154x_TERM_CHRG (BIT(3) | BIT(4))
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /* charge type */
101*4882a593Smuzhiyun #define SGM4154x_VBUS_STAT_MASK GENMASK(7, 5)
102*4882a593Smuzhiyun #define SGM4154x_NOT_CHRGING 0
103*4882a593Smuzhiyun #define SGM4154x_USB_SDP BIT(5)
104*4882a593Smuzhiyun #define SGM4154x_USB_CDP BIT(6)
105*4882a593Smuzhiyun #define SGM4154x_USB_DCP (BIT(5) | BIT(6))
106*4882a593Smuzhiyun #define SGM4154x_UNKNOWN (BIT(7) | BIT(5))
107*4882a593Smuzhiyun #define SGM4154x_NON_STANDARD (BIT(7) | BIT(6))
108*4882a593Smuzhiyun #define SGM4154x_OTG_MODE (BIT(7) | BIT(6) | BIT(5))
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /* TEMP Status */
111*4882a593Smuzhiyun #define SGM4154x_TEMP_MASK GENMASK(2, 0)
112*4882a593Smuzhiyun #define SGM4154x_TEMP_NORMAL BIT(0)
113*4882a593Smuzhiyun #define SGM4154x_TEMP_WARM BIT(1)
114*4882a593Smuzhiyun #define SGM4154x_TEMP_COOL (BIT(0) | BIT(1))
115*4882a593Smuzhiyun #define SGM4154x_TEMP_COLD (BIT(0) | BIT(3))
116*4882a593Smuzhiyun #define SGM4154x_TEMP_HOT (BIT(2) | BIT(3))
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /* precharge current */
119*4882a593Smuzhiyun #define SGM4154x_PRECHRG_CUR_MASK GENMASK(7, 4)
120*4882a593Smuzhiyun #define SGM4154x_PRECHRG_CURRENT_STEP_uA 60000
121*4882a593Smuzhiyun #define SGM4154x_PRECHRG_I_MIN_uA 60000
122*4882a593Smuzhiyun #define SGM4154x_PRECHRG_I_MAX_uA 780000
123*4882a593Smuzhiyun #define SGM4154x_PRECHRG_I_DEF_uA 180000
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun /* termination current */
126*4882a593Smuzhiyun #define SGM4154x_TERMCHRG_CUR_MASK GENMASK(3, 0)
127*4882a593Smuzhiyun #define SGM4154x_TERMCHRG_CURRENT_STEP_uA 60000
128*4882a593Smuzhiyun #define SGM4154x_TERMCHRG_I_MIN_uA 60000
129*4882a593Smuzhiyun #define SGM4154x_TERMCHRG_I_MAX_uA 960000
130*4882a593Smuzhiyun #define SGM4154x_TERMCHRG_I_DEF_uA 180000
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun /* charge current */
133*4882a593Smuzhiyun #define SGM4154x_ICHRG_CUR_MASK GENMASK(5, 0)
134*4882a593Smuzhiyun #define SGM4154x_ICHRG_I_STEP_uA 60000
135*4882a593Smuzhiyun #define SGM4154x_ICHRG_I_MIN_uA 0
136*4882a593Smuzhiyun #define SGM4154x_ICHRG_I_MAX_uA 3000000
137*4882a593Smuzhiyun #define SGM4154x_ICHRG_I_DEF_uA 2040000
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /* charge voltage */
140*4882a593Smuzhiyun #define SGM4154x_VREG_V_MASK GENMASK(7, 3)
141*4882a593Smuzhiyun #define SGM4154x_VREG_V_MAX_uV 4624000
142*4882a593Smuzhiyun #define SGM4154x_VREG_V_MIN_uV 3856000
143*4882a593Smuzhiyun #define SGM4154x_VREG_V_DEF_uV 4208000
144*4882a593Smuzhiyun #define SGM4154x_VREG_V_STEP_uV 32000
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /* VREG Fine Tuning */
147*4882a593Smuzhiyun #define SGM4154x_VREG_FT_MASK GENMASK(7, 6)
148*4882a593Smuzhiyun #define SGM4154x_VREG_FT_UP_8mV BIT(6)
149*4882a593Smuzhiyun #define SGM4154x_VREG_FT_DN_8mV BIT(7)
150*4882a593Smuzhiyun #define SGM4154x_VREG_FT_DN_16mV (BIT(7) | BIT(6))
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /* iindpm current */
153*4882a593Smuzhiyun #define SGM4154x_IINDPM_I_MASK GENMASK(4, 0)
154*4882a593Smuzhiyun #define SGM4154x_IINDPM_I_MIN_uA 100000
155*4882a593Smuzhiyun #define SGM4154x_IINDPM_I_MAX_uA 3800000
156*4882a593Smuzhiyun #define SGM4154x_IINDPM_STEP_uA 100000
157*4882a593Smuzhiyun #define SGM4154x_IINDPM_DEF_uA 2400000
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun #define SGM4154x_VINDPM_INT_MASK BIT(1)
160*4882a593Smuzhiyun #define SGM4154x_VINDPM_INT_DIS BIT(1)
161*4882a593Smuzhiyun #define SGM4154x_IINDPM_INT_MASK BIT(0)
162*4882a593Smuzhiyun #define SGM4154x_IINDPM_INT_DIS BIT(0)
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /* vindpm voltage */
165*4882a593Smuzhiyun #define SGM4154x_VINDPM_V_MASK GENMASK(3, 0)
166*4882a593Smuzhiyun #define SGM4154x_VINDPM_V_MIN_uV 3900000
167*4882a593Smuzhiyun #define SGM4154x_VINDPM_V_MAX_uV 12000000
168*4882a593Smuzhiyun #define SGM4154x_VINDPM_STEP_uV 100000
169*4882a593Smuzhiyun #define SGM4154x_VINDPM_DEF_uV 4500000
170*4882a593Smuzhiyun #define SGM4154x_VINDPM_OS_MASK GENMASK(1, 0)
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun /* DP DM SEL */
173*4882a593Smuzhiyun #define SGM4154x_DP_VSEL_MASK GENMASK(4, 3)
174*4882a593Smuzhiyun #define SGM4154x_DM_VSEL_MASK GENMASK(2, 1)
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /* PUMPX SET */
177*4882a593Smuzhiyun #define SGM4154x_EN_PUMPX BIT(7)
178*4882a593Smuzhiyun #define SGM4154x_PUMPX_UP BIT(6)
179*4882a593Smuzhiyun #define SGM4154x_PUMPX_DN BIT(5)
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun #define SGM4154x_BATFET_DIS_MSK BIT(5)
182*4882a593Smuzhiyun #define SGM4154x_BATFET_DIS_DIS BIT(5)
183*4882a593Smuzhiyun #define SGM4154x_BATFET_DLY_MSK BIT(3)
184*4882a593Smuzhiyun #define SGM4154x_BATFET_DLY_EN BIT(3)
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun #define DEFAULT_INPUT_CURRENT (500 * 1000)
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun struct sgm4154x_init_data {
189*4882a593Smuzhiyun int ichg; /* charge current */
190*4882a593Smuzhiyun int ilim; /* input current */
191*4882a593Smuzhiyun int vreg; /* regulation voltage */
192*4882a593Smuzhiyun int iterm; /* termination current */
193*4882a593Smuzhiyun int iprechg; /* precharge current */
194*4882a593Smuzhiyun int vlim; /* minimum system voltage limit */
195*4882a593Smuzhiyun int max_ichg;
196*4882a593Smuzhiyun int max_vreg;
197*4882a593Smuzhiyun };
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun struct sgm4154x_state {
200*4882a593Smuzhiyun bool vsys_stat;
201*4882a593Smuzhiyun bool therm_stat;
202*4882a593Smuzhiyun bool online;
203*4882a593Smuzhiyun u8 chrg_stat;
204*4882a593Smuzhiyun u8 vbus_status;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun bool chrg_en;
207*4882a593Smuzhiyun bool hiz_en;
208*4882a593Smuzhiyun bool term_en;
209*4882a593Smuzhiyun bool vbus_gd;
210*4882a593Smuzhiyun u8 chrg_type;
211*4882a593Smuzhiyun u8 health;
212*4882a593Smuzhiyun u8 chrg_fault;
213*4882a593Smuzhiyun u8 ntc_fault;
214*4882a593Smuzhiyun };
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun struct sgm4154x_device {
217*4882a593Smuzhiyun struct i2c_client *client;
218*4882a593Smuzhiyun struct device *dev;
219*4882a593Smuzhiyun struct power_supply *charger;
220*4882a593Smuzhiyun struct mutex lock;
221*4882a593Smuzhiyun struct mutex i2c_rw_lock;
222*4882a593Smuzhiyun struct regmap *regmap;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun char model_name[I2C_NAME_SIZE];
225*4882a593Smuzhiyun int device_id;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun struct sgm4154x_init_data init_data;
228*4882a593Smuzhiyun struct sgm4154x_state state;
229*4882a593Smuzhiyun struct regulator_dev *otg_rdev;
230*4882a593Smuzhiyun struct notifier_block pm_nb;
231*4882a593Smuzhiyun int input_current;
232*4882a593Smuzhiyun bool sgm4154x_suspend_flag;
233*4882a593Smuzhiyun bool watchdog_enable;
234*4882a593Smuzhiyun struct workqueue_struct *sgm_monitor_wq;
235*4882a593Smuzhiyun struct delayed_work sgm_delay_work;
236*4882a593Smuzhiyun };
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun /* SGM4154x REG06 BOOST_LIM[5:4], uV */
239*4882a593Smuzhiyun static const unsigned int BOOST_VOLT_LIMIT[] = {
240*4882a593Smuzhiyun 4850000, 5000000, 5150000, 5300000
241*4882a593Smuzhiyun };
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun static const unsigned int BOOST_CURRENT_LIMIT[] = {
244*4882a593Smuzhiyun 1200000, 2000000
245*4882a593Smuzhiyun };
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun enum SGM4154x_VINDPM_OS {
248*4882a593Smuzhiyun VINDPM_OS_3900mV,
249*4882a593Smuzhiyun VINDPM_OS_5900mV,
250*4882a593Smuzhiyun VINDPM_OS_7500mV,
251*4882a593Smuzhiyun VINDPM_OS_10500mV,
252*4882a593Smuzhiyun };
253*4882a593Smuzhiyun
sgm4154x_set_term_curr(struct sgm4154x_device * sgm,int uA)254*4882a593Smuzhiyun static int sgm4154x_set_term_curr(struct sgm4154x_device *sgm, int uA)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun int reg_val;
257*4882a593Smuzhiyun int ret;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun if (uA < SGM4154x_TERMCHRG_I_MIN_uA)
260*4882a593Smuzhiyun uA = SGM4154x_TERMCHRG_I_MIN_uA;
261*4882a593Smuzhiyun else if (uA > SGM4154x_TERMCHRG_I_MAX_uA)
262*4882a593Smuzhiyun uA = SGM4154x_TERMCHRG_I_MAX_uA;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun reg_val = (uA - SGM4154x_TERMCHRG_I_MIN_uA) / SGM4154x_TERMCHRG_CURRENT_STEP_uA;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
267*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_3,
268*4882a593Smuzhiyun SGM4154x_TERMCHRG_CUR_MASK,
269*4882a593Smuzhiyun reg_val);
270*4882a593Smuzhiyun if (ret)
271*4882a593Smuzhiyun dev_err(sgm->dev, "set term current error!\n");
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun return ret;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
sgm4154x_set_prechrg_curr(struct sgm4154x_device * sgm,int uA)276*4882a593Smuzhiyun static int sgm4154x_set_prechrg_curr(struct sgm4154x_device *sgm, int uA)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun int reg_val;
279*4882a593Smuzhiyun int ret;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun if (uA < SGM4154x_PRECHRG_I_MIN_uA)
282*4882a593Smuzhiyun uA = SGM4154x_PRECHRG_I_MIN_uA;
283*4882a593Smuzhiyun else if (uA > SGM4154x_PRECHRG_I_MAX_uA)
284*4882a593Smuzhiyun uA = SGM4154x_PRECHRG_I_MAX_uA;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun reg_val = (uA - SGM4154x_PRECHRG_I_MIN_uA) / SGM4154x_PRECHRG_CURRENT_STEP_uA;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun reg_val = reg_val << 4;
289*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
290*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_3,
291*4882a593Smuzhiyun SGM4154x_PRECHRG_CUR_MASK,
292*4882a593Smuzhiyun reg_val);
293*4882a593Smuzhiyun if (ret)
294*4882a593Smuzhiyun dev_err(sgm->dev, "set precharge current error!\n");
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun return ret;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
sgm4154x_set_ichrg_curr(struct sgm4154x_device * sgm,int uA)299*4882a593Smuzhiyun static int sgm4154x_set_ichrg_curr(struct sgm4154x_device *sgm, int uA)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun int reg_val;
302*4882a593Smuzhiyun int ret;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun if (uA < SGM4154x_ICHRG_I_MIN_uA)
305*4882a593Smuzhiyun uA = SGM4154x_ICHRG_I_MIN_uA;
306*4882a593Smuzhiyun else {
307*4882a593Smuzhiyun if ((sgm->init_data.max_ichg > 0) && (uA > sgm->init_data.max_ichg))
308*4882a593Smuzhiyun uA = sgm->init_data.max_ichg;
309*4882a593Smuzhiyun uA = min(uA, SGM4154x_ICHRG_I_MAX_uA);
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun reg_val = uA / SGM4154x_ICHRG_I_STEP_uA;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
315*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_2,
316*4882a593Smuzhiyun SGM4154x_ICHRG_CUR_MASK,
317*4882a593Smuzhiyun reg_val);
318*4882a593Smuzhiyun if (ret)
319*4882a593Smuzhiyun dev_err(sgm->dev, "set icharge current error!\n");
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun return ret;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
sgm4154x_set_chrg_volt(struct sgm4154x_device * sgm,int chrg_volt)324*4882a593Smuzhiyun static int sgm4154x_set_chrg_volt(struct sgm4154x_device *sgm, int chrg_volt)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun int reg_val;
327*4882a593Smuzhiyun int ret;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun if (chrg_volt < SGM4154x_VREG_V_MIN_uV)
330*4882a593Smuzhiyun chrg_volt = SGM4154x_VREG_V_MIN_uV;
331*4882a593Smuzhiyun else {
332*4882a593Smuzhiyun if ((sgm->init_data.max_vreg > 0) && (chrg_volt > sgm->init_data.max_vreg))
333*4882a593Smuzhiyun chrg_volt = sgm->init_data.max_vreg;
334*4882a593Smuzhiyun chrg_volt = min(chrg_volt, SGM4154x_VREG_V_MAX_uV);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun reg_val = (chrg_volt - SGM4154x_VREG_V_MIN_uV) / SGM4154x_VREG_V_STEP_uV;
338*4882a593Smuzhiyun if (chrg_volt == 4200 * 1000)
339*4882a593Smuzhiyun reg_val = 0x0b;
340*4882a593Smuzhiyun reg_val = reg_val << 3;
341*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
342*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_4,
343*4882a593Smuzhiyun SGM4154x_VREG_V_MASK,
344*4882a593Smuzhiyun reg_val);
345*4882a593Smuzhiyun if (ret)
346*4882a593Smuzhiyun dev_err(sgm->dev, "set charge voltage error!\n");
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun return ret;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun
sgm4154x_set_vindpm_offset_os(struct sgm4154x_device * sgm,enum SGM4154x_VINDPM_OS offset_os)351*4882a593Smuzhiyun static int sgm4154x_set_vindpm_offset_os(struct sgm4154x_device *sgm,
352*4882a593Smuzhiyun enum SGM4154x_VINDPM_OS offset_os)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun int ret;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
357*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_f,
358*4882a593Smuzhiyun SGM4154x_VINDPM_OS_MASK,
359*4882a593Smuzhiyun offset_os);
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun if (ret)
362*4882a593Smuzhiyun dev_err(sgm->dev, "set vindpm offset os error!\n");
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun return ret;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
sgm4154x_set_input_volt_lim(struct sgm4154x_device * sgm,unsigned int vindpm)367*4882a593Smuzhiyun static int sgm4154x_set_input_volt_lim(struct sgm4154x_device *sgm,
368*4882a593Smuzhiyun unsigned int vindpm)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun enum SGM4154x_VINDPM_OS os_val;
371*4882a593Smuzhiyun unsigned int offset;
372*4882a593Smuzhiyun u8 reg_val;
373*4882a593Smuzhiyun int ret;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun if (vindpm < SGM4154x_VINDPM_V_MIN_uV ||
377*4882a593Smuzhiyun vindpm > SGM4154x_VINDPM_V_MAX_uV)
378*4882a593Smuzhiyun return -EINVAL;
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun if (vindpm < 5900000) {
381*4882a593Smuzhiyun os_val = VINDPM_OS_3900mV;
382*4882a593Smuzhiyun offset = 3900000;
383*4882a593Smuzhiyun } else if (vindpm >= 5900000 && vindpm < 7500000) {
384*4882a593Smuzhiyun os_val = VINDPM_OS_5900mV;
385*4882a593Smuzhiyun offset = 5900000;
386*4882a593Smuzhiyun } else if (vindpm >= 7500000 && vindpm < 10500000) {
387*4882a593Smuzhiyun os_val = VINDPM_OS_7500mV;
388*4882a593Smuzhiyun offset = 7500000;
389*4882a593Smuzhiyun } else {
390*4882a593Smuzhiyun os_val = VINDPM_OS_10500mV;
391*4882a593Smuzhiyun offset = 10500000;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun ret = sgm4154x_set_vindpm_offset_os(sgm, os_val);
395*4882a593Smuzhiyun if (ret) {
396*4882a593Smuzhiyun dev_err(sgm->dev, "set vin dpm error!\n");
397*4882a593Smuzhiyun return ret;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun reg_val = (vindpm - offset) / SGM4154x_VINDPM_STEP_uV;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap, SGM4154x_CHRG_CTRL_6,
403*4882a593Smuzhiyun SGM4154x_VINDPM_V_MASK, reg_val);
404*4882a593Smuzhiyun if (ret) {
405*4882a593Smuzhiyun dev_err(sgm->dev, "input voltage error!\n");
406*4882a593Smuzhiyun return ret;
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun return ret;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
sgm4154x_set_input_curr_lim(struct sgm4154x_device * sgm,int iindpm)412*4882a593Smuzhiyun static int sgm4154x_set_input_curr_lim(struct sgm4154x_device *sgm, int iindpm)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun int reg_val;
415*4882a593Smuzhiyun int ret;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun if (iindpm < SGM4154x_IINDPM_I_MIN_uA)
418*4882a593Smuzhiyun return -EINVAL;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun if ((iindpm > SGM4154x_IINDPM_I_MAX_uA) || (iindpm > sgm->init_data.ilim))
421*4882a593Smuzhiyun iindpm = min(SGM4154x_IINDPM_I_MAX_uA, sgm->init_data.ilim);
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun sgm->input_current = iindpm;
424*4882a593Smuzhiyun reg_val = (iindpm-SGM4154x_IINDPM_I_MIN_uA) / SGM4154x_IINDPM_STEP_uA;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
427*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_0,
428*4882a593Smuzhiyun SGM4154x_IINDPM_I_MASK,
429*4882a593Smuzhiyun reg_val);
430*4882a593Smuzhiyun if (ret)
431*4882a593Smuzhiyun dev_err(sgm->dev, "set input current limit error!\n");
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun return ret;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
sgm4154x_get_input_curr_lim(struct sgm4154x_device * sgm)436*4882a593Smuzhiyun static int sgm4154x_get_input_curr_lim(struct sgm4154x_device *sgm)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun int ret;
439*4882a593Smuzhiyun int ilim;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun ret = regmap_read(sgm->regmap, SGM4154x_CHRG_CTRL_0, &ilim);
442*4882a593Smuzhiyun if (ret) {
443*4882a593Smuzhiyun dev_err(sgm->dev, "get input current limit error!\n");
444*4882a593Smuzhiyun return ret;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun if (SGM4154x_IINDPM_I_MASK == (ilim & SGM4154x_IINDPM_I_MASK))
447*4882a593Smuzhiyun return SGM4154x_IINDPM_I_MAX_uA;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun ilim = (ilim & SGM4154x_IINDPM_I_MASK) * SGM4154x_IINDPM_STEP_uA + SGM4154x_IINDPM_I_MIN_uA;
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun return ilim;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
sgm4154x_watchdog_timer_reset(struct sgm4154x_device * sgm)454*4882a593Smuzhiyun static int sgm4154x_watchdog_timer_reset(struct sgm4154x_device *sgm)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun int ret;
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
459*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_1,
460*4882a593Smuzhiyun SGM4154x_WDT_RST_MASK,
461*4882a593Smuzhiyun SGM4154x_WDT_RST);
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun if (ret)
464*4882a593Smuzhiyun dev_err(sgm->dev, "set watchdog timer error!\n");
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun return ret;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun
sgm4154x_set_watchdog_timer(struct sgm4154x_device * sgm,int time)469*4882a593Smuzhiyun static int sgm4154x_set_watchdog_timer(struct sgm4154x_device *sgm, int time)
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun u8 reg_val;
472*4882a593Smuzhiyun int ret;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun if (time == 0)
475*4882a593Smuzhiyun reg_val = SGM4154x_WDT_TIMER_DISABLE;
476*4882a593Smuzhiyun else if (time == 40)
477*4882a593Smuzhiyun reg_val = SGM4154x_WDT_TIMER_40S;
478*4882a593Smuzhiyun else if (time == 80)
479*4882a593Smuzhiyun reg_val = SGM4154x_WDT_TIMER_80S;
480*4882a593Smuzhiyun else
481*4882a593Smuzhiyun reg_val = SGM4154x_WDT_TIMER_160S;
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
484*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_5,
485*4882a593Smuzhiyun SGM4154x_WDT_TIMER_MASK,
486*4882a593Smuzhiyun reg_val);
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun if (ret) {
489*4882a593Smuzhiyun dev_err(sgm->dev, "set watchdog timer error!\n");
490*4882a593Smuzhiyun return ret;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun if (time) {
494*4882a593Smuzhiyun DBG("sgm41542: enable watchdog\n");
495*4882a593Smuzhiyun if (!sgm->watchdog_enable)
496*4882a593Smuzhiyun queue_delayed_work(sgm->sgm_monitor_wq,
497*4882a593Smuzhiyun &sgm->sgm_delay_work,
498*4882a593Smuzhiyun msecs_to_jiffies(1000 * 5));
499*4882a593Smuzhiyun sgm->watchdog_enable = true;
500*4882a593Smuzhiyun } else {
501*4882a593Smuzhiyun DBG("sgm41542: disable watchdog\n");
502*4882a593Smuzhiyun sgm->watchdog_enable = false;
503*4882a593Smuzhiyun sgm4154x_watchdog_timer_reset(sgm);
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun return ret;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun
sgm4154x_enable_charger(struct sgm4154x_device * sgm)509*4882a593Smuzhiyun static int sgm4154x_enable_charger(struct sgm4154x_device *sgm)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun int ret;
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
514*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_1,
515*4882a593Smuzhiyun SGM4154x_CHRG_EN,
516*4882a593Smuzhiyun SGM4154x_CHRG_EN);
517*4882a593Smuzhiyun if (ret)
518*4882a593Smuzhiyun dev_err(sgm->dev, "enable charger error!\n");
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun return ret;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun
sgm4154x_disable_charger(struct sgm4154x_device * sgm)523*4882a593Smuzhiyun static int sgm4154x_disable_charger(struct sgm4154x_device *sgm)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun int ret;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
528*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_1,
529*4882a593Smuzhiyun SGM4154x_CHRG_EN,
530*4882a593Smuzhiyun 0);
531*4882a593Smuzhiyun if (ret)
532*4882a593Smuzhiyun dev_err(sgm->dev, "disable charger error!\n");
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun return ret;
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun
sgm4154x_set_vac_ovp(struct sgm4154x_device * sgm)537*4882a593Smuzhiyun static int sgm4154x_set_vac_ovp(struct sgm4154x_device *sgm)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun int reg_val;
540*4882a593Smuzhiyun int ret;
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun reg_val = 0xFF & SGM4154x_VAC_OVP_MASK;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
545*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_6,
546*4882a593Smuzhiyun SGM4154x_VAC_OVP_MASK,
547*4882a593Smuzhiyun reg_val);
548*4882a593Smuzhiyun if (ret)
549*4882a593Smuzhiyun dev_err(sgm->dev, "set vac ovp error!\n");
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun return ret;
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun
sgm4154x_set_recharge_volt(struct sgm4154x_device * sgm,int recharge_volt)554*4882a593Smuzhiyun static int sgm4154x_set_recharge_volt(struct sgm4154x_device *sgm, int recharge_volt)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun int reg_val;
557*4882a593Smuzhiyun int ret;
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun reg_val = (recharge_volt - SGM4154x_VRECHRG_OFFSET_mV) / SGM4154x_VRECHRG_STEP_mV;
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
562*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_4,
563*4882a593Smuzhiyun SGM4154x_VRECHARGE,
564*4882a593Smuzhiyun reg_val);
565*4882a593Smuzhiyun if (ret)
566*4882a593Smuzhiyun dev_err(sgm->dev, "set recharger error!\n");
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun return ret;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
sgm4154x_get_state(struct sgm4154x_device * sgm,struct sgm4154x_state * state)571*4882a593Smuzhiyun static int sgm4154x_get_state(struct sgm4154x_device *sgm,
572*4882a593Smuzhiyun struct sgm4154x_state *state)
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun int chrg_param_0, chrg_param_1, chrg_param_2;
575*4882a593Smuzhiyun int chrg_stat;
576*4882a593Smuzhiyun int fault;
577*4882a593Smuzhiyun int ret;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun ret = regmap_read(sgm->regmap, SGM4154x_CHRG_STAT, &chrg_stat);
580*4882a593Smuzhiyun if (ret) {
581*4882a593Smuzhiyun pr_err("read SGM4154x_CHRG_STAT fail\n");
582*4882a593Smuzhiyun return ret;
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun DBG("SGM4154x_CHRG_STAT[0x%x]: 0x%x\n", SGM4154x_CHRG_STAT, chrg_stat);
586*4882a593Smuzhiyun state->chrg_type = chrg_stat & SGM4154x_VBUS_STAT_MASK;
587*4882a593Smuzhiyun state->chrg_stat = chrg_stat & SGM4154x_CHG_STAT_MASK;
588*4882a593Smuzhiyun state->online = !!(chrg_stat & SGM4154x_PG_STAT);
589*4882a593Smuzhiyun state->therm_stat = !!(chrg_stat & SGM4154x_THERM_STAT);
590*4882a593Smuzhiyun state->vsys_stat = !!(chrg_stat & SGM4154x_VSYS_STAT);
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun ret = regmap_read(sgm->regmap, SGM4154x_CHRG_FAULT, &fault);
593*4882a593Smuzhiyun if (ret) {
594*4882a593Smuzhiyun pr_err("read SGM4154x_CHRG_FAULT fail\n");
595*4882a593Smuzhiyun return ret;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun DBG("SGM4154x_CHRG_FAULT[0x%x]: 0x%x\n", SGM4154x_CHRG_FAULT, fault);
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun state->chrg_fault = fault;
600*4882a593Smuzhiyun state->ntc_fault = fault & SGM4154x_TEMP_MASK;
601*4882a593Smuzhiyun state->health = state->ntc_fault;
602*4882a593Smuzhiyun ret = regmap_read(sgm->regmap, SGM4154x_CHRG_CTRL_0, &chrg_param_0);
603*4882a593Smuzhiyun if (ret) {
604*4882a593Smuzhiyun pr_err("read SGM4154x_CHRG_CTRL_0 fail\n");
605*4882a593Smuzhiyun return ret;
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun state->hiz_en = !!(chrg_param_0 & SGM4154x_HIZ_EN);
608*4882a593Smuzhiyun DBG("SGM4154x_CHRG_CTRL_0[0x%x]: 0x%x\n", SGM4154x_CHRG_CTRL_0, chrg_param_0);
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun ret = regmap_read(sgm->regmap, SGM4154x_CHRG_CTRL_5, &chrg_param_1);
611*4882a593Smuzhiyun if (ret) {
612*4882a593Smuzhiyun pr_err("read SGM4154x_CHRG_CTRL_5 fail\n");
613*4882a593Smuzhiyun return ret;
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun state->term_en = !!(chrg_param_1 & SGM4154x_TERM_EN);
616*4882a593Smuzhiyun DBG("SGM4154x_CHRG_CTRL_5[0x%x]: 0x%x\n", SGM4154x_CHRG_CTRL_5, chrg_param_1);
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun ret = regmap_read(sgm->regmap, SGM4154x_CHRG_CTRL_a, &chrg_param_2);
619*4882a593Smuzhiyun if (ret) {
620*4882a593Smuzhiyun pr_err("read SGM4154x_CHRG_CTRL_a fail\n");
621*4882a593Smuzhiyun return ret;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun state->vbus_gd = !!(chrg_param_2 & SGM4154x_VBUS_GOOD);
624*4882a593Smuzhiyun DBG("SGM4154x_CHRG_CTRL_a[0x%x]: 0x%x\n", SGM4154x_CHRG_CTRL_a, chrg_param_2);
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun DBG("chrg_type: 0x%x\n", state->chrg_type);
627*4882a593Smuzhiyun DBG("chrg_stat: 0x%x\n", state->chrg_stat);
628*4882a593Smuzhiyun DBG("online: 0x%x\n", state->online);
629*4882a593Smuzhiyun DBG("therm_stat: 0x%x\n", state->therm_stat);
630*4882a593Smuzhiyun DBG("vsys_stat: 0x%x\n", state->vsys_stat);
631*4882a593Smuzhiyun DBG("chrg_fault: 0x%x\n", state->chrg_fault);
632*4882a593Smuzhiyun DBG("ntc_fault: 0x%x\n", state->ntc_fault);
633*4882a593Smuzhiyun DBG("health: 0x%x\n", state->health);
634*4882a593Smuzhiyun DBG("hiz_en: 0x%x\n", state->hiz_en);
635*4882a593Smuzhiyun DBG("term_en: 0x%x\n", state->term_en);
636*4882a593Smuzhiyun DBG("vbus_gd: 0x%x\n", state->vbus_gd);
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun return ret;
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun
sgm4154x_property_is_writeable(struct power_supply * psy,enum power_supply_property prop)641*4882a593Smuzhiyun static int sgm4154x_property_is_writeable(struct power_supply *psy,
642*4882a593Smuzhiyun enum power_supply_property prop)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun switch (prop) {
645*4882a593Smuzhiyun case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
646*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
647*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
648*4882a593Smuzhiyun case POWER_SUPPLY_PROP_ONLINE:
649*4882a593Smuzhiyun return true;
650*4882a593Smuzhiyun default:
651*4882a593Smuzhiyun return false;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun
sgm4154x_charger_set_property(struct power_supply * psy,enum power_supply_property prop,const union power_supply_propval * val)655*4882a593Smuzhiyun static int sgm4154x_charger_set_property(struct power_supply *psy,
656*4882a593Smuzhiyun enum power_supply_property prop,
657*4882a593Smuzhiyun const union power_supply_propval *val)
658*4882a593Smuzhiyun {
659*4882a593Smuzhiyun struct sgm4154x_device *sgm = power_supply_get_drvdata(psy);
660*4882a593Smuzhiyun int ret = -EINVAL;
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun switch (prop) {
663*4882a593Smuzhiyun case POWER_SUPPLY_PROP_ONLINE:
664*4882a593Smuzhiyun if (val->intval) {
665*4882a593Smuzhiyun ret = sgm4154x_enable_charger(sgm);
666*4882a593Smuzhiyun sgm4154x_set_watchdog_timer(sgm, SGM4154x_WDT_TIMER_40S);
667*4882a593Smuzhiyun } else {
668*4882a593Smuzhiyun sgm4154x_set_watchdog_timer(sgm, 0);
669*4882a593Smuzhiyun ret = sgm4154x_disable_charger(sgm);
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun break;
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
674*4882a593Smuzhiyun ret = sgm4154x_set_input_curr_lim(sgm, val->intval);
675*4882a593Smuzhiyun break;
676*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
677*4882a593Smuzhiyun ret = sgm4154x_set_ichrg_curr(sgm, val->intval);
678*4882a593Smuzhiyun break;
679*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
680*4882a593Smuzhiyun ret = sgm4154x_set_chrg_volt(sgm, val->intval);
681*4882a593Smuzhiyun break;
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun default:
684*4882a593Smuzhiyun return -EINVAL;
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun return ret;
688*4882a593Smuzhiyun }
689*4882a593Smuzhiyun
sgm4154x_charger_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)690*4882a593Smuzhiyun static int sgm4154x_charger_get_property(struct power_supply *psy,
691*4882a593Smuzhiyun enum power_supply_property psp,
692*4882a593Smuzhiyun union power_supply_propval *val)
693*4882a593Smuzhiyun {
694*4882a593Smuzhiyun struct sgm4154x_device *sgm = power_supply_get_drvdata(psy);
695*4882a593Smuzhiyun struct sgm4154x_state state;
696*4882a593Smuzhiyun int ret = 0;
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun mutex_lock(&sgm->lock);
699*4882a593Smuzhiyun ret = sgm4154x_get_state(sgm, &state);
700*4882a593Smuzhiyun if (ret) {
701*4882a593Smuzhiyun dev_err(sgm->dev, "get state error!\n");
702*4882a593Smuzhiyun mutex_unlock(&sgm->lock);
703*4882a593Smuzhiyun return ret;
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun sgm->state = state;
706*4882a593Smuzhiyun mutex_unlock(&sgm->lock);
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun switch (psp) {
709*4882a593Smuzhiyun case POWER_SUPPLY_PROP_STATUS:
710*4882a593Smuzhiyun if (!state.chrg_type || (state.chrg_type == SGM4154x_OTG_MODE))
711*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
712*4882a593Smuzhiyun else if (!state.chrg_stat)
713*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
714*4882a593Smuzhiyun else if (state.chrg_stat == SGM4154x_TERM_CHRG)
715*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_FULL;
716*4882a593Smuzhiyun else
717*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_CHARGING;
718*4882a593Smuzhiyun break;
719*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CHARGE_TYPE:
720*4882a593Smuzhiyun switch (state.chrg_stat) {
721*4882a593Smuzhiyun case SGM4154x_PRECHRG:
722*4882a593Smuzhiyun val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
723*4882a593Smuzhiyun break;
724*4882a593Smuzhiyun case SGM4154x_FAST_CHRG:
725*4882a593Smuzhiyun val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
726*4882a593Smuzhiyun break;
727*4882a593Smuzhiyun case SGM4154x_TERM_CHRG:
728*4882a593Smuzhiyun val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
729*4882a593Smuzhiyun break;
730*4882a593Smuzhiyun case SGM4154x_NOT_CHRGING:
731*4882a593Smuzhiyun val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
732*4882a593Smuzhiyun break;
733*4882a593Smuzhiyun default:
734*4882a593Smuzhiyun val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
735*4882a593Smuzhiyun }
736*4882a593Smuzhiyun break;
737*4882a593Smuzhiyun case POWER_SUPPLY_PROP_MANUFACTURER:
738*4882a593Smuzhiyun val->strval = SGM4154x_MANUFACTURER;
739*4882a593Smuzhiyun break;
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun case POWER_SUPPLY_PROP_MODEL_NAME:
742*4882a593Smuzhiyun val->strval = SGM4154x_NAME;
743*4882a593Smuzhiyun break;
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun case POWER_SUPPLY_PROP_ONLINE:
746*4882a593Smuzhiyun val->intval = state.online;
747*4882a593Smuzhiyun break;
748*4882a593Smuzhiyun case POWER_SUPPLY_PROP_PRESENT:
749*4882a593Smuzhiyun val->intval = state.vbus_gd;
750*4882a593Smuzhiyun break;
751*4882a593Smuzhiyun case POWER_SUPPLY_PROP_TYPE:
752*4882a593Smuzhiyun val->intval = POWER_SUPPLY_TYPE_USB;
753*4882a593Smuzhiyun break;
754*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
755*4882a593Smuzhiyun val->intval = sgm->init_data.max_vreg;
756*4882a593Smuzhiyun break;
757*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
758*4882a593Smuzhiyun val->intval = SGM4154x_ICHRG_I_MAX_uA;
759*4882a593Smuzhiyun break;
760*4882a593Smuzhiyun case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
761*4882a593Smuzhiyun val->intval = 12 * 1000 * 1000;
762*4882a593Smuzhiyun break;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
765*4882a593Smuzhiyun val->intval = sgm4154x_get_input_curr_lim(sgm);
766*4882a593Smuzhiyun if (val->intval < 0)
767*4882a593Smuzhiyun return -EINVAL;
768*4882a593Smuzhiyun break;
769*4882a593Smuzhiyun default:
770*4882a593Smuzhiyun return -EINVAL;
771*4882a593Smuzhiyun }
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun return ret;
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun
registers_show(struct device * dev,struct device_attribute * attr,char * buf)776*4882a593Smuzhiyun static ssize_t registers_show(struct device *dev,
777*4882a593Smuzhiyun struct device_attribute *attr,
778*4882a593Smuzhiyun char *buf)
779*4882a593Smuzhiyun {
780*4882a593Smuzhiyun struct sgm4154x_device *sgm4154x = dev_get_drvdata(dev);
781*4882a593Smuzhiyun u8 tmpbuf[30];
782*4882a593Smuzhiyun int idx = 0;
783*4882a593Smuzhiyun u8 addr;
784*4882a593Smuzhiyun int val;
785*4882a593Smuzhiyun int len;
786*4882a593Smuzhiyun int ret;
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun for (addr = 0x0; addr <= SGM4154x_CHRG_CTRL_f; addr++) {
789*4882a593Smuzhiyun ret = regmap_read(sgm4154x->regmap, addr, &val);
790*4882a593Smuzhiyun if (ret == 0) {
791*4882a593Smuzhiyun len = snprintf(tmpbuf, 30,
792*4882a593Smuzhiyun "Reg[%.2X] = 0x%.2x\n",
793*4882a593Smuzhiyun addr,
794*4882a593Smuzhiyun val);
795*4882a593Smuzhiyun memcpy(&buf[idx], tmpbuf, len);
796*4882a593Smuzhiyun idx += len;
797*4882a593Smuzhiyun }
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun return idx;
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun
registers_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)803*4882a593Smuzhiyun static ssize_t registers_store(struct device *dev,
804*4882a593Smuzhiyun struct device_attribute *attr,
805*4882a593Smuzhiyun const char *buf, size_t count)
806*4882a593Smuzhiyun {
807*4882a593Smuzhiyun struct sgm4154x_device *sgm4154x = dev_get_drvdata(dev);
808*4882a593Smuzhiyun unsigned int reg;
809*4882a593Smuzhiyun int ret;
810*4882a593Smuzhiyun int val;
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun ret = sscanf(buf, "%x %x", ®, &val);
813*4882a593Smuzhiyun if (ret == 2 && reg <= SGM4154x_CHRG_CTRL_f)
814*4882a593Smuzhiyun regmap_write(sgm4154x->regmap, (unsigned char)reg, val);
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun return count;
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun static DEVICE_ATTR_RW(registers);
819*4882a593Smuzhiyun
sgm4154x_create_device_node(struct device * dev)820*4882a593Smuzhiyun static void sgm4154x_create_device_node(struct device *dev)
821*4882a593Smuzhiyun {
822*4882a593Smuzhiyun device_create_file(dev, &dev_attr_registers);
823*4882a593Smuzhiyun }
824*4882a593Smuzhiyun
sgm4154x_irq_handler_thread(int irq,void * private)825*4882a593Smuzhiyun static irqreturn_t sgm4154x_irq_handler_thread(int irq, void *private)
826*4882a593Smuzhiyun {
827*4882a593Smuzhiyun struct sgm4154x_device *sgm4154x = private;
828*4882a593Smuzhiyun struct sgm4154x_state state;
829*4882a593Smuzhiyun int ret;
830*4882a593Smuzhiyun u8 addr;
831*4882a593Smuzhiyun int val;
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun for (addr = 0x0; addr <= SGM4154x_CHRG_CTRL_f; addr++) {
834*4882a593Smuzhiyun ret = regmap_read(sgm4154x->regmap, addr, &val);
835*4882a593Smuzhiyun if (ret)
836*4882a593Smuzhiyun dev_err(sgm4154x->dev, "read addr[0x%x] error!\n", addr);
837*4882a593Smuzhiyun DBG("[0x%x]: 0x%x\n", addr, val);
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun ret = sgm4154x_get_state(sgm4154x, &state);
840*4882a593Smuzhiyun if (ret) {
841*4882a593Smuzhiyun dev_err(sgm4154x->dev, "get state error!\n");
842*4882a593Smuzhiyun return IRQ_NONE;
843*4882a593Smuzhiyun }
844*4882a593Smuzhiyun sgm4154x->state = state;
845*4882a593Smuzhiyun if (state.vbus_gd) {
846*4882a593Smuzhiyun if (sgm4154x->input_current >= DEFAULT_INPUT_CURRENT) {
847*4882a593Smuzhiyun ret = sgm4154x_set_input_curr_lim(sgm4154x, sgm4154x->input_current);
848*4882a593Smuzhiyun if (ret) {
849*4882a593Smuzhiyun dev_err(sgm4154x->dev, "set input current error!\n");
850*4882a593Smuzhiyun return IRQ_NONE;
851*4882a593Smuzhiyun }
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun }
854*4882a593Smuzhiyun power_supply_changed(sgm4154x->charger);
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun return IRQ_HANDLED;
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun static enum power_supply_property sgm4154x_power_supply_props[] = {
860*4882a593Smuzhiyun POWER_SUPPLY_PROP_TYPE,
861*4882a593Smuzhiyun POWER_SUPPLY_PROP_MANUFACTURER,
862*4882a593Smuzhiyun POWER_SUPPLY_PROP_MODEL_NAME,
863*4882a593Smuzhiyun POWER_SUPPLY_PROP_STATUS,
864*4882a593Smuzhiyun POWER_SUPPLY_PROP_ONLINE,
865*4882a593Smuzhiyun POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT,
866*4882a593Smuzhiyun POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
867*4882a593Smuzhiyun POWER_SUPPLY_PROP_CHARGE_TYPE,
868*4882a593Smuzhiyun POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
869*4882a593Smuzhiyun POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
870*4882a593Smuzhiyun POWER_SUPPLY_PROP_PRESENT
871*4882a593Smuzhiyun };
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun static char *sgm4154x_charger_supplied_to[] = {
874*4882a593Smuzhiyun "usb",
875*4882a593Smuzhiyun };
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun static struct power_supply_desc sgm4154x_power_supply_desc = {
878*4882a593Smuzhiyun .name = "sgm4154x-charger",
879*4882a593Smuzhiyun .type = POWER_SUPPLY_TYPE_USB,
880*4882a593Smuzhiyun .properties = sgm4154x_power_supply_props,
881*4882a593Smuzhiyun .num_properties = ARRAY_SIZE(sgm4154x_power_supply_props),
882*4882a593Smuzhiyun .get_property = sgm4154x_charger_get_property,
883*4882a593Smuzhiyun .set_property = sgm4154x_charger_set_property,
884*4882a593Smuzhiyun .property_is_writeable = sgm4154x_property_is_writeable,
885*4882a593Smuzhiyun };
886*4882a593Smuzhiyun
sgm4154x_is_volatile_reg(struct device * dev,unsigned int reg)887*4882a593Smuzhiyun static bool sgm4154x_is_volatile_reg(struct device *dev, unsigned int reg)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun switch (reg) {
890*4882a593Smuzhiyun case SGM4154x_CHRG_CTRL_0 ... SGM4154x_CHRG_CTRL_f:
891*4882a593Smuzhiyun return true;
892*4882a593Smuzhiyun default:
893*4882a593Smuzhiyun return false;
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun }
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun static const struct regmap_config sgm4154x_regmap_config = {
898*4882a593Smuzhiyun .reg_bits = 8,
899*4882a593Smuzhiyun .val_bits = 8,
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun .max_register = SGM4154x_CHRG_CTRL_f,
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
904*4882a593Smuzhiyun .volatile_reg = sgm4154x_is_volatile_reg,
905*4882a593Smuzhiyun };
906*4882a593Smuzhiyun
sgm4154x_power_supply_init(struct sgm4154x_device * sgm,struct device * dev)907*4882a593Smuzhiyun static int sgm4154x_power_supply_init(struct sgm4154x_device *sgm,
908*4882a593Smuzhiyun struct device *dev)
909*4882a593Smuzhiyun {
910*4882a593Smuzhiyun struct power_supply_config psy_cfg = { .drv_data = sgm,
911*4882a593Smuzhiyun .of_node = dev->of_node, };
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun psy_cfg.supplied_to = sgm4154x_charger_supplied_to;
914*4882a593Smuzhiyun psy_cfg.num_supplicants = ARRAY_SIZE(sgm4154x_charger_supplied_to);
915*4882a593Smuzhiyun psy_cfg.of_node = dev->of_node;
916*4882a593Smuzhiyun sgm->charger = devm_power_supply_register(sgm->dev,
917*4882a593Smuzhiyun &sgm4154x_power_supply_desc,
918*4882a593Smuzhiyun &psy_cfg);
919*4882a593Smuzhiyun if (IS_ERR(sgm->charger))
920*4882a593Smuzhiyun return -EINVAL;
921*4882a593Smuzhiyun
922*4882a593Smuzhiyun return 0;
923*4882a593Smuzhiyun }
924*4882a593Smuzhiyun
sgm4154x_hw_init(struct sgm4154x_device * sgm)925*4882a593Smuzhiyun static int sgm4154x_hw_init(struct sgm4154x_device *sgm)
926*4882a593Smuzhiyun {
927*4882a593Smuzhiyun struct power_supply_battery_info bat_info = { };
928*4882a593Smuzhiyun int chrg_stat, ret = 0;
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun ret = power_supply_get_battery_info(sgm->charger, &bat_info);
931*4882a593Smuzhiyun if (ret) {
932*4882a593Smuzhiyun pr_info("sgm4154x: no battery information is supplied\n");
933*4882a593Smuzhiyun /*
934*4882a593Smuzhiyun * If no battery information is supplied, we should set
935*4882a593Smuzhiyun * default charge termination current to 120 mA, and default
936*4882a593Smuzhiyun * charge termination voltage to 4.35V.
937*4882a593Smuzhiyun */
938*4882a593Smuzhiyun bat_info.constant_charge_current_max_ua =
939*4882a593Smuzhiyun SGM4154x_ICHRG_I_DEF_uA;
940*4882a593Smuzhiyun bat_info.constant_charge_voltage_max_uv =
941*4882a593Smuzhiyun SGM4154x_VREG_V_DEF_uV;
942*4882a593Smuzhiyun bat_info.precharge_current_ua =
943*4882a593Smuzhiyun SGM4154x_PRECHRG_I_DEF_uA;
944*4882a593Smuzhiyun bat_info.charge_term_current_ua =
945*4882a593Smuzhiyun SGM4154x_TERMCHRG_I_DEF_uA;
946*4882a593Smuzhiyun sgm->init_data.max_ichg =
947*4882a593Smuzhiyun SGM4154x_ICHRG_I_MAX_uA;
948*4882a593Smuzhiyun sgm->init_data.max_vreg = SGM4154x_VREG_V_DEF_uV;
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun if (!bat_info.constant_charge_current_max_ua)
951*4882a593Smuzhiyun bat_info.constant_charge_current_max_ua =
952*4882a593Smuzhiyun SGM4154x_ICHRG_I_MAX_uA;
953*4882a593Smuzhiyun if (!bat_info.constant_charge_voltage_max_uv)
954*4882a593Smuzhiyun bat_info.constant_charge_voltage_max_uv =
955*4882a593Smuzhiyun SGM4154x_VREG_V_DEF_uV;
956*4882a593Smuzhiyun if (!bat_info.precharge_current_ua)
957*4882a593Smuzhiyun bat_info.precharge_current_ua =
958*4882a593Smuzhiyun SGM4154x_PRECHRG_I_DEF_uA;
959*4882a593Smuzhiyun if (!bat_info.charge_term_current_ua)
960*4882a593Smuzhiyun bat_info.charge_term_current_ua =
961*4882a593Smuzhiyun SGM4154x_TERMCHRG_I_DEF_uA;
962*4882a593Smuzhiyun if (!sgm->init_data.max_ichg)
963*4882a593Smuzhiyun sgm->init_data.max_ichg =
964*4882a593Smuzhiyun SGM4154x_ICHRG_I_MAX_uA;
965*4882a593Smuzhiyun
966*4882a593Smuzhiyun if (bat_info.constant_charge_voltage_max_uv)
967*4882a593Smuzhiyun sgm->init_data.max_vreg = bat_info.constant_charge_voltage_max_uv;
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun ret = sgm4154x_set_watchdog_timer(sgm, 0);
970*4882a593Smuzhiyun if (ret)
971*4882a593Smuzhiyun goto err_out;
972*4882a593Smuzhiyun
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun ret = sgm4154x_set_prechrg_curr(sgm, bat_info.precharge_current_ua);
975*4882a593Smuzhiyun if (ret)
976*4882a593Smuzhiyun goto err_out;
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun ret = sgm4154x_set_chrg_volt(sgm,
979*4882a593Smuzhiyun sgm->init_data.max_vreg);
980*4882a593Smuzhiyun if (ret)
981*4882a593Smuzhiyun goto err_out;
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun ret = sgm4154x_set_term_curr(sgm,
984*4882a593Smuzhiyun bat_info.charge_term_current_ua);
985*4882a593Smuzhiyun if (ret)
986*4882a593Smuzhiyun goto err_out;
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun ret = sgm4154x_set_input_volt_lim(sgm, sgm->init_data.vlim);
989*4882a593Smuzhiyun if (ret)
990*4882a593Smuzhiyun goto err_out;
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun ret = regmap_read(sgm->regmap, SGM4154x_CHRG_STAT, &chrg_stat);
993*4882a593Smuzhiyun if (ret) {
994*4882a593Smuzhiyun pr_err("read SGM4154x_CHRG_STAT fail\n");
995*4882a593Smuzhiyun goto err_out;
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun if (!(chrg_stat & SGM4154x_PG_STAT)) {
999*4882a593Smuzhiyun ret = sgm4154x_set_input_curr_lim(sgm, DEFAULT_INPUT_CURRENT);
1000*4882a593Smuzhiyun if (ret)
1001*4882a593Smuzhiyun goto err_out;
1002*4882a593Smuzhiyun ret = sgm4154x_set_ichrg_curr(sgm,
1003*4882a593Smuzhiyun bat_info.constant_charge_current_max_ua);
1004*4882a593Smuzhiyun if (ret)
1005*4882a593Smuzhiyun goto err_out;
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun ret = sgm4154x_disable_charger(sgm);
1008*4882a593Smuzhiyun if (ret)
1009*4882a593Smuzhiyun goto err_out;
1010*4882a593Smuzhiyun }
1011*4882a593Smuzhiyun ret = sgm4154x_set_vac_ovp(sgm);
1012*4882a593Smuzhiyun if (ret)
1013*4882a593Smuzhiyun goto err_out;
1014*4882a593Smuzhiyun
1015*4882a593Smuzhiyun regmap_update_bits(sgm->regmap,
1016*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_d,
1017*4882a593Smuzhiyun 0x01,
1018*4882a593Smuzhiyun 0x00);
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun regmap_update_bits(sgm->regmap,
1021*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_a,
1022*4882a593Smuzhiyun SGM4154x_IINDPM_INT_MASK,
1023*4882a593Smuzhiyun SGM4154x_IINDPM_INT_DIS);
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun regmap_update_bits(sgm->regmap,
1026*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_a,
1027*4882a593Smuzhiyun SGM4154x_VINDPM_INT_MASK,
1028*4882a593Smuzhiyun SGM4154x_VINDPM_INT_DIS);
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun
1031*4882a593Smuzhiyun ret = sgm4154x_set_recharge_volt(sgm, 200);
1032*4882a593Smuzhiyun if (ret)
1033*4882a593Smuzhiyun goto err_out;
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun DBG("ichrg_curr:%d\n"
1036*4882a593Smuzhiyun "prechrg_curr:%d\n"
1037*4882a593Smuzhiyun "chrg_vol:%d\n"
1038*4882a593Smuzhiyun "term_curr:%d\n"
1039*4882a593Smuzhiyun "input_curr_lim:%d\n",
1040*4882a593Smuzhiyun bat_info.constant_charge_current_max_ua,
1041*4882a593Smuzhiyun bat_info.precharge_current_ua,
1042*4882a593Smuzhiyun bat_info.constant_charge_voltage_max_uv,
1043*4882a593Smuzhiyun bat_info.charge_term_current_ua,
1044*4882a593Smuzhiyun sgm->init_data.ilim);
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun return 0;
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun err_out:
1049*4882a593Smuzhiyun return ret;
1050*4882a593Smuzhiyun }
1051*4882a593Smuzhiyun
sgm4154x_parse_dt(struct sgm4154x_device * sgm)1052*4882a593Smuzhiyun static int sgm4154x_parse_dt(struct sgm4154x_device *sgm)
1053*4882a593Smuzhiyun {
1054*4882a593Smuzhiyun int ret;
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun ret = device_property_read_u32(sgm->dev,
1057*4882a593Smuzhiyun "input-voltage-limit-microvolt",
1058*4882a593Smuzhiyun &sgm->init_data.vlim);
1059*4882a593Smuzhiyun if (ret)
1060*4882a593Smuzhiyun sgm->init_data.vlim = SGM4154x_VINDPM_DEF_uV;
1061*4882a593Smuzhiyun
1062*4882a593Smuzhiyun if (sgm->init_data.vlim > SGM4154x_VINDPM_V_MAX_uV ||
1063*4882a593Smuzhiyun sgm->init_data.vlim < SGM4154x_VINDPM_V_MIN_uV)
1064*4882a593Smuzhiyun return -EINVAL;
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun ret = device_property_read_u32(sgm->dev,
1067*4882a593Smuzhiyun "input-current-limit-microamp",
1068*4882a593Smuzhiyun &sgm->init_data.ilim);
1069*4882a593Smuzhiyun if (ret)
1070*4882a593Smuzhiyun sgm->init_data.ilim = SGM4154x_IINDPM_DEF_uA;
1071*4882a593Smuzhiyun
1072*4882a593Smuzhiyun if (sgm->init_data.ilim > SGM4154x_IINDPM_I_MAX_uA ||
1073*4882a593Smuzhiyun sgm->init_data.ilim < SGM4154x_IINDPM_I_MIN_uA)
1074*4882a593Smuzhiyun return -EINVAL;
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun return 0;
1077*4882a593Smuzhiyun }
1078*4882a593Smuzhiyun
sgm4154x_set_otg_voltage(struct sgm4154x_device * sgm,int uv)1079*4882a593Smuzhiyun static int sgm4154x_set_otg_voltage(struct sgm4154x_device *sgm, int uv)
1080*4882a593Smuzhiyun {
1081*4882a593Smuzhiyun int ret = 0;
1082*4882a593Smuzhiyun int reg_val = -1;
1083*4882a593Smuzhiyun int i = 0;
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun while (i < 4) {
1086*4882a593Smuzhiyun if (uv == BOOST_VOLT_LIMIT[i]) {
1087*4882a593Smuzhiyun reg_val = i;
1088*4882a593Smuzhiyun break;
1089*4882a593Smuzhiyun }
1090*4882a593Smuzhiyun i++;
1091*4882a593Smuzhiyun }
1092*4882a593Smuzhiyun if (reg_val < 0)
1093*4882a593Smuzhiyun return reg_val;
1094*4882a593Smuzhiyun reg_val = reg_val << 4;
1095*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
1096*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_6,
1097*4882a593Smuzhiyun SGM4154x_BOOSTV,
1098*4882a593Smuzhiyun reg_val);
1099*4882a593Smuzhiyun if (ret) {
1100*4882a593Smuzhiyun dev_err(sgm->dev, "set otg voltage error!\n");
1101*4882a593Smuzhiyun return ret;
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun return ret;
1105*4882a593Smuzhiyun }
1106*4882a593Smuzhiyun
sgm4154x_set_otg_current(struct sgm4154x_device * sgm,int ua)1107*4882a593Smuzhiyun static int sgm4154x_set_otg_current(struct sgm4154x_device *sgm, int ua)
1108*4882a593Smuzhiyun {
1109*4882a593Smuzhiyun int ret = 0;
1110*4882a593Smuzhiyun
1111*4882a593Smuzhiyun if (ua == BOOST_CURRENT_LIMIT[0]) {
1112*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
1113*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_2,
1114*4882a593Smuzhiyun SGM4154x_BOOST_LIM,
1115*4882a593Smuzhiyun 0);
1116*4882a593Smuzhiyun if (ret) {
1117*4882a593Smuzhiyun dev_err(sgm->dev, "set boost current limit error!\n");
1118*4882a593Smuzhiyun return ret;
1119*4882a593Smuzhiyun }
1120*4882a593Smuzhiyun } else if (ua == BOOST_CURRENT_LIMIT[1]) {
1121*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
1122*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_2,
1123*4882a593Smuzhiyun SGM4154x_BOOST_LIM,
1124*4882a593Smuzhiyun BIT(7));
1125*4882a593Smuzhiyun if (ret) {
1126*4882a593Smuzhiyun dev_err(sgm->dev, "set boost current limit error!\n");
1127*4882a593Smuzhiyun return ret;
1128*4882a593Smuzhiyun }
1129*4882a593Smuzhiyun }
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun return ret;
1132*4882a593Smuzhiyun }
1133*4882a593Smuzhiyun
sgm4154x_enable_vbus(struct regulator_dev * rdev)1134*4882a593Smuzhiyun static int sgm4154x_enable_vbus(struct regulator_dev *rdev)
1135*4882a593Smuzhiyun {
1136*4882a593Smuzhiyun struct sgm4154x_device *sgm = rdev_get_drvdata(rdev);
1137*4882a593Smuzhiyun int ret = 0;
1138*4882a593Smuzhiyun
1139*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
1140*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_1,
1141*4882a593Smuzhiyun SGM4154x_OTG_EN,
1142*4882a593Smuzhiyun SGM4154x_OTG_EN);
1143*4882a593Smuzhiyun if (ret) {
1144*4882a593Smuzhiyun dev_err(sgm->dev, "set OTG enable error!\n");
1145*4882a593Smuzhiyun return ret;
1146*4882a593Smuzhiyun }
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun return ret;
1149*4882a593Smuzhiyun }
1150*4882a593Smuzhiyun
sgm4154x_disable_vbus(struct regulator_dev * rdev)1151*4882a593Smuzhiyun static int sgm4154x_disable_vbus(struct regulator_dev *rdev)
1152*4882a593Smuzhiyun {
1153*4882a593Smuzhiyun struct sgm4154x_device *sgm = rdev_get_drvdata(rdev);
1154*4882a593Smuzhiyun int ret = 0;
1155*4882a593Smuzhiyun
1156*4882a593Smuzhiyun ret = regmap_update_bits(sgm->regmap,
1157*4882a593Smuzhiyun SGM4154x_CHRG_CTRL_1,
1158*4882a593Smuzhiyun SGM4154x_OTG_EN,
1159*4882a593Smuzhiyun 0);
1160*4882a593Smuzhiyun if (ret) {
1161*4882a593Smuzhiyun dev_err(sgm->dev, "set OTG disable error!\n");
1162*4882a593Smuzhiyun return ret;
1163*4882a593Smuzhiyun }
1164*4882a593Smuzhiyun
1165*4882a593Smuzhiyun return ret;
1166*4882a593Smuzhiyun }
1167*4882a593Smuzhiyun
sgm4154x_is_enabled_vbus(struct regulator_dev * rdev)1168*4882a593Smuzhiyun static int sgm4154x_is_enabled_vbus(struct regulator_dev *rdev)
1169*4882a593Smuzhiyun {
1170*4882a593Smuzhiyun struct sgm4154x_device *sgm = rdev_get_drvdata(rdev);
1171*4882a593Smuzhiyun int temp = 0;
1172*4882a593Smuzhiyun int ret = 0;
1173*4882a593Smuzhiyun
1174*4882a593Smuzhiyun ret = regmap_read(sgm->regmap, SGM4154x_CHRG_CTRL_1, &temp);
1175*4882a593Smuzhiyun if (ret) {
1176*4882a593Smuzhiyun dev_err(sgm->dev, "get vbus status error!\n");
1177*4882a593Smuzhiyun return ret;
1178*4882a593Smuzhiyun }
1179*4882a593Smuzhiyun
1180*4882a593Smuzhiyun return (temp & SGM4154x_OTG_EN) ? 1 : 0;
1181*4882a593Smuzhiyun }
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun static const struct regulator_ops sgm4154x_vbus_ops = {
1184*4882a593Smuzhiyun .enable = sgm4154x_enable_vbus,
1185*4882a593Smuzhiyun .disable = sgm4154x_disable_vbus,
1186*4882a593Smuzhiyun .is_enabled = sgm4154x_is_enabled_vbus,
1187*4882a593Smuzhiyun };
1188*4882a593Smuzhiyun
1189*4882a593Smuzhiyun static struct regulator_desc sgm4154x_otg_rdesc = {
1190*4882a593Smuzhiyun .of_match = "otg-vbus",
1191*4882a593Smuzhiyun .name = "otg-vbus",
1192*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
1193*4882a593Smuzhiyun .ops = &sgm4154x_vbus_ops,
1194*4882a593Smuzhiyun .owner = THIS_MODULE,
1195*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
1196*4882a593Smuzhiyun .fixed_uV = 5000000,
1197*4882a593Smuzhiyun .n_voltages = 1,
1198*4882a593Smuzhiyun };
1199*4882a593Smuzhiyun
sgm4154x_vbus_regulator_register(struct sgm4154x_device * sgm)1200*4882a593Smuzhiyun static int sgm4154x_vbus_regulator_register(struct sgm4154x_device *sgm)
1201*4882a593Smuzhiyun {
1202*4882a593Smuzhiyun struct device_node *np;
1203*4882a593Smuzhiyun struct regulator_config config = {};
1204*4882a593Smuzhiyun int ret = 0;
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun np = of_get_child_by_name(sgm->dev->of_node, "regulators");
1207*4882a593Smuzhiyun if (!np) {
1208*4882a593Smuzhiyun dev_warn(sgm->dev, "cannot find regulators node\n");
1209*4882a593Smuzhiyun return -ENXIO;
1210*4882a593Smuzhiyun }
1211*4882a593Smuzhiyun
1212*4882a593Smuzhiyun /* otg regulator */
1213*4882a593Smuzhiyun config.dev = sgm->dev;
1214*4882a593Smuzhiyun config.driver_data = sgm;
1215*4882a593Smuzhiyun sgm->otg_rdev = devm_regulator_register(sgm->dev,
1216*4882a593Smuzhiyun &sgm4154x_otg_rdesc,
1217*4882a593Smuzhiyun &config);
1218*4882a593Smuzhiyun if (IS_ERR(sgm->otg_rdev))
1219*4882a593Smuzhiyun ret = PTR_ERR(sgm->otg_rdev);
1220*4882a593Smuzhiyun
1221*4882a593Smuzhiyun return ret;
1222*4882a593Smuzhiyun }
1223*4882a593Smuzhiyun
sgm4154x_suspend_notifier(struct notifier_block * nb,unsigned long event,void * dummy)1224*4882a593Smuzhiyun static int sgm4154x_suspend_notifier(struct notifier_block *nb,
1225*4882a593Smuzhiyun unsigned long event,
1226*4882a593Smuzhiyun void *dummy)
1227*4882a593Smuzhiyun {
1228*4882a593Smuzhiyun struct sgm4154x_device *sgm = container_of(nb, struct sgm4154x_device, pm_nb);
1229*4882a593Smuzhiyun
1230*4882a593Smuzhiyun switch (event) {
1231*4882a593Smuzhiyun
1232*4882a593Smuzhiyun case PM_SUSPEND_PREPARE:
1233*4882a593Smuzhiyun sgm->sgm4154x_suspend_flag = 1;
1234*4882a593Smuzhiyun return NOTIFY_OK;
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun case PM_POST_SUSPEND:
1237*4882a593Smuzhiyun sgm->sgm4154x_suspend_flag = 0;
1238*4882a593Smuzhiyun return NOTIFY_OK;
1239*4882a593Smuzhiyun
1240*4882a593Smuzhiyun default:
1241*4882a593Smuzhiyun return NOTIFY_DONE;
1242*4882a593Smuzhiyun }
1243*4882a593Smuzhiyun }
1244*4882a593Smuzhiyun
sgm4154x_hw_chipid_detect(struct sgm4154x_device * sgm)1245*4882a593Smuzhiyun static int sgm4154x_hw_chipid_detect(struct sgm4154x_device *sgm)
1246*4882a593Smuzhiyun {
1247*4882a593Smuzhiyun int ret = 0;
1248*4882a593Smuzhiyun int val = 0;
1249*4882a593Smuzhiyun
1250*4882a593Smuzhiyun ret = regmap_read(sgm->regmap, SGM4154x_CHRG_CTRL_b, &val);
1251*4882a593Smuzhiyun if (ret < 0)
1252*4882a593Smuzhiyun return ret;
1253*4882a593Smuzhiyun
1254*4882a593Smuzhiyun return val;
1255*4882a593Smuzhiyun }
1256*4882a593Smuzhiyun
sgm_charger_work(struct work_struct * work)1257*4882a593Smuzhiyun static void sgm_charger_work(struct work_struct *work)
1258*4882a593Smuzhiyun {
1259*4882a593Smuzhiyun struct sgm4154x_device *sgm =
1260*4882a593Smuzhiyun container_of(work,
1261*4882a593Smuzhiyun struct sgm4154x_device,
1262*4882a593Smuzhiyun sgm_delay_work.work);
1263*4882a593Smuzhiyun
1264*4882a593Smuzhiyun sgm4154x_watchdog_timer_reset(sgm);
1265*4882a593Smuzhiyun if (sgm->watchdog_enable)
1266*4882a593Smuzhiyun queue_delayed_work(sgm->sgm_monitor_wq,
1267*4882a593Smuzhiyun &sgm->sgm_delay_work,
1268*4882a593Smuzhiyun msecs_to_jiffies(1000 * 5));
1269*4882a593Smuzhiyun }
1270*4882a593Smuzhiyun
sgm4154x_probe(struct i2c_client * client,const struct i2c_device_id * id)1271*4882a593Smuzhiyun static int sgm4154x_probe(struct i2c_client *client,
1272*4882a593Smuzhiyun const struct i2c_device_id *id)
1273*4882a593Smuzhiyun {
1274*4882a593Smuzhiyun struct device *dev = &client->dev;
1275*4882a593Smuzhiyun struct sgm4154x_device *sgm;
1276*4882a593Smuzhiyun int ret;
1277*4882a593Smuzhiyun
1278*4882a593Smuzhiyun sgm = devm_kzalloc(dev, sizeof(*sgm), GFP_KERNEL);
1279*4882a593Smuzhiyun if (!sgm)
1280*4882a593Smuzhiyun return -ENOMEM;
1281*4882a593Smuzhiyun
1282*4882a593Smuzhiyun sgm->client = client;
1283*4882a593Smuzhiyun sgm->dev = dev;
1284*4882a593Smuzhiyun
1285*4882a593Smuzhiyun mutex_init(&sgm->lock);
1286*4882a593Smuzhiyun
1287*4882a593Smuzhiyun strncpy(sgm->model_name, id->name, I2C_NAME_SIZE);
1288*4882a593Smuzhiyun
1289*4882a593Smuzhiyun sgm->regmap = devm_regmap_init_i2c(client, &sgm4154x_regmap_config);
1290*4882a593Smuzhiyun if (IS_ERR(sgm->regmap)) {
1291*4882a593Smuzhiyun dev_err(dev, "Failed to allocate register map\n");
1292*4882a593Smuzhiyun return PTR_ERR(sgm->regmap);
1293*4882a593Smuzhiyun }
1294*4882a593Smuzhiyun
1295*4882a593Smuzhiyun i2c_set_clientdata(client, sgm);
1296*4882a593Smuzhiyun
1297*4882a593Smuzhiyun ret = sgm4154x_parse_dt(sgm);
1298*4882a593Smuzhiyun if (ret) {
1299*4882a593Smuzhiyun dev_err(dev, "Failed to read device tree properties%d\n", ret);
1300*4882a593Smuzhiyun return ret;
1301*4882a593Smuzhiyun }
1302*4882a593Smuzhiyun
1303*4882a593Smuzhiyun ret = sgm4154x_hw_chipid_detect(sgm);
1304*4882a593Smuzhiyun if ((ret & SGM4154x_PN_MASK) != SGM4154x_PN_ID) {
1305*4882a593Smuzhiyun pr_info("[%s] device not found !\n", __func__);
1306*4882a593Smuzhiyun return ret;
1307*4882a593Smuzhiyun }
1308*4882a593Smuzhiyun
1309*4882a593Smuzhiyun device_init_wakeup(dev, 1);
1310*4882a593Smuzhiyun
1311*4882a593Smuzhiyun if (client->irq) {
1312*4882a593Smuzhiyun ret = devm_request_threaded_irq(dev, client->irq, NULL,
1313*4882a593Smuzhiyun sgm4154x_irq_handler_thread,
1314*4882a593Smuzhiyun IRQF_TRIGGER_FALLING |
1315*4882a593Smuzhiyun IRQF_ONESHOT,
1316*4882a593Smuzhiyun "sgm41542-irq", sgm);
1317*4882a593Smuzhiyun if (ret)
1318*4882a593Smuzhiyun goto error_out;
1319*4882a593Smuzhiyun enable_irq_wake(client->irq);
1320*4882a593Smuzhiyun }
1321*4882a593Smuzhiyun
1322*4882a593Smuzhiyun sgm->pm_nb.notifier_call = sgm4154x_suspend_notifier;
1323*4882a593Smuzhiyun register_pm_notifier(&sgm->pm_nb);
1324*4882a593Smuzhiyun
1325*4882a593Smuzhiyun ret = sgm4154x_power_supply_init(sgm, dev);
1326*4882a593Smuzhiyun if (ret) {
1327*4882a593Smuzhiyun dev_err(dev, "Failed to register power supply\n");
1328*4882a593Smuzhiyun goto error_out;
1329*4882a593Smuzhiyun }
1330*4882a593Smuzhiyun
1331*4882a593Smuzhiyun ret = sgm4154x_hw_init(sgm);
1332*4882a593Smuzhiyun if (ret) {
1333*4882a593Smuzhiyun dev_err(dev, "Cannot initialize the chip.\n");
1334*4882a593Smuzhiyun goto error_out;
1335*4882a593Smuzhiyun }
1336*4882a593Smuzhiyun
1337*4882a593Smuzhiyun /* OTG setting 5V/1.2A */
1338*4882a593Smuzhiyun ret = sgm4154x_set_otg_voltage(sgm, 5000000);
1339*4882a593Smuzhiyun if (ret) {
1340*4882a593Smuzhiyun dev_err(sgm->dev, "set OTG voltage error!\n");
1341*4882a593Smuzhiyun return ret;
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun ret = sgm4154x_set_otg_current(sgm, 1200000);
1345*4882a593Smuzhiyun if (ret) {
1346*4882a593Smuzhiyun dev_err(sgm->dev, "set OTG current error!\n");
1347*4882a593Smuzhiyun return ret;
1348*4882a593Smuzhiyun }
1349*4882a593Smuzhiyun
1350*4882a593Smuzhiyun sgm->sgm_monitor_wq = alloc_ordered_workqueue("%s",
1351*4882a593Smuzhiyun WQ_MEM_RECLAIM | WQ_FREEZABLE, "sgm-monitor-wq");
1352*4882a593Smuzhiyun INIT_DELAYED_WORK(&sgm->sgm_delay_work, sgm_charger_work);
1353*4882a593Smuzhiyun
1354*4882a593Smuzhiyun sgm4154x_vbus_regulator_register(sgm);
1355*4882a593Smuzhiyun sgm4154x_create_device_node(sgm->dev);
1356*4882a593Smuzhiyun return ret;
1357*4882a593Smuzhiyun error_out:
1358*4882a593Smuzhiyun
1359*4882a593Smuzhiyun return ret;
1360*4882a593Smuzhiyun }
1361*4882a593Smuzhiyun
sgm4154x_charger_remove(struct i2c_client * client)1362*4882a593Smuzhiyun static int sgm4154x_charger_remove(struct i2c_client *client)
1363*4882a593Smuzhiyun {
1364*4882a593Smuzhiyun struct sgm4154x_device *sgm = i2c_get_clientdata(client);
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun destroy_workqueue(sgm->sgm_monitor_wq);
1367*4882a593Smuzhiyun regulator_unregister(sgm->otg_rdev);
1368*4882a593Smuzhiyun power_supply_unregister(sgm->charger);
1369*4882a593Smuzhiyun mutex_destroy(&sgm->lock);
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun return 0;
1372*4882a593Smuzhiyun }
1373*4882a593Smuzhiyun
sgm4154x_charger_shutdown(struct i2c_client * client)1374*4882a593Smuzhiyun static void sgm4154x_charger_shutdown(struct i2c_client *client)
1375*4882a593Smuzhiyun {
1376*4882a593Smuzhiyun struct sgm4154x_device *sgm = i2c_get_clientdata(client);
1377*4882a593Smuzhiyun int ret = 0;
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun sgm4154x_set_prechrg_curr(sgm, SGM4154x_PRECHRG_I_DEF_uA);
1380*4882a593Smuzhiyun ret = sgm4154x_disable_charger(sgm);
1381*4882a593Smuzhiyun if (ret)
1382*4882a593Smuzhiyun pr_err("Failed to disable charger, ret = %d\n", ret);
1383*4882a593Smuzhiyun }
1384*4882a593Smuzhiyun
1385*4882a593Smuzhiyun static const struct i2c_device_id sgm4154x_i2c_ids[] = {
1386*4882a593Smuzhiyun { "sgm41542", 0 },
1387*4882a593Smuzhiyun {},
1388*4882a593Smuzhiyun };
1389*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, sgm4154x_i2c_ids);
1390*4882a593Smuzhiyun
1391*4882a593Smuzhiyun static const struct of_device_id sgm4154x_of_match[] = {
1392*4882a593Smuzhiyun { .compatible = "sgm,sgm41542", },
1393*4882a593Smuzhiyun { },
1394*4882a593Smuzhiyun };
1395*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, sgm4154x_of_match);
1396*4882a593Smuzhiyun
1397*4882a593Smuzhiyun static struct i2c_driver sgm4154x_driver = {
1398*4882a593Smuzhiyun .driver = {
1399*4882a593Smuzhiyun .name = "sgm4154x-charger",
1400*4882a593Smuzhiyun .of_match_table = sgm4154x_of_match,
1401*4882a593Smuzhiyun },
1402*4882a593Smuzhiyun .probe = sgm4154x_probe,
1403*4882a593Smuzhiyun .remove = sgm4154x_charger_remove,
1404*4882a593Smuzhiyun .shutdown = sgm4154x_charger_shutdown,
1405*4882a593Smuzhiyun .id_table = sgm4154x_i2c_ids,
1406*4882a593Smuzhiyun };
1407*4882a593Smuzhiyun module_i2c_driver(sgm4154x_driver);
1408*4882a593Smuzhiyun
1409*4882a593Smuzhiyun MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");
1410*4882a593Smuzhiyun MODULE_DESCRIPTION("sgm4154x charger driver");
1411*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1412