From 3b08379cb6e841c934ded3db3c70a3d0906cea65 Mon Sep 17 00:00:00 2001 From: AppaRao Puli Date: Thu, 20 Jun 2019 18:11:43 +0530 Subject: [PATCH] Manufacturing mode physical presence detection Support for physical presence of manufacturing mode added. Front panel power button press for 15 seconds will be detected and marked as special mode for manufacturing request. There will be Status LED blink for 10 seconds to do the physical indication to the user. This indicates the user that he has pressed power button long enough for manufacturing mode detection. Tested: 1. Verified by holding the power button when u-boot boots for 15 seconds, and confirmed that bootargs passed to linux has special=mfg string and status led blink physical indication has been provided 2. Verified in normal condition special=mfg string is not passed and no physical indication has been provided Signed-off-by: Richard Marian Thomaiyar Signed-off-by: AppaRao Puli Signed-off-by: Jae Hyun Yoo --- board/aspeed/ast2600_intel/intel.c | 87 ++++++++++++++++++++++++++++-- common/autoboot.c | 12 ++++- 2 files changed, 95 insertions(+), 4 deletions(-) diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c index f45b9d06a3f5..7664ac0ddfc6 100644 --- a/board/aspeed/ast2600_intel/intel.c +++ b/board/aspeed/ast2600_intel/intel.c @@ -8,6 +8,8 @@ #include #include +#define SYS_PWR_RESET_FLAG BIT(0) /* from scu_info.c */ + /* use GPIOC0 on intel boards */ #define FFUJ_GPIO "gpio@1e78000016" @@ -60,6 +62,26 @@ int gpio_abort(void) return value <= 0 ? 0 : 1; } +int read_frontpanel_power_button(void) +{ +#define FP_PWRBTN_GPIO "gpio@1e780000122" /* GPIOP2 */ + struct gpio_desc desc; + int ret; + + ret = dm_gpio_lookup_name(FP_PWRBTN_GPIO, &desc); + if (ret) + return ret; + ret = dm_gpio_request(&desc, "fp_pwrbtn"); + if (ret) + return ret; + ret = dm_gpio_set_dir_flags(&desc, GPIOD_ACTIVE_LOW); + if (ret) + return ret; + ret = dm_gpio_get_value(&desc); + dm_gpio_free(desc.dev, &desc); + return ret; +} + #define SCU_BASE 0x1E6E2000 #define SCU_338 0x338 //Generate UART 24 MHz Reference from UXCLK #define SCU_33C 0x33c //Generate UART 24 MHz Reference from HUXCLK @@ -119,6 +141,10 @@ static void gpio_passthru_init(void) SCU_BASE | SCU_418); } +void board_pre_abort_autoboot(void) +{ +} + #define AST_LPC_BASE 0x1e789000 #define LPC_SNOOP_ADDR 0x80 #define HICR5 0x080 /* Host Interface Control Register 5 */ @@ -301,8 +327,6 @@ int board_early_init_f(void) set_gpio_default_state(); - gpio_passthru_init(); - port80h_snoop_init(); sgpio_init(); @@ -389,6 +413,56 @@ static void update_bootargs_cmd(const char *key, const char *value) free(buf); } +static bool is_mfg_mode_phy_req(void) +{ + /* + * Assume mfg mode physical request is made, if power button + * is pressed continously for 15 seconds, indicate the + * same in bootargs + */ + const uint32_t delay_in_ms = 100; + const uint32_t read_count = ((15 * 1000) / delay_in_ms); + const uint32_t delay_for_indication = 2 * 1000; + uint32_t count; +#ifdef CONFIG_LED_BLINK + struct udevice *dev; + int ret; +#endif + + for (count = 0; count < read_count; ++count) { + if (read_frontpanel_power_button() != 1) + return false; + + mdelay(delay_in_ms); + } + + printf("MFG mode is requested.\n"); + +#ifdef CONFIG_LED_BLINK + ret = led_get_by_label("green", &dev); + if (!ret) { + led_set_period(dev, 160); + } +#endif + + /* + * Delay up to 15 seconds until the power button is released to prevent + * unintentional power button overriding to PCH through GPIO + * pass-through. + */ + for (count = 0; count < read_count; ++count) { + if (read_frontpanel_power_button() != 1) + break; + + mdelay(delay_in_ms); + } + /* Keep the indication at least for 2 seconds */ + if (delay_in_ms * count < delay_for_indication) + mdelay(delay_for_indication - (delay_in_ms * count)); + + return true; +} + extern void espi_init(void); extern void kcs_init(void); extern void timer_enable(int n, u32 interval_us, interrupt_handler_t *handler, @@ -414,8 +488,15 @@ int board_late_init(void) snprintf(value, sizeof(value), "0x%x", gd->reset_reason); update_bootargs_cmd("resetreason", value); - if (read_ffuj()) + /* Update the special mode in bootargs */ + if (gd->reset_reason & SYS_PWR_RESET_FLAG && is_mfg_mode_phy_req()) + update_bootargs_cmd("special", "mfg"); + + gpio_passthru_init(); + + if (read_ffuj()) { kcs_init(); + } return 0; } diff --git a/common/autoboot.c b/common/autoboot.c index 5e69000b848b..8a9978042386 100644 --- a/common/autoboot.c +++ b/common/autoboot.c @@ -261,13 +261,19 @@ int gpio_abort(void) return 0; } +/* Allow for board specific config when we check abort condition */ +__weak void board_pre_abort_autoboot(void) +{ + /* please define board specific board_pre_abort_autoboot() */ +} + static int abortboot(int bootdelay) { int abort = 0; abort = gpio_abort(); if (abort) - return abort; + goto exit; if (bootdelay >= 0) abort = __abortboot(bootdelay); @@ -277,6 +283,10 @@ static int abortboot(int bootdelay) gd->flags &= ~GD_FLG_SILENT; #endif +exit: + if (abort) + board_pre_abort_autoboot(); + return abort; } -- 2.17.1