OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [spi/] [freescale/] [dspi/] [current/] [src/] [spi_freescale_dspi.c] - Blame information for rev 847

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//=============================================================================
2
//
3
//      spi_freescale_dspi.c
4
//
5
//      SPI driver implementation for Freescale DSPI
6
//
7
//=============================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 2011 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//=============================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):   ilijak
43
// Date:        2011-11-04
44
// Purpose:     Freescale DSPI SPI driver implementation
45
//
46
//####DESCRIPTIONEND####
47
//
48
//=============================================================================
49
 
50
#include <string.h>
51
#include <cyg/hal/hal_io.h>
52
#include <cyg/hal/hal_if.h>
53
#include <cyg/hal/hal_intr.h>
54
#include <cyg/hal/drv_api.h>
55
 
56
#include <cyg/infra/cyg_type.h>
57
#include <cyg/infra/cyg_ass.h>
58
#include <cyg/infra/diag.h>
59
 
60
#include <cyg/io/spi.h>
61
#include <cyg/hal/hal_endian.h>
62
 
63
#include <pkgconf/devs_spi_freescale_dspi.h>
64
#if defined(CYGHWR_DEVS_SPI_FREESCALE_DSPI0) || \
65
    defined(CYGHWR_DEVS_SPI_FREESCALE_DSPI1) || \
66
    defined(CYGHWR_DEVS_SPI_FREESCALE_DSPI2)
67
 
68
#include <cyg/io/spi_freescale_dspi.h>
69
 
70
 
71
#define DEBUG_SPI CYGPKG_DEVS_SPI_FREESCALE_DSPI_DEBUG_LEVEL
72
 
73
#if DEBUG_SPI >= 3
74
# define DEBUG3_PRINTF(args...) diag_printf(args)
75
#else
76
# define DEBUG3_PRINTF(args...)
77
#endif
78
 
79
#if DEBUG_SPI >= 2
80
# define DEBUG2_PRINTF(args...) diag_printf(args)
81
#else
82
# define DEBUG2_PRINTF(args...)
83
#endif
84
 
85
#if DEBUG_SPI >= 1
86
# define DEBUG1_PRINTF(args...) diag_printf(args)
87
#else
88
# define DEBUG1_PRINTF(args...)
89
#endif
90
 
91
# define DEBUG0_PRINTF(args...) diag_printf(args)
92
 
93
 
94
//-----------------------------------------------------------------------------
95
// API function call forward references.
96
 
97
static void dspi_transaction_begin    (cyg_spi_device*);
98
static void dspi_transaction_transfer (cyg_spi_device*, cyg_bool, cyg_uint32,
99
                                       const cyg_uint8*, cyg_uint8*, cyg_bool);
100
static void dspi_transaction_tick     (cyg_spi_device*, cyg_bool, cyg_uint32);
101
static void dspi_transaction_end      (cyg_spi_device*);
102
static int  dspi_get_config           (cyg_spi_device*, cyg_uint32,
103
                                       void*, cyg_uint32*);
104
static int  dspi_set_config           (cyg_spi_device*, cyg_uint32,
105
                                       const void*, cyg_uint32*);
106
 
107
//-----------------------------------------------------------------------------
108
// Instantiate the bus state data structures.
109
 
110
#include <cyg/io/spi_freescale_dspi_buses.inl>
111
 
112
// Some hardware manipulation inline functions and macros
113
 
114
static inline void dspi_disable(cyghwr_devs_freescale_dspi_t* dspi_p)
115
{
116
    dspi_p->mcr |=  FREESCALE_DSPI_MCR_MDIS_M;
117
}
118
 
119
static inline void dspi_enable(cyghwr_devs_freescale_dspi_t* dspi_p)
120
{
121
    dspi_p->mcr &=  ~FREESCALE_DSPI_MCR_MDIS_M;
122
}
123
 
124
static inline void dspi_halt(cyghwr_devs_freescale_dspi_t* dspi_p)
125
{
126
    dspi_p->mcr |=  FREESCALE_DSPI_MCR_HALT_M;
127
}
128
 
129
static inline void dspi_tlah(cyghwr_devs_freescale_dspi_t* dspi_p)
130
{
131
    dspi_p->mcr &=  ~FREESCALE_DSPI_MCR_HALT_M;
132
}
133
 
134
static inline void
135
dspi_irq_enable(cyghwr_devs_freescale_dspi_t* dspi_p, cyg_uint32 irq_mask)
136
{
137
    dspi_p->rser |= irq_mask;
138
}
139
 
140
static inline void
141
dspi_irq_disable(cyghwr_devs_freescale_dspi_t* dspi_p, cyg_uint32 irq_mask)
142
{
143
    dspi_p->rser &= ~irq_mask;
144
}
145
 
146
static inline void
147
dspi_status_clear(cyghwr_devs_freescale_dspi_t* dspi_p, cyg_uint32 sr_mask)
148
{
149
    dspi_p->sr |= sr_mask;
150
}
151
 
152
static inline void
153
dspi_fifo_clear(cyghwr_devs_freescale_dspi_t* dspi_p)
154
{
155
    dspi_p->mcr |= FREESCALE_DSPI_MCR_CLR_RXF_M | FREESCALE_DSPI_MCR_CLR_TXF_M;
156
}
157
 
158
static inline void
159
dspi_fifo_drain(cyghwr_devs_freescale_dspi_t* dspi_p)
160
{
161
    dspi_p->sr |= FREESCALE_DSPI_SR_RFDF_M;
162
}
163
 
164
 
165
#define DSPI_IRQ_ENABLE(__dspi_p) \
166
        dspi_irq_enable(__dspi_p, FREESCALE_DSPI_RSER_EOQF_RE_M)
167
#define DSPI_IRQ_DISABLE(__dspi_p) \
168
        dspi_irq_disable(__dspi_p, FREESCALE_DSPI_RSER_EOQF_RE_M)
169
#define DSPI_EOQ_CLEAR(__dspi_p) \
170
        dspi_status_clear(__dspi_p, FREESCALE_DSPI_SR_EOQF_M | \
171
                                     FREESCALE_DSPI_SR_TCF_M | \
172
                                        FREESCALE_DSPI_SR_RFDF_M)
173
#define DSPI_TXRX_ENABLE(__dspi_p) \
174
        dspi_status_clear(__dspi_p, FREESCALE_DSPI_SR_TXRXS_M)
175
 
