From 006694d099e86e5a928fb39bdea280ab42c9d59c Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 15 Oct 2012 14:16:59 +0100 Subject: [PATCH 1/5] regulator: gpio-regulator: Allow use of GPIO controlled regulators though DT Here we provide the GPIO Regulator driver with Device Tree capability, so that when a platform is booting with DT instead of platform data we can still make full use of it. Signed-off-by: Lee Jones Reviewed-by: Stephen Warren Signed-off-by: Mark Brown --- .../bindings/regulator/gpio-regulator.txt | 36 +++++++ drivers/regulator/gpio-regulator.c | 94 +++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/gpio-regulator.txt diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt new file mode 100644 index 000000000000..3703be2ab821 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt @@ -0,0 +1,36 @@ +GPIO controlled regulators + +Required properties: +- compatible : Must be "regulator-gpio". + +Optional properties: +- gpio-enable : GPIO to use to enable/disable the regulator. +- gpios : GPIO group used to control voltage. +- states : Selection of available voltages and GPIO configs. +- startup-delay-us : Startup time in microseconds. +- enable-active-high : Polarity of GPIO is active high (default is low). + +Any property defined as part of the core regulator binding defined in +regulator.txt can also be used. + +Example: + + mmciv: gpio-regulator { + compatible = "regulator-gpio"; + + regulator-name = "mmci-gpio-supply"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2600000>; + regulator-boot-on; + + gpio-enable = <&gpio0 23 0x4>; + gpios = <&gpio0 24 0x4 + &gpio0 25 0x4>; + states = <1800000 0x3 + 2200000 0x2 + 2600000 0x1 + 2900000 0x0>; + + startup-delay-us = <100000>; + enable-active-high; + }; diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 8b5944f2d7d1..e467d0ac8705 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -28,9 +28,12 @@ #include #include #include +#include #include #include #include +#include +#include struct gpio_regulator_data { struct regulator_desc desc; @@ -129,6 +132,84 @@ static struct regulator_ops gpio_regulator_voltage_ops = { .list_voltage = gpio_regulator_list_voltage, }; +struct gpio_regulator_config * +of_get_gpio_regulator_config(struct device *dev, struct device_node *np) +{ + struct gpio_regulator_config *config; + struct property *prop; + const char *regtype; + int proplen, gpio, i; + + config = devm_kzalloc(dev, + sizeof(struct gpio_regulator_config), + GFP_KERNEL); + if (!config) + return ERR_PTR(-ENOMEM); + + config->init_data = of_get_regulator_init_data(dev, np); + if (!config->init_data) + return ERR_PTR(-EINVAL); + + config->supply_name = config->init_data->constraints.name; + + if (of_property_read_bool(np, "enable-active-high")) + config->enable_high = true; + + if (of_property_read_bool(np, "enable-at-boot")) + config->enabled_at_boot = true; + + of_property_read_u32(np, "startup-delay-us", &config->startup_delay); + + config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0); + + /* Fetch GPIOs. */ + for (i = 0; ; i++) + if (of_get_named_gpio(np, "gpios", i) < 0) + break; + config->nr_gpios = i; + + config->gpios = devm_kzalloc(dev, + sizeof(struct gpio) * config->nr_gpios, + GFP_KERNEL); + if (!config->gpios) + return ERR_PTR(-ENOMEM); + + for (i = 0; config->nr_gpios; i++) { + gpio = of_get_named_gpio(np, "gpios", i); + if (gpio < 0) + break; + config->gpios[i].gpio = gpio; + } + + /* Fetch states. */ + prop = of_find_property(np, "states", NULL); + proplen = prop->length / sizeof(int); + + config->states = devm_kzalloc(dev, + sizeof(struct gpio_regulator_state) + * (proplen / 2), + GFP_KERNEL); + if (!config->states) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < proplen / 2; i++) { + config->states[i].value = + be32_to_cpup((int *)prop->value + (i * 2)); + config->states[i].gpios = + be32_to_cpup((int *)prop->value + (i * 2 + 1)); + } + config->nr_states = i; + + of_property_read_string(np, "regulator-type", ®type); + + if (!strncmp("voltage", regtype, 7)) + config->type = REGULATOR_VOLTAGE; + else if (!strncmp("current", regtype, 7)) + config->type = REGULATOR_CURRENT; + + return config; +} + static struct regulator_ops gpio_regulator_current_ops = { .get_current_limit = gpio_regulator_get_value, .set_current_limit = gpio_regulator_set_current_limit, @@ -137,10 +218,17 @@ static struct regulator_ops gpio_regulator_current_ops = { static int __devinit gpio_regulator_probe(struct platform_device *pdev) { struct gpio_regulator_config *config = pdev->dev.platform_data; + struct device_node *np = pdev->dev.of_node; struct gpio_regulator_data *drvdata; struct regulator_config cfg = { }; int ptr, ret, state; + if (np) { + config = of_get_gpio_regulator_config(&pdev->dev, np); + if (IS_ERR(config)) + return PTR_ERR(config); + } + drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data), GFP_KERNEL); if (drvdata == NULL) { @@ -270,12 +358,18 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id regulator_gpio_of_match[] __devinitconst = { + { .compatible = "regulator-gpio", }, + {}, +}; + static struct platform_driver gpio_regulator_driver = { .probe = gpio_regulator_probe, .remove = __devexit_p(gpio_regulator_remove), .driver = { .name = "gpio-regulator", .owner = THIS_MODULE, + .of_match_table = regulator_gpio_of_match, }, }; From dea05fe66edb4540a53ed6623794c4978315256a Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 12 Nov 2012 17:58:28 +0800 Subject: [PATCH 2/5] regulator: gpio-regulator: doc: Fix wrong key gpio-enable Wrong description in binding document. Doc use "gpio-enable", but code use "enable-gpio" In drivers/regulator/gpio-regulator.c config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0); Signed-off-by: Frank Li Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/gpio-regulator.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt index 3703be2ab821..f71f8083c2ae 100644 --- a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt @@ -4,7 +4,7 @@ Required properties: - compatible : Must be "regulator-gpio". Optional properties: -- gpio-enable : GPIO to use to enable/disable the regulator. +- enable-gpio : GPIO to use to enable/disable the regulator. - gpios : GPIO group used to control voltage. - states : Selection of available voltages and GPIO configs. - startup-delay-us : Startup time in microseconds. @@ -23,7 +23,7 @@ Example: regulator-max-microvolt = <2600000>; regulator-boot-on; - gpio-enable = <&gpio0 23 0x4>; + enable-gpio = <&gpio0 23 0x4>; gpios = <&gpio0 24 0x4 &gpio0 25 0x4>; states = <1800000 0x3 From f8a9f757cb425c4784b80b001c7a77c7810b499f Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 12 Nov 2012 17:59:52 +0800 Subject: [PATCH 3/5] regulator: gpio-regulator: fix can't find regulator node in dt Need initilize of_node in regulator config when register regulator, otherwise regulator driver think it is no-dt device. in regulator_dev_lookup list_for_each_entry(r, ®ulator_list, list) if (r->dev.parent && node == r->dev.of_node) return r r->dev.of_noe will be zero if miss config in cfg. Signed-off-by: Frank Li Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index e467d0ac8705..faa2f712eb0d 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -303,6 +303,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) cfg.dev = &pdev->dev; cfg.init_data = config->init_data; cfg.driver_data = drvdata; + cfg.of_node = np; if (config->enable_gpio >= 0) cfg.ena_gpio = config->enable_gpio; From 216f2b9c95ac6e4f00b08df807bc4454434a9afb Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 14 Nov 2012 11:51:36 +0000 Subject: [PATCH 4/5] regulator: gpio-regulator: Catch 'no states property' misuse A selection of voltage or current values (AKA states) should always be specified when using a GPIO regulator. If there are no switchable states then the fixed regulators should be used instead. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/gpio-regulator.txt | 3 ++- drivers/regulator/gpio-regulator.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt index f71f8083c2ae..63c659800c03 100644 --- a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt @@ -2,11 +2,12 @@ GPIO controlled regulators Required properties: - compatible : Must be "regulator-gpio". +- states : Selection of available voltages and GPIO configs. + if there are no states, then use a fixed regulator Optional properties: - enable-gpio : GPIO to use to enable/disable the regulator. - gpios : GPIO group used to control voltage. -- states : Selection of available voltages and GPIO configs. - startup-delay-us : Startup time in microseconds. - enable-active-high : Polarity of GPIO is active high (default is low). diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index faa2f712eb0d..dc9260545b80 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -183,6 +183,11 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) /* Fetch states. */ prop = of_find_property(np, "states", NULL); + if (!prop) { + dev_err(dev, "No 'states' property found\n"); + return ERR_PTR(-EINVAL); + } + proplen = prop->length / sizeof(int); config->states = devm_kzalloc(dev, From ec4f7b88b4a89253ec922d48f77b269ce5cffc2c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 4 Dec 2012 10:32:05 +0800 Subject: [PATCH 5/5] regulator: gpio-regulator: Add ifdef CONFIG_OF guard for regulator_gpio_of_match Use of_match_ptr and add ifdef CONFIG_OF guard for regulator_gpio_of_match. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index dc9260545b80..8c4e23739494 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -364,10 +364,12 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev) return 0; } +#if defined(CONFIG_OF) static const struct of_device_id regulator_gpio_of_match[] __devinitconst = { { .compatible = "regulator-gpio", }, {}, }; +#endif static struct platform_driver gpio_regulator_driver = { .probe = gpio_regulator_probe, @@ -375,7 +377,7 @@ static struct platform_driver gpio_regulator_driver = { .driver = { .name = "gpio-regulator", .owner = THIS_MODULE, - .of_match_table = regulator_gpio_of_match, + .of_match_table = of_match_ptr(regulator_gpio_of_match), }, };