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

4.115
Last change on this file since db21e1d was db21e1d, checked in by Sebastian Huber <sebastian.huber@…>, on 04/03/13 at 10:05:49

bsp/mpc55xx: eDMA API changes

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