uboot/common/soft_spi.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
   4 *
   5 * Influenced by code from:
   6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 */
  26
  27#include <common.h>
  28#include <spi.h>
  29
  30#if defined(CONFIG_SOFT_SPI)
  31
  32/*-----------------------------------------------------------------------
  33 * Definitions
  34 */
  35
  36#ifdef DEBUG_SPI
  37#define PRINTD(fmt,args...)     printf (fmt ,##args)
  38#else
  39#define PRINTD(fmt,args...)
  40#endif
  41
  42
  43/*=====================================================================*/
  44/*                         Public Functions                            */
  45/*=====================================================================*/
  46
  47/*-----------------------------------------------------------------------
  48 * Initialization
  49 */
  50void spi_init (void)
  51{
  52#ifdef  SPI_INIT
  53        volatile immap_t *immr = (immap_t *)CFG_IMMR;
  54
  55        SPI_INIT;
  56#endif
  57}
  58
  59
  60/*-----------------------------------------------------------------------
  61 * SPI transfer
  62 *
  63 * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks
  64 * "bitlen" bits in the SPI MISO port.  That's just the way SPI works.
  65 *
  66 * The source of the outgoing bits is the "dout" parameter and the
  67 * destination of the input bits is the "din" parameter.  Note that "dout"
  68 * and "din" can point to the same memory location, in which case the
  69 * input data overwrites the output data (since both are buffered by
  70 * temporary variables, this is OK).
  71 *
  72 * If the chipsel() function is not NULL, it is called with a parameter
  73 * of '1' (chip select active) at the start of the transfer and again with
  74 * a parameter of '0' at the end of the transfer.
  75 *
  76 * If the chipsel() function _is_ NULL, it the responsibility of the
  77 * caller to make the appropriate chip select active before calling
  78 * spi_xfer() and making it inactive after spi_xfer() returns.
  79 */
  80int  spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din)
  81{
  82#ifdef CFG_IMMR
  83        volatile immap_t *immr = (immap_t *)CFG_IMMR;
  84#endif
  85        uchar tmpdin  = 0;
  86        uchar tmpdout = 0;
  87        int   j;
  88
  89        PRINTD("spi_xfer: chipsel %08X dout %08X din %08X bitlen %d\n",
  90                (int)chipsel, *(uint *)dout, *(uint *)din, bitlen);
  91
  92        if(chipsel != NULL) {
  93                (*chipsel)(1);  /* select the target chip */
  94        }
  95
  96        for(j = 0; j < bitlen; j++) {
  97                /*
  98                 * Check if it is time to work on a new byte.
  99                 */
 100                if((j % 8) == 0) {
 101                        tmpdout = *dout++;
 102                        if(j != 0) {
 103                                *din++ = tmpdin;
 104                        }
 105                        tmpdin  = 0;
 106                }
 107                SPI_SCL(0);
 108                SPI_SDA(tmpdout & 0x80);
 109                SPI_DELAY;
 110                SPI_SCL(1);
 111                SPI_DELAY;
 112                tmpdin  <<= 1;
 113                tmpdin   |= SPI_READ;
 114                tmpdout <<= 1;
 115        }
 116        /*
 117         * If the number of bits isn't a multiple of 8, shift the last
 118         * bits over to left-justify them.  Then store the last byte
 119         * read in.
 120         */
 121        if((bitlen % 8) != 0)
 122                tmpdin <<= 8 - (bitlen % 8);
 123        *din++ = tmpdin;
 124
 125        SPI_SCL(0);             /* SPI wants the clock left low for idle */
 126
 127        if(chipsel != NULL) {
 128                (*chipsel)(0);  /* deselect the target chip */
 129
 130        }
 131
 132        return(0);
 133}
 134
 135#endif  /* CONFIG_SOFT_SPI */
 136