diff options
Diffstat (limited to 'bsps/arm/imx/gpio/imx-gpio.c')
-rw-r--r-- | bsps/arm/imx/gpio/imx-gpio.c | 359 |
1 files changed, 0 insertions, 359 deletions
diff --git a/bsps/arm/imx/gpio/imx-gpio.c b/bsps/arm/imx/gpio/imx-gpio.c deleted file mode 100644 index 552e1d5cc2..0000000000 --- a/bsps/arm/imx/gpio/imx-gpio.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (C) 2019-2020 embedded brains GmbH. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <assert.h> -#include <bsp/fatal.h> -#include <bsp/fdt.h> -#include <bsp/imx-gpio.h> -#include <libfdt.h> -#include <rtems.h> -#include <rtems/sysinit.h> - -#define IMX_GPIO_ALIAS_NAME "gpioX" - -/* - * i.MX6ULL has 5, i.MX7D has 7 - * - * Be careful when changing this. The attach() does a simple ASCII conversion. - */ -#define IMX_MAX_GPIO_MODULES 7 - -struct imx_gpio_regs { - uint32_t dr; - uint32_t gdir; - uint32_t psr; - uint32_t icr1; -#define IMX_GPIO_ICR_LOW_LEVEL 0 -#define IMX_GPIO_ICR_HIGH_LEVEL 1 -#define IMX_GPIO_ICR_RISING_EDGE 2 -#define IMX_GPIO_ICR_FALLING_EDGE 3 - uint32_t icr2; - uint32_t imr; - uint32_t isr; - uint32_t edge_sel; -}; - -struct imx_gpio { - char name[sizeof(IMX_GPIO_ALIAS_NAME)]; - struct imx_gpio_regs *regs; - rtems_interrupt_lock lock; -}; - -/* The GPIO modules. These will be initialized based on the FDT alias table. */ -struct imx_gpio imx_gpio[IMX_MAX_GPIO_MODULES]; - -const char *imx_gpio_get_name(struct imx_gpio *imx_gpio) -{ - return imx_gpio->name; -} - -static void imx_gpio_attach(void) -{ - size_t i; - const void *fdt; - - fdt = bsp_fdt_get(); - - memset(imx_gpio, 0, sizeof(imx_gpio)); - - for (i = 0; i < IMX_MAX_GPIO_MODULES; ++i) { - const char *path; - int node; - const uint32_t *val; - uint32_t gpio_regs = 0; - int len; - - memcpy(imx_gpio[i].name, IMX_GPIO_ALIAS_NAME, sizeof(IMX_GPIO_ALIAS_NAME)); - imx_gpio[i].name[sizeof(IMX_GPIO_ALIAS_NAME)-2] = (char)('0' + i); - - path = fdt_get_alias(fdt, imx_gpio[i].name); - if (path == NULL) { - continue; - } - - node = fdt_path_offset(fdt, path); - if (node < 0) { - bsp_fatal(IMX_FATAL_GPIO_UNEXPECTED_FDT); - } - - val = fdt_getprop(fdt, node, "reg", &len); - if (len > 0) { - gpio_regs = fdt32_to_cpu(val[0]); - } else { - bsp_fatal(IMX_FATAL_GPIO_UNEXPECTED_FDT); - } - - imx_gpio[i].regs = (struct imx_gpio_regs *)gpio_regs; - rtems_interrupt_lock_initialize(&imx_gpio[i].lock, imx_gpio[i].name); - } -} - -struct imx_gpio *imx_gpio_get_by_index(unsigned idx) -{ - if ((idx < IMX_MAX_GPIO_MODULES) && (imx_gpio[idx].regs != NULL)) { - return &imx_gpio[idx]; - } - return NULL; -} - -struct imx_gpio *imx_gpio_get_by_register(void *regs) -{ - size_t i; - - for (i = 0; i < IMX_MAX_GPIO_MODULES; ++i) { - if (imx_gpio[i].regs == regs) { - return &imx_gpio[i]; - } - } - return NULL; -} - -static void imx_gpio_direction_input(struct imx_gpio_pin *pin) -{ - rtems_interrupt_lock_context lock_context; - rtems_interrupt_lock_acquire(&pin->gpio->lock, &lock_context); - pin->gpio->regs->gdir &= ~pin->mask; - rtems_interrupt_lock_release(&pin->gpio->lock, &lock_context); -} - -static void imx_gpio_direction_output(struct imx_gpio_pin *pin) -{ - rtems_interrupt_lock_context lock_context; - rtems_interrupt_lock_acquire(&pin->gpio->lock, &lock_context); - pin->gpio->regs->gdir |= pin->mask; - rtems_interrupt_lock_release(&pin->gpio->lock, &lock_context); -} - -static void imx_gpio_set_interrupt_any_edge(struct imx_gpio_pin *pin) -{ - rtems_interrupt_lock_context lock_context; - rtems_interrupt_lock_acquire(&pin->gpio->lock, &lock_context); - pin->gpio->regs->edge_sel |= pin->mask; - rtems_interrupt_lock_release(&pin->gpio->lock, &lock_context); -} - -static void imx_gpio_set_interrupt_mode(struct imx_gpio_pin *pin, uint32_t mode) -{ - size_t i; - - for (i=0; i < 32; ++i) { - if ((pin->mask & (1u << i)) != 0) { - volatile uint32_t *icr; - size_t shift; - rtems_interrupt_lock_context lock_context; - - if (i < 16) { - icr = &pin->gpio->regs->icr1; - shift = 2 * i; - } else { - icr = &pin->gpio->regs->icr2; - shift = 2 * (i - 16); - } - - rtems_interrupt_lock_acquire(&pin->gpio->lock, &lock_context); - *icr = (*icr & ~(3u << shift)) | (mode << shift); - rtems_interrupt_lock_release(&pin->gpio->lock, &lock_context); - } - } -} - -rtems_status_code imx_gpio_init_from_fdt_property ( - struct imx_gpio_pin *pin, - int node_offset, - const char *property, - enum imx_gpio_mode mode, - size_t index -) -{ - int len; - const uint32_t *val; - rtems_status_code sc = RTEMS_SUCCESSFUL; - const void *fdt; - uint32_t gpio_regs; - const unsigned pin_length_dwords = 3; - const unsigned pin_length_bytes = (pin_length_dwords * sizeof(uint32_t)); - uint32_t gpio_phandle; - uint32_t pin_nr; - int cfgnode; - - memset(pin, 0, sizeof(*pin)); - - fdt = bsp_fdt_get(); - val = fdt_getprop(fdt, node_offset, property, &len); - if (val == NULL || (len % pin_length_bytes != 0) || - (index >= len / pin_length_bytes)) { - sc = RTEMS_UNSATISFIED; - } - if (sc == RTEMS_SUCCESSFUL) { - pin_nr = fdt32_to_cpu(val[1 + index * pin_length_dwords]); - gpio_phandle = fdt32_to_cpu(val[0 + index * pin_length_dwords]); - - cfgnode = fdt_node_offset_by_phandle(fdt, gpio_phandle); - val = fdt_getprop(fdt, cfgnode, "reg", &len); - if (len > 0) { - gpio_regs = fdt32_to_cpu(val[0]); - } else { - sc = RTEMS_UNSATISFIED; - } - } - if (sc == RTEMS_SUCCESSFUL) { - pin->gpio = imx_gpio_get_by_register((void *)gpio_regs); - pin->mask = 1u << pin_nr; - pin->shift = pin_nr; - pin->mode = mode; - } - if (sc == RTEMS_SUCCESSFUL) { - imx_gpio_init(pin); - } - - return sc; -} - -rtems_vector_number imx_gpio_get_irq_of_node( - const void *fdt, - int node, - size_t index -) -{ - const uint32_t *val; - uint32_t pin; - int parent; - size_t parent_index; - int len; - - val = fdt_getprop(fdt, node, "interrupts", &len); - if (val == NULL || len < (int) ((index + 1) * 8)) { - return UINT32_MAX; - } - pin = fdt32_to_cpu(val[index * 2]); - if (pin < 16) { - parent_index = 0; - } else { - parent_index = 1; - } - - val = fdt_getprop(fdt, node, "interrupt-parent", &len); - if (len != 4) { - return UINT32_MAX; - } - parent = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(val[0])); - - return imx_get_irq_of_node(fdt, parent, parent_index); -} - -void imx_gpio_init (struct imx_gpio_pin *pin) -{ - switch (pin->mode) { - case (IMX_GPIO_MODE_INTERRUPT_LOW): - imx_gpio_direction_input(pin); - imx_gpio_set_interrupt_mode(pin, IMX_GPIO_ICR_LOW_LEVEL); - break; - case (IMX_GPIO_MODE_INTERRUPT_HIGH): - imx_gpio_direction_input(pin); - imx_gpio_set_interrupt_mode(pin, IMX_GPIO_ICR_HIGH_LEVEL); - break; - case (IMX_GPIO_MODE_INTERRUPT_RISING): - imx_gpio_direction_input(pin); - imx_gpio_set_interrupt_mode(pin, IMX_GPIO_ICR_RISING_EDGE); - break; - case (IMX_GPIO_MODE_INTERRUPT_FALLING): - imx_gpio_direction_input(pin); - imx_gpio_set_interrupt_mode(pin, IMX_GPIO_ICR_FALLING_EDGE); - break; - case (IMX_GPIO_MODE_INTERRUPT_ANY_EDGE): - imx_gpio_direction_input(pin); - imx_gpio_set_interrupt_any_edge(pin); - /* Interrupt mode isn't really relevant here. Just set it to get - * a defined behaviour in case of a bug. */ - imx_gpio_set_interrupt_mode(pin, IMX_GPIO_ICR_FALLING_EDGE); - break; - case (IMX_GPIO_MODE_INPUT): - imx_gpio_direction_input(pin); - break; - case (IMX_GPIO_MODE_OUTPUT): - imx_gpio_direction_output(pin); - break; - default: - assert(false); - break; - } -} - -void imx_gpio_set_output(struct imx_gpio_pin *pin, uint32_t set) -{ - rtems_interrupt_lock_context lock_context; - set <<= pin->shift; - set &= pin->mask; - rtems_interrupt_lock_acquire(&pin->gpio->lock, &lock_context); - pin->gpio->regs->dr = (pin->gpio->regs->dr & ~pin->mask) | set; - rtems_interrupt_lock_release(&pin->gpio->lock, &lock_context); -} - -void imx_gpio_toggle_output(struct imx_gpio_pin *pin) -{ - rtems_interrupt_lock_context lock_context; - rtems_interrupt_lock_acquire(&pin->gpio->lock, &lock_context); - pin->gpio->regs->dr = (pin->gpio->regs->dr ^ pin->mask); - rtems_interrupt_lock_release(&pin->gpio->lock, &lock_context); -} - -uint32_t imx_gpio_get_input(struct imx_gpio_pin *pin) -{ - return (pin->gpio->regs->dr & pin->mask) >> pin->shift; -} - -void imx_gpio_int_disable(struct imx_gpio_pin *pin) -{ - rtems_interrupt_lock_context lock_context; - rtems_interrupt_lock_acquire(&pin->gpio->lock, &lock_context); - pin->gpio->regs->imr &= ~pin->mask; - rtems_interrupt_lock_release(&pin->gpio->lock, &lock_context); -} - -void imx_gpio_int_enable(struct imx_gpio_pin *pin) -{ - rtems_interrupt_lock_context lock_context; - rtems_interrupt_lock_acquire(&pin->gpio->lock, &lock_context); - pin->gpio->regs->imr |= pin->mask; - rtems_interrupt_lock_release(&pin->gpio->lock, &lock_context); -} - -uint32_t imx_gpio_get_isr(struct imx_gpio_pin *pin) -{ - return (pin->gpio->regs->isr & pin->mask) >> pin->shift; -} - -void imx_gpio_clear_isr(struct imx_gpio_pin *pin, uint32_t clr) -{ - pin->gpio->regs->isr = (clr << pin->shift) & pin->mask; -} - -RTEMS_SYSINIT_ITEM( - imx_gpio_attach, - RTEMS_SYSINIT_DEVICE_DRIVERS, - RTEMS_SYSINIT_ORDER_FIRST -); |