SPI子系统之驱动SSD1306 OLED(3)

/* NOTE we _need_ to call chipselect() early, ideally with adapter
    * setup, unless the hardware defaults cooperate to avoid confusion
    * between normal (active low) and inverted chipselects.
    */

/* [cgw]: spi忙的话,通过改变CS的状态释放SPI */
    /* deselect chip (low or high) */
    spin_lock(&bitbang->lock);
    if (!bitbang->busy) {
        bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
        ndelay(cs->nsecs);
    }
    spin_unlock(&bitbang->lock);

return 0;
}


static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
{
    struct spi_bitbang_cs    *cs = spi->controller_state;
    unsigned        nsecs = cs->nsecs;
   
    /* [cgw]: 具体数据收发就是这里实现的 */
    return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t);
}

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 {
        /* [cgw]: 入队一个工作到工作队列 */
        list_add_tail(&m->queue, &bitbang->queue);
        queue_work(bitbang->workqueue, &bitbang->work);
    }
    spin_unlock_irqrestore(&bitbang->lock, flags);

return status;
}

int spi_bitbang_start(struct spi_bitbang *bitbang)
{
    int    status;

if (!bitbang->master || !bitbang->chipselect)
        return -EINVAL;
   
    /* [cgw]: 注册一个工作队列 */
    INIT_WORK(&bitbang->work, bitbang_work);
    spin_lock_init(&bitbang->lock);
    INIT_LIST_HEAD(&bitbang->queue);

/* [cgw]: 配置相关方法 */
    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;

/* [cgw]: 创建一个单线程,用于调度工作队列 */
    /* this task is the only thing to touch the SPI bits */
    bitbang->busy = 0;
    bitbang->workqueue = create_singlethread_workqueue(
            bitbang->master->cdev.dev->bus_id);
    if (bitbang->workqueue == NULL) {
        status = -EBUSY;
        goto err1;
    }

/* [cgw]: 注册一个spi主机 */
    /* driver may get busy before register() returns, especially
    * if someone registered boardinfo for devices
    */
    status = spi_register_master(bitbang->master);
    if (status < 0)
        goto err2;

return status;

err2:
    destroy_workqueue(bitbang->workqueue);
err1:
    return status;
}

因为在s3c2410_spigpio_probe中注册了spi的设备,因此我们还需为这些设备提供驱动,以被这些设备探测到,探测这些驱动的条件也是设备和驱动的名字同名,即spi_ssd1306。我们这里提供了一个ssd1306 OLED的驱动

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/f06f37a19007f6f04167f392c9581460.html