diff options
-rw-r--r-- | board/discovery/board.c | 20 | ||||
-rw-r--r-- | board/discovery/board.h | 8 | ||||
-rw-r--r-- | chip/stm32l/build.mk | 2 | ||||
-rw-r--r-- | chip/stm32l/gpio.c | 69 | ||||
-rw-r--r-- | chip/stm32l/registers.h | 18 | ||||
-rw-r--r-- | chip/stm32l/watchdog.c | 6 |
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(); |