]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/spi/arm/at91/v2_0/src/spi_at91.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / spi / arm / at91 / v2_0 / src / spi_at91.c
1 //==========================================================================
2 //
3 //      spi_at91.c
4 //
5 //      Atmel AT91 (ARM) SPI driver 
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, 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 version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 // -------------------------------------------
36 //####ECOSGPLCOPYRIGHTEND####
37 //==========================================================================
38 //#####DESCRIPTIONBEGIN####
39 //
40 // Author(s):     Savin Zlobec <savin@elatec.si> 
41 // Date:          2004-08-25
42 //
43 //####DESCRIPTIONEND####
44 //
45 //==========================================================================
46
47 #include <pkgconf/hal.h>
48 #include <pkgconf/io_spi.h>
49 #include <pkgconf/devs_spi_arm_at91.h>
50
51 #include <cyg/infra/cyg_type.h>
52 #include <cyg/infra/cyg_ass.h>
53 #include <cyg/hal/hal_io.h>
54 #include <cyg/hal/hal_if.h>
55 #include <cyg/hal/hal_intr.h>
56 #include <cyg/hal/drv_api.h>
57 #include <cyg/io/spi.h>
58 #include <cyg/io/spi_at91.h>
59 #include <cyg/error/codes.h>
60
61 // -------------------------------------------------------------------------
62 static void spi_at91_init_bus(cyg_spi_at91_bus_t * bus);
63
64 static cyg_uint32 spi_at91_ISR(cyg_vector_t vector, cyg_addrword_t data);
65
66 static void spi_at91_DSR(cyg_vector_t   vector, 
67                          cyg_ucount32   count, 
68                          cyg_addrword_t data);
69
70 static void spi_at91_transaction_begin(cyg_spi_device *dev);
71
72 static void spi_at91_transaction_transfer(cyg_spi_device  *dev,
73                                           cyg_bool         polled,
74                                           cyg_uint32       count,
75                                           const cyg_uint8 *tx_data,
76                                           cyg_uint8       *rx_data,
77                                           cyg_bool         drop_cs);
78
79 static void spi_at91_transaction_tick(cyg_spi_device *dev,
80                                       cyg_bool        polled,
81                                       cyg_uint32      count);
82
83 static void spi_at91_transaction_end(cyg_spi_device* dev);
84
85 static int spi_at91_get_config(cyg_spi_device *dev, 
86                                cyg_uint32      key, 
87                                void           *buf,
88                                cyg_uint32     *len);
89
90 static int spi_at91_set_config(cyg_spi_device *dev, 
91                                cyg_uint32      key, 
92                                const void     *buf, 
93                                cyg_uint32     *len);
94
95 // -------------------------------------------------------------------------
96 // AT91 SPI BUS
97
98 #ifdef CYGHWR_DEVS_SPI_ARM_AT91_BUS0
99 cyg_spi_at91_bus_t cyg_spi_at91_bus0 = {
100     .spi_bus.spi_transaction_begin    = spi_at91_transaction_begin,
101     .spi_bus.spi_transaction_transfer = spi_at91_transaction_transfer,
102     .spi_bus.spi_transaction_tick     = spi_at91_transaction_tick,
103     .spi_bus.spi_transaction_end      = spi_at91_transaction_end,
104     .spi_bus.spi_get_config           = spi_at91_get_config,
105     .spi_bus.spi_set_config           = spi_at91_set_config,
106     .interrupt_number                 = CYGNUM_HAL_INTERRUPT_SPI,
107     .base                             = AT91_SPI,
108 #ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS0_NONE
109     .cs_en[0]                         = true,
110     .cs_gpio[0]                       = CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS0,
111 #else
112     .cs_en[0]                         = false,
113 #endif
114 #ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS1_NONE
115     .cs_en[1]                         = true,
116     .cs_gpio[1]                       = CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS1,
117 #else
118     .cs_en[1]                         = false,
119 #endif
120 #ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS2_NONE
121     .cs_en[2]                         = true,
122     .cs_gpio[2]                       = CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS2,
123 #else
124     .cs_en[2]                         = false,
125 #endif
126 #ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS3_NONE
127     .cs_en[3]                         = true,
128     .cs_gpio[3]                       = CYGDAT_DEVS_SPI_ARM_AT91_BUS0_NPCS3,
129 #else
130     .cs_en[3]                         = false,
131 #endif
132 };
133
134 CYG_SPI_DEFINE_BUS_TABLE(cyg_spi_at91_device_t, 0);
135 #endif
136 #ifdef CYGHWR_DEVS_SPI_ARM_AT91_BUS1
137 cyg_spi_at91_bus_t cyg_spi_at91_bus1 = {
138     .spi_bus.spi_transaction_begin    = spi_at91_transaction_begin,
139     .spi_bus.spi_transaction_transfer = spi_at91_transaction_transfer,
140     .spi_bus.spi_transaction_tick     = spi_at91_transaction_tick,
141     .spi_bus.spi_transaction_end      = spi_at91_transaction_end,
142     .spi_bus.spi_get_config           = spi_at91_get_config,
143     .spi_bus.spi_set_config           = spi_at91_set_config,
144     .interrupt_number                 = CYGNUM_HAL_INTERRUPT_SPI1,
145     .base                             = AT91_SPI1,
146 #ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS0_NONE
147     .cs_en[0]                         = true,
148     .cs_gpio[0]                       = CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS0,
149 #else
150     .cs_en[0]                         = false,
151 #endif
152 #ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS1_NONE
153     .cs_en[1]                         = true,
154     .cs_gpio[1]                       = CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS1,
155 #else
156     .cs_en[1]                         = false,
157 #endif
158 #ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS2_NONE
159     .cs_en[2]                         = true,
160     .cs_gpio[2]                       = CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS2,
161 #else
162     .cs_en[2]                         = false,
163 #endif
164 #ifndef CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS3_NONE
165     .cs_en[3]                         = true,
166     .cs_gpio[3]                       = CYGDAT_DEVS_SPI_ARM_AT91_BUS1_NPCS3,
167 #else
168     .cs_en[3]                         = false,
169 #endif
170 };
171
172 CYG_SPI_DEFINE_BUS_TABLE(cyg_spi_at91_device_t, 1);
173 #endif
174 // -------------------------------------------------------------------------
175
176 void
177 cyg_spi_at91_bus_init(void)
178 {
179
180 #ifdef CYGHWR_DEVS_SPI_ARM_AT91_BUS0
181    // NOTE: here we let the SPI controller control 
182    //       the data in, out and clock signals, but 
183    //       we need to handle the chip selects manually 
184    //       in order to achieve better chip select control 
185    //       in between transactions.
186
187    // Put SPI MISO, MOIS and SPCK pins into peripheral mode
188    HAL_ARM_AT91_PIO_CFG(AT91_SPI_SPCK);
189    HAL_ARM_AT91_PIO_CFG(AT91_SPI_MISO);
190    HAL_ARM_AT91_PIO_CFG(AT91_SPI_MOIS);
191    spi_at91_init_bus(&cyg_spi_at91_bus0);
192 #endif
193 #ifdef CYGHWR_DEVS_SPI_ARM_AT91_BUS1
194    // NOTE: here we let the SPI controller control 
195    //       the data in, out and clock signals, but 
196    //       we need to handle the chip selects manually 
197    //       in order to achieve better chip select control 
198    //       in between transactions.
199
200    // Put SPI MISO, MOIS and SPCK pins into peripheral mode
201    HAL_ARM_AT91_PIO_CFG(AT91_SPI1_SPCK);
202    HAL_ARM_AT91_PIO_CFG(AT91_SPI1_MISO);
203    HAL_ARM_AT91_PIO_CFG(AT91_SPI1_MOSI);
204    spi_at91_init_bus(&cyg_spi_at91_bus1);
205 #endif
206 }
207
208 // -------------------------------------------------------------------------
209
210 static void spi_at91_init_bus(cyg_spi_at91_bus_t * spi_bus)
211 {
212     cyg_uint32 ctr;
213     // Create and attach SPI interrupt object
214     cyg_drv_interrupt_create(spi_bus->interrupt_number,
215                              4,                   
216                              (cyg_addrword_t)spi_bus,   
217                              spi_at91_ISR,
218                              spi_at91_DSR,
219                              &spi_bus->spi_interrupt_handle,
220                              &spi_bus->spi_interrupt);
221
222     cyg_drv_interrupt_attach(spi_bus->spi_interrupt_handle);
223
224     // Init transfer mutex and condition
225     cyg_drv_mutex_init(&spi_bus->transfer_mx);
226     cyg_drv_cond_init(&spi_bus->transfer_cond, 
227                       &spi_bus->transfer_mx);
228    
229     // Init flags
230     spi_bus->transfer_end = true;
231     spi_bus->cs_up        = false;
232     
233     // Soft reset the SPI controller
234     HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_CR, AT91_SPI_CR_SWRST);
235
236     // Configure SPI pins
237       
238
239     // Put SPI chip select pins in IO output mode
240     for(ctr = 0;ctr<4;ctr++)
241     {
242        if(spi_bus->cs_en[ctr])
243        {
244           HAL_ARM_AT91_GPIO_CFG_DIRECTION(spi_bus->cs_gpio[ctr],AT91_PIN_OUT);
245        }
246     }
247     // Call upper layer bus init
248     CYG_SPI_BUS_COMMON_INIT(&spi_bus->spi_bus);
249 }
250
251 static cyg_uint32 
252 spi_at91_ISR(cyg_vector_t vector, cyg_addrword_t data)
253 {
254     cyg_uint32 stat;
255     cyg_spi_at91_bus_t * spi_bus = (cyg_spi_at91_bus_t *)data;
256     // Read the status register and disable
257     // the SPI int events that have occoured
258     
259     HAL_READ_UINT32(spi_bus->base+AT91_SPI_SR,   stat);
260     HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_IDR, stat);
261     
262     cyg_drv_interrupt_mask(vector);
263     cyg_drv_interrupt_acknowledge(vector);
264
265     return CYG_ISR_CALL_DSR;
266 }
267
268 static void 
269 spi_at91_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
270 {
271     cyg_spi_at91_bus_t *spi_bus = (cyg_spi_at91_bus_t *) data;
272     cyg_uint32 stat;
273     
274     // Read the status register and 
275     // check for transfer completition
276     
277     HAL_READ_UINT32(spi_bus->base+AT91_SPI_SR, stat);
278
279     if((stat & AT91_SPI_SR_ENDRX) && (stat & AT91_SPI_SR_ENDTX))
280     {
281         // Transfer ended  
282         spi_bus->transfer_end = true;
283         cyg_drv_cond_signal(&spi_bus->transfer_cond);
284     }
285     else
286     {
287         // Transfer still in progress - unmask the SPI 
288         // int so we can get more SPI int events
289         cyg_drv_interrupt_unmask(vector);
290     }
291 }
292
293 static cyg_bool 
294 spi_at91_calc_scbr(cyg_spi_at91_device_t *dev)
295 {
296     cyg_uint32 scbr;
297     cyg_bool   res = true;
298     
299     // Calculate SCBR from baud rate
300     
301     scbr = CYGNUM_HAL_ARM_AT91_CLOCK_SPEED / (2*dev->cl_brate);
302
303     if (scbr < 2)
304     {
305         dev->cl_scbr  = 2;
306         dev->cl_div32 = 0;
307         res = false;
308     }
309     else if (scbr > 255)
310     {
311         dev->cl_div32 = 1;
312         
313         scbr = CYGNUM_HAL_ARM_AT91_CLOCK_SPEED / (64*dev->cl_brate);
314
315         if (scbr < 2) 
316         {
317             dev->cl_scbr = 2;
318             res = false;
319         }
320         else if (scbr > 255) 
321         {
322             dev->cl_scbr = 255;
323             res = false;
324         }
325         else
326             dev->cl_scbr = (cyg_uint8)scbr;
327     }
328     else
329     {
330         dev->cl_scbr  = (cyg_uint8)scbr;
331         dev->cl_div32 = 0;
332     }
333     
334     return res;
335 }
336
337 static void
338 spi_at91_set_npcs(cyg_spi_at91_bus_t *spi_bus,int val)
339 {
340    cyg_uint32 ctr;
341    for(ctr=0;ctr<4;ctr++)
342    {
343       if(spi_bus->cs_en[ctr])
344       {
345         HAL_ARM_AT91_GPIO_PUT(spi_bus->cs_gpio[ctr], (val & (1<<ctr)));
346       }
347    }
348 }
349
350 static void
351 spi_at91_start_transfer(cyg_spi_at91_device_t *dev)
352 {
353     cyg_spi_at91_bus_t *spi_bus = (cyg_spi_at91_bus_t *)dev->spi_device.spi_bus;
354   
355     if (spi_bus->cs_up)
356         return;
357  
358     // Force minimal delay between two transfers - in case two transfers
359     // follow each other w/o delay, then we have to wait here in order for
360     // the peripheral device to detect cs transition from inactive to active. 
361     CYGACC_CALL_IF_DELAY_US(dev->tr_bt_udly);
362     
363     // Raise CS
364
365 #ifdef CYGHWR_DEVS_SPI_ARM_AT91_PCSDEC
366     spi_at91_set_npcs(spi_bus,~dev->dev_num);
367 #else
368     spi_at91_set_npcs(spi_bus,~(1<<dev->dev_num));
369 #endif
370     CYGACC_CALL_IF_DELAY_US(dev->cs_up_udly);
371    
372     spi_bus->cs_up = true;
373 }
374
375 static void
376 spi_at91_drop_cs(cyg_spi_at91_device_t *dev)
377 {
378     cyg_spi_at91_bus_t *spi_bus = (cyg_spi_at91_bus_t *)dev->spi_device.spi_bus;
379     
380     if (!spi_bus->cs_up)
381        return;
382            
383     // Drop CS
384
385     CYGACC_CALL_IF_DELAY_US(dev->cs_dw_udly);
386     spi_at91_set_npcs(spi_bus,0x0F); 
387     spi_bus->cs_up = false;
388 }
389
390 static void
391 spi_at91_transfer(cyg_spi_at91_device_t *dev,
392                   cyg_uint32             count, 
393                   const cyg_uint8       *tx_data,
394                   cyg_uint8             *rx_data)
395 {
396     cyg_spi_at91_bus_t *spi_bus = (cyg_spi_at91_bus_t *)dev->spi_device.spi_bus;
397
398     // Since PDC transfer buffer counters are 16 bit long, 
399     // we have to split longer transfers into chunks. 
400     while (count > 0)
401     {
402         cyg_uint16 tr_count = count > 0xFFFF ? 0xFFFF : count;
403
404         // Set rx buf pointer and counter 
405         if (NULL != rx_data)
406         {
407             HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_RPR, (cyg_uint32)rx_data);
408             HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_RCR, (cyg_uint32)tr_count);
409         }
410
411         // Set tx buf pointer and counter  
412         HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_TPR, (cyg_uint32)tx_data);
413         HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_TCR, (cyg_uint32)tr_count);
414    
415 #ifdef AT91_SPI_PTCR
416         HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_PTCR, 
417                          AT91_SPI_PTCR_RXTEN | AT91_SPI_PTCR_TXTEN);
418 #endif
419         // Enable the SPI int events we are interested in
420         HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_IER, 
421                          AT91_SPI_SR_ENDRX | AT91_SPI_SR_ENDTX);
422
423         cyg_drv_mutex_lock(&spi_bus->transfer_mx);
424         {
425             spi_bus->transfer_end = false;
426     
427             // Unmask the SPI int
428             cyg_drv_interrupt_unmask(spi_bus->interrupt_number);
429         
430             // Wait for its completition
431             cyg_drv_dsr_lock();
432             {
433                 while (!spi_bus->transfer_end)
434                     cyg_drv_cond_wait(&spi_bus->transfer_cond);
435             }
436             cyg_drv_dsr_unlock();
437         }    
438         cyg_drv_mutex_unlock(&spi_bus->transfer_mx);
439
440         if (NULL == rx_data)
441         {
442             cyg_uint32 val;
443         
444             // If rx buffer was NULL, then the PDC receiver data transfer
445             // was not started and we didn't wait for ENDRX, but only for 
446             // ENDTX. Meaning that right now the last byte is being serialized 
447             // over the line and when finished input data will appear in 
448             // rx data reg. We have to wait for this to happen here, if we
449             // don't we'll get the last received byte as the first one in the
450             // next transfer!
451         
452             // FIXME: is there any better way to do this? 
453             // If not, then precalculate this value.
454             val = 8000000/dev->cl_brate;
455             CYGACC_CALL_IF_DELAY_US(val > 1 ? val : 1);
456
457             // Clear the rx data reg
458             HAL_READ_UINT32(spi_bus->base+AT91_SPI_RDR, val);
459         }
460
461         // Adjust running variables
462         
463         if (NULL != rx_data)
464             rx_data += tr_count;
465         tx_data += tr_count;
466         count   -= tr_count;
467     }
468 }
469
470 static void
471 spi_at91_transfer_polled(cyg_spi_at91_device_t *dev, 
472                          cyg_uint32             count,
473                          const cyg_uint8       *tx_data,
474                          cyg_uint8             *rx_data)
475 {
476     cyg_uint32 val;
477     cyg_spi_at91_bus_t *spi_bus = (cyg_spi_at91_bus_t *)dev->spi_device.spi_bus;
478
479     // Transmit and receive byte by byte
480     while (count-- > 0)
481     {
482         // Wait for transmit data register empty
483         do
484         {
485             HAL_READ_UINT32(spi_bus->base+AT91_SPI_SR, val);
486         } while ( !(val & AT91_SPI_SR_TDRE) );
487        
488         // Send next byte over the wire 
489         val = *tx_data++;
490         HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_TDR, val);
491         
492         // Wait for reveive data register full 
493         do
494         {
495             HAL_READ_UINT32(spi_bus->base+AT91_SPI_SR, val);
496         } while ( !(val & AT91_SPI_SR_RDRF) );
497         
498         // Store received byte 
499         HAL_READ_UINT32(spi_bus->base+AT91_SPI_RDR, val);
500         if (NULL != rx_data)
501             *rx_data++ = val; 
502     }
503 }
504
505 // -------------------------------------------------------------------------
506
507 static void 
508 spi_at91_transaction_begin(cyg_spi_device *dev)
509 {
510     cyg_spi_at91_device_t *at91_spi_dev = (cyg_spi_at91_device_t *) dev;    
511     cyg_spi_at91_bus_t *spi_bus = 
512       (cyg_spi_at91_bus_t *)at91_spi_dev->spi_device.spi_bus;
513     cyg_uint32 val;
514     
515     if (!at91_spi_dev->init)
516     {
517         at91_spi_dev->init = true;
518         spi_at91_calc_scbr(at91_spi_dev);
519     }
520     
521     // Configure SPI channel 0 - this is the only channel we 
522     // use for all devices since we drive chip selects manually
523     
524     val = AT91_SPI_CSR_BITS8;
525
526     if (1 == at91_spi_dev->cl_pol)
527         val |= AT91_SPI_CSR_CPOL;
528
529     if (1 == at91_spi_dev->cl_pha)
530         val |= AT91_SPI_CSR_NCPHA;
531
532     val |= AT91_SPI_CSR_SCBR(at91_spi_dev->cl_scbr);
533
534     HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_CSR0, val); 
535
536     // Enable SPI clock
537     HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCER, 1<<spi_bus->interrupt_number);
538
539     // Enable the SPI controller
540     HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_CR, AT91_SPI_CR_SPIEN);
541     
542     /* As we are using this driver only in master mode with NPCS0 
543        configured as GPIO instead of a peripheral pin, it is neccessary 
544        for the Mode Failure detection to be switched off as this will
545        cause havoc with the driver */ 
546
547     // Put SPI bus into master mode
548     if (1 == at91_spi_dev->cl_div32) {
549       val = AT91_SPI_MR_MSTR | AT91_SPI_MR_DIV32;
550 #ifdef AT91_SPI_MR_MODFDIS
551       val |= AT91_SPI_MR_MODFDIS;
552 #endif
553       HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_MR, val);
554     } else {
555       val = AT91_SPI_MR_MSTR;
556 #ifdef AT91_SPI_MR_MODFDIS
557       val |= AT91_SPI_MR_MODFDIS;
558 #endif
559       HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_MR, val);
560     }
561 }
562
563 static void 
564 spi_at91_transaction_transfer(cyg_spi_device  *dev, 
565                               cyg_bool         polled,  
566                               cyg_uint32       count, 
567                               const cyg_uint8 *tx_data, 
568                               cyg_uint8       *rx_data, 
569                               cyg_bool         drop_cs) 
570 {
571     cyg_spi_at91_device_t *at91_spi_dev = (cyg_spi_at91_device_t *) dev;
572
573     // Select the device if not already selected
574     spi_at91_start_transfer(at91_spi_dev);
575  
576     // Perform the transfer
577     if (polled)
578         spi_at91_transfer_polled(at91_spi_dev, count, tx_data, rx_data);
579     else
580         spi_at91_transfer(at91_spi_dev, count, tx_data, rx_data);
581
582     // Deselect the device if requested
583     if (drop_cs)
584         spi_at91_drop_cs(at91_spi_dev);
585 }
586
587 static void 
588 spi_at91_transaction_tick(cyg_spi_device *dev, 
589                           cyg_bool        polled,  
590                           cyg_uint32      count)
591 {
592     const cyg_uint32 zeros[10] = { 0,0,0,0,0,0,0,0,0,0 };
593
594     cyg_spi_at91_device_t *at91_spi_dev = (cyg_spi_at91_device_t *) dev;
595     
596     // Transfer count zeros to the device - we don't touch the
597     // chip select, the device could be selected or deselected.
598     // It is up to the device driver to decide in wich state the
599     // device will be ticked.
600     
601     while (count > 0)
602     {
603         int tcnt = count > 40 ? 40 : count;
604         
605         if (polled)
606             spi_at91_transfer_polled(at91_spi_dev, tcnt, 
607                                      (const cyg_uint8 *) zeros, NULL);
608         else
609             spi_at91_transfer(at91_spi_dev, tcnt, 
610                               (const cyg_uint8 *) zeros, NULL);
611
612         count -= tcnt;
613     }
614 }
615
616 static void                    
617 spi_at91_transaction_end(cyg_spi_device* dev)
618 {
619     cyg_spi_at91_device_t * at91_spi_dev = (cyg_spi_at91_device_t *)dev; 
620     cyg_spi_at91_bus_t *spi_bus = 
621       (cyg_spi_at91_bus_t *)at91_spi_dev->spi_device.spi_bus;
622
623     // Disable the SPI controller
624     HAL_WRITE_UINT32(spi_bus->base+AT91_SPI_CR, AT91_SPI_CR_SPIDIS);
625    
626     // Disable SPI clock
627     HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCDR,1<<spi_bus->interrupt_number);
628    
629     spi_at91_drop_cs((cyg_spi_at91_device_t *) dev);
630 }
631
632 static int                     
633 spi_at91_get_config(cyg_spi_device *dev, 
634                     cyg_uint32      key, 
635                     void           *buf,
636                     cyg_uint32     *len)
637 {
638     cyg_spi_at91_device_t *at91_spi_dev = (cyg_spi_at91_device_t *) dev;
639     
640     switch (key) 
641     {
642         case CYG_IO_GET_CONFIG_SPI_CLOCKRATE:
643         {
644             if (*len != sizeof(cyg_uint32))
645                 return -EINVAL;
646             else
647             {
648                 cyg_uint32 *cl_brate = (cyg_uint32 *)buf;
649                 *cl_brate = at91_spi_dev->cl_brate; 
650             }
651         }
652         break;
653         default:
654             return -EINVAL;
655     }
656     return ENOERR;
657 }
658
659 static int                     
660 spi_at91_set_config(cyg_spi_device *dev, 
661                     cyg_uint32      key, 
662                     const void     *buf, 
663                     cyg_uint32     *len)
664 {
665     cyg_spi_at91_device_t *at91_spi_dev = (cyg_spi_at91_device_t *) dev;
666    
667     switch (key) 
668     {
669         case CYG_IO_SET_CONFIG_SPI_CLOCKRATE:
670         {
671             if (*len != sizeof(cyg_uint32))
672                 return -EINVAL;
673             else
674             {
675                 cyg_uint32 cl_brate     = *((cyg_uint32 *)buf);
676                 cyg_uint32 old_cl_brate = at91_spi_dev->cl_brate;
677            
678                 at91_spi_dev->cl_brate = cl_brate;
679             
680                 if (!spi_at91_calc_scbr(at91_spi_dev))
681                 {
682                     at91_spi_dev->cl_brate = old_cl_brate;
683                     spi_at91_calc_scbr(at91_spi_dev);
684                     return -EINVAL;
685                 }
686             }
687         }
688         break;
689         default:
690             return -EINVAL;
691     }
692     return ENOERR;
693 }
694
695 // -------------------------------------------------------------------------
696 // EOF spi_at91.c