I/O memory static mapping map

  
 

In the process of porting Linux to the target board, a static mapping of the physical address of the peripheral I/O memory to the virtual address is usually established:

//The structure used is struct map_desc {unsigned long virtual; //virtual address unsigned long pfn; //__ phys_to_pfn (physical address), is the physical page frame number unsigned long length; //size unsigned int type; //type};


Here is the plat level map_io:

in linux/arch/arm/plat-s5p/cpu.c:

/* table of supported CPUs supported cpu types*/static const char name_s5pv210 [] = " S5PV210 /S5PC110 "; static struct cpu_table cpu_ids [] __initdata = {{.idcode = 0x43110000, .idmask = 0xfffff000, .map_io = s5pv210_map_io, //this is the mach level map_io.init_clocks = s5pv210_init_clocks, .init_uarts = s5pv210_init_uarts, .init = s5pv210_init, .name = name_s5pv210,},};

/* minimal IO mapping * /static struct map_desc s5p_iodesc [] __initdata = {{.virtual = (unsigned long) S5P_VA_CHIPID ,.pfn = __phys_to_pfn(S5P_PA_CHIPID),.length = SZ_4K, //The size of the page in ARM Is 4K, so this length must be a multiple of the .type 4K = MT_DEVICE,}, {.virtual = (unsigned long) S3C_VA_SYS, .pfn = __phys_to_pfn (S5P_PA_SYSCON) ,. length = SZ_64K, .type = MT_DEVICE,}, { .virtual = (unsigned long) S3C_VA_UART, .pfn = __phys_to_pfn (S3C_PA_UART) ,. length = SZ_4K, .type = MT_DEVICE,}, {.virtual = (unsigned long) VA_VIC0, .pfn = __phys_to_pfn (S5P_PA_VIC0) ,. length = SZ_16K, .type = MT_DEVICE,}, {.virtual = (unsigned long) VA_VIC1, .pfn = __phys_to_pfn (S5P_PA_VIC1) ,. length = SZ_16K, .type = MT_DEVICE,}, {.virtual = (unsigned long) S3C_VA_TIMER ,. pfn = __phys_to_pfn (S5P_PA_TIMER) ,. length = SZ_16K, .type = MT_DEVICE,}, {.virtual = (unsigned long) S5P_VA_GPIO, .pfn = __phys_to_pfn (S5P_PA_GPIO) ,. length = SZ_4K, .type = MT_DEVICE,}, { .virtual = (unsigned long) S3C_VA_WATCHDOG, .pfn = __phys_to_pfn (S5P_PA_WDT) ,. length = SZ_4K, .type = MT_DEVICE,}, {.virtual = (unsigned long) S3C_VA_OTG, .pfn = __phys_to_pfn (S5P_PA_OTG) ,. length = SZ_1M,.type = MT_DEVICE,}, {.virtual = (unsigned long)S3C_VA_OTGPHY,.pfn = __ph ys_to_pfn (S5P_PA_OTGPHY) ,. length = SZ_1M, .type = MT_DEVICE,},};


void __init s5p_init_io (struct map_desc * mach_desc, int size, void __iomem * cpuid_addr) {/* initialize the io descriptors we need for initialization * /iotable_init (s5p_iodesc, ARRAY_SIZE (s5p_iodesc)); //ultimately establish the function of the page map (here mainly is a plat level map_io)

idcode = __raw_readl ( Cpuid_addr);s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); //This function will eventually call mach level map_io}


/kernel/arch/arm/mach-s5pv210 /mach-smdkv210.c in which: //initialize the plate called static void __init smdkv210_map_io (void) {s5p_init_io (NULL, 0, S5P_VA_CHIPID); .....} MACHINE_START (SMDKV210, " smdkv210 ") phys_io = S3C_PA_UART. & 0xfff00000, .io_pg_offst = (((u32) S3C_VA_UART) & gt; & gt; 18) & 0xfffc, .boot_params = S5P_PA_SDRAM + 0x100, .fixup = s5pv210_fixup, .init_irq = s5pv210_init_irq, .map_io = smdkv210_map_io, .init_machine = smdkv210_machine_init ,.timer = &s5p_systim Er,MACHINE_END


After this, when the device driver accesses the statically mapped I/O memory, it can directly add the offset to the corresponding virtual address, without using ioremap(). . But I tried using ioremap(), I don't know if it is wrong? ? ?







Additional (mach level map_io ):

in the linux /arch /arm /mach-s5pv210 /cpu.c in:

/* Initial IO mappings * /static struct map_desc s5pv210_iodesc [] __initdata = {{.virtual = (unsigned long) S5P_VA_SYSTIMER, .pfn = __phys_to_pfn (S5PV210_PA_SYSTIMER) ,. length = SZ_1M, .type = MT_DEVICE,}, {.virtual = (unsigned long) VA_VIC2, .pfn = __phys_to_pfn (S5PV210_PA_VIC2) ,. length = SZ_16K ,. type = MT_DEVICE,}, {.virtual = (unsigned long) VA_VIC3, .pfn = __phys_to_pfn (S5PV210_PA_VIC3) ,. length = SZ_16K, .type = MT_DEVICE,}, {.virtual = (unsigned long) S5P_VA_SROMC, .pfn = __phys_to_pfn (S5PV210_PA_SROMC) ,. length = SZ_4K, .type = MT_DEVICE,}, {.virtual = (unsigned long) S5P_VA_AUDSS, .pfn = __phys_to_pfn (S5PV210_PA_AUDSS) ,. length = SZ_1M, .type = MT_DEVICE,}, {.virtual = (unsigned long) S5P_VA_DMC0, .pfn = __phys_to_pfn (S5PV210_PA_DMC0) ,. length = SZ_4K, .type = MT_DEVICE,}, {.virtual = (unsigned long) S5P_VA_DMC1, .pfn = __phys_to_pfn (S5PV210_PA_DMC1) ,. le ngth = SZ_4K, .type = MT_DEVICE,}};

/* s5pv210_map_io ** register the standard cpu IO areas * /void __init s5pv210_map_io (void) {iotable_init (s5pv210_iodesc, ARRAY_SIZE (s5pv210_iodesc));} < Br>

Copyright © Windows knowledge All Rights Reserved