Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1225207
  • 博文数量: 105
  • 博客积分: 127
  • 博客等级: 入伍新兵
  • 技术积分: 962
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-29 15:22
文章分类

全部博文(105)

文章存档

2021年(1)

2019年(3)

2018年(1)

2017年(11)

2016年(47)

2015年(32)

2014年(4)

2012年(6)

我的朋友

分类: LINUX

2015-06-19 16:21:05

原文地址:linux-2.6.35.3\Documentation\driver-model\platform.txt

NOTE : platform 很多人将它翻译成平台,未尝不可,但个人觉得怪怪的,这里这个名词,还是直接用作platform

原文:
Platform Devices and Drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See 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.

Platform 设备和驱动

关于platform 总线的驱动模型接口在 中:platform_device platform_driver . 这条虚拟总线是用于连接设备到小系统,像那些片上系统用于外围设备整合在一起的,或者一些”过气”的PC内部连接;相对于那些大型正式的PCI 或 USB接口。 

Platform 设备

平台设备是这些出现在系统上的自发实体设备。包括老式的基于端口的设备和主机总线外围桥,和在片上系统的大多数集成控制器平台。他们的共同点是直接从CPU总线寻址。一般很少,一个平台设备连接到其他总线上;即使这样,它的注册还是可以直接寻址的。

平台设备都有一个名称,用于与驱动绑定,和一些包括例如地址,中断。

点击(此处)折叠或打开

  1. struct platform_device {
  2.     const char    *name;
  3.     u32        id;
  4.     struct device    dev;
  5.     u32        num_resources;
  6.     struct resource    *resource;
  7. };

原文:
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 *))

Platform 驱动

平台驱动是按照标准的驱动模型协议来的,列举/枚举都是在驱动之外实现的,驱动只是提供probe()remove() 方法,在驱动加载与卸载时调用。支持标准的电源管理和关机通知。

点击(此处)折叠或打开

  1. struct platform_driver {
  2.     int (*probe)(struct platform_device *);
  3.     int (*remove)(struct platform_device *);
  4.     void (*shutdown)(struct platform_device *);
  5.     int (*suspend)(struct platform_device *, pm_message_t state);
  6.     int (*suspend_late)(struct platform_device *, pm_message_t state);
  7.     int (*resume_early)(struct platform_device *);
  8.     int (*resume)(struct platform_device *);
  9.     struct device_driver driver;
  10. };

注意,probe()一般需要验证设备硬件的真实存在;有时候平台设置代码不能确定。Probe 可以使用设备资源,包括时钟,平台设备的platform_data(这个用来传递资源,将device 与 driver建立起一种联系)

设备驱动注册的一般方法:

点击(此处)折叠或打开

  1. int platform_driver_register(struct platform_driver *drv);

或者,在那些不支持热插拔设备的情况下,probe()为了减少运行时的内存占用,一般放在int段:


点击(此处)折叠或打开

  1. int platform_driver_probe(struct platform_driver *drv,
  2. 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.


设备枚举

一般来说,platform具体的代码注册平台设备:

int platform_device_register(struct platform_device *pdev);

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

通常是注册那些真实存在的设备,但有些额外的设备也有可能被注册。例如,内核可能配置一个所有板都没有的一个外部网络适配器(感觉是不是类似于PHY的公版?),同样的可能配置没有任何外设的集成控制器。

在一些情况下,在一个既定的板上,固件应该给出一个板上的设备描述表。如果没有这个表,对于设置正确设备的系统设置代码,惟一的方法是只能为一个特定的目标板编译内核。这种具体的板级内核,在嵌入式
与客户自己的开发板中是比较常见的。

在许多情况下,将内存和IRQ 资源与平台设备关联起来,还不足以让设备驱动工作起来。所以在板级设置代码中,经常通过platform_data 来传递一些其他的附加信息。

嵌入式系统平台设备经常需要一个到多个时钟,经常是直到需要激活时才激活(不需要时不激活,低功耗)。系统设置中也会关联那些设备时钟,通过调用clk_get(&pdev->dev, clock_name)来得返回。


原文:
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.)

老式驱动:设备探测

一些驱动还没有转换为驱动模型,因为他们扮演的一个非标准的角色:驱动注册其平台设备,而不是让这个系统的基础设施。对于那些不支持热插拔或冷插拔的驱动,这种机制要求以一种除驱动方式以外的系
统组件方式来创建设备。这个唯一 “好”的原因是处理老式系统设计,像IBM PCs,依靠易错“探测硬件”模型来配置硬件。新的系统已经放弃了这种方式,而被动态配置(PCI,USB),或由启动固件提供的设备表
PNPACPI on x86)。这里有太多的冲突会带来麻烦,关于可能会在哪里,甚至操作系统合理的猜测出错。(没搞懂)

这种方式的驱动是乏味的。如果你在更新这样一个驱动,请试着将设备枚举放到一个合理的位置。这通常会被清理,因为这样的驱动已经有了“正常”模式,例如被PNP或平台设备设置所使用的设备节点。

多多少少,还是有一些老式驱动的APIs。要避免使用这类APIs的调用,除了在那些有缺陷的驱动中。

点击(此处)折叠或打开

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

你可以使用platform_device_alloc()动态分配一个设备,然后可以使用相关资源进行初使化,调用platform_device_register()。通常一个更好的解决方法是:

点击(此处)折叠或打开

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

