设为首页 加入收藏

TOP

SPI子系统之驱动SSD1306 OLED(一)
2016-12-28 08:16:17 】 浏览:1167
Tags:SPI 子系统 驱动 SSD1306 OLED

理解SPI的驱动框架,还是从最基本的三个入口点触发,platform_device,platform_bus,platform_driver。


其中内核一提供给platform_bus,platform_driver在spi_s3c24xx_gpio.c和spi_s3c24xxc.c中,其中spi_s3c24xx_gpio.c用于IO模拟SPI (本例讨论的是IO模拟SPI),spi_s3c24xxc.c用于s3c24xx的硬件SPI。因此,我们需要动手写一个platform_device。


看看spi_s3c24xx_gpio.c做了些什么。


static int s3c2410_spigpio_probe(struct platform_device *dev)
{
... ...
/* [cgw]: 分配一个SPI主机 */
master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio));
... ...


sp = spi_master_get_devdata(master);


platform_set_drvdata(dev, sp);


/* [cgw]: 分配与spi硬件相关的配置,如指定哪些IO为MISO,MOSI,SCLK,CS,SPI工作模式,最大时钟等等 */
/* copy in the plkatform data */
sp->info = dev->dev.platform_data;


/* [cgw]: 提供实现SPI各种模式的时序的基本方法,和CS的激活方法 */
/* setup spi bitbang adaptor */
sp->bitbang.master = spi_master_get(master);
sp->bitbang.chipselect = s3c2410_spigpio_chipselect;


sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1;
sp->bitbang.txrx_word[SPI_MODE_2] = s3c2410_spigpio_txrx_mode2;
sp->bitbang.txrx_word[SPI_MODE_3] = s3c2410_spigpio_txrx_mode3;


/* [cgw]: 配置相关io为输入输出 */
/* set state of spi pins */
s3c2410_gpio_setpin(sp->info->pin_clk, 0);
s3c2410_gpio_setpin(sp->info->pin_mosi, 0);


s3c2410_gpio_cfgpin(sp->info->pin_clk, S3C2410_GPIO_OUTPUT);
s3c2410_gpio_cfgpin(sp->info->pin_mosi, S3C2410_GPIO_OUTPUT);
s3c2410_gpio_cfgpin(sp->info->pin_miso, S3C2410_GPIO_INPUT);


/* [cgw]: 设置spi的收发,如注册一个工作队列,收发时序的方法,8/16/32的spi数据等等 */
ret = spi_bitbang_start(&sp->bitbang);
... ...


/* [cgw]: 注册sp->info->board_size个spi设备,这几个spi设备都是挂接在统一spi总线上的 */
/* register the chips to go with the board */
for (i = 0; i < sp->info->board_size; i++) {
dev_info(&dev->dev, "registering %p: %s\n",
&sp->info->board_info[i],
sp->info->board_info[i].modalias);


sp->info->board_info[i].controller_data = sp;
spi_new_device(master, sp->info->board_info + i);
}
... ...
}


要想s3c2410_spigpio_probe得到调用,即探测到有效的platform_device,我们需要一个与platform同名("s3c24xx-spi-gpio")的platform_device。


static struct spi_board_info board_info[1] = {
{
.modalias = "spi_ssd1306", /* [cgw]: spi设备名,和设备驱动名对应 */
.bus_num = 0, /* [cgw]: spi总线号,即spi0 */
.chip_select = 2, /* [cgw]: spi总线上的设备号,即spi0.2 */
.max_speed_hz = 50000, /* [cgw]: spi时钟 */
.mode = SPI_MODE_3, /* [cgw]: spi数据模式 */
},
};


static struct s3c2410_spigpio_info spi_dev = {
.pin_clk = S3C2410_GPG7,
.pin_mosi = S3C2410_GPG5,
.pin_miso = S3C2410_GPG6,
.board_size = 1, /* [cgw]: 设置板上spi接口数量为1 */
.board_info = &board_info[0],
.chip_select = ssd1306_chip_select
};


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

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

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目