uboot/cpu/nios/spi.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2004, Li-Pro.Net <www.li-pro.net>
   3 * Stephan Linz <linz@li-pro.net>
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25#include <linux/ctype.h>
  26
  27#if defined(CONFIG_NIOS_SPI)
  28#include <nios-io.h>
  29#include <spi.h>
  30
  31#if !defined(CONFIG_SYS_NIOS_SPIBASE)
  32#error "*** CONFIG_SYS_NIOS_SPIBASE not defined ***"
  33#endif
  34
  35#if !defined(CONFIG_SYS_NIOS_SPIBITS)
  36#error "*** CONFIG_SYS_NIOS_SPIBITS not defined ***"
  37#endif
  38
  39#if (CONFIG_SYS_NIOS_SPIBITS != 8) && (CONFIG_SYS_NIOS_SPIBITS != 16)
  40#error "*** CONFIG_SYS_NIOS_SPIBITS should be either 8 or 16 ***"
  41#endif
  42
  43static nios_spi_t       *spi    = (nios_spi_t *)CONFIG_SYS_NIOS_SPIBASE;
  44
  45/* Warning:
  46 * You cannot enable DEBUG for early system initalization, i. e. when
  47 * this driver is used to read environment parameters like "baudrate"
  48 * from EEPROM which are used to initialize the serial port which is
  49 * needed to print the debug messages...
  50 */
  51#undef  DEBUG
  52
  53#ifdef  DEBUG
  54
  55#define DPRINT(a)       printf a;
  56/* -----------------------------------------------
  57 * Helper functions to peek into tx and rx buffers
  58 * ----------------------------------------------- */
  59static const char * const hex_digit = "0123456789ABCDEF";
  60
  61static char quickhex (int i)
  62{
  63        return hex_digit[i];
  64}
  65
  66static void memdump (const void *pv, int num)
  67{
  68        int i;
  69        const unsigned char *pc = (const unsigned char *) pv;
  70
  71        for (i = 0; i < num; i++)
  72                printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
  73        printf ("\t");
  74        for (i = 0; i < num; i++)
  75                printf ("%c", isprint (pc[i]) ? pc[i] : '.');
  76        printf ("\n");
  77}
  78#else   /* !DEBUG */
  79
  80#define DPRINT(a)
  81#define memdump(p,n)
  82
  83#endif  /* DEBUG */
  84
  85
  86struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
  87                unsigned int max_hz, unsigned int mode)
  88{
  89        struct spi_slave *slave;
  90
  91        if (!spi_cs_is_valid(bus, cs))
  92                return NULL;
  93
  94        slave = malloc(sizeof(struct spi_slave));
  95        if (!slave)
  96                return NULL;
  97
  98        slave->bus = bus;
  99        slave->cs = cs;
 100
 101        /* TODO: Add support for different modes and speeds */
 102
 103        return slave;
 104}
 105
 106void spi_free_slave(struct spi_slave *slave)
 107{
 108        free(slave);
 109}
 110
 111int spi_claim_bus(struct spi_slave *slave)
 112{
 113        return 0;
 114}
 115
 116void spi_release_bus(struct spi_slave *slave)
 117{
 118
 119}
 120
 121/*
 122 * SPI transfer:
 123 *
 124 * See include/spi.h and http://www.altera.com/literature/ds/ds_nios_spi.pdf
 125 * for more informations.
 126 */
 127int spi_xfer(struct spi_slave *slave, int bitlen, const void *dout,
 128                void *din, unsigned long flags)
 129{
 130        const u8 *txd = dout;
 131        u8 *rxd = din;
 132        int j;
 133
 134        DPRINT(("spi_xfer: slave %u:%u dout %08X din %08X bitlen %d\n",
 135                slave->bus, slave->cs, *(uint *)dout, *(uint *)din, bitlen));
 136
 137        memdump(dout, (bitlen + 7) / 8);
 138
 139        if (flags & SPI_XFER_BEGIN)
 140                spi_cs_activate(slave);
 141
 142        if (!(flags & SPI_XFER_END) || bitlen > CONFIG_SYS_NIOS_SPIBITS) {
 143                /* leave chip select active */
 144                spi->control |= NIOS_SPI_SSO;
 145        }
 146
 147        for (   j = 0;                          /* count each byte in */
 148                j < ((bitlen + 7) / 8);         /* dout[] and din[] */
 149
 150#if     (CONFIG_SYS_NIOS_SPIBITS == 8)
 151                j++) {
 152
 153                while ((spi->status & NIOS_SPI_TRDY) == 0)
 154                        ;
 155                spi->txdata = (unsigned)(txd[j]);
 156
 157                while ((spi->status & NIOS_SPI_RRDY) == 0)
 158                        ;
 159                rxd[j] = (unsigned char)(spi->rxdata & 0xff);
 160
 161#elif   (CONFIG_SYS_NIOS_SPIBITS == 16)
 162                j++, j++) {
 163
 164                while ((spi->status & NIOS_SPI_TRDY) == 0)
 165                        ;
 166                if ((j+1) < ((bitlen + 7) / 8))
 167                        spi->txdata = (unsigned)((txd[j] << 8) | txd[j+1]);
 168                else
 169                        spi->txdata = (unsigned)(txd[j] << 8);
 170
 171                while ((spi->status & NIOS_SPI_RRDY) == 0)
 172                        ;
 173                rxd[j] = (unsigned char)((spi->rxdata >> 8) & 0xff);
 174                if ((j+1) < ((bitlen + 7) / 8))
 175                        rxd[j+1] = (unsigned char)(spi->rxdata & 0xff);
 176
 177#else
 178#error "*** unsupported value of CONFIG_SYS_NIOS_SPIBITS ***"
 179#endif
 180
 181        }
 182
 183        if (bitlen > CONFIG_SYS_NIOS_SPIBITS && (flags & SPI_XFER_END)) {
 184                spi->control &= ~NIOS_SPI_SSO;
 185        }
 186
 187        if (flags & SPI_XFER_END)
 188                spi_cs_deactivate(slave);
 189
 190        memdump(din, (bitlen + 7) / 8);
 191
 192        return 0;
 193}
 194
 195#endif /* CONFIG_NIOS_SPI */
 196