summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/mec1322/config_chip.h6
-rw-r--r--chip/mec1322/gpio.c23
-rw-r--r--chip/mec1322/lfw/ec_lfw.c41
-rw-r--r--chip/mec1322/lpc.c54
-rw-r--r--chip/mec1322/registers.h5
-rw-r--r--chip/mec1322/system.c42
-rw-r--r--chip/npcx/system.c33
-rw-r--r--common/system.c4
-rw-r--r--include/system.h20
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 */