From 3415d60113f64176114f1bddc09f76c222d85fae Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sun, 14 Sep 2014 21:23:01 +0200 Subject: regulator: fan53555: enable vin supply The regulator can be supplied by a parent regulator through its vin pin, so add the supply_name for it. Signed-off-by: Heiko Stuebner Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/regulator/fan53555.c') diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 714fd9a89aa1..c912ba7bed33 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -207,6 +207,7 @@ static int fan53555_regulator_register(struct fan53555_device_info *di, struct regulator_desc *rdesc = &di->desc; rdesc->name = "fan53555-reg"; + rdesc->supply_name = "vin"; rdesc->ops = &fan53555_regulator_ops; rdesc->type = REGULATOR_VOLTAGE; rdesc->n_voltages = FAN53555_NVOLTAGES; -- cgit v1.2.3 From dd7e71fbeefe9179b94eed81f8b33da06b9bf062 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 16 Sep 2014 17:54:01 +0200 Subject: regulator: fan53555: use set_ramp_delay to set the ramp up slew rate The regulator constraints already provide a field for the ramp_delay, so there is no need to set this manually. Therefore implement the set_ramp_delay callback and convert the pdata value to the constraint value if necessary. Signed-off-by: Heiko Stuebner Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 53 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 11 deletions(-) (limited to 'drivers/regulator/fan53555.c') diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index c912ba7bed33..5808435cfae0 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -135,6 +135,38 @@ static unsigned int fan53555_get_mode(struct regulator_dev *rdev) return REGULATOR_MODE_NORMAL; } +static int slew_rates[] = { + 64000, + 32000, + 16000, + 8000, + 4000, + 2000, + 1000, + 500, +}; + +static int fan53555_set_ramp(struct regulator_dev *rdev, int ramp) +{ + struct fan53555_device_info *di = rdev_get_drvdata(rdev); + int regval = -1, i; + + for (i = 0; i < ARRAY_SIZE(slew_rates); i++) { + if (ramp <= slew_rates[i]) + regval = i; + else + break; + } + + if (regval < 0) { + dev_err(di->dev, "unsupported ramp value %d\n", ramp); + return -EINVAL; + } + + return regmap_update_bits(di->regmap, FAN53555_CONTROL, + CTL_SLEW_MASK, regval << CTL_SLEW_SHIFT); +} + static struct regulator_ops fan53555_regulator_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -146,6 +178,7 @@ static struct regulator_ops fan53555_regulator_ops = { .is_enabled = regulator_is_enabled_regmap, .set_mode = fan53555_set_mode, .get_mode = fan53555_get_mode, + .set_ramp_delay = fan53555_set_ramp, }; /* For 00,01,03,05 options: @@ -156,8 +189,6 @@ static struct regulator_ops fan53555_regulator_ops = { static int fan53555_device_setup(struct fan53555_device_info *di, struct fan53555_platform_data *pdata) { - unsigned int reg, data, mask; - /* Setup voltage control register */ switch (pdata->sleep_vsel_id) { case FAN53555_VSEL_ID_0: @@ -190,15 +221,8 @@ static int fan53555_device_setup(struct fan53555_device_info *di, "Chip ID[%d]\n not supported!\n", di->chip_id); return -EINVAL; } - /* Init slew rate */ - if (pdata->slew_rate & 0x7) - di->slew_rate = pdata->slew_rate; - else - di->slew_rate = FAN53555_SLEW_RATE_64MV; - reg = FAN53555_CONTROL; - data = di->slew_rate << CTL_SLEW_SHIFT; - mask = CTL_SLEW_MASK; - return regmap_update_bits(di->regmap, reg, mask, data); + + return 0; } static int fan53555_regulator_register(struct fan53555_device_info *di, @@ -248,6 +272,13 @@ static int fan53555_regulator_probe(struct i2c_client *client, if (!di) return -ENOMEM; + /* if no ramp constraint set, get the pdata ramp_delay */ + if (!di->regulator->constraints.ramp_delay) { + int slew_idx = (pdata->slew_rate & 0x7) ? pdata->slew_rate : 0; + + di->regulator->constraints.ramp_delay = slew_rates[slew_idx]; + } + di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); if (IS_ERR(di->regmap)) { dev_err(&client->dev, "Failed to allocate regmap!\n"); -- cgit v1.2.3 From 91f23d8fb67c90a50676e4db9260a21647ef753f Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 16 Sep 2014 21:22:53 +0200 Subject: regulator: fan53555: add devicetree support Add the ability to parse regulator-data from the devicetree. Signed-off-by: Heiko Stuebner Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 50 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) (limited to 'drivers/regulator/fan53555.c') diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 5808435cfae0..fa29ba052841 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -252,9 +254,39 @@ static struct regmap_config fan53555_regmap_config = { .val_bits = 8, }; +static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev, + struct device_node *np) +{ + struct fan53555_platform_data *pdata; + int ret; + u32 tmp; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + pdata->regulator = of_get_regulator_init_data(dev, np); + + ret = of_property_read_u32(np, "fcs,suspend-voltage-selector", + &tmp); + if (!ret) + pdata->sleep_vsel_id = tmp; + + return pdata; +} + +static const struct of_device_id fan53555_dt_ids[] = { + { + .compatible = "fcs,fan53555", + }, + { } +}; +MODULE_DEVICE_TABLE(of, fan53555_dt_ids); + static int fan53555_regulator_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device_node *np = client->dev.of_node; struct fan53555_device_info *di; struct fan53555_platform_data *pdata; struct regulator_config config = { }; @@ -262,6 +294,9 @@ static int fan53555_regulator_probe(struct i2c_client *client, int ret; pdata = dev_get_platdata(&client->dev); + if (!pdata) + pdata = fan53555_parse_dt(&client->dev, np); + if (!pdata || !pdata->regulator) { dev_err(&client->dev, "Platform data not found!\n"); return -ENODEV; @@ -272,11 +307,15 @@ static int fan53555_regulator_probe(struct i2c_client *client, if (!di) return -ENOMEM; - /* if no ramp constraint set, get the pdata ramp_delay */ - if (!di->regulator->constraints.ramp_delay) { - int slew_idx = (pdata->slew_rate & 0x7) ? pdata->slew_rate : 0; + if (!client->dev.of_node) { + /* if no ramp constraint set, get the pdata ramp_delay */ + if (!di->regulator->constraints.ramp_delay) { + int slew_idx = (pdata->slew_rate & 0x7) + ? pdata->slew_rate : 0; - di->regulator->constraints.ramp_delay = slew_rates[slew_idx]; + di->regulator->constraints.ramp_delay + = slew_rates[slew_idx]; + } } di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); @@ -314,6 +353,8 @@ static int fan53555_regulator_probe(struct i2c_client *client, config.init_data = di->regulator; config.regmap = di->regmap; config.driver_data = di; + config.of_node = np; + ret = fan53555_regulator_register(di, &config); if (ret < 0) dev_err(&client->dev, "Failed to register regulator!\n"); @@ -329,6 +370,7 @@ static const struct i2c_device_id fan53555_id[] = { static struct i2c_driver fan53555_regulator_driver = { .driver = { .name = "fan53555-regulator", + .of_match_table = of_match_ptr(fan53555_dt_ids), }, .probe = fan53555_regulator_probe, .id_table = fan53555_id, -- cgit v1.2.3 From ee30928ab616786cae926c5c2efaa4303ba66802 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 16 Sep 2014 21:22:54 +0200 Subject: regulator: fan53555: add support for Silergy SYR82x regulators Silergy SYR82x regulators share the exact same functionality and register layout as the Fairchild FAN53555 regulators. Therefore extend the driver to add support for them. Both types use the same vendor id in their ID1 register, so it's not possible to distinguish them automatically. Similarly, the types also do not match. Type 8 used by the SYR827 and SYR828 start at 712.5mV and increment in 12.5mv steps, while the FAN53555 type 8 starts at 600mV and increments in 10mV steps. Signed-off-by: Heiko Stuebner Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/fan53555.txt | 2 +- .../devicetree/bindings/vendor-prefixes.txt | 1 + drivers/regulator/fan53555.c | 102 ++++++++++++++++++--- 3 files changed, 89 insertions(+), 16 deletions(-) (limited to 'drivers/regulator/fan53555.c') diff --git a/Documentation/devicetree/bindings/regulator/fan53555.txt b/Documentation/devicetree/bindings/regulator/fan53555.txt index b183738d6ca9..54a3f2c80e3a 100644 --- a/Documentation/devicetree/bindings/regulator/fan53555.txt +++ b/Documentation/devicetree/bindings/regulator/fan53555.txt @@ -1,7 +1,7 @@ Binding for Fairchild FAN53555 regulators Required properties: - - compatible: "fcs,fan53555" + - compatible: one of "fcs,fan53555", "silergy,syr827", "silergy,syr828" - reg: I2C address Optional properties: diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 24b92b31f2b5..6073e76575ea 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -125,6 +125,7 @@ sil Silicon Image silabs Silicon Laboratories simtek sii Seiko Instruments, Inc. +silergy Silergy Corp. sirf SiRF Technology, Inc. smsc Standard Microsystems Corporation snps Synopsys, Inc. diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index fa29ba052841..f2f5535099a0 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -52,6 +52,11 @@ #define FAN53555_NVOLTAGES 64 /* Numbers of voltages */ +enum fan53555_vendor { + FAN53555_VENDOR_FAIRCHILD = 0, + FAN53555_VENDOR_SILERGY, +}; + /* IC Type */ enum { FAN53555_CHIP_ID_00 = 0, @@ -62,7 +67,12 @@ enum { FAN53555_CHIP_ID_05, }; +enum { + SILERGY_SYR82X = 8, +}; + struct fan53555_device_info { + enum fan53555_vendor vendor; struct regmap *regmap; struct device *dev; struct regulator_desc desc; @@ -183,6 +193,47 @@ static struct regulator_ops fan53555_regulator_ops = { .set_ramp_delay = fan53555_set_ramp, }; +static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) +{ + /* Init voltage range and step */ + switch (di->chip_id) { + case FAN53555_CHIP_ID_00: + case FAN53555_CHIP_ID_01: + case FAN53555_CHIP_ID_03: + case FAN53555_CHIP_ID_05: + di->vsel_min = 600000; + di->vsel_step = 10000; + break; + case FAN53555_CHIP_ID_04: + di->vsel_min = 603000; + di->vsel_step = 12826; + break; + default: + dev_err(di->dev, + "Chip ID %d not supported!\n", di->chip_id); + return -EINVAL; + } + + return 0; +} + +static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di) +{ + /* Init voltage range and step */ + switch (di->chip_id) { + case SILERGY_SYR82X: + di->vsel_min = 712500; + di->vsel_step = 12500; + break; + default: + dev_err(di->dev, + "Chip ID %d not supported!\n", di->chip_id); + return -EINVAL; + } + + return 0; +} + /* For 00,01,03,05 options: * VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V. * For 04 option: @@ -191,6 +242,8 @@ static struct regulator_ops fan53555_regulator_ops = { static int fan53555_device_setup(struct fan53555_device_info *di, struct fan53555_platform_data *pdata) { + int ret = 0; + /* Setup voltage control register */ switch (pdata->sleep_vsel_id) { case FAN53555_VSEL_ID_0: @@ -205,26 +258,21 @@ static int fan53555_device_setup(struct fan53555_device_info *di, dev_err(di->dev, "Invalid VSEL ID!\n"); return -EINVAL; } - /* Init voltage range and step */ - switch (di->chip_id) { - case FAN53555_CHIP_ID_00: - case FAN53555_CHIP_ID_01: - case FAN53555_CHIP_ID_03: - case FAN53555_CHIP_ID_05: - di->vsel_min = 600000; - di->vsel_step = 10000; + + switch (di->vendor) { + case FAN53555_VENDOR_FAIRCHILD: + ret = fan53555_voltages_setup_fairchild(di); break; - case FAN53555_CHIP_ID_04: - di->vsel_min = 603000; - di->vsel_step = 12826; + case FAN53555_VENDOR_SILERGY: + ret = fan53555_voltages_setup_silergy(di); break; default: dev_err(di->dev, - "Chip ID[%d]\n not supported!\n", di->chip_id); + "vendor %d not supported!\n", di->chip_id); return -EINVAL; } - return 0; + return ret; } static int fan53555_regulator_register(struct fan53555_device_info *di, @@ -278,6 +326,13 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev, static const struct of_device_id fan53555_dt_ids[] = { { .compatible = "fcs,fan53555", + .data = (void *)FAN53555_VENDOR_FAIRCHILD + }, { + .compatible = "silergy,syr827", + .data = (void *)FAN53555_VENDOR_SILERGY, + }, { + .compatible = "silergy,syr828", + .data = (void *)FAN53555_VENDOR_SILERGY, }, { } }; @@ -307,7 +362,16 @@ static int fan53555_regulator_probe(struct i2c_client *client, if (!di) return -ENOMEM; - if (!client->dev.of_node) { + if (client->dev.of_node) { + const struct of_device_id *match; + + match = of_match_device(of_match_ptr(fan53555_dt_ids), + &client->dev); + if (!match) + return -ENODEV; + + di->vendor = (int) match->data; + } else { /* if no ramp constraint set, get the pdata ramp_delay */ if (!di->regulator->constraints.ramp_delay) { int slew_idx = (pdata->slew_rate & 0x7) @@ -316,6 +380,8 @@ static int fan53555_regulator_probe(struct i2c_client *client, di->regulator->constraints.ramp_delay = slew_rates[slew_idx]; } + + di->vendor = id->driver_data; } di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); @@ -363,7 +429,13 @@ static int fan53555_regulator_probe(struct i2c_client *client, } static const struct i2c_device_id fan53555_id[] = { - {"fan53555", -1}, + { + .name = "fan53555", + .driver_data = FAN53555_VENDOR_FAIRCHILD + }, { + .name = "syr82x", + .driver_data = FAN53555_VENDOR_SILERGY + }, { }, }; -- cgit v1.2.3 From 6f34163c5474326dd70239045f1957fe369460dd Mon Sep 17 00:00:00 2001 From: Heiko Stübner Date: Wed, 17 Sep 2014 13:21:48 +0200 Subject: regulator: fan53555: fix wrong cast in probe The vendor-id gathered from the dt match-data was cast to int but assigned to an unsigned long, producing warnings on at least sparc, like drivers/regulator/fan53555.c: In function 'fan53555_regulator_probe': >> drivers/regulator/fan53555.c:373:16: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] di->vendor = (int) match->data; Fix this by using an appropriate cast. Reported-by: kbuild test robot Signed-off-by: Heiko Stuebner Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator/fan53555.c') diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index f2f5535099a0..6ca6e2651168 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -370,7 +370,7 @@ static int fan53555_regulator_probe(struct i2c_client *client, if (!match) return -ENODEV; - di->vendor = (int) match->data; + di->vendor = (unsigned long) match->data; } else { /* if no ramp constraint set, get the pdata ramp_delay */ if (!di->regulator->constraints.ramp_delay) { -- cgit v1.2.3 From fe230531b3f94f33e5a4c0b201b651188c6cc132 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 18 Sep 2014 21:48:48 +0800 Subject: regulator: fan53555: Fixup report wrong vendor message Signed-off-by: Axel Lin Reviewed-by: Heiko Stuebner Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/regulator/fan53555.c') diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 6ca6e2651168..0168106b2cf7 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -267,8 +267,7 @@ static int fan53555_device_setup(struct fan53555_device_info *di, ret = fan53555_voltages_setup_silergy(di); break; default: - dev_err(di->dev, - "vendor %d not supported!\n", di->chip_id); + dev_err(di->dev, "vendor %d not supported!\n", di->vendor); return -EINVAL; } -- cgit v1.2.3 From e13426bf249b4928ad914c9ddf7f8b7e5a93e1c6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 18 Sep 2014 21:49:38 +0800 Subject: regulator: fan53555: Fix null pointer dereference Set di->regulator before dereference it. Signed-off-by: Axel Lin Reviewed-by: Heiko Stuebner Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator/fan53555.c') diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 0168106b2cf7..f8e4257aef92 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -361,6 +361,7 @@ static int fan53555_regulator_probe(struct i2c_client *client, if (!di) return -ENOMEM; + di->regulator = pdata->regulator; if (client->dev.of_node) { const struct of_device_id *match; @@ -389,7 +390,6 @@ static int fan53555_regulator_probe(struct i2c_client *client, return PTR_ERR(di->regmap); } di->dev = &client->dev; - di->regulator = pdata->regulator; i2c_set_clientdata(client, di); /* Get chip ID */ ret = regmap_read(di->regmap, FAN53555_ID1, &val); -- cgit v1.2.3