diff options
Diffstat (limited to 'drivers/regulator/as3722-regulator.c')
-rw-r--r-- | drivers/regulator/as3722-regulator.c | 287 |
1 files changed, 86 insertions, 201 deletions
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c index e5fed289b52d..dc75c33bd950 100644 --- a/drivers/regulator/as3722-regulator.c +++ b/drivers/regulator/as3722-regulator.c @@ -81,7 +81,6 @@ struct as3722_regulator_config_data { struct as3722_regulators { struct device *dev; struct as3722 *as3722; - struct regulator_dev *rdevs[AS3722_REGULATOR_ID_MAX]; struct regulator_desc desc[AS3722_REGULATOR_ID_MAX]; struct as3722_regulator_config_data reg_config_data[AS3722_REGULATOR_ID_MAX]; @@ -314,63 +313,10 @@ static const struct as3722_register_mapping as3722_reg_lookup[] = { }, }; - -static const int as3722_ldo_current[] = { 150000, 300000 }; -static const int as3722_sd016_current[] = { 2500000, 3000000, 3500000 }; - -static int as3722_current_to_index(int min_uA, int max_uA, - const int *curr_table, int n_currents) -{ - int i; - - for (i = n_currents - 1; i >= 0; i--) { - if ((min_uA <= curr_table[i]) && (curr_table[i] <= max_uA)) - return i; - } - return -EINVAL; -} - -static int as3722_ldo_get_current_limit(struct regulator_dev *rdev) -{ - struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev); - struct as3722 *as3722 = as3722_regs->as3722; - int id = rdev_get_id(rdev); - u32 val; - int ret; - - ret = as3722_read(as3722, as3722_reg_lookup[id].vsel_reg, &val); - if (ret < 0) { - dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n", - as3722_reg_lookup[id].vsel_reg, ret); - return ret; - } - if (val & AS3722_LDO_ILIMIT_MASK) - return 300000; - return 150000; -} - -static int as3722_ldo_set_current_limit(struct regulator_dev *rdev, - int min_uA, int max_uA) -{ - struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev); - struct as3722 *as3722 = as3722_regs->as3722; - int id = rdev_get_id(rdev); - int ret; - u32 reg = 0; - - ret = as3722_current_to_index(min_uA, max_uA, as3722_ldo_current, - ARRAY_SIZE(as3722_ldo_current)); - if (ret < 0) { - dev_err(as3722_regs->dev, - "Current range min:max = %d:%d does not support\n", - min_uA, max_uA); - return ret; - } - if (ret) - reg = AS3722_LDO_ILIMIT_BIT; - return as3722_update_bits(as3722, as3722_reg_lookup[id].vsel_reg, - AS3722_LDO_ILIMIT_MASK, reg); -} +static const unsigned int as3722_ldo_current[] = { 150000, 300000 }; +static const unsigned int as3722_sd016_current[] = { + 2500000, 3000000, 3500000 +}; static const struct regulator_ops as3722_ldo0_ops = { .is_enabled = regulator_is_enabled_regmap, @@ -379,16 +325,16 @@ static const struct regulator_ops as3722_ldo0_ops = { .list_voltage = regulator_list_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_current_limit = as3722_ldo_get_current_limit, - .set_current_limit = as3722_ldo_set_current_limit, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, }; static const struct regulator_ops as3722_ldo0_extcntrl_ops = { .list_voltage = regulator_list_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_current_limit = as3722_ldo_get_current_limit, - .set_current_limit = as3722_ldo_set_current_limit, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, }; static int as3722_ldo3_set_tracking_mode(struct as3722_regulators *as3722_reg, @@ -440,8 +386,8 @@ static const struct regulator_ops as3722_ldo6_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear_range, - .get_current_limit = as3722_ldo_get_current_limit, - .set_current_limit = as3722_ldo_set_current_limit, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, .get_bypass = regulator_get_bypass_regmap, .set_bypass = regulator_set_bypass_regmap, }; @@ -451,8 +397,8 @@ static const struct regulator_ops as3722_ldo6_extcntrl_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear_range, - .get_current_limit = as3722_ldo_get_current_limit, - .set_current_limit = as3722_ldo_set_current_limit, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, .get_bypass = regulator_get_bypass_regmap, .set_bypass = regulator_set_bypass_regmap, }; @@ -471,8 +417,8 @@ static const struct regulator_ops as3722_ldo_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear_range, - .get_current_limit = as3722_ldo_get_current_limit, - .set_current_limit = as3722_ldo_set_current_limit, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, }; static const struct regulator_ops as3722_ldo_extcntrl_ops = { @@ -480,8 +426,8 @@ static const struct regulator_ops as3722_ldo_extcntrl_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .list_voltage = regulator_list_voltage_linear_range, - .get_current_limit = as3722_ldo_get_current_limit, - .set_current_limit = as3722_ldo_set_current_limit, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, }; static unsigned int as3722_sd_get_mode(struct regulator_dev *rdev) @@ -539,85 +485,6 @@ static int as3722_sd_set_mode(struct regulator_dev *rdev, return ret; } -static int as3722_sd016_get_current_limit(struct regulator_dev *rdev) -{ - struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev); - struct as3722 *as3722 = as3722_regs->as3722; - int id = rdev_get_id(rdev); - u32 val, reg; - int mask; - int ret; - - switch (id) { - case AS3722_REGULATOR_ID_SD0: - reg = AS3722_OVCURRENT_REG; - mask = AS3722_OVCURRENT_SD0_TRIP_MASK; - break; - case AS3722_REGULATOR_ID_SD1: - reg = AS3722_OVCURRENT_REG; - mask = AS3722_OVCURRENT_SD1_TRIP_MASK; - break; - case AS3722_REGULATOR_ID_SD6: - reg = AS3722_OVCURRENT_DEB_REG; - mask = AS3722_OVCURRENT_SD6_TRIP_MASK; - break; - default: - return -EINVAL; - } - ret = as3722_read(as3722, reg, &val); - if (ret < 0) { - dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n", - reg, ret); - return ret; - } - val &= mask; - val >>= ffs(mask) - 1; - if (val == 3) - return -EINVAL; - return as3722_sd016_current[val]; -} - -static int as3722_sd016_set_current_limit(struct regulator_dev *rdev, - int min_uA, int max_uA) -{ - struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev); - struct as3722 *as3722 = as3722_regs->as3722; - int id = rdev_get_id(rdev); - int ret; - int val; - int mask; - u32 reg; - - ret = as3722_current_to_index(min_uA, max_uA, as3722_sd016_current, - ARRAY_SIZE(as3722_sd016_current)); - if (ret < 0) { - dev_err(as3722_regs->dev, - "Current range min:max = %d:%d does not support\n", - min_uA, max_uA); - return ret; - } - - switch (id) { - case AS3722_REGULATOR_ID_SD0: - reg = AS3722_OVCURRENT_REG; - mask = AS3722_OVCURRENT_SD0_TRIP_MASK; - break; - case AS3722_REGULATOR_ID_SD1: - reg = AS3722_OVCURRENT_REG; - mask = AS3722_OVCURRENT_SD1_TRIP_MASK; - break; - case AS3722_REGULATOR_ID_SD6: - reg = AS3722_OVCURRENT_DEB_REG; - mask = AS3722_OVCURRENT_SD6_TRIP_MASK; - break; - default: - return -EINVAL; - } - ret <<= ffs(mask) - 1; - val = ret & mask; - return as3722_update_bits(as3722, reg, mask, val); -} - static bool as3722_sd0_is_low_voltage(struct as3722_regulators *as3722_regs) { int err; @@ -649,8 +516,8 @@ static const struct regulator_ops as3722_sd016_ops = { .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_current_limit = as3722_sd016_get_current_limit, - .set_current_limit = as3722_sd016_set_current_limit, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, .get_mode = as3722_sd_get_mode, .set_mode = as3722_sd_set_mode, }; @@ -660,8 +527,8 @@ static const struct regulator_ops as3722_sd016_extcntrl_ops = { .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_current_limit = as3722_sd016_get_current_limit, - .set_current_limit = as3722_sd016_set_current_limit, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, .get_mode = as3722_sd_get_mode, .set_mode = as3722_sd_set_mode, }; @@ -807,42 +674,45 @@ static int as3722_regulator_probe(struct platform_device *pdev) config.regmap = as3722->regmap; for (id = 0; id < AS3722_REGULATOR_ID_MAX; id++) { + struct regulator_desc *desc; + + desc = &as3722_regs->desc[id]; reg_config = &as3722_regs->reg_config_data[id]; - as3722_regs->desc[id].name = as3722_reg_lookup[id].name; - as3722_regs->desc[id].supply_name = as3722_reg_lookup[id].sname; - as3722_regs->desc[id].id = as3722_reg_lookup[id].regulator_id; - as3722_regs->desc[id].n_voltages = - as3722_reg_lookup[id].n_voltages; - as3722_regs->desc[id].type = REGULATOR_VOLTAGE; - as3722_regs->desc[id].owner = THIS_MODULE; - as3722_regs->desc[id].enable_reg = - as3722_reg_lookup[id].enable_reg; - as3722_regs->desc[id].enable_mask = - as3722_reg_lookup[id].enable_mask; - as3722_regs->desc[id].vsel_reg = as3722_reg_lookup[id].vsel_reg; - as3722_regs->desc[id].vsel_mask = - as3722_reg_lookup[id].vsel_mask; + desc->name = as3722_reg_lookup[id].name; + desc->supply_name = as3722_reg_lookup[id].sname; + desc->id = as3722_reg_lookup[id].regulator_id; + desc->n_voltages = as3722_reg_lookup[id].n_voltages; + desc->type = REGULATOR_VOLTAGE; + desc->owner = THIS_MODULE; + desc->enable_reg = as3722_reg_lookup[id].enable_reg; + desc->enable_mask = as3722_reg_lookup[id].enable_mask; + desc->vsel_reg = as3722_reg_lookup[id].vsel_reg; + desc->vsel_mask = as3722_reg_lookup[id].vsel_mask; switch (id) { case AS3722_REGULATOR_ID_LDO0: if (reg_config->ext_control) ops = &as3722_ldo0_extcntrl_ops; else ops = &as3722_ldo0_ops; - as3722_regs->desc[id].min_uV = 825000; - as3722_regs->desc[id].uV_step = 25000; - as3722_regs->desc[id].linear_min_sel = 1; - as3722_regs->desc[id].enable_time = 500; + desc->min_uV = 825000; + desc->uV_step = 25000; + desc->linear_min_sel = 1; + desc->enable_time = 500; + desc->curr_table = as3722_ldo_current; + desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current); + desc->csel_reg = as3722_reg_lookup[id].vsel_reg; + desc->csel_mask = AS3722_LDO_ILIMIT_MASK; break; case AS3722_REGULATOR_ID_LDO3: if (reg_config->ext_control) ops = &as3722_ldo3_extcntrl_ops; else ops = &as3722_ldo3_ops; - as3722_regs->desc[id].min_uV = 620000; - as3722_regs->desc[id].uV_step = 20000; - as3722_regs->desc[id].linear_min_sel = 1; - as3722_regs->desc[id].enable_time = 500; + desc->min_uV = 620000; + desc->uV_step = 20000; + desc->linear_min_sel = 1; + desc->enable_time = 500; if (reg_config->enable_tracking) { ret = as3722_ldo3_set_tracking_mode(as3722_regs, id, AS3722_LDO3_MODE_PMOS_TRACKING); @@ -859,18 +729,17 @@ static int as3722_regulator_probe(struct platform_device *pdev) ops = &as3722_ldo6_extcntrl_ops; else ops = &as3722_ldo6_ops; - as3722_regs->desc[id].enable_time = 500; - as3722_regs->desc[id].bypass_reg = - AS3722_LDO6_VOLTAGE_REG; - as3722_regs->desc[id].bypass_mask = - AS3722_LDO_VSEL_MASK; - as3722_regs->desc[id].bypass_val_on = - AS3722_LDO6_VSEL_BYPASS; - as3722_regs->desc[id].bypass_val_off = - AS3722_LDO6_VSEL_BYPASS; - as3722_regs->desc[id].linear_ranges = as3722_ldo_ranges; - as3722_regs->desc[id].n_linear_ranges = - ARRAY_SIZE(as3722_ldo_ranges); + desc->enable_time = 500; + desc->bypass_reg = AS3722_LDO6_VOLTAGE_REG; + desc->bypass_mask = AS3722_LDO_VSEL_MASK; + desc->bypass_val_on = AS3722_LDO6_VSEL_BYPASS; + desc->bypass_val_off = AS3722_LDO6_VSEL_BYPASS; + desc->linear_ranges = as3722_ldo_ranges; + desc->n_linear_ranges = ARRAY_SIZE(as3722_ldo_ranges); + desc->curr_table = as3722_ldo_current; + desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current); + desc->csel_reg = as3722_reg_lookup[id].vsel_reg; + desc->csel_mask = AS3722_LDO_ILIMIT_MASK; break; case AS3722_REGULATOR_ID_SD0: case AS3722_REGULATOR_ID_SD1: @@ -889,9 +758,25 @@ static int as3722_regulator_probe(struct platform_device *pdev) AS3722_SD0_VSEL_MAX + 1; as3722_regs->desc[id].min_uV = 610000; } - as3722_regs->desc[id].uV_step = 10000; - as3722_regs->desc[id].linear_min_sel = 1; - as3722_regs->desc[id].enable_time = 600; + desc->uV_step = 10000; + desc->linear_min_sel = 1; + desc->enable_time = 600; + desc->curr_table = as3722_sd016_current; + desc->n_current_limits = + ARRAY_SIZE(as3722_sd016_current); + if (id == AS3722_REGULATOR_ID_SD0) { + desc->csel_reg = AS3722_OVCURRENT_REG; + desc->csel_mask = + AS3722_OVCURRENT_SD0_TRIP_MASK; + } else if (id == AS3722_REGULATOR_ID_SD1) { + desc->csel_reg = AS3722_OVCURRENT_REG; + desc->csel_mask = + AS3722_OVCURRENT_SD1_TRIP_MASK; + } else if (id == AS3722_REGULATOR_ID_SD6) { + desc->csel_reg = AS3722_OVCURRENT_DEB_REG; + desc->csel_mask = + AS3722_OVCURRENT_SD6_TRIP_MASK; + } break; case AS3722_REGULATOR_ID_SD2: case AS3722_REGULATOR_ID_SD3: @@ -901,9 +786,8 @@ static int as3722_regulator_probe(struct platform_device *pdev) ops = &as3722_sd2345_extcntrl_ops; else ops = &as3722_sd2345_ops; - as3722_regs->desc[id].linear_ranges = - as3722_sd2345_ranges; - as3722_regs->desc[id].n_linear_ranges = + desc->linear_ranges = as3722_sd2345_ranges; + desc->n_linear_ranges = ARRAY_SIZE(as3722_sd2345_ranges); break; default: @@ -911,17 +795,19 @@ static int as3722_regulator_probe(struct platform_device *pdev) ops = &as3722_ldo_extcntrl_ops; else ops = &as3722_ldo_ops; - as3722_regs->desc[id].enable_time = 500; - as3722_regs->desc[id].linear_ranges = as3722_ldo_ranges; - as3722_regs->desc[id].n_linear_ranges = - ARRAY_SIZE(as3722_ldo_ranges); + desc->enable_time = 500; + desc->linear_ranges = as3722_ldo_ranges; + desc->n_linear_ranges = ARRAY_SIZE(as3722_ldo_ranges); + desc->curr_table = as3722_ldo_current; + desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current); + desc->csel_reg = as3722_reg_lookup[id].vsel_reg; + desc->csel_mask = AS3722_LDO_ILIMIT_MASK; break; } - as3722_regs->desc[id].ops = ops; + desc->ops = ops; config.init_data = reg_config->reg_init; config.of_node = as3722_regulator_matches[id].of_node; - rdev = devm_regulator_register(&pdev->dev, - &as3722_regs->desc[id], &config); + rdev = devm_regulator_register(&pdev->dev, desc, &config); if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); dev_err(&pdev->dev, "regulator %d register failed %d\n", @@ -929,7 +815,6 @@ static int as3722_regulator_probe(struct platform_device *pdev) return ret; } - as3722_regs->rdevs[id] = rdev; if (reg_config->ext_control) { ret = regulator_enable_regmap(rdev); if (ret < 0) { |