176
// Alternate clocking for spi_transaction_end()
177
// Used to initialize CTAR1.
178
static const cyg_freescale_dspi_clocking_t aux_clocking =
179
{
180
    .frame_size = 4,
181
    .cl_pol = 0,
182
    .cl_pha = 0,
183
    .cl_brate = CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_SPEED,
184
    .cs_up_udly = CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_CS_DELAY,
185
    .cs_dw_udly = CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_CS_DELAY,
186
    .tr_bt_udly =CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_CS_DELAY,
187
    .dl_unit = CYGNUM_DSPI_DELAY_UNIT(
188
                   CYGHWR_DEVS_FREESCALE_DSPI_DSPI_CTAR1_AUX_DELAY_UNIT),
189
    .cl_dbr = CYGHWR_DEVS_FREESCALEDSPI_DSPI_CTAR1_AUX_USE_DBR
190
};
191
 
192
//-----------------------------------------------------------------------------
193
// Implement DSPI ISRs.
194
 
195
// ISR for DSPI with DMA
196
// Disable DSPI IRQ and Tx DMA channel and schedule DSR.
197
static cyg_uint32 dspi_dma_ISR(cyg_vector_t vector, cyg_addrword_t data)
198
{
199
    cyg_spi_freescale_dspi_bus_t* dspi_bus_p =
200
          (cyg_spi_freescale_dspi_bus_t*) data;
201
    cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus_p->setup_p->dspi_p;
202
    cyghwr_hal_freescale_dma_set_t *dma_set_p = dspi_bus_p->setup_p->dma_set_p;
203
    cyghwr_hal_freescale_edma_t *edma_p;
204
    edma_p = dma_set_p->edma_p;
205
 
206
    cyg_drv_isr_lock();
207
 
208
    // Disable the Tx DMA channel and DSPI IRQ.
209
    hal_freescale_edma_erq_disable(edma_p, SPI_DMA_CHAN_I(dma_set_p, TX));
210
    DSPI_IRQ_DISABLE(dspi_p);
211
 
212
    cyg_drv_interrupt_acknowledge(vector);
213
    cyg_drv_isr_unlock();
214
    return (CYG_ISR_CALL_DSR | CYG_ISR_HANDLED);
215
}
216
 
217
// ISR for DSPI without DMA
218
// Disable DSPI IRQ and schedule DSR.
219
static cyg_uint32 dspi_nodma_ISR(cyg_vector_t vector, cyg_addrword_t data)
220
{
221
    cyg_spi_freescale_dspi_bus_t* dspi_bus_p =
222
          (cyg_spi_freescale_dspi_bus_t*) data;
223
    cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus_p->setup_p->dspi_p;
224
 
225
    cyg_drv_isr_lock();
226
 
227
    // Disable the DSPI IRQ.
228
    DSPI_IRQ_DISABLE(dspi_p);
229
 
230
    cyg_drv_interrupt_acknowledge(vector);
231
    cyg_drv_isr_unlock();
232
    return (CYG_ISR_CALL_DSR | CYG_ISR_HANDLED);
233
}
234
 
235
// DSPI DSR
236
static void dspi_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
237
{
238
    cyg_spi_freescale_dspi_bus_t* dspi_bus = (cyg_spi_freescale_dspi_bus_t*) data;
239
 
240
    cyg_drv_dsr_lock();
241
    cyg_drv_cond_signal(&dspi_bus->transfer_done);
242
    cyg_drv_dsr_unlock();
243
}
244
 
245
//-----------------------------------------------------------------------------
246
// Calculate best fit CTAR baud rate setting (using some brute force).
247
// Best fit is considered the highest frequency that is not highe than set point.
248
 
249
static const cyg_uint16 ctar_br[16] = { 2/2, 4/2, 6/2, 8/2, 16/2, 32/2, 64/2,
250
    128/2, 256/2, 512/2, 1024/2, 2048/2, 4096/2, 8192/2, 16384/2, 32768/2 };
251
static const cyg_uint8 ctar_pbr[4] = { 2, 3, 5, 7 };
252
 
253
static const cyg_uint16 ctar_cssck[16] = { 2/2, 4/2, 8/2, 16/2, 32/2, 64/2,
254
    128/2, 256/2, 512/2, 1024/2, 2048/2, 4096/2, 8192/2, 16384/2, 32768/2,
255
    65536/2 };
256
static const cyg_uint8 ctar_pcssck[4] = { 1, 3, 5, 7 };
257
 
258
typedef struct ctar_br_s {
259
    cyg_uint8 valid;
260
    cyg_uint8 br;
261
    cyg_uint8 dbr;
262
    cyg_uint8 pbr;
263
} ctar_br_t;
264
 
265
static int dspi_ctar_brbf (const cyg_freescale_dspi_clocking_t* spi_cocking,
266
                              ctar_br_t* brs_p, const cyg_uint16* br_p,
267
                              const cyg_uint8* pbr_p, cyg_uint32* alt_brate,
268
                              cyg_uint32 sys_clk)
269
{
270
    cyg_uint32 pbr_i;
271
    cyg_uint32 br_i;
272
    cyg_uint32 dbr;
273
    cyg_uint32 clk;
274
    cyg_uint32 baud_bf = 0; // Best fit
275
    cyg_uint32 baud_tmp;
276
    cyg_uint32 baud_sp = alt_brate ? *alt_brate :
277
                         spi_cocking->cl_brate; // Set point
278
 
279
    // Calculate the maximal viable bus speed.
280
    clk = sys_clk;
281
     // Desired baud rate very high, use DBR if allowed
282
    dbr = (baud_sp > (clk / 4)) && spi_cocking->cl_dbr && (br_p == ctar_br);
283
 
284
    for(pbr_i = 0; pbr_i < 3; pbr_i++) {
285
        for(br_i = 0; br_i < 15; br_i++) {
286
            if((baud_tmp = (clk * (1+dbr)) / (pbr_p[pbr_i] * (2*br_p[br_i])))
287
               <= baud_sp)
288
            {
289
                if(baud_tmp > baud_bf) {
290
                    DEBUG3_PRINTF("DSPI Baud:"
291
                                  " SP=%d pbr=0x%x br=0x%x dbr=%d Temp=%d (SysClk=%d)\n",
292
                                  baud_sp, pbr_i, br_i, dbr, baud_tmp, clk);
293
                    brs_p->br = br_i;
294
                    brs_p->pbr = pbr_i;
295
                    brs_p->valid = 1;
296
                    baud_bf = baud_tmp;
297
                    if(baud_tmp == baud_sp)
298
                        goto baud_found;
299
                }
300
            }
301
        }
302
    }
303
    if(!brs_p->valid) {
304
        pbr_i = 3;
305
        br_i = 15;
306
        DEBUG1_PRINTF("DSPI Baud too low:"
307
                      " SP=%d pbr=0x%x br=0x%x Actual=%d (SysClk=%d)\n",
308
                      baud_sp, pbr_i, br_i,
309
                      (clk * (1+dbr)) / (pbr_p[pbr_i] * (2*br_p[br_i])), clk);
310
        brs_p->br = br_i;
311
        brs_p->pbr = pbr_i;
312
 
313
        return -1;
314
    } else {
315
baud_found:
316
        brs_p->dbr = dbr;
317
        DEBUG1_PRINTF("DSPI Baud found:"
318
                      " SP=%d pbr=0x%x br=0x%x dbr=%d Actual=%dHz (%dns) (SysClk=%d)\n",
319
                      baud_sp, brs_p->pbr, brs_p->br, dbr, baud_bf, 1000000000/baud_bf, clk);
320
 
321
        return 0;
322
    }
323
}
324
 
