blob: 20835a6b11e98d91701a8f3a6c81c73a8d85e9a3 [file] [log] [blame]
/*
* (C) Copyright 2007
* Mindspeed Technologies, Inc. <www.mindspeed.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Revision 0.3 2007/04/28 Iurii.Golovach
*/
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_SPI) || defined(CONFIG_SPI)
#include <spi.h>
#include <asm/arch/bsp.h>
#include <asm/arch/spi.h>
spi_chipsel_type spi_chipsel[] = {
(spi_chipsel_type)1,
(spi_chipsel_type)2,
(spi_chipsel_type)4,
(spi_chipsel_type)8
};
int spi_chipsel_cnt = sizeof(spi_chipsel) / sizeof(spi_chipsel[0]);
void spi_hw_init(void)
{
volatile u32 delay_count;
/* enable native SPI (disabled by default) */
SoC_ioctrl_cfg(IOCTRL_SPI_BUS, 1);
/* wait 2 ms SPI to process the data. DON'T REMOVE THIS OTHERWISE SPI WILL NOT BE INITIALIZED */
delay_count = 4000;
while (delay_count--)
;
}
int spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din)
{
uchar j;
u32 tsmode;
if (bitlen < 1)
return 1;
/* checking the din and dout params */
if (!din && !dout)
return 2;
if (!chipsel)
return 3;
if (!din) {
/* transmit only */
tsmode = 0x1;
} else if (!dout) {
/* receive only */
tsmode = 0x2;
} else {
/* transmit & receive */
tsmode = 0x0;
}
/* disable SPI */
*(volatile u32 *) SPI_SSIENR = 0x0;
/* select the target chip */
*(volatile u32 *) SPI_SER = (volatile u32) *chipsel;
*(volatile u32 *) SPI_CTRLR0 = (((tsmode & 0x3) << 8) |
((CFG_SPI_CLOCK_POLARITY & 0x1) << 7) |
((CFG_SPI_CLOCK_PHASE & 0x1) << 6) |
((CFG_SPI_FRAMESIZE - 1) & 0xf));
/* set up the ssi_clk divider value */
*(volatile u32 *) SPI_BAUDR = (CFG_HZ_CLOCK / CFG_SPI_CLOCK_SPEED) & 0xFFFF;
/* disable SPI interrupts */
*(volatile u32 *) SPI_IMR = 0x0;
/* enable SPI */
*(volatile u32 *) SPI_SSIENR = 0x1;
switch (tsmode) {
case 0x1:
/* transmit only */
for (j = 0; j < bitlen / CFG_SPI_FRAMESIZE; j++) {
/* transmit fifo not full */
while(!((*(volatile u32 *) SPI_SR) & TFNF))
;
*(volatile u32 *) SPI_DR = *dout++;
}
/* waits while the data will be written (while TX FIFO isn't empty) */
while(!((*(volatile u32 *) SPI_SR) & TFE))
;
break;
case 0x2:
/* receive only */
/* writing one dummy data word into the transmit FIFO */
*(volatile u32 *)SPI_DR = 0x00;
for (j = 0; j < bitlen / CFG_SPI_FRAMESIZE; j++)
{
/* check that there is data in the fifo */
while(!((*(volatile u32 *) SPI_SR) & RFNE))
;
*din++ = *(volatile u32 *) SPI_DR;
}
break;
default:
/* transmit & receive */
for (j = 0; j < bitlen / CFG_SPI_FRAMESIZE; j++)
{
/* transmit fifo not full */
while(!((*(volatile u32 *) SPI_SR) & TFNF))
;
*(volatile u32 *) SPI_DR = *dout++;
/* check that there is data in the fifo */
while(!((*(volatile u32 *) SPI_SR) & RFNE))
;
*din++ = *(volatile u32 *) SPI_DR;
}
/* waits while the data will be written (while TX FIFO isn't empty) */
while(!((*(volatile u32 *) SPI_SR) & TFE))
;
break;
}
return 0;
}
#endif /* (CONFIG_COMMANDS & CFG_CMD_SPI) || defined(CONFIG_SPI) */