Mapping i/o peripherals on flexbus

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

Mapping i/o peripherals on flexbus

733 次查看
frendi
Contributor I

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.

标签 (1)
0 项奖励
回复
1 回复

430 次查看
frendi
Contributor I

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.

0 项奖励
回复