325
// Set Clock and Transfer Attributes Register
326
#define CYG_ASSERT_LOW_FREQ \
327
   CYG_ASSERT (false, "Freescale DSPI: Cannot run bus as slowly as requested.")
328
cyg_uint32
329
dspi_calc_ctar(const cyg_freescale_dspi_clocking_t* spi_clocking, cyg_uint32 sys_clk)
330
{
331
    cyg_uint32 regval;
332
    ctar_br_t brs;
333
    cyg_uint32 delay_brate;
334
 
335
    regval = FREESCALE_DSPI_CTAR_FMSZ(spi_clocking->frame_size - 1);
336
    if(spi_clocking->cl_pol)
337
        regval |= FREESCALE_DSPI_CTAR_SLAVE_CPOL_M;
338
    if(spi_clocking->cl_pha)
339
        regval |= FREESCALE_DSPI_CTAR_SLAVE_CPHA_M;
340
    if(spi_clocking->lsb_first)
341
        regval |= FREESCALE_DSPI_CTAR_LSBFE_M;
342
 
343
    // Get divider bits
344
    // Baud rate
345
    brs.dbr = 0;
346
    if (!dspi_ctar_brbf(spi_clocking, &brs, ctar_br, ctar_pbr, NULL, sys_clk))
347
    {
348
        regval |= FREESCALE_DSPI_CTAR_BR(brs.br) |
349
              FREESCALE_DSPI_CTAR_PBR(brs.pbr) |
350
              (brs.dbr ? FREESCALE_DSPI_CTAR_DBR_M : 0);
351
    } else
352
        CYG_ASSERT_LOW_FREQ;
353
 
354
    delay_brate = 100000000 / (spi_clocking->dl_unit * spi_clocking->cs_up_udly);
355
    if (!dspi_ctar_brbf(spi_clocking, &brs, ctar_cssck, ctar_pcssck,
356
                           &delay_brate, sys_clk))
357
    {
358
        regval |= FREESCALE_DSPI_CTAR_CSSCK(brs.br) |
359
              FREESCALE_DSPI_CTAR_PCSSCK(brs.pbr);
360
    } else
361
        CYG_ASSERT_LOW_FREQ;
362
 
363
    // Delay between clock and CS negation
364
    delay_brate = 100000000 / (spi_clocking->dl_unit * spi_clocking->cs_dw_udly);
365
    if (!dspi_ctar_brbf(spi_clocking, &brs, ctar_cssck, ctar_pcssck,
366
                           &delay_brate, sys_clk))
367
    {
368
        regval |= FREESCALE_DSPI_CTAR_ASC(brs.br) |
369
              FREESCALE_DSPI_CTAR_PASC(brs.pbr);
370
    } else
371
        CYG_ASSERT_LOW_FREQ;
372
 
373
    // Delay between clock and CS negation and assertion
374
    delay_brate = 100000000 / (spi_clocking->dl_unit * spi_clocking->tr_bt_udly);
375
    if (!dspi_ctar_brbf(spi_clocking, &brs, ctar_cssck, ctar_pcssck,
376
                           &delay_brate, sys_clk))
377
    {
378
        regval |= FREESCALE_DSPI_CTAR_DT(brs.br) |
379
              FREESCALE_DSPI_CTAR_PDT(brs.pbr);
380
    } else
381
        CYG_ASSERT_LOW_FREQ;
382
    return regval;
383
}
384
 
385
//----------------------------------------------------------------------------
386
//Set up SPI bus pins
387
 
388
static void dspi_pin_setup(const cyg_uint32* spi_pins_p,
389
                           const cyg_uint32* cs_pins_p, cyg_uint32 cs_pin_n)
390
{
391
    const cyg_uint32* pin_p;
392
 
393
    for(pin_p = spi_pins_p;
394
        pin_p < spi_pins_p + 3;
395
        CYGHWR_IO_FREESCALE_DSPI_PIN(*pin_p++));
396
 
397
    for(pin_p = cs_pins_p;
398
        pin_p < cs_pins_p + cs_pin_n;
399
        CYGHWR_IO_FREESCALE_DSPI_PIN(*pin_p++));
400
}
401
 
402
//-----------------------------------------------------------------------------
403
// Set up a new SPI bus on initialisation.
404
 
405
static void dspi_bus_setup(cyg_spi_freescale_dspi_bus_t* spi_bus_p)
406
{
407
    cyghwr_devs_freescale_dspi_t* dspi_p = spi_bus_p->setup_p->dspi_p;
408
    cyghwr_hal_freescale_dma_set_t* dma_set_p;
409
    cyghwr_hal_freescale_edma_t* edma_p;
410
    cyg_uint32 dma_chan_i;
411
 
412
    // Get the clock frequency from HAL.
413
    spi_bus_p->clock_freq = CYGHWR_IO_SPI_FREESCALE_DSPI_CLOCK;
414
    DEBUG1_PRINTF("DSPI BUS %p: SysClk=%d\n", spi_bus_p, spi_bus_p->clock_freq);
415
 
416
    // Set up the pins.
417
    dspi_pin_setup(spi_bus_p->setup_p->spi_pin_list_p,
418
                   spi_bus_p->setup_p->cs_pin_list_p,
419
                   spi_bus_p->setup_p->cs_pin_num);
420
 
421
    // Set up default SPI configuration.
422
    dspi_p->mcr = spi_bus_p->setup_p->mcr_opt | FREESCALE_DSPI_MCR_MSTR_M |
423
          FREESCALE_DSPI_MCR_CLR_RXF_M | FREESCALE_DSPI_MCR_CLR_TXF_M |
424
          FREESCALE_DSPI_MCR_MDIS_M;
425
 
426
    // Enable DSPI controller.
427
    dspi_enable(dspi_p);
428
 
429
    if((dma_set_p=spi_bus_p->setup_p->dma_set_p)) {
430
        // Initialize DMA channels
431
        hal_freescale_edma_init_chanset(dma_set_p);
432
#if DEBUG_SPI >= 1
433
        hal_freescale_edma_diag(dma_set_p, 0xffff);
434
        cyghwr_devs_freescale_dspi_diag(spi_bus_p);
435
#endif
436
        // Set up DMA transfer control descriptors
437
        edma_p = dma_set_p->edma_p;
438
        dma_chan_i = dma_set_p->chan_p[SPI_DMA_CHAN_TX_I].dma_chan_i;
439
        hal_freescale_edma_transfer_init(edma_p, dma_chan_i,
440
                                         spi_bus_p->tx_dma_tcd_ini_p);
441
#if DEBUG_SPI >= 1
442
        hal_freescale_edma_transfer_diag(edma_p, dma_chan_i, true);
443
#endif
444
        dma_chan_i = dma_set_p->chan_p[SPI_DMA_CHAN_RX_I].dma_chan_i;
445
        hal_freescale_edma_transfer_init(edma_p, dma_chan_i,
446
                                         spi_bus_p->rx_dma_tcd_ini_p);
447
#if DEBUG_SPI >= 1
448
        hal_freescale_edma_transfer_diag(edma_p, dma_chan_i, true);
449
#endif
450
        // Enable SPI DMA requests
451
        dspi_p->rser = FREESCALE_DSPI_RSER_TFFF_DIRS_M |
452
                       FREESCALE_DSPI_RSER_RFDF_DIRS_M |
453
                       FREESCALE_DSPI_RSER_TFFF_RE_M |
454
                       FREESCALE_DSPI_RSER_RFDF_RE_M;
455
    }
456
#if DEBUG_SPI >= 1
457
    cyghwr_devs_freescale_dspi_diag(spi_bus_p);
458
#endif
459
    // Initialise the synchronisation primitivies.
460
    cyg_drv_mutex_init (&spi_bus_p->transfer_mutex);
461
    cyg_drv_cond_init (&spi_bus_p->transfer_done, &spi_bus_p->transfer_mutex);
462
 
463
    // Hook up the ISR and DSR.
464
    cyg_drv_interrupt_create (spi_bus_p->setup_p->intr_num,
465
                              spi_bus_p->setup_p->intr_prio,
466
                              (cyg_addrword_t) spi_bus_p,
467
                              dma_set_p ? dspi_dma_ISR : dspi_nodma_ISR,
468
                              dspi_DSR, &spi_bus_p->intr_handle,
469
                              &spi_bus_p->intr_data);
470
    cyg_drv_interrupt_attach (spi_bus_p->intr_handle);
471
 
472
    dspi_p->ctar[1] = dspi_calc_ctar(&aux_clocking, spi_bus_p->clock_freq);
473
 
474
    // Call upper layer bus init.
475
    CYG_SPI_BUS_COMMON_INIT(&spi_bus_p->spi_bus);
476
}
477
 
478
//-----------------------------------------------------------------------------
479
// Set up Rx DMA channel
480
static void
481
rx_dma_channel_setup(cyghwr_hal_freescale_dma_set_t *dma_set_p,
482
                     cyg_uint8* data_buf, cyg_uint32 bus_16bit,
483
                     volatile cyghwr_hal_freescale_edma_tcd_t *tcd_p)
484
{
485
    cyg_uint32 step, sdsize;
486
    static cyg_uint8 popr_sink;
487
 
488
    // Set the correct transfer size.
489
    if(bus_16bit) {
490
        step = 2;
491
        sdsize = FREESCALE_EDMA_ATTR_SIZE_16;
492
    } else {
493
        step = 1;
494
        sdsize = FREESCALE_EDMA_ATTR_SIZE_8;
495
    }
496
    if(data_buf) {
497
        tcd_p->doff = step;
498
        tcd_p->daddr = data_buf;
499
    } else {
500
        tcd_p->doff = 0;
501
        tcd_p->daddr = &popr_sink;
502
    }
503
    tcd_p->nbytes.mlno = step;
504
    tcd_p->attr =  FREESCALE_EDMA_ATTR_SSIZE(sdsize) |
505
          FREESCALE_EDMA_ATTR_DSIZE(sdsize) |
506
          FREESCALE_EDMA_ATTR_SMOD(0) |
507
          FREESCALE_EDMA_ATTR_DMOD(0);
508
#if DEBUG_SPI >= 3
509
    hal_freescale_edma_tcd_diag(tcd_p, -1, "[DSPI Rx]");
510
#endif
511
}
512
 
513
//----------------------------------------------------------------------------
514
// Set up Tx FIFO queue
515
// Set up Tx FIFO command queue
516
//     DSPI requires sending command for every transfer.
517
// Used for transfers that fit within DSPI FIFO.
518
 
519
#if DEBUG_SPI >= 2
520
static const char debug_format[] = "BUFF %dbit %s: %p 0x%08x remain %d:\n";
521
#endif
522
 
523
static inline volatile cyg_uint32
524
fifo_pushque_fill(cyg_spi_freescale_dspi_bus_t* dspi_bus, cyg_uint8*
525
                  data_p, cyg_uint32 count, cyg_bool bus_16bit, cyg_uint32 pushr,
526
                  cyg_bool drop_cs)
527
{
528
    cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus->setup_p->dspi_p;
529
    cyg_uint32 txfifo_n = dspi_bus->txfifo_n;
530
 
531
    if(data_p) {
532
        if(!bus_16bit) {
533
            for(; count > 1; count--) {
534
                if(!(--txfifo_n)) {
535
                    dspi_p->pushr = pushr |= *data_p | FREESCALE_DSPI_PUSHR_EOQ_M;
536
                    count--;
537
                    DEBUG2_PRINTF(debug_format, 8, "FBK", &dspi_p->pushr,
538
                                  pushr | *data_p, count);
539
                    return count;
540
                }
541
                dspi_p->pushr = pushr | *data_p++;
542
                DEBUG3_PRINTF(debug_format, 8, "FAD", &dspi_p->pushr,
543
                              pushr | data_p[-1], count-1);
544
            }
545
            pushr |= *data_p;
546
        } else {
547
            cyg_uint16* data16_p = (cyg_uint16 *)data_p;
548
            cyg_uint16 data_word;
549
 
550
            for(; count > 2; count-=2) {
551
                if(!(--txfifo_n)) {
552
                    dspi_p->pushr = pushr |= *data16_p | FREESCALE_DSPI_PUSHR_EOQ_M;
553
                    count-=2;
554
                    DEBUG2_PRINTF(debug_format, 16, "FBK", &dspi_p->pushr,
555
                                  pushr, count);
556
                    return count;
557
                }
558
                data_word = *data16_p++;
559
                dspi_p->pushr = pushr | data_word;
560
                DEBUG3_PRINTF(debug_format, 16, "FAD", &dspi_p->pushr,
561
                              pushr | data_word, (count-1)*2);
562
            }
563
            data_word = *data16_p;
564
            pushr |= data_word;
565
        }
566
    } else {
567
        for(; count > 1; count--) {
568
            if(!(--txfifo_n)) {
569
                dspi_p->pushr = pushr |= FREESCALE_DSPI_PUSHR_EOQ_M;
570
                count--;
571
                DEBUG2_PRINTF(debug_format, 0, "FBK", &dspi_p->pushr,
572
                              pushr, count);
573
                return count;
574
            }
575
            dspi_p->pushr = pushr;
576
            DEBUG3_PRINTF(debug_format, 0, "FAD", &dspi_p->pushr, pushr,
577
                          count-1);
578
        }
579
    }
580
    if(drop_cs)
581
        pushr &= ~FREESCALE_DSPI_PUSHR_CONT_M;
582
    dspi_p->pushr = pushr |= FREESCALE_DSPI_PUSHR_EOQ_M;
583
    DEBUG3_PRINTF(debug_format, data_p ? (bus_16bit ? 16 :8) : pushr,
584
                  (drop_cs ? "FEN" : "FSG"), &dspi_p->pushr, pushr, 0);
585
    return 0;
586
}
587
 
588
//----------------------------------------------------------------------------
589
// Set up Tx
590
// Set up Tx DMA command queue
591
//     DSPI requires sending command for every transfer.
592
// Used for transfers larger than DSPI FIFO
593
 
594
static inline volatile cyg_uint32
595
dma_pushque_fill(cyg_spi_freescale_dspi_bus_t* dspi_bus, cyg_uint8* data_p,
596
                 cyg_uint32 count, cyg_bool bus_16bit, cyg_uint32 pushr,
597
                 cyg_bool drop_cs)
598
{
599
    volatile cyg_uint32* pushque_p;
600
    volatile cyg_uint32* pushque_end;
601
 
602
    pushque_p = dspi_bus->pushque_p;
603
    pushque_end = pushque_p + dspi_bus->pushque_n;
604
    pushque_p = dspi_bus->pushque_p;
605
    if(data_p) {
606
        if(!bus_16bit) {
607
            do {
608
                if(pushque_p == pushque_end) {
609
                    pushque_p[0] = pushr;
610
                    pushque_p[-1] |= FREESCALE_DSPI_PUSHR_EOQ_M;
611
                    DEBUG2_PRINTF(debug_format, 8, "BRK", pushque_p-1,
612
                                  pushque_p[-1], count);
613
                    return count;
614
                }
615
                *pushque_p++ = pushr | *data_p++;
616
                DEBUG3_PRINTF(debug_format, 8, "ADD", pushque_p-1,
617
                              pushque_p[-1], count-1);
618
            } while(--count > 1);
619
            pushr |= *data_p;
620
        } else {
621
            cyg_uint16* data16_p = (cyg_uint16 *)data_p;
622
            cyg_uint16 data_word;
623
            do {
624
                if(pushque_p == pushque_end) {
625
                    pushque_p[0] = pushr;
626
                    pushque_p[-1] |= FREESCALE_DSPI_PUSHR_EOQ_M;
627
                    DEBUG2_PRINTF(debug_format, 16, "BRK", pushque_p-1,
628
                                  pushque_p[-1], count);
629
                    return count;
630
                }
631
                data_word = *data16_p++;
632
                *pushque_p++ = pushr | data_word;
633
                DEBUG3_PRINTF(debug_format, 16, "ADD", pushque_p-1,
634
                              pushque_p[-1], count-2);
635
            } while((count -= 2) > 2);
636
            data_word = *data16_p;
637
            pushr |= data_word;
638
        }
639
    } else {
640
        do {
641
            if(pushque_p == pushque_end) {
642
                pushque_p[0] = pushr;
643
                pushque_p[-1] |= FREESCALE_DSPI_PUSHR_EOQ_M;
644
                DEBUG2_PRINTF(debug_format, 0, "BRK", pushque_p-1,
645
                              pushque_p[-1], count);
646
                return count;
647
            }
648
            *pushque_p++ = pushr;
649
            DEBUG3_PRINTF(debug_format, 0, "BRK", pushque_p-1, pushque_p[-1],
650
                          count-1);
651
        } while(--count > 1);
652
    }
653
    if(drop_cs) pushr &= ~FREESCALE_DSPI_PUSHR_CONT_M;
654
    pushque_p[1] = pushr;
655
    *pushque_p = pushr |= FREESCALE_DSPI_PUSHR_EOQ_M;
656
    DEBUG2_PRINTF(debug_format, data_p ? (bus_16bit ? 16 :8) : 0,
657
                  (drop_cs ? "END" : "SGM"), pushque_p, pushque_p[0], 0);
658
    return 0;
659
}
660
 
661
// Set up Tx DMA channel
662
// Used for transfers larger than DSPI FIFO
663
 
664
static inline cyg_uint32
665
tx_dma_channel_setup(cyg_spi_freescale_dspi_bus_t* dspi_bus,
666
                     cyg_uint8* data_buf, cyg_uint32 count,
667
                     cyg_bool bus_16bit,
668
                     cyg_uint32 pushr, cyg_bool drop_cs)
669
{
670
    cyghwr_hal_freescale_dma_set_t *dma_set_p = dspi_bus->setup_p->dma_set_p;
671
    cyghwr_hal_freescale_edma_t *edma_p =  dma_set_p->edma_p;
672
    volatile cyghwr_hal_freescale_edma_tcd_t *tcd_p;
673
    cyg_uint32 remain=0;
674
    cyg_uint32 dma_chan_i;
675
 
676
    remain = dma_pushque_fill(dspi_bus, data_buf, count, bus_16bit, pushr, drop_cs);
677
    dma_chan_i = SPI_DMA_CHAN_I(dma_set_p, TX);
678
    tcd_p = &edma_p->tcd[dma_chan_i];
679
    tcd_p->saddr = dspi_bus->pushque_p;
680
    DEBUG2_PRINTF("DSPI: Tx channel setup\n");
681
#if DEBUG_SPI >= 3
682
    hal_freescale_edma_transfer_diag(edma_p, dma_chan_i, true);
683
#endif
684
    return remain;
685
}
686
 
687
//-----------------------------------------------------------------------------
688
// Set SPI peripheral chip select.
689
 
690
static inline cyg_uint32
691
dspi_chip_select_set(cyg_int32 cs_i, cyg_bool pccse, cyg_bool assert)
692
{
693
    cyg_uint32 spi_pushr;
694
 
695
    if(cs_i < 0) {
696
        spi_pushr = 0;
697
    } else {
698
        if(pccse) {
699
            spi_pushr = cs_i;
700
        } else {
701
            if(cs_i < 5) {
702
                if(assert) {
703
                    cs_i = 1 << cs_i;
704
                    spi_pushr = FREESCALE_DSPI_PUSHR_PCS(cs_i);
705
                } else
706
                    spi_pushr = 0;
707
            } else {
708
                CYG_ASSERT(1, "DSPI: Peripheral Chip Select out of range.\n");
709
                spi_pushr = 1 << 5;
710
            }
711
        }
712
    }
713
    return spi_pushr;
714
}
715
 
