source: rtems/c/src/lib/libbsp/arm/lpc24xx/ssp/ssp.c @ 9647f7fe

4.104.115
Last change on this file since 9647f7fe was 9647f7fe, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on Feb 27, 2009 at 11:26:44 AM
  • README: Added NCS.
  • Makefile.am, configure.ac, preinstall.am: Added BSP variants.
  • console/console-config.c, clock/clock-config.c, ssp/ssp.c: Fixed register settings. Cleanup.
  • include/bsp.h: Added network defines and functions.
  • include/lpc24xx.h: Added AHB and EMC defines. Fixed Ethernet status sizes.
  • include/system-clocks.h, misc/system-clocks.c: Added micro seconds delay function that uses Timer 1. Changed PLL setup.
  • network/network.c, startup/bspreset.c, startup/linkcmds.lpc2478, startup/linkcmds.lpc2478_ncs, startup/linkcmds.lpc2478_ncs_ram: New files.
  • startup/bspstart.c: Added EMC initialization. Changes for ROM boot.
  • Property mode set to 100644
File size: 16.0 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup lpc24xx
5 *
6 * @brief LibI2C bus driver for the Synchronous Serial Port (SSP).
7 */
8
9/*
10 * Copyright (c) 2008
11 * Embedded Brains GmbH
12 * Obere Lagerstr. 30
13 * D-82178 Puchheim
14 * Germany
15 * rtems@embedded-brains.de
16 *
17 * The license and distribution terms for this file may be found in the file
18 * LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
19 */
20
21#include <stdbool.h>
22
23#include <bsp/ssp.h>
24#include <bsp/lpc24xx.h>
25#include <bsp/irq.h>
26#include <bsp/system-clocks.h>
27#include <bsp/dma.h>
28
29#define RTEMS_STATUS_CHECKS_USE_PRINTK
30
31#include <rtems/status-checks.h>
32
33#define LPC24XX_SSP_NUMBER 2
34
35#define LPC24XX_SSP_FIFO_SIZE 8
36
37#define LPC24XX_SSP_BAUD_RATE 2000000
38
39typedef enum {
40  LPC24XX_SSP_DMA_INVALID = 0,
41  LPC24XX_SSP_DMA_AVAILABLE = 1,
42  LPC24XX_SSP_DMA_NOT_INITIALIZED = 2,
43  LPC24XX_SSP_DMA_INITIALIZATION = 3,
44  LPC24XX_SSP_DMA_TRANSFER_FLAG = 0x80000000U,
45  LPC24XX_SSP_DMA_WAIT = 1 | LPC24XX_SSP_DMA_TRANSFER_FLAG,
46  LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_0 = 2 | LPC24XX_SSP_DMA_TRANSFER_FLAG,
47  LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_1 = 3 | LPC24XX_SSP_DMA_TRANSFER_FLAG,
48  LPC24XX_SSP_DMA_ERROR = 4 | LPC24XX_SSP_DMA_TRANSFER_FLAG,
49  LPC24XX_SSP_DMA_DONE = 5 | LPC24XX_SSP_DMA_TRANSFER_FLAG
50} lpc24xx_ssp_dma_status;
51
52typedef struct {
53  rtems_libi2c_bus_t bus;
54  volatile lpc24xx_ssp *regs;
55  unsigned clock;
56  uint32_t idle_char;
57} lpc24xx_ssp_bus_entry;
58
59typedef struct {
60  lpc24xx_ssp_dma_status status;
61  lpc24xx_ssp_bus_entry *bus;
62  rtems_libi2c_read_write_done_t done;
63  int n;
64  void *arg;
65} lpc24xx_ssp_dma_entry;
66
67static lpc24xx_ssp_dma_entry lpc24xx_ssp_dma_data = {
68  .status = LPC24XX_SSP_DMA_NOT_INITIALIZED,
69  .bus = NULL,
70  .done = NULL,
71  .n = 0,
72  .arg = NULL
73};
74
75static uint32_t lpc24xx_ssp_trash = 0;
76
77static inline bool lpc24xx_ssp_is_busy( const lpc24xx_ssp_bus_entry *bus)
78{
79  return lpc24xx_ssp_dma_data.bus == bus
80    && lpc24xx_ssp_dma_data.status != LPC24XX_SSP_DMA_AVAILABLE;
81}
82
83static void lpc24xx_ssp_handler( rtems_vector_number vector, void *arg)
84{
85  lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) arg;
86  volatile lpc24xx_ssp *regs = e->regs;
87  uint32_t mis = regs->mis;
88  uint32_t icr = 0;
89
90  if (IS_FLAG_SET( mis, SSP_MIS_RORRIS)) {
91    /* TODO */
92    printk( "%s: Receiver overrun!\n", __func__);
93    icr |= SSP_ICR_RORRIS;
94  }
95
96  regs->icr = icr;
97}
98
99static void lpc24xx_ssp_dma_handler( rtems_vector_number vector, void *arg)
100{
101  lpc24xx_ssp_dma_entry *e = (lpc24xx_ssp_dma_entry *) arg;
102  lpc24xx_ssp_dma_status status = e->status;
103  uint32_t tc = 0;
104  uint32_t err = 0;
105  int rv = 0;
106
107  /* Return if we are not in a transfer status */
108  if (IS_FLAG_CLEARED( status, LPC24XX_SSP_DMA_TRANSFER_FLAG)) {
109    return;
110  }
111
112  /* Get interrupt status */
113  tc = GPDMA_INT_TCSTAT;
114  err = GPDMA_INT_ERR_STAT;
115
116  /* Clear interrupt status */
117  GPDMA_INT_TCCLR = tc;
118  GPDMA_INT_ERR_CLR = err;
119
120  /* Change status */
121  if (err == 0) {
122    switch (status) {
123      case LPC24XX_SSP_DMA_WAIT:
124        if (ARE_FLAGS_SET( tc, GPDMA_STATUS_CH_0 | GPDMA_STATUS_CH_1)) {
125          status = LPC24XX_SSP_DMA_DONE;
126        } else if (IS_FLAG_SET( tc, GPDMA_STATUS_CH_0)) {
127          status = LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_1;
128        } else if (IS_FLAG_SET( tc, GPDMA_STATUS_CH_1)) {
129          status = LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_0;
130        }
131        break;
132      case LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_0:
133        if (IS_FLAG_SET( tc, GPDMA_STATUS_CH_1)) {
134          status = LPC24XX_SSP_DMA_ERROR;
135        } else if (IS_FLAG_SET( tc, GPDMA_STATUS_CH_0)) {
136          status = LPC24XX_SSP_DMA_DONE;
137        }
138        break;
139      case LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_1:
140        if (IS_FLAG_SET( tc, GPDMA_STATUS_CH_0)) {
141          status = LPC24XX_SSP_DMA_ERROR;
142        } else if (IS_FLAG_SET( tc, GPDMA_STATUS_CH_1)) {
143          status = LPC24XX_SSP_DMA_DONE;
144        }
145        break;
146      default:
147        status = LPC24XX_SSP_DMA_ERROR;
148        break;
149    }
150  } else {
151    status = LPC24XX_SSP_DMA_ERROR;
152  }
153
154  /* Error cleanup */
155  if (status == LPC24XX_SSP_DMA_ERROR) {
156    lpc24xx_dma_channel_disable( 0, true);
157    lpc24xx_dma_channel_disable( 1, true);
158    status = LPC24XX_SSP_DMA_DONE;
159    rv = -RTEMS_IO_ERROR;
160  }
161
162  /* Done */
163  if (status == LPC24XX_SSP_DMA_DONE) {
164    status = LPC24XX_SSP_DMA_AVAILABLE;
165    if (e->done != NULL) {
166      e->done( rv, e->n, e->arg);
167      e->done = NULL;
168    }
169  }
170
171  /* Set status */
172  e->status = status;
173}
174
175static rtems_status_code lpc24xx_ssp_init( rtems_libi2c_bus_t *bus)
176{
177  rtems_status_code sc = RTEMS_SUCCESSFUL;
178  rtems_interrupt_level level;
179  lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) bus;
180  volatile lpc24xx_ssp *regs = e->regs;
181  unsigned pclk = lpc24xx_cclk();
182  unsigned pre =
183    ((pclk + LPC24XX_SSP_BAUD_RATE - 1) / LPC24XX_SSP_BAUD_RATE + 1) & ~1U;
184  rtems_vector_number vector = UINT32_MAX;
185
186  if (lpc24xx_ssp_dma_data.status == LPC24XX_SSP_DMA_NOT_INITIALIZED) {
187    lpc24xx_ssp_dma_status status = LPC24XX_SSP_DMA_INVALID;
188
189    /* Test and set DMA support status */
190    rtems_interrupt_disable( level);
191    status = lpc24xx_ssp_dma_data.status;
192    if (status == LPC24XX_SSP_DMA_NOT_INITIALIZED) {
193      lpc24xx_ssp_dma_data.status = LPC24XX_SSP_DMA_INITIALIZATION;
194    }
195    rtems_interrupt_enable( level);
196
197    if (status == LPC24XX_SSP_DMA_NOT_INITIALIZED) {
198      /* Install DMA interrupt handler */
199      sc = rtems_interrupt_handler_install(
200        LPC24XX_IRQ_DMA,
201        "SSP DMA",
202        RTEMS_INTERRUPT_SHARED,
203        lpc24xx_ssp_dma_handler,
204        &lpc24xx_ssp_dma_data
205      );
206      RTEMS_CHECK_SC( sc, "Install DMA interrupt handler");
207
208      /* Set DMA support status */
209      lpc24xx_ssp_dma_data.status = LPC24XX_SSP_DMA_AVAILABLE;
210    }
211  }
212
213  /* Disable module */
214  regs->cr1 = 0;
215
216  /* Set clock select and get vector number */
217  switch ((uintptr_t) regs) {
218    case SSP0_BASE_ADDR:
219      rtems_interrupt_disable( level);
220      PCLKSEL1 = SET_PCLKSEL1_PCLK_SSP0( PCLKSEL1, 1);
221      rtems_interrupt_enable( level);
222
223      vector = LPC24XX_IRQ_SPI_SSP_0;
224      break;
225    case SSP1_BASE_ADDR:
226      rtems_interrupt_disable( level);
227      PCLKSEL0 = SET_PCLKSEL0_PCLK_SSP1( PCLKSEL0, 1);
228      rtems_interrupt_enable( level);
229
230      vector = LPC24XX_IRQ_SSP_1;
231      break;
232    default:
233      return RTEMS_IO_ERROR;
234  }
235
236  /* Set serial clock rate to save value */
237  regs->cr0 = SET_SSP_CR0_SCR( 0, 255);
238
239  /* Set clock prescaler */
240  if (pre > 254) {
241    pre = 254;
242  } else if (pre < 2) {
243    pre = 2;
244  }
245  regs->cpsr = pre;
246
247  /* Save clock value */
248  e->clock = pclk / pre;
249
250  /* Enable module and loop back mode */
251  regs->cr1 = SSP_CR1_LBM | SSP_CR1_SSE;
252
253  /* Install interrupt handler */
254  sc = rtems_interrupt_handler_install(
255    vector,
256    "SSP",
257    RTEMS_INTERRUPT_UNIQUE,
258    lpc24xx_ssp_handler,
259    e
260  );
261  RTEMS_CHECK_SC( sc, "Install interrupt handler");
262
263  /* Enable receiver overrun interrupts */
264  e->regs->imsc = SSP_IMSC_RORIM;
265
266  return RTEMS_SUCCESSFUL;
267}
268
269static rtems_status_code lpc24xx_ssp_send_start( rtems_libi2c_bus_t *bus)
270{
271  return RTEMS_SUCCESSFUL;
272}
273
274static rtems_status_code lpc24xx_ssp_send_stop( rtems_libi2c_bus_t *bus)
275{
276  lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) bus;
277
278  /* Release DMA support */
279  if (lpc24xx_ssp_dma_data.bus == e) {
280    if (lpc24xx_ssp_dma_data.status == LPC24XX_SSP_DMA_AVAILABLE) {
281      lpc24xx_dma_channel_release( 0);
282      lpc24xx_dma_channel_release( 1);
283      lpc24xx_ssp_dma_data.bus = NULL;
284    } else {
285      return RTEMS_RESOURCE_IN_USE;
286    }
287  }
288
289  return RTEMS_SUCCESSFUL;
290}
291
292static rtems_status_code lpc24xx_ssp_send_addr(
293  rtems_libi2c_bus_t *bus,
294  uint32_t addr,
295  int rw
296)
297{
298  lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) bus;
299
300  if (lpc24xx_ssp_is_busy( e)) {
301    return RTEMS_RESOURCE_IN_USE;
302  }
303
304  return RTEMS_SUCCESSFUL;
305}
306
307static int lpc24xx_ssp_set_transfer_mode(
308  rtems_libi2c_bus_t *bus,
309  const rtems_libi2c_tfr_mode_t *mode
310)
311{
312  lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) bus;
313  volatile lpc24xx_ssp *regs = e->regs;
314  unsigned clk = e->clock;
315  unsigned br = mode->baudrate;
316  unsigned scr = (clk + br - 1) / br;
317
318  if (lpc24xx_ssp_is_busy( e)) {
319    return -RTEMS_RESOURCE_IN_USE;
320  }
321
322  if (mode->bits_per_char != 8) {
323    return -RTEMS_INVALID_NUMBER;
324  }
325
326  if (mode->lsb_first) {
327    return -RTEMS_INVALID_NUMBER;
328  }
329
330  if (br == 0) {
331    return -RTEMS_INVALID_NUMBER;
332  }
333
334  /* Compute new prescaler if necessary */
335  if (scr > 256 || scr < 1) {
336    unsigned pre = regs->cpsr;
337    unsigned pclk = clk * pre;
338
339    while (scr > 256) {
340      if (pre > 252) {
341        return -RTEMS_INVALID_NUMBER;
342      }
343      pre += 2;
344      clk = pclk / pre;
345      scr = (clk + br - 1) / br;
346    }
347
348    while (scr < 1) {
349      if (pre < 4) {
350        return -RTEMS_INVALID_NUMBER;
351      }
352      pre -= 2;
353      clk = pclk / pre;
354      scr = (clk + br - 1) / br;
355    }
356
357    regs->cpsr = pre;
358    e->clock = clk;
359  }
360
361  /* Adjust SCR */
362  --scr;
363
364  e->idle_char = mode->idle_char;
365
366  while (IS_FLAG_CLEARED( regs->sr, SSP_SR_TFE)) {
367    /* Wait */
368  }
369
370  regs->cr0 = SET_SSP_CR0_DSS( 0, 0x7)
371    | SET_SSP_CR0_SCR( 0, scr)
372    | (mode->clock_inv ? SSP_CR0_CPOL : 0)
373    | (mode->clock_phs ? SSP_CR0_CPHA : 0);
374
375  return 0;
376}
377
378static int lpc24xx_ssp_read_write(
379  rtems_libi2c_bus_t *bus,
380  unsigned char *in,
381  const unsigned char *out,
382  int n
383)
384{
385  lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) bus;
386  volatile lpc24xx_ssp *regs = e->regs;
387  int r = 0;
388  int w = 0;
389  int dr = 1;
390  int dw = 1;
391  int m = 0;
392  uint32_t sr = regs->sr;
393  unsigned char trash = 0;
394  unsigned char idle_char = (unsigned char) e->idle_char;
395
396  if (lpc24xx_ssp_is_busy( e)) {
397    return -RTEMS_RESOURCE_IN_USE;
398  }
399
400  if (n < 0) {
401    return -RTEMS_INVALID_SIZE;
402  }
403
404  /* Disable DMA on SSP */
405  regs->dmacr = 0;
406
407  if (in == NULL) {
408    dr = 0;
409    in = &trash;
410  }
411
412  if (out == NULL) {
413    dw = 0;
414    out = &idle_char;
415  }
416
417  /*
418   * Assumption: The transmit and receive FIFOs are empty.  If this assumption
419   * is not true an input buffer overflow may occur or we may never exit the
420   * loop due to data loss.  This is only possible if entities external to this
421   * driver operate on the SSP.
422   */
423
424  while (w < n) {
425    /* FIFO capacity */
426    m = w - r;
427
428    /* Write */
429    if (IS_FLAG_SET( sr, SSP_SR_TNF) && m < LPC24XX_SSP_FIFO_SIZE) {
430      regs->dr = *out;
431      ++w;
432      out += dw;
433    }
434
435    /* Read */
436    if (IS_FLAG_SET( sr, SSP_SR_RNE)) {
437      *in = (unsigned char) regs->dr;
438      ++r;
439      in += dr;
440    }
441
442    /* New status */
443    sr = regs->sr;
444  }
445
446  /* Read outstanding input */
447  while (r < n) {
448    /* Wait */
449    do {
450      sr = regs->sr;
451    } while (IS_FLAG_CLEARED( sr, SSP_SR_RNE));
452
453    /* Read */
454    *in = (unsigned char) regs->dr;
455    ++r;
456    in += dr;
457  }
458
459  return n;
460}
461
462static int lpc24xx_ssp_read_write_async(
463  rtems_libi2c_bus_t *bus,
464  unsigned char *in,
465  const unsigned char *out,
466  int n,
467  rtems_libi2c_read_write_done_t done,
468  void *arg
469)
470{
471  rtems_status_code sc = RTEMS_SUCCESSFUL;
472  rtems_interrupt_level level;
473  lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) bus;
474  volatile lpc24xx_ssp *ssp = e->regs;
475  volatile lpc24xx_dma_channel *receive_channel = GPDMA_CH_BASE_ADDR( 0);
476  volatile lpc24xx_dma_channel *transmit_channel = GPDMA_CH_BASE_ADDR( 1);
477  uint32_t di = GPDMA_CH_CTRL_DI;
478  uint32_t si = GPDMA_CH_CTRL_SI;
479
480  if (n < 0 || n > (int) GPDMA_CH_CTRL_TSZ_MAX) {
481    return -RTEMS_INVALID_SIZE;
482  }
483
484  /* Try to reserve DMA support for this bus */
485  if (lpc24xx_ssp_dma_data.bus == NULL) {
486    rtems_interrupt_disable( level);
487    if (lpc24xx_ssp_dma_data.bus == NULL) {
488      lpc24xx_ssp_dma_data.bus = e;
489    }
490    rtems_interrupt_enable( level);
491
492    /* Try to obtain DMA channels */
493    if (lpc24xx_ssp_dma_data.bus == e) {
494      bool channel_0 = lpc24xx_dma_channel_obtain( 0);
495      bool channel_1 = lpc24xx_dma_channel_obtain( 1);
496
497      if (!channel_0 && channel_1) {
498        lpc24xx_dma_channel_release( 1);
499        lpc24xx_ssp_dma_data.bus = NULL;
500      } else if (channel_0 && !channel_1) {
501        lpc24xx_dma_channel_release( 0);
502        lpc24xx_ssp_dma_data.bus = NULL;
503      } else if (!channel_0 || !channel_1) {
504        lpc24xx_ssp_dma_data.bus = NULL;
505      }
506    }
507  }
508
509  /* Check if DMA support is available */
510  if (lpc24xx_ssp_dma_data.bus != e
511    || lpc24xx_ssp_dma_data.status != LPC24XX_SSP_DMA_AVAILABLE) {
512    return -RTEMS_RESOURCE_IN_USE;
513  }
514
515  /* Set DMA support status and parameter */
516  lpc24xx_ssp_dma_data.status = LPC24XX_SSP_DMA_WAIT;
517  lpc24xx_ssp_dma_data.done = done;
518  lpc24xx_ssp_dma_data.n = n;
519  lpc24xx_ssp_dma_data.arg = arg;
520
521  /* Enable DMA on SSP */
522  ssp->dmacr = SSP_DMACR_RXDMAE | SSP_DMACR_TXDMAE;
523
524  /* Receive */
525  if (in != NULL) {
526    receive_channel->dest = (uint32_t) in;
527  } else {
528    receive_channel->dest = (uint32_t) &lpc24xx_ssp_trash;
529    di = 0;
530  }
531  receive_channel->src = (uint32_t) &ssp->dr;
532  receive_channel->lli = 0;
533  receive_channel->ctrl = SET_GPDMA_CH_CTRL_TSZ( 0, n)
534    | SET_GPDMA_CH_CTRL_SBSZ( 0, GPDMA_CH_CTRL_BSZ_4)
535    | SET_GPDMA_CH_CTRL_DBSZ( 0, GPDMA_CH_CTRL_BSZ_4)
536    | SET_GPDMA_CH_CTRL_SW( 0, GPDMA_CH_CTRL_W_8)
537    | SET_GPDMA_CH_CTRL_DW( 0, GPDMA_CH_CTRL_W_8)
538    | GPDMA_CH_CTRL_ITC
539    | di;
540  receive_channel->cfg = SET_GPDMA_CH_CFG_SRCPER( 0, GPDMA_CH_CFG_PER_SSP1_RX)
541    | SET_GPDMA_CH_CFG_FLOW( 0, GPDMA_CH_CFG_FLOW_PER_TO_MEM_DMA)
542    | GPDMA_CH_CFG_IE
543    | GPDMA_CH_CFG_ITC
544    | GPDMA_CH_CFG_EN;
545
546  /* Transmit */
547  if (out != NULL) {
548    transmit_channel->src = (uint32_t) out;
549  } else {
550    transmit_channel->src = (uint32_t) &e->idle_char;
551    si = 0;
552  }
553  transmit_channel->dest = (uint32_t) &ssp->dr;
554  transmit_channel->lli = 0;
555  transmit_channel->ctrl = SET_GPDMA_CH_CTRL_TSZ( 0, n)
556    | SET_GPDMA_CH_CTRL_SBSZ( 0, GPDMA_CH_CTRL_BSZ_4)
557    | SET_GPDMA_CH_CTRL_DBSZ( 0, GPDMA_CH_CTRL_BSZ_4)
558    | SET_GPDMA_CH_CTRL_SW( 0, GPDMA_CH_CTRL_W_8)
559    | SET_GPDMA_CH_CTRL_DW( 0, GPDMA_CH_CTRL_W_8)
560    | GPDMA_CH_CTRL_ITC
561    | si;
562  transmit_channel->cfg = SET_GPDMA_CH_CFG_DESTPER( 0, GPDMA_CH_CFG_PER_SSP1_TX)
563    | SET_GPDMA_CH_CFG_FLOW( 0, GPDMA_CH_CFG_FLOW_MEM_TO_PER_DMA)
564    | GPDMA_CH_CFG_IE
565    | GPDMA_CH_CFG_ITC
566    | GPDMA_CH_CFG_EN;
567
568  return 0;
569}
570
571static int lpc24xx_ssp_read( rtems_libi2c_bus_t *bus, unsigned char *in, int n)
572{
573  return lpc24xx_ssp_read_write( bus, in, NULL, n);
574}
575
576static int lpc24xx_ssp_write(
577  rtems_libi2c_bus_t *bus,
578  unsigned char *out,
579  int n
580)
581{
582  return lpc24xx_ssp_read_write( bus, NULL, out, n);
583}
584
585static int lpc24xx_ssp_ioctl( rtems_libi2c_bus_t *bus, int cmd, void *arg)
586{
587  int rv = -1;
588  const rtems_libi2c_tfr_mode_t *tm = (const rtems_libi2c_tfr_mode_t *) arg;
589  rtems_libi2c_read_write_t *rw = (rtems_libi2c_read_write_t *) arg;
590  rtems_libi2c_read_write_async_t *rwa =
591    (rtems_libi2c_read_write_async_t *) arg;
592
593  switch (cmd) {
594    case RTEMS_LIBI2C_IOCTL_READ_WRITE:
595      rv = lpc24xx_ssp_read_write( bus, rw->rd_buf, rw->wr_buf, rw->byte_cnt);
596      break;
597    case RTEMS_LIBI2C_IOCTL_READ_WRITE_ASYNC:
598      rv = lpc24xx_ssp_read_write_async(
599        bus,
600        rwa->rd_buf,
601        rwa->wr_buf,
602        rwa->byte_cnt,
603        rwa->done,
604        rwa->arg
605      );
606      break;
607    case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
608      rv = lpc24xx_ssp_set_transfer_mode( bus, tm);
609      break;
610    default:
611      rv = -RTEMS_NOT_DEFINED;
612      break;
613  }
614
615  return rv;
616}
617
618static const rtems_libi2c_bus_ops_t lpc24xx_ssp_ops = {
619  .init = lpc24xx_ssp_init,
620  .send_start = lpc24xx_ssp_send_start,
621  .send_stop = lpc24xx_ssp_send_stop,
622  .send_addr = lpc24xx_ssp_send_addr,
623  .read_bytes = lpc24xx_ssp_read,
624  .write_bytes = lpc24xx_ssp_write,
625  .ioctl = lpc24xx_ssp_ioctl
626};
627
628static lpc24xx_ssp_bus_entry lpc24xx_ssp_bus_table [LPC24XX_SSP_NUMBER] = {
629  {
630    /* SSP 0 */
631    .bus = {
632      .ops = &lpc24xx_ssp_ops,
633      .size = sizeof( lpc24xx_ssp_bus_entry)
634    },
635    .regs = (volatile lpc24xx_ssp *) SSP0_BASE_ADDR,
636    .clock = 0,
637    .idle_char = 0xffffffff
638  }, {
639    /* SSP 1 */
640    .bus = {
641      .ops = &lpc24xx_ssp_ops,
642      .size = sizeof( lpc24xx_ssp_bus_entry)
643    },
644    .regs = (volatile lpc24xx_ssp *) SSP1_BASE_ADDR,
645    .clock = 0,
646    .idle_char = 0xffffffff
647  }
648};
649
650rtems_libi2c_bus_t * const lpc24xx_ssp_0 =
651  (rtems_libi2c_bus_t *) &lpc24xx_ssp_bus_table [0];
652
653rtems_libi2c_bus_t * const lpc24xx_ssp_1 =
654  (rtems_libi2c_bus_t *) &lpc24xx_ssp_bus_table [1];
Note: See TracBrowser for help on using the repository browser.