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

Last change on this file since 776 was 545, checked in by alain, 10 years ago

Cosmetic

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