716
//-----------------------------------------------------------------------------
717
// Execute SPI transaction.
718
 
719
static void spi_transaction_do (cyg_spi_device* device, cyg_bool tick_only,
720
                                 cyg_bool polled, cyg_uint32 count,
721
                                 const cyg_uint8* tx_data, cyg_uint8* rx_data,
722
                                 cyg_bool drop_cs)
723
{
724
    cyg_spi_freescale_dspi_bus_t* dspi_bus =
725
          (cyg_spi_freescale_dspi_bus_t*) device->spi_bus;
726
    cyg_spi_freescale_dspi_device_t* dspi_device =
727
          (cyg_spi_freescale_dspi_device_t*) device;
728
    cyg_bool bus_16bit = dspi_device->clocking.bus_16bit;
729
    cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus->setup_p->dspi_p;
730
 
731
    cyghwr_hal_freescale_dma_set_t* dma_set_p;
732
    cyghwr_hal_freescale_edma_t* edma_p = NULL;
733
 
734
    cyg_uint32 count_down;
735
    cyg_uint32 txfifo_n = dspi_bus->txfifo_n;
736
    cyg_uint32 pushr;
737
    cyg_uint32 pushque_n;
738
    cyg_uint32 dma_chan_rx_i = 0;
739
    cyg_uint32 dma_chan_tx_i = 0;
740
 
741
#if DEBUG_SPI >= 2
742
    cyg_uint32 first_turn = 1;
743
#endif
744
 
745
    DEBUG2_PRINTF("DSPI: transaction: count=%d drop_cs=%d\n", count, drop_cs);
746
 
747
    // Set up peripheral CS field. DSPI automatically asserts and deasserts CS
748
    pushr = dspi_chip_select_set(tick_only ? -1 : dspi_device->dev_num,
749
                                dspi_p->mcr & FREESCALE_DSPI_MCR_PCSSE_M, true);
750
    pushr |= FREESCALE_DSPI_PUSHR_CONT_M;
751
 
752
    dspi_fifo_clear(dspi_p);
753
    dspi_fifo_drain(dspi_p);
754
 
755
    pushque_n = dspi_bus->pushque_n;
756
    if(bus_16bit)
757
        txfifo_n *= 2;
758
 
759
    if((dma_set_p=dspi_bus->setup_p->dma_set_p)) {
760
        edma_p = dma_set_p->edma_p;
761
        // Set up the DMA channels.
762
        dma_chan_rx_i = SPI_DMA_CHAN_I(dma_set_p, RX);
763
        dma_chan_tx_i = SPI_DMA_CHAN_I(dma_set_p, TX);
764
        rx_dma_channel_setup(dma_set_p, (cyg_uint8*) rx_data,
765
                             bus_16bit, &edma_p->tcd[dma_chan_rx_i]);
766
        hal_freescale_edma_erq_enable(edma_p, dma_chan_rx_i);
767
    }
768
 
769
    if(!polled)
770
        cyg_drv_interrupt_unmask(dspi_bus->setup_p->intr_num);
771
    count_down = count;
772
    while(count_down) {
773
#if DEBUG_SPI >= 2
774
        if(first_turn) {
775
            if(dspi_bus->pushque_p)
776
                dspi_bus->pushque_p[0] |= FREESCALE_DSPI_PUSHR_CTCNT_M;
777
            first_turn = 0;
778
        }
779
#endif
780
        if(dma_set_p && (count_down > txfifo_n)) {
781
            // Transfer size is larger than DSPI FIFO
782
            // Use DMA Tx
783
            count_down = tx_dma_channel_setup(dspi_bus, (cyg_uint8*) tx_data,
784
                                              count_down, bus_16bit,
785
                                              pushr, drop_cs);
786
#if DEBUG_SPI >= 3
787
            hal_freescale_edma_transfer_diag(edma_p, dma_chan_rx_i, true);
788
#endif
789
            // Enable the Tx DMA / SPI controller.
790
            hal_freescale_edma_erq_enable(edma_p, dma_chan_tx_i);
791
            DSPI_EOQ_CLEAR(dspi_p);
792
        } else {
793
            // Transfer size fits within DSPI FIFO
794
            // No need for DMA Tx
795
            DSPI_EOQ_CLEAR(dspi_p);
796
            count_down = fifo_pushque_fill(dspi_bus, (cyg_uint8*) tx_data,
797
                                           count_down, bus_16bit,
798
                                           pushr, drop_cs);
799
#if DEBUG_SPI >= 3
800
            cyghwr_devs_freescale_dspi_diag(dspi_bus);
801
#endif
802
        }
803
 
804
        if(polled) {
805
            DEBUG2_PRINTF("DSPI Polled:\n");
806
            // Busy-wait for DSPI/DMA (polling for completion).
807
            while(!(dspi_p->sr & FREESCALE_DSPI_SR_EOQF_M));
808
 
809
            if(dma_set_p) // Disable the Tx DMA channel on completion.
810
                hal_freescale_edma_erq_disable(edma_p, dma_chan_tx_i);
811
        } else {
812
            // Wait for DSPI/DMA completion. (interrupt driven).
813
            cyg_drv_mutex_lock(&dspi_bus->transfer_mutex);
814
            cyg_drv_dsr_lock();
815
 
816
            DSPI_IRQ_ENABLE(dspi_p);
817
            DEBUG2_PRINTF("DSPI IRQ: Enabled\n");
818
 
819
            // Sit back and wait for the ISR/DSRs to signal completion.
820
            cyg_drv_cond_wait (&dspi_bus->transfer_done);
821
 
822
            cyg_drv_dsr_unlock();
823
            cyg_drv_mutex_unlock(&dspi_bus->transfer_mutex);
824
        }
825
 
826
        if(dma_set_p) {
827
            // Make sure that Rx has been drained by DMA.
828
            if(rx_data)
829
                while((dspi_p->sr & FREESCALE_DSPI_SR_RFDF_M));
830
        } else {
831
            // No DMA - "manually" drain Rx FIFO
832
            DEBUG2_PRINTF("DSPI FIFO: 'Manually' drain Rx fifo\n");
833
#if DEBUG_SPI >= 3
834
            cyghwr_devs_freescale_dspi_diag(dspi_bus);
835
#endif
836
            if(rx_data) {
837
                if(bus_16bit) {
838
                    cyg_uint16* rx_data16 = (cyg_uint16*) rx_data;
839
                    while(dspi_p->sr & FREESCALE_DSPI_SR_RXCTR_M)
840
                        *rx_data16++ = dspi_p->popr;
841
                    rx_data = (cyg_uint8*) rx_data16;
842
                } else {
843
                    while(dspi_p->sr & FREESCALE_DSPI_SR_RXCTR_M)
844
                        *rx_data++ = dspi_p->popr;
845
                }
846
            } else {
847
                dspi_fifo_drain(dspi_p);
848
            }
849
        }
850
        dspi_fifo_clear(dspi_p);
851
        // Prepare for next iteration
852
        if(tx_data) {
853
            tx_data += pushque_n;
854
            if(bus_16bit)
855
                tx_data += pushque_n;
856
        }
857
    }
858
    if(!polled)
859
        cyg_drv_interrupt_mask(dspi_bus->setup_p->intr_num);
860
 
861
    dspi_device->chip_sel = !drop_cs;
862
}
863
 
