lkml.org 
[lkml]   [2022]   [Jun]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v4 11/15] power: supply: axp20x_usb_power: Add support for AXP192
    Date
    The AXP192's USB power supply is similar to the AXP202 but it has
    different USB current limits and a different offset for the VBUS
    status register.

    Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
    Reviewed-by: Chen-Yu Tsai <wens@csie.org>
    Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
    ---
    drivers/power/supply/axp20x_usb_power.c | 84 +++++++++++++++++++++----
    1 file changed, 73 insertions(+), 11 deletions(-)

    diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
    index a1e6d1d44808..f83e2ed6d507 100644
    --- a/drivers/power/supply/axp20x_usb_power.c
    +++ b/drivers/power/supply/axp20x_usb_power.c
    @@ -48,6 +48,9 @@
    #define AXP813_VBUS_CLIMIT_2000mA 2
    #define AXP813_VBUS_CLIMIT_2500mA 3

    +#define AXP192_VBUS_CLIMIT_EN BIT(1)
    +#define AXP192_VBUS_CLIMIT_100mA BIT(0)
    +
    #define AXP20X_ADC_EN1_VBUS_CURR BIT(2)
    #define AXP20X_ADC_EN1_VBUS_VOLT BIT(3)

    @@ -121,6 +124,25 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
    mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
    }

    +static int axp192_get_current_max(struct axp20x_usb_power *power, int *val)
    +{
    + unsigned int v;
    + int ret;
    +
    + ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
    + if (ret)
    + return ret;
    +
    + if (!(v & AXP192_VBUS_CLIMIT_EN))
    + *val = -1;
    + else if (v & AXP192_VBUS_CLIMIT_100mA)
    + *val = 100000;
    + else
    + *val = 500000;
    +
    + return 0;
    +}
    +
    static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val)
    {
    unsigned int v;
    @@ -179,7 +201,7 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
    enum power_supply_property psp, union power_supply_propval *val)
    {
    struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
    - unsigned int input, v;
    + unsigned int input, v, reg;
    int ret;

    switch (psp) {
    @@ -215,6 +237,8 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
    case POWER_SUPPLY_PROP_CURRENT_MAX:
    if (power->axp20x_id == AXP813_ID)
    return axp813_get_current_max(power, &val->intval);
    + else if (power->axp20x_id == AXP192_ID)
    + return axp192_get_current_max(power, &val->intval);
    return axp20x_get_current_max(power, &val->intval);
    case POWER_SUPPLY_PROP_CURRENT_NOW:
    if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
    @@ -256,16 +280,19 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,

    val->intval = POWER_SUPPLY_HEALTH_GOOD;

    - if (power->axp20x_id == AXP202_ID) {
    - ret = regmap_read(power->regmap,
    - AXP20X_USB_OTG_STATUS, &v);
    - if (ret)
    - return ret;
    + if (power->axp20x_id == AXP192_ID)
    + reg = AXP192_USB_OTG_STATUS;
    + else if (power->axp20x_id == AXP202_ID)
    + reg = AXP20X_USB_OTG_STATUS;
    + else
    + break; /* Other chips lack the OTG status register */

    - if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
    - val->intval =
    - POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
    - }
    + ret = regmap_read(power->regmap, reg, &v);
    + if (ret)
    + return ret;
    +
    + if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
    + val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
    break;
    case POWER_SUPPLY_PROP_PRESENT:
    val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
    @@ -316,6 +343,28 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
    return -EINVAL;
    }

    +static int axp192_usb_power_set_current_max(struct axp20x_usb_power *power,
    + int intval)
    +{
    + const unsigned int mask = AXP192_VBUS_CLIMIT_EN |
    + AXP192_VBUS_CLIMIT_100mA;
    + unsigned int val;
    +
    + switch (intval) {
    + case 100000:
    + val = AXP192_VBUS_CLIMIT_EN | AXP192_VBUS_CLIMIT_100mA;
    + break;
    + case 500000:
    + val = AXP192_VBUS_CLIMIT_EN;
    + break;
    + default:
    + return -EINVAL;
    + }
    +
    + return regmap_update_bits(power->regmap,
    + AXP20X_VBUS_IPSOUT_MGMT, mask, val);
    +}
    +
    static int axp813_usb_power_set_current_max(struct axp20x_usb_power *power,
    int intval)
    {
    @@ -383,6 +432,9 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
    if (power->axp20x_id == AXP813_ID)
    return axp813_usb_power_set_current_max(power,
    val->intval);
    + else if (power->axp20x_id == AXP192_ID)
    + return axp192_usb_power_set_current_max(power,
    + val->intval);
    return axp20x_usb_power_set_current_max(power, val->intval);

    default:
    @@ -468,6 +520,13 @@ struct axp_data {
    enum axp20x_variants axp20x_id;
    };

    +static const struct axp_data axp192_data = {
    + .power_desc = &axp20x_usb_power_desc,
    + .irq_names = axp20x_irq_names,
    + .num_irq_names = ARRAY_SIZE(axp20x_irq_names),
    + .axp20x_id = AXP192_ID,
    +};
    +
    static const struct axp_data axp202_data = {
    .power_desc = &axp20x_usb_power_desc,
    .irq_names = axp20x_irq_names,
    @@ -600,7 +659,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
    if (ret)
    return ret;

    - if (power->axp20x_id == AXP202_ID) {
    + if (power->axp20x_id == AXP192_ID || power->axp20x_id == AXP202_ID) {
    /* Enable vbus valid checking */
    ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
    AXP20X_VBUS_MON_VBUS_VALID,
    @@ -659,6 +718,9 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)

    static const struct of_device_id axp20x_usb_power_match[] = {
    {
    + .compatible = "x-powers,axp192-usb-power-supply",
    + .data = &axp192_data,
    + }, {
    .compatible = "x-powers,axp202-usb-power-supply",
    .data = &axp202_data,
    }, {
    --
    2.35.1
    \
     
     \ /
      Last update: 2022-06-29 16:31    [W:2.938 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site