30
30
#define AXP20X_PWR_STATUS_VBUS_PRESENT BIT(5)
31
31
#define AXP20X_PWR_STATUS_VBUS_USED BIT(4)
32
32
33
+ #define AXP717_PWR_STATUS_VBUS_GOOD BIT(5)
34
+
33
35
#define AXP20X_USB_STATUS_VBUS_VALID BIT(2)
34
36
37
+ #define AXP717_PMU_FAULT_VBUS BIT(5)
38
+ #define AXP717_PMU_FAULT_VSYS BIT(3)
39
+
35
40
#define AXP20X_VBUS_VHOLD_uV (b ) (4000000 + (((b) >> 3) & 7) * 100000)
36
41
#define AXP20X_VBUS_VHOLD_MASK GENMASK(5, 3)
37
42
#define AXP20X_VBUS_VHOLD_OFFSET 3
38
43
39
44
#define AXP20X_ADC_EN1_VBUS_CURR BIT(2)
40
45
#define AXP20X_ADC_EN1_VBUS_VOLT BIT(3)
41
46
47
+ #define AXP717_INPUT_VOL_LIMIT_MASK GENMASK(3, 0)
48
+ #define AXP717_INPUT_CUR_LIMIT_MASK GENMASK(5, 0)
49
+ #define AXP717_ADC_DATA_MASK GENMASK(14, 0)
50
+
51
+ #define AXP717_ADC_EN_VBUS_VOLT BIT(2)
52
+
42
53
/*
43
54
* Note do not raise the debounce time, we must report Vusb high within
44
55
* 100ms otherwise we get Vbus errors in musb.
@@ -143,6 +154,24 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
143
154
mod_delayed_work (system_power_efficient_wq , & power -> vbus_detect , DEBOUNCE_TIME );
144
155
}
145
156
157
+ static void axp717_usb_power_poll_vbus (struct work_struct * work )
158
+ {
159
+ struct axp20x_usb_power * power =
160
+ container_of (work , struct axp20x_usb_power , vbus_detect .work );
161
+ unsigned int val ;
162
+ int ret ;
163
+
164
+ ret = regmap_read (power -> regmap , AXP717_ON_INDICATE , & val );
165
+ if (ret )
166
+ return ;
167
+
168
+ val &= AXP717_PWR_STATUS_VBUS_GOOD ;
169
+ if (val != power -> old_status )
170
+ power_supply_changed (power -> supply );
171
+
172
+ power -> old_status = val ;
173
+ }
174
+
146
175
static int axp20x_get_usb_type (struct axp20x_usb_power * power ,
147
176
union power_supply_propval * val )
148
177
{
@@ -288,6 +317,91 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
288
317
return 0 ;
289
318
}
290
319
320
+ static int axp717_usb_power_get_property (struct power_supply * psy ,
321
+ enum power_supply_property psp , union power_supply_propval * val )
322
+ {
323
+ struct axp20x_usb_power * power = power_supply_get_drvdata (psy );
324
+ unsigned int v ;
325
+ int ret ;
326
+
327
+ switch (psp ) {
328
+ case POWER_SUPPLY_PROP_HEALTH :
329
+ val -> intval = POWER_SUPPLY_HEALTH_GOOD ;
330
+ ret = regmap_read (power -> regmap , AXP717_ON_INDICATE , & v );
331
+ if (ret )
332
+ return ret ;
333
+
334
+ if (!(v & AXP717_PWR_STATUS_VBUS_GOOD ))
335
+ val -> intval = POWER_SUPPLY_HEALTH_UNKNOWN ;
336
+
337
+ ret = regmap_read (power -> regmap , AXP717_PMU_FAULT_VBUS , & v );
338
+ if (ret )
339
+ return ret ;
340
+
341
+ v &= (AXP717_PMU_FAULT_VBUS | AXP717_PMU_FAULT_VSYS );
342
+ if (v ) {
343
+ val -> intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE ;
344
+ regmap_write (power -> regmap , AXP717_PMU_FAULT_VBUS , v );
345
+ }
346
+
347
+ break ;
348
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT :
349
+ ret = regmap_read (power -> regmap , AXP717_INPUT_CUR_LIMIT_CTRL , & v );
350
+ if (ret )
351
+ return ret ;
352
+
353
+ /* 50ma step size with 100ma offset. */
354
+ v &= AXP717_INPUT_CUR_LIMIT_MASK ;
355
+ val -> intval = (v * 50000 ) + 100000 ;
356
+ break ;
357
+ case POWER_SUPPLY_PROP_ONLINE :
358
+ case POWER_SUPPLY_PROP_PRESENT :
359
+ ret = regmap_read (power -> regmap , AXP717_ON_INDICATE , & v );
360
+ if (ret )
361
+ return ret ;
362
+ val -> intval = !!(v & AXP717_PWR_STATUS_VBUS_GOOD );
363
+ break ;
364
+ case POWER_SUPPLY_PROP_USB_TYPE :
365
+ return axp20x_get_usb_type (power , val );
366
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN :
367
+ ret = regmap_read (power -> regmap , AXP717_INPUT_VOL_LIMIT_CTRL , & v );
368
+ if (ret )
369
+ return ret ;
370
+
371
+ /* 80mv step size with 3.88v offset. */
372
+ v &= AXP717_INPUT_VOL_LIMIT_MASK ;
373
+ val -> intval = (v * 80000 ) + 3880000 ;
374
+ break ;
375
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW :
376
+ if (IS_ENABLED (CONFIG_AXP20X_ADC )) {
377
+ ret = iio_read_channel_processed (power -> vbus_v ,
378
+ & val -> intval );
379
+ if (ret )
380
+ return ret ;
381
+
382
+ /*
383
+ * IIO framework gives mV but Power Supply framework
384
+ * gives uV.
385
+ */
386
+ val -> intval *= 1000 ;
387
+ return 0 ;
388
+ }
389
+
390
+ ret = axp20x_read_variable_width (power -> regmap ,
391
+ AXP717_VBUS_V_H , 16 );
392
+ if (ret < 0 )
393
+ return ret ;
394
+
395
+ val -> intval = (ret % AXP717_ADC_DATA_MASK ) * 1000 ;
396
+ break ;
397
+ default :
398
+ return - EINVAL ;
399
+ }
400
+
401
+ return 0 ;
402
+
403
+ }
404
+
291
405
static int axp20x_usb_power_set_voltage_min (struct axp20x_usb_power * power ,
292
406
int intval )
293
407
{
@@ -314,6 +428,22 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
314
428
return - EINVAL ;
315
429
}
316
430
431
+ static int axp717_usb_power_set_voltage_min (struct axp20x_usb_power * power ,
432
+ int intval )
433
+ {
434
+ int val ;
435
+
436
+ /* Minimum value of 3.88v and maximum of 5.08v. */
437
+ if (intval < 3880000 || intval > 5080000 )
438
+ return - EINVAL ;
439
+
440
+ /* step size of 80ma with 3.88v offset. */
441
+ val = (intval - 3880000 ) / 80000 ;
442
+ return regmap_update_bits (power -> regmap ,
443
+ AXP717_INPUT_VOL_LIMIT_CTRL ,
444
+ AXP717_INPUT_VOL_LIMIT_MASK , val );
445
+ }
446
+
317
447
static int axp20x_usb_power_set_input_current_limit (struct axp20x_usb_power * power ,
318
448
int intval )
319
449
{
@@ -354,6 +484,29 @@ static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *pow
354
484
return regmap_field_write (power -> curr_lim_fld , reg );
355
485
}
356
486
487
+ static int axp717_usb_power_set_input_current_limit (struct axp20x_usb_power * power ,
488
+ int intval )
489
+ {
490
+ int tmp ;
491
+
492
+ /* Minimum value of 100mA and maximum value of 3.25A*/
493
+ if (intval < 100000 || intval > 3250000 )
494
+ return - EINVAL ;
495
+
496
+ if (power -> max_input_cur && (intval > power -> max_input_cur )) {
497
+ dev_warn (power -> dev ,
498
+ "reqested current %d clamped to max current %d\n" ,
499
+ intval , power -> max_input_cur );
500
+ intval = power -> max_input_cur ;
501
+ }
502
+
503
+ /* Minimum value of 100mA with step size of 50mA. */
504
+ tmp = (intval - 100000 ) / 50000 ;
505
+ return regmap_update_bits (power -> regmap ,
506
+ AXP717_INPUT_CUR_LIMIT_CTRL ,
507
+ AXP717_INPUT_CUR_LIMIT_MASK , tmp );
508
+ }
509
+
357
510
static int axp20x_usb_power_set_property (struct power_supply * psy ,
358
511
enum power_supply_property psp ,
359
512
const union power_supply_propval * val )
@@ -376,6 +529,24 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
376
529
default :
377
530
return - EINVAL ;
378
531
}
532
+ }
533
+
534
+ static int axp717_usb_power_set_property (struct power_supply * psy ,
535
+ enum power_supply_property psp ,
536
+ const union power_supply_propval * val )
537
+ {
538
+ struct axp20x_usb_power * power = power_supply_get_drvdata (psy );
539
+
540
+ switch (psp ) {
541
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT :
542
+ return axp717_usb_power_set_input_current_limit (power , val -> intval );
543
+
544
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN :
545
+ return axp717_usb_power_set_voltage_min (power , val -> intval );
546
+
547
+ default :
548
+ return - EINVAL ;
549
+ }
379
550
380
551
return - EINVAL ;
381
552
}
@@ -399,6 +570,13 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
399
570
psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT ;
400
571
}
401
572
573
+ static int axp717_usb_power_prop_writeable (struct power_supply * psy ,
574
+ enum power_supply_property psp )
575
+ {
576
+ return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
577
+ psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT ;
578
+ }
579
+
402
580
static int axp20x_configure_iio_channels (struct platform_device * pdev ,
403
581
struct axp20x_usb_power * power )
404
582
{
@@ -419,6 +597,19 @@ static int axp20x_configure_iio_channels(struct platform_device *pdev,
419
597
return 0 ;
420
598
}
421
599
600
+ static int axp717_configure_iio_channels (struct platform_device * pdev ,
601
+ struct axp20x_usb_power * power )
602
+ {
603
+ power -> vbus_v = devm_iio_channel_get (& pdev -> dev , "vbus_v" );
604
+ if (IS_ERR (power -> vbus_v )) {
605
+ if (PTR_ERR (power -> vbus_v ) == - ENODEV )
606
+ return - EPROBE_DEFER ;
607
+ return PTR_ERR (power -> vbus_v );
608
+ }
609
+
610
+ return 0 ;
611
+ }
612
+
422
613
static int axp20x_configure_adc_registers (struct axp20x_usb_power * power )
423
614
{
424
615
/* Enable vbus voltage and current measurement */
@@ -429,6 +620,14 @@ static int axp20x_configure_adc_registers(struct axp20x_usb_power *power)
429
620
AXP20X_ADC_EN1_VBUS_VOLT );
430
621
}
431
622
623
+ static int axp717_configure_adc_registers (struct axp20x_usb_power * power )
624
+ {
625
+ /* Enable vbus voltage measurement */
626
+ return regmap_update_bits (power -> regmap , AXP717_ADC_CH_EN_CONTROL ,
627
+ AXP717_ADC_EN_VBUS_VOLT ,
628
+ AXP717_ADC_EN_VBUS_VOLT );
629
+ }
630
+
432
631
static enum power_supply_property axp20x_usb_power_properties [] = {
433
632
POWER_SUPPLY_PROP_HEALTH ,
434
633
POWER_SUPPLY_PROP_PRESENT ,
@@ -447,6 +646,16 @@ static enum power_supply_property axp22x_usb_power_properties[] = {
447
646
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT ,
448
647
};
449
648
649
+ static enum power_supply_property axp717_usb_power_properties [] = {
650
+ POWER_SUPPLY_PROP_HEALTH ,
651
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT ,
652
+ POWER_SUPPLY_PROP_ONLINE ,
653
+ POWER_SUPPLY_PROP_PRESENT ,
654
+ POWER_SUPPLY_PROP_USB_TYPE ,
655
+ POWER_SUPPLY_PROP_VOLTAGE_MIN ,
656
+ POWER_SUPPLY_PROP_VOLTAGE_NOW ,
657
+ };
658
+
450
659
static enum power_supply_property axp813_usb_power_properties [] = {
451
660
POWER_SUPPLY_PROP_HEALTH ,
452
661
POWER_SUPPLY_PROP_PRESENT ,
@@ -476,6 +685,20 @@ static const struct power_supply_desc axp22x_usb_power_desc = {
476
685
.set_property = axp20x_usb_power_set_property ,
477
686
};
478
687
688
+ static const struct power_supply_desc axp717_usb_power_desc = {
689
+ .name = "axp20x-usb" ,
690
+ .type = POWER_SUPPLY_TYPE_USB ,
691
+ .properties = axp717_usb_power_properties ,
692
+ .num_properties = ARRAY_SIZE (axp717_usb_power_properties ),
693
+ .property_is_writeable = axp717_usb_power_prop_writeable ,
694
+ .get_property = axp717_usb_power_get_property ,
695
+ .set_property = axp717_usb_power_set_property ,
696
+ .usb_types = BIT (POWER_SUPPLY_USB_TYPE_SDP ) |
697
+ BIT (POWER_SUPPLY_USB_TYPE_CDP ) |
698
+ BIT (POWER_SUPPLY_USB_TYPE_DCP ) |
699
+ BIT (POWER_SUPPLY_USB_TYPE_UNKNOWN ),
700
+ };
701
+
479
702
static const struct power_supply_desc axp813_usb_power_desc = {
480
703
.name = "axp20x-usb" ,
481
704
.type = POWER_SUPPLY_TYPE_USB ,
@@ -502,6 +725,12 @@ static const char * const axp22x_irq_names[] = {
502
725
"VBUS_REMOVAL" ,
503
726
};
504
727
728
+ static const char * const axp717_irq_names [] = {
729
+ "VBUS_PLUGIN" ,
730
+ "VBUS_REMOVAL" ,
731
+ "VBUS_OVER_V" ,
732
+ };
733
+
505
734
static int axp192_usb_curr_lim_table [] = {
506
735
-1 ,
507
736
-1 ,
@@ -589,6 +818,20 @@ static const struct axp_data axp223_data = {
589
818
.axp20x_cfg_adc_reg = axp20x_configure_adc_registers ,
590
819
};
591
820
821
+ static const struct axp_data axp717_data = {
822
+ .power_desc = & axp717_usb_power_desc ,
823
+ .irq_names = axp717_irq_names ,
824
+ .num_irq_names = ARRAY_SIZE (axp717_irq_names ),
825
+ .curr_lim_fld = REG_FIELD (AXP717_INPUT_CUR_LIMIT_CTRL , 0 , 5 ),
826
+ .usb_bc_en_bit = REG_FIELD (AXP717_MODULE_EN_CONTROL_1 , 4 , 4 ),
827
+ .usb_bc_det_fld = REG_FIELD (AXP717_BC_DETECT , 5 , 7 ),
828
+ .vbus_mon_bit = REG_FIELD (AXP717_ADC_CH_EN_CONTROL , 2 , 2 ),
829
+ .vbus_needs_polling = false,
830
+ .axp20x_read_vbus = & axp717_usb_power_poll_vbus ,
831
+ .axp20x_cfg_iio_chan = axp717_configure_iio_channels ,
832
+ .axp20x_cfg_adc_reg = axp717_configure_adc_registers ,
833
+ };
834
+
592
835
static const struct axp_data axp813_data = {
593
836
.power_desc = & axp813_usb_power_desc ,
594
837
.irq_names = axp22x_irq_names ,
@@ -816,6 +1059,9 @@ static const struct of_device_id axp20x_usb_power_match[] = {
816
1059
}, {
817
1060
.compatible = "x-powers,axp223-usb-power-supply" ,
818
1061
.data = & axp223_data ,
1062
+ }, {
1063
+ .compatible = "x-powers,axp717-usb-power-supply" ,
1064
+ .data = & axp717_data ,
819
1065
}, {
820
1066
.compatible = "x-powers,axp813-usb-power-supply" ,
821
1067
.data = & axp813_data ,
0 commit comments