diff options
author | Louis Yung-Chieh Lo <yjlou@chromium.org> | 2014-07-15 10:41:16 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-07-29 02:21:22 +0000 |
commit | f93f1cfe77ed3603ab16047d79a283a781416db4 (patch) | |
tree | d0ec489650265d06c90297b884f02b96b18094c0 | |
parent | bbb5b0636b5d2b9a9d339e32142bf775717bd929 (diff) | |
download | chrome-ec-f93f1cfe77ed3603ab16047d79a283a781416db4.tar.gz |
hadoken: initial commit.
Board bring up. GPIO / UART / timer / console / task / hook are
working now.
BRANCH=tot
BUG=none
TEST=run on evaluation board and see LED 0/1 are blinking.
Console commands are available to use.
Change-Id: If93a2c94b8abe1c2c931c03a7a12ddd2bed9d9f6
Signed-off-by: Louis Yung-Chieh Lo <yjlou@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/209403
Reviewed-by: Vic Yang <victoryang@chromium.org>
-rw-r--r-- | board/hadoken/board.c | 12 | ||||
-rw-r--r-- | board/hadoken/board.h | 30 | ||||
-rw-r--r-- | board/hadoken/build.mk | 13 | ||||
-rw-r--r-- | board/hadoken/ec.tasklist | 20 | ||||
-rw-r--r-- | board/hadoken/gpio.inc | 46 | ||||
-rw-r--r-- | chip/nrf51/build.mk | 16 | ||||
-rw-r--r-- | chip/nrf51/clock.c | 10 | ||||
-rw-r--r-- | chip/nrf51/config_chip.h | 70 | ||||
-rw-r--r-- | chip/nrf51/gpio.c | 101 | ||||
-rw-r--r-- | chip/nrf51/hwtimer.c | 194 | ||||
-rw-r--r-- | chip/nrf51/jtag.c | 9 | ||||
-rw-r--r-- | chip/nrf51/registers.h | 200 | ||||
-rw-r--r-- | chip/nrf51/system.c | 93 | ||||
-rw-r--r-- | chip/nrf51/uart.c | 130 | ||||
-rw-r--r-- | chip/nrf51/watchdog.c | 20 |
15 files changed, 964 insertions, 0 deletions
diff --git a/board/hadoken/board.c b/board/hadoken/board.c new file mode 100644 index 0000000000..895974efee --- /dev/null +++ b/board/hadoken/board.c @@ -0,0 +1,12 @@ +/* Copyright (c) 2014 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. + */ +#include "gpio.h" +#include "registers.h" +#include "util.h" + + +/* To define the gpio_list[] instance. */ +#include "gpio_list.h" + diff --git a/board/hadoken/board.h b/board/hadoken/board.h new file mode 100644 index 0000000000..feb27e668d --- /dev/null +++ b/board/hadoken/board.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2014 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. + */ + +/* Hadoken board configuration */ + +#ifndef __BOARD_H +#define __BOARD_H + +#ifndef __ASSEMBLER__ + +#undef CONFIG_FLASH /* TODO: implement me */ +#undef CONFIG_FMAP /* TODO: implement me */ +#undef CONFIG_WATCHDOG +#undef CONFIG_LID_SWITCH + + +/* + * nRF51 board specific configuration. + */ +#define NRF51_UART_TX_PIN 25 +#define NRF51_UART_RX_PIN 29 + +#include "gpio_signal.h" + +#endif /* !__ASSEMBLER__ */ + +#endif /* __BOARD_H */ + diff --git a/board/hadoken/build.mk b/board/hadoken/build.mk new file mode 100644 index 0000000000..f8bb859201 --- /dev/null +++ b/board/hadoken/build.mk @@ -0,0 +1,13 @@ +# -*- makefile -*- +# Copyright (c) 2014 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. +# +# Board specific files build + +# the IC is Nordic nRF51822 +CHIP:=nrf51 +CHIP_FAMILY:=nrf51x22 +CHIP_VARIANT:=nrf51822 + +board-y=board.o diff --git a/board/hadoken/ec.tasklist b/board/hadoken/ec.tasklist new file mode 100644 index 0000000000..684f22b716 --- /dev/null +++ b/board/hadoken/ec.tasklist @@ -0,0 +1,20 @@ +/* Copyright (c) 2014 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. + */ + +/** + * List of enabled tasks in the priority order + * + * The first one has the lowest priority. + * + * For each task, use the macro TASK(n, r, d, s) where : + * 'n' in the name of the task + * 'r' in the main routine of the task + * 'd' in an opaque parameter passed to the routine at startup + * 's' is the stack size in bytes; must be a multiple of 8 + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE) \ + diff --git a/board/hadoken/gpio.inc b/board/hadoken/gpio.inc new file mode 100644 index 0000000000..da5df7a968 --- /dev/null +++ b/board/hadoken/gpio.inc @@ -0,0 +1,46 @@ +/* -*- mode:c -*- + * + * Copyright (c) 2014 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. + */ + +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH) +#define GPIO_KB_OUTPUT GPIO_ODR_HIGH + +/* Inputs with interrupt handlers are first for efficiency */ + +/* Keyboard inputs */ +/* + * TODO(yjlou): call keyboard_raw_gpio_interrupt() in chip/nrf51/keyboard_raw.c + */ +GPIO(KB_IN00, 0, 6, GPIO_KB_INPUT, NULL) +GPIO(KB_IN01, 0, 24, GPIO_KB_INPUT, NULL) +GPIO(KB_IN02, 0, 1, GPIO_KB_INPUT, NULL) +GPIO(KB_IN03, 0, 4, GPIO_KB_INPUT, NULL) +GPIO(KB_IN04, 0, 0, GPIO_KB_INPUT, NULL) +GPIO(KB_IN05, 0, 30, GPIO_KB_INPUT, NULL) +GPIO(KB_IN06, 0, 27, GPIO_KB_INPUT, NULL) +GPIO(KB_IN07, 0, 26, GPIO_KB_INPUT, NULL) + +/* Other inputs */ + +/* Outputs */ +GPIO(LED0, 0, 18, GPIO_OUTPUT | GPIO_HIGH, NULL) +GPIO(LED1, 0, 19, GPIO_OUTPUT | GPIO_HIGH, NULL) +GPIO(KB_OUT00, 0, 2, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT01, 0, 10, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT02, 0, 7, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT03, 0, 5, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT04, 0, 3, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT05, 0, 9, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT06, 0, 8, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT07, 0, 28, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT08, 0, 18, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT09, 0, 16, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT10, 0, 12, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT11, 0, 15, GPIO_KB_OUTPUT, NULL) +GPIO(KB_OUT12, 0, 11, GPIO_KB_OUTPUT, NULL) + +/* Unimplemented */ +UNIMPLEMENTED(ENTERING_RW) diff --git a/chip/nrf51/build.mk b/chip/nrf51/build.mk new file mode 100644 index 0000000000..34bea8cc0d --- /dev/null +++ b/chip/nrf51/build.mk @@ -0,0 +1,16 @@ +# -*- makefile -*- +# Copyright (c) 2014 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. +# +# nRF51822 chip specific files build +# + +CORE:=cortex-m0 +# Force ARMv6-M ISA used by the Cortex-M0 +CFLAGS_CPU+=-march=armv6-m -mcpu=cortex-m0 + +chip-y+=gpio.o system.o uart.o +chip-y+=jtag.o watchdog.o + +chip-$(CONFIG_COMMON_TIMER)+=hwtimer.o clock.o diff --git a/chip/nrf51/clock.c b/chip/nrf51/clock.c new file mode 100644 index 0000000000..4d37de56de --- /dev/null +++ b/chip/nrf51/clock.c @@ -0,0 +1,10 @@ +/* Copyright (c) 2014 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. + */ + +/* Clocks and power management settings */ + +void clock_init(void) +{ +} diff --git a/chip/nrf51/config_chip.h b/chip/nrf51/config_chip.h new file mode 100644 index 0000000000..1b39439681 --- /dev/null +++ b/chip/nrf51/config_chip.h @@ -0,0 +1,70 @@ +/* Copyright (c) 2014 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. + */ + +#ifndef __CROS_EC_CONFIG_CHIP_H +#define __CROS_EC_CONFIG_CHIP_H + +#include "core/cortex-m0/config_core.h" + +/* System stack size */ +#define CONFIG_STACK_SIZE 1024 + +/* Idle task stack size */ +#define IDLE_TASK_STACK_SIZE 256 + +/* Default task stack size */ +#define TASK_STACK_SIZE 488 + +/* Larger task stack size, for hook task */ +#define LARGER_TASK_STACK_SIZE 640 + +/* Interval between HOOK_TICK notifications */ +#define HOOK_TICK_INTERVAL_MS 500 +#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC) + +/* Maximum number of deferrable functions */ +#define DEFERRABLE_MAX_COUNT 8 + +/* + * --- chip variant settings --- + */ + +/* RAM mapping */ +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00004000 + +/* Flash mapping */ +#define CONFIG_FLASH_BASE 0x00000000 +#define CONFIG_FLASH_PHYSICAL_SIZE 0x00040000 +#define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE +#define CONFIG_FLASH_BANK_SIZE 0x1000 + +/* Size of one firmware image in flash */ +#define CONFIG_FW_IMAGE_SIZE (128 * 1024) + +/* Define the RO/RW offset */ +#define CONFIG_FW_RO_OFF 0 +#define CONFIG_FW_RO_SIZE (CONFIG_FW_IMAGE_SIZE - CONFIG_FW_PSTATE_SIZE) +#define CONFIG_FW_RW_OFF CONFIG_FW_IMAGE_SIZE +#define CONFIG_FW_RW_SIZE CONFIG_FW_IMAGE_SIZE + +/* + * Put pstate after RO to give RW more space and make RO write protect + * region contiguous. + */ +#define CONFIG_FW_PSTATE_SIZE CONFIG_FLASH_BANK_SIZE +#define CONFIG_FW_PSTATE_OFF (CONFIG_FW_RO_OFF + CONFIG_FW_RO_SIZE) + + +/* Number of IRQ vectors on the NVIC */ +#define CONFIG_IRQ_COUNT 32 + +/* Not that much RAM, set to smaller */ +#undef CONFIG_UART_TX_BUF_SIZE +#define CONFIG_UART_TX_BUF_SIZE 1024 + + +#endif /* __CROS_EC_CONFIG_CHIP_H */ + diff --git a/chip/nrf51/gpio.c b/chip/nrf51/gpio.c new file mode 100644 index 0000000000..db2bd1a5e6 --- /dev/null +++ b/chip/nrf51/gpio.c @@ -0,0 +1,101 @@ +/* Copyright (c) 2014 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. + */ + +#include "common.h" +#include "gpio.h" +#include "hooks.h" +#include "registers.h" +#include "task.h" + + +void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) +{ + uint32_t val = 0; + uint32_t bit = 31 - __builtin_clz(mask); + + if (flags & GPIO_OUTPUT) + val |= 1 << 0; + else if (flags & GPIO_INPUT) + val |= 0 << 0; + + if (flags & GPIO_PULL_DOWN) + val |= 1 << 2; + else if (flags & GPIO_PULL_UP) + val |= 3 << 2; + + if (flags & GPIO_OUTPUT) { + if (flags & GPIO_HIGH) + NRF51_GPIO0_OUTSET = 1 << bit; + else if (flags & GPIO_LOW) + NRF51_GPIO0_OUTCLR = 1 << bit; + } + + NRF51_PIN_CNF(bit) = val; +} + + +static void gpio_init(void) +{ + task_enable_irq(NRF51_PERID_GPIOTE); +} +DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); + + +test_mockable int gpio_get_level(enum gpio_signal signal) +{ + return !!(NRF51_GPIO0_IN & gpio_list[signal].mask); +} + +void gpio_set_level(enum gpio_signal signal, int value) +{ + if (value) + NRF51_GPIO0_OUTSET = gpio_list[signal].mask; + else + NRF51_GPIO0_OUTCLR = gpio_list[signal].mask; +} + + +void gpio_pre_init(void) +{ + const struct gpio_info *g = gpio_list; + int is_warm = 0; + int i; + + if (NRF51_POWER_RESETREAS & (1 << 2)) { + /* This is a warm reboot */ + is_warm = 1; + } + + /* Set all GPIOs to defaults */ + for (i = 0; i < GPIO_COUNT; i++, g++) { + int 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); + + /* Set up GPIO based on flags */ + gpio_set_flags_by_mask(g->port, g->mask, flags); + } +} + + +/* + * TODO: implement GPIO interrupt. + */ +int gpio_enable_interrupt(enum gpio_signal signal) +{ + return EC_ERROR_INVAL; +} +void gpio_interrupt(void) +{ +} +DECLARE_IRQ(NRF51_PERID_GPIOTE, gpio_interrupt, 1); diff --git a/chip/nrf51/hwtimer.c b/chip/nrf51/hwtimer.c new file mode 100644 index 0000000000..b4a1453b95 --- /dev/null +++ b/chip/nrf51/hwtimer.c @@ -0,0 +1,194 @@ +/* Copyright (c) 2014 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. + */ + +/* + * Hardware timers driver. + * + * nRF51x has one hardware counter, but 4 stand-alone capture/compare (CC) + * registers. + * + * CC(0) -- used to interrupt next clock event. + * CC(1) -- used to capture the current value. + * CC(2) -- used to detect overflow on virtual timer (not hardware). + */ + +#include "common.h" +#include "console.h" +#include "hooks.h" +#include "hwtimer.h" +#include "registers.h" +#include "task.h" + +#define CPUTS(outstr) cputs(CC_CLOCK, outstr) +#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) + + +static uint32_t last_deadline; /* cache of event set */ + +/* + * The nRF51x timer cannot be set to a specified value (reset to zero only). + * Thus, we have to use a variable "shift" to maintain the offset between the + * hardware value and virtual clock value. + * + * Once __hw_clock_source_set(ts) is called, the shift will be like: + * + * virtual time ------------------------------------------------ + * <----------> ^ + * shift | ts + * 0 | | + * hardware v + * counter time ------------------------------------------------ + * + * + * Below diagram shows what it is when overflow happens. + * + * | now | prev_read + * v v + * virtual time ------------------------------------------------ + * ----> <------ + * shift shift + * | + * hardware v + * counter time ------------------------------------------------ + * + */ +static uint32_t shift; +static uint32_t overflow; +static uint32_t prev_read; + +void __hw_clock_event_set(uint32_t deadline) +{ + last_deadline = deadline; + NRF51_TIMER0_CC0 = deadline - shift; + + /* enable interrupt */ + NRF51_TIMER0_INTENSET = 1 << NRF51_TIMER_COMPARE0_BIT; +} + +uint32_t __hw_clock_event_get(void) +{ + return last_deadline; +} + +void __hw_clock_event_clear(void) +{ + /* disable interrupt */ + NRF51_TIMER0_INTENCLR = 1 << NRF51_TIMER_COMPARE0_BIT; +} + +uint32_t __hw_clock_source_read(void) +{ + uint32_t now; + + /* to capture the current value */ + NRF51_TIMER0_CAPTURE1 = 1; + now = NRF51_TIMER0_CC1 + shift; + + /* detect if a wrap happened */ + if (now < prev_read) + overflow++; + prev_read = now; + + return now; +} + +void __hw_clock_source_set(uint32_t ts) +{ + shift = prev_read = ts; + + /* reset counter to zero */ + NRF51_TIMER0_STOP = 1; + NRF51_TIMER0_CLEAR = 1; + NRF51_TIMER0_START = 1; + + /* So that no interrupt until next __hw_clock_event_set() */ + NRF51_TIMER0_CC0 = ts - 1; + + /* Update the overflow point */ + NRF51_TIMER0_CC2 = 0 - shift; +} + + +/* Interrupt handler for timer */ +void timer_irq(void) +{ + /* clear status */ + NRF51_TIMER0_COMPARE0 = 0; + if (NRF51_TIMER0_COMPARE2) { + /* Invoke a read to update overflow variable */ + __hw_clock_source_read(); + NRF51_TIMER0_COMPARE2 = 0; + } + + process_timers(overflow); + overflow = 0; +} +DECLARE_IRQ(NRF51_PERID_TIMER0, timer_irq, 1); + + +int __hw_clock_source_init(uint32_t start_t) +{ + /* Start the high freq crystal oscillator */ + NRF51_CLOCK_HFCLKSTART = 1; + /* TODO: check if the crystal oscillator is running (HFCLKSTAT) */ + + /* 32-bit timer mode */ + NRF51_TIMER0_MODE = NRF51_TIMER0_MODE_TIMER; + NRF51_TIMER0_BITMODE = NRF51_TIMER0_BITMODE_32; + + /* + * The external crystal oscillator is 16MHz (HFCLK). + * Set the prescaler to 16 so that the timer counter is increasing + * every micro-second (us). + */ + NRF51_TIMER0_PRESCALER = 4; /* actual value is 2**4 = 16 */ + + /* Not to trigger interrupt until __hw_clock_event_set() is called. */ + NRF51_TIMER0_CC0 = 0xffffffff; + + /* Set to 0 so that the next overflow can trigger timer_irq(). */ + NRF51_TIMER0_CC2 = 0; + NRF51_TIMER0_INTENSET = 1 << NRF51_TIMER_COMPARE2_BIT; + + /* Clear the timer counter */ + NRF51_TIMER0_CLEAR = 1; + + /* Override the count with the start value now that counting has + * started. */ + __hw_clock_source_set(start_t); + + /* Enable interrupt */ + task_enable_irq(NRF51_PERID_TIMER0); + + /* Start the timer */ + NRF51_TIMER0_START = 1; + + return NRF51_PERID_TIMER0; +} + + +/* FIXME: for demo only. remove me later */ +#include "gpio.h" +#include "timer.h" +void blink_led(void) +{ + gpio_set_level(GPIO_LED0, 0); + gpio_set_level(GPIO_LED1, 1); + usleep(250 * 1000); + gpio_set_level(GPIO_LED0, 1); + gpio_set_level(GPIO_LED1, 0); + usleep(250 * 1000); + gpio_set_level(GPIO_LED0, 0); +} +static void test_hook(void) +{ + static int secs; + secs++; + if (!(secs % 100)) + CPRINTS("%s()", __func__); + blink_led(); +} +DECLARE_HOOK(HOOK_SECOND, test_hook, HOOK_PRIO_DEFAULT); diff --git a/chip/nrf51/jtag.c b/chip/nrf51/jtag.c new file mode 100644 index 0000000000..6c2ee03323 --- /dev/null +++ b/chip/nrf51/jtag.c @@ -0,0 +1,9 @@ +/* Copyright (c) 2014 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. + */ +/* Settings to enable JTAG debugging */ + +void jtag_pre_init(void) +{ +} diff --git a/chip/nrf51/registers.h b/chip/nrf51/registers.h new file mode 100644 index 0000000000..fe9b305395 --- /dev/null +++ b/chip/nrf51/registers.h @@ -0,0 +1,200 @@ +/* Copyright (c) 2013 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. + * + * Register map for STM32 processor + */ + +#ifndef __CROS_EC_REGISTERS_H +#define __CROS_EC_REGISTERS_H + +#include "common.h" + +/* + * Peripheral IDs + * + * nRF51 has very good design that the peripheral IDs is actually the IRQ#. + * Thus, the following numbers are used in DECLARE_IRQ(), task_enable_irq() + * and task_disable_irq(). + */ +#define NRF51_PERID_POWER 0 +#define NRF51_PERID_CLOCK 0 +#define NRF51_PERID_RADIO 1 +#define NRF51_PERID_USART 2 +#define NRF51_PERID_SPI0 3 +#define NRF51_PERID_TWI0 3 +#define NRF51_PERID_SPI1 4 +#define NRF51_PERID_TWI1 4 +#define NRF51_PERID_SPIS 4 +#define NRF51_PERID_GPIOTE 6 +#define NRF51_PERID_ADC 7 +#define NRF51_PERID_TIMER0 8 +#define NRF51_PERID_TIMER1 9 +#define NRF51_PERID_TIMER2 10 +#define NRF51_PERID_RTC 11 +#define NRF51_PERID_TEMP 12 +#define NRF51_PERID_RNG 13 +#define NRF51_PERID_ECB 14 +#define NRF51_PERID_CCM 15 +#define NRF51_PERID_AAR 16 +#define NRF51_PERID_WDT 17 +#define NRF51_PERID_QDEC 18 +#define NRF51_PERID_LPCOMP 19 +#define NRF51_PERID_NVMC 30 +#define NRF51_PERID_PPI 31 + + +/* + * Power + */ +#define NRF51_POWER_BASE 0x40000000 +/* Tasks */ +#define NRF51_POWER_CONSTLAT REG32(NRF51_POWER_BASE + 0x078) +#define NRF51_POWER_LOWPWR REG32(NRF51_POWER_BASE + 0x07c) +/* Events */ +#define NRF51_POWER_POFWARN REG32(NRF51_POWER_BASE + 0x108) +/* Registers */ +#define NRF51_POWER_INTENSET REG32(NRF51_POWER_BASE + 0x304) +#define NRF51_POWER_INTENCLR REG32(NRF51_POWER_BASE + 0x308) +#define NRF51_POWER_RESETREAS REG32(NRF51_POWER_BASE + 0x400) +#define NRF51_POWER_SYSTEMOFF REG32(NRF51_POWER_BASE + 0x500) +#define NRF51_POWER_POFCON REG32(NRF51_POWER_BASE + 0x510) +#define NRF51_POWER_GPREGRET REG32(NRF51_POWER_BASE + 0x51c) +#define NRF51_POWER_RAMON REG32(NRF51_POWER_BASE + 0x524) +#define NRF51_POWER_RESET REG32(NRF51_POWER_BASE + 0x544) +#define NRF51_POWER_DCDCEN REG32(NRF51_POWER_BASE + 0x578) + + +/* + * Clock + */ +#define NRF51_CLOCK_BASE 0x40000000 +/* Tasks */ +#define NRF51_CLOCK_HFCLKSTART REG32(NRF51_CLOCK_BASE + 0x000) +#define NRF51_CLOCK_HFCLKSTOP REG32(NRF51_CLOCK_BASE + 0x004) +#define NRF51_CLOCK_LFCLKSTART REG32(NRF51_CLOCK_BASE + 0x008) +#define NRF51_CLOCK_LFCLKSTOP REG32(NRF51_CLOCK_BASE + 0x00c) +#define NRF51_CLOCK_CAL REG32(NRF51_CLOCK_BASE + 0x010) +#define NRF51_CLOCK_CTSTART REG32(NRF51_CLOCK_BASE + 0x014) +#define NRF51_CLOCK_CTSTOP REG32(NRF51_CLOCK_BASE + 0x018) +/* Events */ +#define NRF51_CLOCK_HFCLKSTARTED REG32(NRF51_CLOCK_BASE + 0x100) +#define NRF51_CLOCK_LFCLKSTARTED REG32(NRF51_CLOCK_BASE + 0x104) +#define NRF51_CLOCK_DONE REG32(NRF51_CLOCK_BASE + 0x10c) +#define NRF51_CLOCK_CCTO REG32(NRF51_CLOCK_BASE + 0x110) +/* Registers */ +#define NRF51_CLOCK_INTENSET REG32(NRF51_CLOCK_BASE + 0x304) +#define NRF51_CLOCK_INTENCLR REG32(NRF51_CLOCK_BASE + 0x308) +#define NRF51_CLOCK_HFCLKSTAT REG32(NRF51_CLOCK_BASE + 0x40c) +#define NRF51_CLOCK_LFCLKSTAT REG32(NRF51_CLOCK_BASE + 0x418) +#define NRF51_CLOCK_LFCLKSRC REG32(NRF51_CLOCK_BASE + 0x518) +#define NRF51_CLOCK_CTIV REG32(NRF51_CLOCK_BASE + 0x538) +#define NRF51_CLOCK_XTALFREQ REG32(NRF51_CLOCK_BASE + 0x550) + +/* + * UART + */ +#define NRF51_UART_BASE 0x40002000 +/* Tasks */ +#define NRF51_UART_STARTRX REG32(NRF51_UART_BASE + 0x000) +#define NRF51_UART_STOPRX REG32(NRF51_UART_BASE + 0x004) +#define NRF51_UART_STARTTX REG32(NRF51_UART_BASE + 0x008) +#define NRF51_UART_STOPTX REG32(NRF51_UART_BASE + 0x00c) +/* Events */ +#define NRF51_UART_RXDRDY REG32(NRF51_UART_BASE + 0x108) +#define NRF51_UART_TXDRDY REG32(NRF51_UART_BASE + 0x11c) +#define NRF51_UART_ERROR REG32(NRF51_UART_BASE + 0x124) +#define NRF51_UART_RXTO REG32(NRF51_UART_BASE + 0x144) +/* Registers */ +#define NRF51_UART_INTENSET REG32(NRF51_UART_BASE + 0x304) +#define NRF51_UART_INTENCLR REG32(NRF51_UART_BASE + 0x308) +#define NRF51_UART_ERRORSRC REG32(NRF51_UART_BASE + 0x480) +#define NRF51_UART_ENABLE REG32(NRF51_UART_BASE + 0x500) +#define NRF51_UART_PSELRTS REG32(NRF51_UART_BASE + 0x508) +#define NRF51_UART_PSELTXD REG32(NRF51_UART_BASE + 0x50c) +#define NRF51_UART_PSELCTS REG32(NRF51_UART_BASE + 0x510) +#define NRF51_UART_PSELRXD REG32(NRF51_UART_BASE + 0x514) +#define NRF51_UART_RXD REG32(NRF51_UART_BASE + 0x518) +#define NRF51_UART_TXD REG32(NRF51_UART_BASE + 0x51C) +#define NRF51_UART_BAUDRATE REG32(NRF51_UART_BASE + 0x524) +#define NRF51_UART_CONFIG REG32(NRF51_UART_BASE + 0x56c) +/* For UART.INTEN bits */ +#define NRF55_UART_RXDRDY_BIT ((0x108 - 0x100) / 4) +#define NRF55_UART_TXDRDY_BIT ((0x11c - 0x100) / 4) + + +/* + * Timer / Counter + */ +#define NRF51_TIMER0_BASE 0x40008000 +/* Tasks */ +#define NRF51_TIMER0_START REG32(NRF51_TIMER0_BASE + 0x000) +#define NRF51_TIMER0_STOP REG32(NRF51_TIMER0_BASE + 0x004) +#define NRF51_TIMER0_COUNT REG32(NRF51_TIMER0_BASE + 0x008) +#define NRF51_TIMER0_CLEAR REG32(NRF51_TIMER0_BASE + 0x00c) +#define NRF51_TIMER0_CAPTURE0 REG32(NRF51_TIMER0_BASE + 0x040) +#define NRF51_TIMER0_CAPTURE1 REG32(NRF51_TIMER0_BASE + 0x044) +#define NRF51_TIMER0_CAPTURE2 REG32(NRF51_TIMER0_BASE + 0x048) +#define NRF51_TIMER0_CAPTURE3 REG32(NRF51_TIMER0_BASE + 0x04c) +/* Events */ +#define NRF51_TIMER0_COMPARE0 REG32(NRF51_TIMER0_BASE + 0x140) +#define NRF51_TIMER0_COMPARE1 REG32(NRF51_TIMER0_BASE + 0x144) +#define NRF51_TIMER0_COMPARE2 REG32(NRF51_TIMER0_BASE + 0x148) +#define NRF51_TIMER0_COMPARE3 REG32(NRF51_TIMER0_BASE + 0x14c) +/* Registers */ +#define NRF51_TIMER0_SHORTCUT REG32(NRF51_TIMER0_BASE + 0x200) +#define NRF51_TIMER0_INTENSET REG32(NRF51_TIMER0_BASE + 0x304) +#define NRF51_TIMER0_INTENCLR REG32(NRF51_TIMER0_BASE + 0x308) +#define NRF51_TIMER0_MODE REG32(NRF51_TIMER0_BASE + 0x504) +#define NRF51_TIMER0_BITMODE REG32(NRF51_TIMER0_BASE + 0x508) +#define NRF51_TIMER0_PRESCALER REG32(NRF51_TIMER0_BASE + 0x510) +#define NRF51_TIMER0_CC0 REG32(NRF51_TIMER0_BASE + 0x540) +#define NRF51_TIMER0_CC1 REG32(NRF51_TIMER0_BASE + 0x544) +#define NRF51_TIMER0_CC2 REG32(NRF51_TIMER0_BASE + 0x548) +#define NRF51_TIMER0_CC3 REG32(NRF51_TIMER0_BASE + 0x54c) +/* For Timer.INTEN bits */ +#define NRF51_TIMER_COMPARE0_BIT ((0x140 - 0x100) / 4) +#define NRF51_TIMER_COMPARE1_BIT ((0x144 - 0x100) / 4) +#define NRF51_TIMER_COMPARE2_BIT ((0x148 - 0x100) / 4) +#define NRF51_TIMER_COMPARE3_BIT ((0x14c - 0x100) / 4) +/* For Timer Shortcuts */ +#define NRF51_TIMER_COMPARE0_CLEAR (1 << 0) +#define NRF51_TIMER_COMPARE1_CLEAR (1 << 1) +#define NRF51_TIMER_COMPARE2_CLEAR (1 << 2) +#define NRF51_TIMER_COMPARE3_CLEAR (1 << 3) +#define NRF51_TIMER_COMPARE0_STOP (1 << 8) +#define NRF51_TIMER_COMPARE1_STOP (1 << 9) +#define NRF51_TIMER_COMPARE2_STOP (1 << 10) +#define NRF51_TIMER_COMPARE3_STOP (1 << 11) +/* Timer Mode (NRF51_TIMER0_MODE) */ +#define NRF51_TIMER0_MODE_TIMER 0 /* reset default */ +#define NRF51_TIMER0_MODE_COUNTER 0 +/* Prescaler */ +#define NRF51_TIMER0_PRESCALER_MASK (0xf) /* range: 0-9, reset default: 4 */ +/* Bit length (NRF51_TIMER0_BITMODE) */ +#define NRF51_TIMER0_BITMODE_16 0 /* reset default */ +#define NRF51_TIMER0_BITMODE_8 1 +#define NRF51_TIMER0_BITMODE_24 2 +#define NRF51_TIMER0_BITMODE_32 3 + + +/* + * GPIO + */ +#define NRF51_GPIO_BASE 0x50000000 +#define NRF51_GPIO0_BASE (NRF51_GPIO_BASE + 0x500) +#define NRF51_GPIO0_OUT REG32(NRF51_GPIO0_BASE + 0x004) +#define NRF51_GPIO0_OUTSET REG32(NRF51_GPIO0_BASE + 0x008) +#define NRF51_GPIO0_OUTCLR REG32(NRF51_GPIO0_BASE + 0x00c) +#define NRF51_GPIO0_IN REG32(NRF51_GPIO0_BASE + 0x010) +#define NRF51_GPIO0_DIR REG32(NRF51_GPIO0_BASE + 0x014) /* 1 for output */ +#define NRF51_GPIO0_DIRSET REG32(NRF51_GPIO0_BASE + 0x018) +#define NRF51_GPIO0_DIRCLR REG32(NRF51_GPIO0_BASE + 0x01c) +#define NRF51_PIN_BASE (NRF51_GPIO_BASE + 0x700) +#define NRF51_PIN_CNF(n) REG32(NRF51_PIN_BASE + ((n) * 4)) +#define GPIO_0 NRF51_GPIO0_BASE +#define DUMMY_GPIO_BANK GPIO_0 /* for UNIMPLEMENTED() macro */ + + +#endif /* __CROS_EC_REGISTERS_H */ + diff --git a/chip/nrf51/system.c b/chip/nrf51/system.c new file mode 100644 index 0000000000..293911ca28 --- /dev/null +++ b/chip/nrf51/system.c @@ -0,0 +1,93 @@ +/* Copyright (c) 2014 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. + */ + +/* System module for Chrome EC : hardware specific implementation */ + +#include "common.h" +#include "console.h" +#include "registers.h" +#include "system.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_SYSTEM, outstr) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) + +const char *system_get_chip_vendor(void) +{ + return "nrf"; +} + +const char *system_get_chip_name(void) +{ + return "nrf51822"; +} + +const char *system_get_chip_revision(void) +{ + return ""; +} + +void system_hibernate(uint32_t seconds, uint32_t microseconds) +{ + /* Flush console before hibernating */ + cflush(); + + /* chip specific standby mode */ + CPRINTS("TODO: implement %s()", __func__); +} + + +static void check_reset_cause(void) +{ + uint32_t flags = 0; + uint32_t raw_cause = NRF51_POWER_RESETREAS; + + if (raw_cause & 0x00000001) + flags |= RESET_FLAG_RESET_PIN; + + if (raw_cause & 0x00000002) + flags |= RESET_FLAG_WATCHDOG; + + /* + * According to the data sheet, this bit is set by AIRCR.SYSRESETREQ. + * However, th reset from J-Link also sets this bit. This could mislead + * us. + */ + if (raw_cause & 0x00000004) + flags |= RESET_FLAG_SOFT; + + if (raw_cause & 0x00070008) + flags |= RESET_FLAG_OTHER; + + system_set_reset_flags(flags); + + /* clear it by writing 1's */ + NRF51_POWER_RESETREAS = raw_cause; +} + + +void system_reset(int flags) +{ + CPRINTS("TODO: implement %s(). Infinite loop.", __func__); + while (1) + ; +} + +int system_get_vbnvcontext(uint8_t *block) +{ + CPRINTS("TODO: implement %s()", __func__); + return EC_ERROR_UNIMPLEMENTED; +} + +int system_set_vbnvcontext(const uint8_t *block) +{ + CPRINTS("TODO: implement %s()", __func__); + return EC_ERROR_UNIMPLEMENTED; +} + +void system_pre_init(void) +{ + check_reset_cause(); +} diff --git a/chip/nrf51/uart.c b/chip/nrf51/uart.c new file mode 100644 index 0000000000..90c1990541 --- /dev/null +++ b/chip/nrf51/uart.c @@ -0,0 +1,130 @@ +/* Copyright (c) 2014 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. + */ + +/* USART driver for Chrome EC */ + +#include "clock.h" +#include "console.h" +#include "common.h" +#include "dma.h" +#include "hooks.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "uart.h" +#include "util.h" + +#define CPUTS(outstr) cputs(CC_SYSTEM, outstr) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) + + +static int ever_sent; /* if we ever sent byte to TXD? */ +static int init_done; /* Initialization done? */ +static int should_stop; /* Last TX control action */ + +int uart_init_done(void) +{ + return init_done; +} + +void uart_tx_start(void) +{ + disable_sleep(SLEEP_MASK_UART); + should_stop = 0; + NRF51_UART_INTENSET = (1 << NRF55_UART_TXDRDY_BIT); + task_trigger_irq(NRF51_PERID_USART); +} + +void uart_tx_stop(void) +{ + NRF51_UART_INTENCLR = (1 << NRF55_UART_TXDRDY_BIT); + should_stop = 1; + enable_sleep(SLEEP_MASK_UART); +} + +int uart_tx_ready(void) +{ + /* + * nRF51 design is NOT tx-empty style. Instead, it is if a byte is + * ever transmitted from TxD. This means NRF51_UART_TXDRDY is always + * 0 after reset. So, we use 'ever_sent' to send the first byte. + */ + return NRF51_UART_TXDRDY || (!ever_sent); +} + +int uart_rx_available(void) +{ + return NRF51_UART_RXDRDY; +} + +void uart_tx_flush(void) +{ + while (!uart_tx_ready()) + ; +} + +void uart_write_char(char c) +{ + ever_sent = 1; + NRF51_UART_TXDRDY = 0; + NRF51_UART_TXD = c; + NRF51_UART_STARTTX = 1; +} + +int uart_read_char(void) +{ + NRF51_UART_RXDRDY = 0; + return NRF51_UART_RXD; +} + +void uart_disable_interrupt(void) +{ + task_disable_irq(NRF51_PERID_USART); +} + +void uart_enable_interrupt(void) +{ + task_enable_irq(NRF51_PERID_USART); +} + + +/* Interrupt handler for console USART */ +void uart_interrupt(void) +{ +#ifndef CONFIG_UART_RX_DMA + /* + * Read input FIFO until empty. DMA-based receive does this from a + * hook in the UART buffering module. + */ + uart_process_input(); +#endif + + /* Fill output FIFO */ + uart_process_output(); + +#ifndef CONFIG_UART_TX_DMA + if (!should_stop) + NRF51_UART_INTENSET = (1 << NRF55_UART_TXDRDY_BIT); +#endif /* CONFIG_UART_TX_DMA */ + +} +DECLARE_IRQ(NRF51_PERID_USART, uart_interrupt, 2); + + +void uart_init(void) +{ + NRF51_UART_PSELTXD = NRF51_UART_TX_PIN; /* GPIO Port for Tx */ + NRF51_UART_PSELRXD = NRF51_UART_RX_PIN; /* GPIO Port for Rx */ + NRF51_UART_CONFIG = 0; /* disable HW flow control, no parity bit */ + NRF51_UART_BAUDRATE = 0x01d7e000; /* 115200 */ + NRF51_UART_ENABLE = 0x4; /* Enable UART */ + + uart_enable_interrupt(); + NRF51_UART_INTENSET = (1 << NRF55_UART_RXDRDY_BIT); + NRF51_UART_STARTRX = 1; + + init_done = 1; +} diff --git a/chip/nrf51/watchdog.c b/chip/nrf51/watchdog.c new file mode 100644 index 0000000000..0ec78a99de --- /dev/null +++ b/chip/nrf51/watchdog.c @@ -0,0 +1,20 @@ +/* Copyright (c) 2014 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. + */ + +/* Watchdog driver */ + +#include "common.h" +#include "console.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_SYSTEM, outstr) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) + + +int watchdog_init(void) +{ + CPRINTS("TODO: implement %s()", __func__); + return EC_ERROR_UNIMPLEMENTED; +} |