diff options
author | Mark Brown <broonie@sirena.org.uk> | 2013-04-28 02:13:43 +0100 |
---|---|---|
committer | Mark Brown <broonie@sirena.org.uk> | 2013-04-28 02:13:43 +0100 |
commit | a2c05e91b991179d43e358d5eb9390f57a59a75f (patch) | |
tree | 6f33a25e977d47558ea914ddd96be05683f1d366 /drivers/regulator | |
parent | 2e1be9f7b359d653331876968e68e849857222d3 (diff) | |
parent | 71622e15dd4d497447d19317d93292184ceb67d9 (diff) |
Merge remote-tracking branch 'regulator/topic/max8952' into v3.9-rc8
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/max8952.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index fc7935a19e3a..5259c2fea90a 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -28,6 +28,9 @@ #include <linux/regulator/max8952.h> #include <linux/gpio.h> #include <linux/io.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/regulator/of_regulator.h> #include <linux/slab.h> /* Registers */ @@ -126,6 +129,69 @@ static const struct regulator_desc regulator = { .owner = THIS_MODULE, }; +#ifdef CONFIG_OF +static struct of_device_id max8952_dt_match[] = { + { .compatible = "maxim,max8952" }, + {}, +}; +MODULE_DEVICE_TABLE(of, max8952_dt_match); + +static struct max8952_platform_data *max8952_parse_dt(struct device *dev) +{ + struct max8952_platform_data *pd; + struct device_node *np = dev->of_node; + int ret; + int i; + + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + if (!pd) { + dev_err(dev, "Failed to allocate platform data\n"); + return NULL; + } + + pd->gpio_vid0 = of_get_named_gpio(np, "max8952,vid-gpios", 0); + pd->gpio_vid1 = of_get_named_gpio(np, "max8952,vid-gpios", 1); + pd->gpio_en = of_get_named_gpio(np, "max8952,en-gpio", 0); + + if (of_property_read_u32(np, "max8952,default-mode", &pd->default_mode)) + dev_warn(dev, "Default mode not specified, assuming 0\n"); + + ret = of_property_read_u32_array(np, "max8952,dvs-mode-microvolt", + pd->dvs_mode, ARRAY_SIZE(pd->dvs_mode)); + if (ret) { + dev_err(dev, "max8952,dvs-mode-microvolt property not specified"); + return NULL; + } + + for (i = 0; i < ARRAY_SIZE(pd->dvs_mode); ++i) { + if (pd->dvs_mode[i] < 770000 || pd->dvs_mode[i] > 1400000) { + dev_err(dev, "DVS voltage %d out of range\n", i); + return NULL; + } + pd->dvs_mode[i] = (pd->dvs_mode[i] - 770000) / 10000; + } + + if (of_property_read_u32(np, "max8952,sync-freq", &pd->sync_freq)) + dev_warn(dev, "max8952,sync-freq property not specified, defaulting to 26MHz\n"); + + if (of_property_read_u32(np, "max8952,ramp-speed", &pd->ramp_speed)) + dev_warn(dev, "max8952,ramp-speed property not specified, defaulting to 32mV/us\n"); + + pd->reg_data = of_get_regulator_init_data(dev, np); + if (!pd->reg_data) { + dev_err(dev, "Failed to parse regulator init data\n"); + return NULL; + } + + return pd; +} +#else +static struct max8952_platform_data *max8952_parse_dt(struct device *dev) +{ + return NULL; +} +#endif + static int max8952_pmic_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { @@ -136,6 +202,9 @@ static int max8952_pmic_probe(struct i2c_client *client, int ret = 0, err = 0; + if (client->dev.of_node) + pdata = max8952_parse_dt(&client->dev); + if (!pdata) { dev_err(&client->dev, "Require the platform data\n"); return -EINVAL; @@ -154,11 +223,12 @@ static int max8952_pmic_probe(struct i2c_client *client, max8952->pdata = pdata; config.dev = max8952->dev; - config.init_data = &pdata->reg_data; + config.init_data = pdata->reg_data; config.driver_data = max8952; + config.of_node = client->dev.of_node; config.ena_gpio = pdata->gpio_en; - if (pdata->reg_data.constraints.boot_on) + if (pdata->reg_data->constraints.boot_on) config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; max8952->rdev = regulator_register(®ulator, &config); @@ -271,6 +341,7 @@ static struct i2c_driver max8952_pmic_driver = { .remove = max8952_pmic_remove, .driver = { .name = "max8952", + .of_match_table = of_match_ptr(max8952_dt_match), }, .id_table = max8952_ids, }; |