source: trunk/hal/tsar_mips32/drivers/soclib_spi.c @ 654

Last change on this file since 654 was 619, checked in by alain, 6 years ago

1) Fix a bug in KSH : after the "load" command,

the [ksh] prompt is now printed after completion
of the loaded application.

2) Fix a bug in vmm_handle_cow() : the copy-on-write

use now a hal_remote_memcpy() to replicate the page content.


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