在linux使用platform_driver_register() 注冊 platform_driver 時, 需要在 platform_driver 的probe() 里面知道設備的中斷號, 內存地址等資源。 這些資源的描述信息存放在 resource 數據結構中, 相同的資源存放在一個樹形樹形數據結構中, 通過父節點, 兄弟節點, 子節點相連。 比如中斷資源, IO端口資源, IO內存資源, DMA資源有不同資源樹。 Linux使用 struct resource 來描述一個resouce struct resource { resource_size_t start; //資源范圍的開始 resource_size_t end; //資源范圍的結束 const char *name; //資源擁有者名 unsigned long flags; //資源屬性標識 struct resource *parent, *sibling, *child; //資源樹的父節點, 兄弟節點, 字節點指針 }; resource_size_t 由系統決定 為uint32_t 或uint64_t 。 在platform機制里, 使用platform_get_resource()來獲取指定的資源類型。 比如獲取想獲取中斷號, irq = platform_get_irq(pdev, 0); int platform_get_irq(struct platform_device *dev, unsigned int num) { struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); return r ? r->start : -ENXIO; } EXPORT_SYMBOL_GPL(platform_get_irq); platform_get_irq() 會返回一個start, 即可用的中斷號。 之后便可使用request_irq() 來注冊中斷服務函數。 再比如想要獲取IO內存資源: struct resource *res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 即可得到一個IO內存資源節點指針, 包括了地址的開始,結束地址等, 該IO內存的長度可用 resource_size() 來獲取, 但這段資源只是一個描述, 想真正使用這段IO內存, 還要經過先申請, 再映射的過程。例如可使用devm_request_mem_region()申請出使用這段IO內存, 再使用ioremap() 將其映射出來, 供用戶空間使用。 devm_request_mem_region(&pdev->dev, res_mem->start, resource_size(res_mem), res_mem->name)) addr_start = ioremap(res_mem->start, resource_size(res_mem)); ioremap() 的返回值即為該資源的虛擬地址。 IO內存的資源是在設備樹源(Device Tree Source)文件(以.dts結尾)里給出的,.dts文件就是用來描述目標板硬件信息的, 在uboot啟動后, 使用uboot提供的特定API將其獲取出來, 如fdt_getprop(), fdt_path_offset(), 這些API包含在uboot 的頭文件 里面。 uboot將.dts文件里的描述解析出來, 再對相應寄存器賦值, 在linux啟動后, 使用 platform_get_resource() 即可獲取到這些給定的資源, 在驅動里使用。 例如一個在.dts文件中關于gpio資源的描述: gpio: gpio-controller@1070000000800 { #gpio-cells = <2>; compatible = "cavium,octeon-3860-gpio"; reg = <0x10700 0x00000800 0x0 0x100>; gpio-controller; … 根據其描述, 可知道gpio控制器的IO內存起始地址為:0x107900000800, 長度為0x100. 即從 0x107900000800 到 0x1079000008ff. 在目標板里使用 cat /proc/iomem 可以看到: 1070000000800-10700000008ff : /soc@0/gpio-controller@1070000000800 關于i2c 的描述: twsi0: i2c@1180000001000 { #address-cells = <1>; #size-cells = <0>; compatible = "cavium,octeon-3860-twsi"; reg = <0x11800 0x00001000 0x0 0x200>; interrupts = <0 45>; clock-rate = <100000>; IO內存起始地址為: 0x118000001000, 長度為0x200. 從 0x118000001000 到 0x1180000011ff. 在目標板里使用 cat /proc/iomem 可以看到: 1180000001000-11800000011ff : /soc@0/i2c@1180000001000
在linux使用platform_driver_register() 注冊 platform_driver 時, 需要在 platform_driver 的probe() 里面知道設備的中斷號, 內存地址等資源。 這些資源的描述信息存放在 resource 數據結構中, 相同的資源存放在一個樹形樹形數據結構中, 通過父節點, 兄弟節點, 子節點相連。 比如中斷資源, IO端口資源, IO內存資源, DMA資源有不同資源樹。 Linux使用 struct resource 來描述一個resouce struct resource { resource_size_t start; //資源范圍的開始 resource_size_t end; //資源范圍的結束 const char *name; //資源擁有者名 unsigned long flags; //資源屬性標識 struct resource *parent, *sibling, *child; //資源樹的父節點, 兄弟節點, 字節點指針 }; resource_size_t 由系統決定 為uint32_t 或uint64_t 。 在platform機制里, 使用platform_get_resource()來獲取指定的資源類型。 比如獲取想獲取中斷號, irq = platform_get_irq(pdev, 0); int platform_get_irq(struct platform_device *dev, unsigned int num) { struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); return r ? r->start : -ENXIO; } EXPORT_SYMBOL_GPL(platform_get_irq); platform_get_irq() 會返回一個start, 即可用的中斷號。 之后便可使用request_irq() 來注冊中斷服務函數。 再比如想要獲取IO內存資源: struct resource *res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 即可得到一個IO內存資源節點指針, 包括了地址的開始,結束地址等, 該IO內存的長度可用 resource_size() 來獲取, 但這段資源只是一個描述, 想真正使用這段IO內存, 還要經過先申請, 再映射的過程。例如可使用devm_request_mem_region()申請出使用這段IO內存, 再使用ioremap() 將其映射出來, 供用戶空間使用。 devm_request_mem_region(&pdev->dev, res_mem->start, resource_size(res_mem), res_mem->name)) addr_start = ioremap(res_mem->start, resource_size(res_mem)); ioremap() 的返回值即為該資源的虛擬地址。 IO內存的資源是在設備樹源(Device Tree Source)文件(以.dts結尾)里給出的,.dts文件就是用來描述目標板硬件信息的, 在uboot啟動后, 使用uboot提供的特定API將其獲取出來, 如fdt_getprop(), fdt_path_offset(), 這些API包含在uboot 的頭文件 里面。 uboot將.dts文件里的描述解析出來, 再對相應寄存器賦值, 在linux啟動后, 使用 platform_get_resource() 即可獲取到這些給定的資源, 在驅動里使用。 例如一個在.dts文件中關于gpio資源的描述: gpio: gpio-controller@1070000000800 { #gpio-cells = <2>; compatible = "cavium,octeon-3860-gpio"; reg = <0x10700 0x00000800 0x0 0x100>; gpio-controller; … 根據其描述, 可知道gpio控制器的IO內存起始地址為:0x107900000800, 長度為0x100. 即從 0x107900000800 到 0x1079000008ff. 在目標板里使用 cat /proc/iomem 可以看到: 1070000000800-10700000008ff : /soc@0/gpio-controller@1070000000800 關于i2c 的描述: twsi0: i2c@1180000001000 { #address-cells = <1>; #size-cells = <0>; compatible = "cavium,octeon-3860-twsi"; reg = <0x11800 0x00001000 0x0 0x200>; interrupts = <0 45>; clock-rate = <100000>; IO內存起始地址為: 0x118000001000, 長度為0x200. 從 0x118000001000 到 0x1180000011ff. 在目標板里使用 cat /proc/iomem 可以看到: 1180000001000-11800000011ff : /soc@0/i2c@1180000001000
?
評論
查看更多