[Linux driver]揭秘platform_driver, platform_device

嵌入式Linux设备树(DTS)详解:从硬件描述到驱动匹配的完整指南 在嵌入式Linux开发中,硬件描述与驱动匹配是系统启动和运行的基础。传统的内核硬编码方式将硬件信息直接写入驱动代码,导致内核镜像与特定硬件板卡强耦合,难以适配多种硬件变体。设备树(Device Tree)技术应运而生,其核心原理是将硬件描述从内核代码中剥离,形成独立的、结构化的配置文件(DTS文件),实现硬件描述的“软配置”。这一机制为内核提供了标准化的硬件清单,使得同一内核镜像能够动态适配不同外设配置的板卡,极大地提升了代码的复用性和可维护性。其技术价值在于实现了硬件与驱动解耦,支持模块化开发和分层描述( 阅读详情

Platform的出现,如同PCI总线一样,把没有“领导层”的设备全部纳入麾下,是个收养所,

专门收养如SPI I2C等连接多slave设备的微型总线,这样一来,linux的sysfs以及kobj内核管理数据结构

就可以很好的管理这些微总线,把他们出现在fs下面供用户查看其状态,也便于统一的进行电源管理工作;

下面是platform的原文介绍:

 

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 tobuild

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

 

 

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 <linux/platform_device.h>.

 

 

C语言的魔法时刻:Linux驱动中的面向对象思想揭秘 C语言中的面向对象思想:Linux驱动设计精要 本文深入剖析了Linux内核中platform_driver结构体所体现的面向对象编程思想。通过分析这一常见驱动接口,揭示了其在C语言环境下实现的三大面向对象特性: 封装:将驱动操作函数指针与属性数据统一封装在结构体中,形成清晰的接口边界 继承:通过结构体嵌套和container_of宏实现类继承关系,复用通用驱动管理代码 多态:利用函数指针表实现运行时动态绑定,同一接口支持不同设备驱动的具体实现 阅读详情

相关推荐

浅谈武术擂台格斗机器人大赛

武术擂台机器人赛是工科类专业的一个跨学科的竞赛项目,它涵盖了机械结构、硬件电路和计算机程序等技术领域。笔者在校期间有幸参加过四次这样的比赛,有成功也有失败,对此深有感悟。本文仅为个人观点,有说得不对的地方,望积极指出,希望能帮助到有需要的人。

weixin_43811044的博客 1万+

platform_device 和 platform_driver 驱动管理(转载)

从Linux 2.6起引入了一套新的驱动管理和注册机制:Platform_device和Platform_driver。Linux中大部分的设备驱动,都可以使用这套机制, 设备用Platform_device表示,驱动用Platform_driver进行注册。Linux platform driver机制和传统的device driver 机制(通过driver_register函数进行注册)相比,一个十分明显的优势在于platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序中使用这些资源

woniuguilai的专栏 929

[Unity]-[UI]-[Image] 关于UI精灵图资源导入设置的详细解释

如果纹理存储了有特定含义的信息,并且您需要着色器中的确切值(例如,平滑度或金属度),请禁用此属性。此选项允许将纹理编码为特定格式(RGBM 或 dLDR,具体取决于平台)并通过后期处理步骤对纹理数据进行处理(推拉式扩张通道)。使用在3D模型的专业法线贴图。通用的纹理类型,一般在Material上的材质图片参数使用,比如漫反射、法线贴图这些。​​Compression​​:ASTC 6x6(移动端)或DXT5(PC)​​Compression​​:BC5(PC)或ASTC 6x6(移动端)

sky_smile_Allen的博客 2171

ubuntu18.04安装时ACPI error 无法进入系统的问题

问题描述:安装系统时无法进入图形界面 出现 一堆错误 布拉布拉布拉 [0.101261] ACPI Error: [_ppc] Namespace lookup failure, AE_ALREADY_EXISTS (20170531/dswload-378) [0.101268] ACPI Exception: AE_ALREADY_EXISTS, During name lookup...

weixin_30480075的博客 1万+

Codesys 3.5报警功能配置保姆级教程:从变量定义到确认方式(含REF/ACK详解)

本文详细介绍了Codesys 3.5报警功能的配置流程,从变量定义到确认方式的选择,特别解析了REF和ACK两种确认方式的底层逻辑。通过实战案例和代码示例,帮助工程师快速掌握报警系统的搭建与调试技巧,提升工业自动化项目的可靠性。

weixin_29245767的博客 458

微信小程序获取用户手机号全流程实战(附完整代码)

本文详细介绍了微信小程序获取用户手机号的全流程实战,包括前端授权、后端解密及安全合规要点。通过传统授权按钮和新版手机号快速验证组件两种方案,帮助开发者高效实现功能,并附完整代码示例。重点解析了微信小程序接口的使用技巧和常见问题解决方案,确保数据安全与用户体验。

weixin_29280219的博客 568

Linux 下 platform 设备驱动

在Linux2.6 以后的设备驱动模型中,需要关心总线、设备和驱动3个实体,总线将设备和驱动绑定。在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反 ,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。 一个现实的Linux 设备和驱动通常都需要挂接在一种总线上,对于本身依附于PCI、USB、I2C、SPI等的设备而言,这自然不是问题,但是在嵌入式系统里面,在SoC系统中...

weixin_42005898的博客 569

dolphinscheduler集群服务一键安装启动实现流程剖析

通过以上分析我们基本梳理清楚了整个dolphinscheduler项目的一键安装启动逻辑, 我们现在在通过一张图正好理一下整个实现流程。关于一键停止集群服务及一件查询集群各个角色服务实例运行状态的实现也都在stop-all.sh/status-all.sh及dolphinscheduler-daemon.sh这三个脚本中, 有兴趣自行研究。写这篇文章的核心目的不仅在于给大家分享如何优秀的开源项目的一键安装部署的实现过程。

最爱嫣夜来 1207

关于platform_device一些讲解

从2.6版本开始引入了platform这个概念,在开发底层驱动程序时,首先要确认的就是设备的资源信息,例如设备的地址, 在2.6内核中将每个设备的资源用结构platform_device来描述,该结构体定义在kernel\include\linux\platform_device.h中: struct platform_device { const char * name; u32 id; struct device dev; u32 num_resources; struct resou

Gick 6361

Visual Studio调试技巧与实用方法总结(实战经验分享)

本文根据多年的项目实战经验,详细介绍一些Visual Studio常用的高效调试手段与技巧。

dvlinker的技术专栏 3万+

[deprecated]第四章:TTM分析: 4.2.1 存储分配ttm_bo_validate功能实现分析

ttm_bo_validate是TTM框架中负责验证和调整BufferObject物理内存分配的核心函数,主要用于显存管理。该函数通过placement参数判断BO是否需要迁移或重新分配资源,完成内存分配、迁移及缓存策略调整等操作。实现流程包括资源释放、兼容性检查、迁移保护、新资源分配、迁移实现等步骤,支持多跳迁移和临时缓冲区。典型应用于显存溢出迁移、缓存策略调整、驱动初始化等场景,确保BO始终处于预期状态。

图形/计算GPU的驱动与虚拟化技术分享园地 842

内核ACPI函数API之acpi_create_platform_device

acpi_create_platform_device 这个函数会为没有platform_driver 自动创建platform_device设备。只有当用户只调用register_platform_driver就可以匹配device和driver 其源码分析如下: struct platform_device *acpi_create_platform_device(struct acpi_de...

jason的笔记 1123

AUTOSAR内存篇 -内存驱动(Mem)

Mem驱动程序的task是基于底层内存设备技术的物理分段的低级内存访问。Mem驱动程序的API与内存设备技术无关,因此向存储器访问模块上层提供了与存储器设备无关的接口。所有高级功能(如跨段操作)都由内存访问模块处理,以尽可能降低Mem驱动器的复杂性和占用空间。Mem驱动API命名、类型定义和文件命名规则都遵循标准的AUTUSAR BSW模块实现。服务Mem_Init初始化Mem驱动的内部状态,并设置Mem驱动Job处理状态到MEM_JOB_OK。

IOT2017的博客 713

Linux-2.6.38的LCD驱动分析(二)

Linux-2.6.38的LCD驱动分析(二) 参考自:http://blog.chinaunix.net/uid-11114210-id-2907026.html 二、s3cfb_probe函数分析 2.1 驱动的入口点     摆在面前的第一个问题相信应该是,这个函数是从那里开始运行的。这里就应该从long long ago 开始了,打开linux-2.

LL-Studio的专栏 3141

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Linux内核中ideapad-laptop.c文件全解析2

Linux内核中ideapad-laptop.c文件全解析2

phmatthaus的专栏 801

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Linux-2.6.20的LCD驱动分析(二)

二、s3c2410fb_probe函数分析 2.1驱动的入口点 摆在面前的第一个问题相信应该是,这个函数是从那里开始运行的。这里就应该从long long ago开始了,打开drivers/video/s3c2410fb.c文件,然后找到s3c2410fb_init函数,先不管它里面是怎么回事,再把目光下移就会看到这样一串字符串module_init(s3c2410fb_init),郁闷,这和

zhuxw技术博客 404

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

设备树与驱动模型的深度对话:揭秘Linux内核如何‘看见’硬件

本文深入探讨了Linux内核中设备树(Device Tree)与驱动模型的协同工作机制,揭示了内核如何通过设备树解析、compatible字符串匹配和资源分配来‘看见’并初始化硬件。重点分析了设备树语法、reg和irq资源解析,以及其与platform_driver的匹配逻辑,为嵌入式Linux开发者提供深度技术洞察。

tensor9flow的博客 180

揭秘嵌入式Linux设备树配置:如何高效编写C语言驱动并加载内核模块

掌握嵌入式 Linux 的 C 语言驱动开发(设备树 + 内核模块),本文详解设备树配置与驱动编写方法,适用于ARM平台驱动调试与模块加载。涵盖DTS解析、platform驱动匹配及编译加载流程,提升开发效率,值得收藏。

SimProceed的博客 969

揭秘嵌入式C语言驱动设计:如何用设备树与内核模块打造高效系统

掌握嵌入式Linux的C语言驱动开发(设备树+内核模块),轻松实现硬件高效控制。适用于智能设备、工业自动化等场景,通过设备树描述硬件、内核模块编写驱动,提升系统可维护性与移植性。方法清晰实用,值得收藏。

BreakVein的博客 1026

amlogic-s9xxx-armbian深度解析:全志H6机顶盒网络适配架构揭秘与实战优化

在开源硬件社区中,将Armbian系统移植到Amlogic、全志和Rockchip设备一直是技术爱好者的核心挑战。amlogic-s9xxx-armbian项目为这些设备提供了完整的Armbian运行支持,但在实际部署中,全志H6芯片的网络适配问题成为许多用户面临的技术瓶颈。本文将深入解析全志H6机顶盒在Armbian系统中的网络适配技术架构,提供从现象诊断到根本解决的完整解决方案。 ## 🎯

gitblog_00876的博客 1080

embassy-net-tuntap:在 Linux TUN/TAP 接口上运行 embassy-net 网络栈

`embassy-net-tuntap` 是 Embassy 生态中为 Linux TUN/TAP 虚拟网络接口提供 `embassy-net` 驱动的 crate,它让同一个异步网络栈可以运行在 `std` 桌面/服务器平台上,用于开发、调试、仿真与测试嵌入式网络应用。读完本文你将掌握如何创建 TAP 接口、在 Rust 中初始化 `TunTapDevice` 并将其接入 `embassy-ne

gitblog_00433的博客 396

Linux-2.6.20的LCD驱动分析(二)[转]

二、s3c2410fb_probe函数分析2.1 驱动的入口点摆在面前的第一个问题相信应该是,这个函数是从那里开始运行的。这里就应该从long long ago 开始了,打开drivers/video/s3c2410fb.c文件,然后找到s3c2410fb_init函数,先不管它里面是怎么回事,再把目光下移就会看到这样一串字符串module_init(s3c2410fb_init),郁闷,

Harrison_zhu的专栏 3479

如何在LightGBM中启用GPU加速:快速提升机器学习训练性能的完整指南

还在为LightGBM训练大型数据集时的漫长等待而烦恼吗?想要让机器学习模型的训练速度提升数十倍甚至百倍吗?本文将为你揭秘LightGBM GPU加速的完整实现方案,让你轻松掌握这项强大的性能优化技术。LightGBM是一个基于决策树算法的高性能梯度提升框架,广泛用于排序、分类等机器学习任务,而GPU加速正是其最强大的性能优化功能之一。 ## GPU加速的核心价值与工作原理 LightGBM的

gitblog_01199的博客 828

UART回环测试假通过?揭秘LCR、DLAB、MCR寄存器级陷阱

UART是一种基础但易出错的异步串行通信协议,其可靠性高度依赖寄存器配置与信号完整性。理解LCR(线控寄存器)如何控制数据格式、DLAB(分频锁存访问位)如何开关波特率寄存器访问、MCR(调制解调器控制寄存器)如何启用硬件回环,是定位‘回环通过但实际通信失败’问题的核心。这些底层机制决定了UART在内部回环、外部硬件回环及USB桥接回环等不同模式下的行为差异,直接影响电平兼容性、波特率精度和抗干扰能力。本文聚焦嵌入式系统中高频发生的UART假阳性现象,结合寄存器快照、示波器眼图与产线实测案例,为硬件工程师、

weixin_33991418的博客 414
上一篇: [Linux driver]解密module_init
下一篇: [Linux driver] Mutex, semaphore, spinlock的深度解析
embedded_man2011
博客等级 码龄16年 15粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值