--- bsps/include/dev/gpio/xilinx-axi-gpio.h | 311 ++++++++++++++++++ bsps/shared/dev/gpio/xilinx-axi-gpio.c | 221 +++++++++++++ .../bsps/microblaze/microblaze_fpga/obj.yml | 2 + 3 files changed, 534 insertions(+) create mode 100644 bsps/include/dev/gpio/xilinx-axi-gpio.h create mode 100644 bsps/shared/dev/gpio/xilinx-axi-gpio.c
diff --git a/bsps/include/dev/gpio/xilinx-axi-gpio.h b/bsps/include/dev/gpio/xilinx-axi-gpio.h new file mode 100644 index 0000000000..dbd8748f34 --- /dev/null +++ b/bsps/include/dev/gpio/xilinx-axi-gpio.h @@ -0,0 +1,311 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSBSPsShared + * + * @brief Xilinx AXI GPIO definitions + */ + +/* + * Copyright (C) 2022 On-Line Applications Research Corporation (OAR) + * + * 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 XILINX_AXI_GPIO_H +#define XILINX_AXI_GPIO_H + +#include <bspopts.h> +#include <bsp/utility.h> +#include <rtems.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct { + /* Channel 1 data values */ + + /* + * Used to read general purpose input ports and write to general purpose + * output ports from channel 1. + */ + uint32_t gpio_data; + + /* + * The 3-state control register for channel 1 is used for the dynamic + * configuration of ports as input or output. When a bit is set to 1, the + * corresponding I/O port is an input port. When a bit is set to 0, it is an + * output port. + */ + uint32_t gpio_tri; + + /* Channel 2 data values */ + + /* + * Used to read general purpose input ports and write to general purpose + * output ports from channel 2. + */ + uint32_t gpio2_data; + + /* + * The 3-state control register for channel 2 is used for the dynamic + * configuration of ports as input or output. When a bit is set to 1, the + * corresponding I/O port is an input port. When a bit is set to 0, it is an + * output port. + */ + uint32_t gpio2_tri; + + char _unused[272]; + + /* Only the 31st bit is used to enable interrupts globally */ + #define GLOBAL_INTERRUPT_REGISTER_ENABLE BSP_BIT32(31) + + /* + * Global Interrupt Enable Register + * + * Determines whether interrupts are enabled or disabled. + * + * 0 - Disabled + * 1 - Enabled + */ + uint32_t gier; + + char _unused2[12]; + + /* Used with ip_isr and ip_ier member variables */ + #define CHANNEL_1_INTERRUPT_REGISTER BSP_BIT32(0) + #define CHANNEL_2_INTERRUPT_REGISTER BSP_BIT32(1) + + /* + * IP Status Registers + * + * Contains the status bit for each channel. + * + * 0 - Disabled + * 1 - Enabled + */ + uint32_t ip_isr; + + char _unused3[4]; + + /* + * IP Interrupt Enable Register + * + * Provides the ability to independtly control whether interrupts for each + * channel are enabled or disabled. + * + * 0 - No Channel input interrupt + * 1 - Channel input interrupt + */ + uint32_t ip_ier; +} xilinx_axi_gpio; + +typedef struct { + volatile xilinx_axi_gpio *regs; + bool is_dual; + uint32_t irq; + bool has_interrupts; +} xilinx_axi_gpio_context; + +/** + * @brief Set pin configuration for the specified GPIO channel. + * + * Changes the pin configuration for a channel. Bits set to 0 are output, and + * bits set to 1 are input. + * + * @param[in] ctx the GPIO context + * @param[in] channel the GPIO channel + * @param[in] mask the mask to be applied to @ channel + * + * @retval None + */ +void axi_gpio_set_data_direction( + xilinx_axi_gpio_context *ctx, + uint32_t channel, + uint32_t mask +); + +/** + * @brief Get pin configuration for specified GPIO channel. + * + * Gets the current pin configuration for a specified GPIO channel. Bits set to + * 0 are output, and bits set to 1 are input. + * + * @param[in] ctx the GPIO context + * @param[in] channel the GPIO channel + * + * @retval bitmask specifiying which pins on a channel are input or output + */ +uint32_t axi_gpio_get_data_direction( + xilinx_axi_gpio_context *ctx, + uint32_t channel +); + +/** + * @brief Reads data for specified GPIO channel. + * + * @param[in] channel the GPIO channel + * + * @retval Current values in discretes register. + */ +uint32_t axi_gpio_discrete_read( + xilinx_axi_gpio_context *ctx, + uint32_t channel +); + +/** + * @brief Writes to data register for specified GPIO channel. + * + * @param[in] ctx the GPIO context + * @param[in] channel the GPIO channel + * @param[in] mask the mask to be applied to @ channel + * + * @retval None + */ +void axi_gpio_discrete_write( + xilinx_axi_gpio_context *ctx, + uint32_t channel, + uint32_t mask +); + +/** + * @brief Set bits to 1 on specified GPIO channel. + * + * @param[in] ctx the GPIO context + * @param[in] channel the GPIO channel + * @param[in] mask the mask to be applied to @ channel + * + * @retval None + */ +void axi_gpio_discrete_set( + xilinx_axi_gpio_context *ctx, + uint32_t channel, + uint32_t mask +); + +/** + * @brief Set bits to 0 on specified GPIO channel. + * + * @param[in] ctx the GPIO context + * @param[in] channel the GPIO channel + * @param[in] mask the mask to be applied to @ channel + * + * @retval None + */ +void axi_gpio_discrete_clear( + xilinx_axi_gpio_context *ctx, + uint32_t channel, + uint32_t mask +); + +/** + * @brief Returns the vector number of the interrupt handler. + * + * @param[in] ctx the GPIO context + * + * @retval the vector number + */ +rtems_vector_number axi_gpio_get_irq( xilinx_axi_gpio_context *ctx ); + +/** + * @brief Turns on interrupts globally. + * + * @param[in] ctx the GPIO context + * + * @retval None + */ +void axi_gpio_interrupt_global_enable( xilinx_axi_gpio_context *ctx ); + +/** + * @brief Turns off interrupts globally. + * + * @param[in] ctx the GPIO context + * + * @retval None + */ +void axi_gpio_interrupt_global_disable( xilinx_axi_gpio_context *ctx ); + +/** + * @brief Enables interrupts on specified channel + * + * @param[in] ctx the GPIO context + * @param[in] channel the channel to enable interrupts on + * + * @retval None + */ +void axi_gpio_interrupt_enable( + xilinx_axi_gpio_context *ctx, + uint32_t channel +); + +/** + * @brief Disables interrupts on specified channel + * + * @param[in] ctx the GPIO context + * @param[in] channel the channel to turn interrupts on for + * + * @retval None + */ +void axi_gpio_interrupt_disable( + xilinx_axi_gpio_context *ctx, + uint32_t channel +); + +/** + * @brief Clear status of interrupt signals on a specific channel + * + * @param[in] ctx the GPIO context + * @param[in] channel the channel to clear the interrupt pending status from + * + * @retval None + */ +void axi_gpio_interrupt_clear( + xilinx_axi_gpio_context *ctx, + uint32_t channel +); + +/** + * @brief Return a bitmask of the interrupts that are enabled + * + * @param[in] ctx the GPIO context + * + * @retval the bitmask of enabled interrupts + */ +uint32_t axi_gpio_interrupt_get_enabled( xilinx_axi_gpio_context *ctx ); + +/** + * @brief Return a bitmask of the status of the interrupt signals + * + * @param[in] ctx the GPIO context + * + * @retval bitmask containing statuses of interrupt signals + */ +uint32_t axi_gpio_interrupt_get_status( xilinx_axi_gpio_context *ctx ); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XILINX_AXI_GPIO_H */ diff --git a/bsps/shared/dev/gpio/xilinx-axi-gpio.c b/bsps/shared/dev/gpio/xilinx-axi-gpio.c new file mode 100644 index 0000000000..53146a7bf0 --- /dev/null +++ b/bsps/shared/dev/gpio/xilinx-axi-gpio.c @@ -0,0 +1,221 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSBSPsShared + * + * @brief Xilinx AXI GPIO implementation + */ + +/* + * Copyright (C) 2022 On-Line Applications Research Corporation (OAR) + * + * 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 <dev/gpio/xilinx-axi-gpio.h> + +void axi_gpio_set_data_direction( + xilinx_axi_gpio_context *ctx, + uint32_t channel, + uint32_t mask +) +{ + assert( channel == 1 || (ctx->is_dual && channel == 2) ); + + if ( channel == 1 ) { + ctx->regs->gpio_tri = mask; + } else if ( ctx->is_dual && channel == 2 ) { + ctx->regs->gpio2_tri = mask; + } +} + +uint32_t axi_gpio_get_data_direction( + xilinx_axi_gpio_context *ctx, + uint32_t channel +) +{ + assert( channel == 1 || (ctx->is_dual && channel == 2) ); + + if ( channel == 1 ) { + return ctx->regs->gpio_tri; + } else if ( ctx->is_dual && channel == 2 ) { + return ctx->regs->gpio2_tri; + } + + return 0; +} + +uint32_t axi_gpio_discrete_read( + xilinx_axi_gpio_context *ctx, + uint32_t channel +) +{ + assert( channel == 1 || (ctx->is_dual && channel == 2) ); + + if ( channel == 1 ) { + return ctx->regs->gpio_data; + } else if ( ctx->is_dual && channel == 2 ) { + return ctx->regs->gpio2_tri; + } + + return 0; +} + +void axi_gpio_discrete_write( + xilinx_axi_gpio_context *ctx, + uint32_t channel, + uint32_t mask +) +{ + assert( channel == 1 || (ctx->is_dual && channel == 2) ); + + if ( channel == 1 ) { + ctx->regs->gpio_data = mask; + } else if ( ctx->is_dual && channel == 2 ) { + ctx->regs->gpio2_tri = mask; + } +} + +void axi_gpio_discrete_set( + xilinx_axi_gpio_context *ctx, + uint32_t channel, + uint32_t mask +) +{ + assert( channel == 1 || (ctx->is_dual && channel == 2) ); + + if ( channel == 1 ) { + ctx->regs->gpio_data |= mask; + } else if ( ctx->is_dual && channel == 2 ) { + ctx->regs->gpio2_tri |= mask; + } +} + +void axi_gpio_discrete_clear( + xilinx_axi_gpio_context *ctx, + uint32_t channel, + uint32_t mask +) +{ + assert( channel == 1 || (ctx->is_dual && channel == 2) ); + + if ( channel == 1 ) { + ctx->regs->gpio_data &= ~mask; + } else if ( ctx->is_dual && channel == 2 ) { + ctx->regs->gpio2_tri &= ~mask; + } +} + +rtems_vector_number axi_gpio_get_irq( xilinx_axi_gpio_context *ctx ) +{ + return ctx->irq; +} + +void axi_gpio_interrupt_global_enable( xilinx_axi_gpio_context *ctx ) +{ + assert( ctx->has_interrupts ); + + if ( ctx->has_interrupts ) { + ctx->regs->gier = GLOBAL_INTERRUPT_REGISTER_ENABLE; + } +} + +void axi_gpio_interrupt_global_disable( xilinx_axi_gpio_context *ctx ) +{ + assert( ctx->has_interrupts ); + + if ( ctx->has_interrupts ) { + ctx->regs->gier = 0x0; + } +} + +void axi_gpio_interrupt_enable( + xilinx_axi_gpio_context *ctx, + uint32_t channel +) +{ + assert( ctx->has_interrupts ); + assert( channel == 1 || (ctx->is_dual && channel == 2) ); + + if ( ctx->has_interrupts ) { + if ( channel == 1 ) { + ctx->regs->ip_ier |= CHANNEL_1_INTERRUPT_REGISTER; + } else if ( ctx->is_dual && channel == 2 ) { + ctx->regs->ip_ier |= CHANNEL_2_INTERRUPT_REGISTER; + } + } +} + +void axi_gpio_interrupt_disable( + xilinx_axi_gpio_context *ctx, + uint32_t channel +) +{ + assert( channel == 1 || (ctx->is_dual && channel == 2) ); + + if ( channel == 1 ) { + ctx->regs->ip_ier &= ~CHANNEL_1_INTERRUPT_REGISTER; + } else if ( ctx->is_dual && channel == 2 ) { + ctx->regs->ip_ier &= ~CHANNEL_2_INTERRUPT_REGISTER; + } +} + +void axi_gpio_interrupt_clear( + xilinx_axi_gpio_context *ctx, + uint32_t channel +) +{ + assert( channel == 1 || (ctx->is_dual && channel == 2) ); + + if ( channel == 1 ) { + ctx->regs->ip_isr &= CHANNEL_1_INTERRUPT_REGISTER; + } else if ( ctx->is_dual && channel == 2 ) { + ctx->regs->ip_isr &= CHANNEL_2_INTERRUPT_REGISTER; + } +} + +uint32_t axi_gpio_interrupt_get_enabled( xilinx_axi_gpio_context *ctx ) +{ + assert( ctx->has_interrupts ); + + if ( ctx->has_interrupts ) { + return ctx->regs->ip_ier; + } + + return 0; +} + +uint32_t axi_gpio_interrupt_get_status( xilinx_axi_gpio_context *ctx ) +{ + assert( ctx->has_interrupts ); + + if ( ctx->has_interrupts ) { + return ctx->regs->ip_isr; + } + + return 0; +} diff --git a/spec/build/bsps/microblaze/microblaze_fpga/obj.yml b/spec/build/bsps/microblaze/microblaze_fpga/obj.yml index 993ba04004..3d151db193 100644 --- a/spec/build/bsps/microblaze/microblaze_fpga/obj.yml +++ b/spec/build/bsps/microblaze/microblaze_fpga/obj.yml @@ -14,6 +14,7 @@ install: - bsps/microblaze/microblaze_fpga/include/tm27.h - destination: ${BSP_INCLUDEDIR}/bsp source: + - bsps/include/dev/gpio/xilinx-axi-gpio.h - bsps/microblaze/microblaze_fpga/include/bsp/irq.h - bsps/microblaze/microblaze_fpga/include/bsp/jffs2_qspi.h - bsps/microblaze/include/common/xil_types.h @@ -44,6 +45,7 @@ source: - bsps/shared/dev/cpucounter/cpucounterfrequency.c - bsps/shared/dev/cpucounter/cpucounterread.c - bsps/shared/dev/getentropy/getentropy-cpucounter.c +- bsps/shared/dev/gpio/xilinx-axi-gpio.c - bsps/shared/dev/serial/console-termios-init.c - bsps/shared/dev/serial/console-termios.c - bsps/shared/irq/irq-default-handler.c -- 2.32.0 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel