MT7688内核的SPI驱动位于:
build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7688/linux-3.18.45/drivers/spi/spi-mt7621.c
在用户态打开spi设置,测试transfer时发现驱动对数据长度有限制,阅读驱动代码发现半双工写入的限制为36bytes:
在mt7621_spi_transfer_half_duplex函数中,有如下判断:
if (WARN_ON(len + rlen > 36))
{
status = -EIO;
goto msg_done;
}
初步分析其原因:该SPI驱动主要是为了
配合MT7688的SPI Controller控制外挂的SPI FLASH而设计的。
通过阅读MT7688的datasheet并结合现有驱动代码,可知SPI控制器的数据缓存由SPI_OP_ADDR(10000B04)以及SPI_DIDO_0(10000B08)-SPI_DIDO_7(10000B24)共计9个32bit位宽(36bytes)的寄存器构成。
通过改造mt7621_spi_transfer_half_duplex函数->mt7621_spi_transfer_half_duplex_cs1,使其支持多字节读写:
static int mt7621_spi_transfer_one_message(struct spi_master *master,
struct spi_message *m)
{
struct spi_device *spi = m->spi;
int cs = spi->chip_select;
if(cs == 0)
{
return mt7621_spi_transfer_half_duplex(master, m);
}
else if(cs == 1)
{
return mt7621_spi_transfer_half_duplex_cs1(master, m);
}
return 0;
}
static int mt7621_spi_transfer_half_duplex_cs1(struct spi_master *master,
struct spi_message *m)
{
struct mt7621_spi *rs = spi_master_get_devdata(master);
struct spi_device *spi = m->spi;
unsigned int speed = spi->max_speed_hz;
struct spi_transfer *t = NULL;
int status = 0;
int i=0;
u8* tbuf;
u8 *rbuf;
u32 data[9];
u32 val=0;
u32 r_index=0;
u8 n_xfer=0;
int tmp =0 ;
u32 n_byte_to_write=0;
u32 n_byte_to_read=0;
u32 rw_left=0;
u32 tdata=0;
tbuf = (u8*)kbuf;
tmp = mt7621_spi_wait_till_ready(spi);
if(tmp != 0)
{
status = -EIO;
goto msg_done;
}
list_for_each_entry(t, &m->transfers, transfer_list)
{
const u8 *buf = t->tx_buf; // send buffer
int rlen = t->len; // length to read or write.
if (t->rx_buf)
{
n_byte_to_read += rlen;
rbuf = t->rx_buf;
}
if (!buf) // send buffer
continue;
//update speed
if (t->speed_hz < speed)
speed