driver-model/platform

来源:互联网 发布:伊朗伊斯兰革命知乎 编辑:程序博客网 时间:2024/04/25 13:24
Chinese translated version of Documentation/driver-model/platform


If you have any comment or update to the content, please contact the
original document maintainer directly.  However, if you have a problem
communicating in English you can also ask the Chinese maintainer for
help.  Contact the Chinese maintainer if this translation is outdated
or if there is a problem with the translation.


Chinese maintainer: jinxin <575068677@qq.com>
---------------------------------------------------------------------
Documentation/driver-model/platform 的中文翻译


如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
译存在问题,请联系中文版维护者。


中文版维护者: 金鑫  <575068677.com>
中文版翻译者: 金鑫  <575068677.com>
中文版校译者: 金鑫  <575068677.com>


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.
见<linux/platform_device.h>。平台总线的驱动程序模块接口:平台设备,平台驱动程序。
这种伪总线是用来在总线上连接设备的最小基础设施,像那些用于在许多系统芯片处理器的集成外设,
或一些“遗留”PC互联;而非太正式指定的PCI或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.
平台设备通常指的是那些在系统中看起来有自治能力的设备, 包括老式的基于端口的设备和连接外设总线的
北桥(host bridges),以及在集成芯片平台上的绝大多数控制器. 它们通常拥有的一个共同特征是直接编址于CPU总线上.
偶尔平台设备会通过某段其他类型的总线连入平台, 它们的寄存器也会被直接编址.


Platform devices are given a name, used in driver binding, and a
list of resources such as addresses and IRQs.
平台设备会被分配到一个名字(用于驱动绑定)以及一系列类似地址和中断请求号(IRQ)的资源.




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.
平台驱动遵循以下驱动模型约定,设备发现和设备例举是在驱动外处理的,驱动程序提供
probe()和remove()函数。它们支持通通过标准惯例来实现电源管理和关机通知。


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.
注意使用Probe()函数之前应验证probe()指定设备的硬件确实存在(因为平台设置的代码并不确定)。
Probe()函数可以使用设备的资源包括时钟和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:
或者当知道设备是热设备时,可以把probe()放在init函数中来减小运行时内存的占用。
    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.
在某些时候,固件引导启动时候会输出一张描述所有连接在板子上设备的表。
如果没有这张表,正确启动系统代码的唯一方法是为板子编译一个特定的内核。
这种board-specific内核广泛应用在嵌入和普通系统开发上。


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.
通常,内存和IRQ(中断请求)资源和平台联系在一起并不足够让设备驱动工作。板设置代码
还需要用设备的platform_data提供额外的信息。


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.
嵌入式系统为了平台设备频繁的需要一个或者多个时钟,这些时钟通常只有在
需要的时候才会被打开(为了省电)。系统启动时通过设备联系和设置这些时钟,
通过clk_get(&pdev->dev, clock_name)来得到需要的时钟。


Legacy Drivers:  Device Probing
Legacy Drivers:设备检测


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
一些驱动不会完全的按照驱动模式来执行,因为他们扮演出一个non-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.
这种驱动的唯一好处是可以用来处理一些老的系统,像最初的IBM PC,依靠硬件结构上
易于出错的"probe-the-hardware"模式。新的系统已经很大程度上遗弃了那种模式,新的系统
对bus-level提供了动态配置(PCI,USB),或者对设备表提供了引导固件(例如x86上的PNPACPI)。
关于使用什么驱动,在哪里使用有许许多多的有冲突的配置选项,甚至操作系统有根据的推测
也可能出错造成麻烦。


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.
这种类型的驱动是不鼓励的。如果你在升级这样的一个驱动,请尝试把设备枚举到
驱动外一个更合适的位置。这通常会清除,因为这类的驱动已经拥有了“标准”模式。
就像使用设备节点时被PNP或者平台设备设置创建一样。


None the less, there are some APIs to support such legacy drivers.  Avoid
using these calls except with such hotplug-deficient drivers.
依然,有一些APIs支持这些Legacy Drivers。 在热插拔设备上要避免使用这些APIs。


    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:
你可以用platform_device_alloc()来动态的分配一个设备,用资源和
platform_device_register()来初始化它。 
一个更好的方法是:
    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.
通过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.dev.bus_id是设备的名字,它由两部分组成:
    * platform_device.name ... which is also used to for driver matching.
* platform_device.name ... 是用来设备匹配的
    * platform_device.id ... the device instance number, or else "-1"
      to indicate there's only one.
* platform_device.id ...设备实例号,-1表示同名的设备只有一个。

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".
它们是串级的。如果name/id 是"serial"/0就代表了bus_id 是"serial.0",
如果是"serial/3" 就表示 bus_id 是"serial.3"; 这两个都是用于名字是"serial“的平台
驱动。同时"my_rtc"/-1 表示 bus_id "my_rtc" (没有实例id),平台驱动叫做 "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:
驱动绑定是通过驱动核心自动完成的,在发现了匹配的设备和驱动之后调用
驱动probe()函数。如果probe()函数成功,驱动和设备就照常绑定起来了。
有三种不同的方法来发现设备和驱动之间的匹配。
    - 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.
当一个驱动用platform_driver_register()注册时,所有在对应总线上没有绑定的设备
检查是否有匹配。驱动通常在启动的晚期进行或者模块加载时注册。
    - 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_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.
早期的平台接口在系统启动时提供平台数据和平台设备驱动。代码以
early_param() 命令行分析为基础,能在早期被执行。


Example: "earlyprintk" class early serial console in 6 steps
例子:"earlyprintk"控制台在早期的六步


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.
代码的体系结构用early_platform_add_devices()函数注册平台设备数据。
在早期的情况,串行控制台应该为了串行接口对硬件进行配置。
在这种情况下注册了的设备应该与稍后的平台驱动竞争。


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.
体系结构代码调用parse_early_param()来解析内核命令行。这将会执行所有
匹配的early_param() 回调函数。用户特定的早期平台设备将在这是被注册。
为了早期的串行控制台,用户可以在内核命令行通过像"earlyprintk=serial.0" 
where "earlyprintk"的字符串来指定端口。"serial" 是平台驱动的名字,
0是平台驱动的id。如果id是-1,然后是点,那么id可以忽略。


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.
体系结构代码可能会随意的强迫所有属于一个特定的类的平台驱动用
early_platform_driver_register_all()来注册。用户指定的设备在第2步比
这些平台驱动有更高的权限。这一步被串行驱动忽略,因为早期的串行驱动
程序代码在用户指定内核命令行端口之前不可用。


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).
内编译的平台驱动用early_platform_init()在第2步,第3步自动注册。
串行驱动例子应该用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.
体系结构代码调用early_platform_driver_probe()函数和一个特定的类
来匹配早期注册的平台设备(和一个特定的类)。匹配的设备会得到probed()。
这一步能执行在系统早期的任何时候。尽可能早的执行对串行端口有益。


6. Inside the early platform driver probe()
在早期平台驱动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.
在系统启动的早期驱动代码需要额外的关照,特别是有关内存分配和中断
登记的时候。在probe()函数内的代码能使用is_early_platform_device()来
它是否在平台设备早期还是在长贵的平台设备时间。再起串行驱动在这时执行
register_console()函数。
For further information, see <linux/platform_device.h>.
更多信息请见<linux/platform_device.h>。
原创粉丝点击