source: rtems/bsps/arm/raspberrypi/gpio/rpi-gpio.c @ 69a24c3

5
Last change on this file since 69a24c3 was fc1bdb83, checked in by Sebastian Huber <sebastian.huber@…>, on 04/25/18 at 08:36:01

bsp/raspberrypi: Move source files to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

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