source: trunk/softs/tsar_boot/io_drivers/spi.c @ 278

Last change on this file since 278 was 276, checked in by bouyer, 12 years ago

A boot loader to be stored in ROM of a TSAR platform.
Based on Cesar FUGUET's work.
Platform-specific files are in a subdirectory, e.g. platform_fpga_de2-115,
so the same code can be targetted to different platforms.
The platform is selected with the PLATFORM_DIR environnement variable.
The supported variant are soclib and fpga, the later being the default
and the former selected by defining the SOCLIB environnement variable.
The boot loader embeds a binary device tree describing the platform,
to be used by the loaded software.

File size: 2.9 KB
Line 
1/*
2 * \file    spi.c
3 * \data    31 August 2012
4 * \author  Cesar Fuguet <cesar.fuguet-tortolero@lip6.fr>
5 */
6#include <spi.h>
7
8#define in_reset __attribute__((section (".reset")))
9
10/**
11 * \param   spi :   Initialized pointer to the SPI controller
12 *
13 * \brief   Wait until the SPI controller has finished a transfer
14 *
15 * Wait until the GO_BUSY bit of the SPI controller be deasserted
16 */
17in_reset static void _spi_wait_if_busy(struct spi_dev * spi)
18{
19    volatile register int delay;
20
21    while(SPI_IS_BUSY(spi))
22    {
23        for (delay = 0; delay < 10000; delay++);
24    }
25}
26
27/**
28 * \param   spi : Initialized pointer to the SPI controller
29 *
30 * \return  void
31 *
32 * \brief   Init transfer of the tx registers to the selected slaves
33 */
34in_reset static void _spi_init_transfer(struct spi_dev * spi)
35{
36    unsigned int spi_ctrl = ioread32(&spi->ctrl);
37
38    iowrite32(&spi->ctrl, spi_ctrl | SPI_CTRL_GO_BSY);
39}
40
41/**
42 * \param   spi_freq    : Desired frequency for the generated clock from the SPI
43 *                        controller
44 * \param   sys_freq    : System clock frequency
45 *
46 * \brief   Calculated the value for the divider register in order to obtain the SPI
47 *          desired clock frequency
48 */
49in_reset static unsigned int _spi_calc_divider_value  (
50        unsigned int spi_freq   ,
51        unsigned int sys_freq   )
52{
53    return ((sys_freq / (spi_freq * 2)) - 1);
54}
55
56in_reset void spi_put_tx(struct spi_dev * spi, unsigned char byte, int index)
57{
58    _spi_wait_if_busy(spi);
59    {
60        iowrite8(&spi->rx_tx[index % 4], byte);
61        _spi_init_transfer(spi);
62
63        asm volatile("sync");
64    }
65    _spi_wait_if_busy(spi);
66}
67
68in_reset volatile unsigned char spi_get_rx(struct spi_dev * spi, int index)
69{
70    return ioread8(&spi->rx_tx[index % 4]);
71}
72
73in_reset void spi_ss_assert(struct spi_dev * spi, int index)
74{
75    unsigned int spi_ss = ioread32(&spi->ss);
76
77    iowrite32(&spi->ss, spi_ss | (1 << index));
78}
79
80in_reset void spi_ss_deassert(struct spi_dev * spi, int index)
81{
82    unsigned int spi_ss = ioread32(&spi->ss);
83
84    iowrite32(&spi->ss, spi_ss & ~(1 << index));
85}
86
87in_reset void spi_dev_config (
88        struct spi_dev * spi,
89        int spi_freq            ,
90        int sys_freq        ,
91        int char_len            ,
92        int tx_edge                     ,
93        int rx_edge                     )
94{
95    unsigned int spi_ctrl = ioread32(&spi->ctrl);
96
97    if      ( tx_edge == 0 ) spi_ctrl |=  SPI_CTRL_TXN_EN;
98    else if ( tx_edge == 1 ) spi_ctrl &= ~SPI_CTRL_TXN_EN;
99    if      ( rx_edge == 0 ) spi_ctrl |=  SPI_CTRL_RXN_EN;
100    else if ( rx_edge == 1 ) spi_ctrl &= ~SPI_CTRL_RXN_EN;
101    if      ( char_len > 0 ) spi_ctrl  = (spi_ctrl & ~SPI_CTRL_CHAR_LEN_MASK) |
102        (char_len &  SPI_CTRL_CHAR_LEN_MASK);
103
104    iowrite32(&spi->ctrl, spi_ctrl);
105
106    if (spi_freq > 0 && sys_freq > 0)
107        iowrite32(&spi->divider, _spi_calc_divider_value(spi_freq, sys_freq));
108
109}
110
111#undef in_reset
112
113/*
114 * vim: tabstop=4 : shiftwidth=4 : expandtab : softtabstop=4
115 */
Note: See TracBrowser for help on using the repository browser.