File indexing completed on 2025-05-11 08:23:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <assert.h>
0037
0038 #include <bsp/fatal.h>
0039 #include <bsp/fdt.h>
0040 #include <bsp/microblaze-gpio.h>
0041
0042 #include <libfdt.h>
0043
0044 #ifdef __cplusplus
0045 extern "C" {
0046 #endif
0047
0048 #ifdef BSP_MICROBLAZE_FPGA_USE_FDT
0049 rtems_status_code microblaze_gpio_init_context_from_fdt(
0050 Microblaze_GPIO_context *context,
0051 int index
0052 )
0053 {
0054 if ( context == NULL ) {
0055 return RTEMS_INVALID_ADDRESS;
0056 }
0057
0058 const char* compatible = "xlnx,xps-gpio-1.00.a";
0059 const void *fdt = bsp_fdt_get();
0060 int node = fdt_node_offset_by_compatible( fdt, -1, compatible );
0061 if ( node < 0 ) {
0062 return RTEMS_INVALID_NUMBER;
0063 }
0064
0065
0066 for(int i = 0; i < index; i++) {
0067 node = fdt_node_offset_by_compatible( fdt, node, compatible );
0068 if ( node < 0 ) {
0069 return RTEMS_INVALID_NUMBER;
0070 }
0071 }
0072
0073 const uint32_t *prop;
0074 prop = fdt_getprop( fdt, node, "reg", NULL );
0075 if ( prop != NULL ) {
0076 context->regs = (Microblaze_GPIO_registers *) fdt32_to_cpu( prop[0] );
0077 } else {
0078 return RTEMS_INVALID_NUMBER;
0079 }
0080
0081 prop = fdt_getprop( fdt, node, "xlnx,is-dual", NULL );
0082 if ( prop != NULL ) {
0083 context->is_dual = fdt32_to_cpu( prop[0] ) != 0 ? true : false;
0084 } else {
0085 return RTEMS_INVALID_NUMBER;
0086 }
0087
0088 prop = fdt_getprop( fdt, node, "xlnx,interrupt-present", NULL );
0089 if ( prop != NULL ) {
0090 context->has_interrupts = fdt32_to_cpu( prop[0] ) != 0 ? true : false;
0091 } else {
0092 return RTEMS_INVALID_NUMBER;
0093 }
0094
0095 if ( context->has_interrupts ) {
0096 prop = fdt_getprop( fdt, node, "interrupts", NULL );
0097 if ( prop != NULL ) {
0098 context->irq = fdt32_to_cpu( prop[0] );
0099 } else {
0100 return RTEMS_INVALID_NUMBER;
0101 }
0102 }
0103
0104 return RTEMS_SUCCESSFUL;
0105 }
0106 #endif
0107
0108 void microblaze_gpio_set_data_direction(
0109 Microblaze_GPIO_context *ctx,
0110 uint32_t channel,
0111 uint32_t mask
0112 )
0113 {
0114 assert( channel == 1 || (ctx->is_dual && channel == 2) );
0115
0116 if ( channel == 1 ) {
0117 ctx->regs->gpio_tri = mask;
0118 } else if ( ctx->is_dual && channel == 2 ) {
0119 ctx->regs->gpio2_tri = mask;
0120 }
0121 }
0122
0123 uint32_t microblaze_gpio_get_data_direction(
0124 Microblaze_GPIO_context *ctx,
0125 uint32_t channel
0126 )
0127 {
0128 assert( channel == 1 || (ctx->is_dual && channel == 2) );
0129
0130 if ( channel == 1 ) {
0131 return ctx->regs->gpio_tri;
0132 } else if ( ctx->is_dual && channel == 2 ) {
0133 return ctx->regs->gpio2_tri;
0134 }
0135
0136 return 0;
0137 }
0138
0139 uint32_t microblaze_gpio_discrete_read(
0140 Microblaze_GPIO_context *ctx,
0141 uint32_t channel
0142 )
0143 {
0144 assert( channel == 1 || (ctx->is_dual && channel == 2) );
0145
0146 if ( channel == 1 ) {
0147 return ctx->regs->gpio_data;
0148 } else if ( ctx->is_dual && channel == 2 ) {
0149 return ctx->regs->gpio2_tri;
0150 }
0151
0152 return 0;
0153 }
0154
0155 void microblaze_gpio_discrete_write(
0156 Microblaze_GPIO_context *ctx,
0157 uint32_t channel,
0158 uint32_t mask
0159 )
0160 {
0161 assert( channel == 1 || (ctx->is_dual && channel == 2) );
0162
0163 if ( channel == 1 ) {
0164 ctx->regs->gpio_data = mask;
0165 } else if ( ctx->is_dual && channel == 2 ) {
0166 ctx->regs->gpio2_tri = mask;
0167 }
0168 }
0169
0170 void microblaze_gpio_discrete_set(
0171 Microblaze_GPIO_context *ctx,
0172 uint32_t channel,
0173 uint32_t mask
0174 )
0175 {
0176 assert( channel == 1 || (ctx->is_dual && channel == 2) );
0177
0178 if ( channel == 1 ) {
0179 ctx->regs->gpio_data |= mask;
0180 } else if ( ctx->is_dual && channel == 2 ) {
0181 ctx->regs->gpio2_tri |= mask;
0182 }
0183 }
0184
0185 void microblaze_gpio_discrete_clear(
0186 Microblaze_GPIO_context *ctx,
0187 uint32_t channel,
0188 uint32_t mask
0189 )
0190 {
0191 assert( channel == 1 || (ctx->is_dual && channel == 2) );
0192
0193 if ( channel == 1 ) {
0194 ctx->regs->gpio_data &= ~mask;
0195 } else if ( ctx->is_dual && channel == 2 ) {
0196 ctx->regs->gpio2_tri &= ~mask;
0197 }
0198 }
0199
0200 rtems_vector_number microblaze_gpio_get_irq( Microblaze_GPIO_context *ctx )
0201 {
0202 return ctx->irq;
0203 }
0204
0205 void microblaze_gpio_interrupt_global_enable( Microblaze_GPIO_context *ctx )
0206 {
0207 assert( ctx->has_interrupts );
0208
0209 if ( ctx->has_interrupts ) {
0210 ctx->regs->gier = GLOBAL_INTERRUPT_REGISTER_ENABLE;
0211 }
0212 }
0213
0214 void microblaze_gpio_interrupt_global_disable( Microblaze_GPIO_context *ctx )
0215 {
0216 assert( ctx->has_interrupts );
0217
0218 if ( ctx->has_interrupts ) {
0219 ctx->regs->gier = 0x0;
0220 }
0221 }
0222
0223 void microblaze_gpio_interrupt_enable(
0224 Microblaze_GPIO_context *ctx,
0225 uint32_t channel
0226 )
0227 {
0228 assert( ctx->has_interrupts );
0229 assert( channel == 1 || (ctx->is_dual && channel == 2) );
0230
0231 if ( ctx->has_interrupts ) {
0232 if ( channel == 1 ) {
0233 ctx->regs->ip_ier |= CHANNEL_1_INTERRUPT_REGISTER;
0234 } else if ( ctx->is_dual && channel == 2 ) {
0235 ctx->regs->ip_ier |= CHANNEL_2_INTERRUPT_REGISTER;
0236 }
0237 }
0238 }
0239
0240 void microblaze_gpio_interrupt_disable(
0241 Microblaze_GPIO_context *ctx,
0242 uint32_t channel
0243 )
0244 {
0245 assert( channel == 1 || (ctx->is_dual && channel == 2) );
0246
0247 if ( channel == 1 ) {
0248 ctx->regs->ip_ier &= ~CHANNEL_1_INTERRUPT_REGISTER;
0249 } else if ( ctx->is_dual && channel == 2 ) {
0250 ctx->regs->ip_ier &= ~CHANNEL_2_INTERRUPT_REGISTER;
0251 }
0252 }
0253
0254 void microblaze_gpio_interrupt_clear(
0255 Microblaze_GPIO_context *ctx,
0256 uint32_t channel
0257 )
0258 {
0259 assert( channel == 1 || (ctx->is_dual && channel == 2) );
0260
0261 if ( channel == 1 ) {
0262 ctx->regs->ip_isr &= CHANNEL_1_INTERRUPT_REGISTER;
0263 } else if ( ctx->is_dual && channel == 2 ) {
0264 ctx->regs->ip_isr &= CHANNEL_2_INTERRUPT_REGISTER;
0265 }
0266 }
0267
0268 uint32_t microblaze_gpio_interrupt_get_enabled( Microblaze_GPIO_context *ctx )
0269 {
0270 assert( ctx->has_interrupts );
0271
0272 if ( ctx->has_interrupts ) {
0273 return ctx->regs->ip_ier;
0274 }
0275
0276 return 0;
0277 }
0278
0279 uint32_t microblaze_gpio_interrupt_get_status( Microblaze_GPIO_context *ctx )
0280 {
0281 assert( ctx->has_interrupts );
0282
0283 if ( ctx->has_interrupts ) {
0284 return ctx->regs->ip_isr;
0285 }
0286
0287 return 0;
0288 }
0289
0290 #ifdef __cplusplus
0291 }
0292 #endif