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

static struct platform_device spi_platform_dev = {
    .name        = "s3c24xx-spi-gpio",        /* [cgw]: 设置平台设备名,和平台驱动名对应 */
    .id          = -1,
    .dev = {
        .release = spi_dev_release,
        .platform_data = (void *)&spi_dev,      /* [cgw]: 通过platform_data传递spi_dev给平台驱动
                                                * 平台驱动可以访问spi_dev
                                                */
    },
};

static int spi_dev_init(void)
{
    /* [cgw]: 注册spi_platform_dev平台设备 */
    platform_device_register(&spi_platform_dev);
    return 0;
}

spi_bitbang.c提供了spi底层一些实现细节,注册工作队列(SPI数据的传送最终是通过调用工作队列实现的),spi工作模式,工作频率等。

int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
{
    struct spi_bitbang_cs    *cs = spi->controller_state;
    u8            bits_per_word;
    u32            hz;

if (t) {
        /* [cgw]: spi驱动指定几位数据模式,和传送速度 */
        bits_per_word = t->bits_per_word;
        hz = t->speed_hz;
    } else {
        bits_per_word = 0;
        hz = 0;
    }

/* [cgw]: 根据spi位数,选择合适的时序 */
    /* spi_transfer level calls that work per-word */
    if (!bits_per_word)
        bits_per_word = spi->bits_per_word;
    if (bits_per_word <= 8)
        cs->txrx_bufs = bitbang_txrx_8;
    else if (bits_per_word <= 16)
        cs->txrx_bufs = bitbang_txrx_16;
    else if (bits_per_word <= 32)
        cs->txrx_bufs = bitbang_txrx_32;
    else
        return -EINVAL;

/* [cgw]: 设置SCLK的时钟频率 */
    /* nsecs = (clock period)/2 */
    if (!hz)
        hz = spi->max_speed_hz;
    if (hz) {
        cs->nsecs = (1000000000/2) / hz;
        if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000))
            return -EINVAL;
    }

return 0;
}

int spi_bitbang_setup(struct spi_device *spi)
{
    struct spi_bitbang_cs    *cs = spi->controller_state;
    struct spi_bitbang    *bitbang;
    int            retval;

bitbang = spi_master_get_devdata(spi->master);

/* REVISIT: some systems will want to support devices using lsb-first
    * bit encodings on the wire.  In pure software that would be trivial,
    * just bitbang_txrx_le_cphaX() routines shifting the other way, and
    * some hardware controllers also have this support.
    */
    /* [cgw]: 默认不支持LSB模式,要想使用LSB模式,只要bitbang_txrx_le_cphaX()改变移位的方向即可 */
    if ((spi->mode & SPI_LSB_FIRST) != 0)
        return -EINVAL;

if (!cs) {
        cs = kzalloc(sizeof *cs, GFP_KERNEL);
        if (!cs)
            return -ENOMEM;
        spi->controller_state = cs;
    }

/* [cgw]: 设置spi的默认位数 */
    if (!spi->bits_per_word)
        spi->bits_per_word = 8;

/* per-word shift register access, in hardware or bitbanging */
    /* [cgw]: 设置spi的工作模式,四种 */
    cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
    if (!cs->txrx_word)
        return -EINVAL;

/* [cgw]: 调用spi_bitbang_setup_transfer */
    retval = bitbang->setup_transfer(spi, NULL);
    if (retval < 0)
        return retval;

dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
            __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
            spi->bits_per_word, 2 * cs->nsecs);

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

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