diff options
author | Andrey Petrov <andrey.petrov@intel.com> | 2015-04-16 17:25:44 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-04-23 00:13:55 +0000 |
commit | 279de61f843d6d364c88110d0bb12e91d314f0ba (patch) | |
tree | 6776857ce6585c7035298544e6a6785ef7fa78ad /chip | |
parent | 269c330f0e32a2c26e03fc932f9b02426ee09b79 (diff) | |
download | chrome-ec-279de61f843d6d364c88110d0bb12e91d314f0ba.tar.gz |
mec1322: initial version of lfw loader
lfw is a customized boot loader with max targeted code size of 4k
and data size of 2k.It supports minimal functionalities required to
support chromebooks RO/RW architecture.It is placed in the
write porected section with RO image .
Capabilities include SPI,DMA,UART with minimal debugging support.
Currently sysjump support is missing and exception handling is very basic.
BUG=chromium:37510
TEST=make buildall -j, flashing and booting on strago
BRANCH=None
Change-Id: I803998d489297dfe0745dcccbb54412035d73f78
Signed-off-by: Andrey Petrov <andrey.petrov@intel.com>
Signed-off-by: Divya Jyothi <divya.jyothi@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/265904
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/mec1322/build.mk | 29 | ||||
-rw-r--r-- | chip/mec1322/lfw/ec_lfw.c | 241 | ||||
-rw-r--r-- | chip/mec1322/lfw/ec_lfw.h | 21 | ||||
-rw-r--r-- | chip/mec1322/lfw/ec_lfw.ld | 56 |
4 files changed, 346 insertions, 1 deletions
diff --git a/chip/mec1322/build.mk b/chip/mec1322/build.mk index 8e137b336b..2d49949e4f 100644 --- a/chip/mec1322/build.mk +++ b/chip/mec1322/build.mk @@ -31,8 +31,35 @@ SCRIPTDIR:=./chip/${CHIP}/util CHIP_SPI_SIZE_KB?=256 # Commands to convert $^ to $@.tmp -cmd_obj_to_bin = $(OBJCOPY) --gap-fill=0xff -O binary $^ $@.tmp1 ; \ +cmd_obj_to_bin = $(OBJCOPY) --gap-fill=0xff -O binary $< $@.tmp1 ; \ ${SCRIPTDIR}/pack_ec.py -o $@.tmp -i $@.tmp1 \ --payload_key ${SCRIPTDIR}/rsakey_sign_payload.pem \ --header_key ${SCRIPTDIR}/rsakey_sign_header.pem \ --spi_size ${CHIP_SPI_SIZE_KB} ; rm -f $@.tmp1 + +mec1322-lfw = chip/mec1322/lfw/ec_lfw +mec1322-lfw-flat = $(out)/$(mec1322-lfw)-lfw.flat + +# build these specifically for lfw with -lfw suffix +objs_lfw = $(patsubst %, $(out)/%-lfw.o, \ + $(addprefix common/, util gpio) \ + $(addprefix chip/$(CHIP)/, spi dma gpio clock hwtimer) \ + core/$(CORE)/cpu $(mec1322-lfw)) + +# reuse version.o (and its dependencies) from main board +objs_lfw += $(out)/common/version.o + +dirs-y+=chip/$(CHIP)/lfw + +# objs with -lfw suffix are to include lfw's gpio +$(out)/%-lfw.o: private CC+=-Iboard/$(BOARD)/lfw +$(out)/%-lfw.o: %.c + $(call quiet,c_to_o,CC ) + +# let lfw's elf link only with selected objects +$(out)/%-lfw.elf: private objs = $(objs_lfw) +$(out)/%-lfw.elf: %.ld $(objs_lfw) + $(call quiet,elf,LD ) + +# final image needs lfw loader +$(out)/$(PROJECT).bin: $(mec1322-lfw-flat) diff --git a/chip/mec1322/lfw/ec_lfw.c b/chip/mec1322/lfw/ec_lfw.c new file mode 100644 index 0000000000..0d953e6ae9 --- /dev/null +++ b/chip/mec1322/lfw/ec_lfw.c @@ -0,0 +1,241 @@ +/* Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * MEC1322 SoC little FW + * + */ + +#include <stdint.h> + +#include "config.h" +#include "gpio.h" +#include "spi.h" +#include "spi_flash.h" +#include "util.h" +#include "timer.h" +#include "dma.h" +#include "registers.h" +#include "cpu.h" +#include "clock.h" +#include "system.h" +#include "version.h" +#include "hwtimer.h" +#include "gpio_list.h" + +#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, + set by MEC ROM loader*/ + &lfw_main, /* reset vector */ + &fault_handler, /* NMI handler */ + &fault_handler, /* HardFault handler */ + &fault_handler, /* MPU fault handler */ + &fault_handler /* Bus fault handler */ +}; + +void timer_init() +{ + uint32_t val = 0; + + /* Ensure timer is not running */ + MEC1322_TMR32_CTL(0) &= ~(1 << 5); + + /* Enable timer */ + MEC1322_TMR32_CTL(0) |= (1 << 0); + + val = MEC1322_TMR32_CTL(0); + + /* Pre-scale = 48 -> 1MHz -> Period = 1us */ + val = (val & 0xffff) | (47 << 16); + + MEC1322_TMR32_CTL(0) = val; + + /* Set preload to use the full 32 bits of the timer */ + MEC1322_TMR32_PRE(0) = 0xffffffff; + + /* Override the count */ + MEC1322_TMR32_CNT(0) = 0xffffffff; + + /* Auto restart */ + MEC1322_TMR32_CTL(0) |= (1 << 3); + + /* Start counting in timer 0 */ + MEC1322_TMR32_CTL(0) |= (1 << 5); + +} + +static int spi_flash_readloc(uint8_t *buf_usr, + unsigned int offset, + unsigned int bytes) +{ + uint8_t cmd[4] = {SPI_FLASH_READ, + (offset >> 16) & 0xFF, + (offset >> 8) & 0xFF, + offset & 0xFF}; + + if (offset + bytes > CONFIG_SPI_FLASH_SIZE) + return EC_ERROR_INVAL; + + return spi_transaction(cmd, 4, buf_usr, bytes); +} + +int spi_rwimage_load(void) +{ + uint8_t *buf = (uint8_t *) (CONFIG_FW_RW_OFF + CONFIG_FLASH_BASE); + uint32_t i; + + memset((void *)buf, 0xFF, (CONFIG_FW_RW_SIZE - 4)); + + spi_enable(1); + + for (i = 0; i < CONFIG_FW_RW_SIZE; i += SPI_CHUNK_SIZE) + spi_flash_readloc(&buf[i], + CONFIG_RW_IMAGE_FLASHADDR + i, + SPI_CHUNK_SIZE); + + spi_enable(0); + + return 0; + +} + +void udelay(unsigned us) +{ + uint32_t t0 = __hw_clock_source_read(); + while (__hw_clock_source_read() - t0 < us) + ; +} + +void usleep(unsigned us) +{ + udelay(us); +} + +int timestamp_expired(timestamp_t deadline, const timestamp_t *now) +{ + timestamp_t now_val; + + if (!now) { + now_val = get_time(); + now = &now_val; + } + + return ((uint32_t)(now->le.lo - deadline.le.lo) >= 0); +} + + +timestamp_t get_time(void) +{ + timestamp_t ts; + + ts.le.hi = 0; + ts.le.lo = __hw_clock_source_read(); + return ts; +} + +void uart_write_c(char c) +{ + /* Wait for space in transmit FIFO. */ + while (!(MEC1322_UART_LSR & (1 << 5))) + ; + MEC1322_UART_TB = c; +} + +void uart_puts(const char *str) +{ + if (!str || !*str) + return; + + do { + uart_write_c(*str++); + } while (*str); +} + +void fault_handler(void) +{ + uart_puts("EXCEPTION!\nTriggering watchdog reset\n"); + /* trigger reset in 1 ms */ + MEC1322_WDG_LOAD = 1; + MEC1322_WDG_CTL |= 1; + while (1) + ; + +} + +void jump_to_image(uintptr_t init_addr) +{ + void (*resetvec)(void) = (void(*)(void))init_addr; + resetvec(); +} + +void uart_init(void) +{ + /* Set UART to reset on VCC1_RESET instaed of nSIO_RESET */ + MEC1322_UART_CFG &= ~(1 << 1); + + /* Baud rate = 115200. 1.8432MHz clock. Divisor = 1 */ + + /* Set CLK_SRC = 0 */ + MEC1322_UART_CFG &= ~(1 << 0); + + /* Set DLAB = 1 */ + MEC1322_UART_LCR |= (1 << 7); + + /* PBRG0/PBRG1 */ + MEC1322_UART_PBRG0 = 1; + MEC1322_UART_PBRG1 = 0; + + /* Set DLAB = 0 */ + MEC1322_UART_LCR &= ~(1 << 7); + + /* Set word length to 8-bit */ + MEC1322_UART_LCR |= (1 << 0) | (1 << 1); + + /* Enable FIFO */ + MEC1322_UART_FCR = (1 << 0); + + /* Activate UART */ + MEC1322_UART_ACT |= (1 << 0); + + gpio_config_module(MODULE_UART, 1); +} + +void lfw_main() +{ + + uintptr_t init_addr; + + /* install vector table */ + *((uintptr_t *) 0xe000ed08) = (uintptr_t) &hdr_int_vect; + + timer_init(); + clock_init(); + cpu_init(); + dma_init(); + uart_init(); + + uart_puts("littlefw"); + uart_puts(version_data.version); + uart_puts("\n"); + + switch (*image_type) { + case SYSTEM_IMAGE_RW: + init_addr = CONFIG_FW_RW_OFF + CONFIG_FLASH_BASE; + spi_rwimage_load(); + case SYSTEM_IMAGE_RO: + default: + init_addr = CONFIG_FW_RO_OFF + CONFIG_FLASH_BASE; + } + + jump_to_image(*(uintptr_t *)(init_addr + 4)); + + /* should never get here */ + while (1) + ; +} diff --git a/chip/mec1322/lfw/ec_lfw.h b/chip/mec1322/lfw/ec_lfw.h new file mode 100644 index 0000000000..b7f9f6359f --- /dev/null +++ b/chip/mec1322/lfw/ec_lfw.h @@ -0,0 +1,21 @@ +/* Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * MEC1322 SoC little FW + * + */ + +void lfw_main(void) __attribute__ ((noreturn, naked)); +void fault_handler(void) __attribute__((naked)); + +struct int_vector_t { + void *stack_ptr; + void *reset_vector; + void *nmi; + void *hard_fault; + void *bus_fault; + void *usage_fault; +}; + +#define SPI_CHUNK_SIZE 1024 diff --git a/chip/mec1322/lfw/ec_lfw.ld b/chip/mec1322/lfw/ec_lfw.ld new file mode 100644 index 0000000000..0467595941 --- /dev/null +++ b/chip/mec1322/lfw/ec_lfw.ld @@ -0,0 +1,56 @@ +/* Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * MEC1322 SoC little FW + * + */ + +/* Memory Spaces Definitions */ +MEMORY +{ + VECTOR(r ) : ORIGIN = 0x100000, LENGTH = 24 + SRAM (xrw) : ORIGIN = 0x100018, LENGTH = 0x1000 - LENGTH(VECTOR) +} + +/* + * The entry point is informative, for debuggers and simulators, + * since the Cortex-M vector points to it anyway. + */ +ENTRY(lfw_main) + +/* Sections Definitions */ + +SECTIONS +{ + + /* + * The vector table goes first + */ + .intvector : + { + . = ALIGN(4); + KEEP(*(.intvector)) + } > VECTOR + + /* + * The program code is stored in the .text section, + * which goes to FLASH. + */ + + .text : + { + *(.text .text.*) /* all remaining code */ + *(.rodata .rodata.*) /* read-only data (constants) */ + } >SRAM + + . = ALIGN(4); + + /* Padding */ + + .fill : { + FILL(0xFF); + . = ORIGIN(SRAM) + LENGTH(SRAM) - 1; + BYTE(0xFF); /* emit at least a byte to make linker happy */ + } +} |