]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
regulator: pfuze100: add pfuze200 support
authorRobin Gong <b38343@freescale.com>
Tue, 4 Mar 2014 09:40:36 +0000 (17:40 +0800)
committerMark Brown <broonie@linaro.org>
Tue, 4 Mar 2014 09:40:31 +0000 (17:40 +0800)
support pfuze200 chip which remove SW1C and SW4 based on pfuze100.

Signed-off-by: Robin Gong <b38343@freescale.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
Documentation/devicetree/bindings/regulator/pfuze100.txt
drivers/regulator/pfuze100-regulator.c
include/linux/regulator/pfuze100.h

index fc989b2e8057b3ced0b306ac53befb4a3edc1f81..34ef5d16d0f1697c51b6759b8a572f33d6b85894 100644 (file)
@@ -1,7 +1,7 @@
 PFUZE100 family of regulators
 
 Required properties:
-- compatible: "fsl,pfuze100"
+- compatible: "fsl,pfuze100" or "fsl,pfuze200"
 - reg: I2C slave address
 
 Required child node:
@@ -10,11 +10,14 @@ Required child node:
   Documentation/devicetree/bindings/regulator/regulator.txt.
 
   The valid names for regulators are:
+  --PFUZE100
   sw1ab,sw1c,sw2,sw3a,sw3b,sw4,swbst,vsnvs,vrefddr,vgen1~vgen6
+  --PFUZE200
+  sw1ab,sw2,sw3a,sw3b,swbst,vsnvs,vrefddr,vgen1~vgen6
 
 Each regulator is defined using the standard binding for regulators.
 
-Example:
+Example 1: PFUZE100
 
        pmic: pfuze100@08 {
                compatible = "fsl,pfuze100";
@@ -113,3 +116,92 @@ Example:
                        };
                };
        };
