[U-Boot] [PATCH] power: regulator: Add support for gpio regulators

Add support for gpio regulators. As of now this driver caters to gpio regulators with one gpio. Supports setting voltage values to gpio regulators and retrieving the values.
Signed-off-by: Keerthy j-keerthy@ti.com --- drivers/power/regulator/Kconfig | 8 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/gpio-regulator.c | 136 +++++++++++++++++++++++++++++++ include/power/regulator.h | 1 + 4 files changed, 146 insertions(+) create mode 100644 drivers/power/regulator/gpio-regulator.c
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 2510474..4776011 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -58,6 +58,14 @@ config DM_REGULATOR_FIXED features for fixed value regulators. The driver implements get/set api for enable and get only for voltage value.
+config DM_REGULATOR_GPIO + bool "Enable Driver Model for GPIO REGULATOR" + depends on DM_REGULATOR + ---help--- + This config enables implementation of driver-model regulator uclass + features for gpio regulators. The driver implements get/set for + voltage value. + config REGULATOR_RK808 bool "Enable driver for RK808 regulators" depends on DM_REGULATOR && PMIC_RK808 diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index 2093048..2d350cb 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o +obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_RK808) += rk808.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o diff --git a/drivers/power/regulator/gpio-regulator.c b/drivers/power/regulator/gpio-regulator.c new file mode 100644 index 0000000..9c8832e --- /dev/null +++ b/drivers/power/regulator/gpio-regulator.c @@ -0,0 +1,136 @@ +/* + * (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com> + * Keerthy j-keerthy@ti.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fdtdec.h> +#include <errno.h> +#include <dm.h> +#include <i2c.h> +#include <asm/gpio.h> +#include <power/pmic.h> +#include <power/regulator.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct gpio_regulator_platdata { + struct gpio_desc gpio; /* GPIO for regulator voltage control */ + int gpio_low_uV; + int gpio_high_uV; +}; + +static int gpio_regulator_ofdata_to_platdata(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + struct gpio_regulator_platdata *dev_pdata; + struct gpio_desc *gpio; + const void *blob = gd->fdt_blob; + int node = dev->of_offset; + int ret, count, i; + u32 states_array[8]; + + dev_pdata = dev_get_platdata(dev); + uc_pdata = dev_get_uclass_platdata(dev); + if (!uc_pdata) + return -ENXIO; + + /* Set type to gpio */ + uc_pdata->type = REGULATOR_TYPE_GPIO; + + /* + * Get gpio regulator gpio desc + * Assuming one GPIO per regulator. + * Can be extended later to multiple GPIOs + * per gpio-regulator. As of now no instance with multiple + * gpios is presnt + */ + gpio = &dev_pdata->gpio; + ret = gpio_request_by_name(dev, "gpios", 0, gpio, GPIOD_IS_OUT); + if (ret) + debug("regulator gpio - not found! Error: %d", ret); + + count = fdtdec_get_int_array_count(blob, node, "states", + states_array, 8); + + if (!count) + return -EINVAL; + + for (i = 0; i < count; i += 2) { + if (states_array[i + 1] == 0) + dev_pdata->gpio_low_uV = states_array[i]; + else + dev_pdata->gpio_high_uV = states_array[i]; + } + + return 0; +} + +static int gpio_regulator_get_value(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev); + int enable; + + if (!dev_pdata->gpio.dev) + return -ENOSYS; + + uc_pdata = dev_get_uclass_platdata(dev); + if (uc_pdata->min_uV > uc_pdata->max_uV) { + debug("Invalid constraints for: %s\n", uc_pdata->name); + return -EINVAL; + } + + enable = dm_gpio_get_value(&dev_pdata->gpio); + if (enable) + return dev_pdata->gpio_high_uV; + else + return dev_pdata->gpio_low_uV; +} + +static int gpio_regulator_set_value(struct udevice *dev, int uV) +{ + struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev); + int ret; + bool enable; + + if (!dev_pdata->gpio.dev) + return -ENOSYS; + + if (uV == dev_pdata->gpio_high_uV) + enable = 1; + else if (uV == dev_pdata->gpio_low_uV) + enable = 0; + else + return -EINVAL; + + ret = dm_gpio_set_value(&dev_pdata->gpio, enable); + if (ret) { + error("Can't set regulator : %s gpio to: %d\n", dev->name, + enable); + return ret; + } + + return 0; +} + +static const struct dm_regulator_ops gpio_regulator_ops = { + .get_value = gpio_regulator_get_value, + .set_value = gpio_regulator_set_value, +}; + +static const struct udevice_id gpio_regulator_ids[] = { + { .compatible = "regulator-gpio" }, + { }, +}; + +U_BOOT_DRIVER(gpio_regulator) = { + .name = "gpio regulator", + .id = UCLASS_REGULATOR, + .ops = &gpio_regulator_ops, + .of_match = gpio_regulator_ids, + .ofdata_to_platdata = gpio_regulator_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct gpio_regulator_platdata), +}; diff --git a/include/power/regulator.h b/include/power/regulator.h index 8ae6b14..5d327e6 100644 --- a/include/power/regulator.h +++ b/include/power/regulator.h @@ -108,6 +108,7 @@ enum regulator_type { REGULATOR_TYPE_BUCK, REGULATOR_TYPE_DVS, REGULATOR_TYPE_FIXED, + REGULATOR_TYPE_GPIO, REGULATOR_TYPE_OTHER, };

