On Tue, Mar 15, 2022 at 2:28 PM Alex White <alex.wh...@oarcorp.com> wrote: > > --- > bsps/include/dev/gpio/xilinx-axi-gpio.h | 311 ++++++++++++++++++ > bsps/shared/dev/gpio/xilinx-axi-gpio.c | 221 +++++++++++++
Is this AXI GPIO interface consistent across Xilinx IP? > .../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 typo: independently > + * channel are enabled or disabled. > + * > + * 0 - No Channel input interrupt > + * 1 - Channel input interrupt > + */ > + uint32_t ip_ier; > +} xilinx_axi_gpio; This `xilinx_` is not a proper namespace for RTEMS. it doesn't correspond with any existing components and so it requires some discussion and approval to introduce it. > + > +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( neither is this `axi_` > + xilinx_axi_gpio_context *ctx, Mixing the newly proposed namespaces is also confusing. > + 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 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel