JackWellem 发表于 2016-1-20 10:27

【Arm Linux】如何在kernel中加入测试pin


环境说明:CPU(imx6)
问题:在uboot中可以添加如下代码,来控制测试pin拉高。
               *(volatile unsigned long*) 0x020A4000 |= (0x200000);    (数据输出值)
               *(volatile unsigned long*) 0x020A4004 |= 0x200000;       (端口方向选择)
         但在kernel中则不行,大概是因为kernel的分页机制而不能访问对应的寄存器,请问有谁知道在内核中如何添加对测试pin的控制?

JackWellem 发表于 2016-1-20 12:31

一、动态映射(ioremap)方式

动态映射方式是大家使用了比较多的,也比较简单。即直接通过内核提供的ioremap函数动态创建一段外设I/O内存资源到内核虚拟地址的映射表,从而可以在内核空间中访问这段I/O资源。
Ioremap宏定义在asm/io.h内:
#define ioremap(cookie,size)         __ioremap(cookie,size,0)


__ioremap函数原型为(arm/mm/ioremap.c):
void __iomem * __ioremap(unsigned long phys_addr, size_t size, unsigned long flags);
phys_addr:要映射的起始的IO地址
size:要映射的空间的大小
flags:要映射的IO空间和权限有关的标志
该函数返回映射后的内核虚拟地址(3G-4G). 接着便可以通过读写该返回的内核虚拟地址去访问之这段I/O内存资源。


举一个简单的例子: (取自s3c2410的iis音频驱动)
比如我们要访问s3c2410平台上的I2S寄存器, 查看datasheet 知道IIS物理地址为0x55000000,我们把它定义为宏S3C2410_PA_IIS,如下:
#define S3C2410_PA_IIS    (0x55000000)
若要在内核空间(iis驱动)中访问这段I/O寄存器(IIS)资源需要先建立到内核地址空间的映射:
our_card->regs = ioremap(S3C2410_PA_IIS, 0x100);
if (our_card->regs == NULL) {
         err = -ENXIO;
         goto exit_err;
}
创建好了之后,我们就可以通过readl(our_card->regs )或writel(value, our_card->regs)等IO接口函数去访问它。
页: [1]
查看完整版本: 【Arm Linux】如何在kernel中加入测试pin