Back to home page

LXR

 
 

    


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

0001 /**
0002  * @file
0003  *
0004  * @ingroup raspberrypi_gpio
0005  *
0006  * @brief Support for the Raspberry PI GPIO.
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 <bsp.h>
0018 #include <bsp/raspberrypi.h>
0019 #include <bsp/irq-generic.h>
0020 #include <bsp/gpio.h>
0021 #include <bsp/rpi-gpio.h>
0022 
0023 #include <stdlib.h>
0024 
0025 RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_gpio_bsp_lock, "rtems_gpio_bsp_lock" );
0026 
0027 /* Calculates a bitmask to assign an alternate function to a given pin. */
0028 #define SELECT_PIN_FUNCTION(fn, pn) (fn << ((pn % 10) * 3))
0029 
0030 rtems_gpio_specific_data alt_func_def[] = {
0031   {.io_function = RPI_ALT_FUNC_0, .pin_data = NULL},
0032   {.io_function = RPI_ALT_FUNC_1, .pin_data = NULL},
0033   {.io_function = RPI_ALT_FUNC_2, .pin_data = NULL},
0034   {.io_function = RPI_ALT_FUNC_3, .pin_data = NULL},
0035   {.io_function = RPI_ALT_FUNC_4, .pin_data = NULL},
0036   {.io_function = RPI_ALT_FUNC_5, .pin_data = NULL}
0037 };
0038 
0039 /* Raspberry Pi 1 Revision 2 gpio interface definitions. */
0040 #include "gpio-interfaces-pi1-rev2.c"
0041 
0042 /* Waits a number of CPU cycles. */
0043 static void arm_delay(uint8_t cycles)
0044 {
0045   uint8_t i;
0046 
0047   for ( i = 0; i < cycles; ++i ) {
0048     asm volatile("nop");
0049   }
0050 }
0051 
0052 static rtems_status_code rpi_select_pin_function(
0053   uint32_t bank,
0054   uint32_t pin,
0055   uint32_t type
0056 ) {
0057   /* Calculate the pin function select register address. */
0058   volatile uint32_t *pin_addr = (uint32_t *) BCM2835_GPIO_REGS_BASE +
0059                                              (pin / 10);
0060   uint32_t reg_old;
0061   uint32_t reg_new;
0062   rtems_interrupt_lock_context lock_context;
0063 
0064   rtems_interrupt_lock_acquire(&rtems_gpio_bsp_lock, &lock_context);
0065   reg_new = reg_old = *pin_addr;
0066   reg_new &= ~SELECT_PIN_FUNCTION(RPI_ALT_FUNC_MASK, pin);
0067   reg_new |= SELECT_PIN_FUNCTION(type, pin);
0068   *pin_addr = reg_new;
0069   rtems_interrupt_lock_release(&rtems_gpio_bsp_lock, &lock_context);
0070 
0071   return RTEMS_SUCCESSFUL;
0072 }
0073 
0074 rtems_status_code rtems_gpio_bsp_multi_set(uint32_t bank, uint32_t bitmask)
0075 {
0076   BCM2835_REG(BCM2835_GPIO_GPSET0) = bitmask;
0077 
0078   return RTEMS_SUCCESSFUL;
0079 }
0080 
0081 rtems_status_code rtems_gpio_bsp_multi_clear(uint32_t bank, uint32_t bitmask)
0082 {
0083   BCM2835_REG(BCM2835_GPIO_GPCLR0) = bitmask;
0084 
0085   return RTEMS_SUCCESSFUL;
0086 }
0087 
0088 uint32_t rtems_gpio_bsp_multi_read(uint32_t bank, uint32_t bitmask)
0089 {
0090   return (BCM2835_REG(BCM2835_GPIO_GPLEV0) & bitmask);
0091 }
0092 
0093 rtems_status_code rtems_gpio_bsp_set(uint32_t bank, uint32_t pin)
0094 {
0095   BCM2835_REG(BCM2835_GPIO_GPSET0) = (1 << pin);
0096 
0097   return RTEMS_SUCCESSFUL;
0098 }
0099 
0100 rtems_status_code rtems_gpio_bsp_clear(uint32_t bank, uint32_t pin)
0101 {
0102   BCM2835_REG(BCM2835_GPIO_GPCLR0) = (1 << pin);
0103 
0104   return RTEMS_SUCCESSFUL;
0105 }
0106 
0107 uint32_t rtems_gpio_bsp_get_value(uint32_t bank, uint32_t pin)
0108 {
0109   return (BCM2835_REG(BCM2835_GPIO_GPLEV0) & (1 << pin));
0110 }
0111 
0112 rtems_status_code rtems_gpio_bsp_select_input(
0113   uint32_t bank,
0114   uint32_t pin,
0115   void *bsp_specific
0116 ) {
0117   return rpi_select_pin_function(bank, pin, RPI_DIGITAL_IN);
0118 }
0119 
0120 rtems_status_code rtems_gpio_bsp_select_output(
0121   uint32_t bank,
0122   uint32_t pin,
0123   void *bsp_specific
0124 ) {
0125   return rpi_select_pin_function(bank, pin, RPI_DIGITAL_OUT);
0126 }
0127 
0128 rtems_status_code rtems_gpio_bsp_select_specific_io(
0129   uint32_t bank,
0130   uint32_t pin,
0131   uint32_t function,
0132   void *pin_data
0133 ) {
0134   return rpi_select_pin_function(bank, pin, function);
0135 }
0136 
0137 rtems_status_code rtems_gpio_bsp_set_resistor_mode(
0138   uint32_t bank,
0139   uint32_t pin,
0140   rtems_gpio_pull_mode mode
0141 ) {
0142   /* Set control signal. */
0143   switch ( mode ) {
0144     case PULL_UP:
0145       BCM2835_REG(BCM2835_GPIO_GPPUD) = (1 << 1);
0146       break;
0147     case PULL_DOWN:
0148       BCM2835_REG(BCM2835_GPIO_GPPUD) = (1 << 0);
0149       break;
0150     case NO_PULL_RESISTOR:
0151       BCM2835_REG(BCM2835_GPIO_GPPUD) = 0;
0152       break;
0153     default:
0154       return RTEMS_UNSATISFIED;
0155   }
0156 
0157   /* Wait 150 cyles, as per BCM2835 documentation. */
0158   arm_delay(150);
0159 
0160   /* Setup clock for the control signal. */
0161   BCM2835_REG(BCM2835_GPIO_GPPUDCLK0) = (1 << pin);
0162 
0163   arm_delay(150);
0164 
0165   /* Remove the control signal. */
0166   BCM2835_REG(BCM2835_GPIO_GPPUD) = 0;
0167 
0168   /* Remove the clock. */
0169   BCM2835_REG(BCM2835_GPIO_GPPUDCLK0) = 0;
0170 
0171   return RTEMS_SUCCESSFUL;
0172 }
0173 
0174 rtems_vector_number rtems_gpio_bsp_get_vector(uint32_t bank)
0175 {
0176   return BCM2835_IRQ_ID_GPIO_0;
0177 }
0178 
0179 uint32_t rtems_gpio_bsp_interrupt_line(rtems_vector_number vector)
0180 {
0181   uint32_t event_status;
0182 
0183   /* Retrieve the interrupt event status. */
0184   event_status = BCM2835_REG(BCM2835_GPIO_GPEDS0);
0185 
0186   /* Clear the interrupt line. */
0187   BCM2835_REG(BCM2835_GPIO_GPEDS0) = event_status;
0188 
0189   return event_status;
0190 }
0191 
0192 rtems_status_code rtems_gpio_bsp_enable_interrupt(
0193   uint32_t bank,
0194   uint32_t pin,
0195   rtems_gpio_interrupt interrupt
0196 ) {
0197   switch ( interrupt ) {
0198     case FALLING_EDGE:
0199       /* Enables asynchronous falling edge detection. */
0200       BCM2835_REG(BCM2835_GPIO_GPAFEN0) |= (1 << pin);
0201       break;
0202     case RISING_EDGE:
0203       /* Enables asynchronous rising edge detection. */
0204       BCM2835_REG(BCM2835_GPIO_GPAREN0) |= (1 << pin);
0205       break;
0206     case BOTH_EDGES:
0207       /* Enables asynchronous falling edge detection. */
0208       BCM2835_REG(BCM2835_GPIO_GPAFEN0) |= (1 << pin);
0209 
0210       /* Enables asynchronous rising edge detection. */
0211       BCM2835_REG(BCM2835_GPIO_GPAREN0) |= (1 << pin);
0212       break;
0213     case LOW_LEVEL:
0214       /* Enables pin low level detection. */
0215       BCM2835_REG(BCM2835_GPIO_GPLEN0) |= (1 << pin);
0216       break;
0217     case HIGH_LEVEL:
0218       /* Enables pin high level detection. */
0219       BCM2835_REG(BCM2835_GPIO_GPHEN0) |= (1 << pin);
0220       break;
0221     case BOTH_LEVELS:
0222       /* Enables pin low level detection. */
0223       BCM2835_REG(BCM2835_GPIO_GPLEN0) |= (1 << pin);
0224 
0225       /* Enables pin high level detection. */
0226       BCM2835_REG(BCM2835_GPIO_GPHEN0) |= (1 << pin);
0227       break;
0228     case NONE:
0229     default:
0230       return RTEMS_UNSATISFIED;
0231   }
0232 
0233   return RTEMS_SUCCESSFUL;
0234 }
0235 
0236 rtems_status_code rtems_gpio_bsp_disable_interrupt(
0237   uint32_t bank,
0238   uint32_t pin,
0239   rtems_gpio_interrupt interrupt
0240 ) {
0241   switch ( interrupt ) {
0242     case FALLING_EDGE:
0243       /* Disables asynchronous falling edge detection. */
0244       BCM2835_REG(BCM2835_GPIO_GPAFEN0) &= ~(1 << pin);
0245       break;
0246     case RISING_EDGE:
0247       /* Disables asynchronous rising edge detection. */
0248       BCM2835_REG(BCM2835_GPIO_GPAREN0) &= ~(1 << pin);
0249       break;
0250     case BOTH_EDGES:
0251       /* Disables asynchronous falling edge detection. */
0252       BCM2835_REG(BCM2835_GPIO_GPAFEN0) &= ~(1 << pin);
0253 
0254       /* Disables asynchronous rising edge detection. */
0255       BCM2835_REG(BCM2835_GPIO_GPAREN0) &= ~(1 << pin);
0256       break;
0257     case LOW_LEVEL:
0258       /* Disables pin low level detection. */
0259       BCM2835_REG(BCM2835_GPIO_GPLEN0) &= ~(1 << pin);
0260       break;
0261     case HIGH_LEVEL:
0262       /* Disables pin high level detection. */
0263       BCM2835_REG(BCM2835_GPIO_GPHEN0) &= ~(1 << pin);
0264       break;
0265     case BOTH_LEVELS:
0266       /* Disables pin low level detection. */
0267       BCM2835_REG(BCM2835_GPIO_GPLEN0) &= ~(1 << pin);
0268 
0269       /* Disables pin high level detection. */
0270       BCM2835_REG(BCM2835_GPIO_GPHEN0) &= ~(1 << pin);
0271       break;
0272     case NONE:
0273     default:
0274       return RTEMS_UNSATISFIED;
0275   }
0276 
0277   return RTEMS_SUCCESSFUL;
0278 }
0279 
0280 rtems_status_code rpi_gpio_select_jtag(void)
0281 {
0282   return rtems_gpio_multi_select(jtag_config, JTAG_PIN_COUNT);
0283 }
0284 
0285 rtems_status_code rpi_gpio_select_spi(void)
0286 {
0287   return rtems_gpio_multi_select(spi_config, SPI_PIN_COUNT);
0288 }
0289 
0290 rtems_status_code rpi_gpio_select_i2c(void)
0291 {
0292   return rtems_gpio_multi_select(i2c_config, I2C_PIN_COUNT);
0293 }
0294 
0295 rtems_status_code rtems_gpio_bsp_multi_select(
0296   rtems_gpio_multiple_pin_select *pins,
0297   uint32_t pin_count,
0298   uint32_t select_bank
0299 ) {
0300   uint32_t register_address;
0301   uint32_t select_register;
0302   uint8_t i;
0303 
0304   register_address = BCM2835_GPIO_REGS_BASE + (select_bank * 0x04);
0305 
0306   select_register = BCM2835_REG(register_address);
0307 
0308   for ( i = 0; i < pin_count; ++i ) {
0309     if ( pins[i].function == DIGITAL_INPUT ) {
0310       select_register &=
0311         ~SELECT_PIN_FUNCTION(RPI_DIGITAL_IN, pins[i].pin_number);
0312     }
0313     else if ( pins[i].function == DIGITAL_OUTPUT ) {
0314       select_register |=
0315         SELECT_PIN_FUNCTION(RPI_DIGITAL_OUT, pins[i].pin_number);
0316     }
0317     else { /* BSP_SPECIFIC function. */
0318       select_register |=
0319         SELECT_PIN_FUNCTION(pins[i].io_function, pins[i].pin_number);
0320     }
0321   }
0322 
0323   BCM2835_REG(register_address) = select_register;
0324 
0325   return RTEMS_SUCCESSFUL;
0326 }
0327 
0328 rtems_status_code rtems_gpio_bsp_specific_group_operation(
0329   uint32_t bank,
0330   uint32_t *pins,
0331   uint32_t pin_count,
0332   void *arg
0333 ) {
0334   return RTEMS_NOT_DEFINED;
0335 }