summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Yung-Chieh Lo <yjlou@chromium.org>2014-07-15 10:41:16 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-07-29 02:21:22 +0000
commitf93f1cfe77ed3603ab16047d79a283a781416db4 (patch)
treed0ec489650265d06c90297b884f02b96b18094c0
parentbbb5b0636b5d2b9a9d339e32142bf775717bd929 (diff)
downloadchrome-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.c12
-rw-r--r--board/hadoken/board.h30
-rw-r--r--board/hadoken/build.mk13
-rw-r--r--board/hadoken/ec.tasklist20
-rw-r--r--board/hadoken/gpio.inc46
-rw-r--r--chip/nrf51/build.mk16
-rw-r--r--chip/nrf51/clock.c10
-rw-r--r--chip/nrf51/config_chip.h70
-rw-r--r--chip/nrf51/gpio.c101
-rw-r--r--chip/nrf51/hwtimer.c194
-rw-r--r--chip/nrf51/jtag.c9
-rw-r--r--chip/nrf51/registers.h200
-rw-r--r--chip/nrf51/system.c93
-rw-r--r--chip/nrf51/uart.c130
-rw-r--r--chip/nrf51/watchdog.c20
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;
+}