source: branch/giet_vm_ioc_drivers/giet_drivers/spi_driver.c @ 283

Last change on this file since 283 was 283, checked in by cfuguet, 10 years ago

Introducing branch to test ioc drivers before merging on trunk

File size: 5.4 KB
Line 
1/**
2 * \file    spi.c
3 * \date    31 August 2012
4 * \author  Cesar Fuguet <cesar.fuguet-tortolero@lip6.fr>
5 */
6#include <spi_driver.h>
7#include <utils.h>
8
9/**
10 * \param   x: input value
11 *
12 * \return  byte-swapped value
13 *
14 * \brief   byte-swap a 32bit word
15 */
16static unsigned int bswap32(unsigned int x)
17{
18  unsigned int y;
19  y =  (x & 0x000000ff) << 24;
20  y |= (x & 0x0000ff00) <<  8;
21  y |= (x & 0x00ff0000) >>  8;
22  y |= (x & 0xff000000) >> 24;
23  return y;
24}
25
26/**
27 * \param   spi :   Initialized pointer to the SPI controller
28 *
29 * \brief   Wait until the SPI controller has finished a transfer
30 *
31 * Wait until the GO_BUSY bit of the SPI controller be deasserted
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 * \param   spi : Initialized pointer to the SPI controller
45 *
46 * \return  void
47 *
48 * \brief   Init transfer of the tx registers to the selected slaves
49 */
50static void _spi_init_transfer(struct 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 * \param   spi_freq    : Desired frequency for the generated clock from the SPI
59 *                        controller
60 * \param   sys_freq    : System clock frequency
61 *
62 * \brief   Calculated the value for the divider register in order to obtain the SPI
63 *          desired clock 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
71void spi_put_tx(struct spi_dev * spi, unsigned char byte, int index)
72{
73    _spi_wait_if_busy(spi);
74    {
75        iowrite8(&spi->rx_tx[index % 4], byte);
76        _spi_init_transfer(spi);
77    }
78    _spi_wait_if_busy(spi);
79}
80
81volatile unsigned char spi_get_rx(struct spi_dev * spi, int index)
82{
83    return ioread8(&spi->rx_tx[index % 4]);
84}
85
86unsigned int spi_get_data( struct spi_dev * spi,
87                           paddr_t buffer      ,
88                           unsigned int count  )
89{
90    unsigned int spi_ctrl0; // ctrl value before calling this function
91    unsigned int spi_ctrl;
92    int i;
93
94    /*
95     * Only reading of one block (512 bytes) are supported
96     */
97    if ( count != 512 ) return 1;
98
99    _spi_wait_if_busy(spi);
100
101    spi_ctrl0 = ioread32(&spi->ctrl);
102
103#if 0
104    /*
105     * Read data using SPI DMA mechanism
106     * Two restrictions:
107     *   1. Can transfer only one block (512 bytes).
108     *   2. The destination buffer must be aligned to SPI burst size (64 bytes)
109     */
110    if ((buffer & 0x3f) == 0)
111    {
112        _puts("spi_get_data(): Starting DMA transfer / count = ");
113        _putx(count);
114        _puts("\n");
115
116        _puts("spi_get_data(): buffer = ");
117        _putx(buffer);
118        _puts("\n");
119
120        spi->dma_base  = (buffer      ) & ((1 << 32) - 1); // 32 lsb
121        spi->dma_baseh = (buffer >> 32) & ((1 << 8 ) - 1); // 8  msb
122        spi->dma_count = count | SPI_DMA_COUNT_READ;
123
124        while ( (spi->dma_count >> 1) );
125
126        goto reset_ctrl;
127    }
128#endif
129
130    /*
131     * Read data without SPI DMA mechanism
132     *
133     * Switch to 128 bits words
134     */
135
136    spi_ctrl = (spi_ctrl0 & ~SPI_CTRL_CHAR_LEN_MASK) | 128;
137    iowrite32(&spi->ctrl, spi_ctrl);
138
139    /*
140     * Read data.
141     * Four 32 bits words at each iteration (128 bits = 16 bytes)
142     */
143    for (i = 0; i < count/16; i++)
144    {
145        iowrite32(&spi->rx_tx[0], 0xffffffff);
146        iowrite32(&spi->rx_tx[1], 0xffffffff);
147        iowrite32(&spi->rx_tx[2], 0xffffffff);
148        iowrite32(&spi->rx_tx[3], 0xffffffff);
149        iowrite32(&spi->ctrl,  spi_ctrl | SPI_CTRL_GO_BSY);
150
151        _spi_wait_if_busy(spi);
152
153        _physical_write( buffer, bswap32(ioread32(&spi->rx_tx[3])) ); 
154        buffer += 4;
155        _physical_write( buffer, bswap32(ioread32(&spi->rx_tx[2])) ); 
156        buffer += 4;
157        _physical_write( buffer, bswap32(ioread32(&spi->rx_tx[1])) ); 
158        buffer += 4;
159        _physical_write( buffer, bswap32(ioread32(&spi->rx_tx[0])) ); 
160        buffer += 4;
161    }
162
163//reset_ctrl:
164
165    /* Switch back to original word size */
166    iowrite32(&spi->ctrl, spi_ctrl0);
167
168    return 0;
169}
170
171void spi_ss_assert(struct spi_dev * spi, int index)
172{
173    unsigned int spi_ss = ioread32(&spi->ss);
174
175    iowrite32(&spi->ss, spi_ss | (1 << index));
176}
177
178void spi_ss_deassert(struct spi_dev * spi, int index)
179{
180    unsigned int spi_ss = ioread32(&spi->ss);
181
182    iowrite32(&spi->ss, spi_ss & ~(1 << index));
183}
184
185void _spi_init ( struct spi_dev * spi,
186                 int spi_freq        ,
187                 int sys_freq        ,
188                 int char_len        ,
189                 int tx_edge         ,
190                 int rx_edge         )
191{
192    unsigned int spi_ctrl = ioread32(&spi->ctrl);
193
194    if      ( tx_edge == 0 ) spi_ctrl |=  SPI_CTRL_TXN_EN;
195    else if ( tx_edge == 1 ) spi_ctrl &= ~SPI_CTRL_TXN_EN;
196    if      ( rx_edge == 0 ) spi_ctrl |=  SPI_CTRL_RXN_EN;
197    else if ( rx_edge == 1 ) spi_ctrl &= ~SPI_CTRL_RXN_EN;
198    if      ( char_len > 0 ) spi_ctrl  = (spi_ctrl & ~SPI_CTRL_CHAR_LEN_MASK) |
199                                         (char_len &  SPI_CTRL_CHAR_LEN_MASK);
200
201    iowrite32(&spi->ctrl, spi_ctrl);
202
203    if (spi_freq > 0 && sys_freq > 0)
204        iowrite32(&spi->divider, _spi_calc_divider_value(spi_freq, sys_freq));
205}
206
207/*
208 * vim: tabstop=4 : shiftwidth=4 : expandtab : softtabstop=4
209 */
Note: See TracBrowser for help on using the repository browser.