UBOOT自带的驱动最多一次一次向mpc8314 SPI控制器中写入32bit传送, 但一次发送16bit, 24bit MPC8314 SPI控制器有点问题;
索性改成每次都固定8bit的传送,测试通过;
void mpc8xxx_spi_init(void)
{
volatile spi8xxx_t *spi = (spi8xxx_t *)SPI_REG_BASE;
spi->mode = 0;
spi->mask = 0x00000000; /* Mask all SPI interrupts */
spi->com = 0; /* LST bit doesn't do anything, so disregard */
spi->event = 0xffffffff; /* Clear all SPI events */
spi->mode = SPI_MODE_CP_BEGIN_EDGECLK | SPI_MODE_CI_INACTIVEHIGH | SPI_MODE_LEN(7) | SPI_MODE_PM(0xf) | SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN;
}
/* 这个函数的重点修改是:每次最多传送8bit, 而不是原始的最多一次传送32bit */
int mpc8xxx_spi_xfer(struct spi_slave *slave, unsigned int bitlen, const unsigned char *dout,
unsigned char *din, unsigned long flags)
{
volatile spi8xxx_t *spi = (spi8xxx_t *)SPI_REG_BASE;
unsigned int tmpdout, tmpdin, event;
int numBlks = bitlen / 8 + (bitlen % 8 ? 1 : 0);
int tm, isRead = 0;
unsigned char charSize = 8;
// poll low CS
spi->event = 0xffffffff; /* Clear all SPI events */
/* handle data in 8-bit chunks */ /* 固定每次都按8bit传送; */
while (numBlks--) {
tmpdout = 0;
charSize = (bitlen >= 8 ? 8 : bitlen);
/* Shift data so it's msb-justified */
tmpdout = *(u8 *)dout;
if (bitlen < 8) {
if (bitlen <= 4)
spi->mode = (spi->mode & 0xff0fffff) |
(3 << 20);
else
spi->mode = (spi->mode & 0xff0fffff) |
((bitlen - 1) << 20);
} else {
spi->mode = (spi->mode & 0xff0fffff) | SPI_MODE_LEN(7);
/* Set up the next iteration if sending > 8 bits */
bitlen -= 8;
dout += 1;
}
spi->tx = tmpdout; /* Write the data out */
/*
* Wait for SPI transmit to get out
* or time out (1 second = 1000 ms)
* The NE event must be read and cleared first
*/
for (tm = 0, isRead = 0; tm < SPI_TIMEOUT; ++tm) {
event = spi->event;
if (event & SPI_EV_NE) {
tmpdin = spi->rx;
spi->event |= SPI_EV_NE;
isRead = 1;
*din = tmpdin & 0xff;
if (charSize == 8) {
din += 1;
}
}
/*
* Only bail when we've had both NE and NF events.
* This will cause timeouts on RO devices, so maybe
* in the future put an arbitrary delay after writing
* the device. Arbitrary delays suck, though...
*/
if (isRead && (event & SPI_EV_NF))
break;
}
if (tm >= SPI_TIMEOUT)
puts("*** spi_xfer: Time out during SPI transfer");
}
return 0;
}
文:董滨华/董兵华/dongbinghua