source: rtems/c/src/lib/libbsp/arm/lpc24xx/ssp/ssp.c @ 4a6cc2a

4.11
Last change on this file since 4a6cc2a was 4a6cc2a, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 8, 2011 at 10:39:46 AM

2011-11-08 Sebastian Huber <sebastian.huber@…>

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