背景介绍:本文参考:
http://blog.csdn.net/qq345260600/article/details/7851620 和
http://blog.chinaunix.net/uid-27717694-id-3774328.html 对ICETEK OMAPL138开发板自带的Linux内核SPI子系统的代码走读了一遍。我根据自身对SPI子系统的认识,对SPI代码划分为以下几个部分。
1 第一阶段 初始化
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,
},
};
static __init void da850_evm_init(void)
{
...
ret = da8xx_pinmux_setup(da850_spi1_pins);
if (ret)
pr_warning("da850_evm_init: spi1 mux setup failed: %d\n",
ret);
da850_init_spi1(BIT(0), da850_spi_board_info,
ARRAY_SIZE(da850_spi_board_info));
...
}
很明显,是先配置spi pinmux;再配置spi1。而pinmux的配置请参考我另一篇文章,这里我们研究da850_init_spi1:
static struct davinci_spi_platform_data da850_spi1_pdata = {
.version = SPI_VERSION_2,
.num_chipselect = 1,
.wdelay = 0,
.odd_parity = 0,
.parity_enable = 0,
.wait_enable = 0,
.timer_disable = 0,
.clk_internal = 1,
.cs_hold = 1,
.intr_level = 1,
.poll_mode = 1,
.use_dma = 1,
.c2tdelay = 8,
.t2cdelay = 8,
};
static struct resource da850_spi1_resources[] = {
[0] = {
.start = 0x01F0E000,
.end = 0x01F0E000 + 0xfff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_DA8XX_SPINT1,
.end = IRQ_DA8XX_SPINT1,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = EDMA_CTLR_CHAN(0, 18),
.end = EDMA_CTLR_CHAN(0, 18),
.flags = IORESOURCE_DMA,
},
[3] = {
.start = EDMA_CTLR_CHAN(0, 19),
.end = EDMA_CTLR_CHAN(0, 19),
.flags = IORESOURCE_DMA,
},
[4] = {
.start = 1,
.end = 1,
.flags = IORESOURCE_DMA,
},
};
static struct platform_device da850_spi1_device = {
.name = "spi_davinci",
.id = 1,
.resource = da850_spi1_resources,
.num_resources = ARRAY_SIZE(da850_spi1_resources),
.dev = {
.platform_data = &da850_spi1_pdata,
},
};
void __init da850_init_spi1(unsigned chipselect_mask,
struct spi_board_info *info, unsigned len)
{
//注册spi device的信息到board_list链表中,待spi master注册好后扫描board_list链表,再正真注册spi device
spi_register_board_info(info, len);
//注册spi1的platform_device
platform_device_register(&da850_spi1_device);
}
接下来,我们分开看spi_register_board_info()和platform_device_register()
1.1 第一.一阶段 注册spi device到board_list 重点关注spi_register_board_info()
/**
* spi_register_board_info - register SPI devices for a given board
* @info: array of chip descriptors
* @n: how many descriptors are provided
* Context: can sleep
*
* Board-specific early init code calls this (probably during arch_initcall)
* with segments of the SPI device table. Any device nodes are created later,
* after the relevant parent SPI controller (bus_num) is defined. We keep
* this table of devices forever, so that reloading a controller driver will
* not make Linux forget about these hard-wired devices.
*
* Other code can also call this, e.g. a particular add-on board might provide
* SPI devices through its expansion connector, so code initializing that board
* would naturally declare its SPI devices.
*
* The board info passed can safely be __initdata ... but be careful of
* any embedded pointers (platform_data, etc), they're copied as-is.
*/
int __init
spi_register_board_info(struct spi_board_info const *info, unsigned n)
{
struct boardinfo *bi;
printk(KERN_INFO "spi_board_info is %d\n", n);
bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
if (!bi)
return -ENOMEM;
bi->n_board_info = n;
memcpy(bi->board_info, info, n * sizeof *info);
mutex_lock(&board_lock);
list_add_tail(&bi->list, &board_list);//
【重点函数 1】挂载到全局链表board_list中,待spi控制器注册后,将会扫描board_list链表进行匹配,才正真注册spi device
mutex_unlock(&board_lock);
return 0;
}
1.2 第一.二阶段 注册platform_device 重点关注platform_device_register()
/**
* platform_device_register - add a platform-level device
* @pdev: platform device we're adding
*/
int platform_device_register(struct platform_device *pdev)
{
device_initialize(&pdev->dev);
return platform_device_add(pdev);
}
EXPORT_SYMBOL_GPL(platform_device_register);
如下仅将2个被调用函数列出,并不继续研究。
/**
* device_initialize - init device structure.
* @dev: device.
*
* This prepares the device for use by other layers by initializing
* its fields.
* It is the first half of device_register(), if called by
* that function, though it can also be called separately, so one
* may use @dev's fields. In particular, get_device()/put_device()
* may be used for reference counting of @dev after calling this
* function.
*
* NOTE: Use put_device() to give up your reference instead of freeing
* @dev directly once you have called this function.
*/
void device_initialize(struct device *dev)
{
dev->kobj.kset = devices_kset;
kobject_init(&dev->kobj, &device_ktype);
INIT_LIST_HEAD(&dev->dma_pools);
init_MUTEX(&dev->sem);
spin_lock_init(&dev->devres_lock);
INIT_LIST_HEAD(&dev->devres_head);
device_init_wakeup(dev, 0);
device_pm_init(dev);
set_dev_node(dev, -1);
}
EXPORT_SYMBOL_GPL(device_initialize);
/**
* platform_device_add - add a platform device to device hierarchy
* @pdev: platform device we're adding
*
* This is part 2 of platform_device_register(), though may be called
* separately _iff_ pdev was allocated by platform_device_alloc().
*/
int platform_device_add(struct platform_device *pdev)
{
int i, ret = 0;
if (!pdev)
return -EINVAL;
if (!pdev->dev.parent)
pdev->dev.parent = &platform_bus;
pdev->dev.bus = &platform_bus_type;
if (pdev->id != -1)
dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
else
dev_set_name(&pdev->dev, "%s", pdev->name);
for (i = 0; i < pdev->num_resources; i++) {
struct resource *p, *r = &pdev->resource[i];
if (r->name == NULL)
r->name = dev_name(&pdev->dev);
p = r->parent;
if (!p) {
if (resource_type(r) == IORESOURCE_MEM)
p = &iomem_resource;
else if (resource_type(r) == IORESOURCE_IO)
p = &ioport_resource;
}
if (p && insert_resource(p, r)) {
printk(KERN_ERR
"%s: failed to claim resource %d\n",
dev_name(&pdev->dev), i);
ret = -EBUSY;
goto failed;
}
}
pr_debug("Registering platform device '%s'. Parent at %s\n",
dev_name(&pdev->dev), dev_name(pdev->dev.parent));
ret = device_add(&pdev->dev);
if (ret == 0)
return ret;
failed:
while (--i >= 0) {
struct resource *r = &pdev->resource[i];
unsigned long type = resource_type(r);
if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
release_resource(r);
}
return ret;
}
EXPORT_SYMBOL_GPL(platform_device_add);
2 第二阶段 注册platform_driver 重点关注platform_driver_register()
static struct platform_driver davinci_spi_driver = {
.driver.name = "spi_davinci",
.remove = __exit_p(davinci_spi_remove),
.suspend = davinci_spi_suspend,
.resume = davinci_spi_resume,
};
static int __init davinci_spi_init(void)
{
return platform_driver_probe(&davinci_spi_driver, davinci_spi_probe);
}
module_init(davinci_spi_init);
那么就调用到“核心层”的函数接口,在/driver/base/platform.c中:
/**
* platform_driver_probe - register driver for non-hotpluggable device
* @drv: platform driver structure
* @probe: the driver probe routine, probably from an __init section
*
* Use this instead of platform_driver_register() when you know the device
* is not hotpluggable and has already been registered, and you want to
* remove its run-once probe() infrastructure from memory after the driver
* has bound to the device.
*
* One typical use for this would be with drivers for controllers integrated
* into system-on-chip processors, where the controller devices have been
* configured as part of board setup.
*
* Returns zero if the driver registered and bound to a device, else returns
* a negative error code and with the driver not registered.
*/
int __init_or_module platform_driver_probe(struct platform_driver *drv,
int (*probe)(struct platform_device *))
{
int retval, code;
/* make sure driver won't have bind/unbind attributes */
drv->driver.suppress_bind_attrs = true;
/* temporary section violation during probe() */
drv->probe = probe;
retval = code = platform_driver_register(drv);//其实看得出参数davinci_spi_probe仅仅是被注册到davinci_spi_driver->probe下,而真正要调用的是platform_driver_register(davinci_spi_driver),所以有些版本的内核中无davinci_spi_probe(),而是直接调用platform_driver_register()。
/*
* Fixup that section violation, being paranoid about code scanning
* the list of drivers in order to probe new devices. Check to see
* if the probe was successful, and make sure any forced probes of
* new devices fail.
*/
spin_lock(&platform_bus_type.p->klist_drivers.k_lock);
drv->probe = NULL;
if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
retval = -ENODEV;
drv->driver.probe = platform_drv_probe_fail;
spin_unlock(&platform_bus_type.p->klist_drivers.k_lock);
if (code != retval)
platform_driver_unregister(drv);
return retval;
}
EXPORT_SYMBOL_GPL(platform_driver_probe);
3 第三阶段 注册一个用于描述spi控制器的结构体spi_master和正真注册spi device 重点关注spi_register_master()
关于platform我们就不再深入研究了,我们只需要知道:当platform_device(即da850_spi1_device)和platform_drvier(即davinci_spi_driver)匹配成功后,会执行驱动中的×××_probe(即davinci_spi_probe)。那么,接着看davinci_spi_probe:
/*
* davinci_spi_probe - probe function for SPI Master Controller
* pdev: platform_device structure which contains plateform specific data
*/
static int davinci_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct davinci_spi *davinci_spi;
struct davinci_spi_platform_data *pdata;
struct resource *r, *mem;
resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
resource_size_t dma_tx_chan = SPI_NO_RESOURCE;
resource_size_t dma_eventq = SPI_NO_RESOURCE;
int i = 0, ret = 0;
pdata = pdev->dev.platform_data;
if (pdata == NULL) {
ret = -ENODEV;
goto err;
}
//分配一个spi控制器的spi_master结构,分配struct spi_master + struct davinci_spi大小的数据,把davinci_spi设为spi_master的私有数据
master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
if (master == NULL) {
ret = -ENOMEM;
goto err;
}
//把spi_master设置为platform_device结构中dev的私有数据
dev_set_drvdata(&pdev->dev, master);
//从master中获得私有数据davinci_spi
davinci_spi = spi_master_get_devdata(master);
if (davinci_spi == NULL) {
ret = -ENOENT;
goto free_master;
}
//从platform device的私有数据中获得spi控制器的寄存器物理地址资源
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) {
ret = -ENOENT;
goto free_master;
}
davinci_spi->pbase = r->start;//spi寄存器起始物理地址
davinci_spi->region_size = resource_size(r);
davinci_spi->pdata = pdata;
//为spi控制器的物理地址申请内存空间
mem = request_mem_region(r->start, davinci_spi->region_size,
pdev->name);
if (mem == NULL) {
ret = -EBUSY;
goto free_master;
}
//将spi控制器的寄存器物理地址映射到内核空间
davinci_spi->base = (struct davinci_spi_reg __iomem *)
ioremap(r->start, davinci_spi->region_size);
if (davinci_spi->base == NULL) {
ret = -ENOMEM;
goto release_region;
}
//从platform device的私有数据中获得spi控制器的中断号
davinci_spi->irq = platform_get_irq(pdev, 0);
if (davinci_spi->irq <= 0) {
ret = -EINVAL;
goto unmap_io;
}
//申请中断号
ret = request_irq(davinci_spi->irq, davinci_spi_irq, IRQF_DISABLED,
dev_name(&pdev->dev), davinci_spi);
if (ret)
goto unmap_io;
/* Allocate tmp_buf for tx_buf */
davinci_spi->tmp_buf = kzalloc(SPI_BUFSIZ, GFP_KERNEL);
if (davinci_spi->tmp_buf == NULL) {
ret = -ENOMEM;
goto irq_free;
}
//spi master计数加1
davinci_spi->bitbang.master = spi_master_get(master);
if (davinci_spi->bitbang.master == NULL) {
ret = -ENODEV;
goto free_tmp_buf;
}
//获得spi时钟
davinci_spi->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(davinci_spi->clk)) {
ret = -ENODEV;
goto put_master;
}
clk_enable(davinci_spi->clk);
master->bus_num = pdev->id;//spi控制器所在的spi总线号
master->num_chipselect = pdata->num_chipselect;//spi控制器的片选数量
master->setup = davinci_spi_setup;//spi控制器的setup函数
master->cleanup = davinci_spi_cleanup;
//spi_bitbang专门负责数据的传输
davinci_spi->bitbang.chipselect = davinci_spi_chipselect;//片选选择函数
davinci_spi->bitbang.setup_transfer = davinci_spi_setup_transfer;//建立传输的函数
davinci_spi->version = pdata->version;//版本号SPI_VERSION_2
use_dma = pdata->use_dma;
//设置一些标志位
davinci_spi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP;
if (davinci_spi->version == SPI_VERSION_2)
davinci_spi->bitbang.flags |= SPI_READY;
//DMA操作的一些设置
if (use_dma) {
r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (r)
dma_rx_chan = r->start;
r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (r)
dma_tx_chan = r->start;
r = platform_get_resource(pdev, IORESOURCE_DMA, 2);
if (r)
dma_eventq = r->start;
}
if (!use_dma ||
dma_rx_chan == SPI_NO_RESOURCE ||
dma_tx_chan == SPI_NO_RESOURCE ||
dma_eventq == SPI_NO_RESOURCE) {
davinci_spi->bitbang.txrx_bufs = davinci_spi_bufs_pio;
use_dma = 0;
} else {
davinci_spi->bitbang.txrx_bufs = davinci_spi_bufs_dma;
davinci_spi->dma_channels = kzalloc(master->num_chipselect
* sizeof(struct davinci_spi_dma), GFP_KERNEL);
if (davinci_spi->dma_channels == NULL) {
ret = -ENOMEM;
goto free_clk;
}
for (i = 0; i < master->num_chipselect; i++) {
davinci_spi->dma_channels[i].dma_rx_channel = -1;
davinci_spi->dma_channels[i].dma_rx_sync_dev =
dma_rx_chan;
davinci_spi->dma_channels[i].dma_tx_channel = -1;
davinci_spi->dma_channels[i].dma_tx_sync_dev =
dma_tx_chan;
davinci_spi->dma_channels[i].eventq = dma_eventq;
}
dev_info(&pdev->dev, "DaVinci SPI driver in EDMA mode\n"
"Using RX channel = %d , TX channel = %d and "
"event queue = %d", dma_rx_chan, dma_tx_chan,
dma_eventq);
}
//设置spi的读写函数
davinci_spi->get_rx = davinci_spi_rx_buf_u8;
davinci_spi->get_tx = davinci_spi_tx_buf_u8;
init_completion(&davinci_spi->done);
ret = davinci_spi_cpufreq_register(davinci_spi);
if (ret) {
pr_info("davinci SPI contorller driver failed to register "
"cpufreq\n");
goto free_dma;
}
/* Reset In/OUT SPI module */
iowrite32(0, davinci_spi->base + SPIGCR0);
udelay(100);
iowrite32(1, davinci_spi->base + SPIGCR0);
/* Clock internal */
if (davinci_spi->pdata->clk_internal)
set_io_bits(davinci_spi->base + SPIGCR1,
SPIGCR1_CLKMOD_MASK);
else
clear_io_bits(davinci_spi->base + SPIGCR1,
SPIGCR1_CLKMOD_MASK);
/* master mode default */
set_io_bits(davinci_spi->base + SPIGCR1, SPIGCR1_MASTER_MASK);
if (davinci_spi->pdata->intr_level)
iowrite32(SPI_INTLVL_1, davinci_spi->base + SPILVL);
else
iowrite32(SPI_INTLVL_0, davinci_spi->base + SPILVL);
//设置bitbang传输
ret = spi_bitbang_start(&davinci_spi->bitbang);
if (ret)
goto unregister_cpufreq;
dev_info(&pdev->dev, "Controller at 0x%p \n", davinci_spi->base);
if (!pdata->poll_mode)
dev_info(&pdev->dev, "Operating in interrupt mode"
" using IRQ %d\n", davinci_spi->irq);
return ret;
unregister_cpufreq:
davinci_spi_cpufreq_deregister(davinci_spi);
free_dma:
kfree(davinci_spi->dma_channels);
free_clk:
clk_disable(davinci_spi->clk);
clk_put(davinci_spi->clk);
put_master:
spi_master_put(master);
free_tmp_buf:
kfree(davinci_spi->tmp_buf);
irq_free:
free_irq(davinci_spi->irq, davinci_spi);
unmap_io:
iounmap(davinci_spi->base);
release_region:
release_mem_region(davinci_spi->pbase, davinci_spi->region_size);
free_master:
kfree(master);
err:
return ret;
}
此probe函数中数据结构和代码的设计都是按照驱动框架的要求来实现的,主要包括spi controller memory的映射,IRQ的注册,controller的reset和对register进行初始化赋值。以及,调用spi_alloc_master分配一个用于描述spi controller的spi_master,并对spi_master进行赋值等。最后,它将调用spi_bitbang_start()来创建一个work queue,由此SPI设备驱动可以向这个工作队列注册transfer方法。
这里,我们接着看spi_bitbang_start:
/**
* spi_bitbang_start - start up a polled/bitbanging SPI master driver
* @bitbang: driver handle
*
* Caller should have zero-initialized all parts of the structure, and then
* provided callbacks for chip selection and I/O loops. If the master has
* a transfer method, its final step should call spi_bitbang_transfer; or,
* that's the default if the transfer routine is not initialized. It should
* also set up the bus number and number of chipselects.
*
* For i/o loops, provide callbacks either per-word (for bitbanging, or for
* hardware that basically exposes a shift register) or per-spi_transfer
* (which takes better advantage of hardware like fifos or DMA engines).
*
* Drivers using per-word I/O loops should use (or call) spi_bitbang_setup,
* spi_bitbang_cleanup and spi_bitbang_setup_transfer to handle those spi
* master methods. Those methods are the defaults if the bitbang->txrx_bufs
* routine isn't initialized.
*
* This routine registers the spi_master, which will process requests in a
* dedicated task, keeping IRQs unblocked most of the time. To stop
* processing those requests, call spi_bitbang_stop().
*/
int spi_bitbang_start(struct spi_bitbang *bitbang)
{
int status;
if (!bitbang->master || !bitbang->chipselect)
return -EINVAL;
INIT_WORK(&bitbang->work, bitbang_work);
spin_lock_init(&bitbang->lock);
INIT_LIST_HEAD(&bitbang->queue);
if (!bitbang->master->mode_bits)
bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
if (!bitbang->master->transfer)
bitbang->master->transfer = spi_bitbang_transfer;
if (!bitbang->txrx_bufs) {
bitbang->use_dma = 0;
bitbang->txrx_bufs = spi_bitbang_bufs;
if (!bitbang->master->setup) {
if (!bitbang->setup_transfer)
bitbang->setup_transfer =
spi_bitbang_setup_transfer;
bitbang->master->setup = spi_bitbang_setup;
bitbang->master->cleanup = spi_bitbang_cleanup;
}
} else if (!bitbang->master->setup)
return -EINVAL;
/* this task is the only thing to touch the SPI bits */
bitbang->busy = 0;
bitbang->workqueue = create_singlethread_workqueue(
dev_name(bitbang->master->dev.parent));
if (bitbang->workqueue == NULL) {
status = -EBUSY;
goto err1;
}
/* driver may get busy before register() returns, especially
* if someone registered boardinfo for devices
*/
//注册spi控制器
status = spi_register_master(bitbang->master);
if (status < 0)
goto err2;
return status;
err2:
destroy_workqueue(bitbang->workqueue);
err1:
return status;
}
EXPORT_SYMBOL_GPL(spi_bitbang_start);
我们下面看spi_register_master:
/**
* spi_register_master - register SPI master controller
* @master: initialized master, originally from spi_alloc_master()
* Context: can sleep
*
* SPI master controllers connect to their drivers using some non-SPI bus,
* such as the platform bus. The final stage of probe() in that code
* includes calling spi_register_master() to hook up to this SPI bus glue.
*
* SPI controllers use board specific (often SOC specific) bus numbers,
* and board-specific addressing for SPI devices combines those numbers
* with chip select numbers. Since SPI does not directly support dynamic
* device identification, boards need configuration tables telling which
* chip is at which address.
*
* This must be called from context that can sleep. It returns zero on
* success, else a negative error code (dropping the master's refcount).
* After a successful return, the caller is responsible for calling
* spi_unregister_master().
*/
int spi_register_master(struct spi_master *master)
{
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
struct device *dev = master->dev.parent;
int status = -ENODEV;
int dynamic = 0;
if (!dev)
return -ENODEV;
/* even if it's just one always-selected device, there must
* be at least one chipselect
*/
if (master->num_chipselect == 0)
return -EINVAL;
/* convention: dynamically assigned bus IDs count down from the max */
if (master->bus_num < 0) {
/* FIXME switch to an IDR based scheme, something like
* I2C now uses, so we can't run out of "dynamic" IDs
*/
master->bus_num = atomic_dec_return(&dyn_bus_id);
dynamic = 1;
}
/* register the device, then userspace will see it.
* registration fails if the bus ID is in use.
*/
//设置spi控制器的名称,即在sysfs文件系统中显示的名称
dev_set_name(&master->dev, "spi%u", master->bus_num);
//设备添加到内核,会在sysfs文件系统下创建属性文件,这也是sys/class/spi_master下产生spi0,spi1的原因
status = device_add(&master->dev);
if (status < 0)
goto done;
dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
dynamic ? " (dynamic)" : "");
/* populate children from any spi device tables */
//搜寻总线上的spi device并注册到内核
scan_boardinfo(master);
status = 0;
done:
return status;
}
EXPORT_SYMBOL_GPL(spi_register_master);
此函数主要是注册spi master和搜寻spi device并注册,接着我们看scan_boardinfo:
/* FIXME someone should add support for a __setup("spi", ...) that
* creates board info from kernel command lines
*/
static void scan_boardinfo(struct spi_master *master)
{
struct boardinfo *bi;
mutex_lock(&board_lock);
//
【重点函数 2】遍历board_list中的spi_board_info,如果设备的总线号与控制器的总线好相等,则创建新spi device
//此board_list就是上面list_add_tail(&bi->list, &board_list);中生成的board_list。
list_for_each_entry(bi, &board_list, list) {
struct spi_board_info *chip = bi->board_info;
unsigned n;
for (n = bi->n_board_info; n > 0; n--, chip++) {
//检查在同一个spi总线上
if (chip->bus_num != master->bus_num)
continue;
/* NOTE: this relies on spi_new_device to
* issue diagnostics when given bogus inputs
*/
//将spi master和spi device联系起来
(void) spi_new_device(master, chip);
}
}
mutex_unlock(&board_lock);
}
这里根据board_list搜寻spi device,我们接着看将spi控制器和spi外设联系起来的实现,spi_new_device:
/**
* spi_new_device - instantiate one new SPI device
* @master: Controller to which device is connected
* @chip: Describes the SPI device
* Context: can sleep
*
* On typical mainboards, this is purely internal; and it's not needed
* after board init creates the hard-wired devices. Some development
* platforms may not be able to use spi_register_board_info though, and
* this is exported so that for example a USB or parport based adapter
* driver could add devices (which it would learn about out-of-band).
*
* Returns the new device, or NULL.
*/
struct spi_device *spi_new_device(struct spi_master *master,
struct spi_board_info *chip)
{
struct spi_device *proxy;
int status;
/* NOTE: caller did any chip->bus_num checks necessary.
*
* Also, unless we change the return value convention to use
* error-or-pointer (not NULL-or-pointer), troubleshootability
* suggests syslogged diagnostics are best here (ugh).
*/
//申请1个spi device,并将master赋值给spi device,这样可以通过spi device访问到master
proxy = spi_alloc_device(master);
if (!proxy)
return NULL;
WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
proxy->chip_select = chip->chip_select;
proxy->max_speed_hz = chip->max_speed_hz;
proxy->mode = chip->mode;
proxy->irq = chip->irq;
strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
proxy->dev.platform_data = (void *) chip->platform_data;
proxy->controller_data = chip->controller_data;
proxy->controller_state = NULL;
//添加spi device
status = spi_add_device(proxy);
if (status < 0) {
spi_dev_put(proxy);
return NULL;
}
return proxy;
}
EXPORT_SYMBOL_GPL(spi_new_device);
接着看添加spi外设,spi_add_device:
/**
* spi_add_device - Add spi_device allocated with spi_alloc_device
* @spi: spi_device to register
*
* Companion function to spi_alloc_device. Devices allocated with
* spi_alloc_device can be added onto the spi bus with this function.
*
* Returns 0 on success; negative errno on failure
*/
int spi_add_device(struct spi_device *spi)
{
static DEFINE_MUTEX(spi_add_lock);
struct device *dev = spi->master->dev.parent;
int status;
//检查spi device的片选号不能超过spi控制器的片选数量
/* Chipselects are numbered 0..max; validate. */
if (spi->chip_select >= spi->master->num_chipselect) {
dev_err(dev, "cs%d >= max %d\n",
spi->chip_select,
spi->master->num_chipselect);
return -EINVAL;
}
//设置spi device在Linux设备驱动模型中的name,如spi0.0
/* Set the bus ID string */
dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev),
spi->chip_select);
/* We need to make sure there's no other device with this
* chipselect **BEFORE** we call setup(), else we'll trash
* its configuration. Lock against concurrent add() calls.
*/
mutex_lock(&spi_add_lock);
//检查总线上没有重名的spi device
if (bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev))
!= NULL) {
dev_err(dev, "chipselect %d already in use\n",
spi->chip_select);
status = -EBUSY;
goto done;
}
//设置spi控制器
/* Drivers may modify this initial i/o setup, but will
* normally rely on the device being setup. Devices
* using SPI_CS_HIGH can't coexist well otherwise...
*/
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 device添加到内核,在sysfs文件系统下创建相应的属性文件(设备文件dev文件不会在这里创建,下边注册spi driver时会创建dev文件)
/* Device may be bound to an active driver when this returns */
status = device_add(&spi->dev);
if (status < 0)
dev_err(dev, "can't %s %s, status %d\n",
"add", dev_name(&spi->dev), status);
else
dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
done:
mutex_unlock(&spi_add_lock);
return status;
}
EXPORT_SYMBOL_GPL(spi_add_device);
我们接着看spi_setup:
/**
* spi_setup - setup SPI mode and clock rate
* @spi: the device whose settings are being modified
* Context: can sleep, and no requests are queued to the device
*
* SPI protocol drivers may need to update the transfer mode if the
* device doesn't work with its default. They may likewise need
* to update clock rates or word sizes from initial values. This function
* changes those settings, and must be called from a context that can sleep.
* Except for SPI_CS_HIGH, which takes effect immediately, the changes take
* effect the next time the device is selected and data is transferred to
* or from it. When this function returns, the spi device is deselected.
*
* Note that this call will fail if the protocol driver specifies an option
* that the underlying controller or its driver does not support. For
* example, not all hardware supports wire transfers using nine bit words,
* LSB-first wire encoding, or active-high chipselects.
*/
int spi_setup(struct spi_device *spi)
{
unsigned bad_bits;
int status;
/* help drivers fail *cleanly* when they need options
* that aren't supported with their current master
*/
bad_bits = spi->mode & ~spi->master->mode_bits;
if (bad_bits) {
dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
bad_bits);
return -EINVAL;
}
if (!spi->bits_per_word)
spi->bits_per_word = 8;
status = spi->master->setup(spi);
dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s"
"%u bits/w, %u Hz max --> %d\n",
(int) (spi->mode & (SPI_CPOL | SPI_CPHA)),
(spi->mode & SPI_CS_HIGH) ? "cs_high, " : "",
(spi->mode & SPI_LSB_FIRST) ? "lsb, " : "",
(spi->mode & SPI_3WIRE) ? "3wire, " : "",
(spi->mode & SPI_LOOP) ? "loopback, " : "",
spi->bits_per_word, spi->max_speed_hz,
status);
return status;
}
EXPORT_SYMBOL_GPL(spi_setup);
spi->master->setup()是个钩子函数,其在上面的davinci_spi_probe()中被赋值,那么真正调用的是davinci_spi_setup():
/*
* davinci_spi_setup - This functions will set default transfer method
* @spi: spi device on which data transfer to be done
*
* This functions sets the default transfer method.
*/
static int davinci_spi_setup(struct spi_device *spi)
{
int retval;
struct davinci_spi *davinci_spi;
struct davinci_spi_dma *davinci_spi_dma;
struct device *sdev;
//从spi master的私有数据中取出davinci_spi
davinci_spi = spi_master_get_devdata(spi->master);
sdev = davinci_spi->bitbang.master->dev.parent;
//设置spi发送速度
/* if bits per word length is zero then set it default 8 */
if (!spi->bits_per_word)
spi->bits_per_word = 8;
davinci_spi->slave[spi->chip_select].cmd_to_write = 0;
//设置spi dma
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;
}
}
}
/*
* SPI in DaVinci and DA8xx operate between
* 600 KHz and 50 MHz
*/
if (spi->max_speed_hz < 600000 || spi->max_speed_hz > 50000000) {
dev_dbg(sdev, "Operating frequency is not in acceptable "
"range\n");
return -EINVAL;
}
//设置spi FMT寄存器
/*
* Set up SPIFMTn register, unique to this chipselect.
*
* NOTE: we could do all of these with one write. Also, some
* of the "version 2" features are found in chips that don't
* support all of them...
*/
if (spi->mode & SPI_LSB_FIRST)
set_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK,
spi->chip_select);
else
clear_fmt_bits(davinci_spi->base, SPIFMT_SHIFTDIR_MASK,
spi->chip_select);
if (spi->mode & SPI_CPOL)
set_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK,
spi->chip_select);
else
clear_fmt_bits(davinci_spi->base, SPIFMT_POLARITY_MASK,
spi->chip_select);
if (!(spi->mode & SPI_CPHA))
set_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK,
spi->chip_select);
else
clear_fmt_bits(davinci_spi->base, SPIFMT_PHASE_MASK,
spi->chip_select);
//设置spi控制器和片选拐角
/*
* Version 1 hardware supports two basic SPI modes:
* - Standard SPI mode uses 4 pins, with chipselect
* - 3 pin SPI is a 4 pin variant without CS (SPI_NO_CS)
* (distinct from SPI_3WIRE, with just one data wire;
* or similar variants without MOSI or without MISO)
*
* Version 2 hardware supports an optional handshaking signal,
* so it can support two more modes:
* - 5 pin SPI variant is standard SPI plus SPI_READY
* - 4 pin with enable is (SPI_READY | SPI_NO_CS)
*/
if (davinci_spi->version == SPI_VERSION_2) {
clear_fmt_bits(davinci_spi->base, SPIFMT_WDELAY_MASK,
spi->chip_select);
set_fmt_bits(davinci_spi->base,
(davinci_spi->pdata->wdelay
<< SPIFMT_WDELAY_SHIFT)
& SPIFMT_WDELAY_MASK,
spi->chip_select);
if (davinci_spi->pdata->odd_parity)
set_fmt_bits(davinci_spi->base,
SPIFMT_ODD_PARITY_MASK,
spi->chip_select);
else
clear_fmt_bits(davinci_spi->base,
SPIFMT_ODD_PARITY_MASK,
spi->chip_select);
if (davinci_spi->pdata->parity_enable)
set_fmt_bits(davinci_spi->base,
SPIFMT_PARITYENA_MASK,
spi->chip_select);
else
clear_fmt_bits(davinci_spi->base,
SPIFMT_PARITYENA_MASK,
spi->chip_select);
if (davinci_spi->pdata->wait_enable)
set_fmt_bits(davinci_spi->base,
SPIFMT_WAITENA_MASK,
spi->chip_select);
else
clear_fmt_bits(davinci_spi->base,
SPIFMT_WAITENA_MASK,
spi->chip_select);
if (davinci_spi->pdata->timer_disable)
set_fmt_bits(davinci_spi->base,
SPIFMT_DISTIMER_MASK,
spi->chip_select);
else
clear_fmt_bits(davinci_spi->base,
SPIFMT_DISTIMER_MASK,
spi->chip_select);
}
//设置spi传输模式
retval = davinci_spi_setup_transfer(spi, NULL);
return retval;
}
这里就是配置spi控制器的寄存器了,可以对照到omapl138的芯片手册中spi register配置章节。
4 第四阶段 注册spi driver 重点关注spi_register_driver()
这里我们以spidev驱动为例继续分析spi driver。/driver/spi/spidev.c是linux内核提供的一个spi通用驱动。
static struct spi_driver spidev_spi_driver = {
.driver = {
.name = "spidev",
.owner = THIS_MODULE,
},
.probe = spidev_probe,
.remove = __devexit_p(spidev_remove),
/* NOTE: suspend/resume methods are not necessary here.
* We don't do anything except pass the requests to/from
* the underlying controller. The refrigerator handles
* most issues; the controller driver handles the rest.
*/
};
static int __init spidev_init(void)
{
int status;
/* Claim our 256 reserved device numbers. Then register a class
* that will key udev/mdev to add/remove /dev nodes. Last, register
* the driver which manages those device numbers.
*/
BUILD_BUG_ON(N_SPI_MINORS > 256);
//注册spi字符设备的操作方法
status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);
if (status < 0)
return status;
spidev_class = class_create(THIS_MODULE, "spidev");
if (IS_ERR(spidev_class)) {
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
return PTR_ERR(spidev_class);
}
//注册spi driver
status = spi_register_driver(&spidev_spi_driver);
if (status < 0) {
class_destroy(spidev_class);
unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
}
return status;
}
module_init(spidev_init);
接着我们看spi_register_driver:
/**
* spi_register_driver - register a SPI driver
* @sdrv: the driver to register
* Context: can sleep
*/
int spi_register_driver(struct spi_driver *sdrv)
{
sdrv->driver.bus = &spi_bus_type;
if (sdrv->probe)
sdrv->driver.probe = spi_drv_probe;
if (sdrv->remove)
sdrv->driver.remove = spi_drv_remove;
if (sdrv->shutdown)
sdrv->driver.shutdown = spi_drv_shutdown;
return driver_register(&sdrv->driver);
}
EXPORT_SYMBOL_GPL(spi_register_driver);
到这里,我不再向下深入研究spi外设驱动在内核的调用流程,但需要知道当spi device和spi driver匹配成功后,会调用spidev_probe(),此函数会注册spi外设的字符设备。如下,仅列出spidev_probe():
/*-------------------------------------------------------------------------*/
/* The main reason to have this class is to
make mdev/udev create the
*
/dev/spidevB.C character device nodes exposing our userspace API.
* It
also simplifies memory management.
*/
static struct class *spidev_class;
/*-------------------------------------------------------------------------*/
static int __devinit spidev_probe(struct
spi_device *spi)
{
struct
spidev_data *spidev;
int status;
unsigned
long minor;
/*
Allocate driver data */
spidev
= kzalloc(sizeof(*spidev), GFP_KERNEL);
if
(!spidev)
return
-ENOMEM;
/*
Initialize the driver data */
spidev->spi
= spi;
spin_lock_init(&spidev->spi_lock);
mutex_init(&spidev->buf_lock);
INIT_LIST_HEAD(&spidev->device_entry);
/*
If we can allocate a minor number, hook up this device.
* Reusing minors is fine so long as udev or
mdev is working.
*/
mutex_lock(&device_list_lock);
minor
= find_first_zero_bit(minors, N_SPI_MINORS);
if
(minor < N_SPI_MINORS) {
struct
device *dev;
spidev->devt
= MKDEV(SPIDEV_MAJOR, minor);
dev
= device_create(spidev_class, &spi->dev, spidev->devt,
spidev, "spidev%d.%d",
spi->master->bus_num,
spi->chip_select);
status
= IS_ERR(dev) ? PTR_ERR(dev) : 0;
}
else {
dev_dbg(&spi->dev,
"no minor number available!\n");
status
= -ENODEV;
}
if
(status == 0) {
set_bit(minor,
minors);
list_add(&spidev->device_entry,
&device_list);
}
mutex_unlock(&device_list_lock);
if
(status == 0)
spi_set_drvdata(spi,
spidev);
else
kfree(spidev);
return
status;
}
另外,spidev_init()函数中注册了标准的read/write/ioctl/open/release函数接口,以便在用户空间的应用程序对spi外设进行“读”“写”“设置”(设置是通过调用ioctl(),调到spi_setup(),实现重新设置spi device的默认传输方式)操作:
static const struct file_operations
spidev_fops = {
.owner
= THIS_MODULE,
/*
REVISIT switch to aio primitives, so that userspace
* gets more complete API coverage. It'll simplify things
* too, except for the locking.
*/
.write
= spidev_write,
.read
= spidev_read,
.unlocked_ioctl
= spidev_ioctl,
.open
= spidev_open,
.release
= spidev_release,
};
以上操作函数的具体实现不一一列出,但需要知道spidev.c中,设备的半双工模式和全双工模式都实现了。spi应用程序的编码,请看我后面的文章。
备注:涉及到的相关目录如下
/arch/arm/mach-davici/
/driver/spi/spi.c /driver/spi/davinci_spi.c /driver/spi/spi_bitbang.c
/driver/base/platform.c /driver/base/core.c