+
+
+Example 2: PFUZE200
+
+       pmic: pfuze200@08 {
+               compatible = "fsl,pfuze200";
+               reg = <0x08>;
+
+               regulators {
+                       sw1a_reg: sw1ab {
+                               regulator-min-microvolt = <300000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       sw2_reg: sw2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3a_reg: sw3a {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1975000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3b_reg: sw3b {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1975000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       swbst_reg: swbst {
+                               regulator-min-microvolt = <5000000>;
+                               regulator-max-microvolt = <5150000>;
+                       };
+
+                       snvs_reg: vsnvs {
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vref_reg: vrefddr {
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vgen1_reg: vgen1 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1550000>;
+                       };
+
+                       vgen2_reg: vgen2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1550000>;
+                       };
+
+                       vgen3_reg: vgen3 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       vgen4_reg: vgen4 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vgen5_reg: vgen5 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vgen6_reg: vgen6 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+               };
+       };
index 371a55374edc076d502262671a098a9cb6ec4e0a..ef330e69336a230154ff789693829122fd622801 100644 (file)
@@ -56,6 +56,8 @@
 #define PFUZE100_VGEN5VOL      0x70
 #define PFUZE100_VGEN6VOL      0x71
 
+enum chips {PFUZE100, PFUZE200, PFUZE_NUM};
+
 struct pfuze_regulator {
        struct regulator_desc desc;
        unsigned char stby_reg;
@@ -63,6 +65,7 @@ struct pfuze_regulator {
 };
 
 struct pfuze_chip {
+       int     chip_id;
        struct regmap *regmap;
        struct device *dev;
        struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR];
@@ -77,15 +80,15 @@ static const int pfuze100_vsnvs[] = {
        1000000, 1100000, 1200000, 1300000, 1500000, 1800000, 3000000,
 };
 
-static const struct i2c_device_id pfuze_device_id[] = {
-       {.name = "pfuze100"},
-       {},
+static const struct i2c_device_id pfuze_device_id[PFUZE_NUM] = {
+       {.name = "pfuze100", .driver_data = PFUZE100},
+       {.name = "pfuze200", .driver_data = PFUZE200},
 };
 MODULE_DEVICE_TABLE(i2c, pfuze_device_id);
 
-static const struct of_device_id pfuze_dt_ids[] = {
-       { .compatible = "fsl,pfuze100" },
-       {},
+static const struct of_device_id pfuze_dt_ids[PFUZE_NUM] = {
+       { .compatible = "fsl,pfuze100", .data = (void *)PFUZE100},
+       { .compatible = "fsl,pfuze200", .data = (void *)PFUZE200},
 };
 MODULE_DEVICE_TABLE(of, pfuze_dt_ids);
 
@@ -139,14 +142,14 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
 
 };
 
-#define PFUZE100_FIXED_REG(_name, base, voltage)       \
-       [PFUZE100_ ## _name] = {        \
+#define PFUZE100_FIXED_REG(_chip, _name, base, voltage)        \
+       [_chip ## _ ## _name] = {       \
                .desc = {       \
                        .name = #_name, \
                        .n_voltages = 1,        \
                        .ops = &pfuze100_fixed_regulator_ops,   \
                        .type = REGULATOR_VOLTAGE,      \
-                       .id = PFUZE100_ ## _name,       \
+                       .id = _chip ## _ ## _name,      \
                        .owner = THIS_MODULE,   \
                        .min_uV = (voltage),    \
                        .enable_reg = (base),   \
@@ -154,14 +157,14 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
                },      \
        }
 
-#define PFUZE100_SW_REG(_name, base, min, max, step)   \
-       [PFUZE100_ ## _name] = {        \
+#define PFUZE100_SW_REG(_chip, _name, base, min, max, step)    \
+       [_chip ## _ ## _name] = {       \
                .desc = {       \
                        .name = #_name,\
                        .n_voltages = ((max) - (min)) / (step) + 1,     \
                        .ops = &pfuze100_sw_regulator_ops,      \
                        .type = REGULATOR_VOLTAGE,      \
-                       .id = PFUZE100_ ## _name,       \
+                       .id = _chip ## _ ## _name,      \
                        .owner = THIS_MODULE,   \
                        .min_uV = (min),        \
                        .uV_step = (step),      \
@@ -172,14 +175,14 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
                .stby_mask = 0x3f,      \
        }
 
-#define PFUZE100_SWB_REG(_name, base, mask, voltages)  \
-       [PFUZE100_ ## _name] = {        \
+#define PFUZE100_SWB_REG(_chip, _name, base, mask, voltages)   \
+       [_chip ## _ ##  _name] = {      \
                .desc = {       \
                        .name = #_name, \
                        .n_voltages = ARRAY_SIZE(voltages),     \
                        .ops = &pfuze100_swb_regulator_ops,     \
                        .type = REGULATOR_VOLTAGE,      \
-                       .id = PFUZE100_ ## _name,       \
+                       .id = _chip ## _ ## _name,      \
                        .owner = THIS_MODULE,   \
                        .volt_table = voltages, \
                        .vsel_reg = (base),     \
@@ -187,14 +190,14 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
                },      \
        }
 
-#define PFUZE100_VGEN_REG(_name, base, min, max, step) \
-       [PFUZE100_ ## _name] = {        \
+#define PFUZE100_VGEN_REG(_chip, _name, base, min, max, step)  \
+       [_chip ## _ ## _name] = {       \
                .desc = {       \
                        .name = #_name, \
                        .n_voltages = ((max) - (min)) / (step) + 1,     \
                        .ops = &pfuze100_ldo_regulator_ops,     \
                        .type = REGULATOR_VOLTAGE,      \
-                       .id = PFUZE100_ ## _name,       \
+                       .id = _chip ## _ ## _name,      \
                        .owner = THIS_MODULE,   \
                        .min_uV = (min),        \
                        .uV_step = (step),      \
@@ -207,25 +210,45 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
                .stby_mask = 0x20,      \
        }
 
+/* PFUZE100 */
 static struct pfuze_regulator pfuze100_regulators[] = {
-       PFUZE100_SW_REG(SW1AB, PFUZE100_SW1ABVOL, 300000, 1875000, 25000),
-       PFUZE100_SW_REG(SW1C, PFUZE100_SW1CVOL, 300000, 1875000, 25000),
-       PFUZE100_SW_REG(SW2, PFUZE100_SW2VOL, 400000, 1975000, 25000),
-       PFUZE100_SW_REG(SW3A, PFUZE100_SW3AVOL, 400000, 1975000, 25000),
-       PFUZE100_SW_REG(SW3B, PFUZE100_SW3BVOL, 400000, 1975000, 25000),
-       PFUZE100_SW_REG(SW4, PFUZE100_SW4VOL, 400000, 1975000, 25000),
-       PFUZE100_SWB_REG(SWBST, PFUZE100_SWBSTCON1, 0x3 , pfuze100_swbst),
-       PFUZE100_SWB_REG(VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
-       PFUZE100_FIXED_REG(VREFDDR, PFUZE100_VREFDDRCON, 750000),
-       PFUZE100_VGEN_REG(VGEN1, PFUZE100_VGEN1VOL, 800000, 1550000, 50000),
-       PFUZE100_VGEN_REG(VGEN2, PFUZE100_VGEN2VOL, 800000, 1550000, 50000),
-       PFUZE100_VGEN_REG(VGEN3, PFUZE100_VGEN3VOL, 1800000, 3300000, 100000),
-       PFUZE100_VGEN_REG(VGEN4, PFUZE100_VGEN4VOL, 1800000, 3300000, 100000),
-       PFUZE100_VGEN_REG(VGEN5, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000),
-       PFUZE100_VGEN_REG(VGEN6, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000),
+       PFUZE100_SW_REG(PFUZE100, SW1AB, PFUZE100_SW1ABVOL, 300000, 1875000, 25000),
+       PFUZE100_SW_REG(PFUZE100, SW1C, PFUZE100_SW1CVOL, 300000, 1875000, 25000),
+       PFUZE100_SW_REG(PFUZE100, SW2, PFUZE100_SW2VOL, 400000, 1975000, 25000),
+       PFUZE100_SW_REG(PFUZE100, SW3A, PFUZE100_SW3AVOL, 400000, 1975000, 25000),
+       PFUZE100_SW_REG(PFUZE100, SW3B, PFUZE100_SW3BVOL, 400000, 1975000, 25000),
+       PFUZE100_SW_REG(PFUZE100, SW4, PFUZE100_SW4VOL, 400000, 1975000, 25000),
+       PFUZE100_SWB_REG(PFUZE100, SWBST, PFUZE100_SWBSTCON1, 0x3 , pfuze100_swbst),
+       PFUZE100_SWB_REG(PFUZE100, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
+       PFUZE100_FIXED_REG(PFUZE100, VREFDDR, PFUZE100_VREFDDRCON, 750000),
+       PFUZE100_VGEN_REG(PFUZE100, VGEN1, PFUZE100_VGEN1VOL, 800000, 1550000, 50000),
+       PFUZE100_VGEN_REG(PFUZE100, VGEN2, PFUZE100_VGEN2VOL, 800000, 1550000, 50000),
+       PFUZE100_VGEN_REG(PFUZE100, VGEN3, PFUZE100_VGEN3VOL, 1800000, 3300000, 100000),
+       PFUZE100_VGEN_REG(PFUZE100, VGEN4, PFUZE100_VGEN4VOL, 1800000, 3300000, 100000),
+       PFUZE100_VGEN_REG(PFUZE100, VGEN5, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000),
+       PFUZE100_VGEN_REG(PFUZE100, VGEN6, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000),
+};
+
+static struct pfuze_regulator pfuze200_regulators[] = {
+       PFUZE100_SW_REG(PFUZE200, SW1AB, PFUZE100_SW1ABVOL, 300000, 1875000, 25000),
+       PFUZE100_SW_REG(PFUZE200, SW2, PFUZE100_SW2VOL, 400000, 1975000, 25000),
+       PFUZE100_SW_REG(PFUZE200, SW3A, PFUZE100_SW3AVOL, 400000, 1975000, 25000),
+       PFUZE100_SW_REG(PFUZE200, SW3B, PFUZE100_SW3BVOL, 400000, 1975000, 25000),
+       PFUZE100_SWB_REG(PFUZE200, SWBST, PFUZE100_SWBSTCON1, 0x3 , pfuze100_swbst),
+       PFUZE100_SWB_REG(PFUZE200, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
+       PFUZE100_FIXED_REG(PFUZE200, VREFDDR, PFUZE100_VREFDDRCON, 750000),
+       PFUZE100_VGEN_REG(PFUZE200, VGEN1, PFUZE100_VGEN1VOL, 800000, 1550000, 50000),
+       PFUZE100_VGEN_REG(PFUZE200, VGEN2, PFUZE100_VGEN2VOL, 800000, 1550000, 50000),
+       PFUZE100_VGEN_REG(PFUZE200, VGEN3, PFUZE100_VGEN3VOL, 1800000, 3300000, 100000),
+       PFUZE100_VGEN_REG(PFUZE200, VGEN4, PFUZE100_VGEN4VOL, 1800000, 3300000, 100000),
+       PFUZE100_VGEN_REG(PFUZE200, VGEN5, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000),
+       PFUZE100_VGEN_REG(PFUZE200, VGEN6, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000),
 };
 
+static struct pfuze_regulator *pfuze_regulators;
+
 #ifdef CONFIG_OF
+/* PFUZE100 */
 static struct of_regulator_match pfuze100_matches[] = {
        { .name = "sw1ab",      },
        { .name = "sw1c",       },
@@ -244,6 +267,26 @@ static struct of_regulator_match pfuze100_matches[] = {
        { .name = "vgen6",      },
 };
 
+/* PFUZE200 */
+static struct of_regulator_match pfuze200_matches[] = {
+
+       { .name = "sw1ab",      },
+       { .name = "sw2",        },
+       { .name = "sw3a",       },
+       { .name = "sw3b",       },
+       { .name = "swbst",      },
+       { .name = "vsnvs",      },
+       { .name = "vrefddr",    },
+       { .name = "vgen1",      },
+       { .name = "vgen2",      },
+       { .name = "vgen3",      },
+       { .name = "vgen4",      },
+       { .name = "vgen5",      },
+       { .name = "vgen6",      },
+};
+
+static struct of_regulator_match *pfuze_matches;
+
 static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
 {
        struct device *dev = chip->dev;
@@ -260,8 +303,20 @@ static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
                return -EINVAL;
        }
 
-       ret = of_regulator_match(dev, parent, pfuze100_matches,
-                                ARRAY_SIZE(pfuze100_matches));
+       switch (chip->chip_id) {
+       case PFUZE200:
+               pfuze_matches = pfuze200_matches;
+               ret = of_regulator_match(dev, parent, pfuze200_matches,
+                                        ARRAY_SIZE(pfuze200_matches));
+               break;
+
+       case PFUZE100:
+       default:
+               pfuze_matches = pfuze100_matches;
+               ret = of_regulator_match(dev, parent, pfuze100_matches,
+                                        ARRAY_SIZE(pfuze100_matches));
+               break;
+       }
 
        of_node_put(parent);
        if (ret < 0) {
@@ -275,12 +330,12 @@ static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
 
 static inline struct regulator_init_data *match_init_data(int index)
 {
-       return pfuze100_matches[index].init_data;
+       return pfuze_matches[index].init_data;
 }
 
 static inline struct device_node *match_of_node(int index)
 {
-       return pfuze100_matches[index].of_node;
+       return pfuze_matches[index].of_node;
 }
 #else
 static int pfuze_parse_regulators_dt(struct pfuze_chip *chip)
@@ -308,16 +363,14 @@ static int pfuze_identify(struct pfuze_chip *pfuze_chip)
        if (ret)
                return ret;
 
-       switch (value & 0x0f) {
-       /*
-        * Freescale misprogrammed 1-3% of parts prior to week 8 of 2013
-        * as ID=8
-        */
-       case 0x8:
+       if (((value & 0x0f) == 0x8) && (pfuze_chip->chip_id == PFUZE100)) {
+               /*
+                * Freescale misprogrammed 1-3% of parts prior to week 8 of 2013
+                * as ID=8 in PFUZE100
+                */
                dev_info(pfuze_chip->dev, "Assuming misprogrammed ID=0x8");
-       case 0x0:
-               break;
-       default:
+       } else if ((value & 0x0f) != pfuze_chip->chip_id) {
+               /* device id NOT match with your setting */
                dev_warn(pfuze_chip->dev, "Illegal ID: %x\n", value);
                return -ENODEV;
        }
@@ -353,17 +406,31 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
            dev_get_platdata(&client->dev);
        struct regulator_config config = { };
        int i, ret;
+       const struct of_device_id *match;
+       u32 regulator_num;
+       u32 sw_check_start, sw_check_end;
 
        pfuze_chip = devm_kzalloc(&client->dev, sizeof(*pfuze_chip),
                        GFP_KERNEL);
        if (!pfuze_chip)
                return -ENOMEM;
 
-       i2c_set_clientdata(client, pfuze_chip);
-
-       memcpy(pfuze_chip->regulator_descs, pfuze100_regulators,
-               sizeof(pfuze_chip->regulator_descs));
+       if (client->dev.of_node) {
+               match = of_match_device(of_match_ptr(pfuze_dt_ids),
+                               &client->dev);
+               if (!match) {
+                       dev_err(&client->dev, "Error: No device match found\n");
+                       return -ENODEV;
+               }
+               pfuze_chip->chip_id = (int)(long)match->data;
+       } else if (id) {
+               pfuze_chip->chip_id = id->driver_data;
+       } else {
+               dev_err(&client->dev, "No dts match or id table match found\n");
+               return -ENODEV;
+       }
 
+       i2c_set_clientdata(client, pfuze_chip);
        pfuze_chip->dev = &client->dev;
 
        pfuze_chip->regmap = devm_regmap_init_i2c(client, &pfuze_regmap_config);
@@ -380,11 +447,34 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
                return ret;
        }
 
+       /* use the right regulators after identify the right device */
+       switch (pfuze_chip->chip_id) {
+       case PFUZE200:
+               pfuze_regulators = pfuze200_regulators;
+               regulator_num = ARRAY_SIZE(pfuze200_regulators);
+               sw_check_start = PFUZE200_SW2;
+               sw_check_end = PFUZE200_SW3B;
+               break;
+
+       case PFUZE100:
+       default:
+               pfuze_regulators = pfuze100_regulators;
+               regulator_num = ARRAY_SIZE(pfuze100_regulators);
+               sw_check_start = PFUZE100_SW2;
+               sw_check_end = PFUZE100_SW4;
+               break;
+       }
+       dev_info(&client->dev, "pfuze%s found.\n",
+               (pfuze_chip->chip_id == PFUZE100) ? "100" : "200");
+
+       memcpy(pfuze_chip->regulator_descs, pfuze_regulators,
+               sizeof(pfuze_chip->regulator_descs));
+
        ret = pfuze_parse_regulators_dt(pfuze_chip);
        if (ret)
                return ret;
 
-       for (i = 0; i < PFUZE100_MAX_REGULATOR; i++) {
+       for (i = 0; i < regulator_num; i++) {
                struct regulator_init_data *init_data;
                struct regulator_desc *desc;
                int val;
@@ -397,7 +487,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
                        init_data = match_init_data(i);
 
                /* SW2~SW4 high bit check and modify the voltage value table */
-               if (i > PFUZE100_SW1C && i < PFUZE100_SWBST) {
+               if (i >= sw_check_start && i <= sw_check_end) {
                        regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val);
                        if (val & 0x40) {
                                desc->min_uV = 800000;
@@ -415,7 +505,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
                        devm_regulator_register(&client->dev, desc, &config);
                if (IS_ERR(pfuze_chip->regulators[i])) {
                        dev_err(&client->dev, "register regulator%s failed\n",
-                               pfuze100_regulators[i].desc.name);
+                               pfuze_regulators[i].desc.name);
                        return PTR_ERR(pfuze_chip->regulators[i]);
                }
        }
index 65d550bf395474f8427f8d67a2eaa1bd2db20945..364f7a7c43db3db23e67805983e90b3dd0187837 100644 (file)
 #define PFUZE100_VGEN6         14
 #define PFUZE100_MAX_REGULATOR 15
 
+#define PFUZE200_SW1AB         0
+#define PFUZE200_SW2           1
+#define PFUZE200_SW3A          2
+#define PFUZE200_SW3B          3
+#define PFUZE200_SWBST         4
+#define PFUZE200_VSNVS         5
+#define PFUZE200_VREFDDR       6
+#define PFUZE200_VGEN1         7
+#define PFUZE200_VGEN2         8
+#define PFUZE200_VGEN3         9
+#define PFUZE200_VGEN4         10
+#define PFUZE200_VGEN5         11
+#define PFUZE200_VGEN6         12
+
 struct regulator_init_data;
 
 struct pfuze_regulator_platform_data {