]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00274473-2 regulator: anatop: implement more callback
authorAnson Huang <b20788@freescale.com>
Thu, 8 Aug 2013 21:12:06 +0000 (17:12 -0400)
committerJason Liu <r64343@freescale.com>
Wed, 30 Oct 2013 01:54:33 +0000 (09:54 +0800)
Need to support anatop PU regulator on/off dynamically,
so we need to add enable/disable/is_enabled/enable_time
for anatop regulator.

Only PU regulator in anatop can support dynamical on/off,
so this implement is only for PU regulator, other regulators
are always on.

Signed-off-by: Anson Huang <b20788@freescale.com>
drivers/regulator/anatop-regulator.c

index 0d4a8ccbb53616275bda7d8f4ca817d8d68ad104..c91ab175a58e93c16a7e1113d40e8728a1570fc6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011, 2013 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
 #define LDO_RAMP_UP_UNIT_IN_CYCLES      64 /* 64 cycles per step */
 #define LDO_RAMP_UP_FREQ_IN_MHZ         24 /* cycle based on 24M OSC */
 
+#define REG_SET         0x4
+#define REG_CLR         0x8
+#define SOC_PU_FIELD_OFFSET   0x9
+
+/*
+ * for CORE, SOC and PU regulator, the register field
+ * has following definition: 00001 -- Target core voltage
+ * = 0.725V, which means the lowest setting in this
+ * field is 0.725V once the regulator is enabled. So
+ * when these regulators are turned on from off status,
+ * we need to count the voltage step of 0V to 0.7V, it will
+ * need additional delay, so the additional step number is
+ * 700mV / 25mV = 28.
+ */
+#define CORE_REG_ENABLE_STEP_ADD 28
+
 struct anatop_regulator {
        const char *name;
        u32 control_reg;
@@ -97,12 +113,86 @@ static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg)
        return regulator_get_voltage_sel_regmap(reg);
 }
 
+/*
+ * currently on anatop regulators, only PU regulator supports
+ * enable/disable function, and its voltage must be equal
+ * to SOC voltage, so we need to get SOC voltage then set
+ * into PU regulator. Other regulators are always on due
+ * to hardware design, so enable/disable/is_enabled/enable_time
+ * functions are only used by PU regulator.
+ */
+static int anatop_regmap_enable(struct regulator_dev *reg)
+{
+       struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+       u32 val;
+
+       if (!anatop_reg->control_reg)
+               return -ENOTSUPP;
+
+       regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
+       val &= ((1 << anatop_reg->vol_bit_width) - 1) <<
+               (anatop_reg->vol_bit_shift + SOC_PU_FIELD_OFFSET);
+       regmap_write(anatop_reg->anatop, anatop_reg->control_reg +
+               REG_SET, val >> SOC_PU_FIELD_OFFSET);
+
+       return 0;
+}
+
+static int anatop_regmap_disable(struct regulator_dev *reg)
+{
+       struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+
+       if (!anatop_reg->control_reg)
+               return -ENOTSUPP;
+
+       regmap_write(anatop_reg->anatop, anatop_reg->control_reg +
+               REG_CLR, ((1 << anatop_reg->vol_bit_width) - 1) <<
+               anatop_reg->vol_bit_shift);
+
+       return 0;
+}
+
+static int anatop_regmap_is_enabled(struct regulator_dev *reg)
+{
+       struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+       u32 val;
+
+       if (!anatop_reg->control_reg)
+               return -ENOTSUPP;
+
+       regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
+
+       return (val >> anatop_reg->vol_bit_shift) &
+               ((1 << anatop_reg->vol_bit_width) - 1) ? 1 : 0;
+}
+
+static int anatop_regmap_enable_time(struct regulator_dev *reg)
+{
+       struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+       u32 val, soc_val;
+
+       if (!anatop_reg->control_reg)
+               return -ENOTSUPP;
+
+       regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
+       soc_val = (val >> (anatop_reg->vol_bit_shift +
+               SOC_PU_FIELD_OFFSET)) &
+               ((1 << anatop_reg->vol_bit_width) - 1);
+
+       return anatop_regmap_set_voltage_time_sel(reg, 0,
+               soc_val + CORE_REG_ENABLE_STEP_ADD);
+}
+
 static struct regulator_ops anatop_rops = {
        .set_voltage_sel = anatop_regmap_set_voltage_sel,
        .set_voltage_time_sel = anatop_regmap_set_voltage_time_sel,
        .get_voltage_sel = anatop_regmap_get_voltage_sel,
+       .enable = anatop_regmap_enable,
+       .disable = anatop_regmap_disable,
+       .is_enabled = anatop_regmap_is_enabled,
        .list_voltage = regulator_list_voltage_linear,
        .map_voltage = regulator_map_voltage_linear,
+       .enable_time = anatop_regmap_enable_time,
 };
 
 static int anatop_regulator_probe(struct platform_device *pdev)