diff options
Diffstat (limited to 'chip/nrf51/gpio.c')
-rw-r--r-- | chip/nrf51/gpio.c | 311 |
1 files changed, 0 insertions, 311 deletions
diff --git a/chip/nrf51/gpio.c b/chip/nrf51/gpio.c deleted file mode 100644 index 53694b5a74..0000000000 --- a/chip/nrf51/gpio.c +++ /dev/null @@ -1,311 +0,0 @@ -/* Copyright 2014 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. - */ - -#include "common.h" -#include "gpio.h" -#include "hooks.h" -#include "registers.h" -#include "task.h" -#include "util.h" - -/* - * For each interrupt (INT0-INT3, PORT), record which GPIO entry uses it. - */ - -static const struct gpio_info *gpio_ints[NRF51_GPIOTE_IN_COUNT]; -static const struct gpio_info *gpio_int_port; - -volatile uint32_t * const nrf51_alt_funcs[] = { - /* UART */ - &NRF51_UART_PSELRTS, - &NRF51_UART_PSELTXD, - &NRF51_UART_PSELCTS, - &NRF51_UART_PSELRXD, - /* SPI1 (SPI Master) */ - &NRF51_SPI0_PSELSCK, - &NRF51_SPI0_PSELMOSI, - &NRF51_SPI0_PSELMISO, - /* TWI0 (I2C) */ - &NRF51_TWI0_PSELSCL, - &NRF51_TWI0_PSELSDA, - /* SPI1 (SPI Master) */ - &NRF51_SPI1_PSELSCK, - &NRF51_SPI1_PSELMOSI, - &NRF51_SPI1_PSELMISO, - /* TWI1 (I2C) */ - &NRF51_TWI1_PSELSCL, - &NRF51_TWI1_PSELSDA, - /* SPIS1 (SPI SLAVE) */ - &NRF51_SPIS1_PSELSCK, - &NRF51_SPIS1_PSELMISO, - &NRF51_SPIS1_PSELMOSI, - &NRF51_SPIS1_PSELCSN, - /* QDEC (ROTARY DECODER) */ - &NRF51_QDEC_PSELLED, - &NRF51_QDEC_PSELA, - &NRF51_QDEC_PSELB, - /* LPCOMP (Low Power Comparator) */ - &NRF51_LPCOMP_PSEL, -}; - -const unsigned int nrf51_alt_func_count = ARRAY_SIZE(nrf51_alt_funcs); - -/* Make sure the function table and defines stay in sync */ -BUILD_ASSERT(ARRAY_SIZE(nrf51_alt_funcs) == NRF51_MAX_ALT_FUNCS && - NRF51_MAX_ALT_FUNCS <= GPIO_ALT_FUNC_MAX); - -void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) -{ - uint32_t val = 0; - uint32_t bit = GPIO_MASK_TO_NUM(mask); - - if (flags & GPIO_OUTPUT) - val |= NRF51_PIN_CNF_DIR_OUTPUT; - else if (flags & GPIO_INPUT) - val |= NRF51_PIN_CNF_DIR_INPUT; - - if (flags & GPIO_PULL_DOWN) - val |= NRF51_PIN_CNF_PULLDOWN; - else if (flags & GPIO_PULL_UP) - val |= NRF51_PIN_CNF_PULLUP; - - /* TODO: Drive strength? H0D1? */ - if (flags & GPIO_OPEN_DRAIN) - val |= NRF51_PIN_CNF_DRIVE_S0D1; - - if (flags & GPIO_OUTPUT) { - if (flags & GPIO_HIGH) - NRF51_GPIO0_OUTSET = mask; - else if (flags & GPIO_LOW) - NRF51_GPIO0_OUTCLR = mask; - } - - /* Interrupt levels */ - if (flags & GPIO_INT_SHARED) { - /* - * There are no shared edge-triggered interrupts; - * they're either high or low. - */ - ASSERT((flags & (GPIO_INT_F_RISING | GPIO_INT_F_FALLING)) == 0); - ASSERT((flags & GPIO_INT_LEVEL) != GPIO_INT_LEVEL); - if (flags & GPIO_INT_F_LOW) - val |= NRF51_PIN_CNF_SENSE_LOW; - else if (flags & GPIO_INT_F_HIGH) - val |= NRF51_PIN_CNF_SENSE_HIGH; - } - - NRF51_PIN_CNF(bit) = val; -} - - -static void gpio_init(void) -{ - task_enable_irq(NRF51_PERID_GPIOTE); -} -DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); - - -test_mockable int gpio_get_level(enum gpio_signal signal) -{ - return !!(NRF51_GPIO0_IN & gpio_list[signal].mask); -} - -void gpio_set_level(enum gpio_signal signal, int value) -{ - if (value) - NRF51_GPIO0_OUTSET = gpio_list[signal].mask; - else - NRF51_GPIO0_OUTCLR = gpio_list[signal].mask; -} - - -void gpio_pre_init(void) -{ - const struct gpio_info *g = gpio_list; - int is_warm = 0; - int i; - - if (NRF51_POWER_RESETREAS & - (NRF51_POWER_RESETREAS_OFF | /* GPIO Wake */ - NRF51_POWER_RESETREAS_LPCOMP)) { - /* This is a warm reboot */ - is_warm = 1; - } - - /* Initialize Interrupt configuration */ - for (i = 0; i < NRF51_GPIOTE_IN_COUNT; i++) - gpio_ints[i] = NULL; - gpio_int_port = NULL; - - /* Set all GPIOs to defaults */ - for (i = 0; i < GPIO_COUNT; i++, g++) { - int flags = g->flags; - - if (flags & GPIO_DEFAULT) - continue; - - /* - * If this is a warm reboot, don't set the output levels again. - */ - if (is_warm) - flags &= ~(GPIO_LOW | GPIO_HIGH); - - /* Set up GPIO based on flags */ - gpio_set_flags_by_mask(g->port, g->mask, flags); - } -} - -/* - * NRF51 doesn't have an alternate function table. - * Use the pin select registers in place of the function number. - */ -void gpio_set_alternate_function(uint32_t port, uint32_t mask, - enum gpio_alternate_func func) -{ - uint32_t bit = GPIO_MASK_TO_NUM(mask); - - ASSERT((~mask & BIT(bit)) == 0); /* Only one bit set. */ - ASSERT(port == GPIO_0); - ASSERT((func >= GPIO_ALT_FUNC_DEFAULT && func < nrf51_alt_func_count) || - func == GPIO_ALT_FUNC_NONE); - - /* Remove the previous setting(s) */ - if (func == GPIO_ALT_FUNC_NONE) { - int i; - for (i = 0; i < nrf51_alt_func_count; i++) { - if (*(nrf51_alt_funcs[i]) == bit) - *(nrf51_alt_funcs[i]) = 0xffffffff; - } - } else { - *(nrf51_alt_funcs[func]) = bit; - } -} - - -/* - * Enable the interrupt associated with the "signal" - * The architecture has one general (PORT) - * and NRF51_GPIOTE_IN_COUNT single-pin (IN0, IN1, ...) interrupts. - * - */ -int gpio_enable_interrupt(enum gpio_signal signal) -{ - int pin; - const struct gpio_info *g = gpio_list + signal; - - /* Fail if not implemented or no interrupt handler */ - if (!g->mask || signal >= GPIO_IH_COUNT) - return EC_ERROR_INVAL; - - /* If it's not shared, use INT0-INT3, otherwise use PORT. */ - if (!(g->flags & GPIO_INT_SHARED)) { - int int_num, free_slot = -1; - uint32_t event_config = 0; - - for (int_num = 0; int_num < NRF51_GPIOTE_IN_COUNT; int_num++) { - if (gpio_ints[int_num] == g) - return EC_SUCCESS; /* This is already set up. */ - - if (gpio_ints[int_num] == NULL && free_slot == -1) - free_slot = int_num; - } - - ASSERT(free_slot != -1); - - gpio_ints[free_slot] = g; - pin = GPIO_MASK_TO_NUM(g->mask); - event_config = (pin << NRF51_GPIOTE_PSEL_POS) | - NRF51_GPIOTE_MODE_EVENT; - - ASSERT(g->flags & (GPIO_INT_F_RISING | GPIO_INT_F_FALLING)); - - /* RISING | FALLING = TOGGLE */ - if (g->flags & GPIO_INT_F_RISING) - event_config |= NRF51_GPIOTE_POLARITY_LOTOHI; - if (g->flags & GPIO_INT_F_FALLING) - event_config |= NRF51_GPIOTE_POLARITY_HITOLO; - - NRF51_GPIOTE_CONFIG(free_slot) = event_config; - - /* Enable the IN[] interrupt. */ - NRF51_GPIOTE_INTENSET = 1 << free_slot; - - } else { - /* The first handler for the shared interrupt wins. */ - if (gpio_int_port == NULL) { - gpio_int_port = g; - - /* Enable the PORT interrupt. */ - NRF51_GPIOTE_INTENSET = 1 << NRF51_GPIOTE_PORT_BIT; - } - } - - return EC_SUCCESS; -} - -/* - * Disable the interrupt associated with the "signal" - * The architecture has one general (PORT) - * and NRF51_GPIOTE_IN_COUNT single-pin (IN0, IN1, ...) interrupts. - */ -int gpio_disable_interrupt(enum gpio_signal signal) -{ - const struct gpio_info *g = gpio_list + signal; - int i; - - /* Fail if not implemented or no interrupt handler */ - if (!g->mask || signal >= GPIO_IH_COUNT) - return EC_ERROR_INVAL; - - /* If it's not shared, use INT0-INT3, otherwise use PORT. */ - if (!(g->flags & GPIO_INT_SHARED)) { - for (i = 0; i < NRF51_GPIOTE_IN_COUNT; i++) { - /* Remove matching handler. */ - if (gpio_ints[i] == g) { - /* Disable the interrupt */ - NRF51_GPIOTE_INTENCLR = - 1 << NRF51_GPIOTE_IN_BIT(i); - /* Zero the handler */ - gpio_ints[i] = NULL; - } - } - } else { - /* Disable the interrupt */ - NRF51_GPIOTE_INTENCLR = 1 << NRF51_GPIOTE_PORT_BIT; - /* Zero the shared handler */ - gpio_int_port = NULL; - } - - return EC_SUCCESS; -} - -/* - * Clear interrupt and run handler. - */ -void gpio_interrupt(void) -{ - const struct gpio_info *g; - int i; - int signal; - - for (i = 0; i < NRF51_GPIOTE_IN_COUNT; i++) { - if (NRF51_GPIOTE_IN(i)) { - NRF51_GPIOTE_IN(i) = 0; - g = gpio_ints[i]; - signal = g - gpio_list; - if (g && signal < GPIO_IH_COUNT) - gpio_irq_handlers[signal](signal); - } - } - - if (NRF51_GPIOTE_PORT) { - NRF51_GPIOTE_PORT = 0; - g = gpio_int_port; - signal = g - gpio_list; - if (g && signal < GPIO_IH_COUNT) - gpio_irq_handlers[signal](signal); - } -} -DECLARE_IRQ(NRF51_PERID_GPIOTE, gpio_interrupt, 1); |