864
//-----------------------------------------------------------------------------
865
// Initialise SPI interfaces on startup.
866
 
867
static void CYGBLD_ATTRIB_C_INIT_PRI(CYG_INIT_BUS_SPI)
868
dspi_spi_init(void)
869
{
870
#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI0
871
  dspi_bus_setup (&cyg_spi_dspi_bus0);
872
#endif
873
 
874
#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI1
875
  dspi_bus_setup (&cyg_spi_dspi_bus1);
876
#endif
877
 
878
#ifdef CYGHWR_DEVS_SPI_FREESCALE_DSPI2
879
  dspi_bus_setup (&cyg_spi_dspi_bus2);
880
#endif
881
}
882
 
883
 
884
//-----------------------------------------------------------------------------
885
// Start a SPI transaction.
886
 
887
static void dspi_transaction_begin(cyg_spi_device* device)
888
{
889
    cyg_spi_freescale_dspi_bus_t* dspi_bus =
890
          (cyg_spi_freescale_dspi_bus_t*) device->spi_bus;
891
    cyg_spi_freescale_dspi_device_t* dspi_device =
892
          (cyg_spi_freescale_dspi_device_t*) device;
893
 
894
    // On the first transaction, generate the values to be programmed into the
895
    // SPI configuration registers for this device and cache them. This avoids
896
    // having to recalculate the prescaler for every transaction.
897
    if(!(dspi_device->clocking.dspi_ctar))
898
        dspi_device->clocking.dspi_ctar = dspi_calc_ctar(&dspi_device->clocking,
899
                                                dspi_bus->clock_freq);
900
    // Set up the SPI controller.
901
    dspi_bus->setup_p->dspi_p->ctar[0] = dspi_device->clocking.dspi_ctar;
902
#if DEBUG_SPI >= 2
903
    cyghwr_devs_freescale_dspi_diag(dspi_bus);
904
#endif
905
}
906
 
907
//-----------------------------------------------------------------------------
908
// Run a transaction transfer.
909
 
910
static void dspi_transaction_transfer(cyg_spi_device* device, cyg_bool polled,
911
                                      cyg_uint32 count,
912
                                      const cyg_uint8* tx_data,
913
                                      cyg_uint8* rx_data,
914
                                      cyg_bool drop_cs)
915
{
916
    cyg_spi_freescale_dspi_device_t* dspi_device =
917
          (cyg_spi_freescale_dspi_device_t*) device;
918
 
919
    DEBUG3_PRINTF("Transaction tx_data = %p count=%d\n", tx_data, count);
920
 
921
    // Check for unsupported transactions.
922
    CYG_ASSERT (count > 0, "DSPI: Null transfer requested.");
923
 
924
    // We check that the buffers are half-word aligned and that count is a
925
    // multiple of two in order to carry out the 16-bit transfer.
926
    if (dspi_device->clocking.bus_16bit) {
927
        CYG_ASSERT (!(count & 1) && !((cyg_uint32) tx_data & 1) &&
928
                    !((cyg_uint32) rx_data & 1),
929
                    "DSPI: Misaligned data in 16-bit transfer.");
930
    }
931
    spi_transaction_do (device, false, polled, count, tx_data, rx_data, drop_cs);
932
}
933
 
934
//-----------------------------------------------------------------------------
935
// Carry out a bus tick operation - this drops chip select then pushes the
936
// required number of zeros onto the bus.
937
 
938
static void dspi_transaction_tick(cyg_spi_device* device, cyg_bool polled,
939
                                  cyg_uint32 count)
940
{
941
    cyg_spi_freescale_dspi_device_t* dspi_device =
942
          (cyg_spi_freescale_dspi_device_t*) device;
943
 
944
    // Check for unsupported transactions.
945
    CYG_ASSERT (count > 0, "DSPI: Null transfer requested.");
946
 
947
    // We check that count is a multiple of two in order
948
    // to carry out the 16-bit transfer.
949
    if (dspi_device->clocking.bus_16bit) {
950
        CYG_ASSERT (!(count & 1),
951
                    "DSPI: Misaligned data in 16-bit transfer.");
952
    }
953
 
954
    // Perform null transfer
955
    spi_transaction_do (device, true, polled, count, NULL, NULL, true);
956
}
957
 
958
//-----------------------------------------------------------------------------
959
// Terminate a SPI transaction, disabling the SPI controller.
960
 
961
static void dspi_transaction_end(cyg_spi_device* device)
962
{
963
    cyg_spi_freescale_dspi_bus_t* dspi_bus =
964
          (cyg_spi_freescale_dspi_bus_t*) device->spi_bus;
965
    cyg_spi_freescale_dspi_device_t* dspi_device =
966
          (cyg_spi_freescale_dspi_device_t*) device;
967
 
968
    cyghwr_hal_freescale_dma_set_t *dma_set_p = dspi_bus->setup_p->dma_set_p;
969
    cyghwr_hal_freescale_edma_t *edma_p;
970
    cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus->setup_p->dspi_p;
971
 
972
    if(dma_set_p) {
973
        edma_p = dma_set_p->edma_p;
974
        hal_freescale_edma_erq_disable(edma_p, SPI_DMA_CHAN_I(dma_set_p, TX));
975
        hal_freescale_edma_erq_disable(edma_p, SPI_DMA_CHAN_I(dma_set_p, RX));
976
    }
977
 
978
    if(dspi_device->chip_sel){
979
        // Clear peripheral CS by executing a dummy 4 bit transfer.
980
        dspi_p->pushr = FREESCALE_DSPI_PUSHR_EOQ_M | FREESCALE_DSPI_PUSHR_CTAS(1);
981
        DSPI_EOQ_CLEAR(dspi_p);
982
        while(!(dspi_p->sr & FREESCALE_DSPI_SR_EOQF_M));
983
        dspi_device->chip_sel = 0;
984
    }
985
}
986
 
987
//-----------------------------------------------------------------------------
988
// Get DSPI configuration parameter
989
 
990
static int dspi_get_config (cyg_spi_device* device, cyg_uint32 key,
991
                            void* buf, cyg_uint32* len)
