diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt index d20b1034e967..585a95546288 100644 --- a/Documentation/devicetree/bindings/mfd/axp20x.txt +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt @@ -22,6 +22,11 @@ Optional properties: AXP152/20X: range: 750-1875, Default: 1.5 MHz AXP22X/80X: range: 1800-4050, Default: 3 MHz +- x-powers,drive-vbus-en: axp221 / axp223 only boolean, set this when the + N_VBUSEN pin is used as an output pin to control an external + regulator to drive the OTG VBus, rather then as an input pin + which signals whether the board is driving OTG VBus or not. + - -supply: a phandle to the regulator supply node. May be omitted if inputs are unregulated, such as using the IPSOUT output from the PMIC. @@ -79,6 +84,7 @@ ELDO3 : LDO : eldoin-supply : shared supply LDO_IO0 : LDO : ips-supply : GPIO 0 LDO_IO1 : LDO : ips-supply : GPIO 1 RTC_LDO : LDO : ips-supply : always on +DRIVEVBUS : Enable output : drivevbus-supply : external regulator AXP809 regulators, type, and corresponding input supply names: diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 728be64e817a..6d9ac76a772f 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -36,6 +36,8 @@ #define AXP20X_FREQ_DCDC_MASK 0x0f +#define AXP22X_MISC_N_VBUSEN_FUNC BIT(4) + #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, _enable_val, _disable_val) \ [_family##_##_id] = { \ @@ -230,6 +232,18 @@ static const struct regulator_desc axp22x_regulators[] = { AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000), }; +static const struct regulator_desc axp22x_drivevbus_regulator = { + .name = "drivevbus", + .supply_name = "drivevbus", + .of_match = of_match_ptr("drivevbus"), + .regulators_node = of_match_ptr("regulators"), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = AXP20X_VBUS_IPSOUT_MGMT, + .enable_mask = BIT(2), + .ops = &axp20x_ops_sw, +}; + static const struct regulator_linear_range axp809_dcdc4_ranges[] = { REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2f, 20000), REGULATOR_LINEAR_RANGE(1800000, 0x30, 0x38, 100000), @@ -411,6 +425,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev) u32 workmode; const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name; const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name; + bool drivevbus = false; switch (axp20x->variant) { case AXP202_ID: @@ -422,6 +437,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev) case AXP223_ID: regulators = axp22x_regulators; nregulators = AXP22X_REG_ID_MAX; + drivevbus = of_property_read_bool(pdev->dev.parent->of_node, + "x-powers,drive-vbus-en"); break; case AXP809_ID: regulators = axp809_regulators; @@ -500,6 +517,19 @@ static int axp20x_regulator_probe(struct platform_device *pdev) &dcdc5_name); } + if (drivevbus) { + /* Change N_VBUSEN sense pin to DRIVEVBUS output pin */ + regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP, + AXP22X_MISC_N_VBUSEN_FUNC, 0); + rdev = devm_regulator_register(&pdev->dev, + &axp22x_drivevbus_regulator, + &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "Failed to register drivevbus\n"); + return PTR_ERR(rdev); + } + } + return 0; }