source: soft/giet_vm/giet_drivers/spi_driver.c @ 334

Last change on this file since 334 was 320, checked in by alain, 11 years ago

All drivers have been modified to use only the information
contained in the hard_config.h file

File size: 9.0 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : spi_driver.c
3// Date     : 31/08/2012
4// Author   : cesar fuguet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7#include <spi_driver.h>
8#include <utils.h>
9
10///////////////////////////////////////////////////////////////////////////////
11//      bswap32()
12// This function makes a byte swap for a 4 bytes word
13// Arguments are:
14// - x : word
15// Returns the word x swapped
16///////////////////////////////////////////////////////////////////////////////
17static unsigned int bswap32(unsigned int x)
18{
19  unsigned int y;
20  y =  (x & 0x000000ff) << 24;
21  y |= (x & 0x0000ff00) <<  8;
22  y |= (x & 0x00ff0000) >>  8;
23  y |= (x & 0xff000000) >> 24;
24  return y;
25}
26
27///////////////////////////////////////////////////////////////////////////////
28//      _spi_wait_if_busy()
29// This function returns when the SPI controller has finished a transfer
30// Arguments are:
31// - spi : initialized pointer to the SPI controller
32///////////////////////////////////////////////////////////////////////////////
33static void _spi_wait_if_busy(struct spi_dev * spi)
34{
35    register int delay;
36
37    while(SPI_IS_BUSY(spi))
38    {
39        for (delay = 0; delay < 100; delay++);
40    }
41}
42
43///////////////////////////////////////////////////////////////////////////////
44//      _spi_init_transfer()
45// This function trigger transfer of the tx registers to the selected slaves
46// Arguments are:
47// - spi : initialized pointer to the SPI controller
48///////////////////////////////////////////////////////////////////////////////
49static void _spi_init_transfer(struct spi_dev * spi)
50{
51    unsigned int spi_ctrl = ioread32(&spi->ctrl);
52
53    iowrite32(&spi->ctrl, spi_ctrl | SPI_CTRL_GO_BSY);
54}
55
56///////////////////////////////////////////////////////////////////////////////
57//      _spi_calc_divider_value()
58// This function computes the value for the divider register in order to obtain
59// the SPI desired clock frequency
60// - spi_freq : desired frequency for the generated clock from the SPI
61//              controller
62// - sys_freq : system clock frequency
63// Returns the computed frequency
64///////////////////////////////////////////////////////////////////////////////
65static unsigned int _spi_calc_divider_value( unsigned int spi_freq ,
66                                             unsigned int sys_freq )
67{
68    return ((sys_freq / (spi_freq * 2)) - 1);
69}
70
71///////////////////////////////////////////////////////////////////////////////
72//      spi_put_tx()
73// This function writes a byte on the tx register and trigger transfert
74// - spi  : initialized pointer to the SPI controller
75// - byte : byte to write on tx register
76// - index: index of the tx register
77///////////////////////////////////////////////////////////////////////////////
78void spi_put_tx(struct spi_dev * spi, unsigned char byte, int index)
79{
80    _spi_wait_if_busy(spi);
81    {
82        iowrite8(&spi->rx_tx[index % 4], byte);
83        _spi_init_transfer(spi);
84    }
85    _spi_wait_if_busy(spi);
86}
87
88///////////////////////////////////////////////////////////////////////////////
89//      spi_get_rx()
90// This function reads a byte on the rx register
91// - spi  : initialized pointer to the SPI controller
92// - index: index of the rx register
93// Returns the byte read
94///////////////////////////////////////////////////////////////////////////////
95volatile unsigned char spi_get_rx(struct spi_dev * spi, int index)
96{
97    return ioread8(&spi->rx_tx[index % 4]);
98}
99
100///////////////////////////////////////////////////////////////////////////////
101//      spi_get_data()
102// This function reads count bytes and store them on a memory buffer
103// - spi   : initialized pointer to the SPI controller
104// - buffer: physical address of the buffer containing the read data
105// - count : number of bytes to get (must be 512 bytes)
106// Returns 0 if success and other value when failure
107///////////////////////////////////////////////////////////////////////////////
108unsigned int spi_get_data( struct spi_dev * spi,
109                           paddr_t buffer      ,
110                           unsigned int count  )
111{
112    unsigned int spi_ctrl0; // ctrl value before calling this function
113    unsigned int spi_ctrl;
114    int i;
115
116    /*
117     * Only reading of one block (512 bytes) are supported
118     */
119    if ( count != 512 ) return 1;
120
121    _spi_wait_if_busy(spi);
122
123    spi_ctrl0 = ioread32(&spi->ctrl);
124
125#if 0
126    /*
127     * Read data using SPI DMA mechanism
128     * Two restrictions:
129     *   1. Can transfer only one block (512 bytes).
130     *   2. The destination buffer must be aligned to SPI burst size (64 bytes)
131     */
132    if ((buffer & 0x3f) == 0)
133    {
134        _puts("spi_get_data(): Starting DMA transfer / count = ");
135        _putx(count);
136        _puts("\n");
137
138        _puts("spi_get_data(): buffer = ");
139        _putx(buffer);
140        _puts("\n");
141
142        spi->dma_base  = (buffer      ) & ((1 << 32) - 1); // 32 lsb
143        spi->dma_baseh = (buffer >> 32) & ((1 << 8 ) - 1); // 8  msb
144        spi->dma_count = count | SPI_DMA_COUNT_READ;
145
146        while ( (spi->dma_count >> 1) );
147
148        goto reset_ctrl;
149    }
150#endif
151
152    /*
153     * Read data without SPI DMA mechanism
154     *
155     * Switch to 128 bits words
156     */
157
158    spi_ctrl = (spi_ctrl0 & ~SPI_CTRL_CHAR_LEN_MASK) | 128;
159    iowrite32(&spi->ctrl, spi_ctrl);
160
161    /*
162     * Read data.
163     * Four 32 bits words at each iteration (128 bits = 16 bytes)
164     */
165    for (i = 0; i < count/16; i++)
166    {
167        iowrite32(&spi->rx_tx[0], 0xffffffff);
168        iowrite32(&spi->rx_tx[1], 0xffffffff);
169        iowrite32(&spi->rx_tx[2], 0xffffffff);
170        iowrite32(&spi->rx_tx[3], 0xffffffff);
171        iowrite32(&spi->ctrl,  spi_ctrl | SPI_CTRL_GO_BSY);
172
173        _spi_wait_if_busy(spi);
174
175        _physical_write( buffer, bswap32(ioread32(&spi->rx_tx[3])) ); 
176        buffer += 4;
177        _physical_write( buffer, bswap32(ioread32(&spi->rx_tx[2])) ); 
178        buffer += 4;
179        _physical_write( buffer, bswap32(ioread32(&spi->rx_tx[1])) ); 
180        buffer += 4;
181        _physical_write( buffer, bswap32(ioread32(&spi->rx_tx[0])) ); 
182        buffer += 4;
183    }
184
185#if 0
186reset_ctrl:
187#endif
188
189    /* Switch back to original word size */
190    iowrite32(&spi->ctrl, spi_ctrl0);
191
192    return 0;
193}
194
195///////////////////////////////////////////////////////////////////////////////
196//      spi_ss_assert()
197// This function enables a SPI slave
198// - spi   : initialized pointer to the SPI controller
199// - index : slave index
200///////////////////////////////////////////////////////////////////////////////
201void spi_ss_assert(struct spi_dev * spi, int index)
202{
203    unsigned int spi_ss = ioread32(&spi->ss);
204
205    iowrite32(&spi->ss, spi_ss | (1 << index));
206}
207
208///////////////////////////////////////////////////////////////////////////////
209//      spi_ss_deassert()
210// This function disables a SPI slave
211// - spi   : initialized pointer to the SPI controller
212// - index : slave index
213///////////////////////////////////////////////////////////////////////////////
214void spi_ss_deassert(struct spi_dev * spi, int index)
215{
216    unsigned int spi_ss = ioread32(&spi->ss);
217
218    iowrite32(&spi->ss, spi_ss & ~(1 << index));
219}
220
221///////////////////////////////////////////////////////////////////////////////
222//      _spi_init()
223// This function initializes the configuration register of SPI controller
224// - spi      : initialized pointer to the SPI controller
225// - spi_freq : SPI desired frequency (Hz)
226// - sys_freq : system frequency (Hz)
227// - char_len : bits per transfer
228// - tx_edge  : if 1, transfer on positive edge
229// - rx_edge  : if 1, latch received data on negative edge
230///////////////////////////////////////////////////////////////////////////////
231void _spi_init ( struct spi_dev * spi,
232                 int spi_freq        ,
233                 int sys_freq        ,
234                 int char_len        ,
235                 int tx_edge         ,
236                 int rx_edge         )
237{
238    unsigned int spi_ctrl = ioread32(&spi->ctrl);
239
240    if      ( tx_edge == 0 ) spi_ctrl |=  SPI_CTRL_TXN_EN;
241    else if ( tx_edge == 1 ) spi_ctrl &= ~SPI_CTRL_TXN_EN;
242    if      ( rx_edge == 0 ) spi_ctrl |=  SPI_CTRL_RXN_EN;
243    else if ( rx_edge == 1 ) spi_ctrl &= ~SPI_CTRL_RXN_EN;
244    if      ( char_len > 0 ) spi_ctrl  = (spi_ctrl & ~SPI_CTRL_CHAR_LEN_MASK) |
245                                         (char_len &  SPI_CTRL_CHAR_LEN_MASK);
246
247    iowrite32(&spi->ctrl, spi_ctrl);
248
249    if (spi_freq > 0 && sys_freq > 0)
250        iowrite32(&spi->divider, _spi_calc_divider_value(spi_freq, sys_freq));
251}
252
253///////////////////////////////////////////////////////////////////////////////
254// This ISR handles the IRQ generated by a SPI controler
255///////////////////////////////////////////////////////////////////////////////
256void _spi_isr( unsigned int irq_type,
257               unsigned int irq_id,
258               unsigned int channel )
259{
260    _printf("\n[GIET ERROR] _spi_isr() not implemented\n");
261    _exit();
262}
263
264// Local Variables:
265// tab-width: 4
266// c-basic-offset: 4
267// c-file-offsets:((innamespace . 0)(inline-open . 0))
268// indent-tabs-mode: nil
269// End:
270// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.