summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/discovery/board.c20
-rw-r--r--board/discovery/board.h8
-rw-r--r--chip/stm32l/build.mk2
-rw-r--r--chip/stm32l/gpio.c69
-rw-r--r--chip/stm32l/registers.h18
-rw-r--r--chip/stm32l/watchdog.c6
6 files changed, 108 insertions, 15 deletions
diff --git a/board/discovery/board.c b/board/discovery/board.c
index 560773d829..e6a360dbbd 100644
--- a/board/discovery/board.c
+++ b/board/discovery/board.c
@@ -6,7 +6,19 @@
#include "board.h"
#include "common.h"
+#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[GPIO_COUNT] = {
+ /* Inputs with interrupt handlers are first for efficiency */
+ {"USER_BUTTON", GPIO_A, (1<<0), GPIO_INT_BOTH, NULL},
+ /* Other inputs */
+ /* Outputs */
+ {"BLUE_LED", GPIO_B, (1<<6), GPIO_OUT_LOW, NULL},
+ {"GREEN_LED", GPIO_B, (1<<7), GPIO_OUT_LOW, NULL},
+};
void configure_board(void)
{
@@ -20,9 +32,6 @@ void configure_board(void)
(0x7 << 12) | (0x7 << 8);
STM32L_GPIO_MODER(B) = (STM32L_GPIO_MODER(B) & ~0x00F00000) |
0x00A00000;
-
- /* Green and blue LEDs : configure port 6 and 7 as output */
- STM32L_GPIO_MODER(B) |= (1 << (7 * 2)) | (1 << (6 * 2));
}
/**
@@ -37,11 +46,6 @@ int jtag_pre_init(void)
return EC_SUCCESS;
}
-int gpio_pre_init(void)
-{
- return EC_SUCCESS;
-}
-
int eeprom_init(void)
{
return EC_SUCCESS;
diff --git a/board/discovery/board.h b/board/discovery/board.h
index 42365cacf2..25d681a18b 100644
--- a/board/discovery/board.h
+++ b/board/discovery/board.h
@@ -18,8 +18,12 @@
/* GPIO signal list */
enum gpio_signal {
- GPIO_DUMMY0 = 0, /* Dummy GPIO */
- GPIO_DUMMY1,
+ /* Inputs with interrupt handlers are first for efficiency */
+ GPIO_USER_BUTTON = 0, /* Blue user button */
+ /* Other inputs */
+ /* Outputs */
+ GPIO_BLUE_LED, /* Blue debug LED */
+ GPIO_GREEN_LED, /* Green debug LED */
/* Number of GPIOs; not an actual GPIO */
GPIO_COUNT
diff --git a/chip/stm32l/build.mk b/chip/stm32l/build.mk
index bb354c2f92..6f7c8bcda1 100644
--- a/chip/stm32l/build.mk
+++ b/chip/stm32l/build.mk
@@ -8,5 +8,5 @@
# STM32L15xx SoC family has a Cortex-M3 ARM core
CORE:=cortex-m
-chip-y=uart.o clock.o hwtimer.o system.o
+chip-y=uart.o clock.o hwtimer.o system.o gpio.o
chip-$(CONFIG_TASK_WATCHDOG)+=watchdog.o
diff --git a/chip/stm32l/gpio.c b/chip/stm32l/gpio.c
new file mode 100644
index 0000000000..56d22abf62
--- /dev/null
+++ b/chip/stm32l/gpio.c
@@ -0,0 +1,69 @@
+/* Copyright (c) 2012 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 Chrome EC */
+
+#include "board.h"
+#include "gpio.h"
+#include "registers.h"
+#include "task.h"
+
+/* Signal information from board.c. Must match order from enum gpio_signal. */
+extern const struct gpio_info gpio_list[GPIO_COUNT];
+
+
+int gpio_pre_init(void)
+{
+ const struct gpio_info *g = gpio_list;
+ int i;
+
+ /* Enable all GPIOs clocks
+ * TODO: more fine-grained enabling for power saving
+ */
+ STM32L_RCC_AHBENR |= 0x3f;
+
+ /* Set all GPIOs to defaults */
+ for (i = 0; i < GPIO_COUNT; i++, g++) {
+ /* bitmask for registers with 2 bits per GPIO pin */
+ uint32_t mask2 = (g->mask * g->mask) | (g->mask * g->mask * 2);
+
+ if (g->flags & GPIO_OUTPUT) {
+ /* Set pin level */
+ gpio_set_level(i, g->flags & GPIO_HIGH);
+ /* General purpose output : MODE = 01 */
+ STM32L_GPIO_MODER_OFF(g->port) |= 0x55555555 & mask2;
+ } else {
+ /* Input */
+ STM32L_GPIO_MODER_OFF(g->port) &= ~mask2;
+ if (g->flags & GPIO_PULL) {
+ /* With pull up/down */
+ if (g->flags & GPIO_HIGH) /* Pull Up = 01 */
+ STM32L_GPIO_PUPDR_OFF(g->port) |=
+ 0x55555555 & mask2;
+ else /* Pull Down = 10 */
+ STM32L_GPIO_PUPDR_OFF(g->port) |=
+ 0xaaaaaaaa & mask2;
+ }
+ }
+ }
+
+ return EC_SUCCESS;
+}
+
+
+int gpio_get_level(enum gpio_signal signal)
+{
+ return !!(STM32L_GPIO_IDR_OFF(gpio_list[signal].port) &
+ gpio_list[signal].mask);
+}
+
+
+int gpio_set_level(enum gpio_signal signal, int value)
+{
+ STM32L_GPIO_BSRR_OFF(gpio_list[signal].port) =
+ gpio_list[signal].mask << (value ? 0 : 16);
+
+ return EC_SUCCESS;
+}
diff --git a/chip/stm32l/registers.h b/chip/stm32l/registers.h
index 6e9fc9e0c5..23bad85a44 100644
--- a/chip/stm32l/registers.h
+++ b/chip/stm32l/registers.h
@@ -125,6 +125,13 @@
#define STM32L_GPIOE_BASE 0x40021000
#define STM32L_GPIOH_BASE 0x40021400
+#define GPIO_A STM32L_GPIOA_BASE
+#define GPIO_B STM32L_GPIOB_BASE
+#define GPIO_C STM32L_GPIOC_BASE
+#define GPIO_D STM32L_GPIOD_BASE
+#define GPIO_E STM32L_GPIOE_BASE
+#define GPIO_H STM32L_GPIOH_BASE
+
#define STM32L_GPIO_REG32(l, offset) \
REG32(STM32L_CAT(STM32L_GPIO, l, _BASE) + (offset))
#define STM32L_GPIO_REG16(l, offset) \
@@ -141,6 +148,17 @@
#define STM32L_GPIO_AFRL(l) STM32L_GPIO_REG32(l, 0x20)
#define STM32L_GPIO_AFRH(l) STM32L_GPIO_REG32(l, 0x24)
+#define STM32L_GPIO_MODER_OFF(b) REG32((b) + 0x00)
+#define STM32L_GPIO_OTYPER_OFF(b) REG16((b) + 0x04)
+#define STM32L_GPIO_OSPEEDR_OFF(b) REG32((b) + 0x08)
+#define STM32L_GPIO_PUPDR_OFF(b) REG32((b) + 0x0C)
+#define STM32L_GPIO_IDR_OFF(b) REG16((b) + 0x10)
+#define STM32L_GPIO_ODR_OFF(b) REG16((b) + 0x14)
+#define STM32L_GPIO_BSRR_OFF(b) REG32((b) + 0x18)
+#define STM32L_GPIO_LCKR_OFF(b) REG32((b) + 0x1C)
+#define STM32L_GPIO_AFRL_OFF(b) REG32((b) + 0x20)
+#define STM32L_GPIO_AFRH_OFF(b) REG32((b) + 0x24)
+
/* --- I2C --- */
#define STM32L_I2C1_BASE 0x40005400
#define STM32L_I2C2_BASE 0x40005800
diff --git a/chip/stm32l/watchdog.c b/chip/stm32l/watchdog.c
index 114c3e9211..4a1cd7f6d2 100644
--- a/chip/stm32l/watchdog.c
+++ b/chip/stm32l/watchdog.c
@@ -60,14 +60,12 @@ void watchdog_task(void)
{
while (1) {
#ifdef BOARD_discovery
- /* TODO use GPIO API: gpio_set_level(GPIO_GREEN_LED, 1); */
- STM32L_GPIO_ODR(B) |= (1 << 7) ;
+ gpio_set_level(GPIO_GREEN_LED, 1);
#endif
usleep(500000);
watchdog_reload();
#ifdef BOARD_discovery
- /* TODO use GPIO API: gpio_set_level(GPIO_GREEN_LED, 0); */
- STM32L_GPIO_ODR(B) &= ~(1 << 7) ;
+ gpio_set_level(GPIO_GREEN_LED, 0);
#endif
usleep(500000);
watchdog_reload();