## 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_*()` 系列 |