From b99f00b7f974faec2329f21100f72e0a332be1f2 Mon Sep 17 00:00:00 2001 From: Divya Jyothi Date: Thu, 14 May 2015 10:11:13 -0700 Subject: mec1322: Added support for sysjump. changes added to support flashrom are: sysjump support to be able to copy the RO/RW image and jump to it without causing AP to reboot while its alreday ON. LPC init should be reinitialized on sysjump corrected gpio_set_flags_by_mask to make sure we update the register only for GPIO_LOW condition and not all else conditions. BUG=chrome-os-partner:38103 TEST=commands : flashrom -p ec -w ec.bin flashrom -p ec -r ec.bin BRANCH=none Change-Id: I23892f0378d756052030e73034c3acdd41477e34 Signed-off-by: Divya Jyothi Signed-off-by: Shamile Khan Reviewed-on: https://chromium-review.googlesource.com/272000 Reviewed-by: Shawn N --- chip/mec1322/config_chip.h | 6 +----- chip/mec1322/gpio.c | 23 +++++++++++++++++--- chip/mec1322/lfw/ec_lfw.c | 41 +++++++++++++++++++++++++++-------- chip/mec1322/lpc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++- chip/mec1322/registers.h | 5 +++++ chip/mec1322/system.c | 42 +++++++++++++++++++++++++++++++----- chip/npcx/system.c | 33 +++++++++++----------------- common/system.c | 4 +++- include/system.h | 20 +++++++++++++---- 9 files changed, 179 insertions(+), 49 deletions(-) diff --git a/chip/mec1322/config_chip.h b/chip/mec1322/config_chip.h index 49131ec243..8257b03d32 100644 --- a/chip/mec1322/config_chip.h +++ b/chip/mec1322/config_chip.h @@ -156,12 +156,8 @@ which contains Loader and RO Images */ #define CONFIG_RW_IMAGE_FLASHADDR (CONFIG_FLASH_BASE_SPI + \ CONFIG_RW_STORAGE_OFF) -/* Memory Lcation shared between lfw and RO /RW image */ -#define SHARED_RAM_LFW_RORW (CONFIG_MEC_SRAM_BASE_START + \ - (CONFIG_LOADER_SIZE - 4)) - /* Non-memmapped, external SPI */ -/* #define CONFIG_CODERAM_ARCH */ +#define CONFIG_CODERAM_ARCH #undef CONFIG_FLASH_MAPPED #undef CONFIG_FLASH_PSTATE #define CONFIG_SPI_FLASH diff --git a/chip/mec1322/gpio.c b/chip/mec1322/gpio.c index 5c894a2daa..256e674ca2 100644 --- a/chip/mec1322/gpio.c +++ b/chip/mec1322/gpio.c @@ -9,6 +9,7 @@ #include "gpio.h" #include "hooks.h" #include "registers.h" +#include "system.h" #include "task.h" #include "timer.h" #include "util.h" @@ -134,7 +135,7 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) if (flags & GPIO_HIGH) MEC1322_GPIO_CTL(port, i) |= (1 << 16); - else + else if (flags & GPIO_LOW) MEC1322_GPIO_CTL(port, i) &= ~(1 << 16); } } @@ -177,10 +178,26 @@ int gpio_disable_interrupt(enum gpio_signal signal) void gpio_pre_init(void) { int i; + int flags; + int is_warm = gpio_is_reboot_warm(); const struct gpio_info *g = gpio_list; - for (i = 0; i < GPIO_COUNT; i++, g++) - gpio_set_flags_by_mask(g->port, g->mask, g->flags); + + for (i = 0; i < GPIO_COUNT; i++, g++) { + flags = g->flags; + + if (flags & GPIO_DEFAULT) + continue; + + /* + * If this is a warm reboot, don't set the output levels or + * we'll shut off the AP. + */ + if (is_warm) + flags &= ~(GPIO_LOW | GPIO_HIGH); + + gpio_set_flags_by_mask(g->port, g->mask, flags); + } } /* Clear any interrupt flags before enabling GPIO interrupt */ diff --git a/chip/mec1322/lfw/ec_lfw.c b/chip/mec1322/lfw/ec_lfw.c index 2ceaa35644..cd811b1c22 100644 --- a/chip/mec1322/lfw/ec_lfw.c +++ b/chip/mec1322/lfw/ec_lfw.c @@ -25,9 +25,6 @@ #include "ec_lfw.h" -static uintptr_t *const image_type = (uintptr_t *const) SHARED_RAM_LFW_RORW; - - __attribute__ ((section(".intvector"))) const struct int_vector_t hdr_int_vect = { (void *)0x11FA00, /* init sp, unused, @@ -85,18 +82,18 @@ static int spi_flash_readloc(uint8_t *buf_usr, return spi_transaction(cmd, 4, buf_usr, bytes); } -int spi_rwimage_load(void) +int spi_image_load(uint32_t offset) { uint8_t *buf = (uint8_t *) (CONFIG_RW_MEM_OFF + CONFIG_FLASH_BASE); uint32_t i; - memset((void *)buf, 0xFF, (CONFIG_RW_SIZE - 4)); + memset((void *)buf, 0xFF, (CONFIG_FW_IMAGE_SIZE - 4)); spi_enable(1); - for (i = 0; i < CONFIG_RW_SIZE; i += SPI_CHUNK_SIZE) + for (i = 0; i < CONFIG_FW_IMAGE_SIZE; i += SPI_CHUNK_SIZE) spi_flash_readloc(&buf[i], - CONFIG_RW_IMAGE_FLASHADDR + i, + offset + i, SPI_CHUNK_SIZE); spi_enable(0); @@ -206,6 +203,24 @@ void uart_init(void) gpio_config_module(MODULE_UART, 1); } +void system_init(void) +{ + + uint32_t status = MEC1322_VBAT_STS; + uint32_t wdt_cnt = MEC1322_EC_WDT_CNT; + + /* Reset the image type if reset cause is power-on */ + if (status & (1 << 7) || (wdt_cnt == 0)) + MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX) + = SYSTEM_IMAGE_UNKNOWN; +} + + +enum system_image_copy_t system_get_image_copy(void) +{ + return MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX); +} + void lfw_main() { @@ -219,17 +234,25 @@ void lfw_main() cpu_init(); dma_init(); uart_init(); + system_init(); uart_puts("littlefw"); uart_puts(version_data.version); uart_puts("\n"); - switch (*image_type) { + switch (system_get_image_copy()) { case SYSTEM_IMAGE_RW: + uart_puts("lfw-RW load\n"); init_addr = CONFIG_RW_MEM_OFF + CONFIG_FLASH_BASE; - spi_rwimage_load(); + spi_image_load(CONFIG_RW_IMAGE_FLASHADDR); + break; case SYSTEM_IMAGE_RO: + uart_puts("lfw-RO load\n"); + spi_image_load(CONFIG_RO_IMAGE_FLASHADDR); + /* fall through */ default: + MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX) = + SYSTEM_IMAGE_RO; init_addr = CONFIG_RO_MEM_OFF + CONFIG_FLASH_BASE; } diff --git a/chip/mec1322/lpc.c b/chip/mec1322/lpc.c index 673edfe62d..7cdc120330 100644 --- a/chip/mec1322/lpc.c +++ b/chip/mec1322/lpc.c @@ -14,6 +14,7 @@ #include "lpc.h" #include "port80.h" #include "registers.h" +#include "system.h" #include "task.h" #include "timer.h" #include "util.h" @@ -22,6 +23,8 @@ #define CPUTS(outstr) cputs(CC_LPC, outstr) #define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) +#define LPC_SYSJUMP_TAG 0x4c50 /* "LP" */ + static uint8_t mem_mapped[0x200] __attribute__((section(".bss.big_align"))); static uint32_t host_events; /* Currently pending SCI/SMI events */ @@ -180,6 +183,34 @@ static void lpc_send_response_packet(struct host_packet *pkt) MEC1322_ACPI_EC_STATUS(1) &= ~EC_LPC_STATUS_PROCESSING; } +/** + * Preserve event masks across a sysjump. + */ +static void lpc_sysjump(void) +{ + system_add_jump_tag(LPC_SYSJUMP_TAG, 1, + sizeof(event_mask), event_mask); +} +DECLARE_HOOK(HOOK_SYSJUMP, lpc_sysjump, HOOK_PRIO_DEFAULT); + +/** + * Restore event masks after a sysjump. + */ +static void lpc_post_sysjump(void) +{ + const uint32_t *prev_mask; + int size, version; + + prev_mask = (const uint32_t *)system_get_jump_tag(LPC_SYSJUMP_TAG, + &version, &size); + if (!prev_mask || version != 1 || size != sizeof(event_mask)) + return; + + memcpy(event_mask, prev_mask, sizeof(event_mask)); +} + + + /* * Most registers in LPC module are reset when the host is off. We need to * set up LPC again when the host is starting up. @@ -257,6 +288,20 @@ static void setup_lpc(void) } DECLARE_HOOK(HOOK_CHIPSET_STARTUP, setup_lpc, HOOK_PRIO_FIRST); +static void lpc_resume(void) +{ + /* Mask all host events until the host unmasks them itself. */ + lpc_set_host_event_mask(LPC_HOST_EVENT_SMI, 0); + lpc_set_host_event_mask(LPC_HOST_EVENT_SCI, 0); + lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, 0); + + /* Store port 80 event so we know where resume happened */ + port_80_write(PORT_80_EVENT_RESUME); +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, lpc_resume, HOOK_PRIO_DEFAULT); + + + static void lpc_init(void) { /* Activate LPC interface */ @@ -265,6 +310,13 @@ static void lpc_init(void) /* Initialize host args and memory map to all zero */ memset(lpc_host_args, 0, sizeof(*lpc_host_args)); memset(lpc_get_memmap_range(), 0, EC_MEMMAP_SIZE); + + setup_lpc(); + + /* Restore event masks if needed */ + lpc_post_sysjump(); + + } /* * Set prio to higher than default; this way LPC memory mapped data is ready @@ -508,7 +560,7 @@ int lpc_get_pltrst_asserted(void) /* On boards without a host, this command is used to set up LPC */ static int lpc_command_init(int argc, char **argv) { - setup_lpc(); + lpc_init(); return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(lpcinit, lpc_command_init, NULL, NULL, NULL); diff --git a/chip/mec1322/registers.h b/chip/mec1322/registers.h index 1c21e9b8bf..b7a8612f83 100644 --- a/chip/mec1322/registers.h +++ b/chip/mec1322/registers.h @@ -130,6 +130,11 @@ static inline uintptr_t gpio_port_base(int port_id) #define MEC1322_VBAT_CE REG32(MEC1322_VBAT_BASE + 0x8) #define MEC1322_VBAT_RAM(x) REG32(MEC1322_VBAT_BASE + 0x400 + 4 * (x)) +/* Miscellaneous firmware control fields + * scratch pad index cannot be more than 16 as + * mec has 64 bytes = 16 indexes of scratchpad RAM + */ +#define MEC1322_IMAGETYPE_IDX 15 /* LPC */ #define MEC1322_LPC_CFG_BASE 0x400f3300 diff --git a/chip/mec1322/system.c b/chip/mec1322/system.c index 2460dc51b2..b779bac26c 100644 --- a/chip/mec1322/system.c +++ b/chip/mec1322/system.c @@ -14,6 +14,7 @@ #include "registers.h" #include "shared_mem.h" #include "system.h" +#include "hooks.h" #include "task.h" #include "timer.h" #include "util.h" @@ -60,6 +61,27 @@ static void check_reset_cause(void) system_set_reset_flags(flags); } +/* TODO(crbug.com/40789): Rename this function system_is_reboot_warm */ +int gpio_is_reboot_warm(void) +{ + uint32_t reset_flags; + /* + * Check reset cause here, + * gpio_pre_init is executed faster than system_pre_init + */ + check_reset_cause(); + reset_flags = system_get_reset_flags(); + + if ((reset_flags & RESET_FLAG_RESET_PIN) || + (reset_flags & RESET_FLAG_POWER_ON) || + (reset_flags & RESET_FLAG_WATCHDOG) || + (reset_flags & RESET_FLAG_HARD) || + (reset_flags & RESET_FLAG_SOFT)) + return 0; + else + return 1; +} + void system_pre_init(void) { /* Enable direct NVIC */ @@ -71,6 +93,10 @@ void system_pre_init(void) /* Deassert nSIO_RESET */ MEC1322_PCR_PWR_RST_CTL &= ~(1 << 0); + if (MEC1322_VBAT_RAM(HIBDATA_INDEX_SAVED_RESET_FLAGS) & + RESET_FLAG_POWER_ON) + MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX) = 0; + check_reset_cause(); } @@ -370,14 +396,20 @@ void htimer_interrupt(void) } DECLARE_IRQ(MEC1322_IRQ_HTIMER, htimer_interrupt, 1); -/* TODO(crosbug.com/p/37510): Implement bootloader */ enum system_image_copy_t system_get_shrspi_image_copy(void) { - return SYSTEM_IMAGE_RW; + return MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX); +} + +uint32_t system_get_lfw_address(void) +{ + uint32_t * const lfw_vector = (uint32_t * const) CONFIG_FLASH_BASE; + + return *(lfw_vector + 1); } -/* TODO(crosbug.com/p/37510): Implement bootloader */ -uint32_t system_get_lfw_address(uint32_t flash_addr) +void system_set_image_copy(enum system_image_copy_t copy) { - return CONFIG_RO_MEM_OFF; + MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX) = (copy == SYSTEM_IMAGE_RW) ? + SYSTEM_IMAGE_RW : SYSTEM_IMAGE_RO; } diff --git a/chip/npcx/system.c b/chip/npcx/system.c index a103292e0e..e1ae1c134a 100644 --- a/chip/npcx/system.c +++ b/chip/npcx/system.c @@ -19,11 +19,6 @@ #include "hwtimer_chip.h" #include "system_chip.h" -#ifdef CONFIG_CODERAM_ARCH -/* base address for jumping */ -uint32_t base_addr; -#endif - /* Flags for BBRM_DATA_INDEX_WAKE */ #define HIBERNATE_WAKE_MTC (1 << 0) /* MTC alarm */ #define HIBERNATE_WAKE_PIN (1 << 1) /* Wake pin */ @@ -829,16 +824,25 @@ void system_lpc_host_register_init(void){ system_sib_write_reg(SIO_OFFSET, 0x30, 0x01); } #ifdef CONFIG_CODERAM_ARCH -uint32_t system_get_lfw_address(uint32_t flash_addr) +uint32_t system_get_lfw_address(void) { /* Little FW located on top of flash - 4K */ uint32_t jump_addr = (CONFIG_FLASH_BASE + CONFIG_SPI_FLASH_SIZE - CONFIG_LFW_OFFSET + 1); - /* restore base address for jumping*/ - base_addr = flash_addr; + return jump_addr; } +void system_set_image_copy(enum system_image_copy_t copy) +{ + /* Jump to RO region -- set flag */ + if (copy == SYSTEM_IMAGE_RO) + SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION); + else /* Jump to RW region -- clear flag */ + CLEAR_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION); + +} + enum system_image_copy_t system_get_shrspi_image_copy(void) { /* RO region FW */ @@ -847,17 +851,4 @@ enum system_image_copy_t system_get_shrspi_image_copy(void) else/* RW region FW */ return SYSTEM_IMAGE_RW; } - -/** - * Set flag for jumping across a sysjump. - */ -static void system_sysjump(void) -{ - /* Jump to RO region -- set flag */ - if (base_addr == CONFIG_FLASH_BASE + CONFIG_RO_MEM_OFF) - SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION); - else /* Jump to RW region -- clear flag */ - CLEAR_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION); -} -DECLARE_HOOK(HOOK_SYSJUMP, system_sysjump, HOOK_PRIO_DEFAULT); #endif diff --git a/common/system.c b/common/system.c index 821cfd7cd3..64f2b24579 100644 --- a/common/system.c +++ b/common/system.c @@ -494,7 +494,9 @@ int system_run_image_copy(enum system_image_copy_t copy) #ifdef CONFIG_CODERAM_ARCH /* Jump to little FW for code ram architecture */ - init_addr = system_get_lfw_address(base); + init_addr = system_get_lfw_address(); + + system_set_image_copy(copy); #else /* Make sure the reset vector is inside the destination image */ init_addr = *(uintptr_t *)(base + 4); diff --git a/include/system.h b/include/system.h index 259e34fc92..c55e4a0f2e 100644 --- a/include/system.h +++ b/include/system.h @@ -371,20 +371,32 @@ void system_reset_rtc_alarm(void); #ifdef CONFIG_CODERAM_ARCH /** - * Determine which address should be jumped and return address of littel FW + * Return address of little FW to prepare for sysjump * * Note: This feature is used for code ram arch * - * @param flash_addr jump address of spi flash for RO or RW region */ -uint32_t system_get_lfw_address(uint32_t flash_addr); +uint32_t system_get_lfw_address(void); /** - * Return whcih region is used in Code RAM + * Setup the destination image for a sysjump + * + * Note: This is called for devices with code ram arc by system code + * just before the jump to the little firmware. It should store the + * destination image so that it will be available to the little + * firmware after the jump. + * + * @param copy Region - (RO/RW) to use in code ram + */ +void system_set_image_copy(enum system_image_copy_t copy); + +/** + * Return which region is used in Code RAM * * Note: This feature is used for code ram arch * */ enum system_image_copy_t system_get_shrspi_image_copy(void); + #endif #endif /* __CROS_EC_SYSTEM_H */ -- cgit v1.2.1