LPC3250 IO空间图
机器描述
在board-smartarm3250.c中实现:
MACHINE_START (LPC3XXX, "SmartARM3250 board with the LPC3250 Microcontroller")
/* Maintainer: Kevin Wells, NXP Semiconductors */
.phys_io= UART5_BASE,
.io_pg_offst= ((io_p2v (UART5_BASE))>>18) & 0xfffc,
.boot_params= 0x80000100,
.map_io= lpc32xx_map_io, //CPU IO映射入口
.init_irq= lpc32xx_init_irq,
.timer= &lpc32xx_timer,
.init_machine= smartarm3250_board_init,
MACHINE_END
IO映射实现
LPC3250移植代码对已经安排了外设的片内IO空间进行了映射,包括IRAM、AHB总线上的外设、FAB和APB总线上的外设。在arch-lpc32xx.c中实现:
static struct map_desc lpc32xx_io_desc[] __initdata = {
{
//AHB0总线空间IO映射
.virtual= io_p2v(
AHB0_START),
.pfn= __phys_to_pfn(
AHB0_START),
.length=
AHB0_SIZE,
.type= MT_DEVICE
},
{
//AHB1总线空间IO映射
.virtual= io_p2v(AHB1_START),
.pfn= __phys_to_pfn(AHB1_START),
.length= AHB1_SIZE,
.type= MT_DEVICE
},
{
//FAB和APB总线空间IO映射
.virtual= io_p2v(FABAPB_START),
.pfn= __phys_to_pfn(FABAPB_START),
.length= FABAPB_SIZE,
.type= MT_DEVICE
},
{
//IRAM空间IO映射
.virtual= io_p2v(IRAM_BASE),
.pfn= __phys_to_pfn(IRAM_BASE),
.length= (SZ_64K * 4),
.type= MT_DEVICE
},
};
void __init
lpc32xx_map_io(void)
{
iotable_init (lpc32xx_io_desc, ARRAY_SIZE (lpc32xx_io_desc));
}
涉及到的宏定义
在
platform.h文件中定义所使用的宏定义。以AHB0为例:
/*
* AHB 0 physical base addresses
*/
#define SLC_BASE 0x20020000
#define SSP0_BASE 0x20084000
#define SPI1_BASE 0x20088000
#define SSP1_BASE 0x2008C000
#define SPI2_BASE 0x20090000
#define I2S0_BASE 0x20094000
#define SD_BASE 0x20098000
#define I2S1_BASE 0x2009C000
#define MLC_BASE 0x200A8000
#define
AHB0_START SLC_BASE
#define
AHB0_SIZE ((MLC_BASE - SLC_BASE) + SZ_4K)
延伸阅读
添加用户的特定IO映射
如果要用户外扩了设备,需要添加IO映射,可以修改.map_io为用户自定义io_map函数,在自定义io_map函数中调用CPU的io_map函数。下面是基于PXA270的mainstone系统。
首先声明一个map_desc结构,然后在自定义io_map函数中调用iotable_init函数对用户空间映射进行初始化:
610 static struct
map_desc mainstone_io_desc[] __initdata = {
611 { /* CPLD */
612 .virtual =
MST_FPGA_VIRT,
613 .pfn =
__phys_to_pfn(
MST_FPGA_PHYS),
614 .length = 0x00100000,
615 .type = MT_DEVICE
616 }
617 };
618
619 static void __init mainstone_map_io(void)
620 {
621
pxa_map_io();
622
iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc));
623
624 /* for use I SRAM as framebuffer. */
625 PSLR |= 0xF04;
626 PCFR = 0x66;
627 }
628
629 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
630 /* Maintainer: MontaVista Software Inc. */
631 .phys_io = 0x40000000,
632 .boot_params = 0xa0000100, /* BLOB boot parameter setting */
633 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
634
.map_io = mainstone_map_io, //IO空间映射
635 .init_irq = mainstone_init_irq,
636 .timer = &pxa_timer,
637 .init_machine = mainstone_init,
638 MACHINE_END
_phys_to_pfn
_phys_to_pfn在arch/arm/include/asm/memory.h文件中定义:
120 /*
121 * Convert a physical address to a Page Frame Number and back
122 */
123 #define
__phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT)
124 #define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
而下面这是LPC3250的io_p2v实现:
/* Start of virtual addresses for IO devices */
#
define IO_BASE 0xF0000000
#define
io_p2v(x) (IO_BASE | (((x) & 0xff000000) >> 4) | ((x) & 0x000fffff))
#define io_v2p(x) ((((x) & 0x0ff00000) << 4) | ((x) & 0x000fffff))
PAGE_SHIFT
见arch/arm/include/asm/page.h文件:
13 /* PAGE_SHIFT determines the page size */
14
#define PAGE_SHIFT 12
15 #define PAGE_SIZE (1UL << PAGE_SHIFT)
16 #define PAGE_MASK (~(PAGE_SIZE-1))
io_p2v
每个处理器都有自己的io_p2v实现,下面是PXA270处理器的,见arch/arm/mach-pxa/include/mach/hardware.h文件:
28 /*
29 * Intel PXA2xx internal register mapping:
30 *
31 * 0x40000000 - 0x41ffffff <--> 0xf2000000 - 0xf3ffffff
32 * 0x44000000 - 0x45ffffff <--> 0xf4000000 - 0xf5ffffff
33 * 0x48000000 - 0x49ffffff <--> 0xf6000000 - 0xf7ffffff
34 * 0x4c000000 - 0x4dffffff <--> 0xf8000000 - 0xf9ffffff
35 * 0x50000000 - 0x51ffffff <--> 0xfa000000 - 0xfbffffff
36 * 0x54000000 - 0x55ffffff <--> 0xfc000000 - 0xfdffffff
37 * 0x58000000 - 0x59ffffff <--> 0xfe000000 - 0xffffffff
38 *
39 * Note that not all PXA2xx chips implement all those addresses, and the
40 * kernel only maps the minimum needed range of this mapping.
41 */
42
#define io_p2v(x) (0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))
43 #define io_v2p(x) (0x3c000000 + ((x) & 0x01ffffff) + (((x) & 0x0e000000) << 1))
添加外扩设备寄存器
18 #define MST_FPGA_PHYS PXA_CS2_PHYS
19 #define
MST_FPGA_VIRT (0xf0000000)
20 #define
MST_P2V(x) ((x) - MST_FPGA_PHYS + MST_FPGA_VIRT)
21 #define MST_V2P(x) ((x) - MST_FPGA_VIRT + MST_FPGA_PHYS)
22
23 #ifndef __ASSEMBLY__
24 # define __MST_REG(x) (*((volatile unsigned long *)MST_P2V(x)))
25 #else
26 # define __MST_REG(x) MST_P2V(x)
27 #endif
28
29 /* board level registers in the FPGA */
30
31 #define MST_LEDDAT1 __MST_REG(0x08000010)
32 #define MST_LEDDAT2 __MST_REG(0x08000014)
33 #define MST_LEDCTRL __MST_REG(0x08000040)
34 #define MST_GPSWR __MST_REG(0x08000060)
35 #define MST_MSCWR1 __MST_REG(0x08000080)
36 #define MST_MSCWR2 __MST_REG(0x08000084)
37 #define MST_MSCWR3 __MST_REG(0x08000088)
38 #define MST_MSCRD __MST_REG(0x08000090)
39 #define MST_INTMSKENA __MST_REG(0x080000c0)
40 #define MST_INTSETCLR __MST_REG(0x080000d0)
41 #define MST_PCMCIA0 __MST_REG(0x080000e0)
42 #define MST_PCMCIA1 __MST_REG(0x080000e4)