背景介绍:ICETEK OMAPL138开发板的厂商提供的kernel.sdk中,默认只初始化了1个spi控制器,并挂载1个spi外设及spi外设驱动。而我们当前的项目需要,2个spi控制器,并分别挂多个spi外设。那么,我们先尝试在现有spi1控制器上,再挂一个spi外设,本文旨在于此。(其实,关于增加spi0控制器的开发工作,由于项目决定使用TI的OMAPL138,而我查看了TI官网推荐的kernel.sdk中,默认已经初始化好了spi0控制器和spi1控制器,所以这一步,在我们项目中没做)
本文参考:
http://zch7811.blog.163.com/blog/static/1770522820135423251597/ 和
http://blog.sina.com.cn/s/blog_3fb7f7270102vbtx.html 基于
ICETEK OMAPL138开发板来添加spi。
操作步骤:
第一步,添加spi驱动。
通过如下操作,将内核自带的spidev驱动加载到内核中:
sudo make menuconfig ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
Device Drivers --->
[*] SPI support --->
<*> SPI controller driver for DaVinci SoC's
<*> User mode SPI device driver support
第二步,添加spi设备。
首先,由于spi的pin是和gpio复用的pin,所以需要添加spi的pin mux配置:(为什么只需要修改如下3个地方,请看我的另一篇关于pinmux的文章)
在kernel.sdk/arch/arm/mach-davinci/include/mach/mux.h的enum davinci_da850_index 中,增加DA850_SPI1_CS_1:
/* SPI1 function */
DA850_SPI1_CS_0,
DA850_SPI1_CS_1,
DA850_SPI1_CLK,
DA850_SPI1_SOMI,
DA850_SPI1_SIMO,
在kernel.sdk/arch/arm/mach-davinci/da850.c的static const struct mux_config da850_pins[]中,增加MUX_CFG(DA850, SPI1_CS_1, 5, 0, 15, 1, false):
/* SPI1 function */
MUX_CFG(DA850, SPI1_CS_0, 5, 4, 15, 1, false)
MUX_CFG(DA850, SPI1_CS_1, 5, 0, 15, 1, false)
MUX_CFG(DA850, SPI1_CLK, 5, 8, 15, 1, false)
MUX_CFG(DA850, SPI1_SOMI, 5, 16, 15, 1, false)
MUX_CFG(DA850, SPI1_SIMO, 5, 20, 15, 1, false)
在kernel.sdk/arch/arm/mach-davinci/da850.c的const short da850_spi1_pins[] __initdata中,增加DA850_SPI1_CS_1:
DA850_SPI1_CS_0, DA850_SPI1_CS_1, DA850_SPI1_CLK, DA850_SPI1_SOMI, DA850_SPI1_SIMO,
其次,添加spi设备:
增加一个名称为spidev的设备
static struct spi_board_info da850_spi_board_info[] = {
[0] = {
.modalias = "m25p80",
.platform_data = &spi_flash_data,
.mode = SPI_MODE_0,
.max_speed_hz = 30000000, /* max sample rate at 3V */
.bus_num = 1,
.chip_select = 0,
},
[1] = {
.modalias = "spidev",
.mode = SPI_MODE_3,
.max_speed_hz = 30000000, /* max sample rate at 3V */
.bus_num = 1,
.chip_select = 1,
},
};
一般情况下,通过如上2个步骤后,spi外设和spi外设驱动就会被挂载上去了,即:在/sys/bus/spi/devices/下多出个spi1.1;在/sys/bus/spi/drivers/下多出个spidev。并且,如果spi外设和spi外设驱动匹配成功,就会注册spi字符设备,即:在/dev/下多出个spidev1.1。然而,spi外设驱动的确挂载成功了,但是spi外设挂载失败了,也没有匹配成功。查看单板启动日志中有报错,接下来我们就一步步解决报错吧。
解决问题:
新增后,会报错:spi_davinci spi_davinci.1: cs1 >= max 1
通过一步步加打印调试,发现在:
int spi_add_device(struct spi_device *spi)
{
...
if (spi->chip_select >= spi->master->num_chipselect)
...
}
很明显,由于这里的master->num_chipselect,其能力被限制为1了。而当我们在da850_spi_board_info中增加一条后,这里spi->chip_select的取值依次为0,1,相应地需要把num_chipselect增加为2,那么num_chipselect在哪儿修改呢?
通过直接分析函数调用关系:由于spi_add_device()<-spi_new_device()<-scan_boardinfo()<-spi_register_master()<-spi_bitbang_start()<-davinci_spi_probe(),那么到此我们就找到了master->num_chipselect被赋值的地方:
static int davinci_spi_probe(struct platform_device *pdev)
{
...
master->num_chipselect = pdata->num_chipselect;
...
}
而在davinci_spi_probe()中的master->num_chipselect的值,就是通过传入的platform_device(即da850_spi1_device)参数赋值的。那么,很明显只需要修改da850_spi1_device中的num_chipselect的能力值即可。
接着,又会报错:spi_davinci spi_davinci.1: can't setup spi1.1, status -11
通过继续一步步加打印调试,或直接grep -rn can't setup,发现在:
int spi_add_device(struct spi_device *spi)
{
...
status = spi_setup(spi);
if (status < 0) {
dev_err(dev, "can't %s %s, status %d\n",
"setup", dev_name(&spi->dev), status);
goto done;
}
...
}
这里直接看不出来,需要继续往下分析调用关系。
通过加打印调试分析函数调用出错的原始出处:由于spi_add_device()->spi_setup()->davinci_spi_setup(),而函数出错就是在如下:
static int davinci_spi_setup(struct spi_device *spi)
{
...
if (use_dma && davinci_spi->dma_channels) {
davinci_spi_dma = &davinci_spi->dma_channels[spi->chip_select];
if ((davinci_spi_dma->dma_rx_channel == -1)
|| (davinci_spi_dma->dma_tx_channel == -1)) {
retval = davinci_spi_request_dma(spi);
if (retval < 0)
{
return retval;
}
}
}
...
}
感觉好像和use_dma有很大关系,进一步分析use_dma的调用关系,use_dma是个全局静态变量:
static unsigned use_dma;
而use_dma唯一被赋值的地方:
static int davinci_spi_probe(struct platform_device *pdev)
{
...
use_dma = pdata->use_dma;
...
}
而在davinci_spi_probe()中的use_dma的值,就是通过传入的platform_device(即da850_spi1_device)参数赋值的,这不就和如上第一个问题的修改点不谋而合了嘛!那么和第一个问题一样,我们修改da850_spi1_device中的use_dma的能力值为0试试。果然在/sys/bus/spi/devices/下多出个spi1.1,即是我们新增的spi外设,并且,在/dev/下多出个spidev1.1,即是匹配成功后新增的spi字符设备,那么表示成功了。至于为什么这里要修改dma,我怀疑一般的spi外设不需要配置这个东西,仅spi flash外设可配值。
至此,在/sys/bus/spi/devices/下多出个spi1.1;在/sys/bus/spi/drivers/下多出个spidev;在/dev/下多出个spidev1.1。
阅读(4502) | 评论(0) | 转发(0) |