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

Last change on this file since 540 was 456, checked in by alain, 10 years ago

Defining the NIC and CMA drivers (validated by the classif application).
Updating other drivers to comply with the new tty0 common 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
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// This ISR handles the IRQ generated by a SPI controler
257///////////////////////////////////////////////////////////////////////////////
258void _spi_isr( unsigned int irq_type,
259               unsigned int irq_id,
260               unsigned int channel )
261{
262    _puts("\n[GIET ERROR] _spi_isr() not implemented\n");
263    _exit();
264}
265
266// Local Variables:
267// tab-width: 4
268// c-basic-offset: 4
269// c-file-offsets:((innamespace . 0)(inline-open . 0))
270// indent-tabs-mode: nil
271// End:
272// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.