source: rtems/bsps/arm/lpc24xx/start/io.c @ 0a6b81a

5
Last change on this file since 0a6b81a was 0a6b81a, checked in by Sebastian Huber <sebastian.huber@…>, on 05/09/19 at 07:53:55

bsp/lpc24xx: Add LPC17XX_PIN_TYPE_FAST_SLEW_RATE

  • Property mode set to 100644
File size: 15.2 KB
RevLine 
[9364cf66]1/**
2 * @file
3 *
[c991eeec]4 * @ingroup RTEMSBSPsARMLPC24XX_io
[9364cf66]5 *
[ba938b8d]6 * @brief Input and output module.
[9364cf66]7 */
8
9/*
[14ee5a1e]10 * Copyright (c) 2009-2012 embedded brains GmbH.  All rights reserved.
[d74ed4a]11 *
12 *  embedded brains GmbH
13 *  Obere Lagerstr. 30
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
[9364cf66]17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
[c499856]20 * http://www.rtems.org/license/LICENSE.
[9364cf66]21 */
22
[4a6cc2a]23#include <bsp.h>
[9364cf66]24#include <bsp/io.h>
[4a6cc2a]25#include <bsp/start.h>
[ba938b8d]26#include <bsp/system-clocks.h>
[9364cf66]27
[4a6cc2a]28#define LPC24XX_PIN_SELECT(index) ((index) >> 4U)
[9364cf66]29
[4a6cc2a]30#define LPC24XX_PIN_SELECT_SHIFT(index) (((index) & 0xfU) << 1U)
[9364cf66]31
[d74ed4a]32#define LPC24XX_PIN_SELECT_MASK 0x3U
[9364cf66]33
34rtems_status_code lpc24xx_gpio_config(
[4a6cc2a]35  unsigned index,
[9364cf66]36  lpc24xx_gpio_settings settings
37)
38{
[4a6cc2a]39  if (index <= LPC24XX_IO_INDEX_MAX) {
[9364cf66]40    rtems_interrupt_level level;
[4a6cc2a]41    uint32_t port = LPC24XX_IO_PORT(index);
42    uint32_t port_bit = LPC24XX_IO_PORT_BIT(index);
43    uint32_t output = (settings & LPC24XX_GPIO_OUTPUT) != 0 ? 1U : 0U;
44    uint32_t resistor = settings & 0x3U;
45    #ifdef ARM_MULTILIB_ARCH_V4
46      uint32_t select = LPC24XX_PIN_SELECT(index);
47      uint32_t shift = LPC24XX_PIN_SELECT_SHIFT(index);
48
49      /* Get resistor flags */
50      switch (resistor) {
51        case LPC24XX_GPIO_RESISTOR_PULL_UP:
52          resistor = 0x0U;
53          break;
54        case LPC24XX_GPIO_RESISTOR_NONE:
55          resistor = 0x2U;
56          break;
57        case LPC24XX_GPIO_RESISTOR_PULL_DOWN:
58          resistor = 0x3U;
59          break;
60        default:
61          return RTEMS_INVALID_NUMBER;
62      }
[14ee5a1e]63    #else
64      uint32_t iocon_mask = IOCON_HYS | IOCON_INV
65        | IOCON_SLEW | IOCON_OD | IOCON_FILTER;
66      uint32_t iocon = (settings & iocon_mask) | IOCON_ADMODE;
67      uint32_t iocon_invalid = settings & ~(iocon_mask | LPC24XX_GPIO_OUTPUT);
68
69      /* Get resistor flags */
70      switch (resistor) {
71        case LPC24XX_GPIO_RESISTOR_NONE:
72          resistor = IOCON_MODE(0);
73          break;
74        case LPC24XX_GPIO_RESISTOR_PULL_DOWN:
75          resistor = IOCON_MODE(1);
76          break;
77        case LPC24XX_GPIO_RESISTOR_PULL_UP:
78          resistor = IOCON_MODE(2);
79          break;
80        case LPC17XX_GPIO_HYSTERESIS:
81          resistor = IOCON_MODE(3);
82          break;
83      }
84      iocon |= resistor;
85
86      if (iocon_invalid != 0) {
87        return RTEMS_INVALID_NUMBER;
88      }
89
90      if (output && (settings & LPC17XX_GPIO_INPUT_INVERT) != 0) {
91        return RTEMS_INVALID_NUMBER;
92      }
93
94      if ((settings & LPC17XX_GPIO_INPUT_FILTER) == 0) {
95        iocon |= IOCON_FILTER;
96      } else {
97        iocon &= ~IOCON_FILTER;
98      }
[4a6cc2a]99    #endif
[9364cf66]100
[ba938b8d]101    rtems_interrupt_disable(level);
[9364cf66]102
[4a6cc2a]103    #ifdef ARM_MULTILIB_ARCH_V4
104      /* Resistor */
105      LPC24XX_PINMODE [select] =
106        (LPC24XX_PINMODE [select] & ~(LPC24XX_PIN_SELECT_MASK << shift))
107          | ((resistor & LPC24XX_PIN_SELECT_MASK) << shift);
[14ee5a1e]108    #else
109      LPC17XX_IOCON [index] = iocon;
[4a6cc2a]110    #endif
[9364cf66]111
[ba938b8d]112    rtems_interrupt_flash(level);
[9364cf66]113
114    /* Input or output */
115    LPC24XX_FIO [port].dir =
[4a6cc2a]116      (LPC24XX_FIO [port].dir & ~(1U << port_bit)) | (output << port_bit);
[9364cf66]117
[ba938b8d]118    rtems_interrupt_enable(level);
[9364cf66]119  } else {
120    return RTEMS_INVALID_ID;
121  }
122
123  return RTEMS_SUCCESSFUL;
124}
125
[c468f18b]126#define LPC24XX_MODULE_ENTRY(mod, pwr, clk, idx) \
127  [mod] = { \
128    .power = pwr, \
129    .clock = clk, \
130    .index = idx \
131  }
132
133typedef struct {
134  unsigned char power : 1;
135  unsigned char clock : 1;
136  unsigned char index : 6;
137} lpc24xx_module_entry;
138
139static const lpc24xx_module_entry lpc24xx_module_table [] = {
[4a6cc2a]140  #ifdef ARM_MULTILIB_ARCH_V4
141    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_ACF, 0, 1, 15),
142  #endif
[c468f18b]143  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_ADC, 1, 1, 12),
[4a6cc2a]144  #ifdef ARM_MULTILIB_ARCH_V4
145    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_BAT_RAM, 0, 1, 16),
146  #endif
[c468f18b]147  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_CAN_0, 1, 1, 13),
148  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_CAN_1, 1, 1, 14),
149  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_DAC, 0, 1, 11),
150  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_EMC, 1, 0, 11),
151  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_ETHERNET, 1, 0, 30),
152  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_GPDMA, 1, 1, 29),
[4a6cc2a]153  #ifdef ARM_MULTILIB_ARCH_V4
154    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_GPIO, 0, 1, 17),
155  #else
156    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_GPIO, 0, 1, 15),
157  #endif
[c468f18b]158  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_I2C_0, 1, 1, 7),
159  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_I2C_1, 1, 1, 19),
160  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_I2C_2, 1, 1, 26),
161  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_I2S, 1, 1, 27),
[4a6cc2a]162  #ifdef ARM_MULTILIB_ARCH_V4
163    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_LCD, 1, 0, 20),
164  #else
165    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_LCD, 1, 0, 0),
166  #endif
[c468f18b]167  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_MCI, 1, 1, 28),
[14ee5a1e]168  #ifdef ARM_MULTILIB_ARCH_V7M
169    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_MCPWM, 1, 1, 17),
170  #endif
[c468f18b]171  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_PCB, 0, 1, 18),
172  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_PWM_0, 1, 1, 5),
173  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_PWM_1, 1, 1, 6),
[14ee5a1e]174  #ifdef ARM_MULTILIB_ARCH_V7M
175    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_QEI, 1, 1, 18),
176  #endif
[c468f18b]177  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_RTC, 1, 1, 9),
[4a6cc2a]178  #ifdef ARM_MULTILIB_ARCH_V4
179    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_SPI, 1, 1, 8),
180  #endif
[c468f18b]181  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_SSP_0, 1, 1, 21),
182  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_SSP_1, 1, 1, 10),
[14ee5a1e]183  #ifdef ARM_MULTILIB_ARCH_V7M
184    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_SSP_2, 1, 1, 20),
185  #endif
[c468f18b]186  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_SYSCON, 0, 1, 30),
187  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_TIMER_0, 1, 1, 1),
188  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_TIMER_1, 1, 1, 2),
189  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_TIMER_2, 1, 1, 22),
190  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_TIMER_3, 1, 1, 23),
191  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_UART_0, 1, 1, 3),
192  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_UART_1, 1, 1, 4),
193  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_UART_2, 1, 1, 24),
194  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_UART_3, 1, 1, 25),
[14ee5a1e]195  #ifdef ARM_MULTILIB_ARCH_V7M
196    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_UART_4, 1, 1, 8),
197  #endif
[4a6cc2a]198  #ifdef ARM_MULTILIB_ARCH_V4
199    LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_WDT, 0, 1, 0),
200  #endif
201  LPC24XX_MODULE_ENTRY(LPC24XX_MODULE_USB, 1, 0, 31)
[c468f18b]202};
203
[9364cf66]204static rtems_status_code lpc24xx_module_do_enable(
205  lpc24xx_module module,
206  lpc24xx_module_clock clock,
207  bool enable
208)
209{
[c468f18b]210  rtems_interrupt_level level;
211  bool has_power = false;
212  bool has_clock = false;
213  unsigned index = 0;
[14ee5a1e]214  #ifdef ARM_MULTILIB_ARCH_V7M
215    volatile lpc17xx_scb *scb = &LPC17XX_SCB;
216  #endif
[9364cf66]217
[c468f18b]218  if ((unsigned) module >= LPC24XX_MODULE_COUNT) {
[9364cf66]219      return RTEMS_INVALID_ID;
220  }
221
[4a6cc2a]222  #ifdef ARM_MULTILIB_ARCH_V4
223    if (clock == LPC24XX_MODULE_PCLK_DEFAULT) {
224      #if LPC24XX_PCLKDIV == 1U
225        clock = LPC24XX_MODULE_CCLK;
226      #elif LPC24XX_PCLKDIV == 2U
227        clock = LPC24XX_MODULE_CCLK_2;
228      #elif LPC24XX_PCLKDIV == 4U
229        clock = LPC24XX_MODULE_CCLK_4;
230      #elif LPC24XX_PCLKDIV == 8U
231        clock = LPC24XX_MODULE_CCLK_8;
232      #endif
233    }
234
235    if ((clock & ~LPC24XX_MODULE_CLOCK_MASK) != 0U) {
236      return RTEMS_INVALID_CLOCK;
237    }
[14ee5a1e]238  #else
239    if (clock != LPC24XX_MODULE_PCLK_DEFAULT) {
240      return RTEMS_INVALID_CLOCK;
241    }
[4a6cc2a]242  #endif
[9364cf66]243
[c468f18b]244  has_power = lpc24xx_module_table [module].power;
245  has_clock = lpc24xx_module_table [module].clock;
246  index = lpc24xx_module_table [module].index;
[9364cf66]247
248  /* Enable or disable module */
249  if (enable) {
[c468f18b]250    if (has_power) {
251      rtems_interrupt_disable(level);
[4a6cc2a]252      #ifdef ARM_MULTILIB_ARCH_V4
253        PCONP |= 1U << index;
[14ee5a1e]254      #else
255        scb->pconp |= 1U << index;
[4a6cc2a]256      #endif
[c468f18b]257      rtems_interrupt_enable(level);
258    }
[9364cf66]259
260    if (module != LPC24XX_MODULE_USB) {
[c468f18b]261      if (has_clock) {
[4a6cc2a]262        #ifdef ARM_MULTILIB_ARCH_V4
263          unsigned clock_shift = 2U * index;
264
265          rtems_interrupt_disable(level);
266          if (clock_shift < 32U) {
267            PCLKSEL0 = (PCLKSEL0 & ~(LPC24XX_MODULE_CLOCK_MASK << clock_shift))
268                | (clock << clock_shift);
269          } else {
270            clock_shift -= 32U;
271            PCLKSEL1 = (PCLKSEL1 & ~(LPC24XX_MODULE_CLOCK_MASK << clock_shift))
272                | (clock << clock_shift);
273          }
274          rtems_interrupt_enable(level);
275        #endif
[9364cf66]276      }
277    } else {
[4a6cc2a]278      #ifdef ARM_MULTILIB_ARCH_V4
279        unsigned pllclk = lpc24xx_pllclk();
280        unsigned usbsel = pllclk / 48000000U - 1U;
281
282        if (
283          usbsel > 15U
284            || (usbsel % 2U != 1U)
285            || (pllclk % 48000000U) != 0U
286        ) {
287          return RTEMS_INCORRECT_STATE;
288        }
[9364cf66]289
[4a6cc2a]290        USBCLKCFG = usbsel;
[14ee5a1e]291      #else
[4275124]292        uint32_t pllclk = lpc24xx_pllclk();
293        uint32_t usbclk = 48000000U;
294
295        if (pllclk % usbclk == 0U) {
296          uint32_t usbdiv = pllclk / usbclk;
297
298          scb->usbclksel = LPC17XX_SCB_USBCLKSEL_USBDIV(usbdiv)
299            | LPC17XX_SCB_USBCLKSEL_USBSEL(1);
300        } else {
301          return RTEMS_INCORRECT_STATE;
302        }
[4a6cc2a]303      #endif
[9364cf66]304    }
305  } else {
[c468f18b]306    if (has_power) {
307      rtems_interrupt_disable(level);
[4a6cc2a]308      #ifdef ARM_MULTILIB_ARCH_V4
309        PCONP &= ~(1U << index);
[14ee5a1e]310      #else
311        scb->pconp &= ~(1U << index);
[4a6cc2a]312      #endif
[c468f18b]313      rtems_interrupt_enable(level);
314    }
[9364cf66]315  }
316
317  return RTEMS_SUCCESSFUL;
318}
319
320rtems_status_code lpc24xx_module_enable(
321  lpc24xx_module module,
322  lpc24xx_module_clock clock
323)
324{
[c468f18b]325  return lpc24xx_module_do_enable(module, clock, true);
[9364cf66]326}
327
328rtems_status_code lpc24xx_module_disable(
[c468f18b]329  lpc24xx_module module
[9364cf66]330)
331{
[e8adc8e3]332  return lpc24xx_module_do_enable(
333    module,
334    LPC24XX_MODULE_PCLK_DEFAULT,
335    false
336  );
[9364cf66]337}
[d74ed4a]338
[4e0755c8]339bool lpc24xx_module_is_enabled(lpc24xx_module module)
340{
341  bool enabled = false;
342
343  if ((unsigned) module < LPC24XX_MODULE_COUNT) {
344    bool has_power = lpc24xx_module_table [module].power;
345
346    if (has_power) {
347      unsigned index = lpc24xx_module_table [module].index;
348      #ifdef ARM_MULTILIB_ARCH_V4
349        uint32_t pconp = PCONP;
350      #else
351        uint32_t pconp = LPC17XX_SCB.pconp;
352      #endif
353
354      enabled = (pconp & (1U << index)) != 0;
355    } else {
356      enabled = true;
357    }
358  }
359
360  return enabled;
361}
362
[d74ed4a]363typedef rtems_status_code (*lpc24xx_pin_visitor)(
[4a6cc2a]364  #ifdef ARM_MULTILIB_ARCH_V4
365    volatile uint32_t *pinsel,
366    uint32_t pinsel_mask,
367    uint32_t pinsel_value,
[14ee5a1e]368  #else
369    volatile uint32_t *iocon,
370    lpc24xx_pin_range pin_range,
[4a6cc2a]371  #endif
[d74ed4a]372  volatile uint32_t *fio_dir,
373  uint32_t fio_bit
374);
375
[4a6cc2a]376static BSP_START_TEXT_SECTION __attribute__((flatten)) rtems_status_code
377lpc24xx_pin_set_function(
378  #ifdef ARM_MULTILIB_ARCH_V4
379    volatile uint32_t *pinsel,
380    uint32_t pinsel_mask,
381    uint32_t pinsel_value,
[14ee5a1e]382  #else
383    volatile uint32_t *iocon,
384    lpc24xx_pin_range pin_range,
[4a6cc2a]385  #endif
[d74ed4a]386  volatile uint32_t *fio_dir,
387  uint32_t fio_bit
388)
389{
[4a6cc2a]390  #ifdef ARM_MULTILIB_ARCH_V4
391    rtems_interrupt_level level;
[d74ed4a]392
[4a6cc2a]393    rtems_interrupt_disable(level);
394    *pinsel = (*pinsel & ~pinsel_mask) | pinsel_value;
395    rtems_interrupt_enable(level);
[14ee5a1e]396  #else
[e9e5b92d]397    uint32_t iocon_extra = 0;
[0a66c126]398    uint32_t iocon_not_analog = IOCON_ADMODE;
[e9e5b92d]399
[14ee5a1e]400    /* TODO */
[e9e5b92d]401    switch (pin_range.fields.type) {
[0a66c126]402      case LPC17XX_PIN_TYPE_ADC:
403      case LPC17XX_PIN_TYPE_DAC:
404        iocon_not_analog = 0;
405        break;
[e9e5b92d]406      case LPC17XX_PIN_TYPE_I2C_FAST_PLUS:
407        iocon_extra |= IOCON_HS;
408        break;
409      case LPC17XX_PIN_TYPE_OPEN_DRAIN:
410        iocon_extra |= IOCON_OD;
411        break;
[0a6b81a]412      case LPC17XX_PIN_TYPE_FAST_SLEW_RATE:
413        iocon_extra |= IOCON_SLEW;
414        break;
[e9e5b92d]415      default:
416        break;
417    }
418
[0a66c126]419    *iocon = IOCON_FUNC(pin_range.fields.function) | iocon_extra | iocon_not_analog;
[4a6cc2a]420  #endif
[d74ed4a]421
422  return RTEMS_SUCCESSFUL;
423}
424
[4a6cc2a]425static BSP_START_TEXT_SECTION rtems_status_code lpc24xx_pin_check_function(
426  #ifdef ARM_MULTILIB_ARCH_V4
427    volatile uint32_t *pinsel,
428    uint32_t pinsel_mask,
429    uint32_t pinsel_value,
[14ee5a1e]430  #else
431    volatile uint32_t *iocon,
432    lpc24xx_pin_range pin_range,
[4a6cc2a]433  #endif
[d74ed4a]434  volatile uint32_t *fio_dir,
435  uint32_t fio_bit
436)
437{
[4a6cc2a]438  #ifdef ARM_MULTILIB_ARCH_V4
439    if ((*pinsel & pinsel_mask) == pinsel_value) {
440      return RTEMS_SUCCESSFUL;
441    } else {
442      return RTEMS_IO_ERROR;
443    }
[14ee5a1e]444  #else
445    /* TODO */
446    return RTEMS_IO_ERROR;
[4a6cc2a]447  #endif
[d74ed4a]448}
449
[4a6cc2a]450static BSP_START_TEXT_SECTION __attribute__((flatten)) rtems_status_code
451lpc24xx_pin_set_input(
452  #ifdef ARM_MULTILIB_ARCH_V4
453    volatile uint32_t *pinsel,
454    uint32_t pinsel_mask,
455    uint32_t pinsel_value,
[14ee5a1e]456  #else
457    volatile uint32_t *iocon,
458    lpc24xx_pin_range pin_range,
[4a6cc2a]459  #endif
[d74ed4a]460  volatile uint32_t *fio_dir,
461  uint32_t fio_bit
462)
463{
464  rtems_interrupt_level level;
465
466  rtems_interrupt_disable(level);
467  *fio_dir &= ~fio_bit;
[4a6cc2a]468  #ifdef ARM_MULTILIB_ARCH_V4
469    *pinsel &= ~pinsel_mask;
[14ee5a1e]470  #else
471    *iocon = IOCON_MODE(2) | IOCON_ADMODE | IOCON_FILTER;
[4a6cc2a]472  #endif
[d74ed4a]473  rtems_interrupt_enable(level);
474
475  return RTEMS_SUCCESSFUL;
476}
477
[4a6cc2a]478static BSP_START_TEXT_SECTION rtems_status_code lpc24xx_pin_check_input(
479  #ifdef ARM_MULTILIB_ARCH_V4
480    volatile uint32_t *pinsel,
481    uint32_t pinsel_mask,
482    uint32_t pinsel_value,
[14ee5a1e]483  #else
484    volatile uint32_t *iocon,
485    lpc24xx_pin_range pin_range,
[4a6cc2a]486  #endif
[d74ed4a]487  volatile uint32_t *fio_dir,
488  uint32_t fio_bit
489)
490{
[4a6cc2a]491  rtems_status_code sc = RTEMS_IO_ERROR;
492  bool is_input = (*fio_dir & fio_bit) == 0;
493
494  if (is_input) {
495    #ifdef ARM_MULTILIB_ARCH_V4
496      bool is_gpio = (*pinsel & pinsel_mask) == 0;
[14ee5a1e]497    #else
498      bool is_gpio = IOCON_FUNC_GET(*iocon) == 0;
[4a6cc2a]499    #endif
500
501    if (is_gpio) {
502      sc = RTEMS_SUCCESSFUL;
503    }
[d74ed4a]504  }
[4a6cc2a]505
506  return sc;
[d74ed4a]507}
508
[4a6cc2a]509static BSP_START_DATA_SECTION const lpc24xx_pin_visitor
510  lpc24xx_pin_visitors [] = {
[d74ed4a]511  [LPC24XX_PIN_SET_FUNCTION] = lpc24xx_pin_set_function,
512  [LPC24XX_PIN_CHECK_FUNCTION] = lpc24xx_pin_check_function,
513  [LPC24XX_PIN_SET_INPUT] = lpc24xx_pin_set_input,
514  [LPC24XX_PIN_CHECK_INPUT] = lpc24xx_pin_check_input
515};
516
[4a6cc2a]517BSP_START_TEXT_SECTION rtems_status_code lpc24xx_pin_config(
[d74ed4a]518  const lpc24xx_pin_range *pins,
519  lpc24xx_pin_action action
520)
521{
522  rtems_status_code sc = RTEMS_SUCCESSFUL;
523
524  if ((unsigned) action <= LPC24XX_PIN_CHECK_INPUT) {
525    lpc24xx_pin_visitor visitor = lpc24xx_pin_visitors [action];
526    lpc24xx_pin_range terminal = LPC24XX_PIN_TERMINAL;
[4a6cc2a]527    lpc24xx_pin_range pin_range = *pins;
528    uint32_t previous_port_bit = pin_range.fields.port_bit;
529
530    while (sc == RTEMS_SUCCESSFUL && pin_range.value != terminal.value) {
531      uint32_t port = pin_range.fields.port;
532      uint32_t port_bit = pin_range.fields.port_bit;
533      uint32_t port_bit_last = port_bit;
534      uint32_t range = pin_range.fields.range;
535      #ifdef ARM_MULTILIB_ARCH_V4
536        uint32_t function = pin_range.fields.function;
537      #endif
[d74ed4a]538      volatile uint32_t *fio_dir = &LPC24XX_FIO [port].dir;
539
[4a6cc2a]540      if (range) {
541        port_bit = previous_port_bit;
542      }
543
544      while (sc == RTEMS_SUCCESSFUL && port_bit <= port_bit_last) {
545        uint32_t index = LPC24XX_IO_INDEX_BY_PORT(port, port_bit);
546        uint32_t fio_bit = 1U << port_bit;
547        #ifdef ARM_MULTILIB_ARCH_V4
548          uint32_t select = LPC24XX_PIN_SELECT(index);
549          uint32_t shift = LPC24XX_PIN_SELECT_SHIFT(index);
550          volatile uint32_t *pinsel = &LPC24XX_PINSEL [select];
551          uint32_t pinsel_mask = LPC24XX_PIN_SELECT_MASK << shift;
552          uint32_t pinsel_value = (function & LPC24XX_PIN_SELECT_MASK) << shift;
[d74ed4a]553
[4a6cc2a]554          sc = (*visitor)(pinsel, pinsel_mask, pinsel_value, fio_dir, fio_bit);
[14ee5a1e]555        #else
556          volatile uint32_t *iocon = &LPC17XX_IOCON [index];
557
558          sc = (*visitor)(iocon, pin_range, fio_dir, fio_bit);
[4a6cc2a]559        #endif
[d74ed4a]560
[4a6cc2a]561        ++port_bit;
[d74ed4a]562      }
563
564      ++pins;
[4a6cc2a]565      previous_port_bit = port_bit;
566      pin_range = *pins;
[d74ed4a]567    }
568  } else {
569    sc = RTEMS_NOT_DEFINED;
570  }
571
572  return sc;
573}
Note: See TracBrowser for help on using the repository browser.