diff options
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/regulator/Kconfig | 8 | ||||
-rw-r--r-- | drivers/power/regulator/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/regulator/gpio-regulator.c | 137 |
3 files changed, 146 insertions, 0 deletions
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index c7e88c0..255eccf 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -68,6 +68,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 ab461ec..e9ae22e 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o obj-$(CONFIG_REGULATOR_PWM) += pwm_regulator.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..0a60a9c --- /dev/null +++ b/drivers/power/regulator/gpio-regulator.c @@ -0,0 +1,137 @@ +/* + * (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> + +#define GPIO_REGULATOR_MAX_STATES 2 + +DECLARE_GLOBAL_DATA_PTR; + +struct gpio_regulator_platdata { + struct gpio_desc gpio; /* GPIO for regulator voltage control */ + int states[GPIO_REGULATOR_MAX_STATES]; + int voltages[GPIO_REGULATOR_MAX_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, j; + 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, j = 0; i < count; i += 2) { + dev_pdata->voltages[j] = states_array[i]; + dev_pdata->states[j] = states_array[i + 1]; + j++; + } + + 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 == dev_pdata->states[0]) + return dev_pdata->voltages[0]; + else + return dev_pdata->voltages[1]; +} + +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->voltages[0]) + enable = dev_pdata->states[0]; + else if (uV == dev_pdata->voltages[1]) + enable = dev_pdata->states[1]; + 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), +}; |