summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic (Chun-Ju) Yang <victoryang@chromium.org>2013-11-05 18:50:10 +0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2013-11-21 04:30:55 +0000
commit14c7191b53607e46187cea6e95ebf869f3b85e2a (patch)
tree7eccaa37279665a6c67b46c9b43cd814bb34837c
parent5524ba7bf71b8ee520f3c8410b65b5bba07544c4 (diff)
downloadchrome-ec-14c7191b53607e46187cea6e95ebf869f3b85e2a.tar.gz
mec1322: initial commit
This is the initial commit of mec1322 support. This includes: - Basic GPIO driver. Interrupt not supported yet. - Microsecond timer - UART driver The script to pack the firmware binary will be checked in in following-up CL. BUG=chrome-os-partner:24107 TEST=Build and boot on eval board BRANCH=None Change-Id: I9013c908049d1f740f84bb56abca51b779f39eef Signed-off-by: Vic (Chun-Ju) Yang <victoryang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/175716 Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--board/mec1322_evb/board.c27
-rw-r--r--board/mec1322_evb/board.h45
-rw-r--r--board/mec1322_evb/build.mk12
-rw-r--r--board/mec1322_evb/ec.tasklist21
-rw-r--r--chip/lm4/registers.h2
-rw-r--r--chip/mec1322/build.mk15
-rw-r--r--chip/mec1322/clock.c38
-rw-r--r--chip/mec1322/config_chip.h94
-rw-r--r--chip/mec1322/gpio.c116
-rw-r--r--chip/mec1322/hwtimer.c109
-rw-r--r--chip/mec1322/jtag.c13
-rw-r--r--chip/mec1322/registers.h152
-rw-r--r--chip/mec1322/system.c71
-rw-r--r--chip/mec1322/uart.c154
-rw-r--r--chip/stm32/registers.h2
-rw-r--r--include/common.h1
-rw-r--r--include/gpio.h6
17 files changed, 873 insertions, 5 deletions
diff --git a/board/mec1322_evb/board.c b/board/mec1322_evb/board.c
new file mode 100644
index 0000000000..d2638056a3
--- /dev/null
+++ b/board/mec1322_evb/board.c
@@ -0,0 +1,27 @@
+/* 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.
+ */
+/* MEC1322 eval board-specific configuration */
+
+#include "gpio.h"
+#include "registers.h"
+#include "util.h"
+
+/* GPIO signal list. Must match order from enum gpio_signal. */
+const struct gpio_info gpio_list[] = {
+ {"LED1", GPIO_PORT(15), (1 << 4), GPIO_ODR_LOW, NULL},
+ {"LED2", GPIO_PORT(15), (1 << 5), GPIO_ODR_HIGH, NULL},
+ {"LED3", GPIO_PORT(15), (1 << 6), GPIO_ODR_LOW, NULL},
+ /* Unimplemented signals which we need to emulate for now */
+ GPIO_SIGNAL_NOT_IMPLEMENTED("RECOVERYn"),
+ GPIO_SIGNAL_NOT_IMPLEMENTED("WP"),
+ GPIO_SIGNAL_NOT_IMPLEMENTED("ENTERING_RW"),
+};
+BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ {GPIO_PORT(16), 0x24, 1, MODULE_UART}, /* UART0 */
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
diff --git a/board/mec1322_evb/board.h b/board/mec1322_evb/board.h
new file mode 100644
index 0000000000..269cb4fb9d
--- /dev/null
+++ b/board/mec1322_evb/board.h
@@ -0,0 +1,45 @@
+/* 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.
+ */
+
+/* MEC1322 eval board configuration */
+
+#ifndef __BOARD_H
+#define __BOARD_H
+
+/* Optional features */
+#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands */
+
+/* Modules we want to exclude */
+#undef CONFIG_EEPROM
+#undef CONFIG_EOPTION
+#undef CONFIG_PSTORE
+#undef CONFIG_LID_SWITCH
+#undef CONFIG_LPC
+#undef CONFIG_PECI
+#undef CONFIG_SWITCH
+#undef CONFIG_WATCHDOG
+
+#ifndef __ASSEMBLER__
+
+/* GPIO signal list */
+enum gpio_signal {
+ GPIO_LED1 = 0,
+ GPIO_LED2,
+ GPIO_LED3,
+ /*
+ * Signals which aren't implemented on MEC1322 eval board but we'll
+ * emulate anyway, to make it more convenient to debug other code.
+ */
+ GPIO_RECOVERYn, /* Recovery signal from DOWN button */
+ GPIO_WP, /* Write protect input */
+ GPIO_ENTERING_RW, /* EC entering RW code */
+
+ /* Number of GPIOs; not an actual GPIO */
+ GPIO_COUNT
+};
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* __BOARD_H */
diff --git a/board/mec1322_evb/build.mk b/board/mec1322_evb/build.mk
new file mode 100644
index 0000000000..5f03511802
--- /dev/null
+++ b/board/mec1322_evb/build.mk
@@ -0,0 +1,12 @@
+# -*- makefile -*-
+# 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.
+#
+# Board specific files build
+#
+
+# the IC is SMSC MEC1322
+CHIP:=mec1322
+
+board-y=board.o
diff --git a/board/mec1322_evb/ec.tasklist b/board/mec1322_evb/ec.tasklist
new file mode 100644
index 0000000000..d3ac489b42
--- /dev/null
+++ b/board/mec1322_evb/ec.tasklist
@@ -0,0 +1,21 @@
+/* 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.
+ */
+
+/**
+ * List of enabled tasks in the priority order
+ *
+ * The first one has the lowest priority.
+ *
+ * For each task, use the macro TASK_ALWAYS(n, r, d, s) for base tasks and
+ * TASK_NOTEST(n, r, d, s) for tasks that can be excluded in test binaries,
+ * 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, TASK_STACK_SIZE) \
+ TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE)
diff --git a/chip/lm4/registers.h b/chip/lm4/registers.h
index b87a7b55ec..8db3b2c71f 100644
--- a/chip/lm4/registers.h
+++ b/chip/lm4/registers.h
@@ -487,6 +487,8 @@ enum clock_gate_offsets {
#define GPIO_P LM4_GPIO_P
#define GPIO_Q LM4_GPIO_Q
+#define DUMMY_GPIO_BANK GPIO_A
+
/* Value to write to LM4_GPIO_LOCK to unlock writes */
#define LM4_GPIO_LOCK_UNLOCK 0x4c4f434b
diff --git a/chip/mec1322/build.mk b/chip/mec1322/build.mk
new file mode 100644
index 0000000000..ae435bf8c6
--- /dev/null
+++ b/chip/mec1322/build.mk
@@ -0,0 +1,15 @@
+# -*- makefile -*-
+# 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.
+#
+# MEC1322 chip specific files build
+#
+
+# MEC1322 SoC has a Cortex-M4 ARM core
+CORE:=cortex-m
+# Allow the full Cortex-M4 instruction set
+CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4
+
+# Required chip modules
+chip-y=clock.o gpio.o hwtimer.o system.o uart.o jtag.o
diff --git a/chip/mec1322/clock.c b/chip/mec1322/clock.c
new file mode 100644
index 0000000000..6111b7de86
--- /dev/null
+++ b/chip/mec1322/clock.c
@@ -0,0 +1,38 @@
+/* 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.
+ */
+
+/* Clocks and power management settings */
+
+#include "clock.h"
+#include "common.h"
+#include "console.h"
+#include "registers.h"
+#include "util.h"
+
+/* Console output macros */
+#define CPUTS(outstr) cputs(CC_CLOCK, outstr)
+#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args)
+
+static int freq = 48000000;
+
+void clock_wait_cycles(uint32_t cycles)
+{
+ asm("1: subs %0, #1\n"
+ " bne 1b\n" :: "r"(cycles));
+}
+
+int clock_get_freq(void)
+{
+ return freq;
+}
+
+void clock_init(void)
+{
+ /* XOSEL = Single ended clock source */
+ MEC1322_VBAT_CE |= 0x1;
+
+ /* 32K clock enable */
+ MEC1322_VBAT_CE |= 0x2;
+}
diff --git a/chip/mec1322/config_chip.h b/chip/mec1322/config_chip.h
new file mode 100644
index 0000000000..93cb2b4dda
--- /dev/null
+++ b/chip/mec1322/config_chip.h
@@ -0,0 +1,94 @@
+/* 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.
+ */
+
+#ifndef __CROS_EC_CONFIG_CHIP_H
+#define __CROS_EC_CONFIG_CHIP_H
+
+/* CPU core BFD configuration */
+#include "core/cortex-m/config_core.h"
+
+/* Number of IRQ vectors on the NVIC */
+#define CONFIG_IRQ_COUNT 93
+
+/* Use a bigger console output buffer */
+#undef CONFIG_UART_TX_BUF_SIZE
+#define CONFIG_UART_TX_BUF_SIZE 2048
+
+/* Interval between HOOK_TICK notifications */
+#define HOOK_TICK_INTERVAL (250 * MSEC)
+
+/* Maximum number of deferrable functions */
+#define DEFERRABLE_MAX_COUNT 8
+
+/* Number of I2C ports */
+#define I2C_PORT_COUNT 4
+
+/****************************************************************************/
+/* Memory mapping */
+
+/*
+ * The memory region for RAM is actually 0x00100000-0x00120000. The lower 96K
+ * stores code and the higher 32K stores data. To reflect this, let's say
+ * the lower 96K is flash, and the higher 32K is RAM.
+ */
+#define CONFIG_RAM_BASE 0x00118000
+#define CONFIG_RAM_SIZE 0x00008000
+
+/* System stack size */
+#define CONFIG_STACK_SIZE 4096
+
+/* non-standard task stack sizes */
+#define IDLE_TASK_STACK_SIZE 512
+#define LARGER_TASK_STACK_SIZE 640
+
+/* Default task stack size */
+#define TASK_STACK_SIZE 512
+
+#define CONFIG_FLASH_BASE 0x00100000
+
+#define CONFIG_FLASH_PHYSICAL_SIZE 0x00018000
+
+/* Size of one firmware image in RAM */
+
+/****************************************************************************/
+/* Define our flash layout. */
+
+/* Size of one firmware image in flash */
+#ifndef CONFIG_FW_IMAGE_SIZE
+#define CONFIG_FW_IMAGE_SIZE (CONFIG_FLASH_PHYSICAL_SIZE / 2)
+#endif
+
+/* RO firmware must start at beginning of flash */
+#define CONFIG_FW_RO_OFF 0
+
+#define CONFIG_FW_RO_SIZE CONFIG_FW_IMAGE_SIZE
+#define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE
+
+/* Either way, RW firmware is one firmware image offset from the start */
+#define CONFIG_FW_RW_OFF CONFIG_FW_IMAGE_SIZE
+#define CONFIG_FW_RW_SIZE CONFIG_FW_IMAGE_SIZE
+
+/* TODO(crosbug.com/p/23796): why 2 sets of configs with the same numbers? */
+#define CONFIG_FW_WP_RO_OFF CONFIG_FW_RO_OFF
+#define CONFIG_FW_WP_RO_SIZE CONFIG_FW_RO_SIZE
+
+#define CONFIG_FLASH_BANK_SIZE 4
+
+/****************************************************************************/
+/* Customize the build */
+/* Optional features present on this chip */
+#if 0
+#define CONFIG_ADC
+#define CONFIG_I2C
+#define CONFIG_LPC
+#define CONFIG_PECI
+#define CONFIG_SWITCH
+#define CONFIG_MPU
+#endif
+#define CONFIG_FPU
+
+#undef CONFIG_FLASH
+
+#endif /* __CROS_EC_CONFIG_CHIP_H */
diff --git a/chip/mec1322/gpio.c b/chip/mec1322/gpio.c
new file mode 100644
index 0000000000..065b4383ec
--- /dev/null
+++ b/chip/mec1322/gpio.c
@@ -0,0 +1,116 @@
+/* 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.
+ */
+
+/* GPIO module for MEC1322 */
+
+#include "common.h"
+#include "gpio.h"
+#include "registers.h"
+#include "timer.h"
+#include "util.h"
+
+void gpio_set_alternate_function(uint32_t port, uint32_t mask, int func)
+{
+ int i;
+ uint32_t val;
+
+ while (mask) {
+ i = __builtin_ffs(mask) - 1;
+ val = MEC1322_GPIO_CTL(port, i);
+ val &= ~((1 << 12) | (1 << 13));
+ val |= (func & 0x3) << 12;
+ MEC1322_GPIO_CTL(port, i) = val;
+ mask &= ~(1 << i);
+ }
+}
+
+test_mockable int gpio_get_level(enum gpio_signal signal)
+{
+ uint32_t mask = gpio_list[signal].mask;
+ int i = 31 - __builtin_clz(mask);
+ uint32_t val = MEC1322_GPIO_CTL(gpio_list[signal].port, i);
+
+ if (val & (1 << 9)) /* Output */
+ return (val & (1 << 16)) ? 1 : 0;
+ else
+ return (val & (1 << 24)) ? 1 : 0;
+}
+
+void gpio_set_level(enum gpio_signal signal, int value)
+{
+ uint32_t mask = gpio_list[signal].mask;
+ int i = 31 - __builtin_clz(mask);
+ if (value)
+ MEC1322_GPIO_CTL(gpio_list[signal].port, i) |= (1 << 16);
+ else
+ MEC1322_GPIO_CTL(gpio_list[signal].port, i) &= ~(1 << 16);
+}
+
+void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags)
+{
+ int i;
+ uint32_t val;
+ while (mask) {
+ i = 31 - __builtin_clz(mask);
+ mask &= ~(1 << i);
+ val = MEC1322_GPIO_CTL(port, i);
+
+ /*
+ * Select open drain first, so that we don't glitch the signal
+ * when changing the line to an output.
+ */
+ if (flags & GPIO_OPEN_DRAIN)
+ val |= (1 << 8);
+ else
+ val &= ~(1 << 8);
+
+ if (flags & GPIO_OUTPUT) {
+ val |= (1 << 9);
+ val &= ~(1 << 10);
+ } else {
+ val &= ~(1 << 9);
+ val |= (1 << 10);
+ }
+
+ /* Handle pullup / pulldown */
+ if (flags & GPIO_PULL_UP)
+ val = (val & ~0x3) | 0x1;
+ else if (flags & GPIO_PULL_DOWN)
+ val = (val & ~0x3) | 0x2;
+ else
+ val &= ~0x3;
+
+ /* TODO(crosbug.com/p/24107): Set up interrupt */
+
+ /* Use as GPIO */
+ val &= ~((1 << 12) | (1 << 13));
+
+ MEC1322_GPIO_CTL(port, i) = val;
+
+ if (flags & GPIO_HIGH)
+ MEC1322_GPIO_CTL(port, i) |= (1 << 16);
+ else
+ MEC1322_GPIO_CTL(port, i) &= ~(1 << 16);
+ }
+}
+
+int gpio_enable_interrupt(enum gpio_signal signal)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+int gpio_disable_interrupt(enum gpio_signal signal)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
+void gpio_pre_init(void)
+{
+ int i;
+ 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);
+}
diff --git a/chip/mec1322/hwtimer.c b/chip/mec1322/hwtimer.c
new file mode 100644
index 0000000000..51fa28647b
--- /dev/null
+++ b/chip/mec1322/hwtimer.c
@@ -0,0 +1,109 @@
+/* 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.
+ */
+
+/* Hardware timers driver */
+
+#include "clock.h"
+#include "common.h"
+#include "hooks.h"
+#include "hwtimer.h"
+#include "registers.h"
+#include "task.h"
+#include "timer.h"
+
+void __hw_clock_event_set(uint32_t deadline)
+{
+ MEC1322_TMR32_CNT(1) = MEC1322_TMR32_CNT(0) -
+ (0xffffffff - deadline);
+ MEC1322_TMR32_CTL(1) |= (1 << 5);
+}
+
+uint32_t __hw_clock_event_get(void)
+{
+ return MEC1322_TMR32_CNT(1) - MEC1322_TMR32_CNT(0) + 0xffffffff;
+}
+
+void __hw_clock_event_clear(void)
+{
+ MEC1322_TMR32_CTL(1) &= ~(1 << 5);
+}
+
+uint32_t __hw_clock_source_read(void)
+{
+ return 0xffffffff - MEC1322_TMR32_CNT(0);
+}
+
+void __hw_clock_source_set(uint32_t ts)
+{
+ MEC1322_TMR32_CTL(0) &= ~(1 << 5);
+ MEC1322_TMR32_CNT(0) = 0xffffffff - ts;
+ MEC1322_TMR32_CTL(0) |= (1 << 5);
+}
+
+static void __hw_clock_source_irq(int timer_id)
+{
+ if (timer_id == 1)
+ MEC1322_TMR32_STS(1) |= 1;
+ /* If IRQ is from timer 0, 32-bit timer overflowed */
+ process_timers(timer_id == 0);
+}
+
+static void __hw_clock_source_irq_0(void) { __hw_clock_source_irq(0); }
+DECLARE_IRQ(MEC1322_IRQ_TIMER32_0, __hw_clock_source_irq_0, 1);
+static void __hw_clock_source_irq_1(void) { __hw_clock_source_irq(1); }
+DECLARE_IRQ(MEC1322_IRQ_TIMER32_1, __hw_clock_source_irq_1, 1);
+
+static void configure_timer(int timer_id)
+{
+ uint32_t val;
+
+ /* Ensure timer is not running */
+ MEC1322_TMR32_CTL(timer_id) &= ~(1 << 5);
+
+ /* Enable timer */
+ MEC1322_TMR32_CTL(timer_id) |= (1 << 0);
+
+ val = MEC1322_TMR32_CTL(timer_id);
+
+ /* Pre-scale = 48 -> 1MHz -> Period = 1us */
+ val = (val & 0xffff) | (47 << 16);
+
+ MEC1322_TMR32_CTL(timer_id) = val;
+
+ /* Set preload to use the full 32 bits of the timer */
+ MEC1322_TMR32_PRE(timer_id) = 0xffffffff;
+
+ /* Enable interrupt */
+ MEC1322_TMR32_IEN(timer_id) |= 1;
+}
+
+int __hw_clock_source_init(uint32_t start_t)
+{
+ /*
+ * The timer can only fire interrupt when its value reaches zero.
+ * Therefore we need two timers:
+ * - Timer 0 as free running timer
+ * - Timer 1 as event timer
+ */
+ configure_timer(0);
+ configure_timer(1);
+
+ /* Override the count */
+ MEC1322_TMR32_CNT(0) = 0xffffffff - start_t;
+
+ /* Auto restart */
+ MEC1322_TMR32_CTL(0) |= (1 << 3);
+
+ /* Start counting in timer 0 */
+ MEC1322_TMR32_CTL(0) |= (1 << 5);
+
+ /* Enable interrupt */
+ task_enable_irq(MEC1322_IRQ_TIMER32_0);
+ task_enable_irq(MEC1322_IRQ_TIMER32_1);
+ MEC1322_INT_ENABLE(23) |= (1 << 4) | (1 << 5);
+ MEC1322_INT_BLK_EN |= (1 << 23);
+
+ return MEC1322_IRQ_TIMER32_1;
+}
diff --git a/chip/mec1322/jtag.c b/chip/mec1322/jtag.c
new file mode 100644
index 0000000000..fdc2ed63cd
--- /dev/null
+++ b/chip/mec1322/jtag.c
@@ -0,0 +1,13 @@
+/* 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.
+ */
+/* Settings to enable JTAG debugging */
+
+#include "jtag.h"
+#include "registers.h"
+
+void jtag_pre_init(void)
+{
+ /* Not implemented yet */
+}
diff --git a/chip/mec1322/registers.h b/chip/mec1322/registers.h
new file mode 100644
index 0000000000..1e7634267f
--- /dev/null
+++ b/chip/mec1322/registers.h
@@ -0,0 +1,152 @@
+/* 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 MEC1322 processor
+ */
+
+#ifndef __CROS_EC_REGISTERS_H
+#define __CROS_EC_REGISTERS_H
+
+#include "common.h"
+
+/* EC Chip Configuration */
+#define MEC1322_CHIP_BASE 0x400fff00
+#define MEC1322_CHIP_DEV_ID REG8(MEC1322_CHIP_BASE + 0x20)
+#define MEC1322_CHIP_DEV_REV REG8(MEC1322_CHIP_BASE + 0x21)
+
+
+/* EC Subsystem */
+#define MEC1322_EC_BASE 0x4000fc00
+#define MEC1322_EC_INT_CTRL REG32(MEC1322_EC_BASE + 0x18)
+
+
+/* Interrupt aggregator */
+#define MEC1322_INT_BASE 0x4000c000
+#define MEC1322_INTx_BASE(x) (MEC1322_INT_BASE + ((x) - 8) * 0x14)
+#define MEC1322_INT_SOURCE(x) REG32(MEC1322_INTx_BASE(x) + 0x0)
+#define MEC1322_INT_ENABLE(x) REG32(MEC1322_INTx_BASE(x) + 0x4)
+#define MEC1322_INT_RESULT(x) REG32(MEC1322_INTx_BASE(x) + 0x8)
+#define MEC1322_INT_DISABLE(x) REG32(MEC1322_INTx_BASE(x) + 0xc)
+#define MEC1322_INT_BLK_EN REG32(MEC1322_INT_BASE + 0x200)
+#define MEC1322_INT_BLK_DIS REG32(MEC1322_INT_BASE + 0x204)
+#define MEC1322_INT_BLK_IRQ REG32(MEC1322_INT_BASE + 0x208)
+
+
+/* UART */
+#define MEC1322_UART_CONFIG_BASE 0x400f1f00
+#define MEC1322_UART_RUNTIME_BASE 0x400f1c00
+
+#define MEC1322_UART_ACT REG8(MEC1322_UART_CONFIG_BASE + 0x30)
+#define MEC1322_UART_CFG REG8(MEC1322_UART_CONFIG_BASE + 0xf0)
+
+/* DLAB=0 */
+#define MEC1322_UART_RB /*R*/ REG8(MEC1322_UART_RUNTIME_BASE + 0x0)
+#define MEC1322_UART_TB /*W*/ REG8(MEC1322_UART_RUNTIME_BASE + 0x0)
+#define MEC1322_UART_IER REG8(MEC1322_UART_RUNTIME_BASE + 0x1)
+/* DLAB=1 */
+#define MEC1322_UART_PBRG0 REG8(MEC1322_UART_RUNTIME_BASE + 0x0)
+#define MEC1322_UART_PBRG1 REG8(MEC1322_UART_RUNTIME_BASE + 0x1)
+
+#define MEC1322_UART_FCR /*W*/ REG8(MEC1322_UART_RUNTIME_BASE + 0x2)
+#define MEC1322_UART_IIR /*R*/ REG8(MEC1322_UART_RUNTIME_BASE + 0x2)
+#define MEC1322_UART_LCR REG8(MEC1322_UART_RUNTIME_BASE + 0x3)
+#define MEC1322_UART_MCR REG8(MEC1322_UART_RUNTIME_BASE + 0x4)
+#define MEC1322_UART_LSR REG8(MEC1322_UART_RUNTIME_BASE + 0x5)
+#define MEC1322_UART_MSR REG8(MEC1322_UART_RUNTIME_BASE + 0x6)
+#define MEC1322_UART_SCR REG8(MEC1322_UART_RUNTIME_BASE + 0x7)
+
+
+/* GPIO */
+#define MEC1322_GPIO_BASE 0x40081000
+#define MEC1322_GPIO_PORT(x) (x)
+#define GPIO_PORT(x) MEC1322_GPIO_PORT(x)
+static inline uintptr_t gpio_port_base(int port_id)
+{
+ int oct = (port_id / 10) * 8 + port_id % 10;
+ return MEC1322_GPIO_BASE + oct * 0x20;
+}
+#define MEC1322_GPIO_CTL(port, id) REG32(gpio_port_base(port) + (id << 2))
+
+#define DUMMY_GPIO_BANK GPIO_PORT(0)
+
+
+/* Timer */
+#define MEC1322_TMR16_BASE(x) (0x40000c00 + (x) * 0x20)
+#define MEC1322_TMR32_BASE(x) (0x40000c80 + (x) * 0x20)
+
+#define MEC1322_TMR16_CNT(x) REG32(MEC1322_TMR16_BASE(x) + 0x0)
+#define MEC1322_TMR16_PRE(x) REG32(MEC1322_TMR16_BASE(x) + 0x4)
+#define MEC1322_TMR16_STS(x) REG32(MEC1322_TMR16_BASE(x) + 0x8)
+#define MEC1322_TMR16_IEN(x) REG32(MEC1322_TMR16_BASE(x) + 0xc)
+#define MEC1322_TMR16_CTL(x) REG32(MEC1322_TMR16_BASE(x) + 0x10)
+#define MEC1322_TMR32_CNT(x) REG32(MEC1322_TMR32_BASE(x) + 0x0)
+#define MEC1322_TMR32_PRE(x) REG32(MEC1322_TMR32_BASE(x) + 0x4)
+#define MEC1322_TMR32_STS(x) REG32(MEC1322_TMR32_BASE(x) + 0x8)
+#define MEC1322_TMR32_IEN(x) REG32(MEC1322_TMR32_BASE(x) + 0xc)
+#define MEC1322_TMR32_CTL(x) REG32(MEC1322_TMR32_BASE(x) + 0x10)
+
+
+/* Watchdog */
+#define MEC1322_WDG_BASE 0x40000400
+#define MEC1322_WDG_LOAD REG16(MEC1322_WDG_BASE + 0x0)
+#define MEC1322_WDG_CTL REG8(MEC1322_WDG_BASE + 0x4)
+#define MEC1322_WDG_KICK REG8(MEC1322_WDG_BASE + 0x8)
+#define MEC1322_WDG_CNT REG16(MEC1322_WDG_BASE + 0xc)
+
+
+/* VBAT */
+#define MEC1322_VBAT_BASE 0x4000a400
+#define MEC1322_VBAT_STS REG32(MEC1322_VBAT_BASE + 0x0)
+#define MEC1322_VBAT_CE REG32(MEC1322_VBAT_BASE + 0x8)
+
+
+/* IRQ Numbers */
+#define MEC1322_IRQ_I2C_0 0
+#define MEC1322_IRQ_I2C_1 1
+#define MEC1322_IRQ_I2C_2 2
+#define MEC1322_IRQ_I2C_3 3
+#define MEC1322_IRQ_DMA_0 4
+#define MEC1322_IRQ_DMA_1 5
+#define MEC1322_IRQ_DMA_2 6
+#define MEC1322_IRQ_DMA_3 7
+#define MEC1322_IRQ_DMA_4 8
+#define MEC1322_IRQ_DMA_5 9
+#define MEC1322_IRQ_DMA_6 10
+#define MEC1322_IRQ_DMA_7 11
+#define MEC1322_IRQ_LPC 12
+#define MEC1322_IRQ_UART 13
+#define MEC1322_IRQ_EMI 14
+#define MEC1322_IRQ_ACPIEC0_IBF 15
+#define MEC1322_IRQ_ACPIEC0_OBF 16
+#define MEC1322_IRQ_TIMER16_0 49
+#define MEC1322_IRQ_TIMER16_1 50
+#define MEC1322_IRQ_TIMER16_2 51
+#define MEC1322_IRQ_TIMER16_3 52
+#define MEC1322_IRQ_TIMER32_0 53
+#define MEC1322_IRQ_TIMER32_1 54
+#define MEC1322_IRQ_GIRQ8 57
+#define MEC1322_IRQ_GIRQ9 58
+#define MEC1322_IRQ_GIRQ10 59
+#define MEC1322_IRQ_GIRQ11 60
+#define MEC1322_IRQ_GIRQ12 61
+#define MEC1322_IRQ_GIRQ13 62
+#define MEC1322_IRQ_GIRQ14 63
+#define MEC1322_IRQ_GIRQ15 64
+#define MEC1322_IRQ_GIRQ16 65
+#define MEC1322_IRQ_GIRQ17 66
+#define MEC1322_IRQ_GIRQ18 67
+#define MEC1322_IRQ_GIRQ19 68
+#define MEC1322_IRQ_GIRQ20 69
+#define MEC1322_IRQ_GIRQ21 70
+#define MEC1322_IRQ_GIRQ22 71
+#define MEC1322_IRQ_GIRQ23 72
+#define MEC1322_IRQ_DMA_8 81
+#define MEC1322_IRQ_DMA_9 82
+#define MEC1322_IRQ_DMA_10 83
+#define MEC1322_IRQ_DMA_11 84
+#define MEC1322_IRQ_PWM_WDT3 85
+#define MEC1322_IRQ_RTC 91
+#define MEC1322_IRQ_RTC_ALARM 92
+
+#endif /* __CROS_EC_REGISTERS_H */
diff --git a/chip/mec1322/system.c b/chip/mec1322/system.c
new file mode 100644
index 0000000000..f86f8e144f
--- /dev/null
+++ b/chip/mec1322/system.c
@@ -0,0 +1,71 @@
+/* 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.
+ */
+
+/* System module for Chrome EC : MEC1322 hardware specific implementation */
+
+#include "clock.h"
+#include "common.h"
+#include "console.h"
+#include "cpu.h"
+#include "host_command.h"
+#include "registers.h"
+#include "system.h"
+#include "task.h"
+#include "timer.h"
+#include "util.h"
+
+
+#define DUMMY(x) x {}
+#define DUMMY_int(x) x { return 0; }
+
+DUMMY(void system_hibernate(uint32_t seconds, uint32_t microseconds));
+DUMMY_int(int system_get_vbnvcontext(uint8_t *block));
+DUMMY_int(int system_set_vbnvcontext(const uint8_t *block));
+
+void system_pre_init(void)
+{
+ /* Enable direct NVIC */
+ MEC1322_EC_INT_CTRL |= 1;
+}
+
+void system_reset(int flags)
+{
+ /* Trigger watchdog in 1ms */
+ MEC1322_WDG_LOAD = 1;
+ MEC1322_WDG_CTL |= 1;
+}
+
+const char *system_get_chip_vendor(void)
+{
+ return "smsc";
+}
+
+const char *system_get_chip_name(void)
+{
+ switch (MEC1322_CHIP_DEV_ID) {
+ case 0x15:
+ return "mec1322";
+ default:
+ return "unknown";
+ }
+}
+
+static char to_hex(int x)
+{
+ if (x >= 0 && x <= 9)
+ return '0' + x;
+ return 'a' + x - 10;
+}
+
+const char *system_get_chip_revision(void)
+{
+ static char buf[3];
+ uint8_t rev = MEC1322_CHIP_DEV_REV;
+
+ buf[0] = to_hex(rev / 16);
+ buf[1] = to_hex(rev & 0xf);
+ buf[2] = '\0';
+ return buf;
+}
diff --git a/chip/mec1322/uart.c b/chip/mec1322/uart.c
new file mode 100644
index 0000000000..351541de9d
--- /dev/null
+++ b/chip/mec1322/uart.c
@@ -0,0 +1,154 @@
+/* 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.
+ */
+
+/* UART module for MEC1322 */
+
+#include "clock.h"
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "lpc.h"
+#include "registers.h"
+#include "system.h"
+#include "task.h"
+#include "uart.h"
+#include "util.h"
+
+static int init_done;
+
+int uart_init_done(void)
+{
+ return init_done;
+}
+
+void uart_tx_start(void)
+{
+ /* If interrupt is already enabled, nothing to do */
+ if (MEC1322_UART_IER & (1 << 1))
+ return;
+
+ /*
+ * Re-enable the transmit interrupt, then forcibly trigger the
+ * interrupt. This works around a hardware problem with the
+ * UART where the FIFO only triggers the interrupt when its
+ * threshold is _crossed_, not just met.
+ */
+ MEC1322_UART_IER |= (1 << 1);
+ task_trigger_irq(MEC1322_IRQ_UART);
+}
+
+void uart_tx_stop(void)
+{
+ MEC1322_UART_IER &= ~(1 << 1);
+}
+
+void uart_tx_flush(void)
+{
+ /* Wait for transmit FIFO empty */
+ while (!(MEC1322_UART_LSR & (1 << 5)))
+ ;
+}
+
+int uart_tx_ready(void)
+{
+ /*
+ * TODO(crosbug.com/p/24107): This is FIFO empty bit instead of
+ * FIFO full bit?
+ */
+ return MEC1322_UART_LSR & (1 << 5);
+}
+
+int uart_rx_available(void)
+{
+ return MEC1322_UART_LSR & (1 << 0);
+}
+
+void uart_write_char(char c)
+{
+ /* Wait for space in transmit FIFO. */
+ while (!uart_tx_ready())
+ ;
+
+ MEC1322_UART_TB = c;
+}
+
+int uart_read_char(void)
+{
+ return MEC1322_UART_RB;
+}
+
+static void uart_clear_rx_fifo(int channel)
+{
+ MEC1322_UART_FCR = (1 << 0) | (1 << 1);
+}
+
+void uart_disable_interrupt(void)
+{
+ task_disable_irq(MEC1322_IRQ_UART);
+}
+
+void uart_enable_interrupt(void)
+{
+ task_enable_irq(MEC1322_IRQ_UART);
+}
+
+/**
+ * Interrupt handler for UART
+ */
+static void uart_ec_interrupt(void)
+{
+ /* Read input FIFO until empty, then fill output FIFO */
+ uart_process_input();
+ uart_process_output();
+}
+DECLARE_IRQ(MEC1322_IRQ_UART, uart_ec_interrupt, 1);
+
+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);
+
+ /*
+ clock_enable_peripheral(CGC_OFFSET_UART, mask,
+ CGC_MODE_RUN | CGC_MODE_SLEEP);*/
+
+ gpio_config_module(MODULE_UART, 1);
+
+ /*
+ * Enable interrupts for UART0.
+ */
+ uart_clear_rx_fifo(0);
+ MEC1322_UART_IER |= (1 << 0);
+ MEC1322_UART_MCR |= (1 << 3);
+ MEC1322_INT_ENABLE(15) |= (1 << 0);
+ MEC1322_INT_BLK_EN |= (1 << 15);
+ task_enable_irq(MEC1322_IRQ_UART);
+
+ init_done = 1;
+}
diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h
index 71c254c992..ead13c58d1 100644
--- a/chip/stm32/registers.h
+++ b/chip/stm32/registers.h
@@ -214,6 +214,8 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define GPIO_G STM32_GPIOG_BASE
#define GPIO_H STM32_GPIOH_BASE
+#define DUMMY_GPIO_BANK GPIO_A
+
#if defined(CHIP_FAMILY_stm32l)
#define STM32_GPIOA_BASE 0x40020000
#define STM32_GPIOB_BASE 0x40020400
diff --git a/include/common.h b/include/common.h
index 06888191fe..b15b72e629 100644
--- a/include/common.h
+++ b/include/common.h
@@ -30,6 +30,7 @@
/* Macros to access registers */
#define REG32(addr) (*(volatile uint32_t *)(addr))
#define REG16(addr) (*(volatile uint16_t *)(addr))
+#define REG8(addr) (*(volatile uint8_t *)(addr))
/*
* Define __aligned(n) and __packed if someone hasn't beat us to it. Linux
diff --git a/include/gpio.h b/include/gpio.h
index fc46e995ce..6b1f80fe99 100644
--- a/include/gpio.h
+++ b/include/gpio.h
@@ -71,11 +71,7 @@ struct gpio_info {
extern const struct gpio_info gpio_list[];
/* Macro for signals which don't exist */
-#ifdef CHIP_lm4
-#define GPIO_SIGNAL_NOT_IMPLEMENTED(name) {name, LM4_GPIO_A, 0, 0, NULL}
-#else
-#define GPIO_SIGNAL_NOT_IMPLEMENTED(name) {name, GPIO_A, 0, 0, NULL}
-#endif
+#define GPIO_SIGNAL_NOT_IMPLEMENTED(name) {name, DUMMY_GPIO_BANK, 0, 0, NULL}
/* GPIO alternate function structure, for use by board.c */
struct gpio_alt_func {