Hello Keerthy,
On 09/15/2016 10:25 AM, Keerthy wrote:
Add support for gpio regulators. As of now this driver caters to gpio regulators with one gpio. Supports setting voltage values to gpio regulators and retrieving the values.
Signed-off-by: Keerthy j-keerthy@ti.com
drivers/power/regulator/Kconfig | 8 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/gpio-regulator.c | 136 +++++++++++++++++++++++++++++++ include/power/regulator.h | 1 + 4 files changed, 146 insertions(+) create mode 100644 drivers/power/regulator/gpio-regulator.c
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 2510474..4776011 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -58,6 +58,14 @@ config DM_REGULATOR_FIXED features for fixed value regulators. The driver implements get/set api for enable and get only for voltage value.
+config DM_REGULATOR_GPIO
- bool "Enable Driver Model for GPIO REGULATOR"
- depends on DM_REGULATOR
- ---help---
- This config enables implementation of driver-model regulator uclass
- features for gpio regulators. The driver implements get/set for
- voltage value.
- config REGULATOR_RK808 bool "Enable driver for RK808 regulators" depends on DM_REGULATOR && PMIC_RK808
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index 2093048..2d350cb 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o +obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_RK808) += rk808.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o diff --git a/drivers/power/regulator/gpio-regulator.c b/drivers/power/regulator/gpio-regulator.c new file mode 100644 index 0000000..9c8832e --- /dev/null +++ b/drivers/power/regulator/gpio-regulator.c @@ -0,0 +1,136 @@ +/*
- (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com>
- Keerthy j-keerthy@ti.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <fdtdec.h> +#include <errno.h> +#include <dm.h> +#include <i2c.h> +#include <asm/gpio.h> +#include <power/pmic.h> +#include <power/regulator.h>
+DECLARE_GLOBAL_DATA_PTR;
+struct gpio_regulator_platdata {
- struct gpio_desc gpio; /* GPIO for regulator voltage control */
- int gpio_low_uV;
- int gpio_high_uV;
+};
The low/high values can be provided by regulator's uclass driver in struct of type "dm_regulator_uclass_platdata", as for other regulators.
But as I can see in the Linux, this driver should provide a structure for the gpio states.
+static int gpio_regulator_ofdata_to_platdata(struct udevice *dev) +{
- struct dm_regulator_uclass_platdata *uc_pdata;
- struct gpio_regulator_platdata *dev_pdata;
- struct gpio_desc *gpio;
- const void *blob = gd->fdt_blob;
- int node = dev->of_offset;
- int ret, count, i;
- u32 states_array[8];
- dev_pdata = dev_get_platdata(dev);
- uc_pdata = dev_get_uclass_platdata(dev);
- if (!uc_pdata)
return -ENXIO;
- /* Set type to gpio */
- uc_pdata->type = REGULATOR_TYPE_GPIO;
- /*
* Get gpio regulator gpio desc
* Assuming one GPIO per regulator.
* Can be extended later to multiple GPIOs
* per gpio-regulator. As of now no instance with multiple
* gpios is presnt
*/
- gpio = &dev_pdata->gpio;
- ret = gpio_request_by_name(dev, "gpios", 0, gpio, GPIOD_IS_OUT);
- if (ret)
debug("regulator gpio - not found! Error: %d", ret);
- count = fdtdec_get_int_array_count(blob, node, "states",
states_array, 8);
- if (!count)
return -EINVAL;
- for (i = 0; i < count; i += 2) {
The below condition is valid for most devices.
In Linux we can find dts for some ARMs in which I can find at least two boards, with inverted meaning of state/voltage, so "0", can be also valid for the high uV.
I think, this driver should keep possible states in platdata.
if (states_array[i + 1] == 0)
dev_pdata->gpio_low_uV = states_array[i];
else
dev_pdata->gpio_high_uV = states_array[i];
- }
- return 0;
+}
+static int gpio_regulator_get_value(struct udevice *dev) +{
- struct dm_regulator_uclass_platdata *uc_pdata;
- struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev);
- int enable;
- if (!dev_pdata->gpio.dev)
return -ENOSYS;
- uc_pdata = dev_get_uclass_platdata(dev);
- if (uc_pdata->min_uV > uc_pdata->max_uV) {
debug("Invalid constraints for: %s\n", uc_pdata->name);
return -EINVAL;
- }
- enable = dm_gpio_get_value(&dev_pdata->gpio);
The returned value (enable) should be compared to the states kept in platdata.
- if (enable)
return dev_pdata->gpio_high_uV;
- else
return dev_pdata->gpio_low_uV;
+}
+static int gpio_regulator_set_value(struct udevice *dev, int uV) +{
- struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev);
- int ret;
- bool enable;
- if (!dev_pdata->gpio.dev)
return -ENOSYS;
- if (uV == dev_pdata->gpio_high_uV)
enable = 1;
- else if (uV == dev_pdata->gpio_low_uV)
enable = 0;
- else
return -EINVAL;
And also here you should get the "enable" value from states kept in platdata.
- ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
- if (ret) {
error("Can't set regulator : %s gpio to: %d\n", dev->name,
enable);
return ret;
- }
- return 0;
+}
+static const struct dm_regulator_ops gpio_regulator_ops = {
- .get_value = gpio_regulator_get_value,
- .set_value = gpio_regulator_set_value,
+};
+static const struct udevice_id gpio_regulator_ids[] = {
- { .compatible = "regulator-gpio" },
- { },
+};
+U_BOOT_DRIVER(gpio_regulator) = {
- .name = "gpio regulator",
- .id = UCLASS_REGULATOR,
- .ops = &gpio_regulator_ops,
- .of_match = gpio_regulator_ids,
- .ofdata_to_platdata = gpio_regulator_ofdata_to_platdata,
- .platdata_auto_alloc_size = sizeof(struct gpio_regulator_platdata),
+}; diff --git a/include/power/regulator.h b/include/power/regulator.h index 8ae6b14..5d327e6 100644 --- a/include/power/regulator.h +++ b/include/power/regulator.h @@ -108,6 +108,7 @@ enum regulator_type { REGULATOR_TYPE_BUCK, REGULATOR_TYPE_DVS, REGULATOR_TYPE_FIXED,
- REGULATOR_TYPE_GPIO, REGULATOR_TYPE_OTHER, };
Best regards,

