]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
board: htc: endeavoru: add an early SPL RCM hook
authorSvyatoslav Ryhel <clamor95@gmail.com>
Fri, 5 Jan 2024 15:35:26 +0000 (17:35 +0200)
committerSvyatoslav Ryhel <clamor95@gmail.com>
Fri, 5 Jan 2024 16:05:42 +0000 (18:05 +0200)
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>
board/htc/endeavoru/endeavoru-spl.c

index 2525b50d3e8a3d792411b6b7cb27065c0d1ab7a5..3c4caff80693b7e8d7ead627514b8fb4191f1d6d 100644 (file)
@@ -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);
+       }
+}