From 86e581a5609dc4b2876e5c3e2e458c91879b353c Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Fri, 5 Jan 2024 17:35:26 +0200 Subject: 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 --- board/htc/endeavoru/endeavoru-spl.c | 56 +++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/board/htc/endeavoru/endeavoru-spl.c b/board/htc/endeavoru/endeavoru-spl.c index 2525b50..3c4caff 100644 --- a/board/htc/endeavoru/endeavoru-spl.c +++ b/board/htc/endeavoru/endeavoru-spl.c @@ -9,7 +9,12 @@ * Svyatoslav Ryhel */ +#include +#include +#include #include +#include +#include #include #include @@ -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); + } +} -- cgit v1.1