Linux设备驱动模型 SPI之一
来源:互联网 发布:电脑怎么连接宽带网络 编辑:程序博客网 时间:2024/06/05 23:40
在前一篇博客当中,我谈了谈自己对于Linux设备驱动模型的一些理解,在这篇博客里,我准备以TI Davinci DM368 的SPI接口为例来谈一谈设备驱动相关的一些知识
首先回顾一下上篇博客总结的数据收发流程
协议 (符合特定外设需求的格式化数据,协议由驱动之上的驱动产生)—〉platform driver (平台设备驱动)—〉platform device(平台设备)—〉外设接口所连接的设备
这里面有四个要素:协议、platform driver、platform device、外设接口所连接的设备。那么这四个要素具体的代码在哪里呢?又是如何实现的呢?
假设SPI接口外部连接的是EEPROM,那么我们需要分析的要素变为三个:协议、platform driver、platform device。
- 定义SPI platform device并注册
- 定义SPIplatform driver并注册
- 定义协议(也就是能够驱动EEPROM的驱动程序)
在这篇博客中,我们先找到与这三个要素相关的代码,在下篇博客中详细分析这些代码是如何组成一个有机的整体,并形成一个在用户空间能够应用的一个设备文件的。
platform driver、platform device、协议代码分析
在Linux内核的架构下…\arch\arm\mach-davinci\dm365.c中有关于SPI platform device的定义和初始化函数(其中涵盖了注册SPI platform device)
static u64 dm365_spi0_dma_mask = DMA_BIT_MASK(32);//dma 掩码static struct davinci_spi_platform_data dm365_spi0_pdata = { .version = SPI_VERSION_1, .num_chipselect = 2, .dma_event_q = EVENTQ_3, .prescaler_limit = 1,};// spi 私有化数据static struct resource dm365_spi0_resources[] = { { .start = 0x01c66000, .end = 0x01c667ff, .flags = IORESOURCE_MEM, }, { .start = IRQ_DM365_SPIINT0_0, .flags = IORESOURCE_IRQ, }, { .start = 17, .flags = IORESOURCE_DMA, }, { .start = 16, .flags = IORESOURCE_DMA, },};//dm365 spi0所占有的资源static struct platform_device dm365_spi0_device = { .name = "spi_davinci",//与platform driver的相同,用于与platform_driver的匹配 .id = 0, .dev = { .dma_mask = &dm365_spi0_dma_mask, .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = &dm365_spi0_pdata, }, .num_resources = ARRAY_SIZE(dm365_spi0_resources), .resource = dm365_spi0_resources,};// dm365 spi platform device资源的整合,也就是SPI platform devicevoid __init dm365_init_spi0(unsigned chipselect_mask, const struct spi_board_info *info, unsigned len){ davinci_cfg_reg(DM365_SPI0_SCLK); davinci_cfg_reg(DM365_SPI0_SDI); davinci_cfg_reg(DM365_SPI0_SDO); /* not all slaves will be wired up */ if (chipselect_mask & BIT(0)) davinci_cfg_reg(DM365_SPI0_SDENA0); if (chipselect_mask & BIT(1)) davinci_cfg_reg(DM365_SPI0_SDENA1); spi_register_board_info(info, len); platform_device_register(&dm365_spi0_device);//注册dm365 spi0也就是注册SPI platform device}
在…\arch\arm\mach-davinci\board-dm365-evm.c中定义了EEPROM的驱动(也就是上文中说的协议)
static struct spi_eeprom at25640 = { .byte_len = SZ_64K / 8, .name = "at25640", .page_size = 32, .flags = EE_ADDR2,};static struct spi_board_info dm365_evm_spi_info[] __initconst = { { .modalias = "at25",//驱动的名字(也就是产生协议相关的格式化数据)我们可以在linux内核driver文件下找到相关的驱动文件 .platform_data = &at25640, .max_speed_hz = 10 * 1000 * 1000, .bus_num = 0, .chip_select = 0, .mode = SPI_MODE_0, },};//spi 接口所连接的设备信息,其中modalias用于指定该外部设备所用的协议(也就是驱动程序)的名字
static __init void dm365_evm_init(void){ int ret; ret = dm365_gpio_register(); if (ret) pr_warn("%s: GPIO init failed: %d\n", __func__, ret); evm_init_i2c(); davinci_serial_init(dm365_serial_device); dm365evm_emac_configure(); dm365evm_mmc_configure(); davinci_setup_mmc(0, &dm365evm_mmc_config); dm365_init_video(&vpfe_cfg, &dm365evm_display_cfg); /* maybe setup mmc1/etc ... _after_ mmc0 */ evm_init_cpld();#ifdef CONFIG_SND_DM365_AIC3X_CODEC dm365_init_asp(&dm365_evm_snd_data);#elif defined(CONFIG_SND_DM365_VOICE_CODEC) dm365_init_vc(&dm365_evm_snd_data);#endif dm365_init_rtc(); dm365_init_ks(&dm365evm_ks_data); dm365_init_spi0(BIT(0), dm365_evm_spi_info, ARRAY_SIZE(dm365_evm_spi_info));}
在…\drivers\spi\spi-davinci.c可以找到platform driver的定义
static struct platform_driver davinci_spi_driver = { .driver = { .name = "spi_davinci",//与platform device相同,用于与platform device的匹配 .of_match_table = of_match_ptr(davinci_spi_of_match), }, .probe = davinci_spi_probe, .remove = davinci_spi_remove,};
在…\drivers\base\platform.c有platform driver的注册函数
int platform_driver_register(struct platform_driver *drv){ drv->driver.bus = &platform_bus_type; if (drv->probe) drv->driver.probe = platform_drv_probe; if (drv->remove) drv->driver.remove = platform_drv_remove; if (drv->shutdown) drv->driver.shutdown = platform_drv_shutdown; return driver_register(&drv->driver);}
总结:platform driver与platform device都注册在 platform bus上,然后根据他们的name域进行匹配,如果匹配成功,则驱动与设备绑定在一起。外设接口所连接的外部设备与协议(外部设备的驱动程序)也经历相似的匹配过程。
之所以一直强调协议(也就是外部设备驱动),主要是为了区分platform driver。
PS:在下篇博客中将详细分析这四个要素之间是如何建立联系的。
- Linux设备驱动模型 SPI之一
- Linux设备驱动模型SPI之二
- Linux SPI总线设备驱动模型详解
- Linux SPI总线设备驱动模型详解
- Linux SPI总线设备驱动模型详解
- spi设备驱动模型
- [Linux] SPI 设备驱动模型(SPI 协议基础)
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- Linux SPI总线和设备驱动架构之一:系统概述
- 浅析伪罗伯特法所构造的任意阶数伪二次幻方中某一任意位置权值的一般求法
- Exynos4412 裸机开发 —— IIC总线
- 机器学习、模式识别中的相似性度量
- 1076. Forwards on Weibo (30)
- uva 11388 最大公约数与最小公倍数的关系
- Linux设备驱动模型 SPI之一
- 安卓TextView中的文本加上横线或者下划线
- vs2010如何检测内存泄漏
- Caffe softmax_layer.cpp学习
- hdu3555数位dp
- windows系统下安装ubuntu的方法
- redis安装步骤
- 统计思维:程序员数学之概率统计(第2版):第1章 探索性数据分析
- 蓝桥杯历届-猜年龄