我正在尝试开发一个 Linux 设备驱动程序来管理 NanoPI Neo 卡(Allwinner H3)的 GPIO 寄存器。
我正在使用一种简单的方法来理解 GPIO 寄存器的行为,仅使用两个驱动程序函数:open
和ioctl
.
目前,我的驱动程序实现能够管理许多寄存器,例如 RTC 和 CPU-PORT,并能够读写其他一些寄存器。
但我在使用/管理 TWI 寄存器 (I2C) 时遇到问题。
阻止我的问题是,无论我在向寄存器本身写入任何值后读取或读取的任何寄存器总是返回 0x00000000,并且在引脚硬件级别似乎没有发生任何事情(PA11/PA12 见下文)
我阅读了CPU 数据表(参见:文档的第 8.1 段)管理 TWI0 的寄存器值和基地址,基地址应为 0x01C2AC00。
我找不到任何 AllWinner H3 GPIO 程序员的参考资料,我不确定是否需要特定操作来激活 TWI 寄存器功能。我所做的唯一操作是将寄存器 PA11 和 PA12 设置为 TWI0_SCK 和 TWI0_SDA 的 I/O。
问题:
你有《全赢H3 GPIO程序员参考》的消息吗?
你知道我必须设置/修改哪个 GPIO 寄存器才能启用 TWI 或至少给我“生命迹象”吗?
我编写的驱动程序的映射和 ioctl 函数的一个非常强大的简化,旨在仅使用 TWI0 寄存器,可能是以下代码,但我的代码要复杂得多,我知道它可以与许多其他寄存器一起使用。
#define TWI_IOBASE(n) (0x01C2AC00 + 0x400*((n)&3))
#define TWI_PAGESIZE 0x400
#define IO_ADDRESS_MSK 0x0000FFFFUL
#define IO_CMD_MSK 0xF0000000UL
#define IO_CMD_READ 0x10000000UL
#define IO_CMD_WRITE 0x20000000UL
static unsigned char * vmaddr;
inline static int drv_init_twi_vm(void)
{
vmaddr=ioremap(TWI_IOBASE(0), TWI_PAGESIZE);
}
static long drv_ioctl_twi_rw(struct file *file, unsigned int cmd, unsigned long * arg)
{
long retval = 1;
unsigned c;
uint32_t r;
void *x;
r=cmd & IO_ADDRESS_MSK;
x=vmaddr+r;
c=cmd & IO_CMD_MSK;
switch(c)
{
case IO_CMD_READ:
if ( copy_to_user((void *)arg, x, 4) ) {
retval = -EFAULT;
}
break;
case IO_CMD_WRITE:
*(unsigned long *)x=*arg;
break;
default:
retval=-EFAULT;
break;
}
return retval;
}