summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hendricks <dhendrix@chromium.org>2012-08-17 11:49:33 -0700
committerGerrit <chrome-bot@google.com>2012-08-17 16:55:26 -0700
commitc1c3ec56f89bd2bb132e1e360b0aaf43aa77e0d8 (patch)
tree2afd880955d786fb60e24f2ef187c82d9ab5be6b
parent91a6726b56d119445808a86997137d2a62fed898 (diff)
downloadchrome-ec-c1c3ec56f89bd2bb132e1e360b0aaf43aa77e0d8.tar.gz
stm32f: split GPIO config logic into its own function
This splits out the GPIO config logic from gpio_pre_init() into its own function so that it may be used by code elsewhere. TODO: Improve alternate function setting, and clean up Snow's board.c Signed-off-by: David Hendricks <dhendrix@chromium.org> BRANCH=snow BUG=none TEST=flashed onto Snow, everything came up as expected Change-Id: I47888c89d4d2bedd0c37b95406a64f024f1ec354 Reviewed-on: https://gerrit.chromium.org/gerrit/30762 Reviewed-by: Simon Glass <sjg@chromium.org> Commit-Ready: David Hendricks <dhendrix@chromium.org> Tested-by: David Hendricks <dhendrix@chromium.org>
-rw-r--r--chip/stm32/gpio-stm32f100.c124
1 files changed, 69 insertions, 55 deletions
diff --git a/chip/stm32/gpio-stm32f100.c b/chip/stm32/gpio-stm32f100.c
index 50c732bc27..dd729eab82 100644
--- a/chip/stm32/gpio-stm32f100.c
+++ b/chip/stm32/gpio-stm32f100.c
@@ -17,6 +17,12 @@
#define CPUTS(outstr) cputs(CC_GPIO, outstr)
#define CPRINTF(format, args...) cprintf(CC_GPIO, format, ## args)
+/*
+ * Special precautions must be taken in order to avoid accidentally rebooting
+ * the AP if we are warm rebooting the EC such as during sysjump.
+ */
+static int is_warm_boot;
+
/* For each EXTI bit, record which GPIO entry is using it */
static const struct gpio_info *exti_events[16];
@@ -46,16 +52,74 @@ static void gpio_config_info(const struct gpio_info *g, uint32_t *addr,
*cnf = *mode << 2;
}
+int gpio_set_flags(enum gpio_signal signal, int flags)
+{
+ const struct gpio_info *g = gpio_list + signal;
+ uint32_t addr, cnf, mode, mask;
+
+ gpio_config_info(g, &addr, &mode, &cnf);
+ mask = REG32(addr) & ~(cnf | mode);
+
+ /*
+ * For STM32, the port configuration field changes meaning
+ * depending on whether the port is an input, analog input,
+ * output, or alternate function.
+ */
+ if (flags & GPIO_OUTPUT) {
+ /* FIXME: This assumes output max speed of 10MHz */
+ mask |= 0x11111111 & mode;
+ if (flags & GPIO_OPEN_DRAIN)
+ mask |= 0x44444444 & cnf;
+ } else {
+ /* GPIOx_ODR determines which resistor to activate in
+ * input mode, see Table 16 (datasheet rm0041) */
+ if (flags & GPIO_PULL_UP) {
+ mask |= 0x88888888 & cnf;
+ STM32_GPIO_BSRR_OFF(g->port) |= g->mask;
+ gpio_set_level(signal, 1);
+ } else if (flags & GPIO_PULL_DOWN) {
+ mask |= 0x88888888 & cnf;
+ gpio_set_level(signal, 0);
+ } else {
+ mask |= 0x44444444 & cnf;
+ }
+ }
+
+ /*
+ * Set pin level after port has been set up as to avoid
+ * potential damage, e.g. driving an open-drain output
+ * high before it has been configured as such.
+ */
+ if ((flags & GPIO_OUTPUT) && !is_warm_boot)
+ /* General purpose, MODE = 01
+ *
+ * If this is a cold boot, set the level.
+ * On a warm reboot, leave things where they were
+ * or we'll shut off the AP. */
+ gpio_set_level(signal, flags & GPIO_HIGH);
+
+ REG32(addr) = mask;
+
+ /* Set up interrupts if necessary */
+ ASSERT(!(flags & GPIO_INT_LEVEL));
+ if (flags & (GPIO_INT_RISING | GPIO_INT_BOTH))
+ STM32_EXTI_RTSR |= g->mask;
+ if (flags & (GPIO_INT_FALLING | GPIO_INT_BOTH))
+ STM32_EXTI_FTSR |= g->mask;
+ /* Interrupt is enabled by gpio_enable_interrupt() */
+
+ return EC_SUCCESS;
+}
+
+
int gpio_pre_init(void)
{
const struct gpio_info *g = gpio_list;
- int is_warm = 0;
int i;
- uint32_t addr, cnf, mode, mask;
if (STM32_RCC_APB1ENR & 1) {
/* This is a warm reboot : TIM2 is already active */
- is_warm = 1;
+ is_warm_boot = 1;
} else {
/* Enable all GPIOs clocks
* TODO: more fine-grained enabling for power saving
@@ -64,58 +128,8 @@ int gpio_pre_init(void)
}
/* Set all GPIOs to defaults */
- for (i = 0; i < GPIO_COUNT; i++, g++) {
- gpio_config_info(g, &addr, &mode, &cnf);
- mask = REG32(addr) & ~(cnf | mode);
-
- /*
- * For STM32, the port configuration field changes meaning
- * depending on whether the port is an input, analog input,
- * output, or alternate function.
- */
- if (g->flags & GPIO_OUTPUT) {
- /* FIXME: This assumes output max speed of 10MHz */
- mask |= 0x11111111 & mode;
- if (g->flags & GPIO_OPEN_DRAIN)
- mask |= 0x44444444 & cnf;
- } else {
- /* GPIOx_ODR determines which resistor to activate in
- * input mode, see Table 16 (datasheet rm0041) */
- if (g->flags & GPIO_PULL_UP) {
- mask |= 0x88888888 & cnf;
- STM32_GPIO_BSRR_OFF(g->port) |= g->mask;
- gpio_set_level(i, 1);
- } else if (g->flags & GPIO_PULL_DOWN) {
- mask |= 0x88888888 & cnf;
- gpio_set_level(i, 0);
- } else {
- mask |= 0x44444444 & cnf;
- }
- }
-
- /*
- * Set pin level after port has been set up as to avoid
- * potential damage, e.g. driving an open-drain output
- * high before it has been configured as such.
- */
- if ((g->flags & GPIO_OUTPUT) && !is_warm)
- /* General purpose, MODE = 01
- *
- * If this is a cold boot, set the level.
- * On a warm reboot, leave things where they were
- * or we'll shut off the AP. */
- gpio_set_level(i, g->flags & GPIO_HIGH);
-
- REG32(addr) = mask;
-
- /* Set up interrupts if necessary */
- ASSERT(!(g->flags & GPIO_INT_LEVEL));
- if (g->flags & (GPIO_INT_RISING | GPIO_INT_BOTH))
- STM32_EXTI_RTSR |= g->mask;
- if (g->flags & (GPIO_INT_FALLING | GPIO_INT_BOTH))
- STM32_EXTI_FTSR |= g->mask;
- /* Interrupt is enabled by gpio_enable_interrupt() */
- }
+ for (i = 0; i < GPIO_COUNT; i++, g++)
+ gpio_set_flags(i, g->flags);
return EC_SUCCESS;
}