首先在设备树里定义一个节点,例如:
uart0: serial@10010000 {
compatible = "sifive,uart0";
reg = <0x0 0x10010000 0x0 0x1000>;
status = "okay";
}
@
符号后面是寄存器的基地址,然后填写compatible
和reg
属性,status
属性设置为okay
。
reg属性中,第二参数为寄存器基址,与@符号后面的地址对应,第四个参数是映射的大小。
驱动中操作:
#define OFFSET 0x60 //某个寄存器的偏移地址
static int my_probe(struct platform_device *pdev)
{
struct resource *res;
void __iomem *base;
u32 regval;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
//寄存器读写
regval = readl(base + OFFSET);//读寄存器
regval |= (1 << 0);//赋值
writel(regval, base + OFFSET);//写寄存器
return 0;
}
先调用platform_get_resource
获取IORESOURCE_MEM
资源,就是获取了设备树中的reg
属性,返回的resource
结构体中包含了起始地址和结束地址。然后调用devm_ioremap_resource
映射这个资源,就能得到一个虚拟地址。后续对该虚拟地址的操作,就等同于对寄存器物理地址的操作。
读写寄存器,可以调用readl
、writel
函数。先读取寄存器的值放到临时变量中,赋值后,再一次性写入。
全部0条评论
快来发表一下你的评论吧 !