On Thursday 15 September 2016 03:04 PM, Przemyslaw Marczak wrote:
Hello Keerthy,
On 09/15/2016 10:25 AM, Keerthy wrote:
Add support for gpio regulators. As of now this driver caters to gpio regulators with one gpio. Supports setting voltage values to gpio regulators and retrieving the values.
Signed-off-by: Keerthy j-keerthy@ti.com
drivers/power/regulator/Kconfig | 8 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/gpio-regulator.c | 136 +++++++++++++++++++++++++++++++ include/power/regulator.h | 1 + 4 files changed, 146 insertions(+) create mode 100644 drivers/power/regulator/gpio-regulator.c
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 2510474..4776011 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -58,6 +58,14 @@ config DM_REGULATOR_FIXED features for fixed value regulators. The driver implements get/set api for enable and get only for voltage value. +config DM_REGULATOR_GPIO
- bool "Enable Driver Model for GPIO REGULATOR"
- depends on DM_REGULATOR
- ---help---
- This config enables implementation of driver-model regulator uclass
- features for gpio regulators. The driver implements get/set for
- voltage value.
- config REGULATOR_RK808 bool "Enable driver for RK808 regulators" depends on DM_REGULATOR && PMIC_RK808
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index 2093048..2d350cb 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o +obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_RK808) += rk808.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o diff --git a/drivers/power/regulator/gpio-regulator.c b/drivers/power/regulator/gpio-regulator.c new file mode 100644 index 0000000..9c8832e --- /dev/null +++ b/drivers/power/regulator/gpio-regulator.c @@ -0,0 +1,136 @@ +/*
- (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com>
- Keerthy j-keerthy@ti.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <fdtdec.h> +#include <errno.h> +#include <dm.h> +#include <i2c.h> +#include <asm/gpio.h> +#include <power/pmic.h> +#include <power/regulator.h>
+DECLARE_GLOBAL_DATA_PTR;
+struct gpio_regulator_platdata {
- struct gpio_desc gpio; /* GPIO for regulator voltage control */
- int gpio_low_uV;
- int gpio_high_uV;
+};
The low/high values can be provided by regulator's uclass driver in struct of type "dm_regulator_uclass_platdata", as for other regulators.
min_uV, max_uV represent the minimum and maximum voltages in dm_regulator_uclass_platdata. I would not use them here.
But as I can see in the Linux, this driver should provide a structure for the gpio states.
Yes so i am keeping the voltage values for 0 and 1 states in a driver specific struct.
+static int gpio_regulator_ofdata_to_platdata(struct udevice *dev) +{
- struct dm_regulator_uclass_platdata *uc_pdata;
- struct gpio_regulator_platdata *dev_pdata;
- struct gpio_desc *gpio;
- const void *blob = gd->fdt_blob;
- int node = dev->of_offset;
- int ret, count, i;
- u32 states_array[8];
- dev_pdata = dev_get_platdata(dev);
- uc_pdata = dev_get_uclass_platdata(dev);
- if (!uc_pdata)
return -ENXIO;
- /* Set type to gpio */
- uc_pdata->type = REGULATOR_TYPE_GPIO;
- /*
* Get gpio regulator gpio desc
* Assuming one GPIO per regulator.
* Can be extended later to multiple GPIOs
* per gpio-regulator. As of now no instance with multiple
* gpios is presnt
*/
- gpio = &dev_pdata->gpio;
- ret = gpio_request_by_name(dev, "gpios", 0, gpio, GPIOD_IS_OUT);
- if (ret)
debug("regulator gpio - not found! Error: %d", ret);
- count = fdtdec_get_int_array_count(blob, node, "states",
states_array, 8);
- if (!count)
return -EINVAL;
- for (i = 0; i < count; i += 2) {
The below condition is valid for most devices.
In Linux we can find dts for some ARMs in which I can find at least two boards, with inverted meaning of state/voltage, so "0", can be also valid for the high uV.
I think, this driver should keep possible states in platdata.
Okay. I get the point. So i will have both states and corresponding states voltages stored in gpio_regulator_platdata structure and set states corresponding to requested voltages.
if (states_array[i + 1] == 0)
dev_pdata->gpio_low_uV = states_array[i];
else
dev_pdata->gpio_high_uV = states_array[i];
- }
- return 0;
+}
+static int gpio_regulator_get_value(struct udevice *dev) +{
- struct dm_regulator_uclass_platdata *uc_pdata;
- struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev);
- int enable;
- if (!dev_pdata->gpio.dev)
return -ENOSYS;
- uc_pdata = dev_get_uclass_platdata(dev);
- if (uc_pdata->min_uV > uc_pdata->max_uV) {
debug("Invalid constraints for: %s\n", uc_pdata->name);
return -EINVAL;
- }
- enable = dm_gpio_get_value(&dev_pdata->gpio);
The returned value (enable) should be compared to the states kept in platdata.
Sure.
- if (enable)
return dev_pdata->gpio_high_uV;
- else
return dev_pdata->gpio_low_uV;
+}
+static int gpio_regulator_set_value(struct udevice *dev, int uV) +{
- struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev);
- int ret;
- bool enable;
- if (!dev_pdata->gpio.dev)
return -ENOSYS;
- if (uV == dev_pdata->gpio_high_uV)
enable = 1;
- else if (uV == dev_pdata->gpio_low_uV)
enable = 0;
- else
return -EINVAL;
And also here you should get the "enable" value from states kept in platdata.
Okay.
- ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
- if (ret) {
error("Can't set regulator : %s gpio to: %d\n", dev->name,
enable);
return ret;
- }
- return 0;
+}
+static const struct dm_regulator_ops gpio_regulator_ops = {
- .get_value = gpio_regulator_get_value,
- .set_value = gpio_regulator_set_value,
+};
+static const struct udevice_id gpio_regulator_ids[] = {
- { .compatible = "regulator-gpio" },
- { },
+};
+U_BOOT_DRIVER(gpio_regulator) = {
- .name = "gpio regulator",
- .id = UCLASS_REGULATOR,
- .ops = &gpio_regulator_ops,
- .of_match = gpio_regulator_ids,
- .ofdata_to_platdata = gpio_regulator_ofdata_to_platdata,
- .platdata_auto_alloc_size = sizeof(struct gpio_regulator_platdata),
+}; diff --git a/include/power/regulator.h b/include/power/regulator.h index 8ae6b14..5d327e6 100644 --- a/include/power/regulator.h +++ b/include/power/regulator.h @@ -108,6 +108,7 @@ enum regulator_type { REGULATOR_TYPE_BUCK, REGULATOR_TYPE_DVS, REGULATOR_TYPE_FIXED,
- REGULATOR_TYPE_GPIO, REGULATOR_TYPE_OTHER, };
Best regards,
Thanks for the review, - Keerthy

