------------------------------------------
本文系本站原创,欢迎转载!
------------------------------------------我们先看spi外设的设备注册:
static struct mc13892_platform_data mc13892_plat = {
.init = mc13892_regulator_init,
};
static struct spi_board_info __initdata mc13892_spi_device = {
.modalias = "pmic_spi",
.irq = IOMUX_TO_IRQ_V3(5),
.max_speed_hz = 6000000, /* max spi SCK clock speed in HZ */
.bus_num = 1,
.chip_select = 1,
.platform_data = &mc13892_plat,
};
在初始化函数中有:
spi_register_board_info(&mc13892_spi_device, 1);
定义如下:
int __init
spi_register_board_info(struct spi_board_info const *info, unsigned n)
{
struct boardinfo *bi;
bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);//申请boardinfo空间
if (!bi)
return -ENOMEM;
bi->n_board_info = n;//spi描述的数目
memcpy(bi->board_info, info, n * sizeof *info);//将信息拷贝到boardinfo中
mutex_lock(&board_lock);
list_add_tail(&bi->list, &board_list);//添加到board_list,这个有点像i2c,这里也应该提前注册好的,以备后面之用
mutex_unlock(&board_lock);
return 0;
}
我们看到,上面的过程将外设的信息添加到board_list中。
我们下面看spi的controller注册:
static struct platform_driver mxc_spi_driver = {
.driver = {
.name = "mxc_spi",
.bus = &platform_bus_type,
.owner = THIS_MODULE,
},
.probe = mxc_spi_probe,
.remove = mxc_spi_remove,
.suspend_late = mxc_spi_suspend,
.resume_early = mxc_spi_resume,
};
static int __init mxc_spi_init(void)
{
pr_debug("Registering the SPI Controller Driver\n");
return platform_driver_register(&mxc_spi_driver);
}
我们对platform应该是非常熟悉了。它匹配后将会执行probe探测函数,即mxc_spi_probe:
static int mxc_spi_probe(struct platform_device *pdev)
{
struct mxc_spi_master *mxc_platform_info;
struct spi_master *master;
struct mxc_spi *master_drv_data = NULL;
unsigned int spi_ver;
int ret = -ENODEV;
/* Get the platform specific data for this master device */
mxc_platform_info = (struct mxc_spi_master *)pdev->dev.platform_data;
if (!mxc_platform_info) {
dev_err(&pdev->dev, "can't get the platform data for CSPI\n");
return -EINVAL;
}
/* Allocate SPI master controller */
master = spi_alloc_master(&pdev->dev, sizeof(struct mxc_spi));//申请master空间
if (!master) {
dev_err(&pdev->dev, "can't alloc for spi_master\n");
return -ENOMEM;
}
/* Set this device's driver data to master */
platform_set_drvdata(pdev, master);//将master设置为pdev的私有变量
/* Set this master's data from platform_info */
master->bus_num = pdev->id + 1;//设置master
master->num_chipselect = mxc_platform_info->maxchipselect;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
#ifdef CONFIG_SPI_MXC_TEST_LOOPBACK
master->num_chipselect += 1;
#endif
/* Set the master controller driver data for this master */
master_drv_data = spi_master_get_devdata(master);
master_drv_data->mxc_bitbang.master = spi_master_get(master);//将master赋值给bitbang
......
/* Set the master bitbang data */
master_drv_data->mxc_bitbang.chipselect = mxc_spi_chipselect;//bitbang的设置
master_drv_data->mxc_bitbang.txrx_bufs = mxc_spi_transfer;//传输函数
master_drv_data->mxc_bitbang.master->setup = mxc_spi_setup;
master_drv_data->mxc_bitbang.master->cleanup = mxc_spi_cleanup;
master_drv_data->mxc_bitbang.setup_transfer = mxc_spi_setup_transfer;//启动传输
......
/* Start the SPI Master Controller driver */
ret = spi_bitbang_start(&master_drv_data->mxc_bitbang);//注册到spi core
......
}
我们看probe主要初始化了master和bitbang,我们下面看spi_bitbang_start(&master_drv_data->mxc_bitbang):
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);//初始化spinlock
INIT_LIST_HEAD(&bitbang->queue);//初始化队列头
if (!bitbang->master->mode_bits)
bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
if (!bitbang->master->transfer)//检测master的transfer是否有定义,如果没有则使用默认的,我们从probe中知道,这个是没有定义的
bitbang->master->transfer = spi_bitbang_transfer;//使用默认的传输函数
if (!bitbang->txrx_bufs) {//检测bitbang的txrx_bufs是否有定义,在mxc_spi的probe中知道已经定义
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)//在mxc_spi的probe中知道已经定义
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
*/
status = spi_register_master(bitbang->master);//注册到spi core
if (status < 0)
goto err2;
return status;
err2:
destroy_workqueue(bitbang->workqueue);
err1:
return status;
}
我们下面看spi_register_master(bitbang->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.
*/
dev_set_name(&master->dev, "spi%u", master->bus_num);//设置master的设备名字
status = device_add(&master->dev);//添加到sys系统中
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 */
scan_boardinfo(master);//搜寻合适的boardinfo
status = 0;
done:
return status;
}
这边主要是实现master设备和搜寻外设的boardinfo,我们下面看scan_boardinfo(master):
static void scan_boardinfo(struct spi_master *master)
{
struct boardinfo *bi;
mutex_lock(&board_lock);
list_for_each_entry(bi, &board_list, list) {//board_list,就是spi_register_board_info函数中生成的那个board_list
struct spi_board_info *chip = bi->board_info;
unsigned n;
for (n = bi->n_board_info; n > 0; n--, chip++) {
if (chip->bus_num != master->bus_num)
continue;
/* NOTE: this relies on spi_new_device to
* issue diagnostics when given bogus inputs
*/
(void) spi_new_device(master, chip);//将master和spi外设联系起来
}
}
mutex_unlock(&board_lock);
}
这里将根据board_list搜寻device,我们接着看spi_new_device(master, chip):
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).
*/
proxy = spi_alloc_device(master);//申请spi设备,有将master赋值给spi device,这样可以通过spi device访问到master
if (!proxy)
return NULL;
WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));//名字长度不超过32
proxy->chip_select = chip->chip_select;//根据boardinfo进行设备的初始化
proxy->max_speed_hz = chip->max_speed_hz;
proxy->mode = chip->mode;
proxy->irq = chip->irq;
strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));//外设driver将根据modias和driver的名字去匹配
proxy->dev.platform_data = (void *) chip->platform_data;
proxy->controller_data = chip->controller_data;
proxy->controller_state = NULL;
status = spi_add_device(proxy);//添加spi设备
if (status < 0) {
spi_dev_put(proxy);
return NULL;
}
return proxy;
}
我们下面看spi_add_device(proxy):
int spi_add_device(struct spi_device *spi)
{
static DEFINE_MUTEX(spi_add_lock);
struct device *dev = spi->master->dev.parent;
int status;
/* Chipselects are numbered 0..max; validate. */
if (spi->chip_select >= spi->master->num_chipselect) {//如果设备设定的编号大于master的总数量,则错误
dev_err(dev, "cs%d >= max %d\n",
spi->chip_select,
spi->master->num_chipselect);
return -EINVAL;
}
/* Set the bus ID string */
dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev),//设置设备名字,并没有设置成modlias
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);
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;
}
/* 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);//初始化master,即spi controller
if (status < 0) {
dev_err(dev, "can't %s %s, status %d\n",
"setup", dev_name(&spi->dev), status);
goto done;
}
/* Device may be bound to an active driver when this returns */
status = device_add(&spi->dev);//将spi设备添加到sys中
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;
}
这里将spi的外设添加到了sys中了,我们下面看下:
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);//调用master的setup,在mxc_spi的probe中有定义,主要是启动spi master的硬件
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;
}
主要是是启动spi master的硬件了。
到这里我们知道想sys中添加了master和外设。那外设得有driver啊,我们下面就看外设的driver:
static struct spi_driver pmic_driver = {
.driver = {
.name = "pmic_spi",
.bus = &spi_bus_type,//bus类型,将按照spi bus类型去匹配
.owner = THIS_MODULE,
},
.probe = pmic_probe,//如果匹配将要执行的探测函数
.remove = __devexit_p(pmic_remove),
.suspend = pmic_suspend,
.resume = pmic_resume,
};
static int __init pmic_init(void)
{
return spi_register_driver(&pmic_driver);//spi注册driver
}
我们看下spi_register_driver(&pmic_driver):
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);
}
driver_register之前已经分析过了,其中知道它将会去匹配bus上面的每个device,我们下面看下spi bus怎么去匹配的:
struct bus_type spi_bus_type = {
.name = "spi",
.dev_attrs = spi_dev_attrs,
.match = spi_match_device,
.uevent = spi_uevent,
.suspend = spi_suspend,
.resume = spi_resume,
};
我们看下spi bus的匹配函数spi_match_device:
static int spi_match_device(struct device *dev, struct device_driver *drv)
{
const struct spi_device *spi = to_spi_device(dev);//从sys设备转换到spi设备
return strcmp(spi->modalias, drv->name) == 0;//匹配spi->modalias和drv->name
}
从函数定义中看到匹配函数将根据的spi设备的modlias和驱动的名字去匹配。我们在driver_register分析中还知道,如果匹配了,将会执行driver的probe探测函数。
好了,spi的master,设备,driver注册分析差不多结束了。下面我们分析数据怎么传输的:
int pmic_read(int reg_num, unsigned int *reg_val)
{
unsigned int frame = 0;
int ret = 0;
if (pmic_drv_data.spi != NULL) {
if (reg_num > MXC_PMIC_MAX_REG_NUM)
return PMIC_ERROR;
frame |= reg_num << MXC_PMIC_REG_NUM_SHIFT;
ret = spi_rw(pmic_drv_data.spi, (u8 *) &frame, 1);
*reg_val = frame & MXC_PMIC_FRAME_MASK;
} else {
if (mc13892_client == NULL)
return PMIC_ERROR;
if (pmic_i2c_24bit_read(mc13892_client, reg_num, reg_val) == -1)
return PMIC_ERROR;
}
return PMIC_SUCCESS;
}
int pmic_write(int reg_num, const unsigned int reg_val)
{
unsigned int frame = 0;
int ret = 0;
if (pmic_drv_data.spi != NULL) {
if (reg_num > MXC_PMIC_MAX_REG_NUM)
return PMIC_ERROR;
frame |= (1 << MXC_PMIC_WRITE_BIT_SHIFT);
frame |= reg_num << MXC_PMIC_REG_NUM_SHIFT;
frame |= reg_val & MXC_PMIC_FRAME_MASK;
ret = spi_rw(pmic_drv_data.spi, (u8 *) &frame, 1);
return ret;
} else {
if (mc13892_client == NULL)
return PMIC_ERROR;
return pmic_i2c_24bit_write(mc13892_client, reg_num, reg_val);
}
}
我们看到无论是pmic的读还是写,最终都转化为spi_rw(pmic_drv_data.spi, (u8 *) &frame, 1),但是传的frame值格式是不一样的:
static inline int spi_rw(struct spi_device *spi, u8 * buf, size_t len)
{
struct spi_transfer t = {//spi传输的单元
.tx_buf = (const void *)buf,
.rx_buf = buf,
.len = len,
.cs_change = 0,
.delay_usecs = 0,
};
struct spi_message m;
spi_message_init(&m);
spi_message_add_tail(&t, &m);//将t添加到spi_message
if (spi_sync(spi, &m) != 0 || m.status != 0)//执行spi_sync
return PMIC_ERROR;
return (len - m.actual_length);
}
spi_sync(spi, &m):
int spi_sync(struct spi_device *spi, struct spi_message *message)
{
DECLARE_COMPLETION_ONSTACK(done);
int status;
message->complete = spi_complete;
message->context = &done;
status = spi_async(spi, message);
if (status == 0) {
wait_for_completion(&done);
status = message->status;
}
message->context = NULL;
return status;
}
通过complete转到spi_async(spi, message):
static inline int
spi_async(struct spi_device *spi, struct spi_message *message)
{
message->spi = spi;
return spi->master->transfer(spi, message);
}
上面spi设备注册的时候就分析过了,通过spi设备可以访问到master,这里就是一个例子。
我们在spi_bitbang_start(struct spi_bitbang *bitbang)分析中知道:bitbang->master->transfer = spi_bitbang_transfer,我们下面看spi_bitbang_transfer:
int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
{
struct spi_bitbang *bitbang;
unsigned long flags;
int status = 0;
m->actual_length = 0;
m->status = -EINPROGRESS;
bitbang = spi_master_get_devdata(spi->master);
spin_lock_irqsave(&bitbang->lock, flags);
if (!spi->max_speed_hz)
status = -ENETDOWN;
else {
list_add_tail(&m->queue, &bitbang->queue);//将m添加到bitbang的queue中
queue_work(bitbang->workqueue, &bitbang->work);//将bitbang->work添加到bitbang->workqueue的工作队列中,然后调度它
}
spin_unlock_irqrestore(&bitbang->lock, flags);
return status;
}
我们在我们在spi_bitbang_start(struct spi_bitbang *bitbang)分析中知道bitbang->work的初始化:
INIT_WORK(&bitbang->work, bitbang_work);
我们下面看bitbang_work:
static void bitbang_work(struct work_struct *work)
{
struct spi_bitbang *bitbang =
container_of(work, struct spi_bitbang, work);
unsigned long flags;
int do_setup = -1;
int (*setup_transfer)(struct spi_device *,
struct spi_transfer *);
setup_transfer = bitbang->setup_transfer;
spin_lock_irqsave(&bitbang->lock, flags);
bitbang->busy = 1;
while (!list_empty(&bitbang->queue)) {//如果queue不为空
struct spi_message *m;
struct spi_device *spi;
unsigned nsecs;
struct spi_transfer *t = NULL;
unsigned tmp;
unsigned cs_change;
int status;
m = container_of(bitbang->queue.next, struct spi_message,//取出spi_message
queue);
list_del_init(&m->queue);
spin_unlock_irqrestore(&bitbang->lock, flags);
/* FIXME this is made-up ... the correct value is known to
* word-at-a-time bitbang code, and presumably chipselect()
* should enforce these requirements too?
*/
nsecs = 100;
spi = m->spi;
tmp = 0;
cs_change = 1;
status = 0;
list_for_each_entry (t, &m->transfers, transfer_list) {//对每个spi_transfer
/* override speed or wordsize? */
if (t->speed_hz || t->bits_per_word)//speed和bits_per_word是否有改变
do_setup = 1;//如果有改变,则做一下setup工作
/* init (-1) or override (1) transfer params */
if (do_setup != 0) {
if (!setup_transfer) {
status = -ENOPROTOOPT;
break;
}
status = setup_transfer(spi, t);
if (status < 0)
break;
}
/* set up default clock polarity, and activate chip;
* this implicitly updates clock and spi modes as
* previously recorded for this device via setup().
* (and also deselects any other chip that might be
* selected ...)
*/
if (cs_change) {
bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
ndelay(nsecs);
}
cs_change = t->cs_change;
if (!t->tx_buf && !t->rx_buf && t->len) {//如果发送和接收的buffer都为空
status = -EINVAL;
break;
}
/* transfer data. the lower level code handles any
* new dma mappings it needs. our caller always gave
* us dma-safe buffers.
*/
if (t->len) {
/* REVISIT dma API still needs a designated
* DMA_ADDR_INVALID; ~0 might be better.
*/
if (!m->is_dma_mapped)
t->rx_dma = t->tx_dma = 0;
status = bitbang->txrx_bufs(spi, t);//传输函数,对应mxc_spi中的mxc_spi_transfer
}
if (status > 0)
m->actual_length += status;
if (status != t->len) {
/* always report some kind of error */
if (status >= 0)
status = -EREMOTEIO;
break;
}
status = 0;
/* protocol tweaks before next transfer */
if (t->delay_usecs)
udelay(t->delay_usecs);
if (!cs_change)
continue;
if (t->transfer_list.next == &m->transfers)
break;
/* sometimes a short mid-message deselect of the chip
* may be needed to terminate a mode or command
*/
ndelay(nsecs);
bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
ndelay(nsecs);
}
m->status = status;
m->complete(m->context);
/* restore speed and wordsize if it was overridden */
if (do_setup == 1)
setup_transfer(spi, NULL);
do_setup = 0;
/* normally deactivate chipselect ... unless no error and
* cs_change has hinted that the next message will probably
* be for this chip too.
*/
if (!(status == 0 && cs_change)) {
ndelay(nsecs);
bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
ndelay(nsecs);
}
spin_lock_irqsave(&bitbang->lock, flags);
}
bitbang->busy = 0;
spin_unlock_irqrestore(&bitbang->lock, flags);
}
我们看最后转到了bitbang->txrx_bufs(spi, t),我们在mxc_spi中probe分析知道,它对应了具体的spi controller的mxc_spi_transfer。
spi的数据传输比i2c稍微复杂了一点,但是整体还是比较的清楚的。好了,spi就分析到此吧。