diff --git a/[refs] b/[refs] index aecc4f059e2e..255f2cd8a2b9 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 78da02186a5a7cd813321ef018a1c6dbaf888722 +refs/heads/master: 9b31835341004022ea2862116de05fea50b8d1e4 diff --git a/trunk/Documentation/devicetree/bindings/mfd/mc13xxx.txt b/trunk/Documentation/devicetree/bindings/mfd/mc13xxx.txt index abd9e3cb2db7..baf07987ae68 100644 --- a/trunk/Documentation/devicetree/bindings/mfd/mc13xxx.txt +++ b/trunk/Documentation/devicetree/bindings/mfd/mc13xxx.txt @@ -10,40 +10,10 @@ Optional properties: - fsl,mc13xxx-uses-touch : Indicate the touchscreen controller is being used Sub-nodes: -- regulators : Contain the regulator nodes. The regulators are bound using - their names as listed below with their registers and bits for enabling. +- regulators : Contain the regulator nodes. The MC13892 regulators are + bound using their names as listed below with their registers and bits + for enabling. -MC13783 regulators: - sw1a : regulator SW1A (register 24, bit 0) - sw1b : regulator SW1B (register 25, bit 0) - sw2a : regulator SW2A (register 26, bit 0) - sw2b : regulator SW2B (register 27, bit 0) - sw3 : regulator SW3 (register 29, bit 20) - vaudio : regulator VAUDIO (register 32, bit 0) - viohi : regulator VIOHI (register 32, bit 3) - violo : regulator VIOLO (register 32, bit 6) - vdig : regulator VDIG (register 32, bit 9) - vgen : regulator VGEN (register 32, bit 12) - vrfdig : regulator VRFDIG (register 32, bit 15) - vrfref : regulator VRFREF (register 32, bit 18) - vrfcp : regulator VRFCP (register 32, bit 21) - vsim : regulator VSIM (register 33, bit 0) - vesim : regulator VESIM (register 33, bit 3) - vcam : regulator VCAM (register 33, bit 6) - vrfbg : regulator VRFBG (register 33, bit 9) - vvib : regulator VVIB (register 33, bit 11) - vrf1 : regulator VRF1 (register 33, bit 12) - vrf2 : regulator VRF2 (register 33, bit 15) - vmmc1 : regulator VMMC1 (register 33, bit 18) - vmmc2 : regulator VMMC2 (register 33, bit 21) - gpo1 : regulator GPO1 (register 34, bit 6) - gpo2 : regulator GPO2 (register 34, bit 8) - gpo3 : regulator GPO3 (register 34, bit 10) - gpo4 : regulator GPO4 (register 34, bit 12) - pwgt1spi : regulator PWGT1SPI (register 34, bit 15) - pwgt2spi : regulator PWGT2SPI (register 34, bit 16) - -MC13892 regulators: vcoincell : regulator VCOINCELL (register 13, bit 23) sw1 : regulator SW1 (register 24, bit 0) sw2 : regulator SW2 (register 25, bit 0) diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index c2d345896839..8bdd7a7ef2f4 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -8712,7 +8712,7 @@ F: drivers/scsi/vmw_pvscsi.c F: drivers/scsi/vmw_pvscsi.h VOLTAGE AND CURRENT REGULATOR FRAMEWORK -M: Liam Girdwood +M: Liam Girdwood M: Mark Brown W: http://opensource.wolfsonmicro.com/node/15 W: http://www.slimlogic.co.uk/?p=48 diff --git a/trunk/drivers/regulator/ab3100.c b/trunk/drivers/regulator/ab3100.c index 111ec69a3e94..740735d1cca0 100644 --- a/trunk/drivers/regulator/ab3100.c +++ b/trunk/drivers/regulator/ab3100.c @@ -488,6 +488,58 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { }, }; +static int ab3100_regulator_register(struct platform_device *pdev, + struct ab3100_platform_data *plfdata, + int id) +{ + struct regulator_desc *desc; + struct ab3100_regulator *reg; + struct regulator_dev *rdev; + struct regulator_config config = { }; + int err, i; + + for (i = 0; i < AB3100_NUM_REGULATORS; i++) { + desc = &ab3100_regulator_desc[i]; + if (desc->id == id) + break; + } + if (desc->id != id) + return -ENODEV; + + /* Same index used for this array */ + reg = &ab3100_regulators[i]; + + /* + * Initialize per-regulator struct. + * Inherit platform data, this comes down from the + * i2c boarddata, from the machine. So if you want to + * see what it looks like for a certain machine, go + * into the machine I2C setup. + */ + reg->dev = &pdev->dev; + if (plfdata) { + /* This will be replaced by device tree data */ + reg->plfdata = plfdata; + config.init_data = &plfdata->reg_constraints[i]; + } + config.dev = &pdev->dev; + config.driver_data = reg; + + rdev = regulator_register(desc, &config); + if (IS_ERR(rdev)) { + err = PTR_ERR(rdev); + dev_err(&pdev->dev, + "%s: failed to register regulator %s err %d\n", + __func__, desc->name, + err); + return err; + } + + /* Then set a pointer back to the registered regulator */ + reg->rdev = rdev; + return 0; +} + /* * NOTE: the following functions are regulators pluralis - it is the * binding to the AB3100 core driver and the parent platform device @@ -497,7 +549,6 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { static int ab3100_regulators_probe(struct platform_device *pdev) { struct ab3100_platform_data *plfdata = pdev->dev.platform_data; - struct regulator_config config = { }; int err = 0; u8 data; int i; @@ -530,42 +581,11 @@ static int ab3100_regulators_probe(struct platform_device *pdev) /* Register the regulators */ for (i = 0; i < AB3100_NUM_REGULATORS; i++) { - struct ab3100_regulator *reg = &ab3100_regulators[i]; - struct regulator_dev *rdev; - - /* - * Initialize per-regulator struct. - * Inherit platform data, this comes down from the - * i2c boarddata, from the machine. So if you want to - * see what it looks like for a certain machine, go - * into the machine I2C setup. - */ - reg->dev = &pdev->dev; - reg->plfdata = plfdata; - - config.dev = &pdev->dev; - config.driver_data = reg; - config.init_data = &plfdata->reg_constraints[i]; + struct regulator_desc *desc = &ab3100_regulator_desc[i]; - /* - * Register the regulator, pass around - * the ab3100_regulator struct - */ - rdev = regulator_register(&ab3100_regulator_desc[i], &config); - if (IS_ERR(rdev)) { - err = PTR_ERR(rdev); - dev_err(&pdev->dev, - "%s: failed to register regulator %s err %d\n", - __func__, ab3100_regulator_desc[i].name, - err); - /* remove the already registered regulators */ - while (--i >= 0) - regulator_unregister(ab3100_regulators[i].rdev); + err = ab3100_regulator_register(pdev, plfdata, desc->id); + if (err) return err; - } - - /* Then set a pointer back to the registered regulator */ - reg->rdev = rdev; } return 0; diff --git a/trunk/drivers/regulator/mc13783-regulator.c b/trunk/drivers/regulator/mc13783-regulator.c index fdf7f0a09090..c46c6705cd74 100644 --- a/trunk/drivers/regulator/mc13783-regulator.c +++ b/trunk/drivers/regulator/mc13783-regulator.c @@ -398,51 +398,33 @@ static int mc13783_regulator_probe(struct platform_device *pdev) struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent); struct mc13xxx_regulator_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct mc13xxx_regulator_init_data *mc13xxx_data; + struct mc13xxx_regulator_init_data *init_data; struct regulator_config config = { }; - int i, ret, num_regulators; + int i, ret; - num_regulators = mc13xxx_get_num_regulators_dt(pdev); + dev_dbg(&pdev->dev, "%s id %d\n", __func__, pdev->id); - if (num_regulators <= 0 && pdata) - num_regulators = pdata->num_regulators; - if (num_regulators <= 0) + if (!pdata) return -EINVAL; priv = devm_kzalloc(&pdev->dev, sizeof(*priv) + - num_regulators * sizeof(priv->regulators[0]), + pdata->num_regulators * sizeof(priv->regulators[0]), GFP_KERNEL); if (!priv) return -ENOMEM; - priv->num_regulators = num_regulators; priv->mc13xxx_regulators = mc13783_regulators; priv->mc13xxx = mc13783; - platform_set_drvdata(pdev, priv); - - mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13783_regulators, - ARRAY_SIZE(mc13783_regulators)); - for (i = 0; i < priv->num_regulators; i++) { - struct regulator_init_data *init_data; + for (i = 0; i < pdata->num_regulators; i++) { struct regulator_desc *desc; - struct device_node *node = NULL; - int id; - - if (mc13xxx_data) { - id = mc13xxx_data[i].id; - init_data = mc13xxx_data[i].init_data; - node = mc13xxx_data[i].node; - } else { - id = pdata->regulators[i].id; - init_data = pdata->regulators[i].init_data; - } - desc = &mc13783_regulators[id].desc; + + init_data = &pdata->regulators[i]; + desc = &mc13783_regulators[init_data->id].desc; config.dev = &pdev->dev; - config.init_data = init_data; + config.init_data = init_data->init_data; config.driver_data = priv; - config.of_node = node; priv->regulators[i] = regulator_register(desc, &config); if (IS_ERR(priv->regulators[i])) { @@ -453,6 +435,8 @@ static int mc13783_regulator_probe(struct platform_device *pdev) } } + platform_set_drvdata(pdev, priv); + return 0; err: while (--i >= 0) @@ -464,11 +448,13 @@ static int mc13783_regulator_probe(struct platform_device *pdev) static int mc13783_regulator_remove(struct platform_device *pdev) { struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); + struct mc13xxx_regulator_platform_data *pdata = + dev_get_platdata(&pdev->dev); int i; platform_set_drvdata(pdev, NULL); - for (i = 0; i < priv->num_regulators; i++) + for (i = 0; i < pdata->num_regulators; i++) regulator_unregister(priv->regulators[i]); return 0; diff --git a/trunk/drivers/regulator/mc13892-regulator.c b/trunk/drivers/regulator/mc13892-regulator.c index b8d35ec598ea..9891aec47b57 100644 --- a/trunk/drivers/regulator/mc13892-regulator.c +++ b/trunk/drivers/regulator/mc13892-regulator.c @@ -465,13 +465,13 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, */ if (mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) { - mask |= MC13892_SWITCHERS0_SWxHI; - if (volt > 1375000) { reg_value -= MC13892_SWxHI_SEL_OFFSET; reg_value |= MC13892_SWITCHERS0_SWxHI; - } else { + mask |= MC13892_SWITCHERS0_SWxHI; + } else if (volt < 1100000) { reg_value &= ~MC13892_SWITCHERS0_SWxHI; + mask |= MC13892_SWITCHERS0_SWxHI; } } @@ -535,7 +535,7 @@ static int mc13892_regulator_probe(struct platform_device *pdev) struct mc13xxx_regulator_init_data *mc13xxx_data; struct regulator_config config = { }; int i, ret; - int num_regulators = 0; + int num_regulators = 0, num_parsed; u32 val; num_regulators = mc13xxx_get_num_regulators_dt(pdev); @@ -545,6 +545,8 @@ static int mc13892_regulator_probe(struct platform_device *pdev) if (num_regulators <= 0) return -EINVAL; + num_parsed = num_regulators; + priv = devm_kzalloc(&pdev->dev, sizeof(*priv) + num_regulators * sizeof(priv->regulators[0]), GFP_KERNEL); @@ -587,9 +589,40 @@ static int mc13892_regulator_probe(struct platform_device *pdev) = mc13892_vcam_get_mode; mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, - ARRAY_SIZE(mc13892_regulators)); + ARRAY_SIZE(mc13892_regulators), + &num_parsed); + + /* + * Perform a little sanity check on the regulator tree - if we found + * a number of regulators from mc13xxx_get_num_regulators_dt and + * then parsed a smaller number in mc13xxx_parse_regulators_dt then + * there is a regulator defined in the regulators node which has + * not matched any usable regulator in the driver. In this case, + * there is one missing and what will happen is the first regulator + * will get registered again. + * + * Fix this by basically making our number of registerable regulators + * equal to the number of regulators we parsed. We are allocating + * too much memory for priv, but this is unavoidable at this point. + * + * As an example of how this can happen, try making a typo in your + * regulators node (vviohi {} instead of viohi {}) so that the name + * does not match.. + * + * The check will basically pass for platform data (non-DT) because + * mc13xxx_parse_regulators_dt for !CONFIG_OF will not touch num_parsed. + * + */ + if (num_parsed != num_regulators) { + dev_warn(&pdev->dev, + "parsed %d != regulators %d - check your device tree!\n", + num_parsed, num_regulators); + + num_regulators = num_parsed; + priv->num_regulators = num_regulators; + } - for (i = 0; i < priv->num_regulators; i++) { + for (i = 0; i < num_regulators; i++) { struct regulator_init_data *init_data; struct regulator_desc *desc; struct device_node *node = NULL; diff --git a/trunk/drivers/regulator/mc13xxx-regulator-core.c b/trunk/drivers/regulator/mc13xxx-regulator-core.c index da4859282302..23cf9f9c383b 100644 --- a/trunk/drivers/regulator/mc13xxx-regulator-core.c +++ b/trunk/drivers/regulator/mc13xxx-regulator-core.c @@ -180,13 +180,15 @@ EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt); struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( struct platform_device *pdev, struct mc13xxx_regulator *regulators, - int num_regulators) + int num_regulators, int *num_parsed) { struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); struct mc13xxx_regulator_init_data *data, *p; struct device_node *parent, *child; int i, parsed = 0; + *num_parsed = 0; + of_node_get(pdev->dev.parent->of_node); parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); if (!parent) @@ -202,13 +204,10 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( p = data; for_each_child_of_node(parent, child) { - int found = 0; - for (i = 0; i < num_regulators; i++) { - if (!regulators[i].desc.name) - continue; if (!of_node_cmp(child->name, regulators[i].desc.name)) { + p->id = i; p->init_data = of_get_regulator_init_data( &pdev->dev, child); @@ -216,19 +215,13 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( p++; parsed++; - found = 1; break; } } - - if (!found) - dev_warn(&pdev->dev, - "Unknown regulator: %s\n", child->name); } of_node_put(parent); - priv->num_regulators = parsed; - + *num_parsed = parsed; return data; } EXPORT_SYMBOL_GPL(mc13xxx_parse_regulators_dt); diff --git a/trunk/drivers/regulator/mc13xxx.h b/trunk/drivers/regulator/mc13xxx.h index 06c8903f182a..007f83387fd6 100644 --- a/trunk/drivers/regulator/mc13xxx.h +++ b/trunk/drivers/regulator/mc13xxx.h @@ -39,7 +39,7 @@ extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, extern int mc13xxx_get_num_regulators_dt(struct platform_device *pdev); extern struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( struct platform_device *pdev, struct mc13xxx_regulator *regulators, - int num_regulators); + int num_regulators, int *num_parsed); #else static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) { @@ -48,7 +48,7 @@ static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) static inline struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( struct platform_device *pdev, struct mc13xxx_regulator *regulators, - int num_regulators) + int num_regulators, int *num_parsed) { return NULL; }