On 09/15/2016 12:34 PM, Keerthy wrote:
On Thursday 15 September 2016 03:04 PM, Przemyslaw Marczak wrote:
Hello Keerthy,
On 09/15/2016 10:25 AM, Keerthy wrote:
Add support for gpio regulators. As of now this driver caters to gpio regulators with one gpio. Supports setting voltage values to gpio regulators and retrieving the values.
Signed-off-by: Keerthy j-keerthy@ti.com
drivers/power/regulator/Kconfig | 8 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/gpio-regulator.c | 136 +++++++++++++++++++++++++++++++ include/power/regulator.h | 1 + 4 files changed, 146 insertions(+) create mode 100644 drivers/power/regulator/gpio-regulator.c
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 2510474..4776011 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -58,6 +58,14 @@ config DM_REGULATOR_FIXED features for fixed value regulators. The driver implements get/set api for enable and get only for voltage value. +config DM_REGULATOR_GPIO
- bool "Enable Driver Model for GPIO REGULATOR"
- depends on DM_REGULATOR
- ---help---
- This config enables implementation of driver-model regulator
uclass
- features for gpio regulators. The driver implements get/set for
- voltage value.
- config REGULATOR_RK808 bool "Enable driver for RK808 regulators" depends on DM_REGULATOR && PMIC_RK808
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index 2093048..2d350cb 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o +obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_RK808) += rk808.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o diff --git a/drivers/power/regulator/gpio-regulator.c b/drivers/power/regulator/gpio-regulator.c new file mode 100644 index 0000000..9c8832e --- /dev/null +++ b/drivers/power/regulator/gpio-regulator.c @@ -0,0 +1,136 @@ +/*
- (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com>
- Keerthy j-keerthy@ti.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <fdtdec.h> +#include <errno.h> +#include <dm.h> +#include <i2c.h> +#include <asm/gpio.h> +#include <power/pmic.h> +#include <power/regulator.h>
+DECLARE_GLOBAL_DATA_PTR;
+struct gpio_regulator_platdata {
- struct gpio_desc gpio; /* GPIO for regulator voltage control */
- int gpio_low_uV;
- int gpio_high_uV;
+};
The low/high values can be provided by regulator's uclass driver in struct of type "dm_regulator_uclass_platdata", as for other regulators.
min_uV, max_uV represent the minimum and maximum voltages in dm_regulator_uclass_platdata. I would not use them here.
Ah right, sorry I just get wrong the name of those variables above - as min/max uV, but your point was about the GPIO lo/hi state.
But as I can see in the Linux, this driver should provide a structure for the gpio states.
Yes so i am keeping the voltage values for 0 and 1 states in a driver specific struct.
+static int gpio_regulator_ofdata_to_platdata(struct udevice *dev) +{
- struct dm_regulator_uclass_platdata *uc_pdata;
- struct gpio_regulator_platdata *dev_pdata;
- struct gpio_desc *gpio;
- const void *blob = gd->fdt_blob;
- int node = dev->of_offset;
- int ret, count, i;
- u32 states_array[8];
- dev_pdata = dev_get_platdata(dev);
- uc_pdata = dev_get_uclass_platdata(dev);
- if (!uc_pdata)
return -ENXIO;
- /* Set type to gpio */
- uc_pdata->type = REGULATOR_TYPE_GPIO;
- /*
* Get gpio regulator gpio desc
* Assuming one GPIO per regulator.
* Can be extended later to multiple GPIOs
* per gpio-regulator. As of now no instance with multiple
* gpios is presnt
*/
- gpio = &dev_pdata->gpio;
- ret = gpio_request_by_name(dev, "gpios", 0, gpio, GPIOD_IS_OUT);
- if (ret)
debug("regulator gpio - not found! Error: %d", ret);
- count = fdtdec_get_int_array_count(blob, node, "states",
states_array, 8);
- if (!count)
return -EINVAL;
- for (i = 0; i < count; i += 2) {
The below condition is valid for most devices.
In Linux we can find dts for some ARMs in which I can find at least two boards, with inverted meaning of state/voltage, so "0", can be also valid for the high uV.
I think, this driver should keep possible states in platdata.
Okay. I get the point. So i will have both states and corresponding states voltages stored in gpio_regulator_platdata structure and set states corresponding to requested voltages.
Yes, so actually the only issue is low/high interpretation.
Maybe the easiest way is a simple array with the voltage, since there are only two states. But maybe the name of gpio_low/hi.. is quite misleading. What about an array gpio_state_uV[2] or something like that?
Then you can use GPIO state's true/false as array index for get method.
if (states_array[i + 1] == 0)
dev_pdata->gpio_low_uV = states_array[i];
else
dev_pdata->gpio_high_uV = states_array[i];
- }
- return 0;
+}
+static int gpio_regulator_get_value(struct udevice *dev) +{
- struct dm_regulator_uclass_platdata *uc_pdata;
- struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev);
- int enable;
- if (!dev_pdata->gpio.dev)
return -ENOSYS;
- uc_pdata = dev_get_uclass_platdata(dev);
- if (uc_pdata->min_uV > uc_pdata->max_uV) {
debug("Invalid constraints for: %s\n", uc_pdata->name);
return -EINVAL;
- }
- enable = dm_gpio_get_value(&dev_pdata->gpio);
The returned value (enable) should be compared to the states kept in platdata.
Sure.
- if (enable)
return dev_pdata->gpio_high_uV;
- else
return dev_pdata->gpio_low_uV;
+}
+static int gpio_regulator_set_value(struct udevice *dev, int uV) +{
- struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev);
- int ret;
- bool enable;
- if (!dev_pdata->gpio.dev)
return -ENOSYS;
- if (uV == dev_pdata->gpio_high_uV)
enable = 1;
- else if (uV == dev_pdata->gpio_low_uV)
enable = 0;
- else
return -EINVAL;
And also here you should get the "enable" value from states kept in platdata.
Okay.
- ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
- if (ret) {
error("Can't set regulator : %s gpio to: %d\n", dev->name,
enable);
return ret;
- }
- return 0;
+}
+static const struct dm_regulator_ops gpio_regulator_ops = {
- .get_value = gpio_regulator_get_value,
- .set_value = gpio_regulator_set_value,
+};
+static const struct udevice_id gpio_regulator_ids[] = {
- { .compatible = "regulator-gpio" },
- { },
+};
+U_BOOT_DRIVER(gpio_regulator) = {
- .name = "gpio regulator",
- .id = UCLASS_REGULATOR,
- .ops = &gpio_regulator_ops,
- .of_match = gpio_regulator_ids,
- .ofdata_to_platdata = gpio_regulator_ofdata_to_platdata,
- .platdata_auto_alloc_size = sizeof(struct
gpio_regulator_platdata), +}; diff --git a/include/power/regulator.h b/include/power/regulator.h index 8ae6b14..5d327e6 100644 --- a/include/power/regulator.h +++ b/include/power/regulator.h @@ -108,6 +108,7 @@ enum regulator_type { REGULATOR_TYPE_BUCK, REGULATOR_TYPE_DVS, REGULATOR_TYPE_FIXED,
- REGULATOR_TYPE_GPIO, REGULATOR_TYPE_OTHER, };
Best regards,
Thanks for the review,
- Keerthy
You are welcome

