source: trunk/softs/tsar_boot/src/spi.c @ 513

Last change on this file since 513 was 415, checked in by cfuguet, 12 years ago

Modifications in soft/tsar_boot:

  • Fixing indentation problems in spi.c code
  • Erasing useless print in boot_elf_loader.c
File size: 4.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.h>
7
8/**
9 * \param   x: input value
10 *
11 * \return  byte-swapped value
12 *
13 * \brief   byte-swap a 32bit word
14 */
15static unsigned int bswap32(unsigned int x)
16{
17  unsigned int y;
18  y =  (x & 0x000000ff) << 24;
19  y |= (x & 0x0000ff00) <<  8;
20  y |= (x & 0x00ff0000) >>  8;
21  y |= (x & 0xff000000) >> 24;
22  return y;
23}
24
25/**
26 * \param   spi :   Initialized pointer to the SPI controller
27 *
28 * \brief   Wait until the SPI controller has finished a transfer
29 *
30 * Wait until the GO_BUSY bit of the SPI controller be deasserted
31 */
32static void _spi_wait_if_busy(struct spi_dev * spi)
33{
34    register int delay;
35
36    while(SPI_IS_BUSY(spi))
37    {
38        for (delay = 0; delay < 100; delay++);
39    }
40}
41
42/**
43 * \param   spi : Initialized pointer to the SPI controller
44 *
45 * \return  void
46 *
47 * \brief   Init transfer of the tx registers to the selected slaves
48 */
49static void _spi_init_transfer(struct spi_dev * spi)
50{
51    unsigned int spi_ctrl = ioread32(&spi->ctrl);
52
53    iowrite32(&spi->ctrl, spi_ctrl | SPI_CTRL_GO_BSY);
54}
55
56/**
57 * \param   spi_freq    : Desired frequency for the generated clock from the SPI
58 *                        controller
59 * \param   sys_freq    : System clock frequency
60 *
61 * \brief   Calculated the value for the divider register in order to obtain the SPI
62 *          desired clock frequency
63 */
64static unsigned int _spi_calc_divider_value  (
65    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
86void spi_get_data(struct spi_dev * spi, void *buf, unsigned int count)
87{
88    unsigned int *data = buf;
89    unsigned char *data8;
90    unsigned int spi_ctrl0, spi_ctrl;
91    int i;
92
93    _spi_wait_if_busy(spi);
94
95    /* switch to 128 bits words */
96    spi_ctrl0 = ioread32(&spi->ctrl);
97    spi_ctrl = (spi_ctrl0 & ~SPI_CTRL_CHAR_LEN_MASK) | 128;
98    iowrite32(&spi->ctrl, spi_ctrl);
99
100    /* read data */
101    for (i = 0; i + 3 < count / 4; i += 4) {
102        iowrite32(&spi->rx_tx[0], 0xffffffff);
103        iowrite32(&spi->rx_tx[1], 0xffffffff);
104        iowrite32(&spi->rx_tx[2], 0xffffffff);
105        iowrite32(&spi->rx_tx[3], 0xffffffff);
106        iowrite32(&spi->ctrl,  spi_ctrl | SPI_CTRL_GO_BSY);
107
108        _spi_wait_if_busy(spi);
109       
110        *data = bswap32(ioread32(&spi->rx_tx[3]));
111        data++;
112        *data = bswap32(ioread32(&spi->rx_tx[2]));
113        data++;
114        *data = bswap32(ioread32(&spi->rx_tx[1]));
115        data++;
116        *data = bswap32(ioread32(&spi->rx_tx[0]));
117        data++;
118    }
119
120    /* switch back to original word size */
121    iowrite32(&spi->ctrl, spi_ctrl0);
122
123    /* read missing bits */
124    data8 = (void *)data;
125    i = i * 4;
126    for (; i < count; i++)
127    {
128        iowrite32(&spi->rx_tx[0], 0xffffffff);
129        iowrite32(&spi->ctrl,  spi_ctrl0 | SPI_CTRL_GO_BSY);
130   
131        _spi_wait_if_busy(spi);
132   
133        *data8 = spi_get_rx(spi, 0);
134        data8++;
135    }
136    return;
137}
138
139void spi_ss_assert(struct spi_dev * spi, int index)
140{
141    unsigned int spi_ss = ioread32(&spi->ss);
142
143    iowrite32(&spi->ss, spi_ss | (1 << index));
144}
145
146void spi_ss_deassert(struct spi_dev * spi, int index)
147{
148    unsigned int spi_ss = ioread32(&spi->ss);
149
150    iowrite32(&spi->ss, spi_ss & ~(1 << index));
151}
152
153void spi_dev_config (
154    struct spi_dev * spi,
155    int spi_freq        ,
156    int sys_freq        ,
157    int char_len        ,
158    int tx_edge         ,
159    int rx_edge         )
160{
161    unsigned int spi_ctrl = ioread32(&spi->ctrl);
162
163    if      ( tx_edge == 0 ) spi_ctrl |=  SPI_CTRL_TXN_EN;
164    else if ( tx_edge == 1 ) spi_ctrl &= ~SPI_CTRL_TXN_EN;
165    if      ( rx_edge == 0 ) spi_ctrl |=  SPI_CTRL_RXN_EN;
166    else if ( rx_edge == 1 ) spi_ctrl &= ~SPI_CTRL_RXN_EN;
167    if      ( char_len > 0 ) spi_ctrl  = (spi_ctrl & ~SPI_CTRL_CHAR_LEN_MASK) |
168                                         (char_len &  SPI_CTRL_CHAR_LEN_MASK);
169
170    iowrite32(&spi->ctrl, spi_ctrl);
171
172    if (spi_freq > 0 && sys_freq > 0)
173        iowrite32(&spi->divider, _spi_calc_divider_value(spi_freq, sys_freq));
174}
175
176/*
177 * vim: tabstop=4 : shiftwidth=4 : expandtab : softtabstop=4
178 */
Note: See TracBrowser for help on using the repository browser.