Hi,
I'm writing to you because i'm having trouble with I/O peripheral mapping on new kernel 2.6.38 on M5445x platform.
I work with a custom platform based on M54452 and we have some peripherals on Flexbus on chip select 2 and chip select 3.
I don't understand how mapping these peripherals on Linux. I've already read all threads about this topic, but I didn't resolve my problem. With previous kernel 2.6.25, I used "ioremap()" to map my peripheral in my device drivers, and it works. With new kernel 2.6.38 it doesn't work anymore..I check on new code of "ioremap" in kmap.c and I seen that there is a new check on KMAP_START and KMAP_END.
For kernel 2.6.25 and kernel 2.6.38 KMAP_START and KMAP_END are the same.
In practice, the situation is this:
#if defined(CONFIG_M5445X) || defined(CONFIG_M547X_8X)
#define VMALLOC_START 0xc0000000
#define VMALLOC_END 0xcfffffff
#define KMAP_START (VMALLOC_END + 1)
#define KMAP_END (0xe8000000 – 1)
#endif
Instead "ioremap" in two kernels are slightly different.
Kernel 2.6.38:
--------------------------------------------------------------------------
if ((physaddr >=KMAP_START) && (physaddr <= KMAP_END)) {
/* if physaddr belongs to virtual address range for ioremap,
* then return physaddr because it has been ioremapped
*/
return (void __iomem *)physaddr;
}
Kernel 2.6.25:
--------------------------------------------------------------------------
if ((physaddr >=0xa0000000) && (physaddr <= 0xb0000000)) {
/* if physaddr belongs to virtual address range for ioremap,
* then return physaddr because it has been ioremapped
*/
return (void __iomem *)physaddr;
}
So, I would like to map my peripherals in this mode replacing ATA physical address because in our platform (M54452) we haven't ATA controller :
#define PERIPHERAL_1_BASE_PHY 0x90000000
#define PERIPHERAL_2_BASE_PHY 0x90010000
#define PERIPHERAL_3_BASE_PHY 0x90020000
but using "ioremap" these physical addresses doesn't work.
Instead if I use physical addresses in 0xC0000000 - 0xE8000000 range, and I disable check on ((physaddr >=KMAP_START) && (physaddr <= KMAP_END)) in ioremap(), everything works. I don't understand the reason. Why I should map my devices on range between VMALLOC_START and KMAP_END?
There is something of strange...
Can you explain me, please?
Thank you very much for your support.
I add some other info on my problem, so I hope that someone can help me.
I set up Flexbus chip select in this way:
CS1 --> BASE 0x90000000 with 64K window
CS2 --> BASE 0x90010000 with 64K window
CS3 --> BASE 0x90020000 with 64K window
This is my code extracted from 'arch/m68k/coldfire/m5445x/config.c' to set up chip select on Flexbus:
#if defined(CONFIG_PERIPHERAL_1) || defined(CONFIG_PERIPHERAL_1_MODULE)
MCF_FBCS_CSAR(1) = PERIPHERAL_1_BASE_PHY;
MCF_FBCS_CSMR(1) = MCF_FBCS_CSMR_BAM_64K | MCF_FBCS_CSMR_V;
MCF_FBCS_CSCR(1) = MCF_FBCS_CSCR_WRAH(0x00) |
MCF_FBCS_CSCR_RDAH(0x00) |
MCF_FBCS_CSCR_ASET(0x01) |
MCF_FBCS_CSCR_WS(0x00) |
MCF_FBCS_CSCR_AA |
MCF_FBCS_CSCR_PS_32 |
MCF_FBCS_CSCR_BEM;
#endif
#if defined(CONFIG_PERIPHERAL_2) || defined(CONFIG_PERIPHERAL_2_MODULE)
MCF_FBCS_CSAR(2) = PERIPHERAL_2_BASE_PHY;
MCF_FBCS_CSMR(2) = MCF_FBCS_CSMR_BAM_64K | MCF_FBCS_CSMR_V;
MCF_FBCS_CSCR(2) = MCF_FBCS_CSCR_WRAH(0x00) |
MCF_FBCS_CSCR_RDAH(0x00) |
MCF_FBCS_CSCR_ASET(0x01) |
MCF_FBCS_CSCR_WS(0x00) |
MCF_FBCS_CSCR_AA |
MCF_FBCS_CSCR_PS_32 |
MCF_FBCS_CSCR_BEM;
#endif
#if defined(CONFIG_PERIPHERAL_3) || defined(CONFIG_PERIPHERAL_3_MODULE)
MCF_FBCS_CSAR(3) = PERIPHERAL_3_BASE_PHY;
MCF_FBCS_CSMR(3) = MCF_FBCS_CSMR_BAM_64K | MCF_FBCS_CSMR_V;
MCF_FBCS_CSCR(3) = MCF_FBCS_CSCR_WRAH(0x00) |
MCF_FBCS_CSCR_RDAH(0x00) |
MCF_FBCS_CSCR_ASET(0x01) |
MCF_FBCS_CSCR_WS(0x00) |
MCF_FBCS_CSCR_AA |
MCF_FBCS_CSCR_PS_32 |
MCF_FBCS_CSCR_BEM;
#endif
Then in my drivers, I did 'ioremap()' ro remap this physical address to virtual kernel address in this way:
static void * __iomem bus_va_base = NULL;
/* Remap I/O devices */
if (!request_mem_region(PERIPHERAL_1_BASE_PHY, PAGE_SIZE, "peripheral_1")) {
printk(KERN_ERR "peripheral_1: request mem region failed");
sts = -EINVAL;
goto init_fail;
}
bus_va_base = ioremap(PERIPHERAL_1_BASE_PHY,PAGE_SIZE);
if(!bus_va_base){
printk("Can't map device!!!");
goto init_fail2;
}
Then to write on that virtual address I use iowrite32be()/ioread32be() functions.
Debugging with Trace32, I can see that bus_va_base have 0xD0000000 as virtual address of PERIPHERAL_1_BASE_PHY (0x90000000). Note that 0xD0000000 is where KMAP_START begin. I think that is everything is right, or not? Why I can't write to bus with addresses class?
Why, instead, if I choose as physical address 0xD0000000 and I remap it, can I write to bus?
At this point I can't understand how memory is mapped on m68k with Linux. I had some experience with ppc and arm, and Linux ran at 0xC0000000.
In m68k/coldfire arch, instead, Linux run at 0x40000000 with 1:1 map to SDRAM (SDRAM physical address is 0x40000000), so how virtual memory works?
Sorry for my bad english.
Thank you very much again.