summaryrefslogtreecommitdiff
path: root/board/htc
diff options
context:
space:
mode:
authorSvyatoslav Ryhel <clamor95@gmail.com>2024-01-05 17:35:26 +0200
committerSvyatoslav Ryhel <clamor95@gmail.com>2024-01-05 18:05:42 +0200
commit86e581a5609dc4b2876e5c3e2e458c91879b353c (patch)
tree8b5a38910083d84d78d38b7957ad0a9b3ea302c1 /board/htc
parent5c39fbfa134a28ae580a9d6768d36d7f5b964724 (diff)
downloadu-boot-86e581a5609dc4b2876e5c3e2e458c91879b353c.tar.gz
u-boot-86e581a5609dc4b2876e5c3e2e458c91879b353c.tar.bz2
u-boot-86e581a5609dc4b2876e5c3e2e458c91879b353c.zip
board: htc: endeavoru: add an early SPL RCM hook
Unlike all other supported Tegra devices and most known Tegra devices, the HTC One X has no hardware way to enter APX/RCM mode, which may lead to a dangerous situation when, if BCT is set correctly and the bootloader is faulty, the device will hang in a permanent brick state. Exiting from this state can be done only by disassembling the device and shortening the testpad to the ground. To prevent this or to minimize the probability of such an accident, it was proposed to add the RCM rebooting hook as early into SPL as possible since SPL is much more robust and has minimal changes that can break bootflow. gpio_early_init_uart() function was chosen as it is the earliest function exposed for setup by the device. Hook performs a check for volume up button state and triggers RCM if it is pressed. Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Diffstat (limited to 'board/htc')
-rw-r--r--board/htc/endeavoru/endeavoru-spl.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/board/htc/endeavoru/endeavoru-spl.c b/board/htc/endeavoru/endeavoru-spl.c
index 2525b50d3e..3c4caff806 100644
--- a/board/htc/endeavoru/endeavoru-spl.c
+++ b/board/htc/endeavoru/endeavoru-spl.c
@@ -9,7 +9,12 @@
* Svyatoslav Ryhel <clamor95@gmail.com>
*/
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/pinmux.h>
#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/board.h>
+#include <asm/arch-tegra/pmc.h>
#include <asm/arch-tegra/tegra_i2c.h>
#include <linux/delay.h>
@@ -30,6 +35,8 @@
#define TPS80032_SMPS1_CFG_STATE_DATA (0x0100 | TPS80032_SMPS1_CFG_STATE_REG)
#define TPS80032_SMPS2_CFG_STATE_DATA (0x0100 | TPS80032_SMPS2_CFG_STATE_REG)
+#define TEGRA_GPIO_PS0 144
+
void pmic_enable_cpu_vdd(void)
{
/* Set VDD_CORE to 1.200V. */
@@ -45,3 +52,52 @@ void pmic_enable_cpu_vdd(void)
tegra_i2c_ll_write(TPS80032_CTL1_I2C_ADDR, TPS80032_SMPS1_CFG_STATE_DATA);
udelay(10 * 1000);
}
+
+/*
+ * Unlike all other supported Tegra devices and most known Tegra devices, the
+ * HTC One X has no hardware way to enter APX/RCM mode, which may lead to a
+ * dangerous situation when, if BCT is set correctly and the bootloader is
+ * faulty, the device will hang in a permanent brick state. Exiting from this
+ * state can be done only by disassembling the device and shortening testpad
+ * to the ground.
+ *
+ * To prevent this or to minimize the probability of such an accident, it was
+ * proposed to add the RCM rebooting hook as early into SPL as possible since
+ * SPL is much more robust and has minimal changes that can break bootflow.
+ *
+ * gpio_early_init_uart() function was chosen as it is the earliest function
+ * exposed for setup by the device. Hook performs a check for volume up
+ * button state and triggers RCM if it is pressed.
+ */
+void gpio_early_init_uart(void)
+{
+ struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
+ struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(TEGRA_GPIO_PS0)];
+ u32 value;
+
+ /* Configure pinmux */
+ pinmux_set_func(PMUX_PINGRP_KB_ROW8_PS0, PMUX_FUNC_KBC);
+ pinmux_set_pullupdown(PMUX_PINGRP_KB_ROW8_PS0, PMUX_PULL_UP);
+ pinmux_tristate_disable(PMUX_PINGRP_KB_ROW8_PS0);
+ pinmux_set_io(PMUX_PINGRP_KB_ROW8_PS0, PMUX_PIN_INPUT);
+
+ /* Configure GPIO direction as input. */
+ value = readl(&bank->gpio_dir_out[GPIO_PORT(TEGRA_GPIO_PS0)]);
+ value &= ~(1 << GPIO_BIT(TEGRA_GPIO_PS0));
+ writel(value, &bank->gpio_dir_out[GPIO_PORT(TEGRA_GPIO_PS0)]);
+
+ /* Enable the pin as a GPIO */
+ value = readl(&bank->gpio_config[GPIO_PORT(TEGRA_GPIO_PS0)]);
+ value |= 1 << GPIO_BIT(TEGRA_GPIO_PS0);
+ writel(value, &bank->gpio_config[GPIO_PORT(TEGRA_GPIO_PS0)]);
+
+ /* Get GPIO value */
+ value = readl(&bank->gpio_in[GPIO_PORT(TEGRA_GPIO_PS0)]);
+ value = (value >> GPIO_BIT(TEGRA_GPIO_PS0)) & 1;
+
+ /* Enter RCM if button is pressed */
+ if (!value) {
+ tegra_pmc_writel(2, PMC_SCRATCH0);
+ tegra_pmc_writel(PMC_CNTRL_MAIN_RST, PMC_CNTRL);
+ }
+}