From 2226dea415e2003b136d0ac32a48f779b7058e7b Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Fri, 22 May 2020 14:22:37 +0300 Subject: meta-nicole: u-boot: add bmc position support This brings: - GPIO support in u-boot - BMC position is determined by the GPIOE1 and stored as a boot argument. (From meta-yadro rev: 1b68cd934fe58ce3c33b272b45497d2a1b4e35e6) Change-Id: Ieaf5bda2267b533327618330760431e66224092a End-User-Impact: In the u-boot shell now available `gpio` command Signed-off-by: Alexander Filippov Signed-off-by: Andrew Geissler --- .../0001-Add-system-reset-status-support.patch | 146 +++--- .../files/0003-aspeed-add-gpio-support.patch | 512 +++++++++++++++++++++ .../0004-aspeed-add-bmc-position-support.patch | 61 +++ .../recipes-bsp/u-boot/u-boot-aspeed_%.bbappend | 2 + 4 files changed, 660 insertions(+), 61 deletions(-) create mode 100644 meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0003-aspeed-add-gpio-support.patch create mode 100644 meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0004-aspeed-add-bmc-position-support.patch (limited to 'meta-yadro/meta-nicole') diff --git a/meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0001-Add-system-reset-status-support.patch b/meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0001-Add-system-reset-status-support.patch index 4daa354d6..d1cc9d9a6 100644 --- a/meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0001-Add-system-reset-status-support.patch +++ b/meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0001-Add-system-reset-status-support.patch @@ -1,4 +1,4 @@ -From cf39fde2c1cfb55aa756bfb551c4087ba2fd4b6c Mon Sep 17 00:00:00 2001 +From 1c5b450a068583f2407767451ef636d0661071da Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Tue, 7 Apr 2020 16:45:41 +0300 Subject: [PATCH] Add system reset status support @@ -11,27 +11,17 @@ and save the reset reasons into kernel command line, for applications to query. Signed-off-by: Alexander Filippov - --- - arch/arm/include/asm/arch-aspeed/ast_g5_platform.h | 1 + - arch/arm/include/asm/arch-aspeed/ast_scu.h | 2 +- - arch/arm/mach-aspeed/ast-scu.c | 6 +- - board/aspeed/ast-g5/ast-g5.c | 98 ++++++++++++++++++++++ - 4 files changed, 105 insertions(+), 2 deletions(-) + arch/arm/include/asm/arch-aspeed/ast_scu.h | 2 +- + arch/arm/include/asm/arch-aspeed/platform.h | 2 + + arch/arm/mach-aspeed/Makefile | 1 + + arch/arm/mach-aspeed/ast-late-init.c | 114 ++++++++++++++++++++ + arch/arm/mach-aspeed/ast-scu.c | 6 +- + 5 files changed, 123 insertions(+), 2 deletions(-) + create mode 100644 arch/arm/mach-aspeed/ast-late-init.c -diff --git a/arch/arm/include/asm/arch-aspeed/ast_g5_platform.h b/arch/arm/include/asm/arch-aspeed/ast_g5_platform.h -index 4210873..d2a4268cd 100644 ---- a/arch/arm/include/asm/arch-aspeed/ast_g5_platform.h -+++ b/arch/arm/include/asm/arch-aspeed/ast_g5_platform.h -@@ -188,5 +188,6 @@ - #define AST_FORMATTER_MEM_SIZE 0xC00000 /* 12MB */ - #define AST_FORMATTER_MEM_BASE (AST_H264_MEM_BASE + AST_H264_MEM_SIZE) - -+#define CONFIG_BOARD_LATE_INIT 1 /* Call board_late_init */ - - #endif diff --git a/arch/arm/include/asm/arch-aspeed/ast_scu.h b/arch/arm/include/asm/arch-aspeed/ast_scu.h -index dcbc673..b428f38 100644 +index dcbc6730d4..b428f386d6 100644 --- a/arch/arm/include/asm/arch-aspeed/ast_scu.h +++ b/arch/arm/include/asm/arch-aspeed/ast_scu.h @@ -29,7 +29,7 @@ @@ -43,48 +33,43 @@ index dcbc673..b428f38 100644 extern void ast_scu_security_info(void); extern u32 ast_scu_revision_id(void); extern u32 ast_scu_get_vga_memsize(void); -diff --git a/arch/arm/mach-aspeed/ast-scu.c b/arch/arm/mach-aspeed/ast-scu.c -index 12de9b8..5afd379 100644 ---- a/arch/arm/mach-aspeed/ast-scu.c -+++ b/arch/arm/mach-aspeed/ast-scu.c -@@ -482,22 +482,26 @@ void ast_scu_security_info(void) - } - } - --void ast_scu_sys_rest_info(void) -+u32 ast_scu_sys_rest_info(void) - { - u32 rest = ast_scu_read(AST_SCU_SYS_CTRL); - - if (rest & SCU_SYS_EXT_RESET_FLAG) { - printf("RST : External\n"); - ast_scu_write(SCU_SYS_EXT_RESET_FLAG, AST_SCU_SYS_CTRL); -+ rest = SCU_SYS_EXT_RESET_FLAG; - } else if (rest & SCU_SYS_WDT_RESET_FLAG) { - printf("RST : Watchdog\n"); - ast_scu_write(SCU_SYS_WDT_RESET_FLAG, AST_SCU_SYS_CTRL); -+ rest = SCU_SYS_WDT_RESET_FLAG; - } else if (rest & SCU_SYS_PWR_RESET_FLAG) { - printf("RST : Power On\n"); - ast_scu_write(SCU_SYS_PWR_RESET_FLAG, AST_SCU_SYS_CTRL); -+ rest = SCU_SYS_PWR_RESET_FLAG; - } else { - printf("RST : CLK en\n"); - } -+ return rest; - } +diff --git a/arch/arm/include/asm/arch-aspeed/platform.h b/arch/arm/include/asm/arch-aspeed/platform.h +index 1c02914fcb..b9207c492f 100644 +--- a/arch/arm/include/asm/arch-aspeed/platform.h ++++ b/arch/arm/include/asm/arch-aspeed/platform.h +@@ -31,4 +31,6 @@ + #err "No define for platform.h" + #endif - u32 ast_scu_get_vga_memsize(void) -diff --git a/board/aspeed/ast-g5/ast-g5.c b/board/aspeed/ast-g5/ast-g5.c -index 12496ce..42d7496 100644 ---- a/board/aspeed/ast-g5/ast-g5.c -+++ b/board/aspeed/ast-g5/ast-g5.c -@@ -105,3 +105,104 @@ void hw_watchdog_reset(void) - writel(0x4755, AST_WDT2_BASE + 0x08); - } - #endif /* CONFIG_WATCHDOG */ ++#define CONFIG_BOARD_LATE_INIT 1 /* Call board_late_init */ ++ + #endif +diff --git a/arch/arm/mach-aspeed/Makefile b/arch/arm/mach-aspeed/Makefile +index 7d8930beb9..4af2a7c96a 100644 +--- a/arch/arm/mach-aspeed/Makefile ++++ b/arch/arm/mach-aspeed/Makefile +@@ -15,3 +15,4 @@ obj-y += timer.o reset.o cpuinfo.o ast-scu.o ast-ahbc.o ast-sdmc.o + obj-$(CONFIG_AST_SPI_NOR) += flash.o + obj-$(CONFIG_ARCH_AST2500) += platform_g5.o + obj-$(CONFIG_ARCH_AST2400) += platform_g4.o ++obj-$(CONFIG_BOARD_LATE_INIT) += ast-late-init.o +diff --git a/arch/arm/mach-aspeed/ast-late-init.c b/arch/arm/mach-aspeed/ast-late-init.c +new file mode 100644 +index 0000000000..5646c0e882 +--- /dev/null ++++ b/arch/arm/mach-aspeed/ast-late-init.c +@@ -0,0 +1,114 @@ ++/* ++ * SPDX-License-Identifier: Apache-2.0 ++ * Copyright (C) 2020 YADRO. ++ */ ++ ++#include ++ ++#include ++#include ++#include + -+#ifdef CONFIG_BOARD_LATE_INIT +static void update_bootargs_cmd(const char *key, const char *value) +{ + int buf_len; @@ -158,7 +143,7 @@ index 12496ce..42d7496 100644 + free(buf); +} + -+int board_late_init(void) ++static void set_reset_reason(void) +{ + u32 reset_reason = ast_scu_sys_rest_info(); + @@ -180,7 +165,46 @@ index 12496ce..42d7496 100644 + snprintf(value, sizeof(value) - 1, "0x%x", reset_reason); + update_bootargs_cmd("resetreason", value); + } ++} ++ ++int board_late_init(void) ++{ ++ set_reset_reason(); + + return 0; +} -+#endif /* CONFIG_BOARD_LATE_INIT */ +diff --git a/arch/arm/mach-aspeed/ast-scu.c b/arch/arm/mach-aspeed/ast-scu.c +index 12de9b8036..5afd3793e3 100644 +--- a/arch/arm/mach-aspeed/ast-scu.c ++++ b/arch/arm/mach-aspeed/ast-scu.c +@@ -482,22 +482,26 @@ void ast_scu_security_info(void) + } + } + +-void ast_scu_sys_rest_info(void) ++u32 ast_scu_sys_rest_info(void) + { + u32 rest = ast_scu_read(AST_SCU_SYS_CTRL); + + if (rest & SCU_SYS_EXT_RESET_FLAG) { + printf("RST : External\n"); + ast_scu_write(SCU_SYS_EXT_RESET_FLAG, AST_SCU_SYS_CTRL); ++ rest = SCU_SYS_EXT_RESET_FLAG; + } else if (rest & SCU_SYS_WDT_RESET_FLAG) { + printf("RST : Watchdog\n"); + ast_scu_write(SCU_SYS_WDT_RESET_FLAG, AST_SCU_SYS_CTRL); ++ rest = SCU_SYS_WDT_RESET_FLAG; + } else if (rest & SCU_SYS_PWR_RESET_FLAG) { + printf("RST : Power On\n"); + ast_scu_write(SCU_SYS_PWR_RESET_FLAG, AST_SCU_SYS_CTRL); ++ rest = SCU_SYS_PWR_RESET_FLAG; + } else { + printf("RST : CLK en\n"); + } ++ return rest; + } + + u32 ast_scu_get_vga_memsize(void) +-- +2.25.4 + diff --git a/meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0003-aspeed-add-gpio-support.patch b/meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0003-aspeed-add-gpio-support.patch new file mode 100644 index 000000000..2e825c8cd --- /dev/null +++ b/meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0003-aspeed-add-gpio-support.patch @@ -0,0 +1,512 @@ +From 9bb68d8820480519e8b331f7a8b866b8718ad7fd Mon Sep 17 00:00:00 2001 +From: Alexander Filippov +Date: Tue, 19 May 2020 18:55:41 +0300 +Subject: [PATCH] aspeed: add gpio support + +This is an initial support for the parallel GPIO pins directly connected +to the AHB on the Aspeed 2400/2500. + +This brings the functions and a shell command to manipulate the GPIO +state. The GPIO value reading and writing work in non interrupt mode +only. + +Signed-off-by: Alexander Filippov +--- + arch/arm/include/asm/arch-aspeed/gpio.h | 65 ++++ + arch/arm/include/asm/arch-aspeed/platform.h | 1 + + drivers/gpio/Makefile | 2 + + drivers/gpio/aspeed_gpio.c | 386 ++++++++++++++++++++ + 4 files changed, 454 insertions(+) + create mode 100644 arch/arm/include/asm/arch-aspeed/gpio.h + create mode 100644 drivers/gpio/aspeed_gpio.c + +diff --git a/arch/arm/include/asm/arch-aspeed/gpio.h b/arch/arm/include/asm/arch-aspeed/gpio.h +new file mode 100644 +index 0000000000..c63987e917 +--- /dev/null ++++ b/arch/arm/include/asm/arch-aspeed/gpio.h +@@ -0,0 +1,65 @@ ++/* ++ * SPDX-License-Identifier: GPL-2.0+ ++ * Copyright (C) 2020 YADRO. ++ */ ++#ifndef _ASPEED_GPIO_H ++#define _ASPEED_GPIO_H ++ ++#define ASPEED_GPIO_PORT_A 0 ++#define ASPEED_GPIO_PORT_B 1 ++#define ASPEED_GPIO_PORT_C 2 ++#define ASPEED_GPIO_PORT_D 3 ++#define ASPEED_GPIO_PORT_E 4 ++#define ASPEED_GPIO_PORT_F 5 ++#define ASPEED_GPIO_PORT_G 6 ++#define ASPEED_GPIO_PORT_H 7 ++#define ASPEED_GPIO_PORT_I 8 ++#define ASPEED_GPIO_PORT_J 9 ++#define ASPEED_GPIO_PORT_K 10 ++#define ASPEED_GPIO_PORT_L 11 ++#define ASPEED_GPIO_PORT_M 12 ++#define ASPEED_GPIO_PORT_N 13 ++#define ASPEED_GPIO_PORT_O 14 ++#define ASPEED_GPIO_PORT_P 15 ++#define ASPEED_GPIO_PORT_Q 16 ++#define ASPEED_GPIO_PORT_R 17 ++#define ASPEED_GPIO_PORT_S 18 ++#define ASPEED_GPIO_PORT_T 19 ++#define ASPEED_GPIO_PORT_U 20 ++#define ASPEED_GPIO_PORT_V 21 ++#define ASPEED_GPIO_PORT_W 22 ++#define ASPEED_GPIO_PORT_X 23 ++#define ASPEED_GPIO_PORT_Y 24 ++#define ASPEED_GPIO_PORT_Z 25 ++#define ASPEED_GPIO_PORT_AA 26 ++#define ASPEED_GPIO_PORT_AB 27 ++#define ASPEED_GPIO_PORT_AC 28 ++ ++#define ASPEED_GPIO_PORT_SHIFT 3 ++#define ASPEED_GPIO_PIN_MASK 0x7 ++#define ASPEED_GPIO(port, pin) \ ++ ((ASPEED_GPIO_PORT_##port << ASPEED_GPIO_PORT_SHIFT) | \ ++ (pin & ASPEED_GPIO_PIN_MASK)) ++ ++/* Direction values */ ++#define ASPEED_GPIO_INPUT 0 ++#define ASPEED_GPIO_OUTPUT 1 ++ ++/* Trigger values */ ++#define ASPEED_GPIO_FALLING_EDGE 0 ++#define ASPEED_GPIO_RISING_EDGE 1 ++#define ASPEED_GPIO_LOW_LEVEL 2 ++#define ASPEED_GPIO_HIGH_LEVEL 3 ++#define ASPEED_GPIO_DUAL_EDGE 4 ++ ++/* Debounce values */ ++#define ASPEED_GPIO_DEBOUNCE_NONE 0 ++#define ASPEED_GPIO_DEBOUNCE_1 1 ++#define ASPEED_GPIO_DEBOUNCE_2 2 ++#define ASPEED_GPIO_DEBOUNCE_3 3 ++ ++#define gpio_status() gpio_info() ++ ++extern void gpio_info(void); ++ ++#endif /* #ifndef _ASPEED_GPIO_H */ +diff --git a/arch/arm/include/asm/arch-aspeed/platform.h b/arch/arm/include/asm/arch-aspeed/platform.h +index b9207c492f..0a05a7a7a0 100644 +--- a/arch/arm/include/asm/arch-aspeed/platform.h ++++ b/arch/arm/include/asm/arch-aspeed/platform.h +@@ -32,5 +32,6 @@ + #endif + + #define CONFIG_BOARD_LATE_INIT 1 /* Call board_late_init */ ++#define CONFIG_CMD_GPIO 1 /* Enable gpio command in shell */ + + #endif +diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile +index 792d19186a..5f043e07ce 100644 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -14,6 +14,8 @@ obj-$(CONFIG_DM_GPIO) += gpio-uclass.o + obj-$(CONFIG_DM_PCA953X) += pca953x_gpio.o + obj-$(CONFIG_DM_74X164) += 74x164_gpio.o + ++obj-$(CONFIG_ARCH_AST2400) += aspeed_gpio.o ++obj-$(CONFIG_ARCH_AST2500) += aspeed_gpio.o + obj-$(CONFIG_AT91_GPIO) += at91_gpio.o + obj-$(CONFIG_ATMEL_PIO4) += atmel_pio4.o + obj-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o +diff --git a/drivers/gpio/aspeed_gpio.c b/drivers/gpio/aspeed_gpio.c +new file mode 100644 +index 0000000000..dc07f5a520 +--- /dev/null ++++ b/drivers/gpio/aspeed_gpio.c +@@ -0,0 +1,386 @@ ++/* ++ * SPDX-License-Identifier: GPL-2.0+ ++ * Copyright (C) 2020 YADRO. ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++typedef struct _ast_gpio_regs ++{ ++ uint32_t base; /* data and direction registers */ ++ uint32_t intcfg; /* interrupt config */ ++ uint32_t debounce; /* debounce config */ ++ uint32_t cmdsrc; /* command source config */ ++ uint32_t data; /* data read register */ ++} ast_gpio_regs_t; ++ ++static ast_gpio_regs_t ast_gpio_regs[] = { ++ /* A/B/C/D */ ++ {AST_GPIO_BASE + 0x0000, AST_GPIO_BASE + 0x0008, AST_GPIO_BASE + 0x0040, ++ AST_GPIO_BASE + 0x0060, AST_GPIO_BASE + 0x00C0}, ++ /* E/F/G/H */ ++ {AST_GPIO_BASE + 0x0020, AST_GPIO_BASE + 0x0028, AST_GPIO_BASE + 0x0048, ++ AST_GPIO_BASE + 0x0068, AST_GPIO_BASE + 0x00C4}, ++ /* I/J/K/L */ ++ {AST_GPIO_BASE + 0x0070, AST_GPIO_BASE + 0x0098, AST_GPIO_BASE + 0x00B0, ++ AST_GPIO_BASE + 0x0090, AST_GPIO_BASE + 0x00C8}, ++ /* M/N/O/P */ ++ {AST_GPIO_BASE + 0x0078, AST_GPIO_BASE + 0x00E8, AST_GPIO_BASE + 0x0100, ++ AST_GPIO_BASE + 0x00E0, AST_GPIO_BASE + 0x00CC}, ++ /* Q/R/S/T */ ++ {AST_GPIO_BASE + 0x0080, AST_GPIO_BASE + 0x0118, AST_GPIO_BASE + 0x0130, ++ AST_GPIO_BASE + 0x0110, AST_GPIO_BASE + 0x00D0}, ++ /* U/V/W/X */ ++ {AST_GPIO_BASE + 0x0088, AST_GPIO_BASE + 0x0148, AST_GPIO_BASE + 0x0160, ++ AST_GPIO_BASE + 0x0140, AST_GPIO_BASE + 0x00D4}, ++ /* Y/Z/AA/AB */ ++ {AST_GPIO_BASE + 0x01E0, AST_GPIO_BASE + 0x0178, AST_GPIO_BASE + 0x0190, ++ AST_GPIO_BASE + 0x0170, AST_GPIO_BASE + 0x00D8}, ++ /* AC */ ++ {AST_GPIO_BASE + 0x01E8, AST_GPIO_BASE + 0x01A8, AST_GPIO_BASE + 0x01C0, ++ AST_GPIO_BASE + 0x01A0, AST_GPIO_BASE + 0x00DC}, ++}; ++ ++#define AST_GPIO_PINS_PER_PORT 8 ++#define AST_GPIO_PORTS_PER_REGISTER 4 ++ ++#define AST_GPIO_PORT(gpio) (gpio >> ASPEED_GPIO_PORT_SHIFT) ++#define AST_GPIO_PIN(gpio) (gpio & ASPEED_GPIO_PIN_MASK) ++#define AST_GPIO_SHIFT(gpio) \ ++ ((AST_GPIO_PORT(gpio) % AST_GPIO_PORTS_PER_REGISTER) * \ ++ AST_GPIO_PINS_PER_PORT + \ ++ AST_GPIO_PIN(gpio)) ++ ++#define AST_GPIO_REG_INDEX(gpio) \ ++ (AST_GPIO_PORT(gpio) / AST_GPIO_PORTS_PER_REGISTER) ++ ++/** ++ * @return Pointer to corresponding item from ast_gpio_regs table. ++ */ ++#define AST_GPIO_REGS(gpio) \ ++ ((AST_GPIO_REG_INDEX(gpio) < ARRAY_SIZE(ast_gpio_regs)) \ ++ ? (ast_gpio_regs + AST_GPIO_REG_INDEX(gpio)) \ ++ : NULL) ++ ++/** ++ * @brief Set a corresponding bit in specified register. ++ * ++ * @param val - Required bit value ++ * @param base - Register address ++ * @param shift - Bit index. ++ */ ++#define AST_GPIO_WRITE(val, base, shift) \ ++ writel(((val) ? readl(base) | (1 << (shift)) \ ++ : readl(base) & ~(1 << (shift))), \ ++ base) ++ ++/** ++ * @brief Get value of corresponging bit from specified register. ++ * ++ * @param base - Register address ++ * @param shift - Bit index ++ * ++ * @return Bit value ++ */ ++#define AST_GPIO_READ(base, shift) ((readl(base) >> (shift)) & 1) ++ ++#define IS_VALID_GPIO(gpio) \ ++ ((gpio) >= ASPEED_GPIO(A, 0) && (gpio) <= ASPEED_GPIO(AC, 7)) ++ ++#define AST_GPIO_DIRECTION 0x04 ++#define AST_GPIO_INT_SENS0 0x04 ++#define AST_GPIO_INT_SENS1 0x08 ++#define AST_GPIO_INT_SENS2 0x0C ++#define AST_GPIO_INT_STATUS 0x10 ++#define AST_GPIO_DEBOUNCE0 0x00 ++#define AST_GPIO_DEBOUNCE1 0x04 ++#define AST_GPIO_CMD_SRC0 0x00 ++#define AST_GPIO_CMD_SRC1 0x04 ++ ++/** ++ * @brief Set a GPIO direction ++ * ++ * @param gpio GPIO line ++ * @param direction GPIO direction (0 for input or 1 for output) ++ * ++ * @return 0 if ok, -1 on error ++ */ ++static int ast_gpio_set_direction(unsigned gpio, unsigned direction) ++{ ++ ast_gpio_regs_t *regs = AST_GPIO_REGS(gpio); ++ if (!regs) ++ { ++ printf("%s: Invalid GPIO!\n", __func__); ++ return -1; ++ } ++ ++ AST_GPIO_WRITE(direction, regs->base + AST_GPIO_DIRECTION, ++ AST_GPIO_SHIFT(gpio)); ++ return 0; ++} ++ ++/** ++ * The 6 following functions are generic u-boot gpio implementation. ++ * They are declared in `include/asm-generic/gpio.h` ++ */ ++ ++int gpio_request(unsigned gpio, const char *label) ++{ ++ return (IS_VALID_GPIO(gpio) ? 0 : -1); ++} ++ ++int gpio_free(unsigned gpio) ++{ ++ return (IS_VALID_GPIO(gpio) ? 0 : -1); ++} ++ ++int gpio_get_value(unsigned gpio) ++{ ++ ast_gpio_regs_t *regs = AST_GPIO_REGS(gpio); ++ if (!regs) ++ { ++ printf("%s: Invalid GPIO!\n", __func__); ++ return -1; ++ } ++ ++ return AST_GPIO_READ(regs->base, AST_GPIO_SHIFT(gpio)); ++} ++ ++int gpio_set_value(unsigned gpio, int value) ++{ ++ ast_gpio_regs_t *regs = AST_GPIO_REGS(gpio); ++ if (!regs) ++ { ++ printf("%s: Invalid GPIO!\n", __func__); ++ return -1; ++ } ++ ++ AST_GPIO_WRITE(value, regs->base, AST_GPIO_SHIFT(gpio)); ++ return 0; ++} ++ ++int gpio_direction_input(unsigned gpio) ++{ ++ return ast_gpio_set_direction(gpio, ASPEED_GPIO_INPUT); ++} ++ ++int gpio_direction_output(unsigned gpio, int value) ++{ ++ int rc = ast_gpio_set_direction(gpio, ASPEED_GPIO_OUTPUT); ++ return (rc == 0 ? gpio_set_value(gpio, value) : rc); ++} ++ ++/** ++ * @brief Convert a string to GPIO line. Used by `do_gpio()` from `cmd/gpio.c` ++ * ++ * @param str a GPIO name or line number ++ * ++ * @return GPIO line if ok, -1 on error ++ */ ++int name_to_gpio(const char *str) ++{ ++ int gpio = -1; ++ ++ if (str) ++ { ++ if (isalpha(*str)) ++ { ++ gpio = (toupper(*str) - 'A') << ASPEED_GPIO_PORT_SHIFT; ++ ++ if (toupper(*str) == 'A' && toupper(*(str + 1)) >= 'A' && ++ toupper(*(str + 1)) <= 'C') ++ { ++ str++; ++ gpio = (ASPEED_GPIO_PORT_AA + toupper(*str) - 'A') ++ << ASPEED_GPIO_PORT_SHIFT; ++ } ++ ++ str++; ++ if (*str >= '0' && *str <= '7' && !*(str + 1)) ++ { ++ gpio += *str - '0'; ++ } ++ else ++ { ++ gpio = -1; ++ } ++ } ++ else if (isdigit(*str)) ++ { ++ gpio = simple_strtoul(str, NULL, 0); ++ } ++ } ++ ++ return gpio; ++} ++ ++/** ++ * @return A GPIO direction in human readable format. ++ */ ++static const char *ast_gpio_direction(unsigned gpio) ++{ ++ ast_gpio_regs_t *regs = AST_GPIO_REGS(gpio); ++ if (regs) ++ { ++ int direction = AST_GPIO_READ(regs->base + AST_GPIO_DIRECTION, ++ AST_GPIO_SHIFT(gpio)); ++ switch (direction) ++ { ++ case ASPEED_GPIO_INPUT: ++ return "input"; ++ case ASPEED_GPIO_OUTPUT: ++ return "output"; ++ default: ++ break; ++ } ++ } ++ return "error"; ++} ++ ++/** ++ * @return An interrupt trigger settings in human readable format. ++ */ ++static const char *ast_gpio_trigger(unsigned gpio) ++{ ++ ast_gpio_regs_t *regs = AST_GPIO_REGS(gpio); ++ if (regs) ++ { ++ unsigned shift = AST_GPIO_SHIFT(gpio); ++ unsigned trigger = ++ (AST_GPIO_READ(regs->intcfg + AST_GPIO_INT_SENS0, shift) << 0) | ++ (AST_GPIO_READ(regs->intcfg + AST_GPIO_INT_SENS1, shift) << 1) | ++ (AST_GPIO_READ(regs->intcfg + AST_GPIO_INT_SENS2, shift) << 2); ++ ++ switch (trigger) ++ { ++ case ASPEED_GPIO_FALLING_EDGE: ++ return "fall"; ++ case ASPEED_GPIO_RISING_EDGE: ++ return "rise"; ++ case ASPEED_GPIO_LOW_LEVEL: ++ return "low "; ++ case ASPEED_GPIO_HIGH_LEVEL: ++ return "high"; ++ default: ++ return "both"; ++ } ++ } ++ return "error"; ++} ++ ++/** ++ * @return An interrupt status in human readable format. ++ */ ++static const char *ast_gpio_int_status(unsigned gpio) ++{ ++ ast_gpio_regs_t *regs = AST_GPIO_REGS(gpio); ++ if (regs) ++ { ++ unsigned shift = AST_GPIO_SHIFT(gpio); ++ if (AST_GPIO_READ(regs->intcfg, shift)) ++ { ++ return AST_GPIO_READ(regs->intcfg + AST_GPIO_INT_STATUS, shift) ++ ? "pending" ++ : "cleaned"; ++ } ++ return "disabled"; ++ } ++ ++ return "error"; ++} ++ ++/** ++ * @return A debounce value in human readable format. ++ */ ++static const char *ast_gpio_debounce(unsigned gpio) ++{ ++ ast_gpio_regs_t *regs = AST_GPIO_REGS(gpio); ++ if (regs) ++ { ++ unsigned shift = AST_GPIO_SHIFT(gpio); ++ unsigned debounce = ++ (AST_GPIO_READ(regs->debounce + AST_GPIO_DEBOUNCE0, shift) << 0) | ++ (AST_GPIO_READ(regs->debounce + AST_GPIO_DEBOUNCE1, shift) << 1); ++ switch (debounce) ++ { ++ case ASPEED_GPIO_DEBOUNCE_NONE: ++ return "none"; ++ case ASPEED_GPIO_DEBOUNCE_1: ++ return "timer1"; ++ case ASPEED_GPIO_DEBOUNCE_2: ++ return "timer2"; ++ case ASPEED_GPIO_DEBOUNCE_3: ++ return "timer3"; ++ default: ++ break; ++ } ++ } ++ ++ return "error"; ++} ++ ++/** ++ * @return A command source value in human readable format. ++ */ ++static const char *ast_gpio_command_source(unsigned gpio) ++{ ++ ast_gpio_regs_t *regs = AST_GPIO_REGS(gpio); ++ if (regs) ++ { ++ /* Used one bit per gpio port */ ++ unsigned shift = AST_GPIO_SHIFT(gpio) - AST_GPIO_PIN(gpio); ++ unsigned cmdsrc = ++ (AST_GPIO_READ(regs->cmdsrc + AST_GPIO_CMD_SRC0, shift) << 0) | ++ (AST_GPIO_READ(regs->cmdsrc + AST_GPIO_CMD_SRC1, shift) << 1); ++ ++ switch (cmdsrc) ++ { ++ /* The single place where these values are used is here. */ ++ case 0x0: ++ return "ARM"; ++ case 0x1: ++ return "LPC"; ++ case 0x2: ++ return "CoCPU"; ++ default: ++ return "Unknown"; ++ } ++ } ++ ++ return "error"; ++} ++ ++/** ++ * @brief Show all GPIO pins statuses. Used by `do_gpio()` in `cmd/gpio.c` ++ */ ++void gpio_info(void) ++{ ++ unsigned first = ASPEED_GPIO(A, 0); ++ unsigned last = ASPEED_GPIO(AC, 7); ++ for (unsigned gpio = first; gpio <= last; gpio++) ++ { ++ unsigned port = AST_GPIO_PORT(gpio); ++ unsigned pin = AST_GPIO_PIN(gpio); ++ unsigned shift = AST_GPIO_SHIFT(gpio); ++ ast_gpio_regs_t *regs = AST_GPIO_REGS(gpio); ++ if (!regs) ++ { ++ printf("gpio %u is invalid!\n", gpio); ++ continue; ++ } ++ ++ printf("gpio %c%c%c line %3d: %s, int: %s, %s, deb: %s, src: %s, " ++ "val: %d/%d\n", ++ (port >= ASPEED_GPIO_PORT_AA ? 'A' : ' '), ++ ('A' + port % ASPEED_GPIO_PORT_AA), ('0' + pin), gpio, ++ ast_gpio_direction(gpio), ast_gpio_trigger(gpio), ++ ast_gpio_int_status(gpio), ast_gpio_debounce(gpio), ++ ast_gpio_command_source(gpio), gpio_get_value(gpio), ++ AST_GPIO_READ(regs->data, shift)); ++ } ++} +-- +2.25.4 + diff --git a/meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0004-aspeed-add-bmc-position-support.patch b/meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0004-aspeed-add-bmc-position-support.patch new file mode 100644 index 000000000..423092b5f --- /dev/null +++ b/meta-yadro/meta-nicole/recipes-bsp/u-boot/files/0004-aspeed-add-bmc-position-support.patch @@ -0,0 +1,61 @@ +From 8098310be5887bd5e80830f105b63ed59dc10421 Mon Sep 17 00:00:00 2001 +From: Alexander Filippov +Date: Fri, 22 May 2020 11:45:31 +0300 +Subject: [PATCH] aspeed: add bmc position support + +There are two Nicoles in one chassis in the Tatlin hardware. +The position is encoded by a pin, read by an MCU, and then translated +to the BMC via GPIO pin GPIOE1. + +This reads the GPIO pin state and put is as a bootargs item. + +Signed-off-by: Alexander Filippov +--- + arch/arm/mach-aspeed/ast-late-init.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/arch/arm/mach-aspeed/ast-late-init.c b/arch/arm/mach-aspeed/ast-late-init.c +index 5646c0e882..7d36dc0d8a 100644 +--- a/arch/arm/mach-aspeed/ast-late-init.c ++++ b/arch/arm/mach-aspeed/ast-late-init.c +@@ -7,6 +7,7 @@ + + #include + #include ++#include + #include + + static void update_bootargs_cmd(const char *key, const char *value) +@@ -106,9 +107,29 @@ static void set_reset_reason(void) + } + } + ++static void set_bmc_position(void) ++{ ++ unsigned gpio = ASPEED_GPIO(E, 1); ++ ++ /* Init GPIO */ ++ if (gpio_request(gpio, "bmcposition") == 0 && ++ gpio_direction_input(gpio) == 0) ++ { ++ int position = gpio_get_value(gpio); ++ if (position >= 0) ++ { ++ printf("BMC Position: %d\n", position); ++ update_bootargs_cmd("bmcposition", position ? "1" : "0"); ++ } ++ } ++ ++ gpio_free(gpio); ++} ++ + int board_late_init(void) + { + set_reset_reason(); ++ set_bmc_position(); + + return 0; + } +-- +2.25.4 + diff --git a/meta-yadro/meta-nicole/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend b/meta-yadro/meta-nicole/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend index bf7802a68..1390922e1 100644 --- a/meta-yadro/meta-nicole/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend +++ b/meta-yadro/meta-nicole/recipes-bsp/u-boot/u-boot-aspeed_%.bbappend @@ -3,4 +3,6 @@ FILESEXTRAPATHS_append := "${THISDIR}/files:" SRC_URI_append = " \ file://0001-Add-system-reset-status-support.patch \ file://0002-config-ast-common-set-fieldmode-to-true.patch \ + file://0003-aspeed-add-gpio-support.patch \ + file://0004-aspeed-add-bmc-position-support.patch \ " -- cgit v1.2.3