Linux Platform总线+SPI总线分析

本文深入剖析Linux系统中SPI和Platform总线的工作原理。SPI驱动模型分为硬件抽象层、平台依赖层和用户接口层,介绍了SPI控制器驱动、设备驱动的注册管理。Platform驱动模型则讲解了platform总线、设备和驱动的结构与交互,包括platform_device、platform_driver的注册过程。文章以MPC8308平台为例,详细分析了SPI和Platform驱动的实现细节。
摘要由CSDN通过智能技术生成

本文以MPC8308(powerpc架构),HX软件包为依据,详细内容可参考源码
CPU: e300c3MPC8308 400MHz
BOARD: Freescale MPC8308ERDB
DRAM: 256M
NAND: 1024M


一、SPI原理模型

这里写图片描述

如上图所示,主设备对应SOC芯片中的SPI控制器,通常,一个SOC中可能存在多个SPI控制器,像上面的例子所示,SOC芯片中有3个SPI控制器。每个控制器下可以连接多个SPI从设备,每个从设备有各自独立的CS引脚。每个从设备共享另外3个信号引脚:SCK、MISO、MOSI。任何时刻,只有一个CS引脚处于有效状态,与该有效CS引脚连接的设备此时可以与主设备(SPI控制器)通信,其它的从设备处于等待状态,并且它们的3个引脚必须处于高阻状态。

二、SPI驱动模型

2.6的Linux内核中,SPI的驱动架构分为如下三个层次:硬件抽象层、平台依赖层和用户接口层。

这里写图片描述

  • 硬件抽象层

spi.c为其主体框架代码,提供了核心数据结构的定义、SPI控制器驱动和设备驱动的注册、注销管理等API。其为硬件平 台无关层,向下屏蔽了物理总线控制器的差异,定义了统一的访问策略和接口;其向上提供了统一的接口,以便SPI设备驱动通过总线控制器进行数据收发。

  • 平台依赖层

SPI总线Master就是一条SPI总线的控制器(所谓控制是相对于本CPU来说的),在物理上连接若干SPI从设备。在Linux驱动中,每种处理器 平台有自己的控制器驱动,属于平台移植相关层。PowerPC平台来说,其是spi_mpc83xx.c。其按照核心层定义的接口实现了 spi_master。

  • 用户接口层

设备驱动层为用户接口层,其为用户提供了通过SPI总线访问具体设备的接口。

  • 平台依赖层-总线控制器驱动

总线控制器驱动,本质上就是实现了具体的总线传输算法并向核心层注册了控制器。

主要分为三个层面,
platform device,platform driver及与SPI core的接口层。

Linux内核的所有SPI控制器驱动程序都在driver/SPI/下面,MPC8xxx驱动是spi_mpc83xx.c。

一个现实的linux设备和驱动通常都需要挂接在一种总线上,比较常见的总线有USB、PCI总线等。但是,在嵌入式系统里面,SoC系统中集成的独立的外设控制器、挂接在SoC内存空间的外设却不依附与此类总线。

基于这样的背景下,2.6内核加入了platform虚拟总线。platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序使用这些资源时使用统一的接口。platform总线对加入到该总线的设备和驱动分别封装了两个结构体——platform_device和platform_driver。并且提供了对应的注册函数。
这里写图片描述
这里写图片描述

在platform总线上注册设备和驱动,只要定义指定的结构体后调用platform给出的注册函数就可以了。

这里写图片描述


下面就介绍一下platform总线、设备和驱动

三、platform驱动模型分析

(1) platform总线:

do_basic_setup(void)

--------->driver_init();

    ---------->platform_bus_init(platform总线初始化)

        ---------->bus_register(&platform_bus_type)



structbus_type platform_bus_type = {

 .name ="platform",                   //定义了总线名字为platform,总线注册后新建目录sys/bus/platform

 .dev_attrs= platform_dev_attrs,

 .match = platform_match,

 .uevent= platform_uevent,

 .pm= PLATFORM_PM_OPS_PTR,

};



static int platform_match(structdevice *dev, struct device_driver *drv)

{

 structplatform_device *pdev;



 pdev= container_of(dev, struct platform_device, dev);

 return(strcmp(pdev->name, drv->name) == 0);     //配对函数检验名字是否一致

}

这里写图片描述

(2) platform设备:

(/include/linux/platform_device.h)

struct platform_device {

 const char * name;

 int id;

 struct device dev;

 u32 num_resources;

 struct resource * resource;

};

//可以看到,platform_device的封装就是指定了一个目录的名字name,并且内嵌device。


//platform_device的注册和注销使用以下函数:

(drivers/base/platform.c)

322 intplatform_device_register(struct platform_device *pdev) //需要判断返回值

337 voidplatform_device_unregister(struct platform_device *pdev)

//注册后,同样会在/sys/device/目录下创建一个以name命名的目录,并且创建软连接到/sys/bus/platform/device下。
  • 源码分析:
machine_device_initcall (mpc830x_edd, mpc830x_spi_init); 

/arch/powerpc/platforms/83xx/mpc830x_edd.c

-->platform_device_alloc ("mpc83xx_spi", i)-->设备树spi设备信息获取-->platform_device_alloc("mpc83xx_spi",i);-->platform_device_add

(3) platform驱动:

(linux/platform_device.h)

 structplatform_driver {

  int(*probe)(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值