mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 17:11:42 +00:00
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:
committed by
ChromeOS Commit Bot
parent
5ea69a7b3b
commit
b99f00b7f9
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user