Issue
I have started learning linux device drivers. I'm doing some sample programs as a part of my learning. To understand memory mapped IO I wrote the following code.(only init is shown here). There is no hardware mapped at the base address.
static unsigned long base = 0xfed00000;
unsigned long device_base=0;
unsigned long virtual_base=0;
static int __init sharedirqmodule_init(void) {
u32 register1=0;
u32 value=0x23456789;
device_base=base;
void *address=0;
if(!request_mem_region(device_base,8,"device"))
return -ENODEV;
virtual_base = (unsigned long) ioremap(device_base, 8);
address=(void *)virtual_base;
printk(KERN_ERR "Sharedirq : Address value: %lx\n",address);
iowrite32(value,address);
wmb();
register1=(u32)ioread32(address);
rmb();
printk(KERN_ERR "Shared irq :value: %d \n",register1);
return 0;
}
The module is insmod'ing. But I'm not getting the correct value I wrote when using ioread32. I'm getting the following output,
[20441.627344] Sharedirq : Address value: ffffc900001ce000
[20441.627365] Shared irq :value: -1
What is going wrong in the program? If the mistake is silly I would appreciate a clue than a direct solution.(Sorry for using multiple variable for the same value.. virtual_base and address)
Solution
There is no hardware mapped at the base address. ... What is going wrong in the program?
As @AndreasBombe pointed out, writing and then reading a memory location that has no hardware (neither RAM or a device register/memory) will produce undefined results.
I just request_mem_region that region and did a ioremap to use that region. Shouldn't that work? I thought it kind of simulate the memory mapped IO usage.
That should "work" in the sense that you will not get any error from those calls. But since there is no hardware at those physical locations, then accessing those virtual addresses makes no sense.
The value should be saved in physical memory as the virtual address provided by ioremap would have mapped to a physical address.
Those routines do not do what you seem to think they do. You previously wrote that there is no hardware at the physical address. Nor will there be any after these routines are called.
request_mem_region() essentially "allocates" the given physical address range (that is, it is recorded as "in use by this driver"). That's all; nothing else but housekeeping of addresses.
ioremap() is architecture specific, and the intent is to provide a virtual address mapping for a region of physical addresses. Linux code can only use virtual address to reference memory, so now those device registers/memory are accessible.
Neither request_mem_region() or ioremap() will actually provide any physical memory for use by your driver.
I thought iowrite and ioread get converted to ordinary MOV instruction in memory mapped IO case.Is my understanding wrong?
The memory mapped I/O location would be accessed as a virtual memory operation. If the instruction set of the CPU uses a MOV opcode to access memory, then you're correct.
But for proper execution of your program, there has to be actual hardware at those locations that can respond to store and fetch operations.
I understand it will fail in I/O mapped case
There is no such thing as "I/O mapped".
There is "port mapped I/O" that has device addresses in a separate space from memory, and are accessed using input and output instructions.
How does a driver written for a memory mapped IO device use the memory it requested using request_mem_region() & ioremap()?
Technically the memory is not "requested". I would phrase it as "the device memory (or registers) are mapped into virtual memory (space)".
In include/asm-generic/iomap.h, the value returned by ioremap() is described as a cookie and therefore should not used as a virtual memory address by the driver, but through accessor functions such as ioread*() & iowrite*():
17 /*
18 * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
19 * access or a MMIO access, these functions don't care. The info is
20 * encoded in the hardware mapping set up by the mapping functions
21 * (or the cookie itself, depending on implementation and hw).
22 *
23 * The generic routines just encode the PIO/MMIO as part of the
24 * cookie, and coldly assume that the MMIO IO mappings are not
25 * in the low address range. Architectures for which this is not
26 * true can't use this generic implementation.
27 */
28
The generic versions of ioread*() & iowrite*() are often replaced by architecture-specific versions.
Will ioread() and iowrite() automatically work in that case?
If "automatically" means "always", then "no". Not every device register may be readable and/or writeable.
The ioread*() should only be performed on a register that is readable. The iowrite*() should only be performed on a register that is writeable. E.G. a device status register is certainly readable and most likely not writeable.
Answered By - sawdust Answer Checked By - Mildred Charles (WPSolving Admin)