source: rtems/bsps/powerpc/mpc55xxevb/dev/dspi.c @ e560ee85

Last change on this file since e560ee85 was e560ee85, checked in by Joel Sherrill <joel@…>, on 03/01/22 at 21:38:55

bsps/powerpc/: Scripted embedded brains header file clean up

Updates #4625.

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