From 43b6e38b27a19f3d193ecf60d62091ab3f737a3e Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Sun, 12 Jan 2020 15:57:42 +0100 Subject: [PATCH 1/7] dts: add property removal option CONFIG_OF_REMOVE_PROPS This can be used for device tree size reduction similar as CONFIG_OF_SPL_REMOVE_PROPS option. Some boards must pass the built-in DTB unchanged to the kernel, thus we may not cut it down unconditionally. Therefore enable the property removal list option only if CONFIG_OF_DTB_PROPS_REMOVE is selected. Signed-off-by: Anatolij Gustschin --- dts/Kconfig | 20 ++++++++++++++++++++ dts/Makefile | 5 +++++ scripts/Makefile.lib | 8 ++++++++ 3 files changed, 33 insertions(+) diff --git a/dts/Kconfig b/dts/Kconfig index d3313dd08f..046a54a173 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -314,6 +314,26 @@ config OF_SPL_REMOVE_PROPS can be discarded. This option defines the list of properties to discard. +config OF_DTB_PROPS_REMOVE + bool "Enable removal of device tree properties" + depends on OF_CONTROL + help + Some boards have restricted amount of storage for U-Boot image. + If the generated binary doesn't fit into available image storage, + the built-in device tree could probably be cut down by removing + some not required device tree properties to reduce the image size. + Enable this option and define the properties to be removed in the + CONFIG_OF_REMOVE_PROPS list. Do not enable this option if you must + pass the built-in DTB directly to the kernel! + +config OF_REMOVE_PROPS + string "List of device tree properties to drop" + depends on OF_DTB_PROPS_REMOVE + default "interrupt-parent interrupts" if PINCTRL + help + Some properties are not used by U-Boot and can be discarded. + This option defines the list of properties to discard. + config SPL_OF_PLATDATA bool "Generate platform data for use in SPL" depends on SPL_OF_CONTROL diff --git a/dts/Makefile b/dts/Makefile index 1f83e615e8..a20930eb9a 100644 --- a/dts/Makefile +++ b/dts/Makefile @@ -19,8 +19,13 @@ endif $(obj)/dt-spl.dtb: $(DTB) $(objtree)/tools/fdtgrep FORCE $(call if_changed,fdtgrep) +ifeq ($(CONFIG_OF_DTB_PROPS_REMOVE),y) +$(obj)/dt.dtb: $(DTB) $(objtree)/tools/fdtgrep FORCE + $(call if_changed,fdt_rm_props) +else $(obj)/dt.dtb: $(DTB) FORCE $(call if_changed,shipped) +endif targets += dt.dtb dt-spl.dtb diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 4ea898a421..30f392fdfb 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -544,3 +544,11 @@ quiet_cmd_fdtgrep = FDTGREP $@ $(objtree)/tools/fdtgrep -r -O dtb - -o $@ \ -P u-boot,dm-pre-reloc -P u-boot,dm-spl -P u-boot,dm-tpl \ $(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS))) + +# fdt_rm_props +# --------------------------------------------------------------------------- +# Pass the original device tree file through fdtgrep. This removes various +# unused properties. The output is typically a smaller device tree file. +quiet_cmd_fdt_rm_props = FDTGREP $@ + cmd_fdt_rm_props = cat $< | $(objtree)/tools/fdtgrep -r -O dtb - -o $@ \ + $(addprefix -P ,$(subst $\",,$(CONFIG_OF_REMOVE_PROPS))) From d1b04cd3aa9c3cc741df24a5536c84b1d54cbda6 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Sun, 12 Jan 2020 15:57:43 +0100 Subject: [PATCH 2/7] tbs2910: add custom CONFIG_OF_REMOVE_PROPS list to defconfig This shrinks the image size: all -3840.0 text -3840.0 Signed-off-by: Anatolij Gustschin Acked-by: Soeren Moch --- configs/tbs2910_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig index d32e7841cc..61d4c74324 100644 --- a/configs/tbs2910_defconfig +++ b/configs/tbs2910_defconfig @@ -46,6 +46,8 @@ CONFIG_EFI_PARTITION=y CONFIG_OF_CONTROL=y CONFIG_OF_EMBED=y CONFIG_DEFAULT_DEVICE_TREE="imx6q-tbs2910" +CONFIG_OF_DTB_PROPS_REMOVE=y +CONFIG_OF_REMOVE_PROPS="dmas dma-names interrupt-parent interrupts interrupts-extended interrupt-names interrupt-map interrupt-map-mask" CONFIG_ENV_IS_IN_MMC=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_DM=y From 2d7818d04ff29581f497b70c8bd903516a179e9d Mon Sep 17 00:00:00 2001 From: Peng Ma Date: Wed, 4 Dec 2019 10:36:47 +0000 Subject: [PATCH 3/7] cmd: sata: Add block unbind device function If we didn't unbind the sata from block device, the same devices would be added after sata remove, This patch is to resolve this issue as below: => sata info SATA#0: (3.0 Gbps) SATA#1: (3.0 Gbps) Device 0: Model: INTEL SSDSA2BW300G3D Firm: 4PC10362 Ser#: BTPR247005PY30 Type: Hard Disk Supports 48-bit addressing Capacity: 286168.1 MB = 279.4 GB (586072368 x 512) Device 1: Model: INTEL SSDSA2BW300G3D Firm: 4PC10362 Ser#: BTPR247005VX30 Type: Hard Disk Supports 48-bit addressing Capacity: 286168.1 MB = 279.4 GB (586072368 x 512) => sata stop => sata info SATA#0: (3.0 Gbps) SATA#1: (3.0 Gbps) Device 0: Model: INTEL SSDSA2BW300G3D Firm: 4PC10362 Ser#: BTPR247005PY300 Type: Hard Disk Supports 48-bit addressing Capacity: 286168.1 MB = 279.4 GB (586072368 x 512) Device 1: Model: INTEL SSDSA2BW300G3D Firm: 4PC10362 Ser#: BTPR247005VX300 Type: Hard Disk Supports 48-bit addressing Capacity: 286168.1 MB = 279.4 GB (586072368 x 512) Device 2: Model: INTEL SSDSA2BW300G3D Firm: 4PC10362 Ser#: BTPR247005PY300 Type: Hard Disk Supports 48-bit addressing Capacity: 286168.1 MB = 279.4 GB (586072368 x 512) Device 3: Model: INTEL SSDSA2BW300G3D Firm: 4PC10362 Ser#: BTPR247005VX300 Type: Hard Disk Supports 48-bit addressing Capacity: 286168.1 MB = 279.4 GB (586072368 x 512) Signed-off-by: Peng Ma Reviewed-by: Simon Glass --- cmd/sata.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/sata.c b/cmd/sata.c index a73cc54bd3..6bdb516cb5 100644 --- a/cmd/sata.c +++ b/cmd/sata.c @@ -26,6 +26,8 @@ int sata_remove(int devnum) struct udevice *dev; int rc; + blk_unbind_all(IF_TYPE_SATA); + rc = uclass_find_device(UCLASS_AHCI, devnum, &dev); if (!rc && !dev) rc = uclass_find_first_device(UCLASS_AHCI, &dev); From e1d26a7642253a4b745a69c5faef494dd0b5c01a Mon Sep 17 00:00:00 2001 From: Ian Ray Date: Tue, 14 Jan 2020 16:18:20 +0000 Subject: [PATCH 4/7] rtc: s35392a: encode command correctly The 3-bit "command", or register, is encoded within the device address. Configure the device accordingly, and pass command in DM I2C read/write calls correctly. Signed-off-by: Ian Ray Signed-off-by: Robert Beckett --- drivers/rtc/s35392a.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/rtc/s35392a.c b/drivers/rtc/s35392a.c index 4f478ccfd7..3bfe481403 100644 --- a/drivers/rtc/s35392a.c +++ b/drivers/rtc/s35392a.c @@ -24,11 +24,13 @@ #include #include -#define S35390A_CMD_STATUS1 0x30 -#define S35390A_CMD_STATUS2 0x31 -#define S35390A_CMD_TIME1 0x32 -#define S35390A_CMD_TIME2 0x33 -#define S35390A_CMD_INT2_REG1 0x35 +#define S35390A_CHIP_ADDR 0x30 + +#define S35390A_CMD_STATUS1 0x0 +#define S35390A_CMD_STATUS2 0x1 +#define S35390A_CMD_TIME1 0x2 +#define S35390A_CMD_TIME2 0x3 +#define S35390A_CMD_INT2_REG1 0x5 #define S35390A_BYTE_YEAR 0 #define S35390A_BYTE_MONTH 1 @@ -85,11 +87,10 @@ static int s35392a_rtc_read(DEV_TYPE *dev, u8 reg, u8 *buf, int len) int ret; #ifdef CONFIG_DM_RTC - /* TODO: we need to tweak the chip address to reg */ - ret = dm_i2c_read(dev, 0, buf, len); + ret = dm_i2c_read(dev, reg, buf, len); #else (void)dev; - ret = i2c_read(reg, 0, -1, buf, len); + ret = i2c_read(S35390A_CHIP_ADDR | reg, 0, -1, buf, len); #endif return ret; @@ -100,11 +101,10 @@ static int s35392a_rtc_write(DEV_TYPE *dev, u8 reg, u8 *buf, int len) int ret; #ifdef CONFIG_DM_RTC - /* TODO: we need to tweak the chip address to reg */ - ret = dm_i2c_write(dev, 0, buf, 1); + ret = dm_i2c_write(dev, reg, buf, len); #else (void)dev; - ret = i2c_write(reg, 0, 0, buf, len); + ret = i2c_write(S35390A_CHIP_ADDR | reg, 0, 0, buf, len); #endif return ret; @@ -336,6 +336,13 @@ void rtc_init(void) static int s35392a_probe(struct udevice *dev) { +#if defined(CONFIG_DM_RTC) + /* 3-bit "command", or register, is encoded within the device address. + */ + i2c_set_chip_offset_len(dev, 0); + i2c_set_chip_addr_offset_mask(dev, 0x7); +#endif + s35392a_rtc_init(dev); return 0; } From 483880c490b0fbd4e4be5a93f55947a42066f825 Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Tue, 14 Jan 2020 15:56:16 +0000 Subject: [PATCH 5/7] power: pmic: add driver for Dialog DA9063 PMIC This adds the basic register access operations and child regulator binding (if a regulator driver exists). Robert Beckett: simplify accesses by using bottom bit of address as offset overflow. This avoids the need to track which page we are on. Add an option CONFIG_SPL_DM_PMIC_DA9063. Signed-off-by: Martin Fuzzey Signed-off-by: Robert Beckett --- drivers/power/pmic/Kconfig | 14 ++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/da9063.c | 130 +++++++++++++++ include/power/da9063_pmic.h | 308 ++++++++++++++++++++++++++++++++++++ 4 files changed, 453 insertions(+) create mode 100644 drivers/power/pmic/da9063.c create mode 100644 include/power/da9063_pmic.h diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index df9372c239..ef8bf49d49 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -40,6 +40,20 @@ config PMIC_ACT8846 functions. It uses an I2C interface and is designed for use with tablets and smartphones. +config DM_PMIC_DA9063 + bool "Enable Driver Model for the Dialog DA9063 PMIC" + depends on DM_PMIC + help + This config enables implementation of driver-model pmic uclass features + for PMIC DA9063. The driver implements read/write operations. + +config SPL_DM_PMIC_DA9063 + bool "Enable Driver Model for the Dialog DA9063 PMIC in SPL" + depends on DM_PMIC && SPL + help + This config enables implementation of driver-model pmic uclass features + for PMIC DA9063. The driver implements read/write operations. + config PMIC_AS3722 bool "Enable support for the Austria Micro Systems (AMS) AS7322 PMIC" help diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index 7b6cb0ee1b..9cd6c375c0 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_DM_PMIC) += pmic-uclass.o obj-$(CONFIG_DM_PMIC_FAN53555) += fan53555.o +obj-$(CONFIG_$(SPL_)DM_PMIC_DA9063) += da9063.o obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o obj-$(CONFIG_DM_PMIC_MC34708) += mc34708.o diff --git a/drivers/power/pmic/da9063.c b/drivers/power/pmic/da9063.c new file mode 100644 index 0000000000..abda7a5a40 --- /dev/null +++ b/drivers/power/pmic/da9063.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Flowbird + * Martin Fuzzey + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct pmic_child_info pmic_children_info[] = { + { .prefix = "ldo", .driver = DA9063_LDO_DRIVER }, + { .prefix = "b", .driver = DA9063_BUCK_DRIVER }, + { }, +}; + +/* + * The register map is non contiguous and attempts to read in the holes fail. + * But "pmic dump" tries to dump the full register map. + * So define the holes here so we can fix that. + */ +struct da9063_reg_hole { + u16 first; + u16 last; +}; + +static const struct da9063_reg_hole da9063_reg_holes[] = { + DA9063_REG_HOLE_1, + DA9063_REG_HOLE_2, + DA9063_REG_HOLE_3, + /* These aren't readable. I can't see why from the datasheet but + * attempts to read fail and the kernel marks them unreadable too, + */ + {DA9063_REG_OTP_COUNT, DA9063_REG_OTP_DATA}, +}; + +static int da9063_reg_count(struct udevice *dev) +{ + return DA9063_NUM_OF_REGS; +} + +static bool da9063_reg_valid(uint reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(da9063_reg_holes); i++) { + const struct da9063_reg_hole *hole = &da9063_reg_holes[i]; + + if (reg >= hole->first && reg <= hole->last) + return false; + } + + return true; +} + +static int da9063_write(struct udevice *dev, uint reg, const uint8_t *buff, + int len) +{ + if (dm_i2c_write(dev, reg, buff, len)) { + pr_err("write error to device: %p register: %#x!", dev, reg); + return -EIO; + } + + return 0; +} + +static int da9063_read(struct udevice *dev, uint reg, uint8_t *buff, int len) +{ + if (!da9063_reg_valid(reg)) + return -ENODATA; + + if (dm_i2c_read(dev, reg, buff, len)) { + pr_err("read error from device: %p register: %#x!", dev, reg); + return -EIO; + } + + return 0; +} + +static int da9063_bind(struct udevice *dev) +{ + ofnode regulators_node; + int children; + + regulators_node = dev_read_subnode(dev, "regulators"); + if (!ofnode_valid(regulators_node)) { + debug("%s: %s regulators subnode not found!", __func__, + dev->name); + return -ENXIO; + } + + debug("%s: '%s' - found regulators subnode\n", __func__, dev->name); + + children = pmic_bind_children(dev, regulators_node, pmic_children_info); + if (!children) + debug("%s: %s - no child found\n", __func__, dev->name); + + /* Always return success for this device */ + return 0; +} + +static int da9063_probe(struct udevice *dev) +{ + return i2c_set_chip_addr_offset_mask(dev, 0x1); +} + +static struct dm_pmic_ops da9063_ops = { + .reg_count = da9063_reg_count, + .read = da9063_read, + .write = da9063_write, +}; + +static const struct udevice_id da9063_ids[] = { + { .compatible = "dlg,da9063" }, + { } +}; + +U_BOOT_DRIVER(pmic_da9063) = { + .name = "da9063_pmic", + .id = UCLASS_PMIC, + .of_match = da9063_ids, + .bind = da9063_bind, + .probe = da9063_probe, + .ops = &da9063_ops, +}; diff --git a/include/power/da9063_pmic.h b/include/power/da9063_pmic.h new file mode 100644 index 0000000000..9b0f76c04f --- /dev/null +++ b/include/power/da9063_pmic.h @@ -0,0 +1,308 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Flowbird + * Martin Fuzzey + */ + +#ifndef __DA9063_PMIC_H_ +#define __DA9063_PMIC_H_ + +/* Register definitions below taken from the kernel */ + +/* Page selection I2C or SPI always in the beginning of any page. */ +/* Page 0 : I2C access 0x000 - 0x0FF SPI access 0x000 - 0x07F */ +/* Page 1 : SPI access 0x080 - 0x0FF */ +/* Page 2 : I2C access 0x100 - 0x1FF SPI access 0x100 - 0x17F */ +/* Page 3 : SPI access 0x180 - 0x1FF */ +#define DA9063_REG_PAGE_CON 0x00 + +/* System Control and Event Registers */ +#define DA9063_REG_STATUS_A 0x01 +#define DA9063_REG_STATUS_B 0x02 +#define DA9063_REG_STATUS_C 0x03 +#define DA9063_REG_STATUS_D 0x04 +#define DA9063_REG_FAULT_LOG 0x05 +#define DA9063_REG_EVENT_A 0x06 +#define DA9063_REG_EVENT_B 0x07 +#define DA9063_REG_EVENT_C 0x08 +#define DA9063_REG_EVENT_D 0x09 +#define DA9063_REG_IRQ_MASK_A 0x0A +#define DA9063_REG_IRQ_MASK_B 0x0B +#define DA9063_REG_IRQ_MASK_C 0x0C +#define DA9063_REG_IRQ_MASK_D 0x0D +#define DA9063_REG_CONTROL_A 0x0E +#define DA9063_REG_CONTROL_B 0x0F +#define DA9063_REG_CONTROL_C 0x10 +#define DA9063_REG_CONTROL_D 0x11 +#define DA9063_REG_CONTROL_E 0x12 +#define DA9063_REG_CONTROL_F 0x13 +#define DA9063_REG_PD_DIS 0x14 + +/* GPIO Control Registers */ +#define DA9063_REG_GPIO_0_1 0x15 +#define DA9063_REG_GPIO_2_3 0x16 +#define DA9063_REG_GPIO_4_5 0x17 +#define DA9063_REG_GPIO_6_7 0x18 +#define DA9063_REG_GPIO_8_9 0x19 +#define DA9063_REG_GPIO_10_11 0x1A +#define DA9063_REG_GPIO_12_13 0x1B +#define DA9063_REG_GPIO_14_15 0x1C +#define DA9063_REG_GPIO_MODE0_7 0x1D +#define DA9063_REG_GPIO_MODE8_15 0x1E +#define DA9063_REG_SWITCH_CONT 0x1F + +/* Regulator Control Registers */ +#define DA9063_REG_BCORE2_CONT 0x20 +#define DA9063_REG_BCORE1_CONT 0x21 +#define DA9063_REG_BPRO_CONT 0x22 +#define DA9063_REG_BMEM_CONT 0x23 +#define DA9063_REG_BIO_CONT 0x24 +#define DA9063_REG_BPERI_CONT 0x25 +#define DA9063_REG_LDO1_CONT 0x26 +#define DA9063_REG_LDO2_CONT 0x27 +#define DA9063_REG_LDO3_CONT 0x28 +#define DA9063_REG_LDO4_CONT 0x29 +#define DA9063_REG_LDO5_CONT 0x2A +#define DA9063_REG_LDO6_CONT 0x2B +#define DA9063_REG_LDO7_CONT 0x2C +#define DA9063_REG_LDO8_CONT 0x2D +#define DA9063_REG_LDO9_CONT 0x2E +#define DA9063_REG_LDO10_CONT 0x2F +#define DA9063_REG_LDO11_CONT 0x30 +#define DA9063_REG_SUPPLIES 0x31 +#define DA9063_REG_DVC_1 0x32 +#define DA9063_REG_DVC_2 0x33 + +/* GP-ADC Control Registers */ +#define DA9063_REG_ADC_MAN 0x34 +#define DA9063_REG_ADC_CONT 0x35 +#define DA9063_REG_VSYS_MON 0x36 +#define DA9063_REG_ADC_RES_L 0x37 +#define DA9063_REG_ADC_RES_H 0x38 +#define DA9063_REG_VSYS_RES 0x39 +#define DA9063_REG_ADCIN1_RES 0x3A +#define DA9063_REG_ADCIN2_RES 0x3B +#define DA9063_REG_ADCIN3_RES 0x3C +#define DA9063_REG_MON_A8_RES 0x3D +#define DA9063_REG_MON_A9_RES 0x3E +#define DA9063_REG_MON_A10_RES 0x3F + +/* RTC Calendar and Alarm Registers */ +#define DA9063_REG_COUNT_S 0x40 +#define DA9063_REG_COUNT_MI 0x41 +#define DA9063_REG_COUNT_H 0x42 +#define DA9063_REG_COUNT_D 0x43 +#define DA9063_REG_COUNT_MO 0x44 +#define DA9063_REG_COUNT_Y 0x45 + +#define DA9063_AD_REG_ALARM_MI 0x46 +#define DA9063_AD_REG_ALARM_H 0x47 +#define DA9063_AD_REG_ALARM_D 0x48 +#define DA9063_AD_REG_ALARM_MO 0x49 +#define DA9063_AD_REG_ALARM_Y 0x4A +#define DA9063_AD_REG_SECOND_A 0x4B +#define DA9063_AD_REG_SECOND_B 0x4C +#define DA9063_AD_REG_SECOND_C 0x4D +#define DA9063_AD_REG_SECOND_D 0x4E + +#define DA9063_BB_REG_ALARM_S 0x46 +#define DA9063_BB_REG_ALARM_MI 0x47 +#define DA9063_BB_REG_ALARM_H 0x48 +#define DA9063_BB_REG_ALARM_D 0x49 +#define DA9063_BB_REG_ALARM_MO 0x4A +#define DA9063_BB_REG_ALARM_Y 0x4B +#define DA9063_BB_REG_SECOND_A 0x4C +#define DA9063_BB_REG_SECOND_B 0x4D +#define DA9063_BB_REG_SECOND_C 0x4E +#define DA9063_BB_REG_SECOND_D 0x4F + +#define DA9063_REG_HOLE_1 {0x50, 0x7F} + +/* Sequencer Control Registers */ +#define DA9063_REG_SEQ 0x81 +#define DA9063_REG_SEQ_TIMER 0x82 +#define DA9063_REG_ID_2_1 0x83 +#define DA9063_REG_ID_4_3 0x84 +#define DA9063_REG_ID_6_5 0x85 +#define DA9063_REG_ID_8_7 0x86 +#define DA9063_REG_ID_10_9 0x87 +#define DA9063_REG_ID_12_11 0x88 +#define DA9063_REG_ID_14_13 0x89 +#define DA9063_REG_ID_16_15 0x8A +#define DA9063_REG_ID_18_17 0x8B +#define DA9063_REG_ID_20_19 0x8C +#define DA9063_REG_ID_22_21 0x8D +#define DA9063_REG_ID_24_23 0x8E +#define DA9063_REG_ID_26_25 0x8F +#define DA9063_REG_ID_28_27 0x90 +#define DA9063_REG_ID_30_29 0x91 +#define DA9063_REG_ID_32_31 0x92 +#define DA9063_REG_SEQ_A 0x95 +#define DA9063_REG_SEQ_B 0x96 +#define DA9063_REG_WAIT 0x97 +#define DA9063_REG_EN_32K 0x98 +#define DA9063_REG_RESET 0x99 + +/* Regulator Setting Registers */ +#define DA9063_REG_BUCK_ILIM_A 0x9A +#define DA9063_REG_BUCK_ILIM_B 0x9B +#define DA9063_REG_BUCK_ILIM_C 0x9C +#define DA9063_REG_BCORE2_CFG 0x9D +#define DA9063_REG_BCORE1_CFG 0x9E +#define DA9063_REG_BPRO_CFG 0x9F +#define DA9063_REG_BIO_CFG 0xA0 +#define DA9063_REG_BMEM_CFG 0xA1 +#define DA9063_REG_BPERI_CFG 0xA2 +#define DA9063_REG_VBCORE2_A 0xA3 +#define DA9063_REG_VBCORE1_A 0xA4 +#define DA9063_REG_VBPRO_A 0xA5 +#define DA9063_REG_VBMEM_A 0xA6 +#define DA9063_REG_VBIO_A 0xA7 +#define DA9063_REG_VBPERI_A 0xA8 +#define DA9063_REG_VLDO1_A 0xA9 +#define DA9063_REG_VLDO2_A 0xAA +#define DA9063_REG_VLDO3_A 0xAB +#define DA9063_REG_VLDO4_A 0xAC +#define DA9063_REG_VLDO5_A 0xAD +#define DA9063_REG_VLDO6_A 0xAE +#define DA9063_REG_VLDO7_A 0xAF +#define DA9063_REG_VLDO8_A 0xB0 +#define DA9063_REG_VLDO9_A 0xB1 +#define DA9063_REG_VLDO10_A 0xB2 +#define DA9063_REG_VLDO11_A 0xB3 +#define DA9063_REG_VBCORE2_B 0xB4 +#define DA9063_REG_VBCORE1_B 0xB5 +#define DA9063_REG_VBPRO_B 0xB6 +#define DA9063_REG_VBMEM_B 0xB7 +#define DA9063_REG_VBIO_B 0xB8 +#define DA9063_REG_VBPERI_B 0xB9 +#define DA9063_REG_VLDO1_B 0xBA +#define DA9063_REG_VLDO2_B 0xBB +#define DA9063_REG_VLDO3_B 0xBC +#define DA9063_REG_VLDO4_B 0xBD +#define DA9063_REG_VLDO5_B 0xBE +#define DA9063_REG_VLDO6_B 0xBF +#define DA9063_REG_VLDO7_B 0xC0 +#define DA9063_REG_VLDO8_B 0xC1 +#define DA9063_REG_VLDO9_B 0xC2 +#define DA9063_REG_VLDO10_B 0xC3 +#define DA9063_REG_VLDO11_B 0xC4 + +/* Backup Battery Charger Control Register */ +#define DA9063_REG_BBAT_CONT 0xC5 + +/* GPIO PWM (LED) */ +#define DA9063_REG_GPO11_LED 0xC6 +#define DA9063_REG_GPO14_LED 0xC7 +#define DA9063_REG_GPO15_LED 0xC8 + +/* GP-ADC Threshold Registers */ +#define DA9063_REG_ADC_CFG 0xC9 +#define DA9063_REG_AUTO1_HIGH 0xCA +#define DA9063_REG_AUTO1_LOW 0xCB +#define DA9063_REG_AUTO2_HIGH 0xCC +#define DA9063_REG_AUTO2_LOW 0xCD +#define DA9063_REG_AUTO3_HIGH 0xCE +#define DA9063_REG_AUTO3_LOW 0xCF + +#define DA9063_REG_HOLE_2 {0xD0, 0xFF} + +/* DA9063 Configuration registers */ +/* OTP */ +#define DA9063_REG_OTP_COUNT 0x101 +#define DA9063_REG_OTP_ADDR 0x102 +#define DA9063_REG_OTP_DATA 0x103 + +/* Customer Trim and Configuration */ +#define DA9063_REG_T_OFFSET 0x104 +#define DA9063_REG_INTERFACE 0x105 +#define DA9063_REG_CONFIG_A 0x106 +#define DA9063_REG_CONFIG_B 0x107 +#define DA9063_REG_CONFIG_C 0x108 +#define DA9063_REG_CONFIG_D 0x109 +#define DA9063_REG_CONFIG_E 0x10A +#define DA9063_REG_CONFIG_F 0x10B +#define DA9063_REG_CONFIG_G 0x10C +#define DA9063_REG_CONFIG_H 0x10D +#define DA9063_REG_CONFIG_I 0x10E +#define DA9063_REG_CONFIG_J 0x10F +#define DA9063_REG_CONFIG_K 0x110 +#define DA9063_REG_CONFIG_L 0x111 + +#define DA9063_AD_REG_MON_REG_1 0x112 +#define DA9063_AD_REG_MON_REG_2 0x113 +#define DA9063_AD_REG_MON_REG_3 0x114 +#define DA9063_AD_REG_MON_REG_4 0x115 +#define DA9063_AD_REG_MON_REG_5 0x116 +#define DA9063_AD_REG_MON_REG_6 0x117 +#define DA9063_AD_REG_TRIM_CLDR 0x118 + +#define DA9063_AD_REG_GP_ID_0 0x119 +#define DA9063_AD_REG_GP_ID_1 0x11A +#define DA9063_AD_REG_GP_ID_2 0x11B +#define DA9063_AD_REG_GP_ID_3 0x11C +#define DA9063_AD_REG_GP_ID_4 0x11D +#define DA9063_AD_REG_GP_ID_5 0x11E +#define DA9063_AD_REG_GP_ID_6 0x11F +#define DA9063_AD_REG_GP_ID_7 0x120 +#define DA9063_AD_REG_GP_ID_8 0x121 +#define DA9063_AD_REG_GP_ID_9 0x122 +#define DA9063_AD_REG_GP_ID_10 0x123 +#define DA9063_AD_REG_GP_ID_11 0x124 +#define DA9063_AD_REG_GP_ID_12 0x125 +#define DA9063_AD_REG_GP_ID_13 0x126 +#define DA9063_AD_REG_GP_ID_14 0x127 +#define DA9063_AD_REG_GP_ID_15 0x128 +#define DA9063_AD_REG_GP_ID_16 0x129 +#define DA9063_AD_REG_GP_ID_17 0x12A +#define DA9063_AD_REG_GP_ID_18 0x12B +#define DA9063_AD_REG_GP_ID_19 0x12C + +#define DA9063_BB_REG_CONFIG_M 0x112 +#define DA9063_BB_REG_CONFIG_N 0x113 + +#define DA9063_BB_REG_MON_REG_1 0x114 +#define DA9063_BB_REG_MON_REG_2 0x115 +#define DA9063_BB_REG_MON_REG_3 0x116 +#define DA9063_BB_REG_MON_REG_4 0x117 +#define DA9063_BB_REG_MON_REG_5 0x11E +#define DA9063_BB_REG_MON_REG_6 0x11F +#define DA9063_BB_REG_TRIM_CLDR 0x120 +/* General Purpose Registers */ +#define DA9063_BB_REG_GP_ID_0 0x121 +#define DA9063_BB_REG_GP_ID_1 0x122 +#define DA9063_BB_REG_GP_ID_2 0x123 +#define DA9063_BB_REG_GP_ID_3 0x124 +#define DA9063_BB_REG_GP_ID_4 0x125 +#define DA9063_BB_REG_GP_ID_5 0x126 +#define DA9063_BB_REG_GP_ID_6 0x127 +#define DA9063_BB_REG_GP_ID_7 0x128 +#define DA9063_BB_REG_GP_ID_8 0x129 +#define DA9063_BB_REG_GP_ID_9 0x12A +#define DA9063_BB_REG_GP_ID_10 0x12B +#define DA9063_BB_REG_GP_ID_11 0x12C +#define DA9063_BB_REG_GP_ID_12 0x12D +#define DA9063_BB_REG_GP_ID_13 0x12E +#define DA9063_BB_REG_GP_ID_14 0x12F +#define DA9063_BB_REG_GP_ID_15 0x130 +#define DA9063_BB_REG_GP_ID_16 0x131 +#define DA9063_BB_REG_GP_ID_17 0x132 +#define DA9063_BB_REG_GP_ID_18 0x133 +#define DA9063_BB_REG_GP_ID_19 0x134 + +/* 0x135 - 0x13f are readable, but not documented */ +#define DA9063_REG_HOLE_3 {0x140, 0x17F} + +/* Chip ID and variant */ +#define DA9063_REG_CHIP_ID 0x181 +#define DA9063_REG_CHIP_VARIANT 0x182 +#define DA9063_REG_CUSTOMER_ID 0x183 +#define DA9063_REG_CONFIG_ID 0x184 + +#define DA9063_NUM_OF_REGS (DA9063_REG_CONFIG_ID + 1) + +/* Drivers name */ +#define DA9063_LDO_DRIVER "da9063_ldo" +#define DA9063_BUCK_DRIVER "da9063_buck" + +#endif From 7ae22d8479c9e832c0a9a18de705553535a1a9f6 Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Tue, 14 Jan 2020 15:56:17 +0000 Subject: [PATCH 6/7] power: regulator: add driver for Dialog DA9063 PMIC Add a driver for the regulators in the the DA9063 PMIC. Robert Beckett: move regulator modes to header so board code can set modes. Correct mode mask used in ldo_set_mode. Add an option CONFIG_SPL_DM_REGULATOR_DA9063. Signed-off-by: Martin Fuzzey Signed-off-by: Robert Beckett --- drivers/power/regulator/Kconfig | 20 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/da9063.c | 388 +++++++++++++++++++++++++++++++ include/power/da9063_pmic.h | 12 + 4 files changed, 421 insertions(+) create mode 100644 drivers/power/regulator/da9063.c diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 25fc787a29..d431102462 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -60,6 +60,26 @@ config SPL_DM_REGULATOR_BD71837 This config enables implementation of driver-model regulator uclass features for regulators on ROHM BD71837 and BD71847 in SPL. +config DM_REGULATOR_DA9063 + bool "Enable Driver Model for REGULATOR DA9063" + depends on DM_REGULATOR && DM_PMIC_DA9063 + help + This config enables implementation of driver-model regulator uclass + features for REGULATOR DA9063. + The driver implements get/set api for value, enable and mode for all + regulators. It also implements the get/set api for current for the + buck regulators. + +config SPL_DM_REGULATOR_DA9063 + bool "Enable Driver Model for REGULATOR DA9063 in SPL" + depends on DM_REGULATOR && DM_PMIC_DA9063 && SPL + help + This config enables implementation of driver-model regulator uclass + features for REGULATOR DA9063. + The driver implements get/set api for value, enable and mode for all + regulators. It also implements the get/set api for current for the + buck regulators. + config DM_REGULATOR_PFUZE100 bool "Enable Driver Model for REGULATOR PFUZE100" depends on DM_REGULATOR && DM_PMIC_PFUZE100 diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index b611c901ba..9d58112dcb 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR) += regulator-uclass.o obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o obj-$(CONFIG_REGULATOR_AS3722) += as3722_regulator.o +obj-$(CONFIG_$(SPL_)DM_REGULATOR_DA9063) += da9063.o obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_BD71837) += bd71837.o diff --git a/drivers/power/regulator/da9063.c b/drivers/power/regulator/da9063.c new file mode 100644 index 0000000000..8990be113e --- /dev/null +++ b/drivers/power/regulator/da9063.c @@ -0,0 +1,388 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Flowbird + * Martin Fuzzey + */ + +#include +#include +#include +#include +#include + +#define DA9063_BUCK_EN 0x01 +#define DA9063_LDO_EN 0x01 +#define DA9063_VBUCK_MASK 0x7F +#define DA9063_BUCK_SL 0x80 +#define DA9063_LDO_SL 0x80 + +#define DA9063_VLDO1_MASK 0x3F +#define DA9063_VLDO2_MASK 0x3F +#define DA9063_VLDO3_MASK 0x7F +#define DA9063_VLDO4_MASK 0x7F +#define DA9063_VLDO5_MASK 0x3F +#define DA9063_VLDO6_MASK 0x3F +#define DA9063_VLDO7_MASK 0x3F +#define DA9063_VLDO8_MASK 0x3F +#define DA9063_VLDO9_MASK 0x3F +#define DA9063_VLDO10_MASK 0x3F +#define DA9063_VLDO11_MASK 0x3F + +#define DA9063_BUCK_MODE_MASK 0xC0 +#define DA9063_BUCK_MODE_MANUAL 0x00 +#define DA9063_BUCK_MODE_SLEEP 0x40 +#define DA9063_BUCK_MODE_SYNC 0x80 +#define DA9063_BUCK_MODE_AUTO 0xC0 + +#define DA9063_BIO_ILIM_MASK 0x0F +#define DA9063_BMEM_ILIM_MASK 0xF0 +#define DA9063_BPRO_ILIM_MASK 0x0F +#define DA9063_BPERI_ILIM_MASK 0xF0 +#define DA9063_BCORE1_ILIM_MASK 0x0F +#define DA9063_BCORE2_ILIM_MASK 0xF0 + +struct da9063_reg_info { + uint min_uV; + uint step_uV; + uint max_uV; + uint min_uA; + uint step_uA; + uint max_uA; + uint en_reg; + uint vsel_reg; + uint mode_reg; + uint ilim_reg; + u8 en_mask; + u8 vsel_mask; + u8 ilim_mask; + const char *dt_node_name; + const int *current_limits; +}; + +struct da9063_priv { + const struct da9063_reg_info *reg_info; +}; + +static struct dm_regulator_mode da9063_ldo_modes[] = { + { .id = DA9063_LDOMODE_SLEEP, + .register_value = DA9063_LDO_SL, .name = "SLEEP" }, + { .id = DA9063_LDOMODE_NORMAL, + .register_value = 0, .name = "NORMAL" }, +}; + +#define DA9063_LDO(regl_name, min_mV, step_mV, max_mV) \ + .min_uV = (min_mV) * 1000, \ + .step_uV = (step_mV) * 1000, \ + .max_uV = (max_mV) * 1000, \ + .en_reg = DA9063_REG_##regl_name##_CONT, \ + .en_mask = DA9063_LDO_EN, \ + .vsel_reg = DA9063_REG_V##regl_name##_A, \ + .vsel_mask = DA9063_V##regl_name##_MASK, \ + .mode_reg = DA9063_REG_V##regl_name##_A \ + +/* This array is directly indexed so must stay in numerical order */ +static const struct da9063_reg_info da9063_ldo_info[] = { + { DA9063_LDO(LDO1, 600, 20, 1860) }, + { DA9063_LDO(LDO2, 600, 20, 1860) }, + { DA9063_LDO(LDO3, 900, 20, 3440) }, + { DA9063_LDO(LDO4, 900, 20, 3440) }, + { DA9063_LDO(LDO5, 900, 50, 3600) }, + { DA9063_LDO(LDO6, 900, 50, 3600) }, + { DA9063_LDO(LDO7, 900, 50, 3600) }, + { DA9063_LDO(LDO8, 900, 50, 3600) }, + { DA9063_LDO(LDO9, 950, 50, 3600) }, + { DA9063_LDO(LDO10, 900, 50, 3600) }, + { DA9063_LDO(LDO11, 900, 50, 3600) }, +}; + +static struct dm_regulator_mode da9063_buck_modes[] = { + { .id = DA9063_BUCKMODE_SLEEP, + .register_value = DA9063_BUCK_MODE_SLEEP, .name = "SLEEP" }, + { .id = DA9063_BUCKMODE_SYNC, + .register_value = DA9063_BUCK_MODE_SYNC, .name = "SYNC" }, + { .id = DA9063_BUCKMODE_AUTO, + .register_value = DA9063_BUCK_MODE_AUTO, .name = "AUTO" }, +}; + +#define DA9063_BUCK(regl_name, dt_name, \ + min_mV, step_mV, max_mV, \ + min_mA, step_mA, max_mA, _ilim_reg) \ + .dt_node_name = dt_name, \ + .min_uV = (min_mV) * 1000, \ + .step_uV = (step_mV) * 1000, \ + .max_uV = (max_mV) * 1000, \ + .min_uA = (min_mA) * 1000, \ + .step_uA = (step_mA) * 1000, \ + .max_uA = (max_mA) * 1000, \ + .en_reg = DA9063_REG_##regl_name##_CONT, \ + .en_mask = DA9063_BUCK_EN, \ + .vsel_reg = DA9063_REG_V##regl_name##_A, \ + .vsel_mask = DA9063_VBUCK_MASK, \ + .mode_reg = DA9063_REG_##regl_name##_CFG, \ + .ilim_reg = DA9063_REG_BUCK_ILIM_##_ilim_reg, \ + .ilim_mask = DA9063_##regl_name##_ILIM_MASK + +static const struct da9063_reg_info da9063_buck_info[] = { + /* mV mA */ + { DA9063_BUCK(BCORE1, "bcore1", 300, 10, 1570, 500, 100, 2000, C) }, + { DA9063_BUCK(BCORE2, "bcore2", 300, 10, 1570, 500, 100, 2000, C) }, + { DA9063_BUCK(BPRO, "bpro", 530, 10, 1800, 500, 100, 2000, B) }, + { DA9063_BUCK(BMEM, "bmem", 800, 20, 3340, 1500, 100, 3000, A) }, + { DA9063_BUCK(BIO, "bio", 800, 20, 3340, 1500, 100, 3000, A) }, + { DA9063_BUCK(BPERI, "bperi", 800, 20, 3340, 1500, 100, 3000, B) }, +}; + +static int da9063_get_enable(struct udevice *dev) +{ + const struct da9063_priv *priv = dev->priv; + const struct da9063_reg_info *info = priv->reg_info; + int ret; + + ret = pmic_reg_read(dev->parent, info->en_reg); + if (ret < 0) + return ret; + + return ret & info->en_mask ? true : false; +} + +static int da9063_set_enable(struct udevice *dev, bool enable) +{ + const struct da9063_priv *priv = dev->priv; + const struct da9063_reg_info *info = priv->reg_info; + + return pmic_clrsetbits(dev->parent, info->en_reg, + info->en_mask, enable ? info->en_mask : 0); +} + +static int da9063_get_voltage(struct udevice *dev) +{ + const struct da9063_priv *priv = dev->priv; + const struct da9063_reg_info *info = priv->reg_info; + int ret; + + ret = pmic_reg_read(dev->parent, info->vsel_reg); + if (ret < 0) + return ret; + + return info->min_uV + (ret & info->vsel_mask) * info->step_uV; +} + +static int da9063_set_voltage(struct udevice *dev, int uV) +{ + const struct da9063_priv *priv = dev->priv; + const struct da9063_reg_info *info = priv->reg_info; + uint sel; + + if (uV < info->min_uV || uV > info->max_uV) + return -EINVAL; + + sel = (uV - info->min_uV) / info->step_uV; + + return pmic_clrsetbits(dev->parent, info->vsel_reg, + info->vsel_mask, sel); +} + +static const struct dm_regulator_mode + *da9063_find_mode_by_id(int id, + const struct dm_regulator_mode *modes, + uint mode_count) +{ + for (; mode_count; mode_count--) { + if (modes->id == id) + return modes; + modes++; + } + return NULL; +} + +static int ldo_get_mode(struct udevice *dev) +{ + const struct da9063_priv *priv = dev->priv; + const struct da9063_reg_info *info = priv->reg_info; + int val; + + val = pmic_reg_read(dev->parent, info->mode_reg); + if (val < 0) + return val; + + if (val & DA9063_LDO_SL) + return DA9063_LDOMODE_SLEEP; + else + return DA9063_LDOMODE_NORMAL; +} + +static int ldo_set_mode(struct udevice *dev, int mode_id) +{ + const struct da9063_priv *priv = dev->priv; + const struct da9063_reg_info *info = priv->reg_info; + const struct dm_regulator_mode *mode; + + mode = da9063_find_mode_by_id(mode_id, + da9063_ldo_modes, + ARRAY_SIZE(da9063_ldo_modes)); + if (!mode) + return -EINVAL; + + return pmic_clrsetbits(dev->parent, info->mode_reg, + DA9063_LDO_SL, mode->register_value); +} + +static int buck_get_mode(struct udevice *dev) +{ + const struct da9063_priv *priv = dev->priv; + const struct da9063_reg_info *info = priv->reg_info; + int i; + int val; + + val = pmic_reg_read(dev->parent, info->mode_reg); + if (val < 0) + return val; + + val &= DA9063_BUCK_MODE_MASK; + if (val == DA9063_BUCK_MODE_MANUAL) { + val = pmic_reg_read(dev->parent, info->vsel_reg); + if (val < 0) + return val; + + if (val & DA9063_BUCK_SL) + return DA9063_BUCKMODE_SLEEP; + else + return DA9063_BUCKMODE_SYNC; + } + + for (i = 0; i < ARRAY_SIZE(da9063_buck_modes); i++) { + if (da9063_buck_modes[i].register_value == val) + return da9063_buck_modes[i].id; + } + + return -EINVAL; +} + +static int buck_set_mode(struct udevice *dev, int mode_id) +{ + const struct da9063_priv *priv = dev->priv; + const struct da9063_reg_info *info = priv->reg_info; + const struct dm_regulator_mode *mode; + + mode = da9063_find_mode_by_id(mode_id, + da9063_buck_modes, + ARRAY_SIZE(da9063_buck_modes)); + if (!mode) + return -EINVAL; + + return pmic_clrsetbits(dev->parent, info->mode_reg, + DA9063_BUCK_MODE_MASK, mode->register_value); +} + +static int buck_get_current_limit(struct udevice *dev) +{ + const struct da9063_priv *priv = dev->priv; + const struct da9063_reg_info *info = priv->reg_info; + int val; + + val = pmic_reg_read(dev->parent, info->ilim_reg); + if (val < 0) + return val; + + val &= info->ilim_mask; + val >>= (ffs(info->ilim_mask) - 1); + + return info->min_uA + val * info->step_uA; +} + +static int buck_set_current_limit(struct udevice *dev, int uA) +{ + const struct da9063_priv *priv = dev->priv; + const struct da9063_reg_info *info = priv->reg_info; + int val; + + if (uA < info->min_uA || uA > info->max_uA) + return -EINVAL; + + val = (uA - info->min_uA) / info->step_uA; + val <<= (ffs(info->ilim_mask) - 1); + + return pmic_clrsetbits(dev->parent, info->ilim_reg, + info->ilim_mask, val); +} + +static int da9063_ldo_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + struct da9063_priv *priv = dev->priv; + + /* LDOs are named numerically in DT so can directly index */ + if (dev->driver_data < 1 || + dev->driver_data > ARRAY_SIZE(da9063_ldo_info)) + return -EINVAL; + priv->reg_info = &da9063_ldo_info[dev->driver_data - 1]; + + uc_pdata = dev_get_uclass_platdata(dev); + uc_pdata->type = REGULATOR_TYPE_LDO; + uc_pdata->mode = da9063_ldo_modes; + uc_pdata->mode_count = ARRAY_SIZE(da9063_ldo_modes); + + return 0; +} + +static int da9063_buck_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + struct da9063_priv *priv = dev->priv; + int i; + + /* Bucks have names rather than numbers so need to match with DT */ + for (i = 0; i < ARRAY_SIZE(da9063_buck_info); i++) { + const struct da9063_reg_info *info = &da9063_buck_info[i]; + + if (!strcmp(info->dt_node_name, dev->name)) { + priv->reg_info = info; + break; + } + } + if (!priv->reg_info) + return -ENODEV; + + uc_pdata = dev_get_uclass_platdata(dev); + uc_pdata->type = REGULATOR_TYPE_BUCK; + uc_pdata->mode = da9063_buck_modes; + uc_pdata->mode_count = ARRAY_SIZE(da9063_buck_modes); + + return 0; +} + +static const struct dm_regulator_ops da9063_ldo_ops = { + .get_value = da9063_get_voltage, + .set_value = da9063_set_voltage, + .get_enable = da9063_get_enable, + .set_enable = da9063_set_enable, + .get_mode = ldo_get_mode, + .set_mode = ldo_set_mode, +}; + +U_BOOT_DRIVER(da9063_ldo) = { + .name = DA9063_LDO_DRIVER, + .id = UCLASS_REGULATOR, + .ops = &da9063_ldo_ops, + .probe = da9063_ldo_probe, + .priv_auto_alloc_size = sizeof(struct da9063_priv), +}; + +static const struct dm_regulator_ops da9063_buck_ops = { + .get_value = da9063_get_voltage, + .set_value = da9063_set_voltage, + .get_enable = da9063_get_enable, + .set_enable = da9063_set_enable, + .get_mode = buck_get_mode, + .set_mode = buck_set_mode, + .get_current = buck_get_current_limit, + .set_current = buck_set_current_limit, +}; + +U_BOOT_DRIVER(da9063_buck) = { + .name = DA9063_BUCK_DRIVER, + .id = UCLASS_REGULATOR, + .ops = &da9063_buck_ops, + .probe = da9063_buck_probe, + .priv_auto_alloc_size = sizeof(struct da9063_priv), +}; diff --git a/include/power/da9063_pmic.h b/include/power/da9063_pmic.h index 9b0f76c04f..273a07ef41 100644 --- a/include/power/da9063_pmic.h +++ b/include/power/da9063_pmic.h @@ -305,4 +305,16 @@ #define DA9063_LDO_DRIVER "da9063_ldo" #define DA9063_BUCK_DRIVER "da9063_buck" +/* Regulator modes */ +enum { + DA9063_LDOMODE_SLEEP, + DA9063_LDOMODE_NORMAL +}; + +enum { + DA9063_BUCKMODE_SLEEP, + DA9063_BUCKMODE_SYNC, + DA9063_BUCKMODE_AUTO, +}; + #endif From b852cca8f0d863bd31ae72c5a5f241da73b8745f Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Tue, 14 Jan 2020 15:56:18 +0000 Subject: [PATCH 7/7] pmic: allow dump command for non contiguous register maps Some PMICs (such as the DA9063) have non-contiguous register maps. Attempting to read the non implemented registers returns an error rather than a dummy value which causes 'pmic dump' to terminate prematurely. Fix this by allowing the PMIC driver to return -ENODATA for such registers, which will then be displayed as '--' by pmic dump. Use a single error code rather than any error code so that we can distinguish between a hardware failure reading the PMIC and a non implemented register known to the driver. Signed-off-by: Martin Fuzzey --- cmd/pmic.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cmd/pmic.c b/cmd/pmic.c index e46d813a70..2400bfb601 100644 --- a/cmd/pmic.c +++ b/cmd/pmic.c @@ -95,7 +95,7 @@ static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) for (reg = 0; reg < pmic_reg_count(dev); reg++) { ret = pmic_reg_read(dev, reg); - if (ret < 0) { + if (ret < 0 && ret != -ENODATA) { printf("Can't read register: %d\n", reg); return failure(ret); } @@ -103,7 +103,15 @@ static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (!(reg % 16)) printf("\n0x%02x: ", reg); - printf(fmt, ret); + if (ret == -ENODATA) { + int i; + + for (i = 0; i < priv->trans_len; i++) + puts("--"); + puts(" "); + } else { + printf(fmt, ret); + } } printf("\n");