linux静态映射--初看mini2440_leds.c驱动疑惑

 

struct map_desc
{
      unsigned long virtual;
      unsigned long pfn;
      unsigned long length;
      unsigned int type;
};
struct machine_desc
{
/*
* Note! The first four elements are used
* by assembler code in head.S, head-common.S
*/
unsigned int nr; /* architecture number */
unsigned int phys_io; /* start of physical io */
unsigned int io_pg_offst; /* byte offset for io page tabe entry */
const char *name; /* architecture name */
unsigned long boot_params; /* tagged list */
unsigned int video_start; /* start of video RAM */
unsigned int video_end; /* end of video RAM */
unsigned int reserve_lp0 :1; /* never has lp0 */
unsigned int reserve_lp1 :1; /* never has lp1 */
unsigned int reserve_lp2 :1; /* never has lp2 */
unsigned int soft_reboot :1; /* soft reboot */
void (*fixup)(struct machine_desc *,
struct tag *, char **,
struct meminfo *);
void (*map_io)(void);/* IO mapping function */
void (*init_irq)(void);
struct sys_timer *timer; /* system tick timer */
void (*init_machine)(void);
 
};
 
#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
static struct map_desc s3c_iodesc[] __initdata =
{
IODESC_ENT(GPIO),
IODESC_ENT(IRQ),
IODESC_ENT(MEMCTRL),
IODESC_ENT(UART)
 
};
#define S3C_ADDR_BASE (0xF4000000)
#define S3C_ADDR(x) (S3C_ADDR_BASE + (x))
#define S3C_VA_UART S3C_ADDR(0x01000000) /* UART */
#define S3C24XX_VA_UART S3C_VA_UART
#define S3C24XX_PA_UART S3C2410_PA_UART
#define S3C2410_PA_UART (0x50000000)
#define S3C2410_PA_GPIO (0x56000000)
#define S3C24XX_PA_GPIO S3C2410_PA_GPIO
#define S3C24XX_VA_GPIO ((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
/* 对以上宏map_desc结构体中的宏展开,如下: */
static struct map_desc s3c_iodesc[] __initdata =
{
{
(unsigned long)S3C24XX_VA_GPIO,
__phys_to_pfn(S3C24XX_PA_GPIO),
S3C24XX_SZ_GPIO,
MT_DEVICE
},
{
(unsigned long)S3C24XX_VA_IRQ,
__phys_to_pfn(S3C24XX_PA_IRQ),
S3C24XX_SZ_IRQ,
MT_DEVICE
},
{
(unsigned long)S3C24XX_VA_MEMCTRL,
__phys_to_pfn(S3C24XX_PA_MEMCTRL),
S3C24XX_SZ_MEMCTRL,
MT_DEVICE
},
{
(unsigned long)S3C24XX_VA_UART,
__phys_to_pfn(S3C24XX_PA_UART),
S3C24XX_SZ_UART,
MT_DEVICE
},
};
static struct map_desc smdk2440_iodesc[] __initdata =
{
/* ISA IO Space map (memory space selected by A24) */
{
.virtual = (u32)S3C24XX_VA_ISA_WORD,
.pfn = __phys_to_pfn(S3C2410_CS2),
.length = 0x10000,
.type = MT_DEVICE,
},
{
.virtual = (u32)S3C24XX_VA_ISA_WORD + 0x10000,
.pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
.length = SZ_4M,
.type = MT_DEVICE,
},
{
.virtual = (u32)S3C24XX_VA_ISA_BYTE,
.pfn = __phys_to_pfn(S3C2410_CS2),
.length = 0x10000,
.type = MT_DEVICE,
},
{
.virtual = (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
.pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
.length = SZ_4M,
.type = MT_DEVICE,
}
};
 
#define MACHINE_START(_type,_name) \
static const struct machine_desc __mach_desc_##_type \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_##_type, \
.name = _name,
#define MACHINE_END \
};
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks < [email protected]> */
.phys_io = S3C2410_PA_UART, /* 被映射的物理地址 */
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, /* S3C24XX_VA_UART:被映射到的虚拟地址 */
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END

static const struct machine_desc __mach_desc_S3C2440
__used__attribute__((__section__(".arch.info.init"))) =
{
.nr = MACH_TYPE_S3C2440,
.name = "SMDK2440",
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
};
static void __init smdk2440_map_io(void)
{
s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
s3c24xx_init_clocks(16934400);
s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}
void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
{

unsigned long idcode = 0x0;
/* initialise the io descriptors we need for initialisation */
iotable_init(mach_desc, size);
iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); /* 初始化io */
if (cpu_architecture() >= CPU_ARCH_ARMv5)
{
        idcode = s3c24xx_read_idcode_v5();
           }
          else
         {
              idcode = s3c24xx_read_idcode_v4();
         }
       arm_pm_restart = s3c24xx_pm_restart;
       s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
}
void __init iotable_init(struct map_desc *io_desc, int nr)
{
      int i;
       for (i = 0; i < nr; i++)
      /* 建立页表 */
       create_mapping(io_desc + i);
}
/* 以上为建立IO的物理地址和虚拟地址映射关系相关的一些宏,结构体,变量,宏*/
 
/* 下面看一下这些函数是如何被调用的
*map_io函数会在系统初始化过程中被调用,
*流程如下:start_kernel()--> setup_arch()-->paging_init()中
*被调用。
*
*struce machine_desc结构体的各个成员函数在不同时期被调用
* 1. .init_machine 在 arch/arm/kernel/setup.c 中被 customize_machine 调用,放在 arch_initcall( ) 段里面,会自动按顺序被调用
* 2. init_irq在start_kernel( ) --> init_IRQ( ) --> init_arch_irq( ) 被调用
* 3. map_io 在 setup_arch( ) --> paging_init( )被调用
*其他主要都在 setup_arch() 中用到。
 
当时很迷惑为什么找不到ioremap函数,由于在系统初始化的时候,内核已经静态建立好了IO的物理地址和虚拟地址的映射关系,
故可以直接使用虚拟地址,而且由于连续的虚拟地址映射到连续的物理地址(在mini2440开发板内核的配置情况下,其他内核配置情况下,连续的虚拟地址不一定对应连续的物理地址),故后面的虚拟地址就可以有S3C24XX_VA_UART进行响应计算获得。
#define S3C_ADDR_BASE (0xF4000000)只不多是认为选择的虚拟地址映射的开始地址而已。

 

你可能感兴趣的:(linux,静态映射)