source: rtems/c/src/lib/libbsp/arm/raspberrypi/gpio/rpi-gpio.c @ 370c09a1

5
Last change on this file since 370c09a1 was 2502e26d, checked in by Ben Gras <beng@…>, on 11/03/15 at 17:00:15

Leftover gpio function rename

Rename rtems_bsp_select_specific_io to rtems_gpio_bsp_select_specific_io.

Should've gone with 5c337d7. Fixes #2456.

  • Property mode set to 100644
File size: 8.1 KB
Line 
1/**
2 * @file rpi-gpio.c
3 *
4 * @ingroup raspberrypi_gpio
5 *
6 * @brief Support for the Raspberry PI GPIO.
7 */
8
9/*
10 *  Copyright (c) 2014-2015 Andre Marques <andre.lousa.marques at gmail.com>
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#include <bsp/raspberrypi.h>
18#include <bsp/irq-generic.h>
19#include <bsp/gpio.h>
20#include <bsp/rpi-gpio.h>
21
22#include <stdlib.h>
23
24/* Calculates a bitmask to assign an alternate function to a given pin. */
25#define SELECT_PIN_FUNCTION(fn, pn) (fn << ((pn % 10) * 3))
26
27rtems_gpio_specific_data alt_func_def[] = {
28  {.io_function = RPI_ALT_FUNC_0, .pin_data = NULL},
29  {.io_function = RPI_ALT_FUNC_1, .pin_data = NULL},
30  {.io_function = RPI_ALT_FUNC_2, .pin_data = NULL},
31  {.io_function = RPI_ALT_FUNC_3, .pin_data = NULL},
32  {.io_function = RPI_ALT_FUNC_4, .pin_data = NULL},
33  {.io_function = RPI_ALT_FUNC_5, .pin_data = NULL}
34};
35
36/* Raspberry Pi 1 Revision 2 gpio interface definitions. */
37#include "gpio-interfaces-pi1-rev2.c"
38
39/* Waits a number of CPU cycles. */
40static void arm_delay(uint8_t cycles)
41{
42  uint8_t i;
43
44  for ( i = 0; i < cycles; ++i ) {
45    asm volatile("nop");
46  }
47}
48
49static rtems_status_code rpi_select_pin_function(
50  uint32_t bank,
51  uint32_t pin,
52  uint32_t type
53) {
54  /* Calculate the pin function select register address. */
55  volatile unsigned int *pin_addr = (unsigned int *) BCM2835_GPIO_REGS_BASE +
56                                    (pin / 10);
57
58  if ( type == RPI_DIGITAL_IN ) {
59    *(pin_addr) &= ~SELECT_PIN_FUNCTION(RPI_DIGITAL_IN, pin);
60  }
61  else {
62    *(pin_addr) |= SELECT_PIN_FUNCTION(type, pin);
63  }
64
65  return RTEMS_SUCCESSFUL;
66}
67
68rtems_status_code rtems_gpio_bsp_multi_set(uint32_t bank, uint32_t bitmask)
69{
70  BCM2835_REG(BCM2835_GPIO_GPSET0) = bitmask;
71
72  return RTEMS_SUCCESSFUL;
73}
74
75rtems_status_code rtems_gpio_bsp_multi_clear(uint32_t bank, uint32_t bitmask)
76{
77  BCM2835_REG(BCM2835_GPIO_GPCLR0) = bitmask;
78
79  return RTEMS_SUCCESSFUL;
80}
81
82uint32_t rtems_gpio_bsp_multi_read(uint32_t bank, uint32_t bitmask)
83{
84  return (BCM2835_REG(BCM2835_GPIO_GPLEV0) & bitmask);
85}
86
87rtems_status_code rtems_gpio_bsp_set(uint32_t bank, uint32_t pin)
88{
89  BCM2835_REG(BCM2835_GPIO_GPSET0) = (1 << pin);
90
91  return RTEMS_SUCCESSFUL;
92}
93
94rtems_status_code rtems_gpio_bsp_clear(uint32_t bank, uint32_t pin)
95{
96  BCM2835_REG(BCM2835_GPIO_GPCLR0) = (1 << pin);
97
98  return RTEMS_SUCCESSFUL;
99}
100
101uint32_t rtems_gpio_bsp_get_value(uint32_t bank, uint32_t pin)
102{
103  return (BCM2835_REG(BCM2835_GPIO_GPLEV0) & (1 << pin));
104}
105
106rtems_status_code rtems_gpio_bsp_select_input(
107  uint32_t bank,
108  uint32_t pin,
109  void *bsp_specific
110) {
111  return rpi_select_pin_function(bank, pin, RPI_DIGITAL_IN);
112}
113
114rtems_status_code rtems_gpio_bsp_select_output(
115  uint32_t bank,
116  uint32_t pin,
117  void *bsp_specific
118) {
119  return rpi_select_pin_function(bank, pin, RPI_DIGITAL_OUT);
120}
121
122rtems_status_code rtems_gpio_bsp_select_specific_io(
123  uint32_t bank,
124  uint32_t pin,
125  uint32_t function,
126  void *pin_data
127) {
128  return rpi_select_pin_function(bank, pin, function);
129}
130
131rtems_status_code rtems_gpio_bsp_set_resistor_mode(
132  uint32_t bank,
133  uint32_t pin,
134  rtems_gpio_pull_mode mode
135) {
136  /* Set control signal. */
137  switch ( mode ) {
138    case PULL_UP:
139      BCM2835_REG(BCM2835_GPIO_GPPUD) = (1 << 1);
140      break;
141    case PULL_DOWN:
142      BCM2835_REG(BCM2835_GPIO_GPPUD) = (1 << 0);
143      break;
144    case NO_PULL_RESISTOR:
145      BCM2835_REG(BCM2835_GPIO_GPPUD) = 0;
146      break;
147    default:
148      return RTEMS_UNSATISFIED;
149  }
150
151  /* Wait 150 cyles, as per BCM2835 documentation. */
152  arm_delay(150);
153
154  /* Setup clock for the control signal. */
155  BCM2835_REG(BCM2835_GPIO_GPPUDCLK0) = (1 << pin);
156
157  arm_delay(150);
158
159  /* Remove the control signal. */
160  BCM2835_REG(BCM2835_GPIO_GPPUD) = 0;
161
162  /* Remove the clock. */
163  BCM2835_REG(BCM2835_GPIO_GPPUDCLK0) = 0;
164
165  return RTEMS_SUCCESSFUL;
166}
167
168rtems_vector_number rtems_gpio_bsp_get_vector(uint32_t bank)
169{
170  return BCM2835_IRQ_ID_GPIO_0;
171}
172
173uint32_t rtems_gpio_bsp_interrupt_line(rtems_vector_number vector)
174{
175  uint32_t event_status;
176
177  /* Retrieve the interrupt event status. */
178  event_status = BCM2835_REG(BCM2835_GPIO_GPEDS0);
179
180  /* Clear the interrupt line. */
181  BCM2835_REG(BCM2835_GPIO_GPEDS0) = event_status;
182
183  return event_status;
184}
185
186rtems_status_code rtems_gpio_bsp_enable_interrupt(
187  uint32_t bank,
188  uint32_t pin,
189  rtems_gpio_interrupt interrupt
190) {
191  switch ( interrupt ) {
192    case FALLING_EDGE:
193      /* Enables asynchronous falling edge detection. */
194      BCM2835_REG(BCM2835_GPIO_GPAFEN0) |= (1 << pin);
195      break;
196    case RISING_EDGE:
197      /* Enables asynchronous rising edge detection. */
198      BCM2835_REG(BCM2835_GPIO_GPAREN0) |= (1 << pin);
199      break;
200    case BOTH_EDGES:
201      /* Enables asynchronous falling edge detection. */
202      BCM2835_REG(BCM2835_GPIO_GPAFEN0) |= (1 << pin);
203
204      /* Enables asynchronous rising edge detection. */
205      BCM2835_REG(BCM2835_GPIO_GPAREN0) |= (1 << pin);
206      break;
207    case LOW_LEVEL:
208      /* Enables pin low level detection. */
209      BCM2835_REG(BCM2835_GPIO_GPLEN0) |= (1 << pin);
210      break;
211    case HIGH_LEVEL:
212      /* Enables pin high level detection. */
213      BCM2835_REG(BCM2835_GPIO_GPHEN0) |= (1 << pin);
214      break;
215    case BOTH_LEVELS:
216      /* Enables pin low level detection. */
217      BCM2835_REG(BCM2835_GPIO_GPLEN0) |= (1 << pin);
218
219      /* Enables pin high level detection. */
220      BCM2835_REG(BCM2835_GPIO_GPHEN0) |= (1 << pin);
221      break;
222    case NONE:
223    default:
224      return RTEMS_UNSATISFIED;
225  }
226
227  return RTEMS_SUCCESSFUL;
228}
229
230rtems_status_code rtems_gpio_bsp_disable_interrupt(
231  uint32_t bank,
232  uint32_t pin,
233  rtems_gpio_interrupt interrupt
234) {
235  switch ( interrupt ) {
236    case FALLING_EDGE:
237      /* Disables asynchronous falling edge detection. */
238      BCM2835_REG(BCM2835_GPIO_GPAFEN0) &= ~(1 << pin);
239      break;
240    case RISING_EDGE:
241      /* Disables asynchronous rising edge detection. */
242      BCM2835_REG(BCM2835_GPIO_GPAREN0) &= ~(1 << pin);
243      break;
244    case BOTH_EDGES:
245      /* Disables asynchronous falling edge detection. */
246      BCM2835_REG(BCM2835_GPIO_GPAFEN0) &= ~(1 << pin);
247
248      /* Disables asynchronous rising edge detection. */
249      BCM2835_REG(BCM2835_GPIO_GPAREN0) &= ~(1 << pin);
250      break;
251    case LOW_LEVEL:
252      /* Disables pin low level detection. */
253      BCM2835_REG(BCM2835_GPIO_GPLEN0) &= ~(1 << pin);
254      break;
255    case HIGH_LEVEL:
256      /* Disables pin high level detection. */
257      BCM2835_REG(BCM2835_GPIO_GPHEN0) &= ~(1 << pin);
258      break;
259    case BOTH_LEVELS:
260      /* Disables pin low level detection. */
261      BCM2835_REG(BCM2835_GPIO_GPLEN0) &= ~(1 << pin);
262
263      /* Disables pin high level detection. */
264      BCM2835_REG(BCM2835_GPIO_GPHEN0) &= ~(1 << pin);
265      break;
266    case NONE:
267    default:
268      return RTEMS_UNSATISFIED;
269  }
270
271  return RTEMS_SUCCESSFUL;
272}
273
274rtems_status_code rpi_gpio_select_jtag(void)
275{
276  return rtems_gpio_multi_select(jtag_config, JTAG_PIN_COUNT);
277}
278
279rtems_status_code rpi_gpio_select_spi(void)
280{
281  return rtems_gpio_multi_select(spi_config, SPI_PIN_COUNT);
282}
283
284rtems_status_code rpi_gpio_select_i2c(void)
285{
286  return rtems_gpio_multi_select(i2c_config, I2C_PIN_COUNT);
287}
288
289rtems_status_code rtems_gpio_bsp_multi_select(
290  rtems_gpio_multiple_pin_select *pins,
291  uint32_t pin_count,
292  uint32_t select_bank
293) {
294  uint32_t register_address;
295  uint32_t select_register;
296  uint8_t i;
297
298  register_address = BCM2835_GPIO_REGS_BASE + (select_bank * 0x04);
299
300  select_register = BCM2835_REG(register_address);
301
302  for ( i = 0; i < pin_count; ++i ) {
303    if ( pins[i].function == DIGITAL_INPUT ) {
304      select_register &=
305        ~SELECT_PIN_FUNCTION(RPI_DIGITAL_IN, pins[i].pin_number);
306    }
307    else if ( pins[i].function == DIGITAL_OUTPUT ) {
308      select_register |=
309        SELECT_PIN_FUNCTION(RPI_DIGITAL_OUT, pins[i].pin_number);
310    }
311    else { /* BSP_SPECIFIC function. */
312      select_register |=
313        SELECT_PIN_FUNCTION(pins[i].io_function, pins[i].pin_number);
314    }
315  }
316
317  BCM2835_REG(register_address) = select_register;
318
319  return RTEMS_SUCCESSFUL;
320}
321
322rtems_status_code rtems_gpio_bsp_specific_group_operation(
323  uint32_t bank,
324  uint32_t *pins,
325  uint32_t pin_count,
326  void *arg
327) {
328  return RTEMS_NOT_DEFINED;
329}
Note: See TracBrowser for help on using the repository browser.