On Thursday 15 September 2016 05:12 PM, Przemyslaw Marczak wrote:
On 09/15/2016 12:34 PM, Keerthy wrote:
On Thursday 15 September 2016 03:04 PM, Przemyslaw Marczak wrote:
Hello Keerthy,
On 09/15/2016 10:25 AM, Keerthy wrote:
Add support for gpio regulators. As of now this driver caters to gpio regulators with one gpio. Supports setting voltage values to gpio regulators and retrieving the values.
Signed-off-by: Keerthy j-keerthy@ti.com
drivers/power/regulator/Kconfig | 8 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/gpio-regulator.c | 136 +++++++++++++++++++++++++++++++ include/power/regulator.h | 1 + 4 files changed, 146 insertions(+) create mode 100644 drivers/power/regulator/gpio-regulator.c
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 2510474..4776011 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -58,6 +58,14 @@ config DM_REGULATOR_FIXED features for fixed value regulators. The driver implements get/set api for enable and get only for voltage value. +config DM_REGULATOR_GPIO
- bool "Enable Driver Model for GPIO REGULATOR"
- depends on DM_REGULATOR
- ---help---
- This config enables implementation of driver-model regulator
uclass
- features for gpio regulators. The driver implements get/set for
- voltage value.
- config REGULATOR_RK808 bool "Enable driver for RK808 regulators" depends on DM_REGULATOR && PMIC_RK808
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index 2093048..2d350cb 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o +obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_RK808) += rk808.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o diff --git a/drivers/power/regulator/gpio-regulator.c b/drivers/power/regulator/gpio-regulator.c new file mode 100644 index 0000000..9c8832e --- /dev/null +++ b/drivers/power/regulator/gpio-regulator.c @@ -0,0 +1,136 @@ +/*
- (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com>
- Keerthy j-keerthy@ti.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <fdtdec.h> +#include <errno.h> +#include <dm.h> +#include <i2c.h> +#include <asm/gpio.h> +#include <power/pmic.h> +#include <power/regulator.h>
+DECLARE_GLOBAL_DATA_PTR;
+struct gpio_regulator_platdata {
- struct gpio_desc gpio; /* GPIO for regulator voltage control */
- int gpio_low_uV;
- int gpio_high_uV;
+};
The low/high values can be provided by regulator's uclass driver in struct of type "dm_regulator_uclass_platdata", as for other regulators.
min_uV, max_uV represent the minimum and maximum voltages in dm_regulator_uclass_platdata. I would not use them here.
Ah right, sorry I just get wrong the name of those variables above - as min/max uV, but your point was about the GPIO lo/hi state.
But as I can see in the Linux, this driver should provide a structure for the gpio states.
Yes so i am keeping the voltage values for 0 and 1 states in a driver specific struct.
+static int gpio_regulator_ofdata_to_platdata(struct udevice *dev) +{
- struct dm_regulator_uclass_platdata *uc_pdata;
- struct gpio_regulator_platdata *dev_pdata;
- struct gpio_desc *gpio;
- const void *blob = gd->fdt_blob;
- int node = dev->of_offset;
- int ret, count, i;
- u32 states_array[8];
- dev_pdata = dev_get_platdata(dev);
- uc_pdata = dev_get_uclass_platdata(dev);
- if (!uc_pdata)
return -ENXIO;
- /* Set type to gpio */
- uc_pdata->type = REGULATOR_TYPE_GPIO;
- /*
* Get gpio regulator gpio desc
* Assuming one GPIO per regulator.
* Can be extended later to multiple GPIOs
* per gpio-regulator. As of now no instance with multiple
* gpios is presnt
*/
- gpio = &dev_pdata->gpio;
- ret = gpio_request_by_name(dev, "gpios", 0, gpio, GPIOD_IS_OUT);
- if (ret)
debug("regulator gpio - not found! Error: %d", ret);
- count = fdtdec_get_int_array_count(blob, node, "states",
states_array, 8);
- if (!count)
return -EINVAL;
- for (i = 0; i < count; i += 2) {
The below condition is valid for most devices.
In Linux we can find dts for some ARMs in which I can find at least two boards, with inverted meaning of state/voltage, so "0", can be also valid for the high uV.
I think, this driver should keep possible states in platdata.
Okay. I get the point. So i will have both states and corresponding states voltages stored in gpio_regulator_platdata structure and set states corresponding to requested voltages.
Yes, so actually the only issue is low/high interpretation.
Maybe the easiest way is a simple array with the voltage, since there are only two states. But maybe the name of gpio_low/hi.. is quite misleading. What about an array gpio_state_uV[2] or something like that?
Then you can use GPIO state's true/false as array index for get method.
Yes. I sent a V2 :-) with your comments fixed.
if (states_array[i + 1] == 0)
dev_pdata->gpio_low_uV = states_array[i];
else
dev_pdata->gpio_high_uV = states_array[i];
- }
- return 0;
+}
+static int gpio_regulator_get_value(struct udevice *dev) +{
- struct dm_regulator_uclass_platdata *uc_pdata;
- struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev);
- int enable;
- if (!dev_pdata->gpio.dev)
return -ENOSYS;
- uc_pdata = dev_get_uclass_platdata(dev);
- if (uc_pdata->min_uV > uc_pdata->max_uV) {
debug("Invalid constraints for: %s\n", uc_pdata->name);
return -EINVAL;
- }
- enable = dm_gpio_get_value(&dev_pdata->gpio);
The returned value (enable) should be compared to the states kept in platdata.
Sure.
- if (enable)
return dev_pdata->gpio_high_uV;
- else
return dev_pdata->gpio_low_uV;
+}
+static int gpio_regulator_set_value(struct udevice *dev, int uV) +{
- struct gpio_regulator_platdata *dev_pdata = dev_get_platdata(dev);
- int ret;
- bool enable;
- if (!dev_pdata->gpio.dev)
return -ENOSYS;
- if (uV == dev_pdata->gpio_high_uV)
enable = 1;
- else if (uV == dev_pdata->gpio_low_uV)
enable = 0;
- else
return -EINVAL;
And also here you should get the "enable" value from states kept in platdata.
Okay.
- ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
- if (ret) {
error("Can't set regulator : %s gpio to: %d\n", dev->name,
enable);
return ret;
- }
- return 0;
+}
+static const struct dm_regulator_ops gpio_regulator_ops = {
- .get_value = gpio_regulator_get_value,
- .set_value = gpio_regulator_set_value,
+};
+static const struct udevice_id gpio_regulator_ids[] = {
- { .compatible = "regulator-gpio" },
- { },
+};
+U_BOOT_DRIVER(gpio_regulator) = {
- .name = "gpio regulator",
- .id = UCLASS_REGULATOR,
- .ops = &gpio_regulator_ops,
- .of_match = gpio_regulator_ids,
- .ofdata_to_platdata = gpio_regulator_ofdata_to_platdata,
- .platdata_auto_alloc_size = sizeof(struct
gpio_regulator_platdata), +}; diff --git a/include/power/regulator.h b/include/power/regulator.h index 8ae6b14..5d327e6 100644 --- a/include/power/regulator.h +++ b/include/power/regulator.h @@ -108,6 +108,7 @@ enum regulator_type { REGULATOR_TYPE_BUCK, REGULATOR_TYPE_DVS, REGULATOR_TYPE_FIXED,
- REGULATOR_TYPE_GPIO, REGULATOR_TYPE_OTHER, };
Best regards,
Thanks for the review,
- Keerthy
You are welcome
participants (3)
-
Keerthy
-
Keerthy
-
Przemyslaw Marczak