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

4.104.114.95
Last change on this file since 574fb67 was 574fb67, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on 07/14/08 at 16:15:28

updated gen83xx BSP
updated haleakala BSP
added MPC55xx BSP

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