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 <divya.jyothi@intel.com>
Signed-off-by: Shamile Khan <shamile.khan@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/272000
Reviewed-by: Shawn N <shawnn@chromium.org>
This commit is contained in:
Divya Jyothi
2015-05-14 10:11:13 -07:00
committed by ChromeOS Commit Bot
parent 5ea69a7b3b
commit b99f00b7f9
9 changed files with 179 additions and 49 deletions

View File

@@ -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

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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);
}
/* TODO(crosbug.com/p/37510): Implement bootloader */
uint32_t system_get_lfw_address(uint32_t flash_addr)
uint32_t system_get_lfw_address(void)
{
return CONFIG_RO_MEM_OFF;
uint32_t * const lfw_vector = (uint32_t * const) CONFIG_FLASH_BASE;
return *(lfw_vector + 1);
}
void system_set_image_copy(enum system_image_copy_t copy)
{
MEC1322_VBAT_RAM(MEC1322_IMAGETYPE_IDX) = (copy == SYSTEM_IMAGE_RW) ?
SYSTEM_IMAGE_RW : SYSTEM_IMAGE_RO;
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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 */