On Fri, 19 May 2017 08:31:03 -0600 Simon Glass <s...@chromium.org> wrote:
> Convert this PMIC driver to driver model and fix up other users. The > regulator and GPIO functions are now handled by separate drivers. > > Note that this currently breaks apalis-tk1, jetson-tk1 and > cei-tk1-som. I have the middle one so will tidy that up in the next > version, at least. Reviewed-by: Lukasz Majewski <lu...@denx.de> > > Signed-off-by: Simon Glass <s...@chromium.org> > --- > > arch/arm/mach-tegra/board2.c | 6 - > board/nvidia/nyan-big/nyan-big.c | 22 +-- > configs/nyan-big_defconfig | 1 + > drivers/power/pmic/Makefile | 2 +- > drivers/power/pmic/as3722.c | 292 > +++++++++++++-------------------------- > include/power/as3722.h | 18 +-- 6 files changed, 114 > insertions(+), 227 deletions(-) > > diff --git a/arch/arm/mach-tegra/board2.c > b/arch/arm/mach-tegra/board2.c index 5aedd3ef9d..0291c7fb33 100644 > --- a/arch/arm/mach-tegra/board2.c > +++ b/arch/arm/mach-tegra/board2.c > @@ -29,7 +29,6 @@ > #ifdef CONFIG_TEGRA_CLOCK_SCALING > #include <asm/arch/emc.h> > #endif > -#include <power/as3722.h> > #include "emc.h" > > DECLARE_GLOBAL_DATA_PTR; > @@ -142,11 +141,6 @@ int board_init(void) > debug("Memory controller init failed: %d\n", err); > # endif > # endif /* CONFIG_TEGRA_PMU */ > -#ifdef CONFIG_PMIC_AS3722 > - err = as3722_init(NULL); > - if (err && err != -ENODEV) > - return err; > -#endif > #endif /* CONFIG_SYS_I2C_TEGRA */ > > #ifdef CONFIG_USB_EHCI_TEGRA > diff --git a/board/nvidia/nyan-big/nyan-big.c > b/board/nvidia/nyan-big/nyan-big.c index 8f68ae9fbe..54acf5418d 100644 > --- a/board/nvidia/nyan-big/nyan-big.c > +++ b/board/nvidia/nyan-big/nyan-big.c > @@ -6,6 +6,7 @@ > */ > > #include <common.h> > +#include <dm.h> > #include <errno.h> > #include <asm/gpio.h> > #include <asm/io.h> > @@ -46,20 +47,23 @@ int tegra_board_id(void) > > int tegra_lcd_pmic_init(int board_id) > { > - struct udevice *pmic; > + struct udevice *dev; > int ret; > > - ret = as3722_get(&pmic); > - if (ret) > - return -ENOENT; > + ret = uclass_get_device_by_driver(UCLASS_PMIC, > + > DM_GET_DRIVER(pmic_as3722), &dev); > + if (ret) { > + debug("%s: Failed to find PMIC\n", __func__); > + return ret; > + } > > if (board_id == 0) > - as3722_write(pmic, 0x00, 0x3c); > + pmic_reg_write(dev, 0x00, 0x3c); > else > - as3722_write(pmic, 0x00, 0x50); > - as3722_write(pmic, 0x12, 0x10); > - as3722_write(pmic, 0x0c, 0x07); > - as3722_write(pmic, 0x20, 0x10); > + pmic_reg_write(dev, 0x00, 0x50); > + pmic_reg_write(dev, 0x12, 0x10); > + pmic_reg_write(dev, 0x0c, 0x07); > + pmic_reg_write(dev, 0x20, 0x10); > > return 0; > } > diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig > index 22769bdc93..a152ff6915 100644 > --- a/configs/nyan-big_defconfig > +++ b/configs/nyan-big_defconfig > @@ -47,6 +47,7 @@ CONFIG_SPI_FLASH_WINBOND=y > CONFIG_DM_PMIC=y > CONFIG_PMIC_AS3722=y > CONFIG_DM_REGULATOR=y > +CONFIG_REGULATOR_AS3722=y > CONFIG_DM_REGULATOR_FIXED=y > CONFIG_PWM_TEGRA=y > CONFIG_SYS_NS16550=y > diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile > index f409e3a0b3..76dda2a070 100644 > --- a/drivers/power/pmic/Makefile > +++ b/drivers/power/pmic/Makefile > @@ -12,7 +12,7 @@ obj-$(CONFIG_DM_PMIC_PFUZE100) += pfuze100.o > obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o > obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o > obj-$(CONFIG_PMIC_ACT8846) += act8846.o > -obj-$(CONFIG_PMIC_AS3722) += as3722.o > +obj-$(CONFIG_PMIC_AS3722) += as3722.o as3722_gpio.o > obj-$(CONFIG_PMIC_MAX8997) += max8997.o > obj-$(CONFIG_PMIC_PM8916) += pm8916.o > obj-$(CONFIG_PMIC_RK8XX) += rk8xx.o > diff --git a/drivers/power/pmic/as3722.c b/drivers/power/pmic/as3722.c > index c09e1de06f..4efe8ee183 100644 > --- a/drivers/power/pmic/as3722.c > +++ b/drivers/power/pmic/as3722.c > @@ -11,264 +11,168 @@ > #include <errno.h> > #include <fdtdec.h> > #include <i2c.h> > - > +#include <dm/lists.h> > #include <power/as3722.h> > +#include <power/pmic.h> > > -#define AS3722_SD_VOLTAGE(n) (0x00 + (n)) > -#define AS3722_GPIO_CONTROL(n) (0x08 + (n)) > -#define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1 << 0) > -#define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7 << 0) > -#define AS3722_GPIO_CONTROL_INVERT (1 << 7) > -#define AS3722_LDO_VOLTAGE(n) (0x10 + (n)) > -#define AS3722_GPIO_SIGNAL_OUT 0x20 > -#define AS3722_SD_CONTROL 0x4d > -#define AS3722_LDO_CONTROL 0x4e > -#define AS3722_ASIC_ID1 0x90 > -#define AS3722_DEVICE_ID 0x0c > -#define AS3722_ASIC_ID2 0x91 > - > -int as3722_read(struct udevice *pmic, u8 reg, u8 *value) > -{ > - int err; > - > - err = dm_i2c_read(pmic, reg, value, 1); > - if (err < 0) > - return err; > - > - return 0; > -} > +#define AS3722_NUM_OF_REGS 0x92 > > -int as3722_write(struct udevice *pmic, u8 reg, u8 value) > +static int as3722_read(struct udevice *dev, uint reg, uint8_t *buff, > int len) { > - int err; > + int ret; > > - err = dm_i2c_write(pmic, reg, &value, 1); > - if (err < 0) > - return err; > + ret = dm_i2c_read(dev, reg, buff, len); > + if (ret < 0) > + return ret; > > return 0; > } > > -static int as3722_read_id(struct udevice *pmic, u8 *id, u8 *revision) > +static int as3722_write(struct udevice *dev, uint reg, const uint8_t > *buff, > + int len) > { > - int err; > + int ret; > > - err = as3722_read(pmic, AS3722_ASIC_ID1, id); > - if (err) { > - error("failed to read ID1 register: %d", err); > - return err; > - } > - > - err = as3722_read(pmic, AS3722_ASIC_ID2, revision); > - if (err) { > - error("failed to read ID2 register: %d", err); > - return err; > - } > + ret = dm_i2c_write(dev, reg, buff, len); > + if (ret < 0) > + return ret; > > return 0; > } > > -int as3722_sd_enable(struct udevice *pmic, unsigned int sd) > +static int as3722_read_id(struct udevice *dev, uint *idp, uint > *revisionp) { > - u8 value; > - int err; > - > - if (sd > 6) > - return -EINVAL; > + int ret; > > - err = as3722_read(pmic, AS3722_SD_CONTROL, &value); > - if (err) { > - error("failed to read SD control register: %d", err); > - return err; > + ret = pmic_reg_read(dev, AS3722_ASIC_ID1); > + if (ret < 0) { > + error("failed to read ID1 register: %d", ret); > + return ret; > } > + *idp = ret; > > - value |= 1 << sd; > - > - err = as3722_write(pmic, AS3722_SD_CONTROL, value); > - if (err < 0) { > - error("failed to write SD control register: %d", > err); > - return err; > + ret = pmic_reg_read(dev, AS3722_ASIC_ID2); > + if (ret < 0) { > + error("failed to read ID2 register: %d", ret); > + return ret; > } > + *revisionp = ret; > > return 0; > } > > -int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 > value) +/* TODO(tred...@nvidia.com): Add proper regulator support to > avoid this */ +int as3722_sd_set_voltage(struct udevice *dev, > unsigned int sd, u8 value) { > - int err; > + int ret; > > if (sd > 6) > return -EINVAL; > > - err = as3722_write(pmic, AS3722_SD_VOLTAGE(sd), value); > - if (err < 0) { > - error("failed to write SD%u voltage register: %d", > sd, err); > - return err; > + ret = pmic_reg_write(dev, AS3722_SD_VOLTAGE(sd), value); > + if (ret < 0) { > + error("failed to write SD%u voltage register: %d", > sd, ret); > + return ret; > } > > return 0; > } > > -int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo) > +int as3722_ldo_set_voltage(struct udevice *dev, unsigned int ldo, u8 > value) { > - u8 value; > - int err; > + int ret; > > if (ldo > 11) > return -EINVAL; > > - err = as3722_read(pmic, AS3722_LDO_CONTROL, &value); > - if (err) { > - error("failed to read LDO control register: %d", > err); > - return err; > - } > - > - value |= 1 << ldo; > - > - err = as3722_write(pmic, AS3722_LDO_CONTROL, value); > - if (err < 0) { > - error("failed to write LDO control register: %d", > err); > - return err; > - } > - > - return 0; > -} > - > -int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, > u8 value) -{ > - int err; > - > - if (ldo > 11) > - return -EINVAL; > - > - err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value); > - if (err < 0) { > + ret = pmic_reg_write(dev, AS3722_LDO_VOLTAGE(ldo), value); > + if (ret < 0) { > error("failed to write LDO%u voltage register: %d", > ldo, > - err); > - return err; > + ret); > + return ret; > } > > return 0; > } > > -int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio, > - unsigned long flags) > +static int as3722_probe(struct udevice *dev) > { > - u8 value = 0; > - int err; > + uint id, revision; > + int ret; > > - if (flags & AS3722_GPIO_OUTPUT_VDDH) > - value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH; > - > - if (flags & AS3722_GPIO_INVERT) > - value |= AS3722_GPIO_CONTROL_INVERT; > - > - err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value); > - if (err) { > - error("failed to configure GPIO#%u: %d", gpio, err); > - return err; > + ret = as3722_read_id(dev, &id, &revision); > + if (ret < 0) { > + error("failed to read ID: %d", ret); > + return ret; > } > > - return 0; > -} > - > -static int as3722_gpio_set(struct udevice *pmic, unsigned int gpio, > - unsigned int level) > -{ > - const char *l; > - u8 value; > - int err; > - > - if (gpio > 7) > - return -EINVAL; > - > - err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT, &value); > - if (err < 0) { > - error("failed to read GPIO signal out register: %d", > err); > - return err; > - } > - > - if (level == 0) { > - value &= ~(1 << gpio); > - l = "low"; > - } else { > - value |= 1 << gpio; > - l = "high"; > + if (id != AS3722_DEVICE_ID) { > + error("unknown device"); > + return -ENOENT; > } > > - err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value); > - if (err) { > - error("failed to set GPIO#%u %s: %d", gpio, l, err); > - return err; > - } > + debug("AS3722 revision %#x found on I2C bus %s\n", revision, > dev->name); > return 0; > } > > -int as3722_gpio_direction_output(struct udevice *pmic, unsigned int > gpio, > - unsigned int level) > -{ > - u8 value; > - int err; > - > - if (gpio > 7) > - return -EINVAL; > +#if CONFIG_IS_ENABLED(PMIC_CHILDREN) > +static const struct pmic_child_info pmic_children_info[] = { > + { .prefix = "sd", .driver = "as3722_stepdown"}, > + { .prefix = "ldo", .driver = "as3722_ldo"}, > + { }, > +}; > > - if (level == 0) > - value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL; > - else > - value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH; > +static int as3722_bind(struct udevice *dev) > +{ > + struct udevice *gpio_dev; > + ofnode regulators_node; > + int children; > + int ret; > > - err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value); > - if (err) { > - error("failed to configure GPIO#%u as output: %d", > gpio, err); > - return err; > + regulators_node = dev_read_subnode(dev, "regulators"); > + if (!ofnode_valid(regulators_node)) { > + debug("%s: %s regulators subnode not found\n", > __func__, > + dev->name); > + return -ENXIO; > } > > - err = as3722_gpio_set(pmic, gpio, level); > - if (err < 0) { > - error("failed to set GPIO#%u high: %d", gpio, err); > - return err; > + children = pmic_bind_children(dev, regulators_node, > pmic_children_info); > + if (!children) > + debug("%s: %s - no child found\n", __func__, > dev->name); > + ret = device_bind_driver(dev, "gpio_as3722", "gpio_as3722", > &gpio_dev); > + if (ret) { > + debug("%s: Cannot bind GPIOs (ret=%d)\n", __func__, > ret); > + return ret; > } > > return 0; > } > +#endif > > -/* Temporary function until we get the pmic framework */ > -int as3722_get(struct udevice **devp) > +static int as3722_reg_count(struct udevice *dev) > { > - int bus = 0; > - int address = 0x40; > - > - return i2c_get_chip_for_busnum(bus, address, 1, devp); > + return AS3722_NUM_OF_REGS; > } > > -int as3722_init(struct udevice **devp) > -{ > - struct udevice *pmic; > - u8 id, revision; > - const unsigned int bus = 0; > - const unsigned int address = 0x40; > - int err; > - > - err = i2c_get_chip_for_busnum(bus, address, 1, &pmic); > - if (err) > - return err; > - err = as3722_read_id(pmic, &id, &revision); > - if (err < 0) { > - error("failed to read ID: %d", err); > - return err; > - } > - > - if (id != AS3722_DEVICE_ID) { > - error("unknown device"); > - return -ENOENT; > - } > - > - debug("AS3722 revision %#x found on I2C bus %u, address > %#x\n", > - revision, bus, address); > - if (devp) > - *devp = pmic; > - > - return 0; > -} > +static struct dm_pmic_ops as3722_ops = { > + .reg_count = as3722_reg_count, > + .read = as3722_read, > + .write = as3722_write, > +}; > + > +static const struct udevice_id as3722_ids[] = { > + { .compatible = "ams,as3722" }, > + { } > +}; > + > +U_BOOT_DRIVER(pmic_as3722) = { > + .name = "as3722_pmic", > + .id = UCLASS_PMIC, > + .of_match = as3722_ids, > +#if CONFIG_IS_ENABLED(PMIC_CHILDREN) > + .bind = as3722_bind, > +#endif > + .probe = as3722_probe, > + .ops = &as3722_ops, > +}; > diff --git a/include/power/as3722.h b/include/power/as3722.h > index 713e79840f..491f1b7ea7 100644 > --- a/include/power/as3722.h > +++ b/include/power/as3722.h > @@ -7,8 +7,6 @@ > #ifndef __POWER_AS3722_H__ > #define __POWER_AS3722_H__ > > -#include <asm/types.h> > - > #define AS3722_GPIO_OUTPUT_VDDH (1 << 0) > #define AS3722_GPIO_INVERT (1 << 1) > > @@ -21,23 +19,9 @@ > #define AS3722_ASIC_ID2 0x91 > > #define AS3722_GPIO_CONTROL(n) (0x08 + (n)) > +#define AS3722_GPIO_SIGNAL_OUT 0x20 > #define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1 << 0) > #define AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7 << 0) > #define AS3722_GPIO_CONTROL_INVERT (1 << 7) > > -struct udevice; > - > -int as3722_init(struct udevice **devp); > -int as3722_sd_enable(struct udevice *pmic, unsigned int sd); > -int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 > value); -int as3722_ldo_enable(struct udevice *pmic, unsigned int > ldo); -int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int > ldo, u8 value); -int as3722_gpio_configure(struct udevice *pmic, > unsigned int gpio, > - unsigned long flags); > -int as3722_gpio_direction_output(struct udevice *pmic, unsigned int > gpio, > - unsigned int level); > -int as3722_read(struct udevice *pmic, u8 reg, u8 *value); > -int as3722_write(struct udevice *pmic, u8 reg, u8 value); > -int as3722_get(struct udevice **devp); > - > #endif /* __POWER_AS3722_H__ */ Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: w...@denx.de _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot