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)只不多是认为选择的虚拟地址映射的开始地址而已。
|