Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:02

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2020 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifndef BSP_IMX_GPIO_H
0029 #define BSP_IMX_GPIO_H
0030 
0031 #include <rtems.h>
0032 #include <stdint.h>
0033 
0034 #ifdef __cplusplus
0035 extern "C" {
0036 #endif /* __cplusplus */
0037 
0038 /** Hardware registers and locking mechanism for one hardware GPIO module. */
0039 struct imx_gpio;
0040 
0041 /** Mode of the pin. */
0042 enum imx_gpio_mode {
0043   IMX_GPIO_MODE_OUTPUT,
0044   IMX_GPIO_MODE_INPUT,
0045   IMX_GPIO_MODE_INTERRUPT_LOW,
0046   IMX_GPIO_MODE_INTERRUPT_HIGH,
0047   IMX_GPIO_MODE_INTERRUPT_RISING,
0048   IMX_GPIO_MODE_INTERRUPT_FALLING,
0049   IMX_GPIO_MODE_INTERRUPT_ANY_EDGE,
0050 };
0051 
0052 /**
0053  * A i.MX GPIO pin or set of pins.
0054  *
0055  * Use this structures to handle pins in the application. You can either get
0056  * them from an FDT entry (with @ref imx_gpio_init_from_fde_property) or fill
0057  * them by hand.
0058  */
0059 struct imx_gpio_pin {
0060   /** Management structure for the GPIO. Get with @ref imx_gpio_get_by_index. */
0061   volatile struct imx_gpio* gpio;
0062   /**
0063    * Select the pins you want to handle with this mask. The mask is not
0064    * influenced by the @a shift field.
0065    */
0066   uint32_t mask;
0067   /** If set to something != 0: Shift the pins that many bits. */
0068   unsigned int shift;
0069   /** Whether the pin is an input, output, interrupt, ... */
0070   enum imx_gpio_mode mode;
0071   /**
0072    * Whether the pin is active low. Only used to store the last field of the FDT
0073    * entries. Can be queried via the @ref imx_gpio_get_active_level.
0074    */
0075   bool is_active_low;
0076 };
0077 
0078 /**
0079  * Initialize a GPIO pin. Only necessary for manually filled imx_gpio
0080  * structures.
0081  */
0082 void imx_gpio_init (struct imx_gpio_pin *pin);
0083 
0084 /**
0085  * Initialize a GPIO pin from the fields in an FDT property.
0086  *
0087  * If you have for example the following property in an FDT node:
0088  *
0089  *     some-node {
0090  *         mixed-stuff = <0>, <&some_node 1>, <&gpio4 22 GPIO_ACTIVE_LOW>, <17>;
0091  *     };
0092  *
0093  * You can get the property using fdt_getprop(...) in your code, somehow find
0094  * the right start position (the phandle &gpio4) and then pass it to this
0095  * function.
0096  *
0097  * If you pass something != NULL to @a next_prop_pointer, you will get a pointer
0098  * to the next part in the attribute. In the example above, that will be a
0099  * pointer to the <17>.
0100  *
0101  * NOTE: The information from the third parameter in the FDT (GPIO_ACTIVE_LOW in
0102  * the example) is currently ignored.
0103  */
0104 rtems_status_code imx_gpio_init_from_fdt_property_pointer(
0105   struct imx_gpio_pin *pin,
0106   const uint32_t *prop_pointer,
0107   enum imx_gpio_mode mode,
0108   const uint32_t **next_prop_pointer);
0109 
0110 /**
0111  * Initialize a GPIO pin from a FDT property.
0112  *
0113  * If you have for example the following property in an FDT node:
0114  *
0115  *     some-node {
0116  *         gpios = <&gpio5 1 GPIO_ACTIVE_LOW>, <&gpio4 22 GPIO_ACTIVE_LOW>;
0117  *     };
0118  *
0119  * you can use the following to initialize the second GPIO:
0120  *
0121  *     imx_gpio_init_from_fdt_property(&pin, node, "gpios",
0122  *         IMX_GPIO_INTERRUPT_LOW, 1);
0123  *
0124  * NOTE: The information from the third parameter in the FDT (GPIO_ACTIVE_LOW in
0125  * the example) is only stored in the imx_gpio_pin structure. It can be queried
0126  * but will not be applied automatically!
0127  */
0128 rtems_status_code imx_gpio_init_from_fdt_property(
0129   struct imx_gpio_pin *pin,
0130   int node_offset,
0131   const char *property,
0132   enum imx_gpio_mode mode,
0133   size_t index);
0134 
0135 /**
0136  * Return the RTEMS interrupt vector belonging to the GPIO interrupt of a given
0137  * node. The node should look like follows:
0138  *
0139  *     some-node {
0140  *         interrupt-parent = <&gpio4>;
0141  *         interrupts = <15 IRQ_TYPE_EDGE_BOTH>, <22 IRQ_TYPE_EDGE_BOTH>;
0142  *     };
0143  *
0144  * To get the interrupt vector from the first GPIO in interrupts use
0145  *
0146  *     imx_gpio_get_irq_of_node(fdt, node, 0);
0147  *
0148  * @returns the interrupt vector if successful.
0149  * @returns BSP_INTERRUPT_VECTOR_INVALID on failure.
0150  */
0151 rtems_vector_number imx_gpio_get_irq_of_node(
0152   const void *fdt,
0153   int node,
0154   size_t index);
0155 
0156 /**
0157  * Return the gpio management structure based on the GPIO index. The index is
0158  * the one used in the FDT alias list. So index 0 is GPIO1 in the i.MX docs for
0159  * most FDTs based on the Linux one.
0160  */
0161 struct imx_gpio *imx_gpio_get_by_index(unsigned idx);
0162 
0163 /**
0164  * Return the gpio management structure based on the GPIO registers.
0165  */
0166 struct imx_gpio *imx_gpio_get_by_register(void *regs);
0167 
0168 /**
0169  * Get the name of the gpio.
0170  */
0171 const char *imx_gpio_get_name(struct imx_gpio *imx_gpio);
0172 
0173 /**
0174  * Set the value of the output pin. @a set will be shifted and masked (in that
0175  * order) based on the values of @a pin.
0176  */
0177 void imx_gpio_set_output(struct imx_gpio_pin *pin, uint32_t set);
0178 
0179 /**
0180  * Toggle the value of the output pin.
0181  */
0182 void imx_gpio_toggle_output(struct imx_gpio_pin *pin);
0183 
0184 /**
0185  * Get the value of the input pin. The input value will be masked and shifted
0186  * (in that order) based on the values of @a pin.
0187  */
0188 uint32_t imx_gpio_get_input(struct imx_gpio_pin *pin);
0189 
0190 /**
0191  * Disable the interrupt of the given @a pin.
0192  */
0193 void imx_gpio_int_disable(struct imx_gpio_pin *pin);
0194 
0195 /**
0196  * Enable the interrupt of the given @a pin.
0197  */
0198 void imx_gpio_int_enable(struct imx_gpio_pin *pin);
0199 
0200 /**
0201  * Read the interrupt status register for the given @a pin.
0202  */
0203 uint32_t imx_gpio_get_isr(struct imx_gpio_pin *pin);
0204 
0205 /**
0206  * Clear the interrupt status register for the given @a pin.
0207  */
0208 void imx_gpio_clear_isr(struct imx_gpio_pin *pin, uint32_t clr);
0209 
0210 /**
0211  * Get the active level of the pin. Returns either 0x0 or 0xFFFFFFFF so that you
0212  * can directly use it with the @ref imx_gpio_set_output function.
0213  */
0214 static inline uint32_t imx_gpio_get_active_level(struct imx_gpio_pin *pin)
0215 {
0216   return (pin->is_active_low) ? 0 : 0xFFFFFFFFU;
0217 }
0218 
0219 /**
0220  * Get the inactive level of the pin. Returns either 0x0 or 0xFFFFFFFF so that
0221  * you can directly use it with the @ref imx_gpio_set_output function.
0222  */
0223 static inline uint32_t imx_gpio_get_inactive_level(struct imx_gpio_pin *pin)
0224 {
0225   return ~imx_gpio_get_active_level(pin);
0226 }
0227 
0228 /**
0229  * Fast access macros for the GPIOs. Note that these assume a FDT based on the
0230  * Linux FDTs.
0231  */
0232 /** @{ */
0233 #define IMX_GPIO1 (imx_gpio_get_by_index(0))
0234 #define IMX_GPIO2 (imx_gpio_get_by_index(1))
0235 #define IMX_GPIO3 (imx_gpio_get_by_index(2))
0236 #define IMX_GPIO4 (imx_gpio_get_by_index(3))
0237 #define IMX_GPIO5 (imx_gpio_get_by_index(4))
0238 #define IMX_GPIO6 (imx_gpio_get_by_index(5))
0239 #define IMX_GPIO7 (imx_gpio_get_by_index(6))
0240 /** @} */
0241 
0242 #ifdef __cplusplus
0243 }
0244 #endif /* __cplusplus */
0245 
0246 #endif /* BSP_IMX_GPIO_H */