[U-Boot] [PATCH 2/5] imx: ventana: fix PMIC rails for IMX6SDL in ldobypass mode
Tim Harvey
tharvey at gateworks.com
Fri Jun 17 15:01:50 CEST 2016
The IMX6SDL has a VDD_SOC max of 1.21v when operating in ldo-bypass mode.
While the kernel technically should be in charge of setting the rails and
bypassing the internal LDO regulators if implementing ldo-bypass mode, it
is impossible to meet the VDD_SOC_IN min and max requirements while switching.
It has been found that exceeding the max of 1.21v in ldo-bypass mode
causes PCIe aborts hanging the system and not meeting the min of 1.275v
in ldo-enabled mode can produce other issues.
As a work-around we will examine the device-tree bindings during ft_board_setup
to determine if we are booting a configured for ldo-bypass and will
adjust the PMIC rails, and bypass the LDO's before booting the kernel.
Signed-off-by: Tim Harvey <tharvey at gateworks.com>
---
board/gateworks/gw_ventana/common.c | 103 +++++++++++++++++++++++---------
board/gateworks/gw_ventana/common.h | 3 +-
board/gateworks/gw_ventana/gw_ventana.c | 29 ++++++++-
3 files changed, 106 insertions(+), 29 deletions(-)
diff --git a/board/gateworks/gw_ventana/common.c b/board/gateworks/gw_ventana/common.c
index 929dde9..366ea93 100644
--- a/board/gateworks/gw_ventana/common.c
+++ b/board/gateworks/gw_ventana/common.c
@@ -856,7 +856,7 @@ void setup_board_gpio(int board, struct ventana_board_info *info)
}
}
-/* setup board specific PMIC */
+/* setup initial board specific PMIC */
void setup_pmic(void)
{
struct pmic *p;
@@ -894,32 +894,81 @@ void setup_pmic(void)
p = pmic_get("LTC3676_PMIC");
if (p && !pmic_probe(p)) {
puts("PMIC: LTC3676\n");
- /*
- * set board-specific scalar for max CPU frequency
- * per CPU based on the LDO enabled Operating Ranges
- * defined in the respective IMX6DQ and IMX6SDL
- * datasheets. The voltage resulting from the R1/R2
- * feedback inputs on Ventana is 1308mV. Note that this
- * is a bit shy of the Vmin of 1350mV in the datasheet
- * for LDO enabled mode but is as high as we can go.
- *
- * We will rely on an OS kernel driver to properly
- * regulate these per CPU operating point and use LDO
- * bypass mode when using the higher frequency
- * operating points to compensate as LDO bypass mode
- * allows the rails be 125mV lower.
- */
- /* mask PGOOD during SW1 transition */
- pmic_reg_write(p, LTC3676_DVB1B,
- 0x1f | LTC3676_PGOOD_MASK);
- /* set SW1 (VDD_SOC) */
- pmic_reg_write(p, LTC3676_DVB1A, 0x1f);
-
- /* mask PGOOD during SW3 transition */
- pmic_reg_write(p, LTC3676_DVB3B,
- 0x1f | LTC3676_PGOOD_MASK);
- /* set SW3 (VDD_ARM) */
- pmic_reg_write(p, LTC3676_DVB3A, 0x1f);
+
+ /* Mask PGOOD during voltage transitions */
+ pmic_reg_read(p, LTC3676_DVB1B, ®);
+ reg |= LTC3676_PGOOD_MASK;
+ pmic_reg_write(p, LTC3676_DVB1B, reg);
+ pmic_reg_read(p, LTC3676_DVB3B, ®);
+ reg |= LTC3676_PGOOD_MASK;
+ pmic_reg_write(p, LTC3676_DVB3B, reg);
+ }
+ }
+}
+
+/*
+ * adjust PMIC rails depending on ldo-bypass or ldo-enabled mode:
+ *
+ * Because the IMX6 VDD_ARM and VDD_SOC rails have minimum values in
+ * ldo-enabled mode which can exceed the maximum values when in
+ * ldo-bypass mode we must alter the rails depending on which mode is desired.
+ *
+ * Because ldo mode is very dependent on kernel support we can examine
+ * the device-tree to decide if the kernel uses ldo-bypass mode.
+ *
+ * ldo-bypass mode min/max values at 800MHz:
+ * IMX6DQ: VDDARM: 1.150v - 1.30v
+ * IMX6DQ: VDDSOC: 1.150v - 1.30v
+ * IMX6SDL: VDDARM: 1.150v - 1.30v
+ * IMX6SDL: VDDSOC: 1.150v - 1.21v <--- exceeding this causes PCIe aborts
+ *
+ * ldo-enabled mode min/max values at 800Mhz are 125mV above the ldo-bypass
+ * values.
+ */
+int adjust_pmic(char ldo_enabled)
+{
+ struct pmic *p;
+ u32 reg;
+
+ debug("%s ldo_%s\n", __func__, ldo_enabled ? "enabled" : "bypass");
+ i2c_set_bus_num(CONFIG_I2C_PMIC);
+
+ /* configure LTC3676 PMIC */
+ if (!i2c_probe(CONFIG_POWER_LTC3676_I2C_ADDR)) {
+ p = pmic_get("LTC3676_PMIC");
+ if (!p)
+ return 0;
+
+ debug("Adjusting %s for ldo-%sabled\n", p->name,
+ ldo_enabled ? "en" : "dis");
+
+ /*
+ * if ldo_enabled mode bump the default 1.185v rails
+ * to 1.308v max
+ */
+ if (ldo_enabled) {
+ /* SW1: VDD_SOC */
+ pmic_reg_read(p, LTC3676_DVB1A, ®);
+ reg |= 0x1f;
+ pmic_reg_write(p, LTC3676_DVB1A, reg);
+ pmic_reg_read(p, LTC3676_DVB1B, ®);
+ reg |= 0x1f;
+ pmic_reg_write(p, LTC3676_DVB1B, reg);
+ /* SW3: VDD_ARM */
+ pmic_reg_read(p, LTC3676_DVB3A, ®);
+ reg |= 0x1f;
+ pmic_reg_write(p, LTC3676_DVB3A, reg);
+ pmic_reg_read(p, LTC3676_DVB3B, ®);
+ reg |= 0x1f;
+ pmic_reg_write(p, LTC3676_DVB3B, reg);
+ } else {
+ /* set max value to bypass FET's */
+ debug("bypassing LDO's\n");
+ set_ldo_voltage(LDO_ARM, 1500);
+ set_ldo_voltage(LDO_PU, 1500);
+ set_ldo_voltage(LDO_SOC, 1500);
}
}
+
+ return 1;
}
diff --git a/board/gateworks/gw_ventana/common.h b/board/gateworks/gw_ventana/common.h
index d037767..3bea94b 100644
--- a/board/gateworks/gw_ventana/common.h
+++ b/board/gateworks/gw_ventana/common.h
@@ -87,8 +87,9 @@ extern struct ventana gpio_cfg[GW_UNKNOWN];
void setup_ventana_i2c(void);
/* configure uart iomux */
void setup_iomux_uart(void);
-/* conifgure PMIC */
+/* configure PMIC */
void setup_pmic(void);
+int adjust_pmic(char ldo_enabled);
/* configure gpio iomux/defaults */
void setup_iomux_gpio(int board, struct ventana_board_info *);
/* late setup of GPIO (configuration per baseboard and env) */
diff --git a/board/gateworks/gw_ventana/gw_ventana.c b/board/gateworks/gw_ventana/gw_ventana.c
index 82313e8..a69549b 100644
--- a/board/gateworks/gw_ventana/gw_ventana.c
+++ b/board/gateworks/gw_ventana/gw_ventana.c
@@ -802,6 +802,24 @@ static inline void ft_delprop_path(void *blob, const char *path,
}
}
+/* return the 'compatible' property of a cpu regulator */
+static inline const char *get_cpureg(void *blob, const char *name)
+{
+ const u32 *handle = NULL;
+ int i, len = 0;
+ const char *s = NULL;
+
+ i = fdt_path_offset(blob, "/cpus/cpu at 0");
+ if (i)
+ handle = fdt_getprop(blob, i, name, NULL);
+ if (handle)
+ i = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*handle));
+ if (i)
+ s = (char *)fdt_getprop(blob, i, "compatible", &len);
+ debug("%s:%s\n", name, s);
+ return s;
+}
+
/*
* called prior to booting kernel or by 'fdt boardsetup' command
*
@@ -822,7 +840,7 @@ int ft_board_setup(void *blob, bd_t *bd)
const char *model = getenv("model");
const char *display = getenv("display");
int i;
- char rev = 0;
+ char rev = 0, ldo_enabled = 0;
/* determine board revision */
for (i = sizeof(ventana_info.model) - 1; i > 0; i--) {
@@ -976,6 +994,15 @@ int ft_board_setup(void *blob, bd_t *bd)
"no-1-8-v");
}
+ /* Determine if we have a kernel using the internal IMX LDO */
+ if (!strcmp("fsl,anatop-regulator", get_cpureg(blob, "arm-supply")) &&
+ !strcmp("fsl,anatop-regulator", get_cpureg(blob, "pu-supply")) &&
+ !strcmp("fsl,anatop-regulator", get_cpureg(blob, "soc-supply")))
+ ldo_enabled = 1;
+ printf(" Config LDO-%s mode\n", ldo_enabled ? "enabled" : "bypass");
+ /* Adjust pmic rails depending on LDO enabled vs bypass */
+ adjust_pmic(ldo_enabled);
+
/*
* Peripheral Config:
* remove nodes by alias path if EEPROM config tells us the
--
1.9.1
More information about the U-Boot
mailing list