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