设为首页 加入收藏

TOP

SPI子系统之驱动SSD1306 OLED(二)
2016-12-28 08:16:17 】 浏览:1174
Tags:SPI 子系统 驱动 SSD1306 OLED
)
{
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);


/* 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(&bitb

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 2/10/10
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Linux网络驱动--snull 下一篇深入理解 Spring 事务原理

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目