spi子系统

本文详细介绍了SPI子系统的组件和工作流程,包括SPI主控制器驱动、协议驱动、数据结构如spi_master、spi_device、spi_board_info、spi_transfer,以及SPI消息的处理方式。在SPI通信中,数据流从用户请求到Protocol driver解析,再到Controller driver与SPI设备交互,然后设备返回数据,最后由Protocol driver解析并上报。文章还探讨了SPI设备的注册过程和SPI数据传输的控制结构,如spi_bitbang的角色。
摘要由CSDN通过智能技术生成

ti8168驱动备份

queue_work调度执行一个指定workqueue中的任务。输入参数:
@ workqueue_struct:指定的workqueue指针
@work_struct:具体任务对象指针
spi目录下Makefile:
ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG 如果配置了SPI_DEBUG则添加DDEBUG宏定义;其中ccflags是指编译相应文件时使用的选项
obj-$(CONFIG_SPI_MASTER)        += spi.o 添加spi子系统,即master
有些时候,没有此对应的硬件上的SPI控制器,而还想要和SPI设备通信,那么就只能用GPIO端口去模拟对应的SPI接口的对应的pin:片选CS,数据输入Data In,数据输出Data Out,
始终Clock,去模拟SPI协议,和对应spi设备进行通信。所以,此时你对每个端口的操作,作为编程者,你自己要去负责信号的同步,保证timing符合协议规定,才能正常进行SPI通
信。这样的SPI的bit-bang。
通过GPIO引脚,用软件来模拟串行通信(SPI/I2C )
obj-$(CONFIG_SPI_BITBANG)       += spi_bitbang.o
这是ti81xx的master驱动选项,需要选择上
config SPI_OMAP24XX                                                     
     tristate "McSPI driver for OMAP/TI81XX"                         
     depends on ARCH_OMAP2PLUS || ARCH_TI81XX                           
     help                                                                
       SPI master controller for OMAP24XX and later Multichannel SPI     
       (McSPI) modules.
spi dev是可以直接在应用层操作spi设备,在驱动层封装具体的设备应用程序
config SPI_SPIDEV
tristate "User mode SPI device driver support"
depends on EXPERIMENTAL
help
  This supports user mode SPI protocol drivers.

  Note that this application programming interface is EXPERIMENTAL
  and hence SUBJECT TO CHANGE WITHOUT NOTICE while it stabilizes.
Makefile和Konfig分析完了,咱们再看看板文件的配置:
从board-ti8168evm.c中没有找到spi master设备的配置,最终在devices中找到了,如下:
static int __init omap2_init_devices(void)
{
omap_init_mcspi();
        。。。
}
arch_initcall(omap2_init_devices);
在系统初始化时,会调用该函数,具体实现如下:
static void omap_init_mcspi(void)
{
        //设置spi寄存器开始地址和结束地址
if (cpu_is_ti81xx())
ti81xx_mcspi_fixup();
        //注册spi master设备
platform_device_register(&omap2_mcspi1);
}
static inline void ti81xx_mcspi_fixup(void)
{
omap2_mcspi1_resources[0].start = TI81XX_MCSPI1_BASE;
omap2_mcspi1_resources[0].end = TI81XX_MCSPI1_BASE + 0xff;
}
在分析platform_device_register()之前,我们先分析下设备结构体:
4个片选:
static struct omap2_mcspi_platform_config omap2_mcspi1_config = {
.num_cs = 4,
};
io资源:
static struct resource omap2_mcspi1_resources[] = {
{
.start = OMAP2_MCSPI1_BASE,
.end = OMAP2_MCSPI1_BASE + 0xff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device omap2_mcspi1 = {
        //设备名,会和master driver name比较
.name = "omap2_mcspi",
.id = 1,
.num_resources = ARRAY_SIZE(omap2_mcspi1_resources),
.resource = omap2_mcspi1_resources,
.dev = {
.platform_data = &omap2_mcspi1_config,
},
};
platform_device_register()注册过程:
int platform_device_register(struct platform_device *pdev)
{
device_initialize(&pdev->dev);
return platform_device_add(pdev);
}
void device_initialize(struct device *dev)
{
dev->kobj.kset = devices_kset;
kobject_init(&dev->kobj, &device_ktype);
INIT_LIST_HEAD(&dev->dma_pools);
mutex_init(&dev->mutex);
lockdep_set_novalidate_class(&dev->mutex);
spin_lock_init(&dev->devres_lock);
INIT_LIST_HEAD(&dev->devres_head);
device_pm_init(dev);
set_dev_node(dev, -1);
}

int platform_device_add(struct platform_device *pdev)
{
int i, ret = 0;
if (!pdev->dev.parent)
pdev->dev.parent = &platform_bus;
pdev->dev.bus = &platform_bus_type;

if (pdev->id != -1)
dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);

for (i = 0; i < pdev->num_resources; i++) {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值