## Plantform Devices
### Platform Device 是什麼?
在 Linux 裡,Platform Device 是一種專門用來描述 SoC(System on Chip)或嵌入式板子上固定存在的硬體裝置 的機制。
這些裝置不像 PCI、USB 那樣能「自動偵測」,
例如:UART、SPI、I²C 控制器、GPIO、NAND、LED、Timer...
👉 Platform Device 就是用來表示「這塊板上有哪些固定硬體」的資料結構。
#### Platform Device / Driver 架構概念
Linux 採用「裝置–驅動」模型:
* Platform Device:描述硬體(誰存在)
* Platform Driver:定義操作硬體的方法(怎麼用)
其中 kernel 是使用 Platform Bus(平台匯流排)來人工登錄與匹配並連結 Platform Device 與 Platform Driver,兩者主要是透過「名字(name)」或者「Device Tree 的 compatible 屬性」來配對。
當 platform_device_register() 和 platform_driver_register() 都被呼叫後,kernel 的 platform bus 會自動比對名稱,找到相同的就呼叫該 driver 的 probe()。
當配對成功時,kernel 會呼叫 driver 的 probe() 進行初始化。
#### Platform Device 結構
```javascript=
#include <linux/platform_device.h>
struct platform_device {
const char *name; // 用來和 driver 匹配
int id; // 若有多個相同裝置,用 id 區分
struct device dev; // 通用 device 結構(在 sysfs 中代表這個裝置)
u32 num_resources; // 資源數量
struct resource *resource; // 設備用的硬體資源
};
```
常見資源類型
```javascript=
struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags; // IORESOURCE_MEM, IORESOURCE_IRQ ...
};
```
#### Platform Driver 結構
```javascript=
struct platform_driver {
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
struct device_driver driver; // 包含名字、匹配表等資訊
};
```
### Platform Driver 註冊流程
1. 註冊 platform device
* kernel(或 board code / Device Tree)宣告有這個硬體
2. 註冊 platform driver
* 驅動程式寫好後呼叫 platform_driver_register()
3. kernel 比對 name / compatible
* 若相符 → 呼叫 driver 的 probe()
* 若移除 → 呼叫 driver 的 remove()
#### 手動建立 Platform Device 範例(C code 版本)
舊式嵌入式板子常用這種「靜態註冊」方式(不用 Device Tree)
* Device =
```javascript=
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
static struct resource joey_resources[] = {
[0] = {
.start = 0x10000000,
.end = 0x10000FFF,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 42,
.end = 42,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device joey_device = {
.name = "joey_platform",
.id = -1,
.num_resources = ARRAY_SIZE(joey_resources),
.resource = joey_resources,
};
```
* Driver =
```javascript =
static int joey_probe(struct platform_device *pdev)
{
struct resource *res;
void __iomem *base;
printk(KERN_INFO "joey_platform: probe()\n");
// 取得記憶體資源
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = ioremap(res->start, resource_size(res));
if (!base)
return -ENOMEM;
printk(KERN_INFO "Mapped I/O base = %p\n", base);
iounmap(base);
return 0;
}
static int joey_remove(struct platform_device *pdev)
{
printk(KERN_INFO "joey_platform: remove()\n");
return 0;
}
static struct platform_driver joey_driver = {
.probe = joey_probe,
.remove = joey_remove,
.driver = {
.name = "joey_platform",
.owner = THIS_MODULE,
},
};
static int __init joey_init(void)
{
platform_device_register(&joey_device);
platform_driver_register(&joey_driver);
return 0;
}
static void __exit joey_exit(void)
{
platform_driver_unregister(&joey_driver);
platform_device_unregister(&joey_device);
}
module_init(joey_init);
module_exit(joey_exit);
MODULE_LICENSE("GPL");
```
### Device Tree 版本(現代用法)
在 ARM、RISC-V 平台上,platform device 通常由 Device Tree (.dts) 自動建立:
```javascript =
Device Tree 片段:
joey_device@10000000 {
compatible = "joey,mydevice";
reg = <0x10000000 0x1000>;
interrupts = <42>;
status = "okay";
};
Driver 端:
static const struct of_device_id joey_of_match[] = {
{ .compatible = "joey,mydevice" },
{},
};
MODULE_DEVICE_TABLE(of, joey_of_match);
static struct platform_driver joey_driver = {
.probe = joey_probe,
.remove = joey_remove,
.driver = {
.name = "joey_driver",
.of_match_table = joey_of_match,
},
};
```
這樣 kernel 啟動時會:
1. 解析 Device Tree → 產生 platform_device
2. 尋找 matching driver(compatible 一致)
3. 呼叫 probe() 進行初始化
### 總結重點
與其他裝置模型相比常使用於內建裝置
| 類型 | 自動偵測 | 典型用途 | 範例 |
| ------------ | ---- | -------- | --------------- |
| **PCI** | ✅ | 外掛式裝置 | 網卡、顯卡 |
| **USB** | ✅ | 可插拔 | USB 隨身碟 |
| **Platform** | ❌ | SoC 內建裝置 | UART、GPIO、Timer |
| **Misc** | ❌ | 簡單軟體裝置 | watchdog、uinput |
Platform Device 機制被廣泛應用在:
* SoC 內部控制器(I2C, SPI, UART, GPIO)
* 驅動字元裝置(char device)
* Power management(suspend/resume callbacks)
* Device Tree 硬體抽象層
總結:
| 重點 | 說明 |
| --------------- | ----------------------------------------------------------- |
| Platform Device | 描述「板上固定硬體」 |
| Platform Driver | 控制硬體的程式邏輯 |
| 配對方式 | name 或 Device Tree 的 compatible |
| 註冊函式 | `platform_device_register()` / `platform_driver_register()` |
| 典型操作 | `ioremap()`、`platform_get_resource()`、`devm_*()` 系列 |