此前遇到用户层无法控制的GPIO引脚,命令也没法改变GPIO高低电平,也没有被别的功能复用,困惑了很久,才知道,硬件地址的寄存器,存在初始固化的操作,将gpio的功能已经写死,需要用修改寄存器的值来改变。以此做个笔记。
一、准备工作
要知道所操作的GPIO地址,首先拿到数据手册《Rockchip RK3528 TRM Part1》;
其次,在手册搜对应引脚,我的是gpio2a5

知道基地址和偏移地址,和对应的寄存器数值对应的功能
二、解决的思路
1、通过内核驱动访问寄存器,修改;
2、通过、/dev/mem,直接访问寄存器;
3、通过寄存器工具,(devmem2, 或者 RK提供的IO工具);
简单测试可行性,可以直接用寄存器工具,这里我是必须更改寄存器的,所以我选更为 安全 ,可控,不会破坏系统稳定性的内核驱动方式修改。
三,通过内核驱动访问寄存器,修改对应的值
1、在内核驱动文件下,创造一个.c文件
touch drivers/misc/rk3528_iomux_multi_we.c
2、实现具体的操作,提醒一句,这里要熟悉平台的操作方式,就比如我这是RK平台,它有一个Rockchip IOC 的「write-enable 掩码写寄存器机制, 不能单独的写对应位,要同时写高 16 位:write_enable和低 16 位:目标值,代码如下:
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/io.h>
#define IOMUX_BASE 0xFF570000
#define IOMUX_SIZE 0x200
struct rk_iomux_cfg {
u32 offset; /* 寄存器偏移 */
u8 shift; /* 位起始 */
u8 width; /* 位宽 */
u32 value; /* 写入值 */
};
/*
* ===== 在这里配置你要改的 pin =====
* 注意:value 是功能选择值,不是 mask
*/
static struct rk_iomux_cfg iomux_cfgs[] = {
/* GPIO2_A4 / A5 / A6 -> GPIO */
{ 0x44, 0, 4, 0x0 }, /* gpio2a4_sel */
{ 0x44, 4, 4, 0x0 }, /* gpio2a5_sel */
{ 0x44, 8, 4, 0x0 }, /* gpio2a6_sel */
/*这里可以添加更多引脚*/
};
static int __init rk3528_iomux_multi_init(void)
{
void __iomem *base;
u32 we_mask, val_mask;
int i;
base = ioremap(IOMUX_BASE, IOMUX_SIZE);
if (!base)
return -ENOMEM;
/*
* 每个 offset 单独组合一次 write_enable + value
* 防止不同寄存器混写
*/
for (i = 0; i < ARRAY_SIZE(iomux_cfgs); ) {
u32 offset = iomux_cfgs[i].offset;
u32 write_val = 0;
we_mask = 0;
val_mask = 0;
/* 合并同一个寄存器里的多个 pin */
for (; i < ARRAY_SIZE(iomux_cfgs) &&
iomux_cfgs[i].offset == offset; i++) {
struct rk_iomux_cfg *c = &iomux_cfgs[i];
u32 mask = ((1 << c->width) - 1);
/* write_enable 对应低16位 */
we_mask |= (mask << c->shift);
val_mask |= (c->value & mask) << c->shift;
}
write_val = (we_mask << 16) | val_mask;
writel(write_val, base + offset);
pr_info("IOMUX WE: off=0x%x we=0x%04x val=0x%04x\n",
offset, we_mask, val_mask);
}
iounmap(base);
return 0;
}
late_initcall(rk3528_iomux_multi_init);
3、Makefile(编进内核)
drivers/misc/Makefile:
obj-y += rk3528_iomux_multi_we.o
4、启动后你应该看到的 dmesg
IOMUX WE: off=0x44 we=0x0fff val=0x0000
这就更改成功了。
四、其它两种方法,更为简单,只是为了系统安全,后续会补充剩余两种方法的详细操作步骤
1719

被折叠的 条评论
为什么被折叠?



