source: trunk/boot/tsar_mips32/boot_spi_utils.c

Last change on this file was 680, checked in by alain, 6 years ago

euh...

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