设备通常会提供一组寄存器用于控制设备、读定设备和获取设备状态,即控制寄存器、数据寄存器和状态寄存器.这些寄存器可能位于I/O空间,也可能位于内存空间.当位于I/O空间时,通常被称为I/O端口,位于内存空间时,对应的内存空间被称为I/O内存.在嵌入式LINUX中,我们接触最多的就是I/O内存:
#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0)
向内核申请n个内存地址,这些地址从first开始,name参数为设备的名称.如果分配成功返回值为非NULL,如果返回NULL,则意味着申请I/O内存失败.
其相反的动作函数为:
int release_resource(struct resource *old)
这对函数一般用来判断I/O内存是否已经被占用了.它一般配合platform_get_resource()函数来使用.platform_get_resource()用来获取平台设备端的I/O内存地址空间,并以其返回值为参数.如下:
struct resource *platform_get_resource(struct platform_device *dev,unsigned int type, unsigned int num)
以S3C2440的RTC为例,简单说明:
1. static int __devinit s3c_rtc_probe(struct platform_device *pdev)
2. {
3. ... ...;
4. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
5. if (res == NULL) {
6. dev_err(&pdev->dev, "failed to get memory region resource
");
7. return -ENOENT;
8. }
9.
10. s3c_rtc_mem = request_mem_region(res->start,res->end-res->start+1,pdev->name);
11. ... ...;
12. }
[注:]I/O内存一般只用来判断我们目标操作内存是否被占用,但是这并不是必须的.
在对I/O内存的存取内核提供了专门的API:
1. unsigned readb(address);
2. unsigned readw(address);
3. unsigned readl(address);
4.
5. void writeb(unsigned value, address);
6. void writew(unsigned value, address);
7. void writel(unsigned value, address);
例如S3C2440的LCD驱动里面,对LCD主控端寄存器的配置:
1. static int __init s3c24xxfb_probe(struct platform_device *pdev,enum s3c_drv_type drv_type)
2. {
3. ... ...;
4. lcdcon1 = readl(info->io + S3C2410_LCDCON1);
5. writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);
6. ... ...;
7. }