source: rtems/c/src/lib/libbsp/arm/lpc24xx/ssp/ssp.c @ 82dcbc8

4.115
Last change on this file since 82dcbc8 was edf846e4, checked in by Sebastian Huber <sebastian.huber@…>, on 05/20/10 at 14:23:13

2010-05-20 Sebastian Huber <sebastian.huber@…>

  • include/lpc24xx.h, misc/dma-copy.c, misc/dma.c, misc/system-clocks.c, ssp/ssp.c, startup/bspstarthooks.c: Removed superfluous macros.
  • 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
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(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 ((mis & SSP_MIS_RORRIS) != 0) {
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(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 ((status & LPC24XX_SSP_DMA_TRANSFER_FLAG) == 0) {
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 ((tc & (GPDMA_STATUS_CH_0 | GPDMA_STATUS_CH_1)) != 0) {
125          status = LPC24XX_SSP_DMA_DONE;
126        } else if ((tc & GPDMA_STATUS_CH_0) != 0) {
127          status = LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_1;
128        } else if ((tc & GPDMA_STATUS_CH_1) != 0) {
129          status = LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_0;
130        }
131        break;
132      case LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_0:
133        if ((tc & GPDMA_STATUS_CH_1) != 0) {
134          status = LPC24XX_SSP_DMA_ERROR;
135        } else if ((tc & GPDMA_STATUS_CH_0) != 0) {
136          status = LPC24XX_SSP_DMA_DONE;
137        }
138        break;
139      case LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_1:
140        if ((tc & GPDMA_STATUS_CH_0) != 0) {
141          status = LPC24XX_SSP_DMA_ERROR;
142        } else if ((tc & GPDMA_STATUS_CH_1) != 0) {
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 ((regs->sr & SSP_SR_TFE) == 0) {
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 ((sr & SSP_SR_TNF) != 0 && m < LPC24XX_SSP_FIFO_SIZE) {
430      regs->dr = *out;
431      ++w;
432      out += dw;
433    }
434
435    /* Read */
436    if ((sr & SSP_SR_RNE) != 0) {
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 ((sr & SSP_SR_RNE) == 0);
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_interrupt_level level;
472  lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) bus;
473  volatile lpc24xx_ssp *ssp = e->regs;
474  volatile lpc24xx_dma_channel *receive_channel = GPDMA_CH_BASE_ADDR(0);
475  volatile lpc24xx_dma_channel *transmit_channel = GPDMA_CH_BASE_ADDR(1);
476  uint32_t di = GPDMA_CH_CTRL_DI;
477  uint32_t si = GPDMA_CH_CTRL_SI;
478
479  if (n < 0 || n > (int) GPDMA_CH_CTRL_TSZ_MAX) {
480    return -RTEMS_INVALID_SIZE;
481  }
482
483  /* Try to reserve DMA support for this bus */
484  if (lpc24xx_ssp_dma_data.bus == NULL) {
485    rtems_interrupt_disable(level);
486    if (lpc24xx_ssp_dma_data.bus == NULL) {
487      lpc24xx_ssp_dma_data.bus = e;
488    }
489    rtems_interrupt_enable(level);
490
491    /* Try to obtain DMA channels */
492    if (lpc24xx_ssp_dma_data.bus == e) {
493      rtems_status_code cs0 = lpc24xx_dma_channel_obtain(0);
494      rtems_status_code cs1 = lpc24xx_dma_channel_obtain(1);
495
496      if (cs0 != RTEMS_SUCCESSFUL || cs1 != RTEMS_SUCCESSFUL) {
497        if (cs0 == RTEMS_SUCCESSFUL) {
498          lpc24xx_dma_channel_release(0);
499        }
500        if (cs1 == RTEMS_SUCCESSFUL) {
501          lpc24xx_dma_channel_release(1);
502        }
503        lpc24xx_ssp_dma_data.bus = NULL;
504      }
505    }
506  }
507
508  /* Check if DMA support is available */
509  if (lpc24xx_ssp_dma_data.bus != e
510    || lpc24xx_ssp_dma_data.status != LPC24XX_SSP_DMA_AVAILABLE) {
511    return -RTEMS_RESOURCE_IN_USE;
512  }
513
514  /* Set DMA support status and parameter */
515  lpc24xx_ssp_dma_data.status = LPC24XX_SSP_DMA_WAIT;
516  lpc24xx_ssp_dma_data.done = done;
517  lpc24xx_ssp_dma_data.n = n;
518  lpc24xx_ssp_dma_data.arg = arg;
519
520  /* Enable DMA on SSP */
521  ssp->dmacr = SSP_DMACR_RXDMAE | SSP_DMACR_TXDMAE;
522
523  /* Receive */
524  if (in != NULL) {
525    receive_channel->desc.dest = (uint32_t) in;
526  } else {
527    receive_channel->desc.dest = (uint32_t) &lpc24xx_ssp_trash;
528    di = 0;
529  }
530  receive_channel->desc.src = (uint32_t) &ssp->dr;
531  receive_channel->desc.lli = 0;
532  receive_channel->desc.ctrl = SET_GPDMA_CH_CTRL_TSZ(0, n)
533    | SET_GPDMA_CH_CTRL_SBSZ(0, GPDMA_CH_CTRL_BSZ_4)
534    | SET_GPDMA_CH_CTRL_DBSZ(0, GPDMA_CH_CTRL_BSZ_4)
535    | SET_GPDMA_CH_CTRL_SW(0, GPDMA_CH_CTRL_W_8)
536    | SET_GPDMA_CH_CTRL_DW(0, GPDMA_CH_CTRL_W_8)
537    | GPDMA_CH_CTRL_ITC
538    | di;
539  receive_channel->cfg = SET_GPDMA_CH_CFG_SRCPER(0, GPDMA_CH_CFG_PER_SSP1_RX)
540    | SET_GPDMA_CH_CFG_FLOW(0, GPDMA_CH_CFG_FLOW_PER_TO_MEM_DMA)
541    | GPDMA_CH_CFG_IE
542    | GPDMA_CH_CFG_ITC
543    | GPDMA_CH_CFG_EN;
544
545  /* Transmit */
546  if (out != NULL) {
547    transmit_channel->desc.src = (uint32_t) out;
548  } else {
549    transmit_channel->desc.src = (uint32_t) &e->idle_char;
550    si = 0;
551  }
552  transmit_channel->desc.dest = (uint32_t) &ssp->dr;
553  transmit_channel->desc.lli = 0;
554  transmit_channel->desc.ctrl = SET_GPDMA_CH_CTRL_TSZ(0, n)
555    | SET_GPDMA_CH_CTRL_SBSZ(0, GPDMA_CH_CTRL_BSZ_4)
556    | SET_GPDMA_CH_CTRL_DBSZ(0, GPDMA_CH_CTRL_BSZ_4)
557    | SET_GPDMA_CH_CTRL_SW(0, GPDMA_CH_CTRL_W_8)
558    | SET_GPDMA_CH_CTRL_DW(0, GPDMA_CH_CTRL_W_8)
559    | GPDMA_CH_CTRL_ITC
560    | si;
561  transmit_channel->cfg = SET_GPDMA_CH_CFG_DESTPER(0, GPDMA_CH_CFG_PER_SSP1_TX)
562    | SET_GPDMA_CH_CFG_FLOW(0, GPDMA_CH_CFG_FLOW_MEM_TO_PER_DMA)
563    | GPDMA_CH_CFG_IE
564    | GPDMA_CH_CFG_ITC
565    | GPDMA_CH_CFG_EN;
566
567  return 0;
568}
569
570static int lpc24xx_ssp_read(rtems_libi2c_bus_t *bus, unsigned char *in, int n)
571{
572  return lpc24xx_ssp_read_write(bus, in, NULL, n);
573}
574
575static int lpc24xx_ssp_write(
576  rtems_libi2c_bus_t *bus,
577  unsigned char *out,
578  int n
579)
580{
581  return lpc24xx_ssp_read_write(bus, NULL, out, n);
582}
583
584static int lpc24xx_ssp_ioctl(rtems_libi2c_bus_t *bus, int cmd, void *arg)
585{
586  int rv = -1;
587  const rtems_libi2c_tfr_mode_t *tm = (const rtems_libi2c_tfr_mode_t *) arg;
588  rtems_libi2c_read_write_t *rw = (rtems_libi2c_read_write_t *) arg;
589  rtems_libi2c_read_write_async_t *rwa =
590    (rtems_libi2c_read_write_async_t *) arg;
591
592  switch (cmd) {
593    case RTEMS_LIBI2C_IOCTL_READ_WRITE:
594      rv = lpc24xx_ssp_read_write(bus, rw->rd_buf, rw->wr_buf, rw->byte_cnt);
595      break;
596    case RTEMS_LIBI2C_IOCTL_READ_WRITE_ASYNC:
597      rv = lpc24xx_ssp_read_write_async(
598        bus,
599        rwa->rd_buf,
600        rwa->wr_buf,
601        rwa->byte_cnt,
602        rwa->done,
603        rwa->arg
604      );
605      break;
606    case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
607      rv = lpc24xx_ssp_set_transfer_mode(bus, tm);
608      break;
609    default:
610      rv = -RTEMS_NOT_DEFINED;
611      break;
612  }
613
614  return rv;
615}
616
617static const rtems_libi2c_bus_ops_t lpc24xx_ssp_ops = {
618  .init = lpc24xx_ssp_init,
619  .send_start = lpc24xx_ssp_send_start,
620  .send_stop = lpc24xx_ssp_send_stop,
621  .send_addr = lpc24xx_ssp_send_addr,
622  .read_bytes = lpc24xx_ssp_read,
623  .write_bytes = lpc24xx_ssp_write,
624  .ioctl = lpc24xx_ssp_ioctl
625};
626
627static lpc24xx_ssp_bus_entry lpc24xx_ssp_bus_table [LPC24XX_SSP_NUMBER] = {
628  {
629    /* SSP 0 */
630    .bus = {
631      .ops = &lpc24xx_ssp_ops,
632      .size = sizeof(lpc24xx_ssp_bus_entry)
633    },
634    .regs = (volatile lpc24xx_ssp *) SSP0_BASE_ADDR,
635    .clock = 0,
636    .idle_char = 0xffffffff
637  }, {
638    /* SSP 1 */
639    .bus = {
640      .ops = &lpc24xx_ssp_ops,
641      .size = sizeof(lpc24xx_ssp_bus_entry)
642    },
643    .regs = (volatile lpc24xx_ssp *) SSP1_BASE_ADDR,
644    .clock = 0,
645    .idle_char = 0xffffffff
646  }
647};
648
649rtems_libi2c_bus_t * const lpc24xx_ssp_0 =
650  (rtems_libi2c_bus_t *) &lpc24xx_ssp_bus_table [0];
651
652rtems_libi2c_bus_t * const lpc24xx_ssp_1 =
653  (rtems_libi2c_bus_t *) &lpc24xx_ssp_bus_table [1];
Note: See TracBrowser for help on using the repository browser.