[U-Boot] [PATCH] power: regulator: Add support for gpio regulators
Keerthy
a0393675 at ti.com
Thu Sep 15 13:54:50 CEST 2016
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 at 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 at 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
>
More information about the U-Boot
mailing list