Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3515406
  • 博文数量: 1805
  • 博客积分: 135
  • 博客等级: 入伍新兵
  • 技术积分: 3345
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-19 20:01
文章分类

全部博文(1805)

文章存档

2017年(19)

2016年(80)

2015年(341)

2014年(438)

2013年(349)

2012年(332)

2011年(248)

分类:

2011-10-28 13:25:19

原文地址:我对linux理解之spi 作者:amingriyue

------------------------------------------
本文系本站原创,欢迎转载!
转载请注明出处:amingriyue.blog.chinaunix.net
------------------------------------------

我们先看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就分析到此吧。


阅读(989) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~