天天看點

Linux 裝置驅動之 DTS 描述的資源

在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, );
           

即可得到一個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 的頭檔案

gpio: gpio-controller@ {
            #gpio-cells = <>;
            compatible = "cavium,octeon-3860-gpio";
            reg = <   >;

            gpio-controller;
           

根據其描述, 可知道gpio控制器的IO記憶體起始位址為:0x107900000800, 長度為0x100.

即從 0x107900000800 到 0x1079000008ff.

在目标闆裡使用 cat /proc/iomem 可以看到:

1070000000800-10700000008ff : /[email protected]/[email protected]

關于i2c 的描述:

twsi0: [email protected] {
            #address-cells = <>;
            #size-cells = <>;
            compatible = "cavium,octeon-3860-twsi";
            reg = <   >;

            interrupts = < >;
            clock-rate = <>;
           

IO記憶體起始位址為: 0x118000001000, 長度為0x200.

從 0x118000001000 到 0x1180000011ff.

在目标闆裡使用 cat /proc/iomem 可以看到:

1180000001000-11800000011ff : /[email protected]/[email protected]

繼續閱讀