Merge remote-tracking branches 'regulator/topic/max8973', 'regulator/topic/max8997...
[linux-2.6-microblaze.git] / drivers / regulator / pfuze100-regulator.c
index ab174f2..67e678c 100644 (file)
@@ -56,6 +56,8 @@
 #define PFUZE100_VGEN5VOL      0x70
 #define PFUZE100_VGEN6VOL      0x71
 
+enum chips { PFUZE100, PFUZE200 };
+
 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];
@@ -78,21 +81,23 @@ static const int pfuze100_vsnvs[] = {
 };
 
 static const struct i2c_device_id pfuze_device_id[] = {
-       {.name = "pfuze100"},
-       {},
+       {.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" },
-       {},
+       { .compatible = "fsl,pfuze100", .data = (void *)PFUZE100},
+       { .compatible = "fsl,pfuze200", .data = (void *)PFUZE200},
+       { }
 };
 MODULE_DEVICE_TABLE(of, pfuze_dt_ids);
 
 static int pfuze100_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
 {
        struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev);
-       int id = rdev->desc->id;
+       int id = rdev_get_id(rdev);
        unsigned int ramp_bits;
        int ret;
 
@@ -139,14 +144,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 +159,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 +177,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 +192,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 +212,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,24 +269,56 @@ 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;
        struct device_node *np, *parent;
        int ret;
 
-       np = of_node_get(dev->parent->of_node);
+       np = of_node_get(dev->of_node);
        if (!np)
-               return 0;
+               return -EINVAL;
 
-       parent = of_find_node_by_name(np, "regulators");
+       parent = of_get_child_by_name(np, "regulators");
        if (!parent) {
                dev_err(dev, "regulators node not found\n");
                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 +332,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 +365,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 +408,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 +449,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 +489,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 +507,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]);
                }
        }
@@ -435,6 +527,6 @@ static struct i2c_driver pfuze_driver = {
 module_i2c_driver(pfuze_driver);
 
 MODULE_AUTHOR("Robin Gong <b38343@freescale.com>");
-MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100 PMIC");
+MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100/PFUZE200 PMIC");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("i2c:pfuze100-regulator");