spi控制器都是挂在platform总线上的,所以要等platform总线上的设备驱动加载spi控制器完成后才能加载spi设备。
1.spi控制器加载
由spi控制器驱动程序调用spi_register_master来完成spi控制器驱动加载
int spi_register_master(struct spi_master *master)
{
...status = of_spi_register_master(master); //片选gpio的解析,片选是在控制器配置的
...
if (master->transfer)
dev_info(dev, "master is unqueued, this is deprecated\n");
else {
status = spi_master_initialize_queue(master); //消息队列的初始化
if (status) {
device_del(&master->dev);
goto done;
}
}
/* add statistics */
spin_lock_init(&master->statistics.lock);mutex_lock(&board_lock);
list_add_tail(&master->list, &spi_master_list);
list_for_each_entry(bi, &board_list, list)
spi_match_master_to_boardinfo(master, &bi->board_info)//这里是通过spi_register_board_info调用,产生的spi device需要解析并添加到maste链表上
mutex_unlock(&board_lock);/* Register devices from the device tree and ACPI */
of_register_spi_devices(master); //spi device的添加
acpi_register_spi_devices(master); //acpi设备的添加,这里不关注
done:
return status;
}
2.片选的解析
以上是spi master,基本上芯片提供商都有自己的解决方案一般不需要我们改动。与我们相关的是spi device dtsi的配置
3.spi device的添加
static void of_register_spi_devices(struct spi_master *master)
{
struct spi_device *spi;
struct device_node *nc;if (!master->dev.of_node)
return;for_each_available_child_of_node(master->dev.of_node, nc) {
if (of_node_test_and_set_flag(nc, OF_POPULATED))
continue;
spi = of_register_spi_device(master, nc);
if (IS_ERR(spi))
dev_warn(&master->dev, "Failed to create SPI device for %s\n",
nc->full_name);
}
}of_register_spi_device(struct spi_master *master, struct device_node *nc)
{
struct spi_device *spi;
int rc;
u32 value;/* Alloc an spi_device */
spi = spi_alloc_device(master);
if (!spi) {
dev_err(&master->dev, "spi_device alloc error for %s\n",
nc->full_name);
rc = -ENOMEM;
goto err_out;
}/* Select device driver */从node中获取compatible属性,然后填充
rc = of_modalias_node(nc, spi->modalias,
sizeof(spi->modalias));
if (rc < 0) {
dev_err(&master->dev, "cannot find modalias for %s\n",
nc->full_name);
goto err_out;
}/* Device address */
rc = of_property_read_u32(nc, "reg", &value);
if (rc) {
dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
nc->full_name, rc);
goto err_out;
}
spi->chip_select = value;//这个reg是spi device必需配置项,且不能大于master设置的最大片选值。主要是设置片选的下标,因为片选数组是在master里面配置的
/* Mode (clock phase/polarity/etc.) */
if (of_find_property(nc, "spi-cpha", NULL))
spi->mode |= SPI_CPHA;
if (of_find_property(nc, "spi-cpol", NULL))
spi->mode |= SPI_CPOL;
if (of_find_property(nc, "spi-cs-high", NULL))
spi->mode |= SPI_CS_HIGH;
if (of_find_property(nc, "spi-3wire", NULL))
spi->mode |= SPI_3WIRE;
if (of_find_property(nc, "spi-lsb-first", NULL))
spi->mode |= SPI_LSB_FIRST;/* Device DUAL/QUAD mode */
if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) {
switch (value) {
case 1:
break;
case 2:
spi->mode |= SPI_TX_DUAL;
break;
case 4:
spi->mode |= SPI_TX_QUAD;
break;
default:
dev_warn(&master->dev,
"spi-tx-bus-width %d not supported\n",
value);
break;
}
}if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) {
switch (value) {
case 1:
break;
case 2:
spi->mode |= SPI_RX_DUAL;
break;
case 4:
spi->mode |= SPI_RX_QUAD;
break;
default:
dev_warn(&master->dev,
"spi-rx-bus-width %d not supported\n",
value);
break;
}
}//上面是spi mode配置,可以在dtsi里面直接配置,也可以在spi_driver匹配成功后,调用spi_setup重新设定mode
/* Device speed */
rc = of_property_read_u32(nc, "spi-max-frequency", &value);
if (rc) {
dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n",
nc->full_name, rc);
goto err_out;
}
spi->max_speed_hz = value;//spi最大速率,必需配置
/* Store a pointer to the node in the device structure */
of_node_get(nc);
spi->dev.of_node = nc;//主要是作一些检测,没有问题完成device添加。这里注意的是如果同相的控制器上片选配置已经存在链表上,那么这个spi device将会添加失败
rc = spi_add_device(spi);
if (rc) {
dev_err(&master->dev, "spi_device register error %s\n",
nc->full_name);
goto err_out;
}return spi;
err_out:
spi_dev_put(spi);
return ERR_PTR(rc);
}从上面大体可知,一个spi device dtsi有两个配置项必需存在
1.reg
2.spi-max-frequency
4.spi中断的解析
在驱动匹配成功后,probe加载时会解析中断。这里只需要按中断配置的方式来正常配置中断就好了. eg:
#interrupt-cells : Defines the width of cells used to represent interrupts. Typically this value is <2>,
which includes a 32-bit number that represents the interrupt number,
and a 32-bit number that represents the interrupt sense and level.
一般device我们用到的#interrupt-cells配置是2,表示有2个参数。一个是中断后,另一个是中断触发方式
#define IRQ_TYPE_NONE 0
#define IRQ_TYPE_EDGE_RISING 1
#define IRQ_TYPE_EDGE_FALLING 2
#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
#define IRQ_TYPE_LEVEL_HIGH 4
#define IRQ_TYPE_LEVEL_LOW 8