diff options
author | Ed Tanous <ed.tanous@intel.com> | 2019-04-15 23:42:44 +0300 |
---|---|---|
committer | Ed Tanous <ed.tanous@intel.com> | 2019-04-17 19:13:25 +0300 |
commit | 816d793003e93c1e5eec0a2e90fbd8b9dde9f7a5 (patch) | |
tree | 341534fed9a2de460ded7f8231ca1cbb178bb2ca /meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files | |
parent | a75bff085ba9443315222231c42692745e5781e9 (diff) | |
download | openbmc-816d793003e93c1e5eec0a2e90fbd8b9dde9f7a5.tar.xz |
Update 4-15-19
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files')
6 files changed, 1071 insertions, 102 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0018-Add-support-for-Macronix-and-Micron-1Gbits-SPI-flash.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0018-Add-support-for-Macronix-and-Micron-1Gbits-SPI-flash.patch index b96211118..2ed297a96 100644 --- a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0018-Add-support-for-Macronix-and-Micron-1Gbits-SPI-flash.patch +++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0018-Add-support-for-Macronix-and-Micron-1Gbits-SPI-flash.patch @@ -1,4 +1,4 @@ -From 5f2a7c03c877454eb78a406934abf6b7d05e40a6 Mon Sep 17 00:00:00 2001 +From 0039c15251a7fcf60154d59933a11d9e17b04d5c Mon Sep 17 00:00:00 2001 From: Jae Hyun Yoo <jae.hyun.yoo@intel.com> Date: Thu, 6 Dec 2018 18:49:04 -0800 Subject: [PATCH] Add support for Macronix and Micron 1Gbits SPI flash @@ -7,27 +7,25 @@ Quick fix to support Macronix and Micron 1Gbits SPI. Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com> --- - arch/arm/mach-aspeed/flash.c | 32 ++++++++++++++++++++++++++++++++ - 1 file changed, 32 insertions(+) + arch/arm/mach-aspeed/flash.c | 33 ++++++++++++++++++++++++++++++++- + 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-aspeed/flash.c b/arch/arm/mach-aspeed/flash.c -index f9f1345523d4..abc0420176a6 100644 +index dece4315d755..2a31b6503a22 100644 --- a/arch/arm/mach-aspeed/flash.c +++ b/arch/arm/mach-aspeed/flash.c -@@ -79,6 +79,8 @@ flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* FLASH chips info */ +@@ -79,6 +79,7 @@ flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* FLASH chips info */ #define MX25L12805D 0x1820C2 #define MX25L25635E 0x1920C2 #define MX66L51235F 0x1A20C2 +#define MX66L1G45G 0x1B20C2 -+#define MT25QL01GB 0x21BA20 #define SST25VF016B 0x4125bf #define SST25VF064C 0x4b25bf #define SST25VF040B 0x8d25bf -@@ -977,6 +979,36 @@ static ulong flash_get_size (ulong base, flash_info_t *info) +@@ -978,6 +979,35 @@ static ulong flash_get_size (ulong base, flash_info_t *info) #endif break; -+ case MT25QL01GB: + case MX66L1G45G: + erase_region_size = 0x10000; + info->readcmd = 0x0b; @@ -60,6 +58,16 @@ index f9f1345523d4..abc0420176a6 100644 case MX25L12805D: info->sector_count = 256; info->size = 0x1000000; +@@ -1093,7 +1123,8 @@ static ulong flash_get_size (ulong base, flash_info_t *info) + info->readcmd = 0x0b; + info->dualport = 0; + info->dummybyte = 1; +- info->buffersize = 1; ++ info->buffersize = 256; ++ info->address32 = 1; + WriteClk = 50; + EraseClk = 25; + ReadClk = 50; -- 2.7.4 diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch index 814a7dc2a..2e541561a 100644 --- a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch +++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0020-Add-system-reset-status-support.patch @@ -1,6 +1,6 @@ -From d0338f68edb7f818b45ee43765cf124c14ccae03 Mon Sep 17 00:00:00 2001 +From 06445210bfda7f9bbbb36133e6818575bd6a0cc1 Mon Sep 17 00:00:00 2001 From: Yong Li <yong.b.li@linux.intel.com> -Date: Tue, 22 Jan 2019 16:15:36 +0800 +Date: Tue, 9 Apr 2019 14:42:05 +0800 Subject: [PATCH] Add system reset status support Will display the reset reasons and other CPU information in u-boot, @@ -9,25 +9,12 @@ for applications to query. Signed-off-by: Yong Li <yong.b.li@linux.intel.com> --- - arch/arm/include/asm/arch-aspeed/ast_scu.h | 1 + arch/arm/include/asm/arch-aspeed/platform.h | 2 ++ - arch/arm/mach-aspeed/ast-scu.c | 55 +++++++++++++++++++++++++++++ - board/aspeed/ast-g5/ast-g5-intel.c | 30 ++++++++++++++++ - board/aspeed/ast-g5/ast-g5.c | 7 ++++ - 5 files changed, 95 insertions(+) + arch/arm/mach-aspeed/ast-scu.c | 4 ++++ + board/aspeed/ast-g5/ast-g5-intel.c | 30 +++++++++++++++++++++++++++++ + board/aspeed/ast-g5/ast-g5.c | 7 +++++++ + 4 files changed, 43 insertions(+) -diff --git a/arch/arm/include/asm/arch-aspeed/ast_scu.h b/arch/arm/include/asm/arch-aspeed/ast_scu.h -index c10e6a9..369c4e3 100644 ---- a/arch/arm/include/asm/arch-aspeed/ast_scu.h -+++ b/arch/arm/include/asm/arch-aspeed/ast_scu.h -@@ -37,6 +37,7 @@ extern void ast_scu_get_who_init_dram(void); - - extern u32 ast_get_clk_source(void); - extern u32 ast_get_h_pll_clk(void); -+extern u32 ast_get_m_pll_clk(void); - extern u32 ast_get_ahbclk(void); - - extern u32 ast_scu_get_vga_memsize(void); diff --git a/arch/arm/include/asm/arch-aspeed/platform.h b/arch/arm/include/asm/arch-aspeed/platform.h index 3b06e52..4e4140d 100644 --- a/arch/arm/include/asm/arch-aspeed/platform.h @@ -42,82 +29,10 @@ index 3b06e52..4e4140d 100644 #err "No define for platform.h" #endif diff --git a/arch/arm/mach-aspeed/ast-scu.c b/arch/arm/mach-aspeed/ast-scu.c -index 63e9c7c..f4268f3 100644 +index 3a9ba05..976c59b 100644 --- a/arch/arm/mach-aspeed/ast-scu.c +++ b/arch/arm/mach-aspeed/ast-scu.c -@@ -100,6 +100,7 @@ static struct soc_id soc_map_table[] = { - SOC_ID("AST2510-A1", 0x04010103), - SOC_ID("AST2520-A1", 0x04010203), - SOC_ID("AST2530-A1", 0x04010403), -+ SOC_ID("AST2500-A2", 0x04030303), - }; - - void ast_scu_init_eth(u8 num) -@@ -235,6 +236,29 @@ u32 ast_get_h_pll_clk(void) - return clk; - } - -+u32 ast_get_m_pll_clk(void) -+{ -+ u32 clk=0; -+ u32 m_pll_set = ast_scu_read(AST_SCU_M_PLL); -+ -+ if(m_pll_set & SCU_M_PLL_OFF) -+ return 0; -+ -+ // Programming -+ clk = ast_get_clk_source(); -+ if(m_pll_set & SCU_M_PLL_BYPASS) { -+ return clk; -+ } else { -+ //PD == SCU20[13:18] -+ //M == SCU20[5:12] -+ //N == SCU20[0:4] -+ //mpll = 24MHz * [(M+1) /(N+1)] / (P+1) -+ clk = ((clk * (SCU_M_PLL_GET_MNUM(m_pll_set) + 1)) / (SCU_M_PLL_GET_NNUM(m_pll_set) + 1))/(SCU_M_PLL_GET_PDNUM(m_pll_set) + 1); -+ } -+ debug("m_pll = %d\n",clk); -+ return clk; -+} -+ - u32 ast_get_ahbclk(void) - { - unsigned int axi_div, ahb_div, hpll; -@@ -304,6 +328,33 @@ u32 ast_get_h_pll_clk(void) - return clk; - } - -+u32 ast_get_m_pll_clk(void) -+{ -+ u32 clk=0; -+ u32 m_pll_set = ast_scu_read(AST_SCU_M_PLL); -+ -+ if(m_pll_set & SCU_M_PLL_OFF) -+ return 0; -+ -+ // Programming -+ clk = ast_get_clk_source(); -+ if(m_pll_set & SCU_M_PLL_BYPASS) { -+ return clk; -+ } else { -+ //OD == SCU24[4] -+ //OD = SCU_M_PLL_GET_DIV(h_pll_set); -+ //Numerator == SCU24[10:5] -+ //num = SCU_M_PLL_GET_NUM(h_pll_set); -+ //Denumerator == SCU24[3:0] -+ //denum = SCU_M_PLL_GET_DENUM(h_pll_set); -+ -+ //hpll = 24MHz * (2-OD) * ((Numerator+2)/(Denumerator+1)) -+ clk = (clk * (2-SCU_M_PLL_GET_DIV(m_pll_set)) * ((SCU_M_PLL_GET_NUM(m_pll_set)+2)/(SCU_M_PLL_GET_DENUM(m_pll_set)+1))); -+ } -+ debug("m_pll = %d\n",clk); -+ return clk; -+} -+ - u32 ast_get_ahbclk(void) - { - unsigned int div, hpll; -@@ -452,6 +503,9 @@ void ast_scu_sys_rest_info(void) +@@ -494,6 +494,9 @@ void ast_scu_sys_rest_info(void) { u32 rest = ast_scu_read(AST_SCU_SYS_CTRL); @@ -127,7 +42,7 @@ index 63e9c7c..f4268f3 100644 if (rest & SCU_SYS_EXT_RESET_FLAG) { printf("RST : External\n"); ast_scu_write(SCU_SYS_EXT_RESET_FLAG, AST_SCU_SYS_CTRL); -@@ -464,6 +518,7 @@ void ast_scu_sys_rest_info(void) +@@ -506,6 +509,7 @@ void ast_scu_sys_rest_info(void) } else { printf("RST : CLK en\n"); } diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-KCS-driver-support-in-uBoot.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-KCS-driver-support-in-uBoot.patch new file mode 100644 index 000000000..79028d2a1 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-KCS-driver-support-in-uBoot.patch @@ -0,0 +1,620 @@ +From 16209364c27a0cb7e2b7fdd445942f68e9180263 Mon Sep 17 00:00:00 2001 +From: AppaRao Puli <apparao.puli@linux.intel.com> +Date: Wed, 13 Mar 2019 14:28:05 +0530 +Subject: [PATCH] KCS driver support in uBoot + +Added KCS support in uBoot. This will enable +KCS channels and set the specified registers +to do KCS communication in uBoot. It also +consist of read and write KCS message transations +work flow implementation( As specified in IPMI +specification Section 9.15). It is enabled +only when Force Firmware Update Jumper is ON. + +Tested By: +Stopped booting in uBoot and sent IPMI commands +via KCS interfaces using cmdtool.efi. + - Get Device ID: + Req: cmdtool.efi 20 18 1 + Res: 00 23 00 12 03 02 BF 57 01 00 7B 00 00 00 00 00 + - Get Self Test Results + Req: cmdtool.efi 20 18 4 + Res: 00 56 00 + - All other commands + Req: cmdtool.efi 20 18 2 + Res: C1 (Invalid). + +Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> +--- + board/aspeed/ast-g5/Makefile | 1 + + board/aspeed/ast-g5/ast-g5-intel.c | 3 + + board/aspeed/ast-g5/ast-g5-kcs.c | 425 +++++++++++++++++++++++++++++++++++++ + board/aspeed/ast-g5/ast-g5-kcs.h | 114 ++++++++++ + 4 files changed, 543 insertions(+) + create mode 100644 board/aspeed/ast-g5/ast-g5-kcs.c + create mode 100644 board/aspeed/ast-g5/ast-g5-kcs.h + +diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile +index 9022433..05972b9 100644 +--- a/board/aspeed/ast-g5/Makefile ++++ b/board/aspeed/ast-g5/Makefile +@@ -4,3 +4,4 @@ obj-y += ast-g5-espi.o + obj-y += ast-g5-irq.o + obj-y += ast-g5-gpio.o + obj-y += ast-g5-timer.o ++obj-y += ast-g5-kcs.o +diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c +index f810a40..f9955c7 100644 +--- a/board/aspeed/ast-g5/ast-g5-intel.c ++++ b/board/aspeed/ast-g5/ast-g5-intel.c +@@ -437,6 +437,7 @@ static void pwm_init(void) + } + + extern void espi_init(void); ++extern void kcs_init(void); + void ast_g5_intel(void) + { + pwm_init(); +@@ -446,6 +447,8 @@ void ast_g5_intel(void) + timer8_init(); + if (intel_force_firmware_jumper_enabled()) { + id_led_control(GPIO_AMBER_LED, EIDLED_On); ++ kcs_init(); ++ /* TODO: need to stop the booting here. */ + } else { + id_led_control(GPIO_GREEN_LED, EIDLED_On); + } +diff --git a/board/aspeed/ast-g5/ast-g5-kcs.c b/board/aspeed/ast-g5/ast-g5-kcs.c +new file mode 100644 +index 0000000..f983b4a +--- /dev/null ++++ b/board/aspeed/ast-g5/ast-g5-kcs.c +@@ -0,0 +1,425 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (c) 2018-2019 Intel Corporation ++ ++#include "ast-g5-kcs.h" ++ ++#define DEBUG_KCS_ENABLED 0 ++#ifdef DEBUG_KCS_ENABLED ++#define DBG_KCS printf ++#else ++#define DBG_KCS(...) ++#endif ++ ++/* TODO: Move to IPMI file. */ ++#define IPMI_CC_OK 0x00 ++#define IPMI_CC_INVALID 0xC1 ++#define IPMI_CC_UNSPECIFIED 0xFF ++ ++#define KCS_CHANNEL_NO_3 3 ++ ++static const u16 enabled_kcs_channel[] = { KCS_CHANNEL_NO_3 }; ++ ++static const struct kcs_io_reg ast_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = { ++ { .idr = LPC_IDR1, .odr = LPC_ODR1, .str = LPC_STR1 }, ++ { .idr = LPC_IDR2, .odr = LPC_ODR2, .str = LPC_STR2 }, ++ { .idr = LPC_IDR3, .odr = LPC_ODR3, .str = LPC_STR3 }, ++ { .idr = LPC_IDR4, .odr = LPC_ODR4, .str = LPC_STR4 } ++}; ++ ++#define NO_OF_ENABLED_KCS_CHANNELS ARRAY_SIZE(enabled_kcs_channel) ++ ++static struct kcs_packet m_kcs_pkt[NO_OF_ENABLED_KCS_CHANNELS]; ++ ++static u16 read_status(u16 channel_num) ++{ ++ return readl(AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].str); ++} ++ ++static void write_status(u16 channel_num, u16 value) ++{ ++ writel(value, AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].str); ++} ++ ++static u16 read_data(u16 channel_num) ++{ ++ return readl(AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].idr); ++} ++ ++static void write_data(u16 channel_num, u16 value) ++{ ++ writel(value, AST_LPC_BASE + ast_kcs_bmc_ioregs[channel_num - 1].odr); ++} ++ ++static void set_kcs_state(u16 channel_num, u16 state) ++{ ++ u16 status = read_status(channel_num); ++ ++ status &= ~KCS_STATE_MASK; ++ status |= KCS_STATE(state) & KCS_STATE_MASK; ++ write_status(channel_num, status); ++} ++ ++static struct kcs_packet *get_kcs_packet(u16 channel_num) ++{ ++ for (u16 idx = 0; idx < NO_OF_ENABLED_KCS_CHANNELS; idx++) { ++ if (channel_num == enabled_kcs_channel[idx]) ++ return &m_kcs_pkt[idx]; ++ } ++ ++ /* very unlike code hits here. */ ++ printf("ERROR: %s error. ChannelNo: %d\n", __func__, channel_num); ++ BUG(); ++} ++ ++static void kcs_force_abort(u16 channel_num) ++{ ++ struct kcs_packet *kcs_pkt = NULL; ++ ++ kcs_pkt = get_kcs_packet(channel_num); ++ printf("ERROR: KCS communication aborted (Channel:%d, Error:%d)\n", ++ channel_num, kcs_pkt->error); ++ set_kcs_state(channel_num, KCS_STATE_ERROR); ++ read_data(channel_num); ++ write_data(channel_num, ZERO_DATA); ++ ++ kcs_pkt->phase = KCS_PHASE_ERROR; ++ kcs_pkt->read_req_done = false; ++ kcs_pkt->data_in_idx = 0; ++} ++ ++static void init_kcs_packet(u16 channel_num) ++{ ++ struct kcs_packet *kcs_pkt = NULL; ++ ++ kcs_pkt = get_kcs_packet(channel_num); ++ kcs_pkt->channel = channel_num; ++ kcs_pkt->read_req_done = false; ++ kcs_pkt->phase = KCS_PHASE_IDLE; ++ kcs_pkt->error = KCS_NO_ERROR; ++ kcs_pkt->data_in_idx = 0; ++ kcs_pkt->data_out_idx = 0; ++ kcs_pkt->data_out_len = 0; ++} ++ ++static void process_kcs_request(u16 channel_num) ++{ ++ struct kcs_packet *kcs_pkt = NULL; ++ ++ kcs_pkt = get_kcs_packet(channel_num); ++ if (!kcs_pkt->read_req_done) ++ return; ++ ++ DBG_KCS("%s:- chan:%d\n", __func__, channel_num); ++ ++#ifdef DEBUG_KCS_ENABLED ++ int i; ++ ++ DBG_KCS("Request data(Len:%d): ", kcs_pkt->data_in_idx); ++ for (i = 0; i < kcs_pkt->data_in_idx; i++) ++ DBG_KCS(" 0x%02x", kcs_pkt->data_in[i]); ++ DBG_KCS("\n"); ++#endif ++ ++ /* ++ * TODO: Move it to IPMI Command Handler ++ * Below code is added for timebeing till ++ * we implement the IPMI command handler. ++ */ ++ kcs_pkt->data_out[0] = kcs_pkt->data_in[0]; /* netfn */ ++ kcs_pkt->data_out[1] = kcs_pkt->data_in[1]; /* cmd */ ++ kcs_pkt->data_out[2] = IPMI_CC_OK; /* cc */ ++ ++ if (((kcs_pkt->data_in[0] >> 2) == 0x06) && ++ (kcs_pkt->data_in[1] == 0x01)) { ++ /* Get Device ID */ ++ u8 device_id[15] = { 0x23, 0x00, 0x12, 0x03, 0x02, ++ 0xBF, 0x57, 0x01, 0x00, 0x7B, ++ 0x00, 0x00, 0x00, 0x00, 0x00 }; ++ for (i = 0; i < 15; i++) ++ kcs_pkt->data_out[i + 3] = device_id[i]; ++ kcs_pkt->data_out_len = 18; ++ } else if (((kcs_pkt->data_in[0] >> 2) == 0x06) && ++ (kcs_pkt->data_in[1] == 0x04)) { ++ /* Get Self Test Results */ ++ kcs_pkt->data_out[3] = 0x56; ++ kcs_pkt->data_out[4] = 0x00; ++ kcs_pkt->data_out_len = 5; ++ } else { ++ kcs_pkt->data_out[2] = ++ IPMI_CC_INVALID; /* Invalid or not supported. */ ++ kcs_pkt->data_out_len = 3; ++ } ++ /* END: TODO */ ++ ++#ifdef DEBUG_KCS_ENABLED ++ DBG_KCS("Response data(Len:%d): ", kcs_pkt->data_out_len); ++ for (i = 0; i < kcs_pkt->data_out_len; i++) ++ DBG_KCS(" 0x%02x", kcs_pkt->data_out[i]); ++ DBG_KCS("\n"); ++#endif ++ ++ kcs_pkt->phase = KCS_PHASE_READ; ++ write_data(channel_num, kcs_pkt->data_out[kcs_pkt->data_out_idx++]); ++ kcs_pkt->read_req_done = false; ++} ++ ++static void read_kcs_data(u16 channel_num) ++{ ++ struct kcs_packet *kcs_pkt = NULL; ++ ++ kcs_pkt = get_kcs_packet(channel_num); ++ DBG_KCS("%s:- chan:%d, kcs_pkt->phase:%d\n", __func__, channel_num, ++ kcs_pkt->phase); ++ ++ switch (kcs_pkt->phase) { ++ case KCS_PHASE_WRITE_START: ++ kcs_pkt->phase = KCS_PHASE_WRITE_DATA; ++ /* fall through */ ++ ++ case KCS_PHASE_WRITE_DATA: ++ if (kcs_pkt->data_in_idx >= MAX_KCS_PKT_SIZE) { ++ kcs_pkt->error = KCS_LENGTH_ERROR; ++ kcs_force_abort(channel_num); ++ return; ++ } ++ set_kcs_state(channel_num, KCS_STATE_WRITE); ++ write_data(channel_num, ZERO_DATA); ++ kcs_pkt->data_in[kcs_pkt->data_in_idx++] = ++ read_data(channel_num); ++ break; ++ ++ case KCS_PHASE_WRITE_END: ++ if (kcs_pkt->data_in_idx >= MAX_KCS_PKT_SIZE) { ++ kcs_pkt->error = KCS_LENGTH_ERROR; ++ kcs_force_abort(channel_num); ++ return; ++ } ++ set_kcs_state(channel_num, KCS_STATE_READ); ++ kcs_pkt->data_in[kcs_pkt->data_in_idx++] = ++ read_data(channel_num); ++ kcs_pkt->phase = KCS_PHASE_READ_WAIT; ++ kcs_pkt->read_req_done = true; ++ ++ process_kcs_request(channel_num); ++ break; ++ ++ case KCS_PHASE_READ: ++ if (kcs_pkt->data_out_idx == kcs_pkt->data_out_len) ++ set_kcs_state(channel_num, KCS_STATE_IDLE); ++ ++ u8 data = read_data(channel_num); ++ if (data != KCS_CTRL_CODE_READ) { ++ DBG_KCS("Invalid Read data. Phase:%d, Data:0x%02x\n", ++ kcs_pkt->phase, data); ++ set_kcs_state(channel_num, KCS_STATE_ERROR); ++ write_data(channel_num, ZERO_DATA); ++ break; ++ } ++ ++ if (kcs_pkt->data_out_idx == kcs_pkt->data_out_len) { ++ write_data(channel_num, ZERO_DATA); ++ kcs_pkt->phase = KCS_PHASE_IDLE; ++ break; ++ } ++ write_data(channel_num, ++ kcs_pkt->data_out[kcs_pkt->data_out_idx++]); ++ break; ++ ++ case KCS_PHASE_ABORT_1: ++ set_kcs_state(channel_num, KCS_STATE_READ); ++ read_data(channel_num); ++ write_data(channel_num, kcs_pkt->error); ++ kcs_pkt->phase = KCS_PHASE_ABORT_2; ++ break; ++ ++ case KCS_PHASE_ABORT_2: ++ set_kcs_state(channel_num, KCS_STATE_IDLE); ++ read_data(channel_num); ++ write_data(channel_num, ZERO_DATA); ++ kcs_pkt->phase = KCS_PHASE_IDLE; ++ break; ++ ++ default: ++ kcs_force_abort(channel_num); ++ } ++} ++ ++static void read_kcs_cmd(u16 channel_num) ++{ ++ struct kcs_packet *kcs_pkt = NULL; ++ ++ kcs_pkt = get_kcs_packet(channel_num); ++ ++ set_kcs_state(channel_num, KCS_STATE_WRITE); ++ write_data(channel_num, ZERO_DATA); ++ ++ u16 cmd = read_data(channel_num); ++ DBG_KCS("%s:- chan:%d, cmd:0x%02x\n", __func__, channel_num, cmd); ++ switch (cmd) { ++ case KCS_CTRL_CODE_WRITE_START: ++ init_kcs_packet(channel_num); ++ kcs_pkt->phase = KCS_PHASE_WRITE_START; ++ break; ++ ++ case KCS_CTRL_CODE_WRITE_END: ++ if (kcs_pkt->error != KCS_NO_ERROR) { ++ kcs_force_abort(channel_num); ++ return; ++ } ++ ++ kcs_pkt->phase = KCS_PHASE_WRITE_END; ++ break; ++ ++ case KCS_CTRL_CODE_GET_STATUS_ABORT: ++ kcs_pkt->phase = KCS_PHASE_ABORT_1; ++ kcs_pkt->error = KCS_ABORT_BY_CMD; ++ break; ++ ++ default: ++ kcs_pkt->error = KCS_ILLEGAL_CTRL_CMD; ++ kcs_force_abort(channel_num); ++ } ++} ++ ++static u16 kcs_irq_handler(struct pt_regs *regs) ++{ ++ for (u16 idx = 0; idx < NO_OF_ENABLED_KCS_CHANNELS; idx++) { ++ u16 channel_num = enabled_kcs_channel[idx]; ++ /* Look-up the interrupted KCS channel */ ++ u16 status = read_status(channel_num); ++ if (status & BIT_STATUS_IBF) { ++ if (status & BIT_STATUS_COD) ++ read_kcs_cmd(channel_num); ++ else ++ read_kcs_data(channel_num); ++ } ++ } ++ ++ return 0; ++} ++ ++static void set_kcs_channel_addr(u16 channel_num) ++{ ++ u32 val; ++ ++ switch (channel_num) { ++ case 1: ++ val = readl(AST_LPC_BASE + LPC_HICR4) & ~BIT_LADR12AS; ++ writel(val, AST_LPC_BASE + LPC_HICR4); ++ val = (KCS_CHANNEL1_ADDR >> 8); ++ writel(val, AST_LPC_BASE + LPC_LADR12H); ++ val = (KCS_CHANNEL1_ADDR & 0xFF); ++ writel(val, AST_LPC_BASE + LPC_LADR12L); ++ break; ++ ++ case 2: ++ val = readl(AST_LPC_BASE + LPC_HICR4) | BIT_LADR12AS; ++ writel(val, AST_LPC_BASE + LPC_HICR4); ++ val = (KCS_CHANNEL2_ADDR >> 8); ++ writel(val, AST_LPC_BASE + LPC_LADR12H); ++ val = (KCS_CHANNEL2_ADDR & 0xFF); ++ writel(val, AST_LPC_BASE + LPC_LADR12L); ++ break; ++ ++ case 3: ++ val = (KCS_CHANNEL3_ADDR >> 8); ++ writel(val, AST_LPC_BASE + LPC_LADR3H); ++ val = (KCS_CHANNEL3_ADDR & 0xFF); ++ writel(val, AST_LPC_BASE + LPC_LADR3L); ++ break; ++ ++ case 4: ++ val = (((KCS_CHANNEL4_ADDR + 1) << 16) | KCS_CHANNEL4_ADDR); ++ writel(val, AST_LPC_BASE + LPC_LADR4); ++ break; ++ ++ default: ++ DBG_KCS("Invalid channel (%d) specified\n", channel_num); ++ break; ++ } ++} ++ ++static void enable_kcs_channel(u16 channel_num, u16 enable) ++{ ++ u32 val; ++ ++ switch (channel_num) { ++ case 1: ++ if (enable) { ++ val = readl(AST_LPC_BASE + LPC_HICR2) | BIT_IBFIE1; ++ writel(val, AST_LPC_BASE + LPC_HICR2); ++ val = readl(AST_LPC_BASE + LPC_HICR0) | BIT_LPC1E; ++ writel(val, AST_LPC_BASE + LPC_HICR0); ++ } else { ++ val = readl(AST_LPC_BASE + LPC_HICR0) & ~BIT_LPC1E; ++ writel(val, AST_LPC_BASE + LPC_HICR0); ++ val = readl(AST_LPC_BASE + LPC_HICR2) & ~BIT_IBFIE1; ++ writel(val, AST_LPC_BASE + LPC_HICR2); ++ } ++ break; ++ ++ case 2: ++ if (enable) { ++ val = readl(AST_LPC_BASE + LPC_HICR2) | BIT_IBFIE2; ++ writel(val, AST_LPC_BASE + LPC_HICR2); ++ val = readl(AST_LPC_BASE + LPC_HICR0) | BIT_LPC2E; ++ writel(val, AST_LPC_BASE + LPC_HICR0); ++ } else { ++ val = readl(AST_LPC_BASE + LPC_HICR0) & ~BIT_LPC2E; ++ writel(val, AST_LPC_BASE + LPC_HICR0); ++ val = readl(AST_LPC_BASE + LPC_HICR2) & ~BIT_IBFIE2; ++ writel(val, AST_LPC_BASE + LPC_HICR2); ++ } ++ break; ++ ++ case 3: ++ if (enable) { ++ val = readl(AST_LPC_BASE + LPC_HICR2) | BIT_IBFIE3; ++ writel(val, AST_LPC_BASE + LPC_HICR2); ++ val = readl(AST_LPC_BASE + LPC_HICR0) | BIT_LPC3E; ++ writel(val, AST_LPC_BASE + LPC_HICR0); ++ val = readl(AST_LPC_BASE + LPC_HICR4) | BIT_KCSENBL; ++ writel(val, AST_LPC_BASE + LPC_HICR4); ++ } else { ++ val = readl(AST_LPC_BASE + LPC_HICR0) & ~BIT_LPC3E; ++ writel(val, AST_LPC_BASE + LPC_HICR0); ++ val = readl(AST_LPC_BASE + LPC_HICR4) & ~BIT_KCSENBL; ++ writel(val, AST_LPC_BASE + LPC_HICR4); ++ val = readl(AST_LPC_BASE + LPC_HICR2) & ~BIT_IBFIE3; ++ writel(val, AST_LPC_BASE + LPC_HICR2); ++ } ++ break; ++ ++ case 4: ++ if (enable) { ++ val = readl(AST_LPC_BASE + LPC_HICRB) | BIT_IBFIE4 | ++ BIT_LPC4E; ++ writel(val, AST_LPC_BASE + LPC_HICRB); ++ } else { ++ val = readl(AST_LPC_BASE + LPC_HICRB) & ++ ~(BIT_IBFIE4 | BIT_LPC4E); ++ writel(val, AST_LPC_BASE + LPC_HICRB); ++ } ++ break; ++ ++ default: ++ DBG_KCS("Invalid channel (%d) specified\n", channel_num); ++ } ++} ++ ++void kcs_init(void) ++{ ++ /* Initialize the KCS channels. */ ++ for (u16 idx = 0; idx < NO_OF_ENABLED_KCS_CHANNELS; idx++) { ++ u16 channel_num = enabled_kcs_channel[idx]; ++ DBG_KCS("%s Channel: %d\n", __func__, channel_num); ++ set_kcs_channel_addr(channel_num); ++ enable_kcs_channel(channel_num, 1); ++ ++ /* Set KCS channel state to idle */ ++ set_kcs_state(channel_num, KCS_STATE_IDLE); ++ } ++ ++ /* KCS interrupt */ ++ request_irq(IRQ_SRC_LPC, kcs_irq_handler); ++} +diff --git a/board/aspeed/ast-g5/ast-g5-kcs.h b/board/aspeed/ast-g5/ast-g5-kcs.h +new file mode 100644 +index 0000000..52b5097 +--- /dev/null ++++ b/board/aspeed/ast-g5/ast-g5-kcs.h +@@ -0,0 +1,114 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* Copyright (c) 2018-2019 Intel Corporation */ ++ ++#include <asm/io.h> ++#include <common.h> ++ ++#include "ast-g5.h" ++ ++#define KCS_CHANNEL_MAX 4 ++#define IRQ_SRC_LPC 8 /* IRQ 8 */ ++#define MAX_KCS_PKT_SIZE (64 * 1024) ++/* KCS channel addresses */ ++#define KCS_CHANNEL1_ADDR 0xCA0 ++#define KCS_CHANNEL2_ADDR 0xCA8 ++#define KCS_CHANNEL3_ADDR 0xCA2 ++#define KCS_CHANNEL4_ADDR 0xCB2 ++ ++#define ZERO_DATA 0x00 ++ ++/* Aspeed KCS control registers */ ++#define LPC_HICR0 0x00 /* Host Interface Control Register 0 */ ++#define LPC_HICR1 0x04 /* Host Interface Control Register 1 */ ++#define LPC_HICR2 0x08 /* Host Interface Control Register 2 */ ++#define LPC_HICR3 0x0C /* Host Interface Control Register 3 */ ++#define LPC_HICR4 0x10 /* Host Interface Control Register 4 */ ++#define LPC_LADR3H 0x14 /* LPC channel #3 Address Register H */ ++#define LPC_LADR3L 0x18 /* LPC channel #3 Address Register H */ ++#define LPC_LADR12H 0x1C /* LPC channel #1#2 Address Register H */ ++#define LPC_LADR12L 0x20 /* LPC channel #1#2 Address Register L */ ++#define LPC_IDR1 0x24 /* Input Data Register 1 */ ++#define LPC_IDR2 0x28 /* Input Data Register 2 */ ++#define LPC_IDR3 0x2C /* Input Data Register 3 */ ++#define LPC_ODR1 0x30 /* Output Data Register 1 */ ++#define LPC_ODR2 0x34 /* Output Data Register 2 */ ++#define LPC_ODR3 0x38 /* Output Data Register 3 */ ++#define LPC_STR1 0x3C /* Status Register 1 */ ++#define LPC_STR2 0x40 /* Status Register 2 */ ++#define LPC_STR3 0x44 /* Status Register 3 */ ++ ++/* LPC Bits */ ++#define BIT_LADR12AS BIT(7) /* Channel Address selection */ ++#define BIT_IBFIE1 BIT(1) /* Enable IDR1 Recv completion interrupt */ ++#define BIT_IBFIE2 BIT(2) /* Enable IDR2 Recv completion interrupt */ ++#define BIT_IBFIE3 BIT(3) /* Enable IBF13 interrupt */ ++#define BIT_LPC1E BIT(5) /* Enable LPC channel #1 */ ++#define BIT_LPC2E BIT(6) /* Enable LPC channel #2 */ ++#define BIT_LPC3E BIT(7) /* Enable LPC channel #2 */ ++#define BIT_KCSENBL BIT(2) /* Enable KCS interface in Channel #3 */ ++ ++/* mapped to lpc-host@80 IO space */ ++#define LPC_HICRB 0x080 ++#define BIT_IBFIE4 BIT(1) ++#define BIT_LPC4E BIT(0) ++#define LPC_LADR4 0x090 ++#define LPC_IDR4 0x094 /* Input Data Register 4 */ ++#define LPC_ODR4 0x098 /* Output Data Register 4 */ ++#define LPC_STR4 0x09c /* Status Data Register 4 */ ++ ++#define BIT_STATUS_OBF BIT(0) /* Output Data Register full #1/#2/#3 */ ++#define BIT_STATUS_IBF BIT(1) /* Input Data Register full #1/#2/#3 */ ++#define BIT_STATUS_COD BIT(3) /* Command/Data - (1=command,0=data) */ ++ ++#define KCS_STATE_MASK 0xC0 /* BIT[6:7] of status register */ ++#define KCS_STATE(state) ((state) << 6) ++ ++/* IPMI2.0(section 9.7) - KCS interface State Bits */ ++#define KCS_STATE_IDLE 0x00 ++#define KCS_STATE_READ 0x01 ++#define KCS_STATE_WRITE 0x02 ++#define KCS_STATE_ERROR 0x03 ++ ++/* IPMI2.0(section 9.10) - KCS interface control codes */ ++#define KCS_CTRL_CODE_GET_STATUS_ABORT 0x60 ++#define KCS_CTRL_CODE_WRITE_START 0x61 ++#define KCS_CTRL_CODE_WRITE_END 0x62 ++#define KCS_CTRL_CODE_READ 0x68 ++ ++struct kcs_io_reg { ++ u32 idr; ++ u32 odr; ++ u32 str; ++}; ++ ++enum kcs_phase { ++ KCS_PHASE_IDLE = 0, ++ KCS_PHASE_WRITE_START = 1, ++ KCS_PHASE_WRITE_DATA = 2, ++ KCS_PHASE_WRITE_END = 3, ++ KCS_PHASE_READ_WAIT = 4, ++ KCS_PHASE_READ = 5, ++ KCS_PHASE_ABORT_1 = 6, ++ KCS_PHASE_ABORT_2 = 7, ++ KCS_PHASE_ERROR = 8 ++}; ++ ++enum kcs_error { ++ KCS_NO_ERROR = 0x00, ++ KCS_ABORT_BY_CMD = 0x01, ++ KCS_ILLEGAL_CTRL_CMD = 0x02, ++ KCS_LENGTH_ERROR = 0x06, ++ KCS_UNSPECIFIED_ERROR = 0xFF, ++}; ++ ++struct kcs_packet { ++ enum kcs_phase phase; ++ enum kcs_error error; ++ u16 channel; ++ bool read_req_done; ++ u16 data_in_idx; ++ u8 data_in[MAX_KCS_PKT_SIZE]; ++ u16 data_out_len; ++ u16 data_out_idx; ++ u8 data_out[MAX_KCS_PKT_SIZE]; ++}; +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-u-boot-env-change-for-PFR-image.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-u-boot-env-change-for-PFR-image.patch new file mode 100644 index 000000000..746063a56 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0022-u-boot-env-change-for-PFR-image.patch @@ -0,0 +1,35 @@ +From 6651a2663ee3e9f02c6ed8377097456528a2ee1a Mon Sep 17 00:00:00 2001 +From: Vikram Bodireddy <vikram.bodireddy@intel.com> +Date: Tue, 26 Mar 2019 20:34:51 +0530 +Subject: [PATCH] u-boot env change for PFR image + +Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com> +--- + include/configs/ast-common.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/configs/ast-common.h b/include/configs/ast-common.h +index b7d7192..dd89d91 100644 +--- a/include/configs/ast-common.h ++++ b/include/configs/ast-common.h +@@ -103,7 +103,7 @@ + #define CONFIG_SYS_MAX_FLASH_BANKS (CONFIG_FMC_CS) + #define CONFIG_SYS_MAX_FLASH_SECT (8192) /* max number of sectors on one chip */ + #define CONFIG_ENV_IS_IN_FLASH 1 +-#define CONFIG_ENV_OFFSET 0x2400000 /* environment starts here */ ++#define CONFIG_ENV_OFFSET 0xa0000 /* environment starts here */ + #define CONFIG_ENV_ADDR (AST_FMC_CS0_BASE + CONFIG_ENV_OFFSET) + #define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */ + +@@ -111,7 +111,7 @@ + #define CONFIG_ENV_ADDR_REDUND (AST_FMC_CS0_BASE + CONFIG_ENV_OFFSET_REDUND) + #define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE + +-#define CONFIG_BOOTCOMMAND "bootm 20080000" ++#define CONFIG_BOOTCOMMAND "bootm 21100000" + #define CONFIG_ENV_OVERWRITE + + #define ASPEED_ENV_SETTINGS \ +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0023-Add-TPM-enable-pulse-triggering.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0023-Add-TPM-enable-pulse-triggering.patch new file mode 100644 index 000000000..5e8cd103d --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0023-Add-TPM-enable-pulse-triggering.patch @@ -0,0 +1,52 @@ +From f762526077a7af02fc93bacc74fb9d49481d664f Mon Sep 17 00:00:00 2001 +From: Jae Hyun Yoo <jae.hyun.yoo@intel.com> +Date: Fri, 29 Mar 2019 12:30:20 -0700 +Subject: [PATCH] Add TPM enable pulse triggering + +This commit adds onboard TPM enable pulse triggering. + +Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com> +--- + board/aspeed/ast-g5/ast-g5-intel.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/board/aspeed/ast-g5/ast-g5-intel.c b/board/aspeed/ast-g5/ast-g5-intel.c +index f9955c70d2f2..d9ba4a47a413 100644 +--- a/board/aspeed/ast-g5/ast-g5-intel.c ++++ b/board/aspeed/ast-g5/ast-g5-intel.c +@@ -53,8 +53,8 @@ static const GPIOValue gpio_table[] = { + GPIO_DEBOUNCE_8MS}, + + /* Enable Pulse -- pin D6 */ +- [GPIO_ENABLE_TPM_PULSE] = {PORT_PIN(GPIO_PORT_D, GPIO_PIN_6), +- GPIO_CFG_DEFAULT, 0, GPIO_DEBOUNCE_8MS}, ++ [GPIO_ENABLE_TPM_PULSE] = {TPM_EN_PULSE_PORT_PIN, GPCFG_OUTPUT_EN, 0, ++ GPIO_DEBOUNCE_NONE}, + }; + + #define LPC_SNOOP_ADDR 0x80 +@@ -232,6 +232,13 @@ void id_led_control(int id, int action) + gpio_set_value(s_led_info[id].gpio, s_led_info[id].state); + } + ++static void enable_onboard_tpm(void) ++{ ++ gpio_set_value(GPIO_ENABLE_TPM_PULSE, 1); ++ mdelay(50); ++ gpio_set_value(GPIO_ENABLE_TPM_PULSE, 0); ++} ++ + static void timer8_irq_handler(void *regs) + { + int i; +@@ -445,6 +452,7 @@ void ast_g5_intel(void) + espi_init(); + sgpio_init(); + timer8_init(); ++ enable_onboard_tpm(); + if (intel_force_firmware_jumper_enabled()) { + id_led_control(GPIO_AMBER_LED, EIDLED_On); + kcs_init(); +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0024-IPMI-command-handler-implementation-in-uboot.patch b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0024-IPMI-command-handler-implementation-in-uboot.patch new file mode 100644 index 000000000..47cb56062 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-bsp/u-boot/files/0024-IPMI-command-handler-implementation-in-uboot.patch @@ -0,0 +1,339 @@ +From d770ea7a30742339b0692858847838dd2a738aeb Mon Sep 17 00:00:00 2001 +From: AppaRao Puli <apparao.puli@linux.intel.com> +Date: Fri, 5 Apr 2019 17:53:21 +0530 +Subject: [PATCH] IPMI command handler implementation in uboot + +IPMI command handler implemtation in uBoot. +Implemented IPMI commands: + 1) Get Device ID + 2) Get Self Test Result + +Tested By: +Ran the above IPMI command Via KCS channel +and got proper response. +- Get Device ID + Req: cmdtool.efi 20 18 1 + Res: 0x00 0x23 0x00 0x82 0x03 0x02 0x00 0x57 0x01 0x00 0x7b 0x00 0x00 0x00 0x00 0x00 +- Get Self Test Results + Req: cmdtool.efi 20 18 4 + Res: 00 56 00 + +Change-Id: I18b205bc45c34f7c4ef16adc29fa5bd494624ceb +Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> +--- + board/aspeed/ast-g5/Makefile | 1 + + board/aspeed/ast-g5/ast-g5-kcs.c | 78 +++++++++++++----------- + board/aspeed/ast-g5/ipmi-handler.c | 118 +++++++++++++++++++++++++++++++++++++ + board/aspeed/ast-g5/ipmi-handler.h | 40 +++++++++++++ + 4 files changed, 202 insertions(+), 35 deletions(-) + create mode 100644 board/aspeed/ast-g5/ipmi-handler.c + create mode 100644 board/aspeed/ast-g5/ipmi-handler.h + +diff --git a/board/aspeed/ast-g5/Makefile b/board/aspeed/ast-g5/Makefile +index 05972b9..f28fcfe 100644 +--- a/board/aspeed/ast-g5/Makefile ++++ b/board/aspeed/ast-g5/Makefile +@@ -5,3 +5,4 @@ obj-y += ast-g5-irq.o + obj-y += ast-g5-gpio.o + obj-y += ast-g5-timer.o + obj-y += ast-g5-kcs.o ++obj-y += ipmi-handler.o +diff --git a/board/aspeed/ast-g5/ast-g5-kcs.c b/board/aspeed/ast-g5/ast-g5-kcs.c +index f983b4a..05b1cc2 100644 +--- a/board/aspeed/ast-g5/ast-g5-kcs.c ++++ b/board/aspeed/ast-g5/ast-g5-kcs.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 + // Copyright (c) 2018-2019 Intel Corporation + +-#include "ast-g5-kcs.h" ++#include "ipmi-handler.h" + + #define DEBUG_KCS_ENABLED 0 + #ifdef DEBUG_KCS_ENABLED +@@ -10,11 +10,6 @@ + #define DBG_KCS(...) + #endif + +-/* TODO: Move to IPMI file. */ +-#define IPMI_CC_OK 0x00 +-#define IPMI_CC_INVALID 0xC1 +-#define IPMI_CC_UNSPECIFIED 0xFF +- + #define KCS_CHANNEL_NO_3 3 + + static const u16 enabled_kcs_channel[] = { KCS_CHANNEL_NO_3 }; +@@ -104,13 +99,13 @@ static void init_kcs_packet(u16 channel_num) + static void process_kcs_request(u16 channel_num) + { + struct kcs_packet *kcs_pkt = NULL; ++ struct ipmi_cmd_data ipmi_data; + + kcs_pkt = get_kcs_packet(channel_num); + if (!kcs_pkt->read_req_done) + return; + + DBG_KCS("%s:- chan:%d\n", __func__, channel_num); +- + #ifdef DEBUG_KCS_ENABLED + int i; + +@@ -119,37 +114,49 @@ static void process_kcs_request(u16 channel_num) + DBG_KCS(" 0x%02x", kcs_pkt->data_in[i]); + DBG_KCS("\n"); + #endif ++ u8 req_lun = kcs_pkt->data_in[0] & 0x03; /* LUN[1:0] */ ++ ipmi_data.net_fun = (kcs_pkt->data_in[0] >> 2); /* netfn[7:2] */ ++ ipmi_data.cmd = kcs_pkt->data_in[1]; /* cmd */ ++ /* We support only BMC LUN 00h */ ++ if (req_lun != LUN_BMC) { ++ kcs_pkt->data_out[0] = ++ GET_RESP_NETFN_LUN(req_lun, ipmi_data.net_fun); ++ kcs_pkt->data_out[1] = ipmi_data.cmd; /* cmd */ ++ kcs_pkt->data_out[2] = IPMI_CC_INVALID_CMD_LUN; /* CC code */ ++ kcs_pkt->data_out_len = 3; ++ goto done; ++ } + +- /* +- * TODO: Move it to IPMI Command Handler +- * Below code is added for timebeing till +- * we implement the IPMI command handler. +- */ +- kcs_pkt->data_out[0] = kcs_pkt->data_in[0]; /* netfn */ +- kcs_pkt->data_out[1] = kcs_pkt->data_in[1]; /* cmd */ +- kcs_pkt->data_out[2] = IPMI_CC_OK; /* cc */ +- +- if (((kcs_pkt->data_in[0] >> 2) == 0x06) && +- (kcs_pkt->data_in[1] == 0x01)) { +- /* Get Device ID */ +- u8 device_id[15] = { 0x23, 0x00, 0x12, 0x03, 0x02, +- 0xBF, 0x57, 0x01, 0x00, 0x7B, +- 0x00, 0x00, 0x00, 0x00, 0x00 }; +- for (i = 0; i < 15; i++) +- kcs_pkt->data_out[i + 3] = device_id[i]; +- kcs_pkt->data_out_len = 18; +- } else if (((kcs_pkt->data_in[0] >> 2) == 0x06) && +- (kcs_pkt->data_in[1] == 0x04)) { +- /* Get Self Test Results */ +- kcs_pkt->data_out[3] = 0x56; +- kcs_pkt->data_out[4] = 0x00; +- kcs_pkt->data_out_len = 5; +- } else { +- kcs_pkt->data_out[2] = +- IPMI_CC_INVALID; /* Invalid or not supported. */ ++ /* Boundary check */ ++ if ((kcs_pkt->data_in_idx - 2) > sizeof(ipmi_data.req_data)) { ++ kcs_pkt->data_out[0] = ++ GET_RESP_NETFN_LUN(req_lun, ipmi_data.net_fun); ++ kcs_pkt->data_out[1] = ipmi_data.cmd; /* cmd */ ++ kcs_pkt->data_out[2] = IPMI_CC_OUT_OF_SPACE; /* CC code */ + kcs_pkt->data_out_len = 3; ++ goto done; + } +- /* END: TODO */ ++ /* Fill in IPMI request data */ ++ ipmi_data.req_len = kcs_pkt->data_in_idx - 2; ++ for (i = 0; i < kcs_pkt->data_in_idx - 2; i++) ++ ipmi_data.req_data[i] = kcs_pkt->data_in[i + 2]; ++ ++ /* Call IPMI command handler */ ++ ipmi_cmd_handler(&ipmi_data); ++ ++ /* Get IPMI response and fill KCS out data */ ++ /* First 2 bytes in KCS response are netFn, Cmd */ ++ kcs_pkt->data_out[0] = GET_RESP_NETFN_LUN(req_lun, ipmi_data.net_fun); ++ kcs_pkt->data_out[1] = ipmi_data.cmd; ++ if ((ipmi_data.res_len + 2) > sizeof(kcs_pkt->data_out)) { ++ kcs_pkt->data_out[2] = IPMI_CC_UNSPECIFIED; /* CC code */ ++ kcs_pkt->data_out_len = 3; ++ goto done; ++ } ++ for (i = 0; i < ipmi_data.res_len; i++) ++ kcs_pkt->data_out[i + 2] = ipmi_data.res_data[i]; ++ ++ kcs_pkt->data_out_len = ipmi_data.res_len + 2; + + #ifdef DEBUG_KCS_ENABLED + DBG_KCS("Response data(Len:%d): ", kcs_pkt->data_out_len); +@@ -158,6 +165,7 @@ static void process_kcs_request(u16 channel_num) + DBG_KCS("\n"); + #endif + ++done: + kcs_pkt->phase = KCS_PHASE_READ; + write_data(channel_num, kcs_pkt->data_out[kcs_pkt->data_out_idx++]); + kcs_pkt->read_req_done = false; +diff --git a/board/aspeed/ast-g5/ipmi-handler.c b/board/aspeed/ast-g5/ipmi-handler.c +new file mode 100644 +index 0000000..9cccee9 +--- /dev/null ++++ b/board/aspeed/ast-g5/ipmi-handler.c +@@ -0,0 +1,118 @@ ++ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (c) 2018-2019 Intel Corporation ++ ++#include "ipmi-handler.h" ++ ++/* IPMI network function codes */ ++#define NETFN_APP 0x06 ++ ++/* IPMI command codes */ ++#define CMD_GET_DEV_ID 0x01 ++#define CMD_GET_SELF_TEST_RESULTS 0x04 ++ ++typedef u16 (*fun_handler)(u8 *req, u16 req_len, u8 *res); ++ ++struct get_dev_id { ++ u8 completion_code; ++ u8 dev_id; ++ u8 dev_rev; ++ u8 fw_rev1; ++ u8 fw_rev2; ++ u8 ipmi_ver; ++ u8 dev_support; ++ u8 mfg_id[3]; ++ u8 product_id[2]; ++ u8 aux_fw_rev[4]; ++}; ++struct self_test_res { ++ u8 completion_code; ++ u8 res_byte[2]; ++}; ++ ++struct ipmi_cmd_table { ++ u8 net_fun; ++ u8 cmd; ++ fun_handler process_cmd; ++}; ++ ++static u16 get_device_id(u8 *req, u16 req_len, u8 *res) ++{ ++ /* Get Device ID */ ++ bool operation = 1; /* Firmware operation */ ++ u8 intel_mfg_id[3] = { 0x57, 0x01, 0x00 }; ++ u8 platform_id[2] = { 0x7B, 0x00 }; ++ u8 aux_fw_rev[4] = { 0x00, 0x00, 0x00, 0x00 }; ++ struct get_dev_id *result = (struct get_dev_id *)res; ++ ++ if (req_len != 0) { ++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; ++ return sizeof(result->completion_code); ++ } ++ ++ result->completion_code = IPMI_CC_OK; ++ result->dev_id = 0x23; ++ result->dev_rev = 0x00; /* Not provides dev SDR */ ++ ++ result->ipmi_ver = 0x02; /* IPMI 2.0 */ ++ result->dev_support = 0x00; /* No dev support in this mode */ ++ memcpy(result->mfg_id, intel_mfg_id, sizeof(result->mfg_id)); ++ memcpy(result->aux_fw_rev, aux_fw_rev, sizeof(result->aux_fw_rev)); ++ ++ /* TODO: Get Firmware version from flash(PFM Header) */ ++ result->fw_rev1 = ((operation << 7) | (0x02 & 0x7F)); ++ result->fw_rev2 = 0x03; ++ /* TODO: Read Platform ID from GPIO */ ++ memcpy(result->product_id, platform_id, sizeof(result->product_id)); ++ ++ return sizeof(struct get_dev_id); ++} ++ ++static u16 get_self_test_result(u8 *req, u16 req_len, u8 *res) ++{ ++ /* Get Self Test Results */ ++ struct self_test_res *result = (struct self_test_res *)res; ++ ++ if (req_len != 0) { ++ result->completion_code = IPMI_CC_INVALID_DATA_LENGTH; ++ return sizeof(result->completion_code); ++ } ++ ++ result->completion_code = IPMI_CC_OK; ++ result->res_byte[0] = 0x56; /* Self test function not implemented. */ ++ result->res_byte[1] = 0x00; ++ ++ return sizeof(struct self_test_res); ++} ++ ++const struct ipmi_cmd_table cmd_info[] = { ++ { NETFN_APP, CMD_GET_DEV_ID, get_device_id }, ++ { NETFN_APP, CMD_GET_SELF_TEST_RESULTS, get_self_test_result } ++}; ++ ++#define CMD_TABLE_SIZE ARRAY_SIZE(cmd_info) ++ ++void ipmi_cmd_handler(struct ipmi_cmd_data *ipmi_data) ++{ ++ int i = 0; ++ for (i = 0; i < CMD_TABLE_SIZE; i++) { ++ if ((cmd_info[i].net_fun == ipmi_data->net_fun) && ++ (cmd_info[i].cmd == ipmi_data->cmd)) { ++ break; ++ } ++ } ++ ++ if (i == CMD_TABLE_SIZE) { ++ /* Invalid or not supported. */ ++ ipmi_data->res_data[0] = IPMI_CC_INVALID_CMD; ++ ipmi_data->res_len = 1; ++ return; ++ } ++ ++ /* Call the appropriate function handler */ ++ ipmi_data->res_len = ++ cmd_info[i].process_cmd(ipmi_data->req_data, ipmi_data->req_len, ++ &ipmi_data->res_data[0]); ++ ++ return; ++} +diff --git a/board/aspeed/ast-g5/ipmi-handler.h b/board/aspeed/ast-g5/ipmi-handler.h +new file mode 100644 +index 0000000..9d46d9b +--- /dev/null ++++ b/board/aspeed/ast-g5/ipmi-handler.h +@@ -0,0 +1,40 @@ ++ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* Copyright (c) 2018-2019 Intel Corporation */ ++ ++#include "ast-g5-kcs.h" ++ ++/* IPMI completion codes */ ++#define IPMI_CC_OK 0x00 ++#define IPMI_CC_NODE_BUSY 0xC0 ++#define IPMI_CC_INVALID_CMD 0xC1 ++#define IPMI_CC_INVALID_CMD_LUN 0xC2 ++#define IPMI_CC_OUT_OF_SPACE 0xC4 ++#define IPMI_CC_INVALID_DATA_LENGTH 0xC7 ++#define IPMI_CC_INVALID_DATA_FIELD 0xCC ++#define IPMI_CC_UNSPECIFIED 0xFF ++ ++/* BMC IPMB LUNs */ ++#define LUN_BMC 0x00 ++#define LUN_OEM1 0x01 ++#define LUN_SMS 0x02 ++#define LUN_OEM2 0x01 ++ ++ ++#define MAX_IPMI_REQ_DATA_SIZE MAX_KCS_PKT_SIZE ++#define MAX_IPMI_RES_DATA_SIZE 64 ++ ++/* Response netFn[7:2], Lun[1:0] */ ++#define GET_RESP_NETFN_LUN(lun, netfn) \ ++ ((lun & 0x03) | (((netfn + 1) << 2) & 0xFD)) ++ ++struct ipmi_cmd_data { ++ u8 net_fun; ++ u8 cmd; ++ u16 req_len; ++ u16 res_len; ++ u8 req_data[MAX_IPMI_REQ_DATA_SIZE]; ++ u8 res_data[MAX_IPMI_RES_DATA_SIZE]; ++}; ++ ++void ipmi_cmd_handler(struct ipmi_cmd_data *ipmi_data); +-- +2.7.4 + |