对于powerpc,并没有提供I/O空间,仅有内存空间,所以对各种外设寄存器的访问,都需要将该寄存器对应的
的物理地址转换成虚拟内存地址后,才能实现对各种外设的访问,用于实现物理地址到虚拟内存转换的函数为
ioremap(unsigned long physaddr, unsigned long size)
其中physaddr:表示外设寄存器对应的物理地址
size:表示需要映射的范围
该函数成功执行后的返回值即为映射后的虚拟起始地址
例如:GPIO的起始物理地址为0x5000A000,GPIO相关的寄存器范围为0x80,则可以
void __iomem *gpio_base_addr = ioremap(0x5000A000,0x80);
然后就可以通过gpio_base_addr,实现设置相应的GPIO口的操作。
对于mips,其地址空间映射机制是比较特殊的(详见see mips run一书),其将4GB的内存空间划分为kusr(0x00000000 - 0x7fffffff)、
kseg0(0x80000000-0x9fffffff)、kseg1(0xA0000000-0xbfffffff)、kseg2(0xC0000000-0xffffffff),其中kusr由用户空间使用,
而kseg0、kseg1由kernel空间使用,其中kseg0中,只需将虚拟地址的最高位清零即转换成物理地址,其该部分的地址总是通过cache来获取;
kseg1区域,只需将最高3位的值清零即可转换成物理地址,这部分的地址的获取是不通过cache的。
mips的处理器一般把外省的物理地址映射到kseg1区,因此只要知道外设的物理地址,则只需要在代码中直接加上0xA000 0000就是外设的虚拟地址,这样的访问速度比较快,
如下两个函数就实现了对外设寄存器的读写操作:
#define REG_GET(phys) (*(volatile uint32_t *)(phys|0xa0000000))
#define REG_SET(phys,val) (*(volatile uint32_t *)(phys|0xa0000000)= val)
的物理地址转换成虚拟内存地址后,才能实现对各种外设的访问,用于实现物理地址到虚拟内存转换的函数为
ioremap(unsigned long physaddr, unsigned long size)
其中physaddr:表示外设寄存器对应的物理地址
size:表示需要映射的范围
该函数成功执行后的返回值即为映射后的虚拟起始地址
例如:GPIO的起始物理地址为0x5000A000,GPIO相关的寄存器范围为0x80,则可以
void __iomem *gpio_base_addr = ioremap(0x5000A000,0x80);
然后就可以通过gpio_base_addr,实现设置相应的GPIO口的操作。
对于mips,其地址空间映射机制是比较特殊的(详见see mips run一书),其将4GB的内存空间划分为kusr(0x00000000 - 0x7fffffff)、
kseg0(0x80000000-0x9fffffff)、kseg1(0xA0000000-0xbfffffff)、kseg2(0xC0000000-0xffffffff),其中kusr由用户空间使用,
而kseg0、kseg1由kernel空间使用,其中kseg0中,只需将虚拟地址的最高位清零即转换成物理地址,其该部分的地址总是通过cache来获取;
kseg1区域,只需将最高3位的值清零即可转换成物理地址,这部分的地址的获取是不通过cache的。
mips的处理器一般把外省的物理地址映射到kseg1区,因此只要知道外设的物理地址,则只需要在代码中直接加上0xA000 0000就是外设的虚拟地址,这样的访问速度比较快,
如下两个函数就实现了对外设寄存器的读写操作:
#define REG_GET(phys) (*(volatile uint32_t *)(phys|0xa0000000))
#define REG_SET(phys,val) (*(volatile uint32_t *)(phys|0xa0000000)= val)