summaryrefslogtreecommitdiffstats
path: root/bsps/arm/imx
diff options
context:
space:
mode:
authorChristian Mauderer <christian.mauderer@embedded-brains.de>2020-11-03 11:21:41 +0100
committerChristian Mauderer <christian.mauderer@embedded-brains.de>2020-11-20 08:53:18 +0100
commit6cece5854499bfba8b00aa23588c78156fe1ff16 (patch)
treea7248b5a348cec975b7847f5755160b6ce9f5655 /bsps/arm/imx
parentimx: Move imx_iomux to arm/shared (diff)
downloadrtems-6cece5854499bfba8b00aa23588c78156fe1ff16.tar.bz2
bsps/imx: Move imx-gpio to arm/shared
Update #4180
Diffstat (limited to 'bsps/arm/imx')
-rw-r--r--bsps/arm/imx/gpio/imx-gpio.c359
-rw-r--r--bsps/arm/imx/headers.am5
-rw-r--r--bsps/arm/imx/include/bsp/imx-gpio.h196
3 files changed, 0 insertions, 560 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
-);
diff --git a/bsps/arm/imx/headers.am b/bsps/arm/imx/headers.am
index e7a2418dea..4db8035c38 100644
--- a/bsps/arm/imx/headers.am
+++ b/bsps/arm/imx/headers.am
@@ -17,9 +17,4 @@ include_arm_freescale_imx_HEADERS += ../../../../../../bsps/arm/imx/include/arm/
include_bspdir = $(includedir)/bsp
include_bsp_HEADERS =
-include_bsp_HEADERS += ../../../../../../bsps/arm/imx/include/bsp/imx-gpio.h
include_bsp_HEADERS += ../../../../../../bsps/arm/imx/include/bsp/irq.h
-
-include_dev_clockdir = $(includedir)/dev/clock
-include_dev_clock_HEADERS =
-include_dev_clock_HEADERS += ../../../../../../bsps/include/dev/clock/arm-generic-timer.h
diff --git a/bsps/arm/imx/include/bsp/imx-gpio.h b/bsps/arm/imx/include/bsp/imx-gpio.h
deleted file mode 100644
index dca2d0cfad..0000000000
--- a/bsps/arm/imx/include/bsp/imx-gpio.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/* SPDX-License-Identifier: BSD-2-Clause */
-
-/*
- * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
- *
- * 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.
- */
-
-#ifndef BSP_IMX_GPIO_H
-#define BSP_IMX_GPIO_H
-
-#include <rtems.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/** Hardware registers and locking mechanism for one hardware GPIO module. */
-struct imx_gpio;
-
-/** Mode of the pin. */
-enum imx_gpio_mode {
- IMX_GPIO_MODE_OUTPUT,
- IMX_GPIO_MODE_INPUT,
- IMX_GPIO_MODE_INTERRUPT_LOW,
- IMX_GPIO_MODE_INTERRUPT_HIGH,
- IMX_GPIO_MODE_INTERRUPT_RISING,
- IMX_GPIO_MODE_INTERRUPT_FALLING,
- IMX_GPIO_MODE_INTERRUPT_ANY_EDGE,
-};
-
-/**
- * A i.MX GPIO pin or set of pins.
- *
- * Use this structures to handle pins in the application. You can either get
- * them from an FDT entry (with @ref imx_gpio_init_from_fde_property) or fill
- * them by hand.
- */
-struct imx_gpio_pin {
- /** Management structure for the GPIO. Get with @ref imx_gpio_get_by_index. */
- volatile struct imx_gpio* gpio;
- /**
- * Select the pins you want to handle with this mask. The mask is not
- * influenced by the @a shift field.
- */
- uint32_t mask;
- /** If set to something != 0: Shift the pins that many bits. */
- unsigned int shift;
- /** Whether the pin is an input, output, interrupt, ... */
- enum imx_gpio_mode mode;
-};
-
-/**
- * Initialize a GPIO pin. Only necessary for manually filled imx_gpio
- * structures.
- */
-void imx_gpio_init (struct imx_gpio_pin *pin);
-
-/**
- * Initialize a GPIO pin from a FDT property.
- *
- * If you have for example the following property in an FDT node:
- *
- * some-node {
- * gpios = <&gpio5 1 GPIO_ACTIVE_LOW>, <&gpio4 22 GPIO_ACTIVE_LOW>;
- * };
- *
- * you can use the following to initialize the second GPIO:
- *
- * imx_gpio_init_from_fdt_property(&pin, node, "gpios",
- * IMX_GPIO_INTERRUPT_LOW, 1);
- *
- * NOTE: The information from the third parameter in the FDT (GPIO_ACTIVE_LOW in
- * the example) is currently ignored.
- */
-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);
-
-/**
- * Return the RTEMS interrupt vector belonging to the GPIO interrupt of a given
- * node. The node should look like follows:
- *
- * some-node {
- * interrupt-parent = <&gpio4>;
- * interrupts = <15 IRQ_TYPE_EDGE_BOTH>, <22 IRQ_TYPE_EDGE_BOTH>;
- * };
- *
- * To get the interrupt vector from the first GPIO in interrupts use
- *
- * imx_gpio_get_irq_of_node(fdt, node, 0);
- *
- * @returns the interrupt vector if successful.
- * @returns BSP_INTERRUPT_VECTOR_INVALID on failure.
- */
-rtems_vector_number imx_gpio_get_irq_of_node(
- const void *fdt,
- int node,
- size_t index);
-
-/**
- * Return the gpio management structure based on the GPIO index. The index is
- * the one used in the FDT alias list. So index 0 is GPIO1 in the i.MX docs for
- * most FDTs based on the Linux one.
- */
-struct imx_gpio *imx_gpio_get_by_index(unsigned idx);
-
-/**
- * Return the gpio management structure based on the GPIO registers.
- */
-struct imx_gpio *imx_gpio_get_by_register(void *regs);
-
-/**
- * Get the name of the gpio.
- */
-const char *imx_gpio_get_name(struct imx_gpio *imx_gpio);
-
-/**
- * Set the value of the output pin. @a set will be shifted and masked (in that
- * order) based on the values of @a pin.
- */
-void imx_gpio_set_output(struct imx_gpio_pin *pin, uint32_t set);
-
-/**
- * Toggle the value of the output pin.
- */
-void imx_gpio_toggle_output(struct imx_gpio_pin *pin);
-
-/**
- * Get the value of the input pin. The input value will be masked and shifted
- * (in that order) based on the values of @a pin.
- */
-uint32_t imx_gpio_get_input(struct imx_gpio_pin *pin);
-
-/**
- * Disable the interrupt of the given @a pin.
- */
-void imx_gpio_int_disable(struct imx_gpio_pin *pin);
-
-/**
- * Enable the interrupt of the given @a pin.
- */
-void imx_gpio_int_enable(struct imx_gpio_pin *pin);
-
-/**
- * Read the interrupt status register for the given @a pin.
- */
-uint32_t imx_gpio_get_isr(struct imx_gpio_pin *pin);
-
-/**
- * Clear the interrupt status register for the given @a pin.
- */
-void imx_gpio_clear_isr(struct imx_gpio_pin *pin, uint32_t clr);
-
-/**
- * Fast access macros for the GPIOs. Note that these assume a FDT based on the
- * Linux FDTs.
- */
-/** @{ */
-#define IMX_GPIO1 (imx_gpio_get_by_index(0))
-#define IMX_GPIO2 (imx_gpio_get_by_index(1))
-#define IMX_GPIO3 (imx_gpio_get_by_index(2))
-#define IMX_GPIO4 (imx_gpio_get_by_index(3))
-#define IMX_GPIO5 (imx_gpio_get_by_index(4))
-#define IMX_GPIO6 (imx_gpio_get_by_index(5))
-#define IMX_GPIO7 (imx_gpio_get_by_index(6))
-/** @} */
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* BSP_IMX_GPIO_H */