2 years ago
#29248

Sir Jo Black
Issues creating a Linux device driver to manage NanoPI TWI (I2C) registers
I'm trying to develop a Linux device driver to manage the GPIO registers of a NanoPI Neo card (Allwinner H3).
I'm using a simple approach to understand the GPIO registers behaviour by means the use of only two driver functions: open
and ioctl
.
My driver implementation, at now, is able to manage a lot of registers such as RTC and CPU-PORT and to read write some other registers.
But I'm having issues in using/managing TWI registers (I2C).
The blocking me issue is that whathever register I read or read after writing any value to the register itself always returns 0x00000000 and nothing seems to happen at pin HW level (PA11/PA12 see below)
I read on the CPU datasheet (see: paragraph 8.1 of the document) the registers value and base address to manage TWI0, base address should be 0x01C2AC00.
I can't find any AllWinner H3 GPIO programmer's reference and I'm not sure if specific operations are required to activate the TWI register functionality. The only operations I have done are to set registers PA11 and PA12 to be the I/O of TWI0_SCK and TWI0_SDA.
Questions:
Do you have any news of an "AllWinner H3 GPIO Programmer's Reference"?
Do you know which GPIO register I have to set / modify to get TWI enabled or at least give me "signs of life"?
A very strong simplification, aimed at using only TWI0 registers, of the mapping and ioctl functions of the driver I wrote might be the following code, but my code is much more sophisticated and I know it works with many other registers.
#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;
}
c
linux-device-driver
nanopi
0 Answers
Your Answer