你可以使用platform_device_register_simple()作为一步调用来进行分配和注册设备。


原文:
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_device.dev.bus_id 是设备规范的名字。两个组件中被建立:

    * 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.

这些都是级联的,所以name/id "serial"/0 表明bus_id "serial.0", 

"serial/3" 表明bus_id "serial.3"platform_driver 都将命名为 "serial"。当"my_rtc"/-1 应该对应的是bus_id "my_rtc"(没有实例ID),platform_driver也将使用"my_rtc"

驱动绑定是由驱动核心自动执行完成的,当设备与驱动之间匹配后调用驱动程序probe()。如果probe()调用成功后,驱动与设备就绑定成功了。找到匹配有三种不同的方法:

-无论什么时候一个设备被注册时,那条总线的驱动都会检测是否匹配。平台设备可以在系统启动很早的时候就被注册。

-当一个驱动用platform_driver_register()注册时,在那条总线上的所有的未绑定的设备都会被检测一次是否匹配。驱动经常在启动过程中较晚的时候,或者以模块的方式插入。

-当用platform_driver_probe()注册驱动时,其实就相当于用platform_driver_register()注册,只是这个驱动在这之后将不被探测,当其他的设备被注册时。(这种接口方式对于
    那些非热插拔的设备来说是可以用的。)


原文:
Early Platform Devices and Drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The early platform interfaces provide platform data to platform device
drivers early on during the system boot. The code is built on top of the
early_param() command line parsing and can be executed very early on.

Example: "earlyprintk" class early serial console in 6 steps

1. Registering early platform device data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The architecture code registers platform device data using the function
early_platform_add_devices(). In the case of early serial console this
should be hardware configuration for the serial port. Devices registered
at this point will later on be matched against early platform drivers.

2. Parsing kernel command line
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The architecture code calls parse_early_param() to parse the kernel
command line. This will execute all matching early_param() callbacks.
User specified early platform devices will be registered at this point.
For the early serial console case the user can specify port on the
kernel command line as "earlyprintk=serial.0" where "earlyprintk" is
the class string, "serial" is the name of the platform driver and
0 is the platform device id. If the id is -1 then the dot and the
id can be omitted.

3. Installing early platform drivers belonging to a certain class
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The architecture code may optionally force registration of all early
platform drivers belonging to a certain class using the function
early_platform_driver_register_all(). User specified devices from
step 2 have priority over these. This step is omitted by the serial
driver example since the early serial driver code should be disabled
unless the user has specified port on the kernel command line.

4. Early platform driver registration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Compiled-in platform drivers making use of early_platform_init() are
automatically registered during step 2 or 3. The serial driver example
should use early_platform_init("earlyprintk", &platform_driver).

5. Probing of early platform drivers belonging to a certain class
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The architecture code calls early_platform_driver_probe() to match
registered early platform devices associated with a certain class with
registered early platform drivers. Matched devices will get probed().
This step can be executed at any point during the early boot. As soon
as possible may be good for the serial port case.

6. Inside the early platform driver probe()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The driver code needs to take special care during early boot, especially
when it comes to memory allocation and interrupt registration. The code
in the probe() function can use is_early_platform_device() to check if
it is called at early platform device or at the regular platform device
time. The early serial driver performs register_console() at this point.

For further information, see .

早期的(启动过程中)平台设备和驱动

在很早的平台接口,在系统启动过程中较早的时候提供平台数据给平台设备驱动。那些代码是建立在early_param()的顶部,这样就可以使得命令行解析很早就可以使用。

例如:"earlyprintk" 在六点关于早期调试串口控制台。

 

1 .注册早期平台设备数据

体系结构相关的代码采用early_platform_add_devices()函数来实现注册平台设备数据。早阶段的串口控制台其实就是对串行端口的硬件配置。在这个时候注册的设备,稍后将会与早阶段的平台驱动相匹配。

2 .解析内核命令行

体系结构相关的代码调用parse_early_param()去解析内核命令行。这将执行所有匹配early_param()回调函数。在这个时候用户指定的早阶段的平台设备将被注册。早阶段的串口控制台,用户可以在内核命令行中指定串口端口,"earlyprintk=serial.0" "serial"是平台驱动的名字,0是平台的设备ID。如果ID-1,那么那个点和id将被忽略。

 

3 .安装早期平台驱动

体系结构代码可以注册所有的早阶段的平台驱动,通过使用函数early_platform_driver_register_all()将其挂到某一类上。步骤2中用户指定的设备优先于这些。如果内核命令行中没有指定端口,早阶段的串口驱动将被禁用,那么这一步也将是被忽略的。


4 .
早阶段平台驱动注册

在步骤23中,利用early_platform_init()注册的平台驱动将被自动调用,串行驱动程序的例子应该使用early_platform_init(“earlyprintk”,与platform_driver)。

 

5 .探测早阶段平台驱动

体系结构代码将调用early_platform_driver_probe()去匹配早阶段的设备与早阶段的驱动。被匹配的设备将调用probed()。这一步将在启动的任何时候可能被执行。对于串口控制台来说,是越早越好。

 

6 .在早阶段平台驱动probe

驱动代码在早阶段的启动过程需要特别留意,特别是内存分配,中断注册等。在probe ()函数中代码,可以调用early_platform_device()来检查该设备是早阶段平台设备,还是一般的平台设备。早期的串口驱动在这个时候是调用register_console() 

 

想了解更多的信息,请查看


阅读(7393) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~