Hi JJ, On 08/18/2017 05:41 PM, Jean-Jacques Hiblot wrote: > Hi Jaehoon, > > > On 18/08/2017 08:52, Jaehoon Chung wrote: >> Dear JJ, >> >> On 08/07/2017 06:43 PM, Jean-Jacques Hiblot wrote: >>> In the TI SOCs a PBIAS cell exists to provide a bias voltage to the MMC1 >>> IO cells. Without this bias voltage these I/O cells can not function >>> properly. The PBIAS cell is controlled by software. >>> >>> Signed-off-by: Jean-Jacques Hiblot <jjhib...@ti.com> >>> Reviewed-by: Tom Rini <tr...@konsulko.com> >>> Reviewed-by: Simon Glass <s...@chromium.org> >> There is an error.. >> >> arm: + am57xx_evm >> +drivers/power/regulator/built-in.o: In function `pbias_regulator_probe': >> +drivers/power/regulator/pbias_regulator.c:196: undefined reference to >> `dev_read_string_index' >> >> i didn't find the dev_read_string_index()..Is there any patch? > This function has been defined in patch : "[PATCH v2 1/3] dm: core: Add > functions to get strings and the string count from a stringlist" > I thought it was already applied to u-boot-mmc.
Will check. Thanks for sharing it. Best Regards, Jaehoon Chung > > Thanks, > Jean-Jacques > >> Best Regards, >> Jaehoon Chung >> >>> --- >>> >>> Hi Jaehoon, >>> >>> Here is the patch for the PBIAS regulator. I modified the KConfig to select >>> the REGMAP and SYSCON features as you suggested. >>> Thanks. >>> JJ >>> >>> changes since v2: >>> - automatically select REGMAP and SYSCON if PBIAS is selected. >>> >>> changes since v1: >>> - automatically select the PBIAS driver if DM_REGULATOR, DM_MMC and >>> MMC_OMAP_HS are set >>> - use the dev_read_*() API to access the DT >>> >>> >>> drivers/mmc/Kconfig | 1 + >>> drivers/power/regulator/Kconfig | 13 ++ >>> drivers/power/regulator/Makefile | 1 + >>> drivers/power/regulator/pbias_regulator.c | 302 >>> ++++++++++++++++++++++++++++++ >>> 4 files changed, 317 insertions(+) >>> create mode 100644 drivers/power/regulator/pbias_regulator.c >>> >>> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig >>> index 588e118..63e1122 100644 >>> --- a/drivers/mmc/Kconfig >>> +++ b/drivers/mmc/Kconfig >>> @@ -158,6 +158,7 @@ config MMC_PCI >>> config MMC_OMAP_HS >>> bool "TI OMAP High Speed Multimedia Card Interface support" >>> select DM_MMC_OPS if DM_MMC >>> + select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR >>> help >>> This selects the TI OMAP High Speed Multimedia card Interface. >>> If you have an omap2plus board with a Multimedia Card slot, >>> diff --git a/drivers/power/regulator/Kconfig >>> b/drivers/power/regulator/Kconfig >>> index f213487..cb5ea08 100644 >>> --- a/drivers/power/regulator/Kconfig >>> +++ b/drivers/power/regulator/Kconfig >>> @@ -142,6 +142,19 @@ config DM_REGULATOR_PALMAS >>> features for REGULATOR PALMAS and the family of PALMAS PMICs. >>> The driver implements get/set api for: value and enable. >>> +config DM_REGULATOR_PBIAS >>> + bool "Enable driver for PBIAS regulator" >>> + depends on DM_REGULATOR >>> + select REGMAP >>> + select SYSCON >>> + ---help--- >>> + This enables implementation of driver-model regulator uclass >>> + features for pseudo-regulator PBIAS found in the OMAP SOCs. >>> + This pseudo-regulator is used to provide a BIAS voltage to MMC1 >>> + signal pads and must be configured properly during a voltage switch. >>> + Voltage switching is required by some operating modes of SDcards and >>> + eMMC. >>> + >>> config DM_REGULATOR_LP873X >>> bool "Enable driver for LP873X PMIC regulators" >>> depends on PMIC_LP873X >>> diff --git a/drivers/power/regulator/Makefile >>> b/drivers/power/regulator/Makefile >>> index ce14d08..75d611a 100644 >>> --- a/drivers/power/regulator/Makefile >>> +++ b/drivers/power/regulator/Makefile >>> @@ -17,5 +17,6 @@ obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o >>> 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_PBIAS) += pbias_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/pbias_regulator.c >>> b/drivers/power/regulator/pbias_regulator.c >>> new file mode 100644 >>> index 0000000..303eca9 >>> --- /dev/null >>> +++ b/drivers/power/regulator/pbias_regulator.c >>> @@ -0,0 +1,302 @@ >>> +/* >>> + * (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com> >>> + * Jean-Jacques Hiblot <jjhib...@ti.com> >>> + * >>> + * SPDX-License-Identifier: GPL-2.0+ >>> + */ >>> + >>> +#include <common.h> >>> +#include <errno.h> >>> +#include <dm.h> >>> +#include <power/pmic.h> >>> +#include <power/regulator.h> >>> +#include <regmap.h> >>> +#include <syscon.h> >>> +#include <linux/bitops.h> >>> +#include <linux/ioport.h> >>> +#include <dm/read.h> >>> + >>> +DECLARE_GLOBAL_DATA_PTR; >>> + >>> +struct pbias_reg_info { >>> + u32 enable; >>> + u32 enable_mask; >>> + u32 disable_val; >>> + u32 vmode; >>> + unsigned int enable_time; >>> + char *name; >>> +}; >>> + >>> +struct pbias_priv { >>> + struct regmap *regmap; >>> + int offset; >>> +}; >>> + >>> +static const struct pmic_child_info pmic_children_info[] = { >>> + { .prefix = "pbias", .driver = "pbias_regulator"}, >>> + { }, >>> +}; >>> + >>> +static int pbias_write(struct udevice *dev, uint reg, const uint8_t *buff, >>> + int len) >>> +{ >>> + struct pbias_priv *priv = dev_get_priv(dev); >>> + uint32_t val = *(uint32_t *)buff; >>> + >>> + if (len != 4) >>> + return -EINVAL; >>> + >>> + return regmap_write(priv->regmap, priv->offset, val); >>> +} >>> + >>> +static int pbias_read(struct udevice *dev, uint reg, uint8_t *buff, int >>> len) >>> +{ >>> + struct pbias_priv *priv = dev_get_priv(dev); >>> + >>> + if (len != 4) >>> + return -EINVAL; >>> + >>> + return regmap_read(priv->regmap, priv->offset, (uint32_t *)buff); >>> +} >>> + >>> +static int pbias_ofdata_to_platdata(struct udevice *dev) >>> +{ >>> + struct pbias_priv *priv = dev_get_priv(dev); >>> + struct udevice *syscon; >>> + struct regmap *regmap; >>> + struct resource res; >>> + int err; >>> + >>> + err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, >>> + "syscon", &syscon); >>> + if (err) { >>> + error("%s: unable to find syscon device (%d)\n", __func__, >>> + err); >>> + return err; >>> + } >>> + >>> + regmap = syscon_get_regmap(syscon); >>> + if (IS_ERR(regmap)) { >>> + error("%s: unable to find regmap (%ld)\n", __func__, >>> + PTR_ERR(regmap)); >>> + return PTR_ERR(regmap); >>> + } >>> + priv->regmap = regmap; >>> + >>> + err = dev_read_resource(dev, 0, &res); >>> + if (err) { >>> + error("%s: unable to find offset (%d)\n", __func__, err); >>> + return err; >>> + } >>> + priv->offset = res.start; >>> + >>> + return 0; >>> +} >>> + >>> +static int pbias_bind(struct udevice *dev) >>> +{ >>> + int children; >>> + >>> + children = pmic_bind_children(dev, dev->node, pmic_children_info); >>> + if (!children) >>> + debug("%s: %s - no child found\n", __func__, dev->name); >>> + >>> + return 0; >>> +} >>> + >>> +static struct dm_pmic_ops pbias_ops = { >>> + .read = pbias_read, >>> + .write = pbias_write, >>> +}; >>> + >>> +static const struct udevice_id pbias_ids[] = { >>> + { .compatible = "ti,pbias-dra7" }, >>> + { } >>> +}; >>> + >>> +U_BOOT_DRIVER(pbias_pmic) = { >>> + .name = "pbias_pmic", >>> + .id = UCLASS_PMIC, >>> + .of_match = pbias_ids, >>> + .bind = pbias_bind, >>> + .ops = &pbias_ops, >>> + .ofdata_to_platdata = pbias_ofdata_to_platdata, >>> + .priv_auto_alloc_size = sizeof(struct pbias_priv), >>> +}; >>> + >>> +static const struct pbias_reg_info pbias_mmc_omap2430 = { >>> + .enable = BIT(1), >>> + .enable_mask = BIT(1), >>> + .vmode = BIT(0), >>> + .disable_val = 0, >>> + .enable_time = 100, >>> + .name = "pbias_mmc_omap2430" >>> +}; >>> + >>> +static const struct pbias_reg_info pbias_sim_omap3 = { >>> + .enable = BIT(9), >>> + .enable_mask = BIT(9), >>> + .vmode = BIT(8), >>> + .enable_time = 100, >>> + .name = "pbias_sim_omap3" >>> +}; >>> + >>> +static const struct pbias_reg_info pbias_mmc_omap4 = { >>> + .enable = BIT(26) | BIT(22), >>> + .enable_mask = BIT(26) | BIT(25) | BIT(22), >>> + .disable_val = BIT(25), >>> + .vmode = BIT(21), >>> + .enable_time = 100, >>> + .name = "pbias_mmc_omap4" >>> +}; >>> + >>> +static const struct pbias_reg_info pbias_mmc_omap5 = { >>> + .enable = BIT(27) | BIT(26), >>> + .enable_mask = BIT(27) | BIT(25) | BIT(26), >>> + .disable_val = BIT(25), >>> + .vmode = BIT(21), >>> + .enable_time = 100, >>> + .name = "pbias_mmc_omap5" >>> +}; >>> + >>> +static const struct pbias_reg_info *pbias_reg_infos[] = { >>> + &pbias_mmc_omap5, >>> + &pbias_mmc_omap4, >>> + &pbias_sim_omap3, >>> + &pbias_mmc_omap2430, >>> + NULL >>> +}; >>> + >>> + >>> +static int pbias_regulator_probe(struct udevice *dev) >>> +{ >>> + const struct pbias_reg_info **p = pbias_reg_infos; >>> + struct dm_regulator_uclass_platdata *uc_pdata; >>> + >>> + uc_pdata = dev_get_uclass_platdata(dev); >>> + >>> + >>> + while (*p) { >>> + int rc; >>> + rc = dev_read_stringlist_search(dev, "regulator-name", >>> + (*p)->name); >>> + if (rc >= 0) { >>> + debug("found regulator %s\n", (*p)->name); >>> + break; >>> + } else if (rc != -ENODATA) { >>> + return rc; >>> + } >>> + p++; >>> + } >>> + if (!*p) { >>> + int i = 0; >>> + const char *s; >>> + >>> + debug("regulator "); >>> + while (dev_read_string_index(dev, "regulator-name", i++, &s) >= 0) >>> + debug("%s'%s' ", (i > 1) ? ", " : "", s); >>> + debug("%s not supported\n", (i > 2) ? "are" : "is"); >>> + return -EINVAL; >>> + } >>> + >>> + uc_pdata->type = REGULATOR_TYPE_OTHER; >>> + dev->priv = (void *)*p; >>> + >>> + return 0; >>> +} >>> + >>> +static int pbias_regulator_get_value(struct udevice *dev) >>> +{ >>> + const struct pbias_reg_info *p = dev_get_priv(dev); >>> + int rc; >>> + uint32_t reg; >>> + >>> + rc = pmic_read(dev->parent, 0, (uint8_t *)®, sizeof(reg)); >>> + if (rc) >>> + return rc; >>> + >>> + debug("%s voltage id %s\n", p->name, >>> + (reg & p->vmode) ? "3.0v" : "1.8v"); >>> + return (reg & p->vmode) ? 3000000 : 1800000; >>> +} >>> + >>> +static int pbias_regulator_set_value(struct udevice *dev, int uV) >>> +{ >>> + const struct pbias_reg_info *p = dev_get_priv(dev); >>> + int rc; >>> + uint32_t reg; >>> + >>> + debug("Setting %s voltage to %s\n", p->name, >>> + (reg & p->vmode) ? "3.0v" : "1.8v"); >>> + >>> + rc = pmic_read(dev->parent, 0, (uint8_t *)®, sizeof(reg)); >>> + if (rc) >>> + return rc; >>> + >>> + if (uV == 3000000) >>> + reg |= p->vmode; >>> + else if (uV == 1800000) >>> + reg &= ~p->vmode; >>> + else >>> + return -EINVAL; >>> + >>> + return pmic_write(dev->parent, 0, (uint8_t *)®, sizeof(reg)); >>> +} >>> + >>> +static int pbias_regulator_get_enable(struct udevice *dev) >>> +{ >>> + const struct pbias_reg_info *p = dev_get_priv(dev); >>> + int rc; >>> + uint32_t reg; >>> + >>> + rc = pmic_read(dev->parent, 0, (uint8_t *)®, sizeof(reg)); >>> + if (rc) >>> + return rc; >>> + >>> + debug("%s id %s\n", p->name, >>> + (reg & p->enable_mask) == (p->disable_val) ? "on" : "off"); >>> + >>> + return (reg & p->enable_mask) == (p->disable_val); >>> +} >>> + >>> +static int pbias_regulator_set_enable(struct udevice *dev, bool enable) >>> +{ >>> + const struct pbias_reg_info *p = dev_get_priv(dev); >>> + int rc; >>> + uint32_t reg; >>> + >>> + debug("Turning %s %s\n", enable ? "on" : "off", p->name); >>> + >>> + rc = pmic_read(dev->parent, 0, (uint8_t *)®, sizeof(reg)); >>> + if (rc) >>> + return rc; >>> + >>> + reg &= ~p->enable_mask; >>> + if (enable) >>> + reg |= p->enable; >>> + else >>> + reg |= p->disable_val; >>> + >>> + rc = pmic_write(dev->parent, 0, (uint8_t *)®, sizeof(reg)); >>> + if (rc) >>> + return rc; >>> + >>> + if (enable) >>> + udelay(p->enable_time); >>> + >>> + return 0; >>> +} >>> + >>> +static const struct dm_regulator_ops pbias_regulator_ops = { >>> + .get_value = pbias_regulator_get_value, >>> + .set_value = pbias_regulator_set_value, >>> + .get_enable = pbias_regulator_get_enable, >>> + .set_enable = pbias_regulator_set_enable, >>> +}; >>> + >>> +U_BOOT_DRIVER(pbias_regulator) = { >>> + .name = "pbias_regulator", >>> + .id = UCLASS_REGULATOR, >>> + .ops = &pbias_regulator_ops, >>> + .probe = pbias_regulator_probe, >>> +}; >>> >> > > > > _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot