驱动程序模型-platform

http://code.google.com/p/linuxkernelchinesedoc/source/browse/trunk/%20linuxkernelchinesedoc/device-model/zplatform.txt

 

 

Platform Devices and Drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See <linux/platform_device.h> for the driver model interface to the
platform bus: platform_device, and platform_driver. This pseudo-bus
is used to connect devices on busses with minimal infrastructure,
like those used to integrate peripherals on many system-on-chip
processors, or some "legacy" PC interconnects; as opposed to large
formally specified ones like PCI or USB.


Platform devices
~~~~~~~~~~~~~~~~
Platform devices are devices that typically appear as autonomous
entities in the system. This includes legacy port-based devices and
host bridges to peripheral buses, and most controllers integrated
into system-on-chip platforms. What they usually have in common
is direct addressing from a CPU bus. Rarely, a platform_device will
be connected through a segment of some other kind of bus; but its
registers will still be directly addressable.

Platform devices are given a name, used in driver binding, and a
list of resources such as addresses and IRQs.

struct platform_device {
const char *name;
u32 id;
struct device dev;
u32 num_resources;
struct resource *resource;
};


Platform drivers
~~~~~~~~~~~~~~~~
Platform drivers follow the standard driver model convention, where
discovery/enumeration is handled outside the drivers, and drivers
provide probe() and remove() methods. They support power management
and shutdown notifications using the standard conventions.

struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver;
};

Note that probe() should general verify that the specified device hardware
actually exists; sometimes platform setup code can't be sure. The probing
can use device resources, including clocks, and device platform_data.

Platform drivers register themselves the normal way:

int platform_driver_register(struct platform_driver *drv);

Or, in common situations where the device is known not to be hot-pluggable,
the probe() routine can live in an init section to reduce the driver's
runtime memory footprint:

int platform_driver_probe(struct platform_driver *drv,
int (*probe)(struct platform_device *))


Device Enumeration
~~~~~~~~~~~~~~~~~~
As a rule, platform specific (and often board-specific) setup code will
register platform devices:

int platform_device_register(struct platform_device *pdev);

int platform_add_devices(struct platform_device **pdevs, int ndev);

The general rule is to register only those devices that actually exist,
but in some cases extra devices might be registered. For example, a kernel
might be configured to work with an external network adapter that might not
be populated on all boards, or likewise to work with an integrated controller
that some boards might not hook up to any peripherals.

In some cases, boot firmware will export tables describing the devices
that are populated on a given board. Without such tables, often the
only way for system setup code to set up the correct devices is to build
a kernel for a specific target board. Such board-specific kernels are
common with embedded and custom systems development.

In many cases, the memory and IRQ resources associated with the platform
device are not enough to let the device's driver work. Board setup code
will often provide additional information using the device's platform_data
field to hold additional information.

Embedded systems frequently need one or more clocks for platform devices,
which are normally kept off until they're actively needed (to save power).
System setup also associates those clocks with the device, so that that
calls to clk_get(&pdev->dev, clock_name) return them as needed.


Legacy Drivers: Device Probing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some drivers are not fully converted to the driver model, because they take
on a non-driver role: the driver registers its platform device, rather than
leaving that for system infrastructure. Such drivers can't be hotplugged
or coldplugged, since those mechanisms require device creation to be in a
different system component than the driver.

The only "good" reason for this is to handle older system designs which, like
original IBM PCs, rely on error-prone "probe-the-hardware" models for hardware
configuration. Newer systems have largely abandoned that model, in favor of
bus-level support for dynamic configuration (PCI, USB), or device tables
provided by the boot firmware (e.g. PNPACPI on x86). There are too many
conflicting options about what might be where, and even educated guesses by
an operating system will be wrong often enough to make trouble.

This style of driver is discouraged. If you're updating such a driver,
please try to move the device enumeration to a more appropriate location,
outside the driver. This will usually be cleanup, since such drivers
tend to already have "normal" modes, such as ones using device nodes that
were created by PNP or by platform device setup.

None the less, there are some APIs to support such legacy drivers. Avoid
using these calls except with such hotplug-deficient drivers.

struct platform_device *platform_device_alloc(
const char *name, int id);

You can use platform_device_alloc() to dynamically allocate a device, which
you will then initialize with resources and platform_device_register().
A better solution is usually:

struct platform_device *platform_device_register_simple(
const char *name, int id,
struct resource *res, unsigned int nres);

You can use platform_device_register_simple() as a one-step call to allocate
and register a device.


Device Naming and Driver Binding
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The platform_device.dev.bus_id is the canonical name for the devices.
It's built from two components:

* platform_device.name ... which is also used to for driver matching.

* platform_device.id ... the device instance number, or else "-1"
to indicate there's only one.

These are concatenated, so name/id "serial"/0 indicates bus_id "serial.0", and
"serial/3" indicates bus_id "serial.3"; both would use the platform_driver
named "serial". While "my_rtc"/-1 would be bus_id "my_rtc" (no instance id)
and use the platform_driver called "my_rtc".

Driver binding is performed automatically by the driver core, invoking
driver probe() after finding a match between device and driver. If the
probe() succeeds, the driver and device are bound as usual. There are
three different ways to find such a match:

- Whenever a device is registered, the drivers for that bus are
checked for matches. Platform devices should be registered very
early during system boot.

- When a driver is registered using platform_driver_register(), all
unbound devices on that bus are checked for matches. Drivers
usually register later during booting, or by module loading.

- Registering a driver using platform_driver_probe() works just like
using platform_driver_register(), except that the driver won't
be probed later if another device registers. (Which is OK, since
this interface is only for use with non-hotpluggable devices.)

 

=================================================================

=================================================================

=================================================================

=================================================================

=================================================================

驱动程序模型-platform
 
 
边学边译, 但愿不会因自己理解的错误而误导大家. 欢迎讨论译稿:)

原文请见[url]http://code.google.com/p/linuxkernelchinesedoc/source/browse/trunk/%20linuxkernelchinesedoc/device-model/zplatform.txt[/url]
我的译文如下(已commit):

平台设备和驱动
~~~~~~~~~~~~
在<linux/platform_device.h>中可以找到面向平台总线的驱动模型接口: platform_device和
platform_driver. 平台总是条伪总线,它被用来连接处在仅有最少基本组件的总线上的那些设备.
这样的总线包括许多片上系统上的那些用来整合外设的总线, 也包括一些"古董" PC上的连接器; 但不包
括像PCI或USB这样的有庞大正规说明的总线.

平台设备
~~~~~~
平台设备通常指的是系统中的自治体, 包括老式的基于端口的设备和连接外设总线的北桥(host bridges),
以及集成在片上系统中的绝大多数控制器. 它们通常拥有的一个共同特征是直接编址于CPU总线上. 即使在某
些罕见的情况下, 平台设备会通过某段其他类型的总线连入系统, 它们的寄存器也会被直接编址.

平台设备会分到一个名称(用在驱动绑定中)以及一系列诸如地址和中断请求号(IRQ)之类的资源.[code]struct platform_device {
        const char        *name;
        u32                id;
        struct device        dev;
        u32                num_resources;
        struct resource        *resource;
};[/code]平台驱动
~~~~~~
平台驱动遵循标准驱动模型的规范, 也就是说发现/列举(discovery/enumeration)在驱动之外处理, 而
由驱动提供probe()和remove方法. 平台驱动按标准规范对电源管理和关机通告提供支持.[code]struct platform_driver {
        int (*probe)(struct platform_device *);
        int (*remove)(struct platform_device *);
        void (*shutdown)(struct platform_device *);
        int (*suspend)(struct platform_device *, pm_message_t state);
        int (*suspend_late)(struct platform_device *, pm_message_t state);
        int (*resume_early)(struct platform_device *);
        int (*resume)(struct platform_device *);
        struct device_driver driver;
};[/code]注意probe()总应该核实指定的设备硬件确实存在;平台设置代码有时不能确定这一点. 枚举(probing)
可以使用的设备资源包括时钟及设备的platform_data.
(译注: platform_data定义在device.txt中的"基本设备结构体"中.)

平台驱动通过普通的方法注册自身:[code]int platform_driver_register(struct platform_driver *drv);[/code]或者, 更常见的情况是已知设备不可热插拔, probe()过程便可以驻留在一个初始化区域(init section)
中,以便减少驱动的运行时内存占用(memory footprint):[code]int platform_driver_probe(struct platform_driver *drv,
                          int (*probe)(struct platform_device *));[/code]设备列举
~~~~~~~
按规定, 应由针对平台(也适用于针对板)的设置代码来注册平台设备:[code]int platform_device_register(struct platform_device *pdev);
int platform_add_devices(struct platform_device **pdevs, int ndev);[/code]一般的规则是只注册那些实际存在的设备, 但也有例外. 例如, 某外部网卡未必会装配在所有的板子上,
或者某集成控制器所在的板上可能没挂任何外设, 而内核却需要被配置来支持这些网卡和控制器.

有些情况下, 启动固件(boot firmware)会导出一张装配到板上的设备的描述表. 如果没有这张表, 通常
就只能通过编译针对目标板的内核来让系统设置代码安装正确的设备了. 这种针对板的内核在嵌入式和自定
义的系统开发中是比较常见的.

多数情况下, 分给平台设备的内存和中断请求号资源是不足以让设备正常工作的. 板设置代码通常会用设备
的platform_data域来存放附加信息, 并向外提供它们.

嵌入式系统时常需要为平台设备提供一个或多个时钟信号. 除非被用到, 这些时钟一般处于静息状态以节电.
系统设置代码也负责为设备提供这些时钟, 以便设备能在它们需要是调用
clk_get(&pdev->dev, clock_name).

老式驱动: 设备枚举
~~~~~~~~~~~~~~~~
有些驱动不能被彻底归入驱动模型, 因为它们承担了一个应该由系统基本组建来完成的任务:注册平台设备.
因为热插拔和冷插拔要求由非驱动程序的系统组件来创建设备,所以上述驱动不支持这两种机制.

保留这些驱动的唯一"恰当"的理由是要用它们应付老式的系统设计, 比如原始的IBM PC就依赖一种容易出错
的"枚举硬件(probe-the-hardware)"模型来配置硬件. 新的系统基本上废弃了这种模型, 而倾向对动态
配置的总线级支持(PCI, USB), 或是由启动固件来提供设备描述表(例如x86上的PNPACPI). 关于什么东西
出现在哪儿有太多冲突的可能,即使由操作系统来做有根据的猜测, 也难免因频繁出错而惹麻烦.

(译注: Understanding the Linux Kernel一书的第13.1.1.1节, 提到了"枚举硬件"其中的一段或许
可以用来解释最后一句中所谓的"冲突")
        [quote]尽管访问I/O端口很容易, 检测哪个I/O端口已被分配给I/O设备却并非易事. 对基于ISA总线
(译注:原始IBM PC采用的总线)的系统来说尤其如此. 通常设备驱动必须盲目地写数据到一些
I/O端口来探测设备的存在, 然而,如果该端口已经被另外一种设备占用, 这样的操作就可能导
致系统崩溃...[/quote]

不提倡这种驱动方式. 假如你在升级这样一个驱动, 请尽力把设备列举从驱动中转移到更合适的地方. 这样
做很赚, 因为驱动程序一开始就处在"正常模式", 可以直接使用由即插即用(PNP)设置或平台设备设置代码
所创建的设备..[code]struct platform_device *platform_device_alloc(
                        const char *name, int id);[/code]你可以用platform_device_alloc()来动态地给设备分配空间, 然后在用platform_device_register()
加上一些资源来初始化该设备.

经常也用另外一个更好的解决办法:[code]struct platform_device *platform_device_register_simple(
                        const char *name, int id,
                        struct resource *res, unsigned int nres);[/code]你可以用platform_device_register_simple()一次完成分配空间和注册设备的任务.

设备命名和驱动绑定
~~~~~~~~~~~~~~~
platform_device.dev.bus_id是设备的真名. 它由两部分组成:

        *platform_device.name ... 这也被用来匹配驱动

        *platform_device.id ...        设备实例号, 或者用"-1"表示只有一个设备.

连接这两项, 像"serial"/0就表示bus_id为"serial.0", "serial"/3表示bus_id为"serial.3";
上面二例都将使用名叫"serial"的平台驱动. 而"my_rtc"/-1的bus_id为"my_rtc"(无实例号), 它的
平台驱动为"my_rtc".

在找到一个设备和驱动的配对后, 驱动绑定是通过调用probe()由驱动核心自动完成的. 如果probe()成功,
驱动和设备就正常绑定了. 有三种不同的方法来进行配对:

        -设备一被注册, 就检查对应总线下的各驱动, 看是否匹配. 平台设备应在系统启动过程的早期被注册

        -当驱动通过platform_driver_register()被注册时, 就检查对应总线上所有未绑定的设备.
         驱动通常在启动过程的后期被注册或通过装载模块来注册.

        -用platform_driver_probe()来注册驱动的效果跟用platform_driver_register()几乎
         相同, 不同点仅在于,如果再有设备注册, 驱动就不会再被枚举了. (这无关紧要, 因为这种接口只
         用在不可热插拔的设备上.)

 
总结一下,写主要有两个东西:

platform driver和platform device

platform driver:有两种注册方式,他提供了对应设备的一些操作(probe,remove...)

platform device:需要通过调用platform device register来执行相应设备的操作,两者通过设备名关联,同时paltform device register允许用户传递一些信息给platform driver. 

回目录 Platform Device系列转载收集


文章出处:DIY部落(http://www.diybl.com/course/6_system/linux/Linuxjs/20090317/162105.html)

=================================================================

=================================================================

=================================================================

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值