浅析armlinux-paging_init()->at91rm9200_map_io()函数5-3
文章来源:http://gliethttp.cublog.cn
建议首先参考《浅析armlinux2_4_19启动程式[head-armv.s文档]》[http://gliethttp.cublog.cn]
//----------------------------------------
//1.arch/arm/mach-at91rm9200/Core.c->at91rm9200_map_io()
static struct map_desc at91rm9200_io_desc[] __initdata = {
/* virtual, physical, length, domain, r, w, c, b */
{ AT91C_VA_BASE_SYS, AT91C_BASE_SYS, SZ_4K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_SPI, AT91C_BASE_SPI, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_SSC2, AT91C_BASE_SSC2, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_SSC1, AT91C_BASE_SSC1, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_SSC0, AT91C_BASE_SSC0, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_US3, AT91C_BASE_US3, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_US2, AT91C_BASE_US2, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_US1, AT91C_BASE_US1, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_US0, AT91C_BASE_US0, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_EMAC, AT91C_BASE_EMAC, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_TWI, AT91C_BASE_TWI, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_MCI, AT91C_BASE_MCI, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_UDP, AT91C_BASE_UDP, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_TCB1, AT91C_BASE_TCB1, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
{ AT91C_VA_BASE_TCB0, AT91C_BASE_TCB0, SZ_16K, DOMAIN_IO, 0, 1, 0, 0},
LAST_DESC
};
//----------------------------------------
//2.
//#define LAST_DESC { last: 1 }
/*
* Serial port configuration.
* 0 .. 3 = USART0 .. USART3
* 4 = DBGU
*/
//#define AT91C_UART_MAP { 4, 1, -1, -1, -1 }/* ttyS0, ..., ttyS4 */
//#define AT91C_CONSOLE 0/* ttyS0 */
void __init at91rm9200_map_io(void)
{int serial[AT91C_NR_UART] = AT91C_UART_MAP;
int i;
iotable_init(at91rm9200_io_desc);//映射控制寄存器的虚拟地址和物理地址对应关系
/* Register UARTs */
for (i = 0; i AT91C_NR_UART; i++) {
if (serial
>= 0)
at91_register_uart(i, serial);
}
}
//----------------------------------------
//3.arch/arm/mm/Mm-armv.c->iotable_init()
void __init iotable_init(struct map_desc *io_desc)
{int i;
for (i = 0; io_desc.last == 0; i++)
//请参见《浅析armlinux-setup_arch()->create_mapping()函数5-2-2》[http://gliethttp.cublog.cn]
//按照映射表at91rm9200_io_desc[]映射at91rm9200处理器的任何控制寄存器虚拟地址和物理地址的对应关系
create_mapping(io_desc + i);
}
//----------------------------------------
//4.drivers/at91/serial/At91_serial.c->at91_register_uart()
void __init at91_register_uart(int idx, int port)
{
if ((idx 0) || (idx >= AT91C_NR_UART)) {
printk(KERN_ERR __FUNCTION__ ": bad index number %d\n", idx);
return;
}
at91_ports[idx].iotype = SERIAL_IO_MEM;
at91_ports[idx].flags = ASYNC_BOOT_AUTOCONF;
at91_ports[idx].uartclk = AT91C_MASTER_CLOCK;
at91_ports[idx].ops = &at91_pops;//登记串口统一操作集
at91_ports[idx].fifosize = 0;
switch (port) {
case 0:
at91_ports[idx].membase = (void *) AT91C_VA_BASE_US0;
at91_ports[idx].mapbase = AT91C_VA_BASE_US0;//虚拟基址
at91_ports[idx].irq = AT91C_ID_US0;//串口0的中断id号
AT91_CfgPIO_USART0();//很简单将io口配置串口模式
break;
case 1:
at91_ports[idx].membase = (void *) AT91C_VA_BASE_US1;
at91_ports[idx].mapbase = AT91C_VA_BASE_US1;
at91_ports[idx].irq = AT91C_ID_US1;
AT91_CfgPIO_USART1();//很简单将io口配置串口模式
break;
case 2:
at91_ports[idx].membase = (void *) AT91C_VA_BASE_US2;
at91_ports[idx].mapbase = AT91C_VA_BASE_US2;//虚拟基址
at91_ports[idx].irq = AT91C_ID_US2;//串口2的中断id号
AT91_CfgPIO_USART2();
break;
case 3:
at91_ports[idx].membase = (void *) AT91C_VA_BASE_US3;
at91_ports[idx].mapbase = AT91C_VA_BASE_US3;//虚拟基址
at91_ports[idx].irq = AT91C_ID_US3;//串口3的中断id号
AT91_CfgPIO_USART3();
break;
case 4:
at91_ports[idx].membase = (void *) AT91C_VA_BASE_DBGU;
at91_ports[idx].mapbase = AT91C_VA_BASE_DBGU;//虚拟基址
at91_ports[idx].irq = AT91C_ID_SYS;//dbgu的中断id号
AT91_CfgPIO_DBGU();
break;
default:
printk(KERN_ERR __FUNCTION__ ": bad port number %d\n", port);
}
}