From 9c25960cbba1fb452adf6a7b9d740fc4358f7d92 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 24 Jan 2014 15:48:18 -0200 Subject: [PATCH 01/17] regulator: gpio-regulator: Remove unneeded OOM error message There is no need to print an OOM message after devm_kzalloc, since there is a generic OOM message in place. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index c0a1d00b78c9..bad44f366b3f 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -239,10 +239,8 @@ static int gpio_regulator_probe(struct platform_device *pdev) drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data), GFP_KERNEL); - if (drvdata == NULL) { - dev_err(&pdev->dev, "Failed to allocate device data\n"); + if (drvdata == NULL) return -ENOMEM; - } drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); if (drvdata->desc.name == NULL) { From 4d047d6c1fbebdee463d6296e27c37764dc54cf7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 28 Jan 2014 13:18:25 +0100 Subject: [PATCH 02/17] regulator: max14577: Remove unused state container definition Remove the "struct max14577_regulator" because this is not used anywhere. It should be removed earlier along with changing the driver after review on the mailing lists. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/max14577.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/regulator/max14577.c b/drivers/regulator/max14577.c index b1078ba3f393..38821458d413 100644 --- a/drivers/regulator/max14577.c +++ b/drivers/regulator/max14577.c @@ -1,7 +1,7 @@ /* * max14577.c - Regulator driver for the Maxim 14577 * - * Copyright (C) 2013 Samsung Electronics + * Copyright (C) 2013,2014 Samsung Electronics * Krzysztof Kozlowski * * This program is free software; you can redistribute it and/or modify @@ -22,12 +22,6 @@ #include #include -struct max14577_regulator { - struct device *dev; - struct max14577 *max14577; - struct regulator_dev **regulators; -}; - static int max14577_reg_is_enabled(struct regulator_dev *rdev) { int rid = rdev_get_id(rdev); From 0094050d783bbadffe83effef11a0bda901153ce Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 30 Jan 2014 21:25:14 -0800 Subject: [PATCH 03/17] regulator: gpio: add gpios-status for DT config->gpios[x].flags indicates initial pin status, and it will be used for drvdata->state on gpio_regulator_probe(). But, current of_get_gpio_regulator_config() doesn't care about this flags. This patch adds new gpios-status property in order to care about initial pin status. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/gpio-regulator.txt | 1 + drivers/regulator/gpio-regulator.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt index 63c659800c03..3ecb585e786c 100644 --- a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt @@ -8,6 +8,7 @@ Required properties: Optional properties: - enable-gpio : GPIO to use to enable/disable the regulator. - gpios : GPIO group used to control voltage. +- gpios-states : gpios pin's initial states. 1 means HIGH - 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 bad44f366b3f..ac3a8c732dd8 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -172,11 +172,22 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) if (!config->gpios) return ERR_PTR(-ENOMEM); + prop = of_find_property(np, "gpios-states", NULL); + if (prop) { + proplen = prop->length / sizeof(int); + if (proplen != config->nr_gpios) { + /* gpios <-> gpios-states mismatch */ + prop = NULL; + } + } + for (i = 0; i < config->nr_gpios; i++) { gpio = of_get_named_gpio(np, "gpios", i); if (gpio < 0) break; config->gpios[i].gpio = gpio; + if (prop && be32_to_cpup((int *)prop->value + i)) + config->gpios[i].flags = GPIOF_OUT_INIT_HIGH; } /* Fetch states. */ From 7f196ec938967af7c3aa2506b8edcd7da5f5ebc6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 5 Dec 2013 19:08:55 +0000 Subject: [PATCH 04/17] regulator: gpio: Document regulator-type property Reported-by: Laurent Pinchart Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/gpio-regulator.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt index 63c659800c03..1229541f48a2 100644 --- a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt @@ -10,6 +10,8 @@ Optional properties: - gpios : GPIO group used to control voltage. - startup-delay-us : Startup time in microseconds. - enable-active-high : Polarity of GPIO is active high (default is low). +- regulator-type : Specifies what is being regulated, must be either + "voltage" or "current", defaults to current. Any property defined as part of the core regulator binding defined in regulator.txt can also be used. From e31108cad3deabb1a63111d7aa699ca67753c01f Mon Sep 17 00:00:00 2001 From: Manish Badarkhe Date: Wed, 29 Jan 2014 20:27:27 +0530 Subject: [PATCH 05/17] devres: introduce API "devm_kstrdup" This patch introduces "devm_kstrdup" API so that the device's driver can allocate memory and copy string. Signed-off-by: Manish Badarkhe Signed-off-by: Mark Brown --- drivers/base/devres.c | 26 ++++++++++++++++++++++++++ include/linux/device.h | 1 + 2 files changed, 27 insertions(+) diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 545c4de412c3..db4e264eecb6 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -790,6 +790,32 @@ void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) } EXPORT_SYMBOL_GPL(devm_kmalloc); +/** + * devm_kstrdup - Allocate resource managed space and + * copy an existing string into that. + * @dev: Device to allocate memory for + * @s: the string to duplicate + * @gfp: the GFP mask used in the devm_kmalloc() call when + * allocating memory + * RETURNS: + * Pointer to allocated string on success, NULL on failure. + */ +char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) +{ + size_t size; + char *buf; + + if (!s) + return NULL; + + size = strlen(s) + 1; + buf = devm_kmalloc(dev, size, gfp); + if (buf) + memcpy(buf, s, size); + return buf; +} +EXPORT_SYMBOL_GPL(devm_kstrdup); + /** * devm_kfree - Resource-managed kfree * @dev: Device this memory belongs to diff --git a/include/linux/device.h b/include/linux/device.h index 952b01033c32..ec1b6e21f0ef 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -626,6 +626,7 @@ static inline void *devm_kcalloc(struct device *dev, return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO); } extern void devm_kfree(struct device *dev, void *p); +extern char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp); void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res); void __iomem *devm_request_and_ioremap(struct device *dev, From 84d0ffbe28e0bdd2f54c91e5162ae42a6c9cf431 Mon Sep 17 00:00:00 2001 From: Manish Badarkhe Date: Wed, 29 Jan 2014 20:27:28 +0530 Subject: [PATCH 06/17] regulator: fixed: update to devm_* API Update the code to use devm_* API so that driver core will manage resources. Signed-off-by: Manish Badarkhe Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 42 +++++++++++---------------------------- 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 5ea64b94341c..3c307d62fd31 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -132,15 +132,15 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) GFP_KERNEL); if (drvdata == NULL) { dev_err(&pdev->dev, "Failed to allocate device data\n"); - ret = -ENOMEM; - goto err; + return -ENOMEM; } - drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); + drvdata->desc.name = devm_kstrdup(&pdev->dev, + config->supply_name, + GFP_KERNEL); if (drvdata->desc.name == NULL) { dev_err(&pdev->dev, "Failed to allocate supply name\n"); - ret = -ENOMEM; - goto err; + return -ENOMEM; } drvdata->desc.type = REGULATOR_VOLTAGE; drvdata->desc.owner = THIS_MODULE; @@ -149,13 +149,13 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->desc.enable_time = config->startup_delay; if (config->input_supply) { - drvdata->desc.supply_name = kstrdup(config->input_supply, - GFP_KERNEL); + drvdata->desc.supply_name = devm_kstrdup(&pdev->dev, + config->input_supply, + GFP_KERNEL); if (!drvdata->desc.supply_name) { dev_err(&pdev->dev, "Failed to allocate input supply\n"); - ret = -ENOMEM; - goto err_name; + return -ENOMEM; } } @@ -186,11 +186,12 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) cfg.driver_data = drvdata; cfg.of_node = pdev->dev.of_node; - drvdata->dev = regulator_register(&drvdata->desc, &cfg); + drvdata->dev = devm_regulator_register(&pdev->dev, &drvdata->desc, + &cfg); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); - goto err_input; + return ret; } platform_set_drvdata(pdev, drvdata); @@ -199,24 +200,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->desc.fixed_uV); return 0; - -err_input: - kfree(drvdata->desc.supply_name); -err_name: - kfree(drvdata->desc.name); -err: - return ret; -} - -static int reg_fixed_voltage_remove(struct platform_device *pdev) -{ - struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev); - - regulator_unregister(drvdata->dev); - kfree(drvdata->desc.supply_name); - kfree(drvdata->desc.name); - - return 0; } #if defined(CONFIG_OF) @@ -229,7 +212,6 @@ MODULE_DEVICE_TABLE(of, fixed_of_match); static struct platform_driver regulator_fixed_voltage_driver = { .probe = reg_fixed_voltage_probe, - .remove = reg_fixed_voltage_remove, .driver = { .name = "reg-fixed-voltage", .owner = THIS_MODULE, From 5676ddc5c62861467582b10b88aadb25ea9c3b52 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 11 Feb 2014 17:27:08 -0800 Subject: [PATCH 07/17] regulator: gpio: print warning if gpios <-> gpios-states mismatch on DT Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index ac3a8c732dd8..5491ceeb53cc 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -176,7 +176,7 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) if (prop) { proplen = prop->length / sizeof(int); if (proplen != config->nr_gpios) { - /* gpios <-> gpios-states mismatch */ + dev_warn(dev, "gpios <-> gpios-states mismatch\n"); prop = NULL; } } From 907339818ecd66c20f57bbf53d1160c3dc9d34a8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 11 Feb 2014 17:27:27 -0800 Subject: [PATCH 08/17] regulator: gpio: explain detail of gpios-states gpios-states is array, and default is 0 Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/gpio-regulator.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt index 3ecb585e786c..356e8bbd9b2a 100644 --- a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt @@ -8,7 +8,8 @@ Required properties: Optional properties: - enable-gpio : GPIO to use to enable/disable the regulator. - gpios : GPIO group used to control voltage. -- gpios-states : gpios pin's initial states. 1 means HIGH +- gpios-states : gpios pin's initial states array. 0: LOW, 1: HIGH. + defualt is LOW if nothing is specified. - startup-delay-us : Startup time in microseconds. - enable-active-high : Polarity of GPIO is active high (default is low). From ad54a0cfbeb4bd4033d09017557ccbc423f9d5ff Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 12 Feb 2014 01:00:34 +0100 Subject: [PATCH 09/17] of: add functions to count number of elements in a property The need to know the number of array elements in a property is a common pattern. To prevent duplication of open-coded implementations add a helper static function that also centralises strict sanity checking and DTB format details, as well as a set of wrapper functions for u8, u16, u32 and u64. Suggested-by: Mark Rutland Signed-off-by: Heiko Stuebner Acked-by: Rob Herring Acked-by: Grant Likely Acked-by: Mark Rutland Signed-off-by: Mark Brown --- drivers/of/base.c | 32 +++++++++++++++++++ include/linux/of.h | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index ff85450d5683..8a2a55c65e5d 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -885,6 +885,38 @@ struct device_node *of_find_node_by_phandle(phandle handle) } EXPORT_SYMBOL(of_find_node_by_phandle); +/** + * of_property_count_elems_of_size - Count the number of elements in a property + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @elem_size: size of the individual element + * + * Search for a property in a device node and count the number of elements of + * size elem_size in it. Returns number of elements on sucess, -EINVAL if the + * property does not exist or its length does not match a multiple of elem_size + * and -ENODATA if the property does not have a value. + */ +int of_property_count_elems_of_size(const struct device_node *np, + const char *propname, int elem_size) +{ + struct property *prop = of_find_property(np, propname, NULL); + + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + + if (prop->length % elem_size != 0) { + pr_err("size of %s in node %s is not a multiple of %d\n", + propname, np->full_name, elem_size); + return -EINVAL; + } + + return prop->length / elem_size; +} +EXPORT_SYMBOL_GPL(of_property_count_elems_of_size); + /** * of_find_property_value_of_size * diff --git a/include/linux/of.h b/include/linux/of.h index 70c64ba17fa5..b59f2e41c7ce 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -250,6 +250,8 @@ extern struct device_node *of_find_node_with_property( extern struct property *of_find_property(const struct device_node *np, const char *name, int *lenp); +extern int of_property_count_elems_of_size(const struct device_node *np, + const char *propname, int elem_size); extern int of_property_read_u32_index(const struct device_node *np, const char *propname, u32 index, u32 *out_value); @@ -431,6 +433,12 @@ static inline struct device_node *of_find_compatible_node( return NULL; } +static inline int of_property_count_elems_of_size(const struct device_node *np, + const char *propname, int elem_size) +{ + return -ENOSYS; +} + static inline int of_property_read_u32_index(const struct device_node *np, const char *propname, u32 index, u32 *out_value) { @@ -569,6 +577,74 @@ extern int of_node_to_nid(struct device_node *np); static inline int of_node_to_nid(struct device_node *device) { return 0; } #endif +/** + * of_property_count_u8_elems - Count the number of u8 elements in a property + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u8 elements + * in it. Returns number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u8 and -ENODATA if the + * property does not have a value. + */ +static inline int of_property_count_u8_elems(const struct device_node *np, + const char *propname) +{ + return of_property_count_elems_of_size(np, propname, sizeof(u8)); +} + +/** + * of_property_count_u16_elems - Count the number of u16 elements in a property + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u16 elements + * in it. Returns number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u16 and -ENODATA if the + * property does not have a value. + */ +static inline int of_property_count_u16_elems(const struct device_node *np, + const char *propname) +{ + return of_property_count_elems_of_size(np, propname, sizeof(u16)); +} + +/** + * of_property_count_u32_elems - Count the number of u32 elements in a property + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u32 elements + * in it. Returns number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u32 and -ENODATA if the + * property does not have a value. + */ +static inline int of_property_count_u32_elems(const struct device_node *np, + const char *propname) +{ + return of_property_count_elems_of_size(np, propname, sizeof(u32)); +} + +/** + * of_property_count_u64_elems - Count the number of u64 elements in a property + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u64 elements + * in it. Returns number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u64 and -ENODATA if the + * property does not have a value. + */ +static inline int of_property_count_u64_elems(const struct device_node *np, + const char *propname) +{ + return of_property_count_elems_of_size(np, propname, sizeof(u64)); +} + /** * of_property_read_bool - Findfrom a property * @np: device node from which the property value is to be read. From 934624d6e9f0b3d41557c4105c286e8daeaadb4e Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 12 Feb 2014 01:01:08 +0100 Subject: [PATCH 10/17] regulator: gpio-regulator: do not open-code counting and access of dt array elements Open coding the counting of elements in a dt-property is abstracted by the newly introduced of_property_count_uXX_elems functions. Additionally the raw iteration over the states element exposes the endian conversion and dtb-format details, which according to Mark Rutland "would be nice to limit [...] to of_ helper functions". Thus change gpio-regulator to use the helper for element counting and of_property_read_u32_index for retrieval of individual values. This makes it possible to remove the raw access to the states property entirely. Signed-off-by: Heiko Stuebner Acked-by: Mark Rutland Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 5491ceeb53cc..9fd55611016c 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -136,7 +136,6 @@ static 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; int ret; @@ -191,14 +190,12 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) } /* Fetch states. */ - prop = of_find_property(np, "states", NULL); - if (!prop) { + proplen = of_property_count_u32_elems(np, "states"); + if (proplen < 0) { dev_err(dev, "No 'states' property found\n"); return ERR_PTR(-EINVAL); } - proplen = prop->length / sizeof(int); - config->states = devm_kzalloc(dev, sizeof(struct gpio_regulator_state) * (proplen / 2), @@ -207,10 +204,10 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) 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)); + of_property_read_u32_index(np, "states", i * 2, + &config->states[i].value); + of_property_read_u32_index(np, "states", i * 2 + 1, + &config->states[i].gpios); } config->nr_states = i; From 1f5a9623eb4300a722eab2f6c6a31a194c804cec Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 13 Feb 2014 16:34:32 +0100 Subject: [PATCH 11/17] regulator: gpio-regulator: fix forgotten gpios-states reading Commit 934624d6e9f0 ("regulator: gpio-regulator: do not open-code counting and access of dt array elements") forgot to convert the recently added gpios-states property using the same pattern. Convert this instance to use the of-helpers too, resolving the build error. Signed-off-by: Heiko Stuebner Signed-off-by: Mark Brown --- drivers/regulator/gpio-regulator.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 9fd55611016c..989b23b377c0 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -171,13 +171,14 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) if (!config->gpios) return ERR_PTR(-ENOMEM); - prop = of_find_property(np, "gpios-states", NULL); - if (prop) { - proplen = prop->length / sizeof(int); - if (proplen != config->nr_gpios) { - dev_warn(dev, "gpios <-> gpios-states mismatch\n"); - prop = NULL; - } + proplen = of_property_count_u32_elems(np, "gpios-states"); + /* optional property */ + if (proplen < 0) + proplen = 0; + + if (proplen > 0 && proplen != config->nr_gpios) { + dev_warn(dev, "gpios <-> gpios-states mismatch\n"); + proplen = 0; } for (i = 0; i < config->nr_gpios; i++) { @@ -185,8 +186,11 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) if (gpio < 0) break; config->gpios[i].gpio = gpio; - if (prop && be32_to_cpup((int *)prop->value + i)) - config->gpios[i].flags = GPIOF_OUT_INIT_HIGH; + if (proplen > 0) { + of_property_read_u32_index(np, "gpios-states", i, &ret); + if (ret) + config->gpios[i].flags = GPIOF_OUT_INIT_HIGH; + } } /* Fetch states. */ From ad5ec6cdb2c409bf34db27c41d151bd307fac2a0 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 18 Feb 2014 16:11:02 +0530 Subject: [PATCH 12/17] regulator: lp872x: Do not hardcode return values Propagate the error values returned by the function instead. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 2e4734ff79fc..2e022aabd951 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -211,7 +211,7 @@ static int lp872x_get_timestep_usec(struct lp872x *lp) ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val); if (ret) - return -EINVAL; + return ret; val = (val & mask) >> shift; if (val >= size) @@ -229,7 +229,7 @@ static int lp872x_regulator_enable_time(struct regulator_dev *rdev) u8 addr, val; if (time_step_us < 0) - return -EINVAL; + return time_step_us; switch (rid) { case LP8720_ID_LDO1 ... LP8720_ID_BUCK: From a1985d469d5c2881b34baee32e4fc74447748b44 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 18 Feb 2014 16:11:03 +0530 Subject: [PATCH 13/17] regulator: lp3971: Do not hardcode return value Propagate the error value returned by the function instead. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/regulator/lp3971.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 3b1102b75071..66fd2330dca0 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -327,7 +327,7 @@ static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count, return -EIO; ret = i2c_smbus_read_byte_data(i2c, reg); if (ret < 0) - return -EIO; + return ret; *dest = ret; return 0; From 145fe1e1d533943fc93da42d6f2e13aba919776e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 18 Feb 2014 16:11:04 +0530 Subject: [PATCH 14/17] regulator: fan53555: Do not hardcode return values Propagate the error values returned by the function instead. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 7ca3d9e3b0fe..a10df7d150cc 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -90,11 +90,11 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV) return 0; ret = regulator_map_voltage_linear(rdev, uV, uV); if (ret < 0) - return -EINVAL; + return ret; ret = regmap_update_bits(di->regmap, di->sleep_reg, VSEL_NSEL_MASK, ret); if (ret < 0) - return -EINVAL; + return ret; /* Cache the sleep voltage setting. * Might not be the real voltage which is rounded */ di->sleep_vol_cache = uV; @@ -260,14 +260,14 @@ static int fan53555_regulator_probe(struct i2c_client *client, ret = regmap_read(di->regmap, FAN53555_ID1, &val); if (ret < 0) { dev_err(&client->dev, "Failed to get chip ID!\n"); - return -ENODEV; + return ret; } di->chip_id = val & DIE_ID; /* Get chip revision */ ret = regmap_read(di->regmap, FAN53555_ID2, &val); if (ret < 0) { dev_err(&client->dev, "Failed to get chip Rev!\n"); - return -ENODEV; + return ret; } di->chip_rev = val & DIE_REV; dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!\n", From df948bbf486817565f0e3c8b65e6cc0bbc13f0eb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 20 Feb 2014 14:23:04 +0530 Subject: [PATCH 15/17] regulator: fan53555: Remove redundant error message kzalloc prints its own OOM message upon failure. Signed-off-by: Sachin Kamat Cc: Yunfan Zhang Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index a10df7d150cc..714fd9a89aa1 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -244,10 +244,9 @@ static int fan53555_regulator_probe(struct i2c_client *client, di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info), GFP_KERNEL); - if (!di) { - dev_err(&client->dev, "Failed to allocate device info data!\n"); + if (!di) return -ENOMEM; - } + di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); if (IS_ERR(di->regmap)) { dev_err(&client->dev, "Failed to allocate regmap!\n"); From f1b3f9031d255e1ac61dcc3b600fcf6e2bebc6f8 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 20 Feb 2014 14:23:05 +0530 Subject: [PATCH 16/17] regulator: fixed: Remove redundant error message kzalloc prints its own OOM message upon failure. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 3c307d62fd31..c61f7e97e4f8 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -130,10 +130,8 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data), GFP_KERNEL); - if (drvdata == NULL) { - dev_err(&pdev->dev, "Failed to allocate device data\n"); + if (!drvdata) return -ENOMEM; - } drvdata->desc.name = devm_kstrdup(&pdev->dev, config->supply_name, From ca5d1b3524b4d90a2e2f1f71583c1dca6b96fd92 Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Wed, 5 Mar 2014 22:11:29 +0100 Subject: [PATCH 17/17] regulator: helpers: Modify helpers enabling multi-bit control This patch extends the regulator helpers to account for device that use multiple bits for control when using regmap enable/disable/bypass ops. The actual regulator helpers wrongly assume that the regulator control is always performed using single bits, using in the regulator_desc struct only two parameters *_reg and *_mask defining register and mask for control. This patch extends this struct and introduces the helpers to take into account devices where control is performed using multiple bits and specific multi-bit values are used for enabling/disabling/bypassing the regulator. Signed-off-by: Carlo Caione Signed-off-by: Mark Brown --- drivers/regulator/helpers.c | 48 +++++++++++++++++++++----------- include/linux/regulator/driver.h | 8 ++++++ 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index e221a271ba56..cbc39096c78d 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -37,10 +37,17 @@ int regulator_is_enabled_regmap(struct regulator_dev *rdev) if (ret != 0) return ret; - if (rdev->desc->enable_is_inverted) - return (val & rdev->desc->enable_mask) == 0; - else - return (val & rdev->desc->enable_mask) != 0; + val &= rdev->desc->enable_mask; + + if (rdev->desc->enable_is_inverted) { + if (rdev->desc->enable_val) + return val != rdev->desc->enable_val; + return val == 0; + } else { + if (rdev->desc->enable_val) + return val == rdev->desc->enable_val; + return val != 0; + } } EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap); @@ -57,10 +64,13 @@ int regulator_enable_regmap(struct regulator_dev *rdev) { unsigned int val; - if (rdev->desc->enable_is_inverted) - val = 0; - else - val = rdev->desc->enable_mask; + if (rdev->desc->enable_is_inverted) { + val = rdev->desc->disable_val; + } else { + val = rdev->desc->enable_val; + if (!val) + val = rdev->desc->enable_mask; + } return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, rdev->desc->enable_mask, val); @@ -80,10 +90,13 @@ int regulator_disable_regmap(struct regulator_dev *rdev) { unsigned int val; - if (rdev->desc->enable_is_inverted) - val = rdev->desc->enable_mask; - else - val = 0; + if (rdev->desc->enable_is_inverted) { + val = rdev->desc->enable_val; + if (!val) + val = rdev->desc->enable_mask; + } else { + val = rdev->desc->disable_val; + } return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, rdev->desc->enable_mask, val); @@ -419,10 +432,13 @@ int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) { unsigned int val; - if (enable) - val = rdev->desc->bypass_mask; - else - val = 0; + if (enable) { + val = rdev->desc->bypass_val_on; + if (!val) + val = rdev->desc->bypass_mask; + } else { + val = rdev->desc->bypass_val_off; + } return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, rdev->desc->bypass_mask, val); diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 9370e65348a4..bbe03a1924c0 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -228,10 +228,14 @@ enum regulator_type { * output when using regulator_set_voltage_sel_regmap * @enable_reg: Register for control when using regmap enable/disable ops * @enable_mask: Mask for control when using regmap enable/disable ops + * @enable_val: Enabling value for control when using regmap enable/disable ops + * @disable_val: Disabling value for control when using regmap enable/disable ops * @enable_is_inverted: A flag to indicate set enable_mask bits to disable * when using regulator_enable_regmap and friends APIs. * @bypass_reg: Register for control when using regmap set_bypass * @bypass_mask: Mask for control when using regmap set_bypass + * @bypass_val_on: Enabling value for control when using regmap set_bypass + * @bypass_val_off: Disabling value for control when using regmap set_bypass * * @enable_time: Time taken for initial enable of regulator (in uS). */ @@ -263,9 +267,13 @@ struct regulator_desc { unsigned int apply_bit; unsigned int enable_reg; unsigned int enable_mask; + unsigned int enable_val; + unsigned int disable_val; bool enable_is_inverted; unsigned int bypass_reg; unsigned int bypass_mask; + unsigned int bypass_val_on; + unsigned int bypass_val_off; unsigned int enable_time; };