992
{
993
    cyg_spi_freescale_dspi_bus_t* dspi_bus =
994
          (cyg_spi_freescale_dspi_bus_t*) device->spi_bus;
995
    cyg_spi_freescale_dspi_device_t* dspi_device =
996
          (cyg_spi_freescale_dspi_device_t*) device;
997
    cyg_uint32* data_p = buf;
998
 
999
    switch (key) {
1000
    case CYG_IO_GET_CONFIG_SPI_CLOCKRATE :
1001
        // Sanity check
1002
        if (NULL == len) {
1003
            CYG_ASSERT (false, "Freescale DSPI:"
1004
                        " Null pointer as len argument for dspi_get_config().");
1005
            return -1;
1006
        } else if (sizeof(cyg_uint32) != *len) {
1007
            CYG_ASSERT (false, "Freescale DSPI:"
1008
                        " Invalid length with dspi_get_config().");
1009
            return -1;
1010
        } else if (NULL == buf) {
1011
            CYG_ASSERT (false, "Freescale DSPI:"
1012
                        " Null poiter as buf argument for dspi_get_config().");
1013
            return -1;
1014
        } else {
1015
            cyg_uint32 ctar, dbr, br, pbr;
1016
 
1017
            ctar = dspi_device->clocking.dspi_ctar;
1018
            dbr = (ctar & FREESCALE_DSPI_CTAR_DBR_M) >>
1019
                  FREESCALE_DSPI_CTAR_DBR_S;
1020
            br = (ctar & FREESCALE_DSPI_CTAR_BR_M) >>
1021
                  FREESCALE_DSPI_CTAR_BR_S;
1022
            pbr = (ctar & FREESCALE_DSPI_CTAR_PBR_M) >>
1023
                  FREESCALE_DSPI_CTAR_PBR_S;
1024
            *data_p = (dspi_bus->clock_freq * (1+dbr)) / (pbr * br);
1025
 
1026
            DEBUG2_PRINTF("DSPI Get Config: baud = %d\n", *data_p);
1027
 
1028
            return 0;
1029
        }
1030
 
1031
    default :
1032
        break;
1033
    }
1034
    return -1;
1035
}
1036
 
1037
//-----------------------------------------------------------------------------
1038
// Change some SPI device configuration parameters
1039
 
1040
static int dspi_set_config(cyg_spi_device* device, cyg_uint32 key,
1041
                           const void* buf, cyg_uint32* len)
1042
{
1043
    cyg_spi_freescale_dspi_device_t* dspi_device =
1044
          (cyg_spi_freescale_dspi_device_t*) device;
1045
    cyg_spi_freescale_dspi_bus_t* dspi_bus =
1046
          (cyg_spi_freescale_dspi_bus_t*) device->spi_bus;
1047
 
1048
    cyg_uint32 regval;
1049
    ctar_br_t brs;
1050
 
1051
    switch (key) {
1052
    case CYG_IO_SET_CONFIG_SPI_CLOCKRATE :
1053
        // Sanity check
1054
        if (NULL == len) {
1055
            CYG_ASSERT (false, "Freescale DSPI:"
1056
                      " Null pointer as len argument for dspi_set_config().");
1057
            return -1;
1058
        } else if (sizeof(cyg_uint32) != *len) {
1059
            CYG_ASSERT (false, "Freescale DSPI:"
1060
                        " Invalid length with dspi_set_config().");
1061
            return -1;
1062
        } else if (NULL == buf) {
1063
            CYG_ASSERT (false, "Freescale DSPI:"
1064
                        " Null pointer as buf argument for dspi_set_config().");
1065
            return -1;
1066
        } else {
1067
            // Get divider bits
1068
            if (!dspi_ctar_brbf(&dspi_device->clocking, &brs,
1069
                                   ctar_br, ctar_pbr, (cyg_uint32 *)buf, dspi_bus->clock_freq))
1070
            {
1071
                // Update the cache of the configuration register settings.
1072
                regval = dspi_device->clocking.dspi_ctar;
1073
                regval &= ~(FREESCALE_DSPI_CTAR_BR_M |
1074
                            FREESCALE_DSPI_CTAR_PBR_M);
1075
                regval |= FREESCALE_DSPI_CTAR_BR(brs.br) |
1076
                      FREESCALE_DSPI_CTAR_PBR(brs.pbr);
1077
                dspi_device->clocking.dspi_ctar = regval;
1078
 
1079
                return 0;
1080
 
1081
            } else {
1082
                CYG_ASSERT (false, "Freescale DSPI:"
1083
                            " Cannot run bus as slowly as requested.");
1084
                return -1;
1085
            }
1086
        }
1087
    default :
1088
        break;
1089
    }
1090
    return -1;
1091
}
1092
 
1093
#if DEBUG_SPI
1094
//----------------------------------------------------------------------------
1095
// Print out a DSPI array state
1096
// Helper for cyghwr_devs_freescale_dspi_diag()
1097
 
1098
void cyghwr_devs_freescale_dspi_diag_array(char* name_p,
1099
                                           volatile cyg_uint32* array_p,
1100
                                           cyg_uint32 array_n)
1101
{
1102
    diag_printf("%s %p[%u]: ", name_p, array_p, array_n);
1103
    for(; array_n; array_n--) {
1104
        diag_printf(" 0x%08x", *array_p++);
1105
    }
1106
    diag_printf("\n");
1107
}
1108
 
1109
//----------------------------------------------------------------------------
1110
// Print out DSPI state
1111
 
1112
void cyghwr_devs_freescale_dspi_diag(cyg_spi_freescale_dspi_bus_t* dspi_bus_p)
1113
{
1114
    cyghwr_devs_freescale_dspi_t* dspi_p = dspi_bus_p->setup_p->dspi_p;
1115
 
1116
    diag_printf("DSPI %p\n", dspi_p);
1117
    diag_printf("  MCR = 0x%08x TCR = 0x%08x\n", dspi_p->mcr, dspi_p->tcr);
1118
    cyghwr_devs_freescale_dspi_diag_array("  CTAR",  dspi_p->ctar,
1119
                                          CYGHWR_DEVS_SPI_FREESCALE_DSPI_CTAR_NUM);
1120
    diag_printf("  SR = 0x%08x RSER = 0x%08x PUSHR = 0x%08x POPR = 0x%08x\n",
1121
                dspi_p->sr, dspi_p->rser, dspi_p->pushr, dspi_p->popr);
1122
    cyghwr_devs_freescale_dspi_diag_array("  TXFR", dspi_p->txfr, dspi_bus_p->txfifo_n);
1123
    cyghwr_devs_freescale_dspi_diag_array("  RXFR", dspi_p->rxfr, dspi_bus_p->rxfifo_n);
1124
}
1125
#endif // DEBUG_SPI
1126
 
1127
#endif // defined(CYGHWR_DEVS_SPI_FREESCALE_DSPIx)
1128
 
1129
//=============================================================================

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.