Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

S3C2410 平台裝置註冊機制詳解:從 Platform Bus 到裝置驅動綁定

編輯:Linux 教學

S3C2410/2440 等 ARM SoC 採用 Linux Device Model 的 Platform Bus 機制管理片上外設。本文詳細解析 Platform Bus 註冊、平台裝置定義、資源描述、板級資訊傳遞、MACHINE_START 巨集、s3c24xx_set_board() 以及 platform_device_register() 完整流程。

一、Platform Bus 註冊


struct device platform_bus = {
    .bus_id = "platform",
};

struct bus_type platform_bus_type = {
    .name  = "platform",
    .match = platform_match,
    .suspend = platform_suspend,
    .resume  = platform_resume,
};

int __init platform_bus_init(void) {
    device_register(&platform_bus);
    return bus_register(&platform_bus_type);
}

二、平台裝置定義與資源描述


// 板級裝置陣列
static struct platform_device *smdk2410_devices[] __initdata = {
    &s3c_device_usb,
    &s3c_device_lcd,
    &s3c_device_wdt,
    &s3c_device_i2c,
    &s3c_device_iis,
};

// 單一裝置範例:NAND 控制器
static struct resource s3c_nand_resource[] = {
    [0] = {
        .start = S3C2410_PA_NAND,
        .end   = S3C2410_PA_NAND + S3C24XX_SZ_NAND,
        .flags = IORESOURCE_MEM,
    }
};

struct platform_device s3c_device_nand = {
    .name          = "s3c2410-nand",
    .id            = -1,
    .num_resources = ARRAY_SIZE(s3c_nand_resource),
    .resource      = s3c_nand_resource,
};

resource 陣列描述裝置佔用的記憶體、IRQ、DMA 等硬體資源。

三、板級資訊封裝與傳遞


static struct s3c24xx_board smdk2410_board __initdata = {
    .devices      = smdk2410_devices,
    .devices_count = ARRAY_SIZE(smdk2410_devices),
};

static void __init smdk2410_map_io(void) {
    s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
    s3c24xx_init_clocks(0);
    s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
    s3c24xx_set_board(&smdk2410_board);  // 關鍵:將板級資訊傳給核心
}

四、機器描述巨集


MACHINE_START(SMDK2410, "SMDK2410")
    .phys_ram      = S3C2410_SDRAM_PA,
    .phys_io       = S3C2410_PA_UART,
    .io_pg_offst   = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
    .boot_params   = S3C2410_SDRAM_PA + 0x100,
    .map_io        = smdk2410_map_io,
    .init_irq      = smdk2410_init_irq,
    .timer         = &s3c24xx_timer,
MACHINE_END

展開後產生 struct machine_desc __mach_desc_SMDK2410,放入 .arch.info.init 區段,供啟動時偵測機器型號使用。

五、s3c24xx_set_board() 實作


static struct s3c24xx_board *board;

void s3c24xx_set_board(struct s3c24xx_board *b) {
    board = b;
    if (b->clocks_count) {
        struct clk **ptr = b->clocks;
        for (int i = b->clocks_count; i > 0; i--, ptr++)
            s3c24xx_register_clock(*ptr);
    }
}

將板級資訊存入全域變數 board,稍後架構初始化時使用。

六、架構初始化:遍歷註冊所有平台裝置


static int __init s3c_arch_init(void) {
    // ... CPU 初始化 ...

    if (board) {
        struct platform_device **ptr = board->devices;
        for (int i = 0; i < board->devices_count; i++, ptr++) {
            int ret = platform_device_register(*ptr);
            if (ret)
                printk(KERN_ERR "failed to add board device %s\n", (*ptr)->name);
        }
    }
    return 0;
}
arch_initcall(s3c_arch_init);

七、platform_device_register() 核心邏輯


int platform_device_register(struct platform_device *pdev) {
    if (!pdev) return -EINVAL;

    // 關聯父裝置
    if (!pdev->dev.parent)
        pdev->dev.parent = &platform_bus;
    pdev->dev.bus = &platform_bus_type;

    // 設定 bus_id
    if (pdev->id != -1)
        snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id);
    else
        strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);

    return device_add(&pdev->dev);  // 加入裝置模型,觸發驅動匹配
}

至此,平台裝置正式掛載到 Platform Bus,等待同名 platform_driver 的 probe() 被呼叫,完成裝置-驅動綁定。

Copyright © Windows教程網 All Rights Reserved