3737#define AXP20X_VBUS_VHOLD_uV (b ) (4000000 + (((b) >> 3) & 7) * 100000)
3838#define AXP20X_VBUS_VHOLD_MASK GENMASK(5, 3)
3939#define AXP20X_VBUS_VHOLD_OFFSET 3
40- #define AXP20X_VBUS_CLIMIT_MASK 3
41- #define AXP20X_VBUS_CLIMIT_900mA 0
42- #define AXP20X_VBUS_CLIMIT_500mA 1
43- #define AXP20X_VBUS_CLIMIT_100mA 2
44- #define AXP20X_VBUS_CLIMIT_NONE 3
45-
46- #define AXP813_VBUS_CLIMIT_900mA 0
47- #define AXP813_VBUS_CLIMIT_1500mA 1
48- #define AXP813_VBUS_CLIMIT_2000mA 2
49- #define AXP813_VBUS_CLIMIT_2500mA 3
5040
5141#define AXP20X_ADC_EN1_VBUS_CURR BIT(2)
5242#define AXP20X_ADC_EN1_VBUS_VOLT BIT(3)
6151 */
6252#define DEBOUNCE_TIME msecs_to_jiffies(50)
6353
54+ struct axp_data {
55+ const struct power_supply_desc * power_desc ;
56+ const char * const * irq_names ;
57+ unsigned int num_irq_names ;
58+ enum axp20x_variants axp20x_id ;
59+ const int * curr_lim_table ;
60+ struct reg_field curr_lim_fld ;
61+ };
62+
6463struct axp20x_usb_power {
6564 struct regmap * regmap ;
65+ struct regmap_field * curr_lim_fld ;
6666 struct power_supply * supply ;
6767 enum axp20x_variants axp20x_id ;
68+ const struct axp_data * axp_data ;
6869 struct iio_channel * vbus_v ;
6970 struct iio_channel * vbus_i ;
7071 struct delayed_work vbus_detect ;
@@ -121,60 +122,6 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
121122 mod_delayed_work (system_power_efficient_wq , & power -> vbus_detect , DEBOUNCE_TIME );
122123}
123124
124- static int axp20x_get_current_max (struct axp20x_usb_power * power , int * val )
125- {
126- unsigned int v ;
127- int ret = regmap_read (power -> regmap , AXP20X_VBUS_IPSOUT_MGMT , & v );
128-
129- if (ret )
130- return ret ;
131-
132- switch (v & AXP20X_VBUS_CLIMIT_MASK ) {
133- case AXP20X_VBUS_CLIMIT_100mA :
134- if (power -> axp20x_id == AXP221_ID )
135- * val = -1 ; /* No 100mA limit */
136- else
137- * val = 100000 ;
138- break ;
139- case AXP20X_VBUS_CLIMIT_500mA :
140- * val = 500000 ;
141- break ;
142- case AXP20X_VBUS_CLIMIT_900mA :
143- * val = 900000 ;
144- break ;
145- case AXP20X_VBUS_CLIMIT_NONE :
146- * val = -1 ;
147- break ;
148- }
149-
150- return 0 ;
151- }
152-
153- static int axp813_get_current_max (struct axp20x_usb_power * power , int * val )
154- {
155- unsigned int v ;
156- int ret = regmap_read (power -> regmap , AXP20X_VBUS_IPSOUT_MGMT , & v );
157-
158- if (ret )
159- return ret ;
160-
161- switch (v & AXP20X_VBUS_CLIMIT_MASK ) {
162- case AXP813_VBUS_CLIMIT_900mA :
163- * val = 900000 ;
164- break ;
165- case AXP813_VBUS_CLIMIT_1500mA :
166- * val = 1500000 ;
167- break ;
168- case AXP813_VBUS_CLIMIT_2000mA :
169- * val = 2000000 ;
170- break ;
171- case AXP813_VBUS_CLIMIT_2500mA :
172- * val = 2500000 ;
173- break ;
174- }
175- return 0 ;
176- }
177-
178125static int axp20x_usb_power_get_property (struct power_supply * psy ,
179126 enum power_supply_property psp , union power_supply_propval * val )
180127{
@@ -213,9 +160,12 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
213160 val -> intval = ret * 1700 ; /* 1 step = 1.7 mV */
214161 return 0 ;
215162 case POWER_SUPPLY_PROP_CURRENT_MAX :
216- if (power -> axp20x_id == AXP813_ID )
217- return axp813_get_current_max (power , & val -> intval );
218- return axp20x_get_current_max (power , & val -> intval );
163+ ret = regmap_field_read (power -> curr_lim_fld , & v );
164+ if (ret )
165+ return ret ;
166+
167+ val -> intval = power -> axp_data -> curr_lim_table [v ];
168+ return 0 ;
219169 case POWER_SUPPLY_PROP_CURRENT_NOW :
220170 if (IS_ENABLED (CONFIG_AXP20X_ADC )) {
221171 ret = iio_read_channel_processed (power -> vbus_i ,
@@ -316,50 +266,17 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
316266 return - EINVAL ;
317267}
318268
319- static int axp813_usb_power_set_current_max (struct axp20x_usb_power * power ,
320- int intval )
269+ static int axp20x_usb_power_set_current_max (struct axp20x_usb_power * power , int intval )
321270{
322- int val ;
271+ const unsigned int max = GENMASK (power -> axp_data -> curr_lim_fld .msb ,
272+ power -> axp_data -> curr_lim_fld .lsb );
323273
324- switch (intval ) {
325- case 900000 :
326- return regmap_update_bits (power -> regmap ,
327- AXP20X_VBUS_IPSOUT_MGMT ,
328- AXP20X_VBUS_CLIMIT_MASK ,
329- AXP813_VBUS_CLIMIT_900mA );
330- case 1500000 :
331- case 2000000 :
332- case 2500000 :
333- val = (intval - 1000000 ) / 500000 ;
334- return regmap_update_bits (power -> regmap ,
335- AXP20X_VBUS_IPSOUT_MGMT ,
336- AXP20X_VBUS_CLIMIT_MASK , val );
337- default :
274+ if (intval == -1 )
338275 return - EINVAL ;
339- }
340276
341- return - EINVAL ;
342- }
343-
344- static int axp20x_usb_power_set_current_max (struct axp20x_usb_power * power ,
345- int intval )
346- {
347- int val ;
348-
349- switch (intval ) {
350- case 100000 :
351- if (power -> axp20x_id == AXP221_ID )
352- return - EINVAL ;
353- fallthrough ;
354- case 500000 :
355- case 900000 :
356- val = (900000 - intval ) / 400000 ;
357- return regmap_update_bits (power -> regmap ,
358- AXP20X_VBUS_IPSOUT_MGMT ,
359- AXP20X_VBUS_CLIMIT_MASK , val );
360- default :
361- return - EINVAL ;
362- }
277+ for (unsigned int i = 0 ; i <= max ; ++ i )
278+ if (power -> axp_data -> curr_lim_table [i ] == intval )
279+ return regmap_field_write (power -> curr_lim_fld , i );
363280
364281 return - EINVAL ;
365282}
@@ -380,9 +297,6 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
380297 return axp20x_usb_power_set_voltage_min (power , val -> intval );
381298
382299 case POWER_SUPPLY_PROP_CURRENT_MAX :
383- if (power -> axp20x_id == AXP813_ID )
384- return axp813_usb_power_set_current_max (power ,
385- val -> intval );
386300 return axp20x_usb_power_set_current_max (power , val -> intval );
387301
388302 default :
@@ -461,39 +375,61 @@ static const char * const axp22x_irq_names[] = {
461375 "VBUS_REMOVAL" ,
462376};
463377
464- struct axp_data {
465- const struct power_supply_desc * power_desc ;
466- const char * const * irq_names ;
467- unsigned int num_irq_names ;
468- enum axp20x_variants axp20x_id ;
378+ static int axp20x_usb_curr_lim_table [] = {
379+ 900000 ,
380+ 500000 ,
381+ 100000 ,
382+ -1 ,
383+ };
384+
385+ static int axp221_usb_curr_lim_table [] = {
386+ 900000 ,
387+ 500000 ,
388+ -1 ,
389+ -1 ,
390+ };
391+
392+ static int axp813_usb_curr_lim_table [] = {
393+ 900000 ,
394+ 1500000 ,
395+ 2000000 ,
396+ 2500000 ,
469397};
470398
471399static const struct axp_data axp202_data = {
472400 .power_desc = & axp20x_usb_power_desc ,
473401 .irq_names = axp20x_irq_names ,
474402 .num_irq_names = ARRAY_SIZE (axp20x_irq_names ),
475403 .axp20x_id = AXP202_ID ,
404+ .curr_lim_table = axp20x_usb_curr_lim_table ,
405+ .curr_lim_fld = REG_FIELD (AXP20X_VBUS_IPSOUT_MGMT , 0 , 1 ),
476406};
477407
478408static const struct axp_data axp221_data = {
479409 .power_desc = & axp22x_usb_power_desc ,
480410 .irq_names = axp22x_irq_names ,
481411 .num_irq_names = ARRAY_SIZE (axp22x_irq_names ),
482412 .axp20x_id = AXP221_ID ,
413+ .curr_lim_table = axp221_usb_curr_lim_table ,
414+ .curr_lim_fld = REG_FIELD (AXP20X_VBUS_IPSOUT_MGMT , 0 , 1 ),
483415};
484416
485417static const struct axp_data axp223_data = {
486418 .power_desc = & axp22x_usb_power_desc ,
487419 .irq_names = axp22x_irq_names ,
488420 .num_irq_names = ARRAY_SIZE (axp22x_irq_names ),
489421 .axp20x_id = AXP223_ID ,
422+ .curr_lim_table = axp20x_usb_curr_lim_table ,
423+ .curr_lim_fld = REG_FIELD (AXP20X_VBUS_IPSOUT_MGMT , 0 , 1 ),
490424};
491425
492426static const struct axp_data axp813_data = {
493427 .power_desc = & axp22x_usb_power_desc ,
494428 .irq_names = axp22x_irq_names ,
495429 .num_irq_names = ARRAY_SIZE (axp22x_irq_names ),
496430 .axp20x_id = AXP813_ID ,
431+ .curr_lim_table = axp813_usb_curr_lim_table ,
432+ .curr_lim_fld = REG_FIELD (AXP20X_VBUS_IPSOUT_MGMT , 0 , 1 ),
497433};
498434
499435#ifdef CONFIG_PM_SLEEP
@@ -592,9 +528,15 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
592528 platform_set_drvdata (pdev , power );
593529
594530 power -> axp20x_id = axp_data -> axp20x_id ;
531+ power -> axp_data = axp_data ;
595532 power -> regmap = axp20x -> regmap ;
596533 power -> num_irqs = axp_data -> num_irq_names ;
597534
535+ power -> curr_lim_fld = devm_regmap_field_alloc (& pdev -> dev , power -> regmap ,
536+ axp_data -> curr_lim_fld );
537+ if (IS_ERR (power -> curr_lim_fld ))
538+ return PTR_ERR (power -> curr_lim_fld );
539+
598540 ret = devm_delayed_work_autocancel (& pdev -> dev , & power -> vbus_detect ,
599541 axp20x_usb_power_poll_vbus );
600542 if (ret )
0 commit comments