Forum Discussion
Altera_Forum
Honored Contributor
14 years agoNios II - Data cache problem
Hi all,
I'm using a Cyclone III DSP Kit (DK-DSP-3C120N) and uClinux. Some days ago I realized a working design which includes a Nios II processor characterized by only an instruction cache. Within the system there's an IP that communicates with the CPU using a PIO peripheral. I wrote a Linux driver for this IP. All seems to work, but if I add also a data cache, Nios II and the IP stop to communicate, it seems that data do not leave the PIO. Can anyone tell me why? Thanks in advance Marco21 Replies
- Altera_Forum
Honored Contributor
Your driver is probably using ioremap_nocache() to map in the device registers - in which case the address you are given will be uncached and you won't need to do explicit cache flushing.
Which might mean your original problem is elsewhere. - Altera_Forum
Honored Contributor
The problem is due to data cache in Nios II processor because without it my software works :)
I don't use ioremap_nocache. May I change something in my driver if I move from a processor with no data cache to a processor with data cache? - Altera_Forum
Honored Contributor
Are You sure that cache flush is reachable from user space?
- Altera_Forum
Honored Contributor
The data cache flush needs to be done with the same virtual address as the memory access itself - which means you'll need to do it from within the driver.
The gcc 'asm' statement for the 'flushda' instruction is quite simple, you might find one if you search through all the header files. If your driver isn't using ioremap_nocache() to get a kernel virtual address for the phyiscal address, what is it using? I am presuming you are using the MMU - I can't remember if that requires the data cache. If you aren't using the MMU (so virtual and physical addresses match), setting the high address bit or using the defines that generate the 'io' forms of the memeory instructions would work. - Altera_Forum
Honored Contributor
--- Quote Start --- it seems that data do not leave the PIO. --- Quote End --- IIRC, the way to go is to define the MMU mapü in a way that the virtual address of the PIO is not cacheable. -Michael - Altera_Forum
Honored Contributor
--- Quote Start --- The problem is due to data cache in Nios II processor because without it my software works :) I don't use ioremap_nocache. May I change something in my driver if I move from a processor with no data cache to a processor with data cache? --- Quote End --- You have to use ioremap_nocache to get a virtual address from your physical address. Then do all your access using that address. This will work with or without an MMU. - Altera_Forum
Honored Contributor
--- Quote Start --- The data cache flush needs to be done with the same virtual address as the memory access itself - which means you'll need to do it from within the driver. The gcc 'asm' statement for the 'flushda' instruction is quite simple, you might find one if you search through all the header files. If your driver isn't using ioremap_nocache() to get a kernel virtual address for the phyiscal address, what is it using? I am presuming you are using the MMU - I can't remember if that requires the data cache. If you aren't using the MMU (so virtual and physical addresses match), setting the high address bit or using the defines that generate the 'io' forms of the memeory instructions would work. --- Quote End --- I'm not using MMU, so I don't use ioremap. I tried to use cache_push_all(), but it didn't works. Can you explain me how can i set 31st bit or where can I find the defines you're talking about? - Altera_Forum
Honored Contributor
Setting the top bit is as simple as:
ptr = (void *)((unsigned int)ptr) | 0x80000000); Although it is probably worth encapsulating it in a# define. I don't know where you are getting the address from. It might be from a numeric constant in a header file - in which case you can or in the top bit then. An alternative is to get the linker script to define the value of a symbol (instead of using the contents of a variable) - in which case it can just define the high value (useful for small systems when the IO addresses can be arranged to be accessible from %gp). - Altera_Forum
Honored Contributor
in the no-MMU case, ioremap_nocache()should do exactkly this and thus provide for decently portable code.
-Michael - Altera_Forum
Honored Contributor
I tried to use ioremap_nocache()
but it doesn't work...:(static int __init fpga_in_init(void) { # ifdef DEBUG_FUNCTION_NAME printk("\n%s\n",__FUNCTION__); # endif int i; dev_t devno; ioremap_nocache((unsigned long)PIO_FPGA_IN_BASE,PIO_FPGA_IN_SIZE); if (!(request_mem_region((unsigned long)PIO_FPGA_IN_BASE, PIO_FPGA_IN_SIZE, "pio_fpga_in"))) return -1; memset(&_fpga_in_dev,0,sizeof(_fpga_in_dev)); ....