Accessing PCI Memory Mapped Registers in Linux Kernel
YOUNGWHAN SONG
breadncup at gmail.com
Tue Dec 21 04:04:52 EST 2010
Hi,
A few days ago, I posted about accessing PCI memory mapped registers. (FYI, the platform I use is 32bit architecture and Linux kernel compiled in 32 bit intel based architecture.)
Now, I found that there is a problem to access 16b aligned registers. For example,
-------------
struct foo {
unsigned int TEST1;
unsigned short int a1[256];
}
void * regsva;
struct foo *test_foo;
if ((regsva = ioremap_nocache(dev->base_addr, (16 * 1024))) == NULL) {
printk("ioremap() failed\n");
goto fail;
}
test_foo = (struct foo*)regsva;
printk(KERN_DBG "value TEST1: 0x%lx\n", readl(test_foo->TEST1));
printk(KERN_DBG "value 0: 0x%x\n", readw(&test_foo->a1[0]);
printk(KERN_DBG "value 1: 0x%x\n", readw(&test_foo->a1[1]);
-------------
The above code in PC (intel based 32bit architecture) with the same h/w module shows that
value TEST1: 0x8080
value 0: 0x9090
value 1: 0xa0a0
So, that's valid value. (I have datasheet to check if the value is correct or not.)
But, when the code is run on our platform (32bit) with the same h/w module, it
shows that
value TEST1: 0x8080
value 0: 0xFFFF
value 1: 0xFFFF
Now, if I change the printk as
printk(KERN_DBG "value 0: 0x%x\n", readl(&test_foo->a1[0]);
printk(KERN_DBG "value 1: 0x%x\n", readl(&test_foo->a1[1]);
Then, even PC shows 0xFFFF like this:
value 0: 0xFFFFFFFF
value 1: 0xFFFFFFFF
So, if the read bit is not aligned correctly, it looks it cannot read correctly.
OK, then,
How can our platform (32 bit) read correctly 16b aligned PCI memory mapped register? (As long as the register is 32 bit, there is no problem.)
At least, I would like to understand why the 16 bit registers and 32 bit registers are responding differently.
Thanks,
Daniel
More information about the Kernelnewbies
mailing list