Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:04

0001 /**
0002  * @file
0003  *
0004  * @ingroup rtems_gpio
0005  *
0006  * @brief RTEMS GPIO API implementation.
0007  */
0008 
0009 /*
0010  *  Copyright (c) 2014-2015 Andre Marques <andre.lousa.marques at gmail.com>
0011  *
0012  *  The license and distribution terms for this file may be
0013  *  found in the file LICENSE in this distribution or at
0014  *  http://www.rtems.org/license/LICENSE.
0015  */
0016 
0017 #include <rtems/score/atomic.h>
0018 #include <rtems/chain.h>
0019 #include <bsp/irq-generic.h>
0020 #include <bsp/gpio.h>
0021 #include <assert.h>
0022 #include <stdlib.h>
0023 
0024 /**
0025  * @brief GPIO API mutex attributes.
0026  */
0027 #define MUTEX_ATTRIBUTES (     \
0028   RTEMS_LOCAL                  \
0029   | RTEMS_PRIORITY             \
0030   | RTEMS_BINARY_SEMAPHORE     \
0031   | RTEMS_INHERIT_PRIORITY     \
0032   | RTEMS_NO_PRIORITY_CEILING  \
0033 )
0034 
0035 #define CREATE_LOCK(name, lock_id) rtems_semaphore_create(   \
0036   name,                                                      \
0037   1,                                                         \
0038   MUTEX_ATTRIBUTES,                                          \
0039   0,                                                         \
0040   lock_id                                                    \
0041 )
0042 
0043 #define ACQUIRE_LOCK(m) assert ( rtems_semaphore_obtain(m,               \
0044                                                         RTEMS_WAIT,      \
0045                                                         RTEMS_NO_TIMEOUT \
0046                                                         ) == RTEMS_SUCCESSFUL )
0047 
0048 #define RELEASE_LOCK(m) assert ( rtems_semaphore_release(m) == RTEMS_SUCCESSFUL )
0049 
0050 /**
0051  * @brief Object containing relevant information about a GPIO group.
0052  *
0053  * Encapsulates relevant data for a GPIO pin group.
0054  */
0055 struct rtems_gpio_group
0056 {
0057   rtems_chain_node node;
0058 
0059   uint32_t *digital_inputs;
0060   uint32_t digital_input_bank;
0061   uint32_t input_count;
0062 
0063   uint32_t *digital_outputs;
0064   uint32_t digital_output_bank;
0065   uint32_t output_count;
0066 
0067   uint32_t *bsp_speficifc_pins;
0068   uint32_t bsp_specific_bank;
0069   uint32_t bsp_specific_pin_count;
0070 
0071   rtems_id group_lock;
0072 };
0073 
0074 /**
0075  * @brief Object containing relevant information to a list of user-defined
0076  *        interrupt handlers.
0077  *
0078  * Encapsulates relevant data for a GPIO interrupt handler.
0079  */
0080 typedef struct
0081 {
0082   rtems_chain_node node;
0083 
0084   /* User-defined ISR routine. */
0085   rtems_gpio_irq_state (*handler) (void *arg);
0086 
0087   /* User-defined arguments for the ISR routine. */
0088   void *arg;
0089 } gpio_handler_node;
0090 
0091 /**
0092  * @brief Object containing relevant information of a pin's interrupt
0093  *        configuration/state.
0094  *
0095  * Encapsulates relevant data of a GPIO pin interrupt state.
0096  */
0097 typedef struct
0098 {
0099   /* Currently active interrupt. */
0100   rtems_gpio_interrupt active_interrupt;
0101 
0102   /* ISR shared flag. */
0103   rtems_gpio_handler_flag handler_flag;
0104 
0105   /* Linked list of interrupt handlers. */
0106   rtems_chain_control handler_chain;
0107 
0108   /* Switch-deboucing information. */
0109   uint32_t debouncing_tick_count;
0110   rtems_interval last_isr_tick;
0111 } gpio_pin_interrupt_state;
0112 
0113 /**
0114  * @brief Object containing information on a GPIO pin.
0115  *
0116  * Encapsulates relevant data about a GPIO pin.
0117  */
0118 typedef struct
0119 {
0120   rtems_gpio_function pin_function;
0121 
0122   /* GPIO pull resistor configuration. */
0123   rtems_gpio_pull_mode resistor_mode;
0124 
0125   /* If true inverts digital in/out applicational logic. */
0126   bool logic_invert;
0127 
0128   /* True if the pin is on a group. */
0129   bool on_group;
0130 
0131   /* Interrupt data for a pin. This field is NULL if no interrupt is enabled
0132    * on the pin. */
0133   gpio_pin_interrupt_state *interrupt_state;
0134 } gpio_pin;
0135 
0136 /**
0137  * @brief Object containing relevant information regarding a GPIO bank state.
0138  *
0139  * Encapsulates relevant data for a GPIO bank.
0140  */
0141 typedef struct
0142 {
0143   uint32_t bank_number;
0144   uint32_t interrupt_counter;
0145   rtems_id lock;
0146 
0147   /* If TRUE the interrupts on the bank will be called
0148    * by a rtems interrupt server, otherwise they will be handled
0149    * in the normal ISR context. */
0150   bool threaded_interrupts;
0151 } gpio_bank;
0152 
0153 static gpio_pin gpio_pin_state[BSP_GPIO_PIN_COUNT];
0154 static Atomic_Flag init_flag = ATOMIC_INITIALIZER_FLAG;
0155 static gpio_bank gpio_bank_state[GPIO_BANK_COUNT];
0156 static Atomic_Uint threaded_interrupt_counter = ATOMIC_INITIALIZER_UINT(0);
0157 static rtems_chain_control gpio_group;
0158 
0159 #define BANK_NUMBER(pin_number) pin_number / BSP_GPIO_PINS_PER_BANK
0160 #define PIN_NUMBER(pin_number) pin_number % BSP_GPIO_PINS_PER_BANK
0161 
0162 static int debounce_switch(gpio_pin_interrupt_state *interrupt_state)
0163 {
0164   rtems_interval time;
0165 
0166   time = rtems_clock_get_ticks_since_boot();
0167 
0168   /* If not enough time has elapsed since last interrupt. */
0169   if (
0170       (time - interrupt_state->last_isr_tick) <
0171       interrupt_state->debouncing_tick_count
0172   ) {
0173     return -1;
0174   }
0175 
0176   interrupt_state->last_isr_tick = time;
0177 
0178   return 0;
0179 }
0180 
0181 /* Returns the amount of pins in a bank. */
0182 static uint32_t get_bank_pin_count(uint32_t bank)
0183 {
0184   /* If the current bank is the last bank, which may not be completely filled. */
0185   if ( bank == GPIO_BANK_COUNT - 1 ) {
0186     return GPIO_LAST_BANK_PINS;
0187   }
0188 
0189   return BSP_GPIO_PINS_PER_BANK;
0190 }
0191 
0192 /* GPIO generic bank ISR. This may be called directly as response to an
0193  * interrupt, or by the rtems interrupt server task if the GPIO bank
0194  * uses threading interrupt handling. */
0195 static void generic_bank_isr(void *arg)
0196 {
0197   gpio_pin_interrupt_state *interrupt_state;
0198   rtems_chain_control *handler_list;
0199   rtems_chain_node *node;
0200   rtems_chain_node *next_node;
0201   gpio_handler_node *isr_node;
0202   rtems_vector_number vector;
0203   uint32_t event_status;
0204   uint32_t bank_number;
0205   uint32_t bank_start_pin;
0206   uint8_t handled_count;
0207   uint8_t rv;
0208   uint8_t i;
0209 
0210   bank_number = *((uint32_t*) arg);
0211 
0212   assert ( bank_number >= 0 && bank_number < GPIO_BANK_COUNT );
0213 
0214   /* Calculate bank start address in the pin_state array. */
0215   bank_start_pin = bank_number * BSP_GPIO_PINS_PER_BANK;
0216 
0217   vector = rtems_gpio_bsp_get_vector(bank_number);
0218 
0219   /* If this bank does not use threaded interrupts we have to
0220    * disable the vector. Otherwise the interrupt server does it. */
0221   if ( gpio_bank_state[bank_number].threaded_interrupts == false ) {
0222     /* Prevents more interrupts from being generated on GPIO. */
0223     bsp_interrupt_vector_disable(vector);
0224   }
0225 
0226   /* Obtains a 32-bit bitmask, with the pins currently reporting interrupts
0227    * signaled with 1. */
0228   event_status = rtems_gpio_bsp_interrupt_line(vector);
0229 
0230   /* Iterates through the bitmask and calls the corresponding handler
0231    * for active interrupts. */
0232   for ( i = 0; i < get_bank_pin_count(bank_number); ++i ) {
0233     /* If active, wake the corresponding pin's ISR task. */
0234     if ( event_status & (1 << i) ) {
0235       interrupt_state = gpio_pin_state[bank_start_pin + i].interrupt_state;
0236 
0237       assert ( interrupt_state != NULL );
0238 
0239       handled_count = 0;
0240 
0241       if ( gpio_bank_state[bank_number].threaded_interrupts ) {
0242         ACQUIRE_LOCK(gpio_bank_state[bank_number].lock);
0243       }
0244 
0245       /* If this pin has the debouncing function attached, call it. */
0246       if ( interrupt_state->debouncing_tick_count > 0 ) {
0247         rv = debounce_switch(interrupt_state);
0248 
0249         /* If the handler call was caused by a switch bounce,
0250          * ignores and move on. */
0251         if ( rv < 0 ) {
0252           if ( gpio_bank_state[bank_number].threaded_interrupts ) {
0253             RELEASE_LOCK(gpio_bank_state[bank_number].lock);
0254           }
0255 
0256           continue;
0257         }
0258       }
0259 
0260       handler_list = &interrupt_state->handler_chain;
0261 
0262       node = rtems_chain_first(handler_list);
0263 
0264       /* Iterate the ISR list. */
0265       while ( !rtems_chain_is_tail(handler_list, node) ) {
0266         isr_node = (gpio_handler_node *) node;
0267 
0268         next_node = node->next;
0269 
0270         if ( (isr_node->handler)(isr_node->arg) == IRQ_HANDLED ) {
0271           ++handled_count;
0272         }
0273 
0274         node = next_node;
0275       }
0276 
0277       /* If no handler assumed the interrupt,
0278        * treat it as a spurious interrupt. */
0279       if ( handled_count == 0 ) {
0280         bsp_interrupt_handler_default(rtems_gpio_bsp_get_vector(bank_number));
0281       }
0282 
0283       if ( gpio_bank_state[bank_number].threaded_interrupts ) {
0284         RELEASE_LOCK(gpio_bank_state[bank_number].lock);
0285       }
0286     }
0287   }
0288 
0289   if ( gpio_bank_state[bank_number].threaded_interrupts == false ) {
0290     bsp_interrupt_vector_enable(vector);
0291   }
0292 }
0293 
0294 /* Verifies if all pins in the received pin array are from the same bank and
0295  * have the defined GPIO function. Produces bitmask of the received pins. */
0296 static rtems_status_code get_pin_bitmask(
0297   uint32_t *pins,
0298   uint32_t pin_count,
0299   uint32_t *bank_number,
0300   uint32_t *bitmask,
0301   rtems_gpio_function function
0302 ) {
0303   uint32_t pin_number;
0304   uint32_t bank;
0305   uint8_t i;
0306 
0307   if ( pin_count < 1 ) {
0308     return RTEMS_UNSATISFIED;
0309   }
0310 
0311   *bitmask = 0;
0312 
0313   for ( i = 0; i < pin_count; ++i ) {
0314     pin_number = pins[i];
0315 
0316     if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
0317       return RTEMS_INVALID_ID;
0318     }
0319 
0320     bank = BANK_NUMBER(pin_number);
0321 
0322     if ( i == 0 ) {
0323       *bank_number = bank;
0324 
0325       ACQUIRE_LOCK(gpio_bank_state[bank].lock);
0326     }
0327     else if ( bank != *bank_number ) {
0328       RELEASE_LOCK(gpio_bank_state[*bank_number].lock);
0329 
0330       return RTEMS_UNSATISFIED;
0331     }
0332 
0333     if (
0334         gpio_pin_state[pin_number].pin_function != function ||
0335         gpio_pin_state[pin_number].on_group
0336     ) {
0337       RELEASE_LOCK(gpio_bank_state[bank].lock);
0338 
0339       return RTEMS_NOT_CONFIGURED;
0340     }
0341 
0342     *bitmask |= (1 << PIN_NUMBER(pin_number));
0343   }
0344 
0345   RELEASE_LOCK(gpio_bank_state[bank].lock);
0346 
0347   return RTEMS_SUCCESSFUL;
0348 }
0349 
0350 static rtems_status_code check_same_bank_and_availability(
0351   const rtems_gpio_pin_conf *pin_confs,
0352   uint32_t pin_count,
0353   uint32_t *bank_number,
0354   uint32_t *pins
0355 ) {
0356   uint32_t pin_number;
0357   uint32_t bank;
0358   uint8_t i;
0359 
0360   for ( i = 0; i < pin_count; ++i ) {
0361     pin_number = pin_confs[i].pin_number;
0362 
0363     bank = BANK_NUMBER(pin_number);
0364 
0365     if ( i == 0 ) {
0366       *bank_number = bank;
0367 
0368       ACQUIRE_LOCK(gpio_bank_state[bank].lock);
0369     }
0370     else if ( bank != *bank_number ) {
0371       RELEASE_LOCK(gpio_bank_state[*bank_number].lock);
0372 
0373       return RTEMS_UNSATISFIED;
0374     }
0375 
0376     if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {
0377       RELEASE_LOCK(gpio_bank_state[bank].lock);
0378 
0379       return RTEMS_RESOURCE_IN_USE;
0380     }
0381 
0382     pins[i] = PIN_NUMBER(pin_number);
0383   }
0384 
0385   RELEASE_LOCK(gpio_bank_state[*bank_number].lock);
0386 
0387   return RTEMS_SUCCESSFUL;
0388 }
0389 
0390 static rtems_status_code setup_resistor_and_interrupt_configuration(
0391   uint32_t pin_number,
0392   rtems_gpio_pull_mode pull_mode,
0393   rtems_gpio_interrupt_configuration *interrupt_conf
0394 ) {
0395   gpio_pin_interrupt_state *interrupt_state;
0396   rtems_status_code sc;
0397   uint32_t bank;
0398 
0399   sc = rtems_gpio_resistor_mode(pin_number, pull_mode);
0400 
0401   if ( sc != RTEMS_SUCCESSFUL ) {
0402 #if defined(DEBUG)
0403     printk("rtems_gpio_resistor_mode failed with status code %d\n", sc);
0404 #endif
0405 
0406     return RTEMS_UNSATISFIED;
0407   }
0408 
0409   if ( interrupt_conf != NULL ) {
0410     bank = BANK_NUMBER(pin_number);
0411 
0412     ACQUIRE_LOCK(gpio_bank_state[bank].lock);
0413 
0414     sc = rtems_gpio_enable_interrupt(
0415            pin_number,
0416            interrupt_conf->active_interrupt,
0417            interrupt_conf->handler_flag,
0418            interrupt_conf->threaded_interrupts,
0419            interrupt_conf->handler,
0420            interrupt_conf->arg
0421          );
0422 
0423     if ( sc != RTEMS_SUCCESSFUL ) {
0424       RELEASE_LOCK(gpio_bank_state[bank].lock);
0425 
0426 #if defined(DEBUG)
0427       printk(
0428         "rtems_gpio_enable_interrupt failed with status code %d\n",
0429         sc
0430       );
0431 #endif
0432 
0433       return RTEMS_UNSATISFIED;
0434     }
0435 
0436     interrupt_state = gpio_pin_state[pin_number].interrupt_state;
0437 
0438     interrupt_state->debouncing_tick_count =
0439       interrupt_conf->debounce_clock_tick_interval;
0440 
0441     interrupt_state->last_isr_tick = 0;
0442 
0443     RELEASE_LOCK(gpio_bank_state[bank].lock);
0444   }
0445 
0446   return RTEMS_SUCCESSFUL;
0447 }
0448 
0449 static rtems_status_code gpio_multi_select(
0450   const rtems_gpio_pin_conf *pins,
0451   uint8_t pin_count,
0452   bool on_group
0453 ) {
0454   rtems_status_code sc;
0455   uint32_t pin_number;
0456   uint32_t bank;
0457   uint8_t i;
0458 
0459   /* If the BSP has multi select capabilities. */
0460 #ifdef BSP_GPIO_PINS_PER_SELECT_BANK
0461   rtems_gpio_multiple_pin_select
0462     pin_data[GPIO_SELECT_BANK_COUNT][BSP_GPIO_PINS_PER_SELECT_BANK];
0463   rtems_gpio_specific_data *bsp_data;
0464 
0465   /* Since each platform may have more than two functions to assign to a pin,
0466    * each pin requires more than one bit in the selection register to
0467    * properly assign a function to it.
0468    * Therefore a selection bank (pin selection register) will support fewer pins
0469    * than a regular bank, meaning that there will be more selection banks than
0470    * regular banks, which have to be handled separately.
0471    *
0472    * This field records the select bank number relative to the GPIO bank. */
0473   uint32_t select_bank;
0474   uint32_t bank_number;
0475   uint32_t select_bank_counter[GPIO_SELECT_BANK_COUNT];
0476   uint32_t select_count;
0477   uint32_t pin;
0478 
0479   if ( pin_count == 0 ) {
0480     return RTEMS_SUCCESSFUL;
0481   }
0482 
0483   for ( i = 0; i < GPIO_SELECT_BANK_COUNT; ++i ) {
0484     select_bank_counter[i] = 0;
0485   }
0486 
0487   for ( i = 0; i < pin_count; ++i ) {
0488     pin_number = pins[i].pin_number;
0489 
0490     if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
0491       return RTEMS_INVALID_ID;
0492     }
0493 
0494     bank = BANK_NUMBER(pin_number);
0495     pin = PIN_NUMBER(pin_number);
0496 
0497     if ( i == 0 ) {
0498       bank_number = bank;
0499 
0500       ACQUIRE_LOCK(gpio_bank_state[bank].lock);
0501     }
0502     else if ( bank != bank_number ) {
0503       RELEASE_LOCK(gpio_bank_state[bank_number].lock);
0504 
0505       return RTEMS_UNSATISFIED;
0506     }
0507 
0508     /* If the pin is already being used returns with an error. */
0509     if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {
0510       RELEASE_LOCK(gpio_bank_state[bank_number].lock);
0511 
0512       return RTEMS_RESOURCE_IN_USE;
0513     }
0514 
0515     select_bank = (pin_number / BSP_GPIO_PINS_PER_SELECT_BANK) -
0516                   (bank * GPIO_SELECT_BANK_COUNT);
0517 
0518     select_count = select_bank_counter[select_bank];
0519 
0520     pin_data[select_bank][select_count].pin_number = pin_number;
0521     pin_data[select_bank][select_count].function = pins[i].function;
0522 
0523     if ( pins[i].function == BSP_SPECIFIC ) {
0524       bsp_data = (rtems_gpio_specific_data *) pins[i].bsp_specific;
0525 
0526       if ( bsp_data == NULL ) {
0527         RELEASE_LOCK(gpio_bank_state[bank_number].lock);
0528 
0529         return RTEMS_UNSATISFIED;
0530       }
0531 
0532       pin_data[select_bank][select_count].io_function = bsp_data->io_function;
0533       pin_data[select_bank][select_count].bsp_specific = bsp_data->pin_data;
0534     }
0535     else {
0536       /* io_function takes a dummy value, as it will not be used. */
0537       pin_data[select_bank][select_count].io_function = 0;
0538       pin_data[select_bank][select_count].bsp_specific = pins[i].bsp_specific;
0539     }
0540 
0541     ++select_bank_counter[select_bank];
0542   }
0543 
0544   for ( i = 0; i < GPIO_SELECT_BANK_COUNT; ++i ) {
0545     if ( select_bank_counter[i] == 0 ) {
0546       continue;
0547     }
0548 
0549     sc = rtems_gpio_bsp_multi_select(
0550            pin_data[i], select_bank_counter[i], i +
0551            (bank_number * GPIO_SELECT_BANK_COUNT)
0552          );
0553 
0554     if ( sc != RTEMS_SUCCESSFUL ) {
0555       RELEASE_LOCK(gpio_bank_state[bank_number].lock);
0556 
0557       return sc;
0558     }
0559   }
0560 
0561   for ( i = 0; i < pin_count; ++i ) {
0562     pin_number = pins[i].pin_number;
0563 
0564     /* Fill other pin state information. */
0565     gpio_pin_state[pin_number].pin_function = pins[i].function;
0566     gpio_pin_state[pin_number].logic_invert = pins[i].logic_invert;
0567     gpio_pin_state[pin_number].on_group = on_group;
0568 
0569     sc = setup_resistor_and_interrupt_configuration(
0570            pin_number,
0571            pins[i].pull_mode,
0572            pins[i].interrupt
0573          );
0574 
0575     if ( sc != RTEMS_SUCCESSFUL ) {
0576       RELEASE_LOCK(gpio_bank_state[bank_number].lock);
0577 
0578       return sc;
0579     }
0580 
0581     bank = BANK_NUMBER(pin_number);
0582     pin = PIN_NUMBER(pin_number);
0583 
0584     if ( pins[i].function == DIGITAL_OUTPUT ) {
0585       if ( pins[i].output_enabled == true ) {
0586         sc = rtems_gpio_bsp_set(bank, pin);
0587       }
0588       else {
0589         sc = rtems_gpio_bsp_clear(bank, pin);
0590       }
0591 
0592       if ( sc != RTEMS_SUCCESSFUL ) {
0593         RELEASE_LOCK(gpio_bank_state[bank_number].lock);
0594 
0595         return sc;
0596       }
0597     }
0598   }
0599 
0600   RELEASE_LOCK(gpio_bank_state[bank_number].lock);
0601 
0602   return sc;
0603 
0604   /* If the BSP does not provide pin multi-selection,
0605    * configures each pin sequentially. */
0606 #else
0607   for ( i = 0; i < pin_count; ++i ) {
0608     pin_number = pins[i].pin_number;
0609 
0610     if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
0611       return RTEMS_INVALID_ID;
0612     }
0613 
0614     bank = BANK_NUMBER(pin_number);
0615 
0616     ACQUIRE_LOCK(gpio_bank_state[bank].lock);
0617 
0618     /* If the pin is already being used returns with an error. */
0619     if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {
0620       RELEASE_LOCK(gpio_bank_state[bank].lock);
0621 
0622       return RTEMS_RESOURCE_IN_USE;
0623     }
0624   }
0625 
0626   for ( i = 0; i < pin_count; ++i ) {
0627     sc = rtems_gpio_request_configuration(&pins[i]);
0628 
0629     if ( sc != RTEMS_SUCCESSFUL ) {
0630       return sc;
0631     }
0632 
0633     gpio_pin_state[pins[i].pin_number].on_group = on_group;
0634   }
0635 
0636   return RTEMS_SUCCESSFUL;
0637 #endif
0638 }
0639 
0640 rtems_status_code rtems_gpio_initialize(void)
0641 {
0642   rtems_status_code sc;
0643   uint32_t i;
0644 
0645   if ( _Atomic_Flag_test_and_set(&init_flag, ATOMIC_ORDER_RELAXED) == true ) {
0646     return RTEMS_SUCCESSFUL;
0647   }
0648 
0649   for ( i = 0; i < GPIO_BANK_COUNT; ++i ) {
0650     sc = CREATE_LOCK(
0651            rtems_build_name('G', 'I', 'N', 'T'),
0652            &gpio_bank_state[i].lock
0653          );
0654 
0655     if ( sc != RTEMS_SUCCESSFUL ) {
0656       return sc;
0657     }
0658 
0659     gpio_bank_state[i].bank_number = i;
0660     gpio_bank_state[i].interrupt_counter = 0;
0661 
0662     /* The threaded_interrupts field is initialized during
0663      * rtems_gpio_enable_interrupt(), as its value is never used before. */
0664   }
0665 
0666   for ( i = 0; i < BSP_GPIO_PIN_COUNT; ++i ) {
0667     gpio_pin_state[i].pin_function = NOT_USED;
0668     gpio_pin_state[i].resistor_mode = NO_PULL_RESISTOR;
0669     gpio_pin_state[i].logic_invert = false;
0670     gpio_pin_state[i].on_group = false;
0671     gpio_pin_state[i].interrupt_state = NULL;
0672   }
0673 
0674   /* Initialize GPIO groups chain. */
0675   rtems_chain_initialize_empty(&gpio_group);
0676 
0677   return RTEMS_SUCCESSFUL;
0678 }
0679 
0680 rtems_gpio_group *rtems_gpio_create_pin_group(void)
0681 {
0682   struct rtems_gpio_group *group;
0683 
0684   group = (struct rtems_gpio_group *) malloc(sizeof(struct rtems_gpio_group));
0685 
0686   return group;
0687 }
0688 
0689 rtems_status_code rtems_gpio_define_pin_group(
0690   const rtems_gpio_group_definition *group_definition,
0691   rtems_gpio_group *group
0692 ) {
0693   rtems_status_code sc;
0694 
0695   if ( group_definition == NULL || group == NULL ) {
0696     return RTEMS_UNSATISFIED;
0697   }
0698 
0699   if (
0700       group_definition->input_count == 0 &&
0701       group_definition->output_count == 0 &&
0702       group_definition->bsp_specific_pin_count == 0
0703   ) {
0704     return RTEMS_UNSATISFIED;
0705   }
0706 
0707   group->input_count = group_definition->input_count;
0708 
0709   if ( group->input_count > 0 ) {
0710     group->digital_inputs =
0711       (uint32_t *) malloc(group->input_count * sizeof(uint32_t));
0712 
0713     /* Evaluate if the pins that will constitute the group are available and
0714      * that pins with the same function within the group all belong
0715      * to the same pin group. */
0716     sc = check_same_bank_and_availability(
0717            group_definition->digital_inputs,
0718            group->input_count,
0719            &group->digital_input_bank,
0720            group->digital_inputs
0721          );
0722 
0723     if ( sc != RTEMS_SUCCESSFUL ) {
0724       return sc;
0725     }
0726   }
0727   else {
0728     group->digital_inputs = NULL;
0729   }
0730 
0731   group->output_count = group_definition->output_count;
0732 
0733   if ( group->output_count > 0 ) {
0734     group->digital_outputs =
0735       (uint32_t *) malloc(group->output_count * sizeof(uint32_t));
0736 
0737     sc = check_same_bank_and_availability(
0738            group_definition->digital_outputs,
0739            group->output_count,
0740            &group->digital_output_bank,
0741            group->digital_outputs
0742          );
0743 
0744     if ( sc != RTEMS_SUCCESSFUL ) {
0745       return sc;
0746     }
0747   }
0748   else {
0749     group->digital_outputs = NULL;
0750   }
0751 
0752   group->bsp_specific_pin_count = group_definition->bsp_specific_pin_count;
0753 
0754   if ( group->bsp_specific_pin_count > 0 ) {
0755     group->bsp_speficifc_pins =
0756       (uint32_t *) malloc(
0757                      group->bsp_specific_pin_count *
0758                      sizeof(uint32_t)
0759                    );
0760 
0761     sc = check_same_bank_and_availability(
0762            group_definition->bsp_specifics,
0763            group->bsp_specific_pin_count,
0764            &group->bsp_specific_bank,
0765            group->bsp_speficifc_pins
0766          );
0767 
0768     if ( sc != RTEMS_SUCCESSFUL ) {
0769       return sc;
0770     }
0771   }
0772   else {
0773     group->bsp_speficifc_pins = NULL;
0774   }
0775 
0776   /* Request the pins. */
0777   sc = gpio_multi_select(
0778          group_definition->digital_inputs,
0779          group_definition->input_count,
0780          true
0781        );
0782 
0783   if ( sc != RTEMS_SUCCESSFUL ) {
0784     return RTEMS_UNSATISFIED;
0785   }
0786 
0787   sc = gpio_multi_select(
0788          group_definition->digital_outputs,
0789          group_definition->output_count,
0790          true
0791        );
0792 
0793   if ( sc != RTEMS_SUCCESSFUL ) {
0794     sc = rtems_gpio_release_multiple_pins(
0795            group_definition->digital_inputs,
0796            group_definition->input_count
0797          );
0798 
0799     assert ( sc == RTEMS_SUCCESSFUL );
0800 
0801     return RTEMS_UNSATISFIED;
0802   }
0803 
0804   sc = gpio_multi_select(
0805          group_definition->bsp_specifics,
0806          group_definition->bsp_specific_pin_count,
0807          true
0808        );
0809 
0810   if ( sc != RTEMS_SUCCESSFUL ) {
0811     sc = rtems_gpio_release_multiple_pins(
0812            group_definition->digital_inputs,
0813            group_definition->input_count
0814          );
0815 
0816     assert ( sc == RTEMS_SUCCESSFUL );
0817 
0818     sc = rtems_gpio_release_multiple_pins(
0819            group_definition->digital_outputs,
0820            group_definition->output_count
0821          );
0822 
0823     assert ( sc == RTEMS_SUCCESSFUL );
0824 
0825     return RTEMS_UNSATISFIED;
0826   }
0827 
0828   /* Create group lock. */
0829   sc = CREATE_LOCK(rtems_build_name('G', 'R', 'P', 'L'), &group->group_lock);
0830 
0831   if ( sc != RTEMS_SUCCESSFUL ) {
0832     return sc;
0833   }
0834 
0835   rtems_chain_append(&gpio_group, &group->node);
0836 
0837   return RTEMS_SUCCESSFUL;
0838 }
0839 
0840 rtems_status_code rtems_gpio_write_group(uint32_t data, rtems_gpio_group *group)
0841 {
0842   rtems_status_code sc = RTEMS_SUCCESSFUL;
0843   uint32_t set_bitmask;
0844   uint32_t clear_bitmask;
0845   uint32_t bank;
0846   uint32_t pin;
0847   uint8_t i;
0848 
0849   if ( group->output_count == 0 ) {
0850     return RTEMS_NOT_DEFINED;
0851   }
0852 
0853   bank = group->digital_output_bank;
0854 
0855   /* Acquire bank lock for the digital output pins. */
0856   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
0857 
0858   /* Acquire group lock. */
0859   ACQUIRE_LOCK(group->group_lock);
0860 
0861   set_bitmask = 0;
0862   clear_bitmask = 0;
0863 
0864   for ( i = 0; i < group->output_count; ++i ) {
0865     pin = group->digital_outputs[i];
0866 
0867     if ( (data & (1 << i)) == 0 ) {
0868       clear_bitmask |= (1 << pin);
0869     }
0870     else {
0871       set_bitmask |= (1 << pin);
0872     }
0873   }
0874 
0875   /* Set the logical highs. */
0876   if ( set_bitmask > 0 ) {
0877     sc = rtems_gpio_bsp_multi_set(bank, set_bitmask);
0878 
0879     if ( sc != RTEMS_SUCCESSFUL ) {
0880       RELEASE_LOCK(group->group_lock);
0881       RELEASE_LOCK(gpio_bank_state[bank].lock);
0882 
0883       return sc;
0884     }
0885   }
0886 
0887   /* Set the logical lows. */
0888   if ( clear_bitmask > 0 ) {
0889     sc = rtems_gpio_bsp_multi_clear(bank, clear_bitmask);
0890 
0891     if ( sc != RTEMS_SUCCESSFUL ) {
0892       RELEASE_LOCK(group->group_lock);
0893       RELEASE_LOCK(gpio_bank_state[bank].lock);
0894 
0895       return sc;
0896     }
0897   }
0898 
0899   RELEASE_LOCK(group->group_lock);
0900   RELEASE_LOCK(gpio_bank_state[bank].lock);
0901 
0902   return RTEMS_SUCCESSFUL;
0903 }
0904 
0905 uint32_t rtems_gpio_read_group(rtems_gpio_group *group)
0906 {
0907   uint32_t read_bitmask;
0908   uint32_t bank;
0909   uint32_t pin;
0910   uint32_t rv;
0911   uint8_t i;
0912 
0913   if ( group->input_count == 0 ) {
0914     return GPIO_INPUT_ERROR;
0915   }
0916 
0917   bank = group->digital_input_bank;
0918 
0919   /* Acquire bank lock for the digital input pins. */
0920   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
0921 
0922   /* Acquire group lock. */
0923   ACQUIRE_LOCK(group->group_lock);
0924 
0925   read_bitmask = 0;
0926 
0927   for ( i = 0; i < group->input_count; ++i ) {
0928     pin = group->digital_inputs[i];
0929 
0930     read_bitmask |= (1 << pin);
0931   }
0932 
0933   rv = rtems_gpio_bsp_multi_read(bank, read_bitmask);
0934 
0935   RELEASE_LOCK(gpio_bank_state[bank].lock);
0936   RELEASE_LOCK(group->group_lock);
0937 
0938   return rv;
0939 }
0940 
0941 rtems_status_code rtems_gpio_group_bsp_specific_operation(
0942   rtems_gpio_group *group,
0943   void *arg
0944 ) {
0945   rtems_status_code sc;
0946   uint32_t bank;
0947 
0948   if ( group->bsp_specific_pin_count == 0 ) {
0949     return RTEMS_NOT_DEFINED;
0950   }
0951 
0952   bank = group->bsp_specific_bank;
0953 
0954   /* Acquire bank lock for the BSP specific function pins. */
0955   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
0956 
0957   /* Acquire group lock. */
0958   ACQUIRE_LOCK(group->group_lock);
0959 
0960   sc = rtems_gpio_bsp_specific_group_operation(
0961          bank,
0962          group->bsp_speficifc_pins,
0963          group->bsp_specific_pin_count,
0964          arg
0965        );
0966 
0967   RELEASE_LOCK(gpio_bank_state[bank].lock);
0968   RELEASE_LOCK(group->group_lock);
0969 
0970   return sc;
0971 }
0972 
0973 rtems_status_code rtems_gpio_multi_select(
0974   const rtems_gpio_pin_conf *pins,
0975   uint8_t pin_count
0976 ) {
0977   return gpio_multi_select(pins, pin_count, false);
0978 }
0979 
0980 rtems_status_code rtems_gpio_request_configuration(
0981   const rtems_gpio_pin_conf *conf
0982 ) {
0983   rtems_status_code sc;
0984 
0985   sc = rtems_gpio_request_pin(
0986          conf->pin_number,
0987          conf->function,
0988          conf->output_enabled,
0989          conf->logic_invert,
0990          conf->bsp_specific
0991        );
0992 
0993   if ( sc != RTEMS_SUCCESSFUL ) {
0994 #if defined(DEBUG)
0995     printk("rtems_gpio_request_pin failed with status code %d\n",sc);
0996 #endif
0997 
0998     return RTEMS_UNSATISFIED;
0999   }
1000 
1001   return setup_resistor_and_interrupt_configuration(
1002            conf->pin_number,
1003            conf->pull_mode,
1004            conf->interrupt
1005          );
1006 }
1007 
1008 rtems_status_code rtems_gpio_update_configuration(
1009   const rtems_gpio_pin_conf *conf
1010 ) {
1011   rtems_gpio_interrupt_configuration *interrupt_conf;
1012   gpio_pin_interrupt_state *interrupt_state;
1013   rtems_status_code sc;
1014   uint32_t bank;
1015 
1016   if ( conf->pin_number < 0 || conf->pin_number >= BSP_GPIO_PIN_COUNT ) {
1017     return RTEMS_INVALID_ID;
1018   }
1019 
1020   bank = BANK_NUMBER(conf->pin_number);
1021 
1022   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1023 
1024   /* If the pin is not being used returns with an error. */
1025   if ( gpio_pin_state[conf->pin_number].pin_function == NOT_USED ) {
1026     RELEASE_LOCK(gpio_bank_state[bank].lock);
1027 
1028     return RTEMS_NOT_CONFIGURED;
1029   }
1030 
1031   sc = rtems_gpio_resistor_mode(conf->pin_number, conf->pull_mode);
1032 
1033   if ( sc != RTEMS_SUCCESSFUL ) {
1034 #if defined(DEBUG)
1035     printk("rtems_gpio_resistor_mode failed with status code %d\n", sc);
1036 #endif
1037 
1038     return RTEMS_UNSATISFIED;
1039   }
1040 
1041   interrupt_conf = (rtems_gpio_interrupt_configuration *) conf->interrupt;
1042 
1043   interrupt_state = gpio_pin_state[conf->pin_number].interrupt_state;
1044 
1045   if ( interrupt_state != NULL ) {
1046     sc = rtems_gpio_disable_interrupt(conf->pin_number);
1047 
1048     if ( sc != RTEMS_SUCCESSFUL ) {
1049       RELEASE_LOCK(gpio_bank_state[bank].lock);
1050 
1051 #if defined(DEBUG)
1052       printk(
1053         "rtems_gpio_disable_interrupt failed with status code %d\n",
1054         sc
1055       );
1056 #endif
1057 
1058       return RTEMS_UNSATISFIED;
1059     }
1060   }
1061 
1062   if ( interrupt_conf != NULL ) {
1063     sc = rtems_gpio_enable_interrupt(
1064            conf->pin_number,
1065            interrupt_conf->active_interrupt,
1066            interrupt_conf->handler_flag,
1067            interrupt_conf->threaded_interrupts,
1068            interrupt_conf->handler,
1069            interrupt_conf->arg
1070          );
1071 
1072     if ( sc != RTEMS_SUCCESSFUL ) {
1073       RELEASE_LOCK(gpio_bank_state[bank].lock);
1074 
1075 #if defined(DEBUG)
1076       printk(
1077         "rtems_gpio_enable_interrupt failed with status code %d\n",
1078         sc
1079       );
1080 #endif
1081 
1082       return RTEMS_UNSATISFIED;
1083     }
1084   }
1085 
1086   if ( interrupt_conf != NULL && interrupt_state != NULL ) {
1087     if (
1088         interrupt_conf->debounce_clock_tick_interval !=
1089         interrupt_state->debouncing_tick_count
1090     ) {
1091       interrupt_state->debouncing_tick_count =
1092         interrupt_conf->debounce_clock_tick_interval;
1093 
1094       interrupt_state->last_isr_tick = 0;
1095     }
1096   }
1097 
1098   RELEASE_LOCK(gpio_bank_state[bank].lock);
1099 
1100   return RTEMS_SUCCESSFUL;
1101 }
1102 
1103 rtems_status_code rtems_gpio_multi_set(
1104  uint32_t *pin_numbers,
1105  uint32_t pin_count
1106 ) {
1107   rtems_status_code sc;
1108   uint32_t bitmask;
1109   uint32_t bank;
1110 
1111   sc = get_pin_bitmask(pin_numbers, pin_count, &bank, &bitmask, DIGITAL_OUTPUT);
1112 
1113   if ( sc != RTEMS_SUCCESSFUL ) {
1114     return sc;
1115   }
1116 
1117   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1118 
1119   sc = rtems_gpio_bsp_multi_set(bank, bitmask);
1120 
1121   RELEASE_LOCK(gpio_bank_state[bank].lock);
1122 
1123   return sc;
1124 }
1125 
1126 rtems_status_code rtems_gpio_multi_clear(
1127   uint32_t *pin_numbers,
1128   uint32_t pin_count
1129 ) {
1130   rtems_status_code sc;
1131   uint32_t bitmask;
1132   uint32_t bank;
1133 
1134   sc = get_pin_bitmask(pin_numbers, pin_count, &bank, &bitmask, DIGITAL_OUTPUT);
1135 
1136   if ( sc != RTEMS_SUCCESSFUL ) {
1137     return sc;
1138   }
1139 
1140   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1141 
1142   sc = rtems_gpio_bsp_multi_clear(bank, bitmask);
1143 
1144   RELEASE_LOCK(gpio_bank_state[bank].lock);
1145 
1146   return sc;
1147 }
1148 
1149 uint32_t rtems_gpio_multi_read(
1150   uint32_t *pin_numbers,
1151   uint32_t pin_count
1152 ) {
1153   rtems_status_code sc;
1154   uint32_t bitmask;
1155   uint32_t bank;
1156   uint32_t rv;
1157 
1158   sc = get_pin_bitmask(pin_numbers, pin_count, &bank, &bitmask, DIGITAL_INPUT);
1159 
1160   if ( sc != RTEMS_SUCCESSFUL ) {
1161     return GPIO_INPUT_ERROR;
1162   }
1163 
1164   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1165 
1166   rv = rtems_gpio_bsp_multi_read(bank, bitmask);
1167 
1168   RELEASE_LOCK(gpio_bank_state[bank].lock);
1169 
1170   return rv;
1171 }
1172 
1173 rtems_status_code rtems_gpio_set(uint32_t pin_number)
1174 {
1175   rtems_status_code sc;
1176   uint32_t bank;
1177   uint32_t pin;
1178 
1179   if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
1180     return RTEMS_INVALID_ID;
1181   }
1182 
1183   bank = BANK_NUMBER(pin_number);
1184   pin = PIN_NUMBER(pin_number);
1185 
1186   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1187 
1188   if (
1189       gpio_pin_state[pin_number].pin_function != DIGITAL_OUTPUT ||
1190       gpio_pin_state[pin_number].on_group
1191   ) {
1192     RELEASE_LOCK(gpio_bank_state[bank].lock);
1193 
1194 #if defined(DEBUG)
1195     printk("Can only set digital output pins\n");
1196 #endif
1197 
1198     return RTEMS_NOT_CONFIGURED;
1199   }
1200 
1201   if ( gpio_pin_state[pin_number].logic_invert ) {
1202     sc = rtems_gpio_bsp_clear(bank, pin);
1203   }
1204   else {
1205     sc = rtems_gpio_bsp_set(bank, pin);
1206   }
1207 
1208   RELEASE_LOCK(gpio_bank_state[bank].lock);
1209 
1210   return sc;
1211 }
1212 
1213 rtems_status_code rtems_gpio_clear(uint32_t pin_number)
1214 {
1215   rtems_status_code sc;
1216   uint32_t bank;
1217   uint32_t pin;
1218 
1219   if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
1220     return RTEMS_INVALID_ID;
1221   }
1222 
1223   bank = BANK_NUMBER(pin_number);
1224   pin = PIN_NUMBER(pin_number);
1225 
1226   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1227 
1228   if (
1229       gpio_pin_state[pin_number].pin_function != DIGITAL_OUTPUT ||
1230       gpio_pin_state[pin_number].on_group
1231   ) {
1232     RELEASE_LOCK(gpio_bank_state[bank].lock);
1233 
1234 #if defined(DEBUG)
1235     printk("Can only clear digital output pins\n");
1236 #endif
1237 
1238     return RTEMS_NOT_CONFIGURED;
1239   }
1240 
1241   if ( gpio_pin_state[pin_number].logic_invert ) {
1242     sc = rtems_gpio_bsp_set(bank, pin);
1243   }
1244   else {
1245     sc = rtems_gpio_bsp_clear(bank, pin);
1246   }
1247 
1248   RELEASE_LOCK(gpio_bank_state[bank].lock);
1249 
1250   return sc;
1251 }
1252 
1253 int rtems_gpio_get_value(uint32_t pin_number)
1254 {
1255   uint32_t bank;
1256   uint32_t pin;
1257   uint32_t rv;
1258 
1259   if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
1260     return -1;
1261   }
1262 
1263   bank = BANK_NUMBER(pin_number);
1264   pin = PIN_NUMBER(pin_number);
1265 
1266   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1267 
1268   if (
1269       gpio_pin_state[pin_number].pin_function != DIGITAL_INPUT ||
1270       gpio_pin_state[pin_number].on_group
1271   ) {
1272     RELEASE_LOCK(gpio_bank_state[bank].lock);
1273 
1274 #if defined(DEBUG)
1275     printk("Can only read digital input pins\n");
1276 #endif
1277 
1278     return -1;
1279   }
1280 
1281   rv = rtems_gpio_bsp_get_value(bank, pin);
1282 
1283   if ( rv == GPIO_INPUT_ERROR ) {
1284     RELEASE_LOCK(gpio_bank_state[bank].lock);
1285 
1286     return -1;
1287   }
1288 
1289   if ( gpio_pin_state[pin_number].logic_invert ) {
1290     RELEASE_LOCK(gpio_bank_state[bank].lock);
1291 
1292     return !rv;
1293   }
1294 
1295   RELEASE_LOCK(gpio_bank_state[bank].lock);
1296 
1297   return rv > 0;
1298 }
1299 
1300 rtems_status_code rtems_gpio_request_pin(
1301   uint32_t pin_number,
1302   rtems_gpio_function function,
1303   bool output_enabled,
1304   bool logic_invert,
1305   void *bsp_specific
1306 ) {
1307   rtems_gpio_specific_data *bsp_data;
1308   rtems_status_code sc = RTEMS_SUCCESSFUL;
1309   uint32_t bank;
1310   uint32_t pin;
1311 
1312   if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
1313     return RTEMS_INVALID_ID;
1314   }
1315 
1316   bank = BANK_NUMBER(pin_number);
1317   pin = PIN_NUMBER(pin_number);
1318 
1319   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1320 
1321   /* If the pin is already being used returns with an error. */
1322   if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {
1323     RELEASE_LOCK(gpio_bank_state[bank].lock);
1324 
1325     return RTEMS_RESOURCE_IN_USE;
1326   }
1327 
1328   switch ( function ) {
1329     case DIGITAL_INPUT:
1330       sc = rtems_gpio_bsp_select_input(bank, pin, bsp_specific);
1331       break;
1332     case DIGITAL_OUTPUT:
1333       sc = rtems_gpio_bsp_select_output(bank, pin, bsp_specific);
1334       break;
1335     case BSP_SPECIFIC:
1336       bsp_data = (rtems_gpio_specific_data *) bsp_specific;
1337 
1338       if ( bsp_data == NULL ) {
1339         RELEASE_LOCK(gpio_bank_state[bank].lock);
1340 
1341         return RTEMS_UNSATISFIED;
1342       }
1343 
1344       sc = rtems_gpio_bsp_select_specific_io(
1345              bank,
1346              pin,
1347              bsp_data->io_function,
1348              bsp_data->pin_data
1349            );
1350       break;
1351     case NOT_USED:
1352     default:
1353       RELEASE_LOCK(gpio_bank_state[bank].lock);
1354 
1355       return RTEMS_NOT_DEFINED;
1356   }
1357 
1358   if ( sc != RTEMS_SUCCESSFUL ) {
1359     RELEASE_LOCK(gpio_bank_state[bank].lock);
1360 
1361     return sc;
1362   }
1363 
1364   /* If the function was successfully assigned to the pin,
1365    * record that information on the gpio_pin_state structure. */
1366   gpio_pin_state[pin_number].pin_function = function;
1367   gpio_pin_state[pin_number].logic_invert = logic_invert;
1368 
1369   if ( function == DIGITAL_OUTPUT ) {
1370     if ( output_enabled == true ) {
1371       sc = rtems_gpio_bsp_set(bank, pin);
1372     }
1373     else {
1374       sc = rtems_gpio_bsp_clear(bank, pin);
1375     }
1376   }
1377 
1378   RELEASE_LOCK(gpio_bank_state[bank].lock);
1379 
1380   return sc;
1381 }
1382 
1383 rtems_status_code rtems_gpio_resistor_mode(
1384   uint32_t pin_number,
1385   rtems_gpio_pull_mode mode
1386 ) {
1387   rtems_status_code sc;
1388   uint32_t bank;
1389   uint32_t pin;
1390 
1391   if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
1392     return RTEMS_INVALID_ID;
1393   }
1394 
1395   bank = BANK_NUMBER(pin_number);
1396   pin = PIN_NUMBER(pin_number);
1397 
1398   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1399 
1400   /* If the desired actuation mode is already set, silently exits.
1401    * The NO_PULL_RESISTOR is a special case, as some platforms have
1402    * pull-up resistors enabled on startup, so this state may have to
1403    * be reinforced in the hardware. */
1404   if (
1405       gpio_pin_state[pin_number].resistor_mode == mode &&
1406       mode != NO_PULL_RESISTOR
1407   ) {
1408     RELEASE_LOCK(gpio_bank_state[bank].lock);
1409 
1410     return RTEMS_SUCCESSFUL;
1411   }
1412 
1413   sc = rtems_gpio_bsp_set_resistor_mode(bank, pin, mode);
1414 
1415   if ( sc != RTEMS_SUCCESSFUL ) {
1416     RELEASE_LOCK(gpio_bank_state[bank].lock);
1417 
1418     return sc;
1419   }
1420 
1421   gpio_pin_state[pin_number].resistor_mode = mode;
1422 
1423   RELEASE_LOCK(gpio_bank_state[bank].lock);
1424 
1425   return RTEMS_SUCCESSFUL;
1426 }
1427 
1428 rtems_status_code rtems_gpio_release_pin(uint32_t pin_number)
1429 {
1430   gpio_pin_interrupt_state *interrupt_state;
1431   rtems_status_code sc;
1432   uint32_t bank;
1433 
1434   if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
1435     return RTEMS_INVALID_ID;
1436   }
1437 
1438   bank = BANK_NUMBER(pin_number);
1439 
1440   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1441 
1442   interrupt_state = gpio_pin_state[pin_number].interrupt_state;
1443 
1444   /* If the pin has an enabled interrupt then remove the handler(s)
1445    * and disable interrupts on that pin. */
1446   if ( interrupt_state != NULL ) {
1447     sc = rtems_gpio_disable_interrupt(pin_number);
1448 
1449     if ( sc != RTEMS_SUCCESSFUL ) {
1450       RELEASE_LOCK(gpio_bank_state[bank].lock);
1451 
1452       return sc;
1453     }
1454   }
1455 
1456   gpio_pin_state[pin_number].pin_function = NOT_USED;
1457   gpio_pin_state[pin_number].resistor_mode = NO_PULL_RESISTOR;
1458   gpio_pin_state[pin_number].logic_invert = false;
1459   gpio_pin_state[pin_number].on_group = false;
1460 
1461   RELEASE_LOCK(gpio_bank_state[bank].lock);
1462 
1463   return RTEMS_SUCCESSFUL;
1464 }
1465 
1466 rtems_status_code rtems_gpio_release_configuration(
1467   const rtems_gpio_pin_conf *conf
1468 ) {
1469   if ( conf == NULL ) {
1470     return RTEMS_UNSATISFIED;
1471   }
1472 
1473   return rtems_gpio_release_pin(conf->pin_number);
1474 }
1475 
1476 rtems_status_code rtems_gpio_release_multiple_pins(
1477   const rtems_gpio_pin_conf *pins,
1478   uint32_t pin_count
1479 ) {
1480   rtems_status_code sc;
1481   uint32_t i;
1482 
1483   if ( pins == NULL ) {
1484     return RTEMS_UNSATISFIED;
1485   }
1486 
1487   for ( i = 0; i < pin_count; ++i ) {
1488     sc = rtems_gpio_release_pin(pins[i].pin_number);
1489 
1490     if ( sc != RTEMS_SUCCESSFUL ) {
1491       return sc;
1492     }
1493   }
1494 
1495   return RTEMS_SUCCESSFUL;
1496 }
1497 
1498 rtems_status_code rtems_gpio_release_pin_group(
1499   rtems_gpio_group *group
1500 ) {
1501   rtems_status_code sc;
1502   uint8_t i;
1503 
1504   ACQUIRE_LOCK(group->group_lock);
1505 
1506   sc = rtems_semaphore_flush(group->group_lock);
1507 
1508   if ( sc != RTEMS_SUCCESSFUL ) {
1509     RELEASE_LOCK(group->group_lock);
1510 
1511     return sc;
1512   }
1513 
1514   RELEASE_LOCK(group->group_lock);
1515 
1516   /* Deletes the group lock. */
1517   sc = rtems_semaphore_delete(group->group_lock);
1518 
1519   if ( sc != RTEMS_SUCCESSFUL ) {
1520     return sc;
1521   }
1522 
1523   /* Pin releasing. */
1524   for ( i = 0; i < group->input_count; ++i ) {
1525     sc = rtems_gpio_release_pin(group->digital_inputs[i]);
1526 
1527     if ( sc != RTEMS_SUCCESSFUL ) {
1528       return sc;
1529     }
1530   }
1531 
1532   if ( group->input_count > 0 ) {
1533     free(group->digital_inputs);
1534   }
1535 
1536   for ( i = 0; i < group->output_count; ++i ) {
1537     sc = rtems_gpio_release_pin(group->digital_outputs[i]);
1538 
1539     if ( sc != RTEMS_SUCCESSFUL ) {
1540       return sc;
1541     }
1542   }
1543 
1544   if ( group->output_count > 0 ) {
1545     free(group->digital_outputs);
1546   }
1547 
1548   for ( i = 0; i < group->bsp_specific_pin_count; ++i ) {
1549     sc = rtems_gpio_release_pin(group->bsp_speficifc_pins[i]);
1550 
1551     if ( sc != RTEMS_SUCCESSFUL ) {
1552       return sc;
1553     }
1554   }
1555 
1556   if ( group->bsp_specific_pin_count > 0 ) {
1557     free(group->bsp_speficifc_pins);
1558   }
1559 
1560   rtems_chain_extract(&group->node);
1561 
1562   free(group);
1563 
1564   return RTEMS_SUCCESSFUL;
1565 }
1566 
1567 rtems_status_code rtems_gpio_debounce_switch(uint32_t pin_number, int ticks)
1568 {
1569   gpio_pin_interrupt_state *interrupt_state;
1570   uint32_t bank;
1571 
1572   if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
1573     return RTEMS_INVALID_ID;
1574   }
1575 
1576   bank = BANK_NUMBER(pin_number);
1577 
1578   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1579 
1580   interrupt_state = gpio_pin_state[pin_number].interrupt_state;
1581 
1582   /* If no interrupt configuration is set for this pin, or if the pin is
1583    * not set as a digital input, or the pin in on a group. */
1584   if (
1585       interrupt_state == NULL ||
1586       gpio_pin_state[pin_number].pin_function != DIGITAL_INPUT ||
1587       gpio_pin_state[pin_number].on_group
1588   ) {
1589     RELEASE_LOCK(gpio_bank_state[bank].lock);
1590 
1591     return RTEMS_NOT_CONFIGURED;
1592   }
1593 
1594   interrupt_state->debouncing_tick_count = ticks;
1595   interrupt_state->last_isr_tick = 0;
1596 
1597   RELEASE_LOCK(gpio_bank_state[bank].lock);
1598 
1599   return RTEMS_SUCCESSFUL;
1600 }
1601 
1602 rtems_status_code rtems_gpio_interrupt_handler_install(
1603   uint32_t pin_number,
1604   rtems_gpio_irq_state (*handler) (void *arg),
1605   void *arg
1606 ) {
1607   gpio_pin_interrupt_state *interrupt_state;
1608   gpio_handler_node *isr_node;
1609   uint32_t bank;
1610 
1611   if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
1612     return RTEMS_INVALID_ID;
1613   }
1614 
1615   bank = BANK_NUMBER(pin_number);
1616 
1617   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1618 
1619   interrupt_state = gpio_pin_state[pin_number].interrupt_state;
1620 
1621   /* If no interrupt configuration is set for this pin. */
1622    if ( interrupt_state == NULL ) {
1623     RELEASE_LOCK(gpio_bank_state[bank].lock);
1624 
1625     return RTEMS_NOT_CONFIGURED;
1626   }
1627 
1628   /* If the current pin has no interrupt enabled
1629    * then it does not need an handler. */
1630   if ( interrupt_state->active_interrupt == NONE ) {
1631     RELEASE_LOCK(gpio_bank_state[bank].lock);
1632 
1633     return RTEMS_NOT_CONFIGURED;
1634   }
1635   /* If the pin already has an enabled interrupt but the installed handler
1636    * is set as unique. */
1637   else if (
1638            interrupt_state->handler_flag == UNIQUE_HANDLER &&
1639            !rtems_chain_is_empty(&interrupt_state->handler_chain)
1640   ) {
1641     RELEASE_LOCK(gpio_bank_state[bank].lock);
1642 
1643     return RTEMS_TOO_MANY;
1644   }
1645 
1646   /* Update the pin's ISR list. */
1647   isr_node = (gpio_handler_node *) malloc(sizeof(gpio_handler_node));
1648 
1649   if ( isr_node == NULL ) {
1650     RELEASE_LOCK(gpio_bank_state[bank].lock);
1651 
1652     return RTEMS_NO_MEMORY;
1653   }
1654 
1655   isr_node->handler = handler;
1656   isr_node->arg = arg;
1657 
1658   rtems_chain_append(&interrupt_state->handler_chain, &isr_node->node);
1659 
1660   RELEASE_LOCK(gpio_bank_state[bank].lock);
1661 
1662   return RTEMS_SUCCESSFUL;
1663 }
1664 
1665 rtems_status_code rtems_gpio_enable_interrupt(
1666   uint32_t pin_number,
1667   rtems_gpio_interrupt interrupt,
1668   rtems_gpio_handler_flag flag,
1669   bool threaded_handling,
1670   rtems_gpio_irq_state (*handler) (void *arg),
1671   void *arg
1672 ) {
1673   gpio_pin_interrupt_state *interrupt_state;
1674   rtems_vector_number vector;
1675   rtems_status_code sc;
1676   uint32_t bank;
1677   uint32_t pin;
1678 
1679   if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
1680     return RTEMS_INVALID_ID;
1681   }
1682 
1683   bank = BANK_NUMBER(pin_number);
1684   pin = PIN_NUMBER(pin_number);
1685 
1686   vector = rtems_gpio_bsp_get_vector(bank);
1687 
1688   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1689 
1690   if (
1691       gpio_pin_state[pin_number].pin_function != DIGITAL_INPUT ||
1692       gpio_pin_state[pin_number].on_group
1693   ) {
1694     RELEASE_LOCK(gpio_bank_state[bank].lock);
1695 
1696     return RTEMS_NOT_CONFIGURED;
1697   }
1698 
1699   /* If the bank already has at least one interrupt enabled on a pin,
1700    * then new interrupts on this bank must follow the current
1701    * threading policy. */
1702   if (
1703       gpio_bank_state[bank].interrupt_counter > 0 &&
1704       gpio_bank_state[bank].threaded_interrupts != threaded_handling
1705   ) {
1706     RELEASE_LOCK(gpio_bank_state[bank].lock);
1707 
1708     return RTEMS_RESOURCE_IN_USE;
1709   }
1710 
1711   /* If an interrupt configuration is already in place for this pin. */
1712   if ( gpio_pin_state[pin_number].interrupt_state != NULL ) {
1713     RELEASE_LOCK(gpio_bank_state[bank].lock);
1714 
1715     return RTEMS_RESOURCE_IN_USE;
1716   }
1717 
1718   gpio_pin_state[pin_number].interrupt_state =
1719     (gpio_pin_interrupt_state *) malloc(sizeof(gpio_pin_interrupt_state));
1720 
1721   if ( gpio_pin_state[pin_number].interrupt_state == NULL ) {
1722     return RTEMS_NO_MEMORY;
1723   }
1724 
1725   interrupt_state = gpio_pin_state[pin_number].interrupt_state;
1726   interrupt_state->active_interrupt = NONE;
1727   interrupt_state->debouncing_tick_count = 0;
1728   interrupt_state->last_isr_tick = 0;
1729 
1730   rtems_chain_initialize_empty( &interrupt_state->handler_chain );
1731 
1732   interrupt_state->active_interrupt = interrupt;
1733   interrupt_state->handler_flag = flag;
1734 
1735   /* Installs the interrupt handler on the GPIO pin
1736    * tracking structure. */
1737   sc = rtems_gpio_interrupt_handler_install(pin_number, handler, arg);
1738 
1739   if ( sc != RTEMS_SUCCESSFUL ) {
1740     free(interrupt_state);
1741     gpio_pin_state[pin_number].interrupt_state = NULL;
1742     RELEASE_LOCK(gpio_bank_state[bank].lock);
1743 
1744     return RTEMS_UNSATISFIED;
1745   }
1746 
1747   if ( threaded_handling ) {
1748     if (
1749         _Atomic_Load_uint(&threaded_interrupt_counter, ATOMIC_ORDER_RELAXED) == 0
1750     ) {
1751       sc = rtems_interrupt_server_initialize(
1752              INTERRUPT_SERVER_PRIORITY,
1753              INTERRUPT_SERVER_STACK_SIZE,
1754              INTERRUPT_SERVER_MODES,
1755              INTERRUPT_SERVER_ATTRIBUTES,
1756              NULL
1757            );
1758 
1759       if ( sc != RTEMS_SUCCESSFUL ) {
1760         RELEASE_LOCK(gpio_bank_state[bank].lock);
1761 
1762         return RTEMS_UNSATISFIED;
1763       }
1764     }
1765 
1766     if ( gpio_bank_state[bank].interrupt_counter == 0 ) {
1767       sc = rtems_interrupt_server_handler_install(
1768              RTEMS_ID_NONE,
1769              vector,
1770              "GPIO_HANDLER",
1771              RTEMS_INTERRUPT_UNIQUE,
1772              (rtems_interrupt_handler) generic_bank_isr,
1773              &gpio_bank_state[bank].bank_number
1774            );
1775 
1776       if ( sc != RTEMS_SUCCESSFUL ) {
1777         RELEASE_LOCK(gpio_bank_state[bank].lock);
1778 
1779         return RTEMS_UNSATISFIED;
1780       }
1781 
1782       _Atomic_Fetch_add_uint(
1783         &threaded_interrupt_counter,
1784         1,
1785         ATOMIC_ORDER_RELAXED
1786       );
1787     }
1788   }
1789   else if ( gpio_bank_state[bank].interrupt_counter == 0 ) {
1790     sc = rtems_interrupt_handler_install(
1791            vector,
1792            "GPIO_HANDLER",
1793            RTEMS_INTERRUPT_UNIQUE,
1794            (rtems_interrupt_handler) generic_bank_isr,
1795            &gpio_bank_state[bank].bank_number
1796          );
1797 
1798     if ( sc != RTEMS_SUCCESSFUL ) {
1799       RELEASE_LOCK(gpio_bank_state[bank].lock);
1800 
1801       return RTEMS_UNSATISFIED;
1802     }
1803   }
1804 
1805   sc = rtems_gpio_bsp_enable_interrupt(bank, pin, interrupt);
1806 
1807   if ( sc != RTEMS_SUCCESSFUL ) {
1808     RELEASE_LOCK(gpio_bank_state[bank].lock);
1809 
1810     return RTEMS_UNSATISFIED;
1811   }
1812 
1813   /* If this was the first interrupt enabled on this GPIO bank,
1814    * record the threading policy. */
1815   if ( gpio_bank_state[bank].interrupt_counter == 0 ) {
1816     gpio_bank_state[bank].threaded_interrupts = threaded_handling;
1817   }
1818 
1819   ++gpio_bank_state[bank].interrupt_counter;
1820 
1821   RELEASE_LOCK(gpio_bank_state[bank].lock);
1822 
1823   return RTEMS_SUCCESSFUL;
1824 }
1825 
1826 rtems_status_code rtems_gpio_interrupt_handler_remove(
1827   uint32_t pin_number,
1828   rtems_gpio_irq_state (*handler) (void *arg),
1829   void *arg
1830 ) {
1831   gpio_pin_interrupt_state *interrupt_state;
1832   rtems_chain_control *handler_list;
1833   rtems_chain_node *node;
1834   rtems_chain_node *next_node;
1835   gpio_handler_node *isr_node;
1836   uint32_t bank;
1837 
1838   if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
1839     return RTEMS_INVALID_ID;
1840   }
1841 
1842   bank = BANK_NUMBER(pin_number);
1843 
1844   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1845 
1846   interrupt_state = gpio_pin_state[pin_number].interrupt_state;
1847 
1848   /* If no interrupt configuration is set for this pin. */
1849   if ( interrupt_state == NULL ) {
1850     RELEASE_LOCK(gpio_bank_state[bank].lock);
1851 
1852     return RTEMS_NOT_CONFIGURED;
1853   }
1854 
1855   handler_list = &interrupt_state->handler_chain;
1856 
1857   node = rtems_chain_first(handler_list);
1858 
1859   /* If the first node is also the last handler for this pin, disables
1860    * interrupts on this pin as there will be no handler to handle it.
1861    * This also removes the remaining handler. */
1862   if ( rtems_chain_is_last(node) ) {
1863     RELEASE_LOCK(gpio_bank_state[bank].lock);
1864 
1865     return rtems_gpio_disable_interrupt(pin_number);
1866   }
1867 
1868   /* Iterate the ISR list. */
1869   while ( !rtems_chain_is_tail(handler_list, node) ) {
1870     isr_node = (gpio_handler_node *) node;
1871 
1872     next_node = node->next;
1873 
1874     if ( isr_node->handler == handler && isr_node->arg == arg ) {
1875       rtems_chain_extract(node);
1876 
1877       break;
1878     }
1879 
1880     node = next_node;
1881   }
1882 
1883   RELEASE_LOCK(gpio_bank_state[bank].lock);
1884 
1885   return RTEMS_SUCCESSFUL;
1886 }
1887 
1888 rtems_status_code rtems_gpio_disable_interrupt(uint32_t pin_number)
1889 {
1890   gpio_pin_interrupt_state *interrupt_state;
1891   rtems_chain_control *handler_list;
1892   rtems_chain_node *node;
1893   rtems_chain_node *next_node;
1894   rtems_vector_number vector;
1895   rtems_status_code sc;
1896   uint32_t bank;
1897   uint32_t pin;
1898 
1899   if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
1900     return RTEMS_INVALID_ID;
1901   }
1902 
1903   bank = BANK_NUMBER(pin_number);
1904   pin = PIN_NUMBER(pin_number);
1905 
1906   vector = rtems_gpio_bsp_get_vector(bank);
1907 
1908   ACQUIRE_LOCK(gpio_bank_state[bank].lock);
1909 
1910   interrupt_state = gpio_pin_state[pin_number].interrupt_state;
1911 
1912   /* If no interrupt configuration is set for this pin. */
1913   if ( interrupt_state == NULL ) {
1914     RELEASE_LOCK(gpio_bank_state[bank].lock);
1915 
1916     return RTEMS_NOT_CONFIGURED;
1917   }
1918 
1919   sc = rtems_gpio_bsp_disable_interrupt(bank, pin, interrupt_state->active_interrupt);
1920 
1921   if ( sc != RTEMS_SUCCESSFUL ) {
1922     RELEASE_LOCK(gpio_bank_state[bank].lock);
1923 
1924     return RTEMS_UNSATISFIED;
1925   }
1926 
1927   interrupt_state->active_interrupt = NONE;
1928 
1929   handler_list = &interrupt_state->handler_chain;
1930 
1931   node = rtems_chain_first(handler_list);
1932 
1933   /* Iterate the ISR list. */
1934   while ( !rtems_chain_is_tail(handler_list, node) ) {
1935     next_node = node->next;
1936 
1937     rtems_chain_extract(node);
1938 
1939     node = next_node;
1940   }
1941 
1942   /* If this is the last GPIO interrupt are left in this bank,
1943    * removes the handler. */
1944   if ( gpio_bank_state[bank].interrupt_counter == 1 ) {
1945     if ( gpio_bank_state[bank].threaded_interrupts ) {
1946       sc = rtems_interrupt_server_handler_remove(
1947              RTEMS_ID_NONE,
1948              vector,
1949              (rtems_interrupt_handler) generic_bank_isr,
1950              &gpio_bank_state[bank].bank_number
1951            );
1952     }
1953     else {
1954       sc = rtems_interrupt_handler_remove(
1955              vector,
1956              (rtems_interrupt_handler) generic_bank_isr,
1957              &gpio_bank_state[bank].bank_number
1958            );
1959     }
1960 
1961     if ( sc != RTEMS_SUCCESSFUL ) {
1962       RELEASE_LOCK(gpio_bank_state[bank].lock);
1963 
1964       return RTEMS_UNSATISFIED;
1965     }
1966   }
1967 
1968   /* Free the pin's interrupt state structure. */
1969   free(interrupt_state);
1970 
1971   --gpio_bank_state[bank].interrupt_counter;
1972 
1973   if ( gpio_bank_state[bank].threaded_interrupts ) {
1974     _Atomic_Fetch_sub_uint(&threaded_interrupt_counter, 1, ATOMIC_ORDER_RELAXED);
1975   }
1976 
1977   RELEASE_LOCK(gpio_bank_state[bank].lock);
1978 
1979   return RTEMS_SUCCESSFUL;
1980 }