1. 学习目标

  1. 理解什么是 Platform Device

理解嵌入式设备的特点:

设备直接挂在 SoC 
没有传统总线

例如:

UART 控制器
GPIO 控制器
ADC
PWM
RTC

  • 理解 Platform Driver 的作用

理解 Linux 如何管理这些设备

platform_device
platform_driver
  • 理解驱动匹配机制

理解 Linux 如何匹配设备和驱动:

name match
device tree match

  • 能编写基本 Platform Driver

掌握核心函数:

platform_driver_register
probe
remove
  • 能从 Device Tree 获取硬件资源

掌握:

寄存器地址
IRQ
GPIO

2. 为什么需要 Platform Driver

PC 系统设备通常通过总线连接:

PCI
USB
SATA

设备可以自动枚举:

PCI Scan

但嵌入式系统不同。

设备通常是:

SoC 内部设备

例如:

UART controller
I2C controller
SPI controller

这些设备:

地址固定
不会自动发现

因此 Linux 需要一种机制描述它们:

platform device

3. Platform 驱动整体结构

Platform 设备模型:

Platform Bus
     
     ├── platform_device
     
     └── platform_driver

匹配流程:

platform_device
        
         match
        
platform_driver
        
        
probe()

4. Platform 设备结构

Platform 设备结构:

struct platform_device
{
    const char *name;
    int id;
    struct device dev;
};

核心成员

name

用于匹配 driver

5. Platform Driver 结构

驱动结构:

struct platform_driver
{
    int (*probe)(struct platform_device *);
    int (*remove)(struct platform_device *);

    struct device_driver driver;
};

核心函数:

probe
remove

6. Platform 驱动匹配机制

Linux 会匹配:

platform_device
platform_driver

匹配方式:

1 name match

device.name == driver.name

2 device tree match

使用:

compatible

例如:

compatible = "my-uart";

7. Platform Driver 生命周期

完整流程:

driver register
      
device register
      
driver match
      
probe()
      
device running
      
remove()

8. probe 函数

当设备匹配成功时:

probe()

被调用。

函数:

int probe(struct platform_device *pdev)

主要工作:

获取资源
初始化硬件
注册设备

9. remove 函数

驱动卸载时调用:

int remove(struct platform_device *pdev)

主要工作:

释放资源
关闭设备

10. Platform 资源(Resource)

设备资源包括:

寄存器地址
IRQ
DMA

Linux 使用:

struct resource

表示资源。


获取寄存器地址

platform_get_resource()

示例:

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

映射寄存器

ioremap()

示例:

base = devm_ioremap_resource(&pdev->dev,res);

获取中断

platform_get_irq()

示例:

irq = platform_get_irq(pdev,0);

11. Platform Driver 示例

简单 Platform 驱动:

static int my_probe(struct platform_device *pdev)
{
    printk("platform driver probe\n");
    return 0;
}

static int my_remove(struct platform_device *pdev)
{
    printk("platform driver remove\n");
    return 0;
}

static struct platform_driver my_driver =
{
    .probe = my_probe,
    .remove = my_remove,
    .driver =
    {
        .name = "my_device",
    },
};

module_platform_driver(my_driver);

12. Device Tree 与 Platform Driver

在嵌入式系统中:

设备通常来自 Device Tree

示例:

uart0: serial@10000000
{
    compatible = "my-uart";
    reg = <0x10000000 0x1000>;
    interrupts = <5>;
};

驱动匹配:

static const struct of_device_id my_of_match[] =
{
    { .compatible = "my-uart" },
    { }
};

注册:

.driver = {
    .name = "my_uart",
    .of_match_table = my_of_match,
}

13. Platform Driver 完整流程

完整流程:

Device Tree
     
     
platform_device
     
     
platform bus
     
     
platform_driver
     
     
probe()

14. 驱动常见问题

probe没有调用

原因:

compatible 不匹配

resource获取失败

原因:

device tree错误

ioremap失败

原因:

地址错误

15. 总结

Platform 驱动核心结构:

Device Tree
      
platform_device
      
platform_bus
      
platform_driver
      
probe()
      
Driver

最重要原则:

设备描述  Device Tree
驱动实现  Platform Driver

16. Q&A

16.1 基础理解

  1. 为什么嵌入式 Linux 使用 platform driver?

  2. platform device 和 platform driver 的关系?


16.2 匹配机制

  1. compatible 的作用是什么?

  2. probe 为什么会被调用?


16.3 资源管理

  1. platform_get_resource 做什么?

  2. 为什么需要 ioremap?