From 3348c8199235cacaf6ca56d277a9cbf1ab2c5d0a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 26 Mar 2010 16:05:15 +0100 Subject: add unaligned access support Signed-off-by: Sascha Hauer --- arch/arm/include/asm/unaligned.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 arch/arm/include/asm/unaligned.h (limited to 'arch') diff --git a/arch/arm/include/asm/unaligned.h b/arch/arm/include/asm/unaligned.h new file mode 100644 index 0000000000..34f7838dc2 --- /dev/null +++ b/arch/arm/include/asm/unaligned.h @@ -0,0 +1,19 @@ +#ifndef _ASM_ARM_UNALIGNED_H +#define _ASM_ARM_UNALIGNED_H + +#include +#include +#include + +/* + * Select endianness + */ +#ifndef __ARMEB__ +#define get_unaligned __get_unaligned_le +#define put_unaligned __put_unaligned_le +#else +#define get_unaligned __get_unaligned_be +#define put_unaligned __put_unaligned_be +#endif + +#endif /* _ASM_ARM_UNALIGNED_H */ -- cgit v1.2.3 From e11c07c33994383052f041dd5551b80bee4fb6f3 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 30 Mar 2010 10:16:47 +0200 Subject: make reset_cpu a __noreturn function Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/clocksource.c | 5 ++++- arch/arm/mach-ep93xx/clocksource.c | 2 +- arch/arm/mach-imx/clocksource.c | 2 +- arch/arm/mach-netx/generic.c | 5 ++++- arch/arm/mach-omap/omap3_generic.c | 2 +- arch/arm/mach-s3c24xx/generic.c | 2 +- arch/blackfin/lib/cpu.c | 5 ++++- arch/m68k/mach-mcfv4e/mcf_reset_cpu.c | 2 +- arch/ppc/mach-mpc5xxx/cpu.c | 2 +- arch/sandbox/os/common.c | 2 +- arch/x86/mach-i386/reset.c | 2 +- include/common.h | 2 +- 12 files changed, 21 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-at91/clocksource.c b/arch/arm/mach-at91/clocksource.c index 564b560092..84df1a13ad 100644 --- a/arch/arm/mach-at91/clocksource.c +++ b/arch/arm/mach-at91/clocksource.c @@ -73,10 +73,13 @@ core_initcall(clocksource_init); /* * Reset the cpu through the reset controller */ -void reset_cpu (ulong ignored) +void __noreturn reset_cpu (unsigned long ignored) { at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); + + /* Not reached */ + while (1); } EXPORT_SYMBOL(reset_cpu); diff --git a/arch/arm/mach-ep93xx/clocksource.c b/arch/arm/mach-ep93xx/clocksource.c index 2a7d90e4e2..3aa8e14a7a 100644 --- a/arch/arm/mach-ep93xx/clocksource.c +++ b/arch/arm/mach-ep93xx/clocksource.c @@ -72,7 +72,7 @@ core_initcall(clocksource_init); /* * Reset the cpu */ -void reset_cpu(ulong ignored) +void __noreturn reset_cpu(unsigned long ignored) { struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; uint32_t value; diff --git a/arch/arm/mach-imx/clocksource.c b/arch/arm/mach-imx/clocksource.c index 09d43183b8..4b400a0ca7 100644 --- a/arch/arm/mach-imx/clocksource.c +++ b/arch/arm/mach-imx/clocksource.c @@ -95,7 +95,7 @@ core_initcall(clocksource_init); /* * Reset the cpu by setting up the watchdog timer and let it time out */ -void reset_cpu (ulong ignored) +void __noreturn reset_cpu (unsigned long ignored) { /* Disable watchdog and set Time-Out field to 0 */ WCR = 0x0000; diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c index 69cf196c61..de1e1b0434 100644 --- a/arch/arm/mach-netx/generic.c +++ b/arch/arm/mach-netx/generic.c @@ -137,9 +137,12 @@ failure: return COMMAND_ERROR_USAGE; } -void reset_cpu(ulong addr) +void __noreturn reset_cpu(unsigned long addr) { SYSTEM_REG(SYSTEM_RES_CR) = 0x01000008; + + /* Not reached */ + while (1); } diff --git a/arch/arm/mach-omap/omap3_generic.c b/arch/arm/mach-omap/omap3_generic.c index 05c5c198bd..9893145780 100644 --- a/arch/arm/mach-omap/omap3_generic.c +++ b/arch/arm/mach-omap/omap3_generic.c @@ -56,7 +56,7 @@ * * @return void */ -void reset_cpu(ulong addr) +void __noreturn reset_cpu(ulong addr) { /* FIXME: Enable WDT and cause reset */ hang(); diff --git a/arch/arm/mach-s3c24xx/generic.c b/arch/arm/mach-s3c24xx/generic.c index 2de03ca809..372904f89d 100644 --- a/arch/arm/mach-s3c24xx/generic.c +++ b/arch/arm/mach-s3c24xx/generic.c @@ -221,7 +221,7 @@ static int clocksource_init (void) } core_initcall(clocksource_init); -void reset_cpu(ulong addr) +void __noreturn reset_cpu(unsigned long addr) { /* Disable watchdog */ writew(0x0000, WTCON); diff --git a/arch/blackfin/lib/cpu.c b/arch/blackfin/lib/cpu.c index e81fa9a6d0..f96d22da13 100644 --- a/arch/blackfin/lib/cpu.c +++ b/arch/blackfin/lib/cpu.c @@ -32,7 +32,7 @@ #include #include -void reset_cpu(ulong ignored) +void __noreturn reset_cpu(ulong ignored) { icache_disable(); @@ -43,6 +43,9 @@ void reset_cpu(ulong ignored) : : "r" (L1_ISRAM) ); + + /* Not reached */ + while (1); } void icache_disable(void) diff --git a/arch/m68k/mach-mcfv4e/mcf_reset_cpu.c b/arch/m68k/mach-mcfv4e/mcf_reset_cpu.c index c7b77abcf5..3b1a25b269 100644 --- a/arch/m68k/mach-mcfv4e/mcf_reset_cpu.c +++ b/arch/m68k/mach-mcfv4e/mcf_reset_cpu.c @@ -27,7 +27,7 @@ /** * Reset the cpu by setting up the watchdog timer and let it time out */ -void reset_cpu (ulong ignored) +void __noreturn reset_cpu (unsigned long ignored) { while ( ignored ) { ; }; diff --git a/arch/ppc/mach-mpc5xxx/cpu.c b/arch/ppc/mach-mpc5xxx/cpu.c index 59b1538cd0..7ee1954be4 100644 --- a/arch/ppc/mach-mpc5xxx/cpu.c +++ b/arch/ppc/mach-mpc5xxx/cpu.c @@ -71,7 +71,7 @@ int checkcpu (void) /* ------------------------------------------------------------------------- */ -void reset_cpu (ulong unused) +void __noreturn reset_cpu (unsigned long unused) { ulong msr; /* Interrupts and MMU off */ diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c index d63a2f4063..acfa35e035 100644 --- a/arch/sandbox/os/common.c +++ b/arch/sandbox/os/common.c @@ -137,7 +137,7 @@ uint64_t linux_get_time(void) return now; } -int reset_cpu(int unused) +void __attribute__((noreturn)) reset_cpu(int unused) { cookmode(); exit(0); diff --git a/arch/x86/mach-i386/reset.c b/arch/x86/mach-i386/reset.c index a4eb364870..cdd970e53e 100644 --- a/arch/x86/mach-i386/reset.c +++ b/arch/x86/mach-i386/reset.c @@ -25,7 +25,7 @@ #include -void reset_cpu(ulong addr) +void __noreturn reset_cpu(unsigned long addr) { /** How to reset the machine? */ while(1) diff --git a/include/common.h b/include/common.h index 76e9be9c27..3b3d2de8d4 100644 --- a/include/common.h +++ b/include/common.h @@ -80,7 +80,7 @@ int readline (const char *prompt, char *buf, int len); long get_ram_size (volatile long *, long); /* $(CPU)/cpu.c */ -void reset_cpu (ulong addr); +void __noreturn reset_cpu(unsigned long addr); /* $(CPU)/interrupts.c */ //void timer_interrupt (struct pt_regs *); -- cgit v1.2.3 From 2bd7418a0488d8f5ff87c587daf7f2828b270d1d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 30 Mar 2010 10:33:43 +0200 Subject: blackfin: implement arch_shutdown call Signed-off-by: Sascha Hauer --- arch/blackfin/include/asm/common.h | 1 + arch/blackfin/lib/board.c | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/include/asm/common.h b/arch/blackfin/include/asm/common.h index 2ab1954176..1ddcd71a3e 100644 --- a/arch/blackfin/include/asm/common.h +++ b/arch/blackfin/include/asm/common.h @@ -3,3 +3,4 @@ * executing an external program */ #define ARCH_HAS_EXECUTE +#define ARCH_SHUTDOWN diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c index 019995b6a7..294d2b03b1 100644 --- a/arch/blackfin/lib/board.c +++ b/arch/blackfin/lib/board.c @@ -54,3 +54,8 @@ int arch_execute(void * address, int argc, char *argv[]) return ret; } + +void arch_shutdown(void) +{ + icache_disable(); +} -- cgit v1.2.3 From 56299cc7fd2934306c1a9840cfb8edb19b3350b2 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 30 Mar 2010 10:38:01 +0200 Subject: remove now unused arch_execute Signed-off-by: Sascha Hauer --- arch/blackfin/include/asm/common.h | 1 - arch/blackfin/lib/board.c | 11 ----------- include/common.h | 1 - 3 files changed, 13 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/include/asm/common.h b/arch/blackfin/include/asm/common.h index 1ddcd71a3e..fa58e372bb 100644 --- a/arch/blackfin/include/asm/common.h +++ b/arch/blackfin/include/asm/common.h @@ -2,5 +2,4 @@ /* We have to disable instruction cache before * executing an external program */ -#define ARCH_HAS_EXECUTE #define ARCH_SHUTDOWN diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c index 294d2b03b1..581947be26 100644 --- a/arch/blackfin/lib/board.c +++ b/arch/blackfin/lib/board.c @@ -44,17 +44,6 @@ int blackfin_mem_malloc_init(void) core_initcall(blackfin_mem_malloc_init); -int arch_execute(void * address, int argc, char *argv[]) -{ - int ret; - - icache_disable(); - ret = ((ulong (*)(int, char *[]))address) (argc, &argv[0]); - icache_enable(); - - return ret; -} - void arch_shutdown(void) { icache_disable(); diff --git a/include/common.h b/include/common.h index d8130b50ad..319535b376 100644 --- a/include/common.h +++ b/include/common.h @@ -134,7 +134,6 @@ unsigned long strtoul_suffix(const char *str, char **endp, int base); void start_barebox(void); void shutdown_barebox(void); -int arch_execute(void *, int argc, char *argv[]); void arch_shutdown(void); int run_shell(void); -- cgit v1.2.3 From cf2703a6fb96cd7703bd5622d69367696f400af5 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 30 Mar 2010 10:40:06 +0200 Subject: ARM: replace cleanup_before_linux with the generic shutdown_barebox function Signed-off-by: Sascha Hauer --- arch/arm/cpu/cpu.c | 12 +++++------- arch/arm/include/asm/common.h | 2 +- arch/arm/lib/armlinux.c | 6 +++--- 3 files changed, 9 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/arm/cpu/cpu.c b/arch/arm/cpu/cpu.c index 1b8fc970de..a5e2fe2a07 100644 --- a/arch/arm/cpu/cpu.c +++ b/arch/arm/cpu/cpu.c @@ -132,18 +132,16 @@ int icache_status (void) } /** - * Prepare a "clean" CPU for Linux to run + * Disable MMU and D-cache, flush caches * @return 0 (always) * - * This function is called by the generic barebox part just before we call - * Linux. It prepares the processor for Linux. + * This function is called by shutdown_barebox to get a clean + * memory/cache state. */ -int cleanup_before_linux (void) +void arch_shutdown(void) { int i; - shutdown_barebox(); - #ifdef CONFIG_MMU mmu_disable(); #endif @@ -151,8 +149,8 @@ int cleanup_before_linux (void) /* flush I/D-cache */ i = 0; asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); - return 0; } + /** * @page arm_boot_preparation Linux Preparation on ARM * diff --git a/arch/arm/include/asm/common.h b/arch/arm/include/asm/common.h index da84fa5f6b..9afcff78f6 100644 --- a/arch/arm/include/asm/common.h +++ b/arch/arm/include/asm/common.h @@ -1 +1 @@ -/* nothing */ +#define ARCH_SHUTDOWN diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c index 2415c29bc7..019c03022b 100644 --- a/arch/arm/lib/armlinux.c +++ b/arch/arm/lib/armlinux.c @@ -192,7 +192,7 @@ int do_bootm_linux(struct image_data *data) /* we assume that the kernel is in place */ printf("\nStarting kernel ...\n\n"); - cleanup_before_linux(); + shutdown_barebox(); theKernel (0, armlinux_architecture, armlinux_bootparams); return -1; @@ -283,7 +283,7 @@ static int do_bootz(struct command *cmdtp, int argc, char *argv[]) #endif setup_end_tag(); - cleanup_before_linux(); + shutdown_barebox(); theKernel(0, armlinux_architecture, armlinux_bootparams); return 0; @@ -325,7 +325,7 @@ static int do_bootu(struct command *cmdtp, int argc, char *argv[]) setup_commandline_tag(commandline); setup_end_tag(); - cleanup_before_linux(); + shutdown_barebox(); theKernel(0, armlinux_architecture, armlinux_bootparams); return 1; -- cgit v1.2.3 From 6f5a6b591a0cf20caf8fc9c15b271ed59984dbbb Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 30 Mar 2010 10:53:23 +0200 Subject: pass arguments to dma_* as unsigned long as the kernel does Signed-off-by: Sascha Hauer --- arch/arm/include/asm/mmu.h | 12 ++++++------ drivers/net/fec_imx.c | 3 ++- drivers/usb/gadget/fsl_udc.c | 3 ++- drivers/usb/usb_ehci_core.c | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h index 0dd3fa826c..d0a6562152 100644 --- a/arch/arm/include/asm/mmu.h +++ b/arch/arm/include/asm/mmu.h @@ -19,9 +19,9 @@ void setup_dma_coherent(unsigned long offset); void *dma_alloc_coherent(size_t size); void dma_free_coherent(void *mem); -void dma_clean_range(const void *, const void *); -void dma_flush_range(const void *, const void *); -void dma_inv_range(const void *, const void *); +void dma_clean_range(unsigned long, unsigned long); +void dma_flush_range(unsigned long, unsigned long); +void dma_inv_range(unsigned long, unsigned long); unsigned long virt_to_phys(void *virt); void *phys_to_virt(unsigned long phys); @@ -46,15 +46,15 @@ static inline unsigned long virt_to_phys(void *mem) return (unsigned long)mem; } -static inline void dma_clean_range(const void *s, const void *e) +static inline void dma_clean_range(unsigned long s, unsigned long e) { } -static inline void dma_flush_range(const void *s, const void *e) +static inline void dma_flush_range(unsigned long s, unsigned long e) { } -static inline void dma_inv_range(const void *s, const void *e) +static inline void dma_inv_range(unsigned long s, unsigned long e) { } diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c index 49140e7d8f..844033347a 100644 --- a/drivers/net/fec_imx.c +++ b/drivers/net/fec_imx.c @@ -425,7 +425,8 @@ static int fec_send(struct eth_device *dev, void *eth_data, int data_length) writew(data_length, &fec->tbd_base[fec->tbd_index].data_length); writel((uint32_t)(eth_data), &fec->tbd_base[fec->tbd_index].data_pointer); - dma_flush_range(eth_data, eth_data + data_length); + dma_flush_range((unsigned long)eth_data, + (unsigned long)(eth_data + data_length)); /* * update BD's status now * This block: diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c index f6dd3ac444..95f3bdd4f3 100644 --- a/drivers/usb/gadget/fsl_udc.c +++ b/drivers/usb/gadget/fsl_udc.c @@ -1224,7 +1224,8 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req) req->ep = ep; - dma_flush_range(req->req.buf, req->req.buf + req->req.length); + dma_flush_range((unsigned long)req->req.buf, + (unsigned long)(req->req.buf + req->req.length)); req->req.status = -EINPROGRESS; req->req.actual = 0; diff --git a/drivers/usb/usb_ehci_core.c b/drivers/usb/usb_ehci_core.c index cb5a073cc5..d7efaadb8c 100644 --- a/drivers/usb/usb_ehci_core.c +++ b/drivers/usb/usb_ehci_core.c @@ -129,9 +129,9 @@ static struct descriptor { static void flush_invalidate(void *addr, int size, int flush) { if (flush) - dma_flush_range(addr, addr + size); + dma_flush_range((unsigned long)addr, (unsigned long)(addr + size)); else - dma_inv_range(addr, addr + size); + dma_inv_range((unsigned long)addr, (unsigned long)(addr + size)); } static void cache_qtd(struct qTD *qtd, int flush) -- cgit v1.2.3 From bcaabae0f622ed80c9dc34ad671d4f75e6596d9d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 30 Mar 2010 10:57:38 +0200 Subject: ARM: Add a wrapper around dma_* functions This is a preparation to add second level cache support. Signed-off-by: Sascha Hauer --- arch/arm/cpu/cache-armv4.S | 6 +++--- arch/arm/cpu/cache-armv5.S | 6 +++--- arch/arm/cpu/cache-armv6.S | 6 +++--- arch/arm/cpu/cache-armv7.S | 12 ++++++------ arch/arm/cpu/mmu.c | 17 ++++++++++++++++- arch/arm/include/asm/mmu.h | 4 ++++ 6 files changed, 35 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/arm/cpu/cache-armv4.S b/arch/arm/cpu/cache-armv4.S index a0ab256017..a79cc27789 100644 --- a/arch/arm/cpu/cache-armv4.S +++ b/arch/arm/cpu/cache-armv4.S @@ -86,7 +86,7 @@ ENDPROC(__mmu_cache_flush) * * (same as v4wb) */ -ENTRY(dma_inv_range) +ENTRY(__dma_inv_range) tst r0, #CACHE_DLINESIZE - 1 bic r0, r0, #CACHE_DLINESIZE - 1 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry @@ -109,7 +109,7 @@ ENTRY(dma_inv_range) * * (same as v4wb) */ -ENTRY(dma_clean_range) +ENTRY(__dma_clean_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #CACHE_DLINESIZE @@ -126,7 +126,7 @@ ENTRY(dma_clean_range) * - start - virtual start address * - end - virtual end address */ -ENTRY(dma_flush_range) +ENTRY(__dma_flush_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry add r0, r0, #CACHE_DLINESIZE diff --git a/arch/arm/cpu/cache-armv5.S b/arch/arm/cpu/cache-armv5.S index 3618c4495f..f52bcb77ca 100644 --- a/arch/arm/cpu/cache-armv5.S +++ b/arch/arm/cpu/cache-armv5.S @@ -62,7 +62,7 @@ ENDPROC(__mmu_cache_flush) * * (same as v4wb) */ -ENTRY(dma_inv_range) +ENTRY(__dma_inv_range) tst r0, #CACHE_DLINESIZE - 1 bic r0, r0, #CACHE_DLINESIZE - 1 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry @@ -85,7 +85,7 @@ ENTRY(dma_inv_range) * * (same as v4wb) */ -ENTRY(dma_clean_range) +ENTRY(__dma_clean_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #CACHE_DLINESIZE @@ -102,7 +102,7 @@ ENTRY(dma_clean_range) * - start - virtual start address * - end - virtual end address */ -ENTRY(dma_flush_range) +ENTRY(__dma_flush_range) bic r0, r0, #CACHE_DLINESIZE - 1 1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry add r0, r0, #CACHE_DLINESIZE diff --git a/arch/arm/cpu/cache-armv6.S b/arch/arm/cpu/cache-armv6.S index ceabd524bd..e3498bb117 100644 --- a/arch/arm/cpu/cache-armv6.S +++ b/arch/arm/cpu/cache-armv6.S @@ -61,7 +61,7 @@ ENDPROC(__mmu_cache_flush) * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_inv_range) +ENTRY(__dma_inv_range) tst r0, #D_CACHE_LINE_SIZE - 1 bic r0, r0, #D_CACHE_LINE_SIZE - 1 #ifdef HARVARD_CACHE @@ -94,7 +94,7 @@ ENTRY(dma_inv_range) * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_clean_range) +ENTRY(__dma_clean_range) bic r0, r0, #D_CACHE_LINE_SIZE - 1 1: #ifdef HARVARD_CACHE @@ -114,7 +114,7 @@ ENTRY(dma_clean_range) * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_flush_range) +ENTRY(__dma_flush_range) bic r0, r0, #D_CACHE_LINE_SIZE - 1 1: #ifdef HARVARD_CACHE diff --git a/arch/arm/cpu/cache-armv7.S b/arch/arm/cpu/cache-armv7.S index b370acdd9e..9afa20d25a 100644 --- a/arch/arm/cpu/cache-armv7.S +++ b/arch/arm/cpu/cache-armv7.S @@ -128,7 +128,7 @@ ENDPROC(__mmu_cache_flush) * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_inv_range) +ENTRY(__dma_inv_range) dcache_line_size r2, r3 sub r3, r2, #1 tst r0, r3 @@ -145,14 +145,14 @@ ENTRY(dma_inv_range) blo 1b dsb mov pc, lr -ENDPROC(dma_inv_range) +ENDPROC(__dma_inv_range) /* * v7_dma_clean_range(start,end) * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_clean_range) +ENTRY(__dma_clean_range) dcache_line_size r2, r3 sub r3, r2, #1 bic r0, r0, r3 @@ -163,14 +163,14 @@ ENTRY(dma_clean_range) blo 1b dsb mov pc, lr -ENDPROC(dma_clean_range) +ENDPROC(__dma_clean_range) /* * v7_dma_flush_range(start,end) * - start - virtual start address of region * - end - virtual end address of region */ -ENTRY(dma_flush_range) +ENTRY(__dma_flush_range) dcache_line_size r2, r3 sub r3, r2, #1 bic r0, r0, r3 @@ -181,5 +181,5 @@ ENTRY(dma_flush_range) blo 1b dsb mov pc, lr -ENDPROC(dma_flush_range) +ENDPROC(__dma_flush_range) diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c index 4c4e19620a..faf47c5b49 100644 --- a/arch/arm/cpu/mmu.c +++ b/arch/arm/cpu/mmu.c @@ -98,7 +98,7 @@ void *dma_alloc_coherent(size_t size) if (mem) return mem + dma_coherent_offset; - return NULL; + return NULL; } unsigned long virt_to_phys(void *virt) @@ -116,3 +116,18 @@ void dma_free_coherent(void *mem) free(mem - dma_coherent_offset); } +void dma_clean_range(unsigned long start, unsigned long end) +{ + __dma_clean_range(start, end); +} + +void dma_flush_range(unsigned long start, unsigned long end) +{ + __dma_flush_range(start, end); +} + +void dma_inv_range(unsigned long start, unsigned long end) +{ + __dma_inv_range(start, end); +} + diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h index d0a6562152..a77910136a 100644 --- a/arch/arm/include/asm/mmu.h +++ b/arch/arm/include/asm/mmu.h @@ -60,5 +60,9 @@ static inline void dma_inv_range(unsigned long s, unsigned long e) #endif +void __dma_clean_range(unsigned long, unsigned long); +void __dma_flush_range(unsigned long, unsigned long); +void __dma_inv_range(unsigned long, unsigned long); + #endif /* __ASM_MMU_H */ -- cgit v1.2.3 From be00ed538c15a3818c2d692e0e66fd2e75a66a25 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 26 Mar 2010 16:08:21 +0100 Subject: add l2x0 cache support Signed-off-by: Sascha Hauer --- arch/arm/cpu/Kconfig | 8 ++ arch/arm/cpu/Makefile | 2 + arch/arm/cpu/cache-l2x0.c | 183 +++++++++++++++++++++++++++++++++++++++++++++ arch/arm/cpu/mmu.c | 11 +++ arch/arm/include/asm/mmu.h | 11 +++ 5 files changed, 215 insertions(+) create mode 100644 arch/arm/cpu/cache-l2x0.c (limited to 'arch') diff --git a/arch/arm/cpu/Kconfig b/arch/arm/cpu/Kconfig index be01f3d6c7..7e17f9d3e2 100644 --- a/arch/arm/cpu/Kconfig +++ b/arch/arm/cpu/Kconfig @@ -69,3 +69,11 @@ config CPU_BIG_ENDIAN Note that your board must be properly built and your board port must properly enable any big-endian related features of your chipset/board/processor. + +config ARCH_HAS_L2X0 + bool + +config CACHE_L2X0 + bool "Enable L2x0 PrimeCell" + depends on ARCH_HAS_L2X0 + diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile index 7f03436325..ae1f762843 100644 --- a/arch/arm/cpu/Makefile +++ b/arch/arm/cpu/Makefile @@ -16,3 +16,5 @@ obj-$(CONFIG_CPU_32v4T) += cache-armv4.o obj-$(CONFIG_CPU_32v5) += cache-armv5.o obj-$(CONFIG_CPU_32v6) += cache-armv6.o obj-$(CONFIG_CPU_32v7) += cache-armv7.o +obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o + diff --git a/arch/arm/cpu/cache-l2x0.c b/arch/arm/cpu/cache-l2x0.c new file mode 100644 index 0000000000..61569d20b1 --- /dev/null +++ b/arch/arm/cpu/cache-l2x0.c @@ -0,0 +1,183 @@ +#include +#include +#include +#include + +#define CACHE_LINE_SIZE 32 + +static void __iomem *l2x0_base; + +#define L2X0_CACHE_ID 0x000 +#define L2X0_CACHE_TYPE 0x004 +#define L2X0_CTRL 0x100 +#define L2X0_AUX_CTRL 0x104 +#define L2X0_TAG_LATENCY_CTRL 0x108 +#define L2X0_DATA_LATENCY_CTRL 0x10C +#define L2X0_EVENT_CNT_CTRL 0x200 +#define L2X0_EVENT_CNT1_CFG 0x204 +#define L2X0_EVENT_CNT0_CFG 0x208 +#define L2X0_EVENT_CNT1_VAL 0x20C +#define L2X0_EVENT_CNT0_VAL 0x210 +#define L2X0_INTR_MASK 0x214 +#define L2X0_MASKED_INTR_STAT 0x218 +#define L2X0_RAW_INTR_STAT 0x21C +#define L2X0_INTR_CLEAR 0x220 +#define L2X0_CACHE_SYNC 0x730 +#define L2X0_INV_LINE_PA 0x770 +#define L2X0_INV_WAY 0x77C +#define L2X0_CLEAN_LINE_PA 0x7B0 +#define L2X0_CLEAN_LINE_IDX 0x7B8 +#define L2X0_CLEAN_WAY 0x7BC +#define L2X0_CLEAN_INV_LINE_PA 0x7F0 +#define L2X0_CLEAN_INV_LINE_IDX 0x7F8 +#define L2X0_CLEAN_INV_WAY 0x7FC +#define L2X0_LOCKDOWN_WAY_D 0x900 +#define L2X0_LOCKDOWN_WAY_I 0x904 +#define L2X0_TEST_OPERATION 0xF00 +#define L2X0_LINE_DATA 0xF10 +#define L2X0_LINE_TAG 0xF30 +#define L2X0_DEBUG_CTRL 0xF40 + +static inline void cache_wait(void __iomem *reg, unsigned long mask) +{ + /* wait for the operation to complete */ + while (readl(reg) & mask) + ; +} + +static inline void cache_sync(void) +{ + void __iomem *base = l2x0_base; + writel(0, base + L2X0_CACHE_SYNC); + cache_wait(base + L2X0_CACHE_SYNC, 1); +} + +static inline void l2x0_clean_line(unsigned long addr) +{ + void __iomem *base = l2x0_base; + cache_wait(base + L2X0_CLEAN_LINE_PA, 1); + writel(addr, base + L2X0_CLEAN_LINE_PA); +} + +static inline void l2x0_inv_line(unsigned long addr) +{ + void __iomem *base = l2x0_base; + cache_wait(base + L2X0_INV_LINE_PA, 1); + writel(addr, base + L2X0_INV_LINE_PA); +} + +static inline void l2x0_flush_line(unsigned long addr) +{ + void __iomem *base = l2x0_base; + + /* Clean by PA followed by Invalidate by PA */ + cache_wait(base + L2X0_CLEAN_LINE_PA, 1); + writel(addr, base + L2X0_CLEAN_LINE_PA); + cache_wait(base + L2X0_INV_LINE_PA, 1); + writel(addr, base + L2X0_INV_LINE_PA); +} + +static inline void l2x0_inv_all(void) +{ + /* invalidate all ways */ + writel(0xff, l2x0_base + L2X0_INV_WAY); + cache_wait(l2x0_base + L2X0_INV_WAY, 0xff); + cache_sync(); +} + +static void l2x0_inv_range(unsigned long start, unsigned long end) +{ + if (start & (CACHE_LINE_SIZE - 1)) { + start &= ~(CACHE_LINE_SIZE - 1); + l2x0_flush_line(start); + start += CACHE_LINE_SIZE; + } + + if (end & (CACHE_LINE_SIZE - 1)) { + end &= ~(CACHE_LINE_SIZE - 1); + l2x0_flush_line(end); + } + + while (start < end) { + unsigned long blk_end = start + min(end - start, 4096UL); + + while (start < blk_end) { + l2x0_inv_line(start); + start += CACHE_LINE_SIZE; + } + } + cache_wait(l2x0_base + L2X0_INV_LINE_PA, 1); + cache_sync(); +} + +static void l2x0_clean_range(unsigned long start, unsigned long end) +{ + void __iomem *base = l2x0_base; + + start &= ~(CACHE_LINE_SIZE - 1); + while (start < end) { + unsigned long blk_end = start + min(end - start, 4096UL); + + while (start < blk_end) { + l2x0_clean_line(start); + start += CACHE_LINE_SIZE; + } + } + cache_wait(base + L2X0_CLEAN_LINE_PA, 1); + cache_sync(); +} + +void l2x0_flush_range(unsigned long start, unsigned long end) +{ + start &= ~(CACHE_LINE_SIZE - 1); + while (start < end) { + unsigned long blk_end = start + min(end - start, 4096UL); + + while (start < blk_end) { + l2x0_flush_line(start); + start += CACHE_LINE_SIZE; + } + } + cache_wait(l2x0_base + L2X0_CLEAN_INV_LINE_PA, 1); + cache_sync(); +} + +static void l2x0_disable(void) +{ + writel(0xff, l2x0_base + L2X0_CLEAN_INV_WAY); + while (readl(l2x0_base + L2X0_CLEAN_INV_WAY)); + writel(0, l2x0_base + L2X0_CTRL); +} + +void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) +{ + __u32 aux; + + l2x0_base = base; + + /* + * Check if l2x0 controller is already enabled. + * If you are booting from non-secure mode + * accessing the below registers will fault. + */ + if (!(readl(l2x0_base + L2X0_CTRL) & 1)) { + + /* l2x0 controller is disabled */ + + aux = readl(l2x0_base + L2X0_AUX_CTRL); + aux &= aux_mask; + aux |= aux_val; + writel(aux, l2x0_base + L2X0_AUX_CTRL); + + l2x0_inv_all(); + + /* enable L2X0 */ + writel(1, l2x0_base + L2X0_CTRL); + } + + outer_cache.inv_range = l2x0_inv_range; + outer_cache.clean_range = l2x0_clean_range; + outer_cache.flush_range = l2x0_flush_range; + outer_cache.disable = l2x0_disable; +} + diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c index faf47c5b49..66ee9872f8 100644 --- a/arch/arm/cpu/mmu.c +++ b/arch/arm/cpu/mmu.c @@ -60,12 +60,17 @@ void mmu_enable(void) ); } +struct outer_cache_fns outer_cache; + /* * Clean and invalide caches, disable MMU */ void mmu_disable(void) { + if (outer_cache.disable) + outer_cache.disable(); + asm volatile ( "bl __mmu_cache_flush;" "bl __mmu_cache_off;" @@ -118,16 +123,22 @@ void dma_free_coherent(void *mem) void dma_clean_range(unsigned long start, unsigned long end) { + if (outer_cache.clean_range) + outer_cache.clean_range(start, end); __dma_clean_range(start, end); } void dma_flush_range(unsigned long start, unsigned long end) { + if (outer_cache.flush_range) + outer_cache.flush_range(start, end); __dma_flush_range(start, end); } void dma_inv_range(unsigned long start, unsigned long end) { + if (outer_cache.inv_range) + outer_cache.inv_range(start, end); __dma_inv_range(start, end); } diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h index a77910136a..fdd23b5549 100644 --- a/arch/arm/include/asm/mmu.h +++ b/arch/arm/include/asm/mmu.h @@ -60,6 +60,17 @@ static inline void dma_inv_range(unsigned long s, unsigned long e) #endif +void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); + +struct outer_cache_fns { + void (*inv_range)(unsigned long, unsigned long); + void (*clean_range)(unsigned long, unsigned long); + void (*flush_range)(unsigned long, unsigned long); + void (*disable)(void); +}; + +extern struct outer_cache_fns outer_cache; + void __dma_clean_range(unsigned long, unsigned long); void __dma_flush_range(unsigned long, unsigned long); void __dma_inv_range(unsigned long, unsigned long); -- cgit v1.2.3 From 844ca16e1f9b398ab118587d32e65e8f7d1f77d2 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 30 Mar 2010 11:07:43 +0200 Subject: pcm043: enable l2x0 cache Also, initialize the MMU in a postcore_initcall to enable it earlier. Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/Kconfig | 3 ++- board/pcm043/pcm043.c | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index eeb392aa1e..10561f0866 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -228,7 +228,8 @@ config MACH_PCM043 bool "phyCORE-i.MX35" select HAS_CFI select HAVE_MMU - select MACH_HAS_LOWLEVEL_INIT + select MACH_HAS_LOWLEVEL_INIT + select ARCH_HAS_L2X0 help Say Y here if you are using Phytec's phyCORE-i.MX35 (pcm043) equipped with a Freescale i.MX35 Processor diff --git a/board/pcm043/pcm043.c b/board/pcm043/pcm043.c index 7b0bad1fb3..2ce7e3a587 100644 --- a/board/pcm043/pcm043.c +++ b/board/pcm043/pcm043.c @@ -145,7 +145,7 @@ static struct device_d imx_ipu_fb_dev = { }; #ifdef CONFIG_MMU -static void pcm043_mmu_init(void) +static int pcm043_mmu_init(void) { mmu_init(); @@ -159,20 +159,21 @@ static void pcm043_mmu_init(void) #else arm_create_section(0x0, TEXT_BASE, 1, PMD_SECT_DEF_UNCACHED); #endif + mmu_enable(); + +#ifdef CONFIG_CACHE_L2X0 + l2x0_init((void __iomem *)0x30000000, 0x00030024, 0x00000000); +#endif + return 0; } -#else -static void pcm043_mmu_init(void) -{ -} +postcore_initcall(pcm043_mmu_init); #endif static int imx35_devices_init(void) { uint32_t reg; - pcm043_mmu_init(); - /* CS0: Nor Flash */ writel(0x0000cf03, CSCR_U(0)); writel(0x10000d03, CSCR_L(0)); -- cgit v1.2.3