source: rtems/c/src/lib/libcpu/powerpc/mpc55xx/dspi/dspi.c @ a762dc2

4.11
Last change on this file since a762dc2 was a762dc2, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 23, 2012 at 10:19:22 AM

Support for MPC5643L.

Rework of the start sequence to reduce the amount assembler code and to
support configuration tables which may be provided by the application.

  • Property mode set to 100644
File size: 19.0 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup mpc55xx_dspi
5 *
6 * @brief Source file for the LibI2C bus driver for the Deserial Serial Peripheral Interface (DSPI).
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 <mpc55xx/regs.h>
22#include <mpc55xx/dspi.h>
23#include <mpc55xx/mpc55xx.h>
24
25#include <bsp/irq.h>
26
27#include <libcpu/powerpc-utility.h>
28
29#define RTEMS_STATUS_CHECKS_USE_PRINTK
30
31#include <rtems/status-checks.h>
32
33#define MPC55XX_DSPI_FIFO_SIZE 4
34
35#define MPC55XX_DSPI_CTAR_NUMBER 8
36
37#define MPC55XX_DSPI_CTAR_DEFAULT 0
38
39#define MPC55XX_DSPI_EDMA_MAGIC_SIZE 128
40
41#define MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE 63
42
43typedef struct {
44        uint32_t scaler : 26;
45        uint32_t pbr : 2;
46        uint32_t br : 4;
47} mpc55xx_dspi_baudrate_scaler_entry;
48
49static const mpc55xx_dspi_baudrate_scaler_entry mpc55xx_dspi_baudrate_scaler_table [MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE] = {
50        { 4, 0, 0 },
51        { 6, 1, 0 },
52        { 8, 0, 1 },
53        { 10, 2, 0 },
54        { 12, 1, 1 },
55        { 14, 3, 0 },
56        { 16, 0, 3 },
57        { 18, 1, 2 },
58        { 20, 2, 1 },
59        { 24, 1, 3 },
60        { 28, 3, 1 },
61        { 30, 2, 2 },
62        { 32, 0, 4 },
63        { 40, 2, 3 },
64        { 42, 3, 2 },
65        { 48, 1, 4 },
66        { 56, 3, 3 },
67        { 64, 0, 5 },
68        { 80, 2, 4 },
69        { 96, 1, 5 },
70        { 112, 3, 4 },
71        { 128, 0, 6 },
72        { 160, 2, 5 },
73        { 192, 1, 6 },
74        { 224, 3, 5 },
75        { 256, 0, 7 },
76        { 320, 2, 6 },
77        { 384, 1, 7 },
78        { 448, 3, 6 },
79        { 512, 0, 8 },
80        { 640, 2, 7 },
81        { 768, 1, 8 },
82        { 896, 3, 7 },
83        { 1024, 0, 9 },
84        { 1280, 2, 8 },
85        { 1536, 1, 9 },
86        { 1792, 3, 8 },
87        { 2048, 0, 10 },
88        { 2560, 2, 9 },
89        { 3072, 1, 10 },
90        { 3584, 3, 9 },
91        { 4096, 0, 11 },
92        { 5120, 2, 10 },
93        { 6144, 1, 11 },
94        { 7168, 3, 10 },
95        { 8192, 0, 12 },
96        { 10240, 2, 11 },
97        { 12288, 1, 12 },
98        { 14336, 3, 11 },
99        { 16384, 0, 13 },
100        { 20480, 2, 12 },
101        { 24576, 1, 13 },
102        { 28672, 3, 12 },
103        { 32768, 0, 14 },
104        { 40960, 2, 13 },
105        { 49152, 1, 14 },
106        { 57344, 3, 13 },
107        { 65536, 0, 15 },
108        { 81920, 2, 14 },
109        { 98304, 1, 15 },
110        { 114688, 3, 14 },
111        { 163840, 2, 15 },
112        { 229376, 3, 15 },
113};
114
115static void mpc55xx_dspi_edma_done( mpc55xx_edma_channel_entry *e, uint32_t error_status)
116{
117        rtems_semaphore_release( e->id);
118
119        if (error_status != 0) {
120                RTEMS_SYSLOG_ERROR( "eDMA error: 0x%08x\n", error_status);
121        }
122}
123
124static mpc55xx_dspi_baudrate_scaler_entry mpc55xx_dspi_search_baudrate_scaler( uint32_t scaler, int min, int mid, int max)
125{
126        if (scaler <= mpc55xx_dspi_baudrate_scaler_table [mid].scaler) {
127                max = mid;
128        } else {
129                min = mid;
130        }
131        mid = (min + max) / 2;
132        if (mid == min) {
133                return mpc55xx_dspi_baudrate_scaler_table [max];
134        } else {
135                return mpc55xx_dspi_search_baudrate_scaler( scaler, min, mid, max);
136        }
137}
138
139static uint32_t mpc55xx_dspi_push_data [8 * MPC55XX_DSPI_NUMBER] __attribute__ ((aligned (32)));
140
141static inline void mpc55xx_dspi_store_push_data( mpc55xx_dspi_bus_entry *e)
142{
143        mpc55xx_dspi_push_data [e->table_index * 8] = e->push_data.R;
144        rtems_cache_flush_multiple_data_lines( &mpc55xx_dspi_push_data [e->table_index * 8], 4);
145}
146
147static inline uint32_t mpc55xx_dspi_push_data_address( mpc55xx_dspi_bus_entry *e)
148{
149        return (uint32_t) &mpc55xx_dspi_push_data [e->table_index * 8];
150}
151
152static inline uint32_t mpc55xx_dspi_nirvana_address( mpc55xx_dspi_bus_entry *e)
153{
154        return (uint32_t) &mpc55xx_dspi_push_data [e->table_index * 8 + 1];
155}
156
157static rtems_status_code mpc55xx_dspi_init( rtems_libi2c_bus_t *bus)
158{
159        rtems_status_code sc = RTEMS_SUCCESSFUL;
160        mpc55xx_dspi_bus_entry *e = (mpc55xx_dspi_bus_entry *) bus;
161        union DSPI_MCR_tag mcr = MPC55XX_ZERO_FLAGS;
162        union DSPI_CTAR_tag ctar = MPC55XX_ZERO_FLAGS;
163        union DSPI_RSER_tag rser = MPC55XX_ZERO_FLAGS;
164        struct tcd_t tcd_push = EDMA_TCD_DEFAULT;
165        int i = 0;
166
167        /* eDMA receive */
168        sc = rtems_semaphore_create (
169                rtems_build_name ( 'S', 'P', 'I', 'R'),
170                0,
171                RTEMS_SIMPLE_BINARY_SEMAPHORE,
172                0,
173                &e->edma_receive.id
174        );
175        RTEMS_CHECK_SC( sc, "create receive update semaphore");
176
177        sc = mpc55xx_edma_obtain_channel( &e->edma_receive, MPC55XX_INTC_DEFAULT_PRIORITY);
178        RTEMS_CHECK_SC( sc, "obtain receive eDMA channel");
179
180        /* eDMA transmit */
181        sc = rtems_semaphore_create (
182                rtems_build_name ( 'S', 'P', 'I', 'T'),
183                0,
184                RTEMS_SIMPLE_BINARY_SEMAPHORE,
185                0,
186                &e->edma_transmit.id
187        );
188        RTEMS_CHECK_SC( sc, "create transmit update semaphore");
189
190        sc = mpc55xx_edma_obtain_channel( &e->edma_transmit, MPC55XX_INTC_DEFAULT_PRIORITY);
191        RTEMS_CHECK_SC( sc, "obtain transmit eDMA channel");
192
193        sc = mpc55xx_edma_obtain_channel( &e->edma_push, MPC55XX_INTC_DEFAULT_PRIORITY);
194        RTEMS_CHECK_SC( sc, "obtain push eDMA channel");
195
196        tcd_push.SADDR = mpc55xx_dspi_push_data_address( e);
197        tcd_push.SDF.B.SSIZE = 2;
198        tcd_push.SDF.B.SOFF = 0;
199        tcd_push.DADDR = (uint32_t) &e->regs->PUSHR.R;
200        tcd_push.SDF.B.DSIZE = 2;
201        tcd_push.CDF.B.DOFF = 0;
202        tcd_push.NBYTES = 4;
203        tcd_push.CDF.B.CITER = 1;
204        tcd_push.BMF.B.BITER = 1;
205
206        EDMA.TCD [e->edma_push.channel] = tcd_push;
207
208        /* Module Control Register */
209        mcr.B.MSTR = e->master ? 1 : 0;
210        mcr.B.CONT_SCKE = 0;
211        mcr.B.DCONF = 0;
212        mcr.B.FRZ = 0;
213        mcr.B.MTFE = 0;
214        mcr.B.PCSSE = 0;
215        mcr.B.ROOE = 0;
216        mcr.B.PCSIS0 = 1;
217        mcr.B.PCSIS1 = 1;
218        mcr.B.PCSIS2 = 1;
219        mcr.B.PCSIS3 = 1;
220        mcr.B.PCSIS5 = 1;
221        mcr.B.MDIS = 0;
222        mcr.B.DIS_TXF = 0;
223        mcr.B.DIS_RXF = 0;
224        mcr.B.CLR_TXF = 0;
225        mcr.B.CLR_RXF = 0;
226        mcr.B.SMPL_PT = 0;
227        mcr.B.HALT = 0;
228
229        e->regs->MCR.R = mcr.R;
230
231        /* Clock and Transfer Attributes Register */
232        ctar.B.DBR = 0;
233        ctar.B.FMSZ = 0x7;
234        ctar.B.CPOL = 0;
235        ctar.B.CPHA = 0;
236        ctar.B.LSBFE = 0;
237        ctar.B.PCSSCK = 0;
238        ctar.B.PASC = 0;
239        ctar.B.PDT = 0;
240        ctar.B.PBR = 0;
241        ctar.B.CSSCK = 0;
242        ctar.B.ASC = 0;
243        ctar.B.DT = 0;
244        ctar.B.BR = 0;
245
246        for (i = 0; i < MPC55XX_DSPI_CTAR_NUMBER; ++i) {
247                e->regs->CTAR [i].R = ctar.R;
248        }
249
250        /* DMA/Interrupt Request Select and Enable Register */
251        rser.B.TFFFRE = 1;
252        rser.B.TFFFDIRS = 1;
253        rser.B.RFDFRE = 1;
254        rser.B.RFDFDIRS = 1;
255
256        e->regs->RSER.R = rser.R;
257
258        return RTEMS_SUCCESSFUL;
259}
260
261static rtems_status_code mpc55xx_dspi_send_start( rtems_libi2c_bus_t *bus)
262{
263        mpc55xx_dspi_bus_entry *e = (mpc55xx_dspi_bus_entry *) bus;
264
265        /* Reset chip selects */
266        e->push_data.B.PCS0 = 0;
267        e->push_data.B.PCS1 = 0;
268        e->push_data.B.PCS2 = 0;
269        e->push_data.B.PCS3 = 0;
270        e->push_data.B.PCS4 = 0;
271        e->push_data.B.PCS5 = 0;
272        mpc55xx_dspi_store_push_data( e);
273
274        return RTEMS_SUCCESSFUL;
275}
276
277static rtems_status_code mpc55xx_dspi_send_stop( rtems_libi2c_bus_t *bus)
278{
279        return RTEMS_SUCCESSFUL;
280}
281
282static rtems_status_code mpc55xx_dspi_send_addr( rtems_libi2c_bus_t *bus, uint32_t addr, int rw)
283{
284        mpc55xx_dspi_bus_entry *e = (mpc55xx_dspi_bus_entry *) bus;
285        union DSPI_SR_tag sr = MPC55XX_ZERO_FLAGS;
286
287        /* Flush transmit and receive FIFO */
288        e->regs->MCR.B.CLR_TXF = 1;
289        e->regs->MCR.B.CLR_RXF = 1;
290
291        /* Clear status flags */
292        sr.B.EOQF = 1;
293        sr.B.TFFF = 1;
294        sr.B.RFDF = 1;
295        e->regs->SR.R = sr.R;
296
297        /* Frame command */
298        e->push_data.R = 0;
299        e->push_data.B.CONT = 0;
300        e->push_data.B.CTAS = MPC55XX_DSPI_CTAR_DEFAULT;
301        e->push_data.B.EOQ = 0;
302        e->push_data.B.CTCNT = 0;
303        switch (addr) {
304                case 0:
305                        e->push_data.B.PCS0 = 1;
306                        break;
307                case 1:
308                        e->push_data.B.PCS1 = 1;
309                        break;
310                case 2:
311                        e->push_data.B.PCS2 = 1;
312                        break;
313                case 3:
314                        e->push_data.B.PCS3 = 1;
315                        break;
316                case 4:
317                        e->push_data.B.PCS4 = 1;
318                        break;
319                case 5:
320                        e->push_data.B.PCS5 = 1;
321                        break;
322                default:
323                        return -RTEMS_INVALID_ADDRESS;
324        }
325        mpc55xx_dspi_store_push_data( e);
326
327        return RTEMS_SUCCESSFUL;
328}
329
330/* FIXME, TODO */
331extern uint32_t bsp_clock_speed;
332
333static int mpc55xx_dspi_set_transfer_mode( rtems_libi2c_bus_t *bus, const rtems_libi2c_tfr_mode_t *mode)
334{
335        mpc55xx_dspi_bus_entry *e = (mpc55xx_dspi_bus_entry *) bus;
336        union DSPI_CTAR_tag ctar = MPC55XX_ZERO_FLAGS;
337
338        if (mode->bits_per_char != 8) {
339                return -RTEMS_INVALID_NUMBER;
340        }
341
342        e->idle_char = mode->idle_char;
343
344        ctar.R = e->regs->CTAR [MPC55XX_DSPI_CTAR_DEFAULT].R;
345
346        ctar.B.PCSSCK = 0;
347        ctar.B.CSSCK = 0;
348        ctar.B.PASC = 0;
349        ctar.B.ASC = 0;
350
351        ctar.B.LSBFE = mode->lsb_first ? 1 : 0;
352        ctar.B.CPOL = mode->clock_inv ? 1 : 0;
353        ctar.B.CPHA = mode->clock_phs ? 1 : 0;
354
355        if (mode->baudrate != e->baud) {
356                uint32_t scaler = bsp_clock_speed / mode->baudrate;
357                mpc55xx_dspi_baudrate_scaler_entry bse = mpc55xx_dspi_search_baudrate_scaler( scaler, 0, MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE / 2, MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE);
358
359                ctar.B.PBR = bse.pbr;
360                ctar.B.BR = bse.br;
361
362                e->baud = mode->baudrate;
363        }
364
365        e->regs->CTAR [MPC55XX_DSPI_CTAR_DEFAULT].R = ctar.R;
366
367        return 0;
368}
369
370/**
371 * @brief Writes @a n characters from @a out to bus @a bus and synchronously stores the received data in @a in.
372 *
373 * eDMA channel usage for transmission:
374 * @dot
375 * digraph push {
376 *  push [label="Push Register"];
377 *  push_data [label="Push Data"];
378 *  idle_push_data [label="Idle Push Data"];
379 *  out [shape=box,label="Output Buffer"];
380 *  edge [color=red,fontcolor=red];
381 *  push -> idle_push_data [label="Transmit Request",URL="\ref mpc55xx_dspi_bus_entry::edma_transmit"];
382 *  push -> out [label="Transmit Request",URL="\ref mpc55xx_dspi_bus_entry::edma_transmit"];
383 *  out -> push_data [label="Channel Link",URL="\ref mpc55xx_dspi_bus_entry::edma_push"];
384 *  edge [color=blue,fontcolor=blue];
385 *  out -> push_data [label="Data"];
386 *  push_data -> push [label="Data"];
387 *  idle_push_data -> push [label="Data"];
388 * }
389 * @enddot
390 *
391 * eDMA channel usage for receiving:
392 * @dot
393 * digraph pop {
394 *  pop [label="Pop Register"];
395 *  nirvana [label="Nirvana"];
396 *  in [shape=box,label="Input Buffer"];
397 *  edge [color=red,fontcolor=red];
398 *  pop -> nirvana [label="Receive Request",URL="\ref mpc55xx_dspi_bus_entry::edma_receive"];
399 *  pop -> in [label="Receive Request",URL="\ref mpc55xx_dspi_bus_entry::edma_receive"];
400 *  edge [color=blue,fontcolor=blue];
401 *  pop -> nirvana [label="Data"];
402 *  pop -> in [label="Data"];
403 * }
404 * @enddot
405 */
406static int mpc55xx_dspi_read_write( rtems_libi2c_bus_t *bus, unsigned char *in, const unsigned char *out, int n)
407{
408        mpc55xx_dspi_bus_entry *e = (mpc55xx_dspi_bus_entry *) bus;
409
410        /* Non cache aligned characters */
411        int n_nc = n;
412
413        /* Cache aligned characters */
414        int n_c = 0;
415
416        /* Register addresses */
417        volatile void *push = &e->regs->PUSHR.R;
418        volatile void *pop = &e->regs->POPR.R;
419        volatile union DSPI_SR_tag *status = &e->regs->SR;
420
421        /* Push and pop data */
422        union DSPI_PUSHR_tag push_data = e->push_data;
423        union DSPI_POPR_tag pop_data;
424
425        /* Status register */
426        union DSPI_SR_tag sr;
427
428        /* Read and write indices */
429        int r = 0;
430        int w = 0;
431
432        if (n == 0) {
433                return 0;
434        } else if (in == NULL && out == NULL) {
435                return -RTEMS_INVALID_ADDRESS;
436        }
437
438        if (n > MPC55XX_DSPI_EDMA_MAGIC_SIZE) {
439                n_nc = (int) mpc55xx_non_cache_aligned_size( in);
440                n_c = (int) mpc55xx_cache_aligned_size( in, (size_t) n);
441                if (n_c > EDMA_TCD_BITER_LINKED_SIZE) {
442                        RTEMS_SYSLOG_WARNING( "buffer size out of range, cannot use eDMA\n");
443                        n_nc = n;
444                        n_c = 0;
445                } else if (n_nc + n_c != n) {
446                        RTEMS_SYSLOG_WARNING( "input buffer not proper cache aligned, cannot use eDMA\n");
447                        n_nc = n;
448                        n_c = 0;
449                }
450        }
451
452#ifdef DEBUG
453        if (e->regs->SR.B.TXCTR != e->regs->SR.B.RXCTR) {
454                RTEMS_SYSLOG_WARNING( "FIFO counter not equal\n");
455        }
456#endif /* DEBUG */
457
458        /* Direct IO */
459        if (out == NULL) {
460                push_data.B.TXDATA = e->idle_char;
461                while (r < n_nc || w < n_nc) {
462                        /* Wait for available FIFO */
463                        do {
464                                sr.R = status->R;
465                        } while (sr.B.TXCTR == MPC55XX_DSPI_FIFO_SIZE && sr.B.RXCTR == 0);
466
467                        /* Write */
468                        if (w < n_nc && (w - r) < MPC55XX_DSPI_FIFO_SIZE && sr.B.TXCTR != MPC55XX_DSPI_FIFO_SIZE) {
469                                ++w;
470                                ppc_write_word( push_data.R, push);
471                        }
472
473                        /* Read */
474                        if (r < n_nc && sr.B.RXCTR != 0) {
475                                pop_data.R = ppc_read_word( pop);
476                                in [r] = (unsigned char) pop_data.B.RXDATA;
477                                ++r;
478                        }
479                }
480        } else if (in == NULL) {
481                while (r < n_nc || w < n_nc) {
482                        /* Wait for available FIFO */
483                        do {
484                                sr.R = status->R;
485                        } while (sr.B.TXCTR == MPC55XX_DSPI_FIFO_SIZE && sr.B.RXCTR == 0);
486
487                        /* Write */
488                        if (w < n_nc && (w - r) < MPC55XX_DSPI_FIFO_SIZE && sr.B.TXCTR != MPC55XX_DSPI_FIFO_SIZE) {
489                                push_data.B.TXDATA = out [w];
490                                ++w;
491                                ppc_write_word( push_data.R, push);
492                        }
493
494                        /* Read */
495                        if (r < n_nc && sr.B.RXCTR != 0) {
496                                pop_data.R = ppc_read_word( pop);
497                                ++r;
498                        }
499                }
500        } else {
501                while (r < n_nc || w < n_nc) {
502                        /* Wait for available FIFO */
503                        do {
504                                sr.R = status->R;
505                        } while (sr.B.TXCTR == MPC55XX_DSPI_FIFO_SIZE && sr.B.RXCTR == 0);
506
507                        /* Write */
508                        if (w < n_nc && (w - r) < MPC55XX_DSPI_FIFO_SIZE && sr.B.TXCTR != MPC55XX_DSPI_FIFO_SIZE) {
509                                push_data.B.TXDATA = out [w];
510                                ++w;
511                                ppc_write_word( push_data.R, push);
512                        }
513
514                        /* Read */
515                        if (r < n_nc && sr.B.RXCTR != 0) {
516                                pop_data.R = ppc_read_word( pop);
517                                in [r] = (unsigned char) pop_data.B.RXDATA;
518                                ++r;
519                        }
520                }
521        }
522
523        /* eDMA transfers */
524        if (n_c > 0) {
525                rtems_status_code sc = RTEMS_SUCCESSFUL;
526                unsigned char *in_c = in + n_nc;
527                const unsigned char *out_c = out + n_nc;
528                struct tcd_t tcd_transmit = EDMA_TCD_DEFAULT;
529                struct tcd_t tcd_receive = EDMA_TCD_DEFAULT;
530
531                /* Cache operations */
532                rtems_cache_flush_multiple_data_lines( out_c, (size_t) n_c);
533                rtems_cache_invalidate_multiple_data_lines( in_c, (size_t) n_c);
534
535                /* Set transmit TCD */
536                if (out == NULL) {
537                        e->push_data.B.TXDATA = e->idle_char;
538                        mpc55xx_dspi_store_push_data( e);
539                        tcd_transmit.SADDR = mpc55xx_dspi_push_data_address( e);
540                        tcd_transmit.SDF.B.SSIZE = 2;
541                        tcd_transmit.SDF.B.SOFF = 0;
542                        tcd_transmit.DADDR = (uint32_t) push;
543                        tcd_transmit.SDF.B.DSIZE = 2;
544                        tcd_transmit.CDF.B.DOFF = 0;
545                        tcd_transmit.NBYTES = 4;
546                        tcd_transmit.CDF.B.CITER = n_c;
547                        tcd_transmit.BMF.B.BITER = n_c;
548                } else {
549                        EDMA.CDSBR.R = e->edma_transmit.channel;
550                        tcd_transmit.SADDR = (uint32_t) out_c;
551                        tcd_transmit.SDF.B.SSIZE = 0;
552                        tcd_transmit.SDF.B.SOFF = 1;
553                        tcd_transmit.DADDR = mpc55xx_dspi_push_data_address( e) + 3;
554                        tcd_transmit.SDF.B.DSIZE = 0;
555                        tcd_transmit.CDF.B.DOFF = 0;
556                        tcd_transmit.NBYTES = 1;
557                        tcd_transmit.CDF.B.CITERE_LINK = 1;
558                        tcd_transmit.BMF.B.BITERE_LINK = 1;
559                        tcd_transmit.BMF.B.MAJORLINKCH = e->edma_push.channel;
560                        tcd_transmit.CDF.B.CITER = EDMA_TCD_LINK_AND_BITER( e->edma_push.channel, n_c);
561                        tcd_transmit.BMF.B.BITER = EDMA_TCD_LINK_AND_BITER( e->edma_push.channel, n_c);
562                        tcd_transmit.BMF.B.MAJORE_LINK = 1;
563                }
564                tcd_transmit.BMF.B.D_REQ = 1;
565                tcd_transmit.BMF.B.INT_MAJ = 1;
566                EDMA.TCD [e->edma_transmit.channel] = tcd_transmit;
567
568                /* Set receive TCD */
569                if (in == NULL) {
570                        tcd_receive.CDF.B.DOFF = 0;
571                        tcd_receive.DADDR = mpc55xx_dspi_nirvana_address( e);
572                } else {
573                        tcd_receive.CDF.B.DOFF = 1;
574                        tcd_receive.DADDR = (uint32_t) in_c;
575                }
576                tcd_receive.SADDR = (uint32_t) pop + 3;
577                tcd_receive.SDF.B.SSIZE = 0;
578                tcd_receive.SDF.B.SOFF = 0;
579                tcd_receive.SDF.B.DSIZE = 0;
580                tcd_receive.NBYTES = 1;
581                tcd_receive.BMF.B.D_REQ = 1;
582                tcd_receive.BMF.B.INT_MAJ = 1;
583                tcd_receive.CDF.B.CITER = n_c;
584                tcd_receive.BMF.B.BITER = n_c;
585                EDMA.TCD [e->edma_receive.channel] = tcd_receive;
586
587                /* Clear request flags */
588                sr.R = 0;
589                sr.B.TFFF = 1;
590                sr.B.RFDF = 1;
591                status->R = sr.R;
592
593                /* Enable hardware requests */
594                mpc55xx_edma_enable_hardware_requests( e->edma_receive.channel, true);
595                mpc55xx_edma_enable_hardware_requests( e->edma_transmit.channel, true);
596
597                /* Wait for transmit update */
598                sc = rtems_semaphore_obtain( e->edma_transmit.id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
599                RTEMS_CHECK_SC_RV( sc, "transmit update");
600
601                /* Wait for receive update */
602                sc = rtems_semaphore_obtain( e->edma_receive.id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
603                RTEMS_CHECK_SC_RV( sc, "receive update");
604        }
605
606        return n;
607}
608
609/**
610 * @brief Reads @a n characters from bus @a bus and stores it in @a in.
611 *
612 * Writes idle characters to receive data.
613 *
614 * @see mpc55xx_dspi_read_write().
615 */
616static int mpc55xx_dspi_read( rtems_libi2c_bus_t *bus, unsigned char *in, int n)
617{
618        return mpc55xx_dspi_read_write( bus, in, NULL, n);
619}
620
621/**
622 * @brief Writes @a n characters from @a out to bus @a bus.
623 *
624 * Discards the synchronously received data.
625 *
626 * @see mpc55xx_dspi_read_write().
627 */
628static int mpc55xx_dspi_write( rtems_libi2c_bus_t *bus, unsigned char *out, int n)
629{
630        return mpc55xx_dspi_read_write( bus, NULL, out, n);
631}
632
633static int mpc55xx_dspi_ioctl( rtems_libi2c_bus_t *bus, int cmd, void *arg)
634{
635        int rv = -1;
636        switch (cmd) {
637                case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
638                        rv = mpc55xx_dspi_set_transfer_mode( bus, (const rtems_libi2c_tfr_mode_t *) arg);
639                        break;
640                case RTEMS_LIBI2C_IOCTL_READ_WRITE:
641                        rv = mpc55xx_dspi_read_write(
642                                bus,
643                                ((rtems_libi2c_read_write_t *) arg)->rd_buf,
644                                ((rtems_libi2c_read_write_t *) arg)->wr_buf,
645                                ((rtems_libi2c_read_write_t *) arg)->byte_cnt
646                        );
647                        break;
648                default:
649                        rv = -RTEMS_NOT_DEFINED;
650                        break;
651        }
652        return rv;
653}
654
655static const rtems_libi2c_bus_ops_t mpc55xx_dspi_ops = {
656        .init        = mpc55xx_dspi_init,
657        .send_start  = mpc55xx_dspi_send_start,
658        .send_stop   = mpc55xx_dspi_send_stop,
659        .send_addr   = mpc55xx_dspi_send_addr,
660        .read_bytes  = mpc55xx_dspi_read,
661        .write_bytes = mpc55xx_dspi_write,
662        .ioctl       = mpc55xx_dspi_ioctl
663};
664
665mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [MPC55XX_DSPI_NUMBER] = {
666        {
667                /* DSPI A */
668                .bus = {
669                        .ops = &mpc55xx_dspi_ops,
670                        .size = sizeof( mpc55xx_dspi_bus_entry)
671                },
672                .table_index = 0,
673                .bus_number = 0,
674                .regs = &DSPI_A,
675                .master = true,
676                .push_data = MPC55XX_ZERO_FLAGS,
677                .edma_transmit = {
678                        .channel = 32,
679                        .done = mpc55xx_dspi_edma_done,
680                        .id = RTEMS_ID_NONE
681                },
682                .edma_push = {
683                        .channel = 43,
684                        .done = mpc55xx_dspi_edma_done,
685                        .id = RTEMS_ID_NONE
686                },
687                .edma_receive = {
688                        .channel = 33,
689                        .done = mpc55xx_dspi_edma_done,
690                        .id = RTEMS_ID_NONE
691                },
692                .idle_char = 0xffffffff,
693                .baud = 0
694        }, {
695                /* DSPI B */
696                .bus = {
697                        .ops = &mpc55xx_dspi_ops,
698                        .size = sizeof( mpc55xx_dspi_bus_entry)
699                },
700                .table_index = 1,
701                .bus_number = 0,
702                .regs = &DSPI_B,
703                .master = true,
704                .push_data = MPC55XX_ZERO_FLAGS,
705                .edma_transmit = {
706                        .channel = 12,
707                        .done = mpc55xx_dspi_edma_done,
708                        .id = RTEMS_ID_NONE
709                },
710                .edma_push = {
711                        .channel = 10,
712                        .done = mpc55xx_dspi_edma_done,
713                        .id = RTEMS_ID_NONE
714                },
715                .edma_receive = {
716                        .channel = 13,
717                        .done = mpc55xx_dspi_edma_done,
718                        .id = RTEMS_ID_NONE
719                },
720                .idle_char = 0xffffffff,
721                .baud = 0
722        }, {
723                /* DSPI C */
724                .bus = {
725                        .ops = &mpc55xx_dspi_ops,
726                        .size = sizeof( mpc55xx_dspi_bus_entry)
727                },
728                .table_index = 2,
729                .bus_number = 0,
730                .regs = &DSPI_C,
731                .master = true,
732                .push_data = MPC55XX_ZERO_FLAGS,
733                .edma_transmit = {
734                        .channel = 14,
735                        .done = mpc55xx_dspi_edma_done,
736                        .id = RTEMS_ID_NONE
737                },
738                .edma_push = {
739                        .channel = 11,
740                        .done = mpc55xx_dspi_edma_done,
741                        .id = RTEMS_ID_NONE
742                },
743                .edma_receive = {
744                        .channel = 15,
745                        .done = mpc55xx_dspi_edma_done,
746                        .id = RTEMS_ID_NONE
747                },
748                .idle_char = 0xffffffff,
749                .baud = 0
750#ifdef DSPI_D
751        }, {
752                /* DSPI D */
753                .bus = {
754                        .ops = &mpc55xx_dspi_ops,
755                        .size = sizeof( mpc55xx_dspi_bus_entry)
756                },
757                .table_index = 3,
758                .bus_number = 0,
759                .regs = &DSPI_D,
760                .master = true,
761                .push_data = MPC55XX_ZERO_FLAGS,
762                .edma_transmit = {
763                        .channel = 16,
764                        .done = mpc55xx_dspi_edma_done,
765                        .id = RTEMS_ID_NONE
766                },
767                .edma_push = {
768                        .channel = 18,
769                        .done = mpc55xx_dspi_edma_done,
770                        .id = RTEMS_ID_NONE
771                },
772                .edma_receive = {
773                        .channel = 17,
774                        .done = mpc55xx_dspi_edma_done,
775                        .id = RTEMS_ID_NONE
776                },
777                .idle_char = 0xffffffff,
778                .baud = 0
779#endif
780        }
781};
Note: See TracBrowser for help on using the repository browser.