diff --git a/Documentation/devicetree/bindings/regulator/tps65023.txt b/Documentation/devicetree/bindings/regulator/tps65023.txt new file mode 100644 index 000000000000..a4714e4da370 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/tps65023.txt @@ -0,0 +1,60 @@ +TPS65023 family of regulators + +Required properties: +- compatible: Must be one of the following. + "ti,tps65020", + "ti,tps65021", + "ti,tps65023", +- reg: I2C slave address +- regulators: list of regulators provided by this controller, must be named + after their hardware counterparts: VDCDC[1-3] and LDO[1-2] +- regulators: This is the list of child nodes that specify the regulator + initialization data for defined regulators. The definition for each of + these nodes is defined using the standard binding for regulators found at + Documentation/devicetree/bindings/regulator/regulator.txt. + +Each regulator is defined using the standard binding for regulators. + +Example: + + tps65023@48 { + compatible = "ti,tps65023"; + reg = <0x48>; + + regulators { + VDCDC1 { + regulator-name = "vdd_mpu"; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + VDCDC2 { + regulator-name = "vdd_core"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + VDCDC3 { + regulator-name = "vdd_io"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + LDO1 { + regulator-name = "vdd_usb18"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + LDO2 { + regulator-name = "vdd_usb33"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c index 5de95c265c1a..4a174cdb50b6 100644 --- a/drivers/mfd/tps6105x.c +++ b/drivers/mfd/tps6105x.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -25,73 +25,18 @@ #include #include -int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value) -{ - int ret; - - ret = mutex_lock_interruptible(&tps6105x->lock); - if (ret) - return ret; - ret = i2c_smbus_write_byte_data(tps6105x->client, reg, value); - mutex_unlock(&tps6105x->lock); - if (ret < 0) - return ret; - - return 0; -} -EXPORT_SYMBOL(tps6105x_set); - -int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf) -{ - int ret; - - ret = mutex_lock_interruptible(&tps6105x->lock); - if (ret) - return ret; - ret = i2c_smbus_read_byte_data(tps6105x->client, reg); - mutex_unlock(&tps6105x->lock); - if (ret < 0) - return ret; - - *buf = ret; - return 0; -} -EXPORT_SYMBOL(tps6105x_get); - -/* - * Masks off the bits in the mask and sets the bits in the bitvalues - * parameter in one atomic operation - */ -int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg, - u8 bitmask, u8 bitvalues) -{ - int ret; - u8 regval; - - ret = mutex_lock_interruptible(&tps6105x->lock); - if (ret) - return ret; - ret = i2c_smbus_read_byte_data(tps6105x->client, reg); - if (ret < 0) - goto fail; - regval = ret; - regval = (~bitmask & regval) | (bitmask & bitvalues); - ret = i2c_smbus_write_byte_data(tps6105x->client, reg, regval); -fail: - mutex_unlock(&tps6105x->lock); - if (ret < 0) - return ret; - - return 0; -} -EXPORT_SYMBOL(tps6105x_mask_and_set); +static struct regmap_config tps6105x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = TPS6105X_REG_3, +}; static int tps6105x_startup(struct tps6105x *tps6105x) { int ret; - u8 regval; + unsigned int regval; - ret = tps6105x_get(tps6105x, TPS6105X_REG_0, ®val); + ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, ®val); if (ret) return ret; switch (regval >> TPS6105X_REG0_MODE_SHIFT) { @@ -145,11 +90,14 @@ static int tps6105x_probe(struct i2c_client *client, if (!tps6105x) return -ENOMEM; + tps6105x->regmap = devm_regmap_init_i2c(client, &tps6105x_regmap_config); + if (IS_ERR(tps6105x->regmap)) + return PTR_ERR(tps6105x->regmap); + i2c_set_clientdata(client, tps6105x); tps6105x->client = client; pdata = dev_get_platdata(&client->dev); tps6105x->pdata = pdata; - mutex_init(&tps6105x->lock); ret = tps6105x_startup(tps6105x); if (ret) { @@ -198,7 +146,7 @@ static int tps6105x_remove(struct i2c_client *client) mfd_remove_devices(&client->dev); /* Put chip in shutdown mode */ - tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0, + regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0, TPS6105X_REG0_MODE_MASK, TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e9b94d7be7c9..73b7683355cd 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -132,6 +132,45 @@ static bool have_full_constraints(void) return has_full_constraints || of_have_populated_dt(); } +/** + * regulator_lock_supply - lock a regulator and its supplies + * @rdev: regulator source + */ +static void regulator_lock_supply(struct regulator_dev *rdev) +{ + struct regulator *supply; + int i = 0; + + while (1) { + mutex_lock_nested(&rdev->mutex, i++); + supply = rdev->supply; + + if (!rdev->supply) + return; + + rdev = supply->rdev; + } +} + +/** + * regulator_unlock_supply - unlock a regulator and its supplies + * @rdev: regulator source + */ +static void regulator_unlock_supply(struct regulator_dev *rdev) +{ + struct regulator *supply; + + while (1) { + mutex_unlock(&rdev->mutex); + supply = rdev->supply; + + if (!rdev->supply) + return; + + rdev = supply->rdev; + } +} + /** * of_get_regulator - get a regulator device node based on supply name * @dev: Device pointer for the consumer (of regulator) device @@ -2364,6 +2403,40 @@ static int _regulator_is_enabled(struct regulator_dev *rdev) return rdev->desc->ops->is_enabled(rdev); } +static int _regulator_list_voltage(struct regulator *regulator, + unsigned selector, int lock) +{ + struct regulator_dev *rdev = regulator->rdev; + const struct regulator_ops *ops = rdev->desc->ops; + int ret; + + if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) + return rdev->desc->fixed_uV; + + if (ops->list_voltage) { + if (selector >= rdev->desc->n_voltages) + return -EINVAL; + if (lock) + mutex_lock(&rdev->mutex); + ret = ops->list_voltage(rdev, selector); + if (lock) + mutex_unlock(&rdev->mutex); + } else if (rdev->supply) { + ret = _regulator_list_voltage(rdev->supply, selector, lock); + } else { + return -EINVAL; + } + + if (ret > 0) { + if (ret < rdev->constraints->min_uV) + ret = 0; + else if (ret > rdev->constraints->max_uV) + ret = 0; + } + + return ret; +} + /** * regulator_is_enabled - is the regulator output enabled * @regulator: regulator source @@ -2453,33 +2526,7 @@ EXPORT_SYMBOL_GPL(regulator_count_voltages); */ int regulator_list_voltage(struct regulator *regulator, unsigned selector) { - struct regulator_dev *rdev = regulator->rdev; - const struct regulator_ops *ops = rdev->desc->ops; - int ret; - - if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) - return rdev->desc->fixed_uV; - - if (ops->list_voltage) { - if (selector >= rdev->desc->n_voltages) - return -EINVAL; - mutex_lock(&rdev->mutex); - ret = ops->list_voltage(rdev, selector); - mutex_unlock(&rdev->mutex); - } else if (rdev->supply) { - ret = regulator_list_voltage(rdev->supply, selector); - } else { - return -EINVAL; - } - - if (ret > 0) { - if (ret < rdev->constraints->min_uV) - ret = 0; - else if (ret > rdev->constraints->max_uV) - ret = 0; - } - - return ret; + return _regulator_list_voltage(regulator, selector, 1); } EXPORT_SYMBOL_GPL(regulator_list_voltage); @@ -2614,6 +2661,23 @@ int regulator_is_supported_voltage(struct regulator *regulator, } EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); +static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, + int max_uV) +{ + const struct regulator_desc *desc = rdev->desc; + + if (desc->ops->map_voltage) + return desc->ops->map_voltage(rdev, min_uV, max_uV); + + if (desc->ops->list_voltage == regulator_list_voltage_linear) + return regulator_map_voltage_linear(rdev, min_uV, max_uV); + + if (desc->ops->list_voltage == regulator_list_voltage_linear_range) + return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); + + return regulator_map_voltage_iterate(rdev, min_uV, max_uV); +} + static int _regulator_call_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) @@ -2702,23 +2766,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } } else if (rdev->desc->ops->set_voltage_sel) { - if (rdev->desc->ops->map_voltage) { - ret = rdev->desc->ops->map_voltage(rdev, min_uV, - max_uV); - } else { - if (rdev->desc->ops->list_voltage == - regulator_list_voltage_linear) - ret = regulator_map_voltage_linear(rdev, - min_uV, max_uV); - else if (rdev->desc->ops->list_voltage == - regulator_list_voltage_linear_range) - ret = regulator_map_voltage_linear_range(rdev, - min_uV, max_uV); - else - ret = regulator_map_voltage_iterate(rdev, - min_uV, max_uV); - } - + ret = regulator_map_voltage(rdev, min_uV, max_uV); if (ret >= 0) { best_val = rdev->desc->ops->list_voltage(rdev, ret); if (min_uV <= best_val && max_uV >= best_val) { @@ -2769,32 +2817,15 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, return ret; } -/** - * regulator_set_voltage - set regulator output voltage - * @regulator: regulator source - * @min_uV: Minimum required voltage in uV - * @max_uV: Maximum acceptable voltage in uV - * - * Sets a voltage regulator to the desired output voltage. This can be set - * during any regulator state. IOW, regulator can be disabled or enabled. - * - * If the regulator is enabled then the voltage will change to the new value - * immediately otherwise if the regulator is disabled the regulator will - * output at the new voltage when enabled. - * - * NOTE: If the regulator is shared between several devices then the lowest - * request voltage that meets the system constraints will be used. - * Regulator system constraints must be set for this regulator before - * calling this function otherwise this call will fail. - */ -int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) +static int regulator_set_voltage_unlocked(struct regulator *regulator, + int min_uV, int max_uV) { struct regulator_dev *rdev = regulator->rdev; int ret = 0; int old_min_uV, old_max_uV; int current_uV; - - mutex_lock(&rdev->mutex); + int best_supply_uV = 0; + int supply_change_uV = 0; /* If we're setting the same range as last time the change * should be a noop (some cpufreq implementations use the same @@ -2838,17 +2869,95 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) if (ret < 0) goto out2; + if (rdev->supply && (rdev->desc->min_dropout_uV || + !rdev->desc->ops->get_voltage)) { + int current_supply_uV; + int selector; + + selector = regulator_map_voltage(rdev, min_uV, max_uV); + if (selector < 0) { + ret = selector; + goto out2; + } + + best_supply_uV = _regulator_list_voltage(regulator, selector, 0); + if (best_supply_uV < 0) { + ret = best_supply_uV; + goto out2; + } + + best_supply_uV += rdev->desc->min_dropout_uV; + + current_supply_uV = _regulator_get_voltage(rdev->supply->rdev); + if (current_supply_uV < 0) { + ret = current_supply_uV; + goto out2; + } + + supply_change_uV = best_supply_uV - current_supply_uV; + } + + if (supply_change_uV > 0) { + ret = regulator_set_voltage_unlocked(rdev->supply, + best_supply_uV, INT_MAX); + if (ret) { + dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", + ret); + goto out2; + } + } + ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); if (ret < 0) goto out2; + if (supply_change_uV < 0) { + ret = regulator_set_voltage_unlocked(rdev->supply, + best_supply_uV, INT_MAX); + if (ret) + dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", + ret); + /* No need to fail here */ + ret = 0; + } + out: - mutex_unlock(&rdev->mutex); return ret; out2: regulator->min_uV = old_min_uV; regulator->max_uV = old_max_uV; - mutex_unlock(&rdev->mutex); + + return ret; +} + +/** + * regulator_set_voltage - set regulator output voltage + * @regulator: regulator source + * @min_uV: Minimum required voltage in uV + * @max_uV: Maximum acceptable voltage in uV + * + * Sets a voltage regulator to the desired output voltage. This can be set + * during any regulator state. IOW, regulator can be disabled or enabled. + * + * If the regulator is enabled then the voltage will change to the new value + * immediately otherwise if the regulator is disabled the regulator will + * output at the new voltage when enabled. + * + * NOTE: If the regulator is shared between several devices then the lowest + * request voltage that meets the system constraints will be used. + * Regulator system constraints must be set for this regulator before + * calling this function otherwise this call will fail. + */ +int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) +{ + int ret = 0; + + regulator_lock_supply(regulator->rdev); + + ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV); + + regulator_unlock_supply(regulator->rdev); + return ret; } EXPORT_SYMBOL_GPL(regulator_set_voltage); @@ -3001,7 +3110,7 @@ static int _regulator_get_voltage(struct regulator_dev *rdev) } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { ret = rdev->desc->fixed_uV; } else if (rdev->supply) { - ret = regulator_get_voltage(rdev->supply); + ret = _regulator_get_voltage(rdev->supply->rdev); } else { return -EINVAL; } @@ -3024,11 +3133,11 @@ int regulator_get_voltage(struct regulator *regulator) { int ret; - mutex_lock(®ulator->rdev->mutex); + regulator_lock_supply(regulator->rdev); ret = _regulator_get_voltage(regulator->rdev); - mutex_unlock(®ulator->rdev->mutex); + regulator_unlock_supply(regulator->rdev); return ret; } diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index 3510b3e7330a..ddc4f10e268a 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ static int tps6105x_regulator_enable(struct regulator_dev *rdev) int ret; /* Activate voltage mode */ - ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0, + ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0, TPS6105X_REG0_MODE_MASK, TPS6105X_REG0_MODE_VOLTAGE << TPS6105X_REG0_MODE_SHIFT); if (ret) @@ -48,7 +48,7 @@ static int tps6105x_regulator_disable(struct regulator_dev *rdev) int ret; /* Set into shutdown mode */ - ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0, + ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0, TPS6105X_REG0_MODE_MASK, TPS6105X_REG0_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT); if (ret) @@ -60,10 +60,10 @@ static int tps6105x_regulator_disable(struct regulator_dev *rdev) static int tps6105x_regulator_is_enabled(struct regulator_dev *rdev) { struct tps6105x *tps6105x = rdev_get_drvdata(rdev); - u8 regval; + unsigned int regval; int ret; - ret = tps6105x_get(tps6105x, TPS6105X_REG_0, ®val); + ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, ®val); if (ret) return ret; regval &= TPS6105X_REG0_MODE_MASK; @@ -78,10 +78,10 @@ static int tps6105x_regulator_is_enabled(struct regulator_dev *rdev) static int tps6105x_regulator_get_voltage_sel(struct regulator_dev *rdev) { struct tps6105x *tps6105x = rdev_get_drvdata(rdev); - u8 regval; + unsigned int regval; int ret; - ret = tps6105x_get(tps6105x, TPS6105X_REG_0, ®val); + ret = regmap_read(tps6105x->regmap, TPS6105X_REG_0, ®val); if (ret) return ret; @@ -96,7 +96,7 @@ static int tps6105x_regulator_set_voltage_sel(struct regulator_dev *rdev, struct tps6105x *tps6105x = rdev_get_drvdata(rdev); int ret; - ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0, + ret = regmap_update_bits(tps6105x->regmap, TPS6105X_REG_0, TPS6105X_REG0_VOLTAGE_MASK, selector << TPS6105X_REG0_VOLTAGE_SHIFT); if (ret) diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 5cc19b44974a..d2c3d7cc35f5 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -86,6 +86,42 @@ #define TPS65023_MAX_REG_ID TPS65023_LDO_2 +#define TPS65023_REGULATOR_DCDC(_num, _t, _em) \ + { \ + .name = "VDCDC"#_num, \ + .of_match = of_match_ptr("VDCDC"#_num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = TPS65023_DCDC_##_num, \ + .n_voltages = ARRAY_SIZE(_t), \ + .ops = &tps65023_dcdc_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .volt_table = _t, \ + .vsel_reg = TPS65023_REG_DEF_CORE, \ + .vsel_mask = ARRAY_SIZE(_t) - 1, \ + .enable_mask = _em, \ + .enable_reg = TPS65023_REG_REG_CTRL, \ + .apply_reg = TPS65023_REG_CON_CTRL2, \ + .apply_bit = TPS65023_REG_CTRL2_GO, \ + } \ + +#define TPS65023_REGULATOR_LDO(_num, _t, _vm) \ + { \ + .name = "LDO"#_num, \ + .of_match = of_match_ptr("LDO"#_num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = TPS65023_LDO_##_num, \ + .n_voltages = ARRAY_SIZE(_t), \ + .ops = &tps65023_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .volt_table = _t, \ + .vsel_reg = TPS65023_REG_LDO_CTRL, \ + .vsel_mask = _vm, \ + .enable_mask = 1 << (_num), \ + .enable_reg = TPS65023_REG_REG_CTRL, \ + } \ + /* Supported voltage values for regulators */ static const unsigned int VCORE_VSEL_table[] = { 800000, 825000, 850000, 875000, @@ -124,25 +160,16 @@ static const unsigned int TPS65023_LDO2_VSEL_table[] = { 2500000, 2800000, 3000000, 3300000, }; -/* Regulator specific details */ -struct tps_info { - const char *name; - u8 table_len; - const unsigned int *table; -}; - /* PMIC details */ struct tps_pmic { - struct regulator_desc desc[TPS65023_NUM_REGULATOR]; struct regulator_dev *rdev[TPS65023_NUM_REGULATOR]; - const struct tps_info *info[TPS65023_NUM_REGULATOR]; + const struct tps_driver_data *driver_data; struct regmap *regmap; - u8 core_regulator; }; /* Struct passed as driver data */ struct tps_driver_data { - const struct tps_info *info; + const struct regulator_desc *desc; u8 core_regulator; }; @@ -154,7 +181,7 @@ static int tps65023_dcdc_get_voltage_sel(struct regulator_dev *dev) if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) return -EINVAL; - if (dcdc != tps->core_regulator) + if (dcdc != tps->driver_data->core_regulator) return 0; return regulator_get_voltage_sel_regmap(dev); @@ -166,7 +193,7 @@ static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev, struct tps_pmic *tps = rdev_get_drvdata(dev); int dcdc = rdev_get_id(dev); - if (dcdc != tps->core_regulator) + if (dcdc != tps->driver_data->core_regulator) return -EINVAL; return regulator_set_voltage_sel_regmap(dev, selector); @@ -199,30 +226,60 @@ static const struct regmap_config tps65023_regmap_config = { .val_bits = 8, }; +static const struct regulator_desc tps65020_regulators[] = { + TPS65023_REGULATOR_DCDC(1, DCDC_FIXED_3300000_VSEL_table, 0x20), + TPS65023_REGULATOR_DCDC(2, DCDC_FIXED_1800000_VSEL_table, 0x10), + TPS65023_REGULATOR_DCDC(3, VCORE_VSEL_table, 0x08), + TPS65023_REGULATOR_LDO(1, TPS65020_LDO_VSEL_table, 0x07), + TPS65023_REGULATOR_LDO(2, TPS65020_LDO_VSEL_table, 0x70), +}; + +static const struct regulator_desc tps65021_regulators[] = { + TPS65023_REGULATOR_DCDC(1, DCDC_FIXED_3300000_VSEL_table, 0x20), + TPS65023_REGULATOR_DCDC(2, DCDC_FIXED_1800000_VSEL_table, 0x10), + TPS65023_REGULATOR_DCDC(3, VCORE_VSEL_table, 0x08), + TPS65023_REGULATOR_LDO(1, TPS65023_LDO1_VSEL_table, 0x07), + TPS65023_REGULATOR_LDO(2, TPS65023_LDO2_VSEL_table, 0x70), +}; + +static const struct regulator_desc tps65023_regulators[] = { + TPS65023_REGULATOR_DCDC(1, VCORE_VSEL_table, 0x20), + TPS65023_REGULATOR_DCDC(2, DCDC_FIXED_3300000_VSEL_table, 0x10), + TPS65023_REGULATOR_DCDC(3, DCDC_FIXED_1800000_VSEL_table, 0x08), + TPS65023_REGULATOR_LDO(1, TPS65023_LDO1_VSEL_table, 0x07), + TPS65023_REGULATOR_LDO(2, TPS65023_LDO2_VSEL_table, 0x70), +}; + +static struct tps_driver_data tps65020_drv_data = { + .desc = tps65020_regulators, + .core_regulator = TPS65023_DCDC_3, +}; + +static struct tps_driver_data tps65021_drv_data = { + .desc = tps65021_regulators, + .core_regulator = TPS65023_DCDC_3, +}; + +static struct tps_driver_data tps65023_drv_data = { + .desc = tps65023_regulators, + .core_regulator = TPS65023_DCDC_1, +}; + static int tps_65023_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct tps_driver_data *drv_data = (void *)id->driver_data; - const struct tps_info *info = drv_data->info; + struct regulator_init_data *init_data = dev_get_platdata(&client->dev); struct regulator_config config = { }; - struct regulator_init_data *init_data; - struct regulator_dev *rdev; struct tps_pmic *tps; int i; int error; - /** - * init_data points to array of regulator_init structures - * coming from the board-evm file. - */ - init_data = dev_get_platdata(&client->dev); - if (!init_data) - return -EIO; - tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); if (!tps) return -ENOMEM; + tps->driver_data = (struct tps_driver_data *)id->driver_data; + tps->regmap = devm_regmap_init_i2c(client, &tps65023_regmap_config); if (IS_ERR(tps->regmap)) { error = PTR_ERR(tps->regmap); @@ -232,58 +289,22 @@ static int tps_65023_probe(struct i2c_client *client, } /* common for all regulators */ - tps->core_regulator = drv_data->core_regulator; + config.dev = &client->dev; + config.driver_data = tps; + config.regmap = tps->regmap; - for (i = 0; i < TPS65023_NUM_REGULATOR; i++, info++, init_data++) { - /* Store regulator specific information */ - tps->info[i] = info; - - tps->desc[i].name = info->name; - tps->desc[i].id = i; - tps->desc[i].n_voltages = info->table_len; - tps->desc[i].volt_table = info->table; - tps->desc[i].ops = (i > TPS65023_DCDC_3 ? - &tps65023_ldo_ops : &tps65023_dcdc_ops); - tps->desc[i].type = REGULATOR_VOLTAGE; - tps->desc[i].owner = THIS_MODULE; - - tps->desc[i].enable_reg = TPS65023_REG_REG_CTRL; - switch (i) { - case TPS65023_LDO_1: - tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL; - tps->desc[i].vsel_mask = 0x07; - tps->desc[i].enable_mask = 1 << 1; - break; - case TPS65023_LDO_2: - tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL; - tps->desc[i].vsel_mask = 0x70; - tps->desc[i].enable_mask = 1 << 2; - break; - default: /* DCDCx */ - tps->desc[i].enable_mask = - 1 << (TPS65023_NUM_REGULATOR - i); - tps->desc[i].vsel_reg = TPS65023_REG_DEF_CORE; - tps->desc[i].vsel_mask = info->table_len - 1; - tps->desc[i].apply_reg = TPS65023_REG_CON_CTRL2; - tps->desc[i].apply_bit = TPS65023_REG_CTRL2_GO; - } - - config.dev = &client->dev; - config.init_data = init_data; - config.driver_data = tps; - config.regmap = tps->regmap; + for (i = 0; i < TPS65023_NUM_REGULATOR; i++) { + if (init_data) + config.init_data = &init_data[i]; /* Register the regulators */ - rdev = devm_regulator_register(&client->dev, &tps->desc[i], - &config); - if (IS_ERR(rdev)) { + tps->rdev[i] = devm_regulator_register(&client->dev, + &tps->driver_data->desc[i], &config); + if (IS_ERR(tps->rdev[i])) { dev_err(&client->dev, "failed to register %s\n", id->name); - return PTR_ERR(rdev); + return PTR_ERR(tps->rdev[i]); } - - /* Save regulator for cleanup */ - tps->rdev[i] = rdev; } i2c_set_clientdata(client, tps); @@ -296,120 +317,33 @@ static int tps_65023_probe(struct i2c_client *client, return 0; } -static const struct tps_info tps65020_regs[] = { - { - .name = "VDCDC1", - .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table), - .table = DCDC_FIXED_3300000_VSEL_table, - }, - { - .name = "VDCDC2", - .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table), - .table = DCDC_FIXED_1800000_VSEL_table, - }, - { - .name = "VDCDC3", - .table_len = ARRAY_SIZE(VCORE_VSEL_table), - .table = VCORE_VSEL_table, - }, - { - .name = "LDO1", - .table_len = ARRAY_SIZE(TPS65020_LDO_VSEL_table), - .table = TPS65020_LDO_VSEL_table, - }, - { - .name = "LDO2", - .table_len = ARRAY_SIZE(TPS65020_LDO_VSEL_table), - .table = TPS65020_LDO_VSEL_table, - }, -}; - -static const struct tps_info tps65021_regs[] = { - { - .name = "VDCDC1", - .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table), - .table = DCDC_FIXED_3300000_VSEL_table, - }, - { - .name = "VDCDC2", - .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table), - .table = DCDC_FIXED_1800000_VSEL_table, - }, - { - .name = "VDCDC3", - .table_len = ARRAY_SIZE(VCORE_VSEL_table), - .table = VCORE_VSEL_table, - }, - { - .name = "LDO1", - .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table), - .table = TPS65023_LDO1_VSEL_table, - }, - { - .name = "LDO2", - .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table), - .table = TPS65023_LDO2_VSEL_table, - }, -}; - -static const struct tps_info tps65023_regs[] = { - { - .name = "VDCDC1", - .table_len = ARRAY_SIZE(VCORE_VSEL_table), - .table = VCORE_VSEL_table, - }, - { - .name = "VDCDC2", - .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table), - .table = DCDC_FIXED_3300000_VSEL_table, - }, - { - .name = "VDCDC3", - .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table), - .table = DCDC_FIXED_1800000_VSEL_table, - }, - { - .name = "LDO1", - .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table), - .table = TPS65023_LDO1_VSEL_table, - }, - { - .name = "LDO2", - .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table), - .table = TPS65023_LDO2_VSEL_table, - }, -}; - -static struct tps_driver_data tps65020_drv_data = { - .info = tps65020_regs, - .core_regulator = TPS65023_DCDC_3, -}; - -static struct tps_driver_data tps65021_drv_data = { - .info = tps65021_regs, - .core_regulator = TPS65023_DCDC_3, -}; - -static struct tps_driver_data tps65023_drv_data = { - .info = tps65023_regs, - .core_regulator = TPS65023_DCDC_1, +static const struct of_device_id tps65023_of_match[] = { + { .compatible = "ti,tps65020", .data = &tps65020_drv_data}, + { .compatible = "ti,tps65021", .data = &tps65021_drv_data}, + { .compatible = "ti,tps65023", .data = &tps65023_drv_data}, + {}, }; +MODULE_DEVICE_TABLE(of, tps65023_of_match); static const struct i2c_device_id tps_65023_id[] = { - {.name = "tps65023", - .driver_data = (unsigned long) &tps65023_drv_data}, - {.name = "tps65021", - .driver_data = (unsigned long) &tps65021_drv_data,}, - {.name = "tps65020", - .driver_data = (unsigned long) &tps65020_drv_data}, + { + .name = "tps65023", + .driver_data = (kernel_ulong_t)&tps65023_drv_data + }, { + .name = "tps65021", + .driver_data = (kernel_ulong_t)&tps65021_drv_data + }, { + .name = "tps65020", + .driver_data = (kernel_ulong_t)&tps65020_drv_data + }, { }, }; - MODULE_DEVICE_TABLE(i2c, tps_65023_id); static struct i2c_driver tps_65023_i2c_driver = { .driver = { .name = "tps65023", + .of_match_table = of_match_ptr(tps65023_of_match), }, .probe = tps_65023_probe, .id_table = tps_65023_id, diff --git a/include/linux/mfd/tps6105x.h b/include/linux/mfd/tps6105x.h index 386743dd931c..8bc51180800a 100644 --- a/include/linux/mfd/tps6105x.h +++ b/include/linux/mfd/tps6105x.h @@ -10,6 +10,7 @@ #define MFD_TPS6105X_H #include +#include #include /* @@ -82,20 +83,15 @@ struct tps6105x_platform_data { /** * struct tps6105x - state holder for the TPS6105x drivers - * @mutex: mutex to serialize I2C accesses * @i2c_client: corresponding I2C client * @regulator: regulator device if used in voltage mode + * @regmap: used for i2c communcation on accessing registers */ struct tps6105x { struct tps6105x_platform_data *pdata; - struct mutex lock; struct i2c_client *client; struct regulator_dev *regulator; + struct regmap *regmap; }; -extern int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value); -extern int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf); -extern int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg, - u8 bitmask, u8 bitvalues); - #endif