]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
mfd: as3722 Update VSEL access control
authorAlex Frid <afrid@nvidia.com>
Wed, 5 Feb 2014 08:06:41 +0000 (00:06 -0800)
committerAleksandr Frid <afrid@nvidia.com>
Tue, 18 Feb 2014 19:15:41 +0000 (11:15 -0800)
- Added an option to mark VSEL registers as volatile by default.
This option should be set either in board platform data, or in device
tree node of the regulator controlled by hardware mechanism underneath
s/w driver.

- Replaced volatile registers table with callback that checks access
attribute at run-time. Added another callback to switch VSEL registers
attributes between volatile and cached.

- Set persistent property for VSEL of all SD regulators (persistent
value is zero). This would allow to use direct write for setting the
voltage selector instead of read-modify-write.

Bug 1454969

Change-Id: I9a434fa8568dc2717a81ae6ecf3891abb903befa
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/367357
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
drivers/mfd/as3722.c
drivers/regulator/as3722-regulator.c
include/linux/mfd/as3722-plat.h
include/linux/mfd/as3722.h

index b6365a2e8bbac4260e15f02df7a1217f5a631593..4c31ea93ef853a620896bc87090cde715773d1f9 100644 (file)
@@ -360,6 +360,44 @@ static const struct regmap_access_table as3722_volatile_table = {
        .n_no_ranges = ARRAY_SIZE(as3722_cacheable_ranges),
 };
 
+static const struct regmap_range vsel_sd_range =
+       regmap_reg_range(AS3722_SD0_VOLTAGE_REG, AS3722_SD6_VOLTAGE_REG);
+
+static const struct regmap_range vsel_ldo_range =
+       regmap_reg_range(AS3722_LDO0_VOLTAGE_REG, AS3722_LDO11_VOLTAGE_REG);
+
+
+bool is_volatile_as3722_register(struct device *dev, unsigned int reg)
+{
+       if (regmap_reg_in_range(reg, &vsel_sd_range) ||
+           regmap_reg_in_range(reg, &vsel_ldo_range)) {
+               struct as3722 *as3722 = dev_get_drvdata(dev);
+               return test_bit(reg, as3722->volatile_vsel_registers);
+       }
+
+       if (regmap_reg_in_ranges(reg, as3722_volatile_table.no_ranges,
+                                as3722_volatile_table.n_no_ranges))
+               return false;
+
+       return true;
+}
+
+int as3722_vsel_volatile_set(struct device *dev, unsigned int reg,
+                             bool is_volatile)
+{
+       if (regmap_reg_in_range(reg, &vsel_sd_range) ||
+           regmap_reg_in_range(reg, &vsel_ldo_range)) {
+               struct as3722 *as3722 = dev_get_drvdata(dev);
+               if (is_volatile)
+                       set_bit(reg, as3722->volatile_vsel_registers);
+               else
+                       clear_bit(reg, as3722->volatile_vsel_registers);
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
 static struct regmap_config as3722_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
@@ -367,9 +405,10 @@ static struct regmap_config as3722_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
        .rd_table = &as3722_readable_table,
        .wr_table = &as3722_writable_table,
-       .volatile_table = &as3722_volatile_table,
+       .volatile_reg = is_volatile_as3722_register,
        .lock = as3722_regmap_config_lock,
        .unlock = as3722_regmap_config_unlock,
+       .reg_volatile_set = as3722_vsel_volatile_set,
 };
 
 static int as3722_i2c_of_probe(struct i2c_client *i2c,
index 8f8716c1c3f8e6bccc5b8f7761fe2932e2c89012..f305177411e7dd49cc48a932e754aecd9df1321d 100644 (file)
@@ -85,6 +85,7 @@ struct as3722_register_mapping {
 struct as3722_regulator_config_data {
        struct regulator_init_data *reg_init;
        bool enable_tracking;
+       bool volatile_vsel;
        int ext_control;
 };
 
@@ -743,6 +744,8 @@ static int as3722_get_regulator_dt_data(struct platform_device *pdev,
                }
                reg_config->enable_tracking =
                        of_property_read_bool(reg_node, "ams,enable-tracking");
+               reg_config->volatile_vsel =
+                       of_property_read_bool(reg_node, "ams,volatile-vsel");
 
        }
        return 0;
@@ -769,6 +772,7 @@ static int as3722_get_regulator_platform_data(struct platform_device *pdev,
                reg_config->reg_init = rpdata->reg_init;
                reg_config->ext_control = rpdata->ext_control;
                reg_config->enable_tracking = rpdata->enable_tracking;
+               reg_config->volatile_vsel = rpdata->volatile_vsel;
        }
        return 0;
 }
@@ -873,6 +877,7 @@ static int as3722_regulator_probe(struct platform_device *pdev)
                        as3722_regs->desc[id].uV_step = 10000;
                        as3722_regs->desc[id].linear_min_sel = 1;
                        as3722_regs->desc[id].enable_time = 275;
+                       as3722_regs->desc[id].vsel_persist = true;
                        break;
                case AS3722_REGULATOR_ID_SD2:
                case AS3722_REGULATOR_ID_SD3:
@@ -886,6 +891,7 @@ static int as3722_regulator_probe(struct platform_device *pdev)
                                                as3722_sd2345_ranges;
                        as3722_regs->desc[id].n_linear_ranges =
                                        ARRAY_SIZE(as3722_sd2345_ranges);
+                       as3722_regs->desc[id].vsel_persist = true;
                        break;
                default:
                        if (reg_config->ext_control)
@@ -904,6 +910,11 @@ static int as3722_regulator_probe(struct platform_device *pdev)
                as3722_regs->desc[id].ops = ops;
                config.init_data = reg_config->reg_init;
                config.of_node = as3722_regulator_matches[id].of_node;
+
+               if (reg_config->volatile_vsel) {
+                       unsigned int bit = as3722_reg_lookup[id].vsel_reg;
+                       __set_bit(bit, as3722->volatile_vsel_registers);
+               }
                rdev = devm_regulator_register(&pdev->dev,
                                        &as3722_regs->desc[id], &config);
                if (IS_ERR(rdev)) {
index e486a922ea9b398e642013750e6e684d9f2e002d..e4e19d6ba733b1beee30b147880339414af4eef1 100644 (file)
@@ -125,6 +125,7 @@ struct as3722_regulator_platform_data {
        int ext_control;
        bool enable_tracking;
        bool disable_tracking_suspend;
+       bool volatile_vsel;
 };
 
 /*
index 4fd8a4a1dba4cb6c60a94c4edcc7b8c2c8bef878..b75d17084c221484220b3f6842f59e518f01d6dc 100644 (file)
@@ -405,6 +405,7 @@ struct as3722 {
        struct device *dev;
        struct regmap *regmap;
        struct i2c_client *client;
+       DECLARE_BITMAP(volatile_vsel_registers, AS3722_LDO11_VOLTAGE_REG);
        int chip_irq;
        unsigned long irq_flags;
        int irq_base;