summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2012-02-02 23:44:30 +0000
committerVincent Palatin <vpalatin@chromium.org>2012-02-03 02:00:27 +0000
commit54f36995a4b626280b868f1efe6049591f3fc53c (patch)
treef97716aa89d2eb812de3efd8104930f75080663b /chip
parentb2b6eb46b32826386e8ab16ed623a6927df043da (diff)
downloadchrome-ec-54f36995a4b626280b868f1efe6049591f3fc53c.tar.gz
stm32l: basic GPIO support
No interrupt support yet. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BUG=None TEST=on Discovery EC console, using "gpioget" and "gpioset" commands check we can switch the LED and read the button state. Change-Id: I01294643d3df070a535dab5a6be02c296487fca5
Diffstat (limited to 'chip')
-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
4 files changed, 90 insertions, 5 deletions
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();