summaryrefslogtreecommitdiff
path: root/drivers/power/regulator
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/regulator')
-rw-r--r--drivers/power/regulator/Kconfig10
-rw-r--r--drivers/power/regulator/Makefile1
-rw-r--r--drivers/power/regulator/fixed.c17
-rw-r--r--drivers/power/regulator/lp87565_regulator.c199
-rw-r--r--drivers/power/regulator/palmas_regulator.c6
-rw-r--r--drivers/power/regulator/pwm_regulator.c8
-rw-r--r--drivers/power/regulator/regulator-uclass.c47
-rw-r--r--drivers/power/regulator/rk8xx.c4
8 files changed, 251 insertions, 41 deletions
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index ef057e0e2f..f2134874c2 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -149,3 +149,13 @@ config DM_REGULATOR_LP873X
This enables implementation of driver-model regulator uclass
features for REGULATOR LP873X and the family of LP873X PMICs.
The driver implements get/set api for: value and enable.
+
+config DM_REGULATOR_LP87565
+ bool "Enable driver for LP87565 PMIC regulators"
+ depends on PMIC_LP87565
+ ---help---
+ This enables implementation of driver-model regulator uclass
+ features for REGULATOR LP87565 and the family of LP87565 PMICs.
+ LP87565 series of PMICs have 4 single phase BUCKs that can also
+ be configured in multi phase modes. The driver implements
+ get/set api for value and enable.
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index 3e01021b76..ce14d08fd4 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
obj-$(CONFIG_REGULATOR_TPS65090) += tps65090_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_PALMAS) += palmas_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP873X) += lp873x_regulator.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP87565) += lp87565_regulator.o
diff --git a/drivers/power/regulator/fixed.c b/drivers/power/regulator/fixed.c
index cd5213766d..656371b235 100644
--- a/drivers/power/regulator/fixed.c
+++ b/drivers/power/regulator/fixed.c
@@ -7,7 +7,6 @@
*/
#include <common.h>
-#include <fdtdec.h>
#include <errno.h>
#include <dm.h>
#include <i2c.h>
@@ -27,8 +26,7 @@ static int fixed_regulator_ofdata_to_platdata(struct udevice *dev)
struct dm_regulator_uclass_platdata *uc_pdata;
struct fixed_regulator_platdata *dev_pdata;
struct gpio_desc *gpio;
- const void *blob = gd->fdt_blob;
- int node = dev_of_offset(dev), flags = GPIOD_IS_OUT;
+ int flags = GPIOD_IS_OUT;
int ret;
dev_pdata = dev_get_platdata(dev);
@@ -39,7 +37,7 @@ static int fixed_regulator_ofdata_to_platdata(struct udevice *dev)
/* Set type to fixed */
uc_pdata->type = REGULATOR_TYPE_FIXED;
- if (fdtdec_get_bool(blob, node, "enable-active-high"))
+ if (dev_read_bool(dev, "enable-active-high"))
flags |= GPIOD_IS_OUT_ACTIVE;
/* Get fixed regulator optional enable GPIO desc */
@@ -53,9 +51,8 @@ static int fixed_regulator_ofdata_to_platdata(struct udevice *dev)
}
/* Get optional ramp up delay */
- dev_pdata->startup_delay_us = fdtdec_get_uint(gd->fdt_blob,
- dev_of_offset(dev),
- "startup-delay-us", 0);
+ dev_pdata->startup_delay_us = dev_read_u32_default(dev,
+ "startup-delay-us", 0);
return 0;
}
@@ -108,8 +105,11 @@ static int fixed_regulator_set_enable(struct udevice *dev, bool enable)
struct fixed_regulator_platdata *dev_pdata = dev_get_platdata(dev);
int ret;
+ debug("%s: dev='%s', enable=%d, delay=%d, has_gpio=%d\n", __func__,
+ dev->name, enable, dev_pdata->startup_delay_us,
+ dm_gpio_is_valid(&dev_pdata->gpio));
/* Enable GPIO is optional */
- if (!dev_pdata->gpio.dev) {
+ if (!dm_gpio_is_valid(&dev_pdata->gpio)) {
if (!enable)
return -ENOSYS;
return 0;
@@ -124,6 +124,7 @@ static int fixed_regulator_set_enable(struct udevice *dev, bool enable)
if (enable && dev_pdata->startup_delay_us)
udelay(dev_pdata->startup_delay_us);
+ debug("%s: done\n", __func__);
return 0;
}
diff --git a/drivers/power/regulator/lp87565_regulator.c b/drivers/power/regulator/lp87565_regulator.c
new file mode 100644
index 0000000000..2a0b8ca642
--- /dev/null
+++ b/drivers/power/regulator/lp87565_regulator.c
@@ -0,0 +1,199 @@
+/*
+ * (C) Copyright 2017
+ * 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 <power/pmic.h>
+#include <power/regulator.h>
+#include <power/lp87565.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const char lp87565_buck_ctrl1[LP87565_BUCK_NUM] = {0x2, 0x4, 0x6, 0x8, 0x2, 0x6};
+static const char lp87565_buck_vout[LP87565_BUCK_NUM] = {0xA, 0xC, 0xE, 0x10, 0xA, 0xE };
+
+static int lp87565_buck_enable(struct udevice *dev, int op, bool *enable)
+{
+ int ret;
+ unsigned int adr;
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+ adr = uc_pdata->ctrl_reg;
+
+ ret = pmic_reg_read(dev->parent, adr);
+ if (ret < 0)
+ return ret;
+
+ if (op == PMIC_OP_GET) {
+ ret &= LP87565_BUCK_MODE_MASK;
+
+ if (ret)
+ *enable = true;
+ else
+ *enable = false;
+
+ return 0;
+ } else if (op == PMIC_OP_SET) {
+ if (*enable)
+ ret |= LP87565_BUCK_MODE_MASK;
+ else
+ ret &= ~LP87565_BUCK_MODE_MASK;
+ ret = pmic_reg_write(dev->parent, adr, ret);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int lp87565_buck_volt2val(int uV)
+{
+ if (uV > LP87565_BUCK_VOLT_MAX)
+ return -EINVAL;
+ else if (uV > 1400000)
+ return (uV - 1420000) / 20000 + 0x9E;
+ else if (uV > 730000)
+ return (uV - 735000) / 5000 + 0x18;
+ else if (uV >= 500000)
+ return (uV - 500000) / 10000;
+ else
+ return -EINVAL;
+}
+
+static int lp87565_buck_val2volt(int val)
+{
+ if (val > LP87565_BUCK_VOLT_MAX_HEX)
+ return -EINVAL;
+ else if (val > 0x9D)
+ return 1400000 + (val - 0x9D) * 20000;
+ else if (val > 0x17)
+ return 730000 + (val - 0x17) * 5000;
+ else if (val >= 0x0)
+ return 500000 + val * 10000;
+ else
+ return -EINVAL;
+}
+
+static int lp87565_buck_val(struct udevice *dev, int op, int *uV)
+{
+ unsigned int hex, adr;
+ int ret;
+ struct dm_regulator_uclass_platdata *uc_pdata;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+
+ if (op == PMIC_OP_GET)
+ *uV = 0;
+
+ adr = uc_pdata->volt_reg;
+
+ ret = pmic_reg_read(dev->parent, adr);
+ if (ret < 0)
+ return ret;
+
+ if (op == PMIC_OP_GET) {
+ ret &= LP87565_BUCK_VOLT_MASK;
+ ret = lp87565_buck_val2volt(ret);
+ if (ret < 0)
+ return ret;
+ *uV = ret;
+
+ return 0;
+ }
+
+ hex = lp87565_buck_volt2val(*uV);
+ if (hex < 0)
+ return hex;
+
+ ret &= 0x0;
+ ret = hex;
+
+ ret = pmic_reg_write(dev->parent, adr, ret);
+
+ return ret;
+}
+
+static int lp87565_buck_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_platdata *uc_pdata;
+ int idx;
+
+ uc_pdata = dev_get_uclass_platdata(dev);
+ uc_pdata->type = REGULATOR_TYPE_BUCK;
+
+ idx = dev->driver_data;
+ if (idx == 0 || idx == 1 || idx == 2 || idx == 3) {
+ debug("Single phase regulator\n");
+ } else if (idx == 23) {
+ idx = 5;
+ } else if (idx == 10) {
+ idx = 4;
+ } else {
+ printf("Wrong ID for regulator\n");
+ return -EINVAL;
+ }
+
+ uc_pdata->ctrl_reg = lp87565_buck_ctrl1[idx];
+ uc_pdata->volt_reg = lp87565_buck_vout[idx];
+
+ return 0;
+}
+
+static int buck_get_value(struct udevice *dev)
+{
+ int uV;
+ int ret;
+
+ ret = lp87565_buck_val(dev, PMIC_OP_GET, &uV);
+ if (ret)
+ return ret;
+
+ return uV;
+}
+
+static int buck_set_value(struct udevice *dev, int uV)
+{
+ return lp87565_buck_val(dev, PMIC_OP_SET, &uV);
+}
+
+static bool buck_get_enable(struct udevice *dev)
+{
+ bool enable = false;
+ int ret;
+
+
+ ret = lp87565_buck_enable(dev, PMIC_OP_GET, &enable);
+ if (ret)
+ return ret;
+
+ return enable;
+}
+
+static int buck_set_enable(struct udevice *dev, bool enable)
+{
+ return lp87565_buck_enable(dev, PMIC_OP_SET, &enable);
+}
+
+static const struct dm_regulator_ops lp87565_buck_ops = {
+ .get_value = buck_get_value,
+ .set_value = buck_set_value,
+ .get_enable = buck_get_enable,
+ .set_enable = buck_set_enable,
+};
+
+U_BOOT_DRIVER(lp87565_buck) = {
+ .name = LP87565_BUCK_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &lp87565_buck_ops,
+ .probe = lp87565_buck_probe,
+};
diff --git a/drivers/power/regulator/palmas_regulator.c b/drivers/power/regulator/palmas_regulator.c
index 399f7a5f55..841c03a504 100644
--- a/drivers/power/regulator/palmas_regulator.c
+++ b/drivers/power/regulator/palmas_regulator.c
@@ -377,7 +377,11 @@ static int palmas_smps_probe(struct udevice *dev)
uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
uc_pdata->volt_reg = palmas_smps_volt[type][idx];
break;
-
+ case 12:
+ idx = 0;
+ uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
+ uc_pdata->volt_reg = palmas_smps_volt[type][idx];
+ break;
default:
printf("Wrong ID for regulator\n");
}
diff --git a/drivers/power/regulator/pwm_regulator.c b/drivers/power/regulator/pwm_regulator.c
index a6c9fccd68..00a7cca7f7 100644
--- a/drivers/power/regulator/pwm_regulator.c
+++ b/drivers/power/regulator/pwm_regulator.c
@@ -32,13 +32,13 @@ struct pwm_regulator_info {
bool polarity;
struct udevice *pwm;
/* initialize voltage of regulator */
- unsigned int init_voltage;
+ int init_voltage;
/* the maximum voltage of regulator */
- unsigned int max_voltage;
+ int max_voltage;
/* the minimum voltage of regulator */
- unsigned int min_voltage;
+ int min_voltage;
/* the current voltage of regulator */
- unsigned int volt_uV;
+ int volt_uV;
};
static int pwm_regulator_enable(struct udevice *dev, bool enable)
diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
index 2e0b5ed307..0a1d1b36c0 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -4,8 +4,8 @@
*
* SPDX-License-Identifier: GPL-2.0+
*/
+
#include <common.h>
-#include <fdtdec.h>
#include <errno.h>
#include <dm.h>
#include <dm/uclass-internal.h>
@@ -146,8 +146,10 @@ int regulator_get_by_platname(const char *plat_name, struct udevice **devp)
for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
ret = uclass_find_next_device(&dev)) {
- if (ret)
+ if (ret) {
+ debug("regulator %s, ret=%d\n", dev->name, ret);
continue;
+ }
uc_pdata = dev_get_uclass_platdata(dev);
if (!uc_pdata || strcmp(plat_name, uc_pdata->name))
@@ -156,7 +158,7 @@ int regulator_get_by_platname(const char *plat_name, struct udevice **devp)
return uclass_get_device_tail(dev, 0, devp);
}
- debug("%s: can't find: %s\n", __func__, plat_name);
+ debug("%s: can't find: %s, ret=%d\n", __func__, plat_name, ret);
return -ENODEV;
}
@@ -219,7 +221,7 @@ int regulator_autoset_by_name(const char *platname, struct udevice **devp)
if (devp)
*devp = dev;
if (ret) {
- debug("Can get the regulator: %s!", platname);
+ debug("Can get the regulator: %s (err=%d)\n", platname, ret);
return ret;
}
@@ -278,20 +280,16 @@ static bool regulator_name_is_unique(struct udevice *check_dev,
static int regulator_post_bind(struct udevice *dev)
{
struct dm_regulator_uclass_platdata *uc_pdata;
- int offset = dev_of_offset(dev);
- const void *blob = gd->fdt_blob;
const char *property = "regulator-name";
uc_pdata = dev_get_uclass_platdata(dev);
- if (!uc_pdata)
- return -ENXIO;
/* Regulator's mandatory constraint */
- uc_pdata->name = fdt_getprop(blob, offset, property, NULL);
+ uc_pdata->name = dev_read_string(dev, property);
if (!uc_pdata->name) {
- debug("%s: dev: %s has no property 'regulator-name'\n",
- __func__, dev->name);
- uc_pdata->name = fdt_get_name(blob, offset, NULL);
+ debug("%s: dev '%s' has no property '%s'\n",
+ __func__, dev->name, property);
+ uc_pdata->name = dev_read_name(dev);
if (!uc_pdata->name)
return -EINVAL;
}
@@ -299,7 +297,7 @@ static int regulator_post_bind(struct udevice *dev)
if (regulator_name_is_unique(dev, uc_pdata->name))
return 0;
- debug("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
+ debug("'%s' of dev: '%s', has nonunique value: '%s\n",
property, dev->name, uc_pdata->name);
return -EINVAL;
@@ -308,25 +306,22 @@ static int regulator_post_bind(struct udevice *dev)
static int regulator_pre_probe(struct udevice *dev)
{
struct dm_regulator_uclass_platdata *uc_pdata;
- int offset = dev_of_offset(dev);
uc_pdata = dev_get_uclass_platdata(dev);
if (!uc_pdata)
return -ENXIO;
/* Regulator's optional constraints */
- uc_pdata->min_uV = fdtdec_get_int(gd->fdt_blob, offset,
- "regulator-min-microvolt", -ENODATA);
- uc_pdata->max_uV = fdtdec_get_int(gd->fdt_blob, offset,
- "regulator-max-microvolt", -ENODATA);
- uc_pdata->min_uA = fdtdec_get_int(gd->fdt_blob, offset,
- "regulator-min-microamp", -ENODATA);
- uc_pdata->max_uA = fdtdec_get_int(gd->fdt_blob, offset,
- "regulator-max-microamp", -ENODATA);
- uc_pdata->always_on = fdtdec_get_bool(gd->fdt_blob, offset,
- "regulator-always-on");
- uc_pdata->boot_on = fdtdec_get_bool(gd->fdt_blob, offset,
- "regulator-boot-on");
+ uc_pdata->min_uV = dev_read_u32_default(dev, "regulator-min-microvolt",
+ -ENODATA);
+ uc_pdata->max_uV = dev_read_u32_default(dev, "regulator-max-microvolt",
+ -ENODATA);
+ uc_pdata->min_uA = dev_read_u32_default(dev, "regulator-min-microamp",
+ -ENODATA);
+ uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
+ -ENODATA);
+ uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
+ uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
/* Those values are optional (-ENODATA if unset) */
if ((uc_pdata->min_uV != -ENODATA) &&
diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c
index e655c2d91f..c1ece96b66 100644
--- a/drivers/power/regulator/rk8xx.c
+++ b/drivers/power/regulator/rk8xx.c
@@ -92,9 +92,9 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic,
struct rk8xx_priv *priv = dev_get_priv(pmic);
switch (priv->variant) {
case RK818_ID:
- return &rk818_ldo[num - 1];
+ return &rk818_ldo[num];
default:
- return &rk808_ldo[num - 1];
+ return &rk808_ldo[num];
}
}