armv7: cache maintenance operations
v2 cover armv7: cache maintenance operations
With D-cache and MMU enabled for ARM in u-boot it becomes imperative to support a minimal set of cache maintenance operations and necessary initializations before enabling MMU.
This series of patches attempt to do the following for armv7:
* Necessary initialization sequence before enabling MMU that includes invalidation of TLB, data caches, branch predictor array etc.
* Framework for supporting SOC specific outer caches in a generic manner (using a structure of function pointers - inspired by the Linux implementation)
* Generic armv7 cache maintenance operations for caches known to the CPU
* Support for ARM PL310 L2 cache controller used in OMAP4
* Cleanup of the cleanup_before_linux() function
* Adapting all armv7 SOCs to use the new framework and removing duplicated code
Testing:
* Extensive testing on OMAP4430SDP and OMAP3430SDP by creating coherency issues and solving them using the maintenance routines
- Eg: memfill a region of memory with a known pattern
- Invalidate the region
- Read back and compare the region with the original pattern
- If match fails it means that invalidate is successful
- Now add a flush call just before the invalidate
- If match succeeds it means that flush was successful
- Outer caches were tested with experiments involving making the function pointers NULL
* Kernel booting on OMAP4430SDP and OMAP3430SDP
Note: v2 has been tested only on OMAP4430SDP
v2:
* Pointer based callback mechanism for outer cache operations changed to a weakly linked functions.
* Change -march=armv7-a back to armv5
* Moved utility macros out of armv7.h
* Added documentation for new CONFIG options.
* Changed implementation of log2n to not use CLZ instruction as armv4 doesn't support this instruction and newly added Tegra2 uses -march=armv4
* Blank line after local variable declarations - fixed globally
* Explicitly added an empty flush_cache() under
#ifdef CONFIG_SYS_NO_DCACHE
* Removed the print inside the weakly linked stub function - __arm_init_before_mmu
* Fixed signature of flush_cache in cache.c
* More descriptive commit message for the PL310 support patch
* C struct for PL310 register accesses
* Fixed white space issues
Aneesh V (10):
arm: make default implementation of cache_flush() weakly linked
armv7: add miscellaneous utility macros
armv7: cache maintenance operations for armv7
armv7: replace CONFIG_L2_OFF with CONFIG_SYS_NO_L2CACHE
armv7: integrate cache maintenance support
arm: minor fixes for cache and mmu handling
armv7: add PL310 support to u-boot
armv7: adapt omap4 to the new cache maintenance framework
armv7: adapt omap3 to the new cache maintenance framework
armv7: adapt s5pc1xx to the new cache maintenance framework
README | 11 + arch/arm/cpu/armv7/Makefile | 2 +- arch/arm/cpu/armv7/cache_v7.c | 390 +++++++++++++++++++++++++ arch/arm/cpu/armv7/cpu.c | 51 ++-- arch/arm/cpu/armv7/omap3/Makefile | 1 - arch/arm/cpu/armv7/omap3/board.c | 138 ++++++++-- arch/arm/cpu/armv7/omap3/cache.S | 263 ----------------- arch/arm/cpu/armv7/omap3/lowlevel_init.S | 32 ++ arch/arm/cpu/armv7/omap4/lowlevel_init.S | 18 ++ arch/arm/cpu/armv7/s5pc1xx/cache.S | 88 +----- arch/arm/cpu/armv7/start.S | 18 +- arch/arm/include/asm/arch-omap3/omap3.h | 20 ++ arch/arm/include/asm/arch-omap3/sys_proto.h | 10 +- arch/arm/include/asm/arch-omap4/sys_proto.h | 1 - arch/arm/include/asm/arch-s5pc1xx/sys_proto.h | 3 - arch/arm/include/asm/armv7.h | 68 +++++ arch/arm/include/asm/pl310.h | 74 +++++ arch/arm/include/asm/utils.h | 80 +++++ arch/arm/lib/Makefile | 1 + arch/arm/lib/board.c | 6 + arch/arm/lib/cache-cp15.c | 16 +- arch/arm/lib/cache-pl310.c | 116 ++++++++ arch/arm/lib/cache.c | 20 +- include/common.h | 5 +- include/configs/ca9x4_ct_vxp.h | 2 +- include/configs/efikamx.h | 2 +- include/configs/mx51evk.h | 2 +- include/configs/mx53evk.h | 2 +- include/configs/omap4_panda.h | 8 +- include/configs/omap4_sdp4430.h | 8 +- include/configs/s5pc210_universal.h | 2 +- include/configs/tegra2-common.h | 2 +- include/configs/vision2.h | 2 +- 33 files changed, 1037 insertions(+), 425 deletions(-) create mode 100644 arch/arm/cpu/armv7/cache_v7.c delete mode 100644 arch/arm/cpu/armv7/omap3/cache.S create mode 100644 arch/arm/include/asm/armv7.h create mode 100644 arch/arm/include/asm/pl310.h create mode 100644 arch/arm/include/asm/utils.h create mode 100644 arch/arm/lib/cache-pl310.c
PATCH v2 1/10 arm: make default implementation of cache_flush() weakly linked
make default implementation of cache_flush() weakly linked so that sub-architectures can override it
--- arch/arm/lib/cache.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/arm/lib/cache.c +3 -1
@@ -25,7 +25,7 @@#include <common.h> -void flush_cache (unsigned long dummy1,unsigned long dummy2) +void __flush_cache (unsigned long start,unsigned long size) {#if defined(CONFIG_OMAP2420 ) || defined(CONFIG_ARM1136 )void arm1136_cache_flush (void );
@@ -45,3 +45,5 @@ void flush_cache (unsigned long dummy1, unsigned long dummy2)#endif return ; } +void flush_cache (unsigned long start,unsigned long size) + __attribute__((weak,alias ("__flush_cache" )));
Signature · 1 line
1.7.0.4
PATCH v2 2/10 armv7: add miscellaneous utility macros
In reply to Aneesh Vadd utility macros for:
* bit field operations
* log2n functions
--- arch/arm/include/asm/utils.h | 80 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 80 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/utils.h
arch/arm/include/asm/utils.h new file +80 -0
@@ -0,0 +1,80 @@ +/* +* (C) Copyright 2010 +* Texas Instruments, <www.ti.com> +* +* Aneesh V <[email protected]> +* +* See file CREDITS for list of people who contributed to this +* project. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, +* MA 02111-1307 USA +*/ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +/* extract a bit field from a bit vector */ +#define get_bit_field (nr, start, mask)\ + (((nr) & (mask)) >> (start)) + +/* Set a field in a bit vector */ +#define set_bit_field (nr, start, mask, val)\ + do { \ + (nr) = ((nr) & ~(mask)) | (((val) << (start)) & (mask));\ + } while (0); + +/* +* Utility macro for read-modify-write of a hardware register +* addr - address of the register +* shift - starting bit position of the field to be modified +* msk - mask for the field +* val - value to be shifted masked and written to the field +*/ +#define modify_reg_32 (addr, shift, msk, val) \ + do {\ + writel(((readl(addr) & ~(msk))|(((val) << (shift)) & (msk))),\ + (addr));\ + } while (0); + +static inline s32 log_2_n_round_up (u32 n) +{ +s32 log2n =-1 ; +u32 temp = n; + +while (temp) { + log2n++; + temp >>=1 ; + } + +if (n & (n -1 )) +return log2n +1 ;/* not power of 2 - round up */ +else +return log2n;/* power of 2 */ +} + +static inline s32 log_2_n_round_down (u32 n) +{ +s32 log2n =-1 ; +u32 temp = n; + +while (temp) { + log2n++; + temp >>=1 ; + } + +return log2n; +} + +#endif /* _OMAP_COMMON_H_ */
Signature · 1 line
1.7.0.4
PATCH v2 3/10 armv7: cache maintenance operations for armv7
In reply to Aneesh V- Add a framework for layered cache maintenance
- separate out SOC specific outer cache maintenance from maintenance of caches known to CPU
- Add generic ARMv7 cache maintenance operations that affect all caches known to ARMv7 CPUs. For instance in Cortex-A8 these opertions will affect both L1 and L2 caches. In Cortex-A9 these will affect only L1 cache
- D-cache operations supported:
- Invalidate entire D-cache
- Invalidate D-cache range
- Flush(clean & invalidate) entire D-cache
- Flush D-cache range
- I-cache operations supported:
- Invalidate entire I-cache
- Add maintenance functions for TLB, branch predictor array etc.
- Enable -march=armv7-a so that armv7 assembly instructions can be used
--- README | 5 + arch/arm/cpu/armv7/Makefile | 2 +- arch/arm/cpu/armv7/cache_v7.c | 390 +++++++++++++++++++++++++++++++++++++++++ arch/arm/include/asm/armv7.h | 68 +++++++ include/common.h | 5 +- 5 files changed, 468 insertions(+), 2 deletions(-) create mode 100644 arch/arm/cpu/armv7/cache_v7.c create mode 100644 arch/arm/include/asm/armv7.h
README +5 -0
@@ -448,6 +448,11 @@ The following options need to be configured: Note: If a "bootargs" environment is defined, it will overwride the defaults discussed just above. +- Cache Configuration: + CONFIG_SYS_NO_ICACHE - Do not enable instruction cache in U-Boot + CONFIG_SYS_NO_DCACHE - Do not enable data cache in U-Boot + CONFIG_SYS_NO_L2CACHE- Do not enable L2 cache in U-Boot + - Serial Ports: CONFIG_PL010_SERIAL
arch/arm/cpu/armv7/Makefile +1 -1
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).o START := start.o -COBJS := cpu.o +COBJS := cpu.o cache_v7.o COBJS += syslib.o SRCS := $(START:.o=.S) $(COBJS:.o=.c)
arch/arm/cpu/armv7/cache_v7.c new file +390 -0
390 lines not on this page · raw message
arch/arm/include/asm/armv7.h new file +68 -0
68 lines not on this page · raw message
include/common.h +4 -1
@@ -411,6 +411,7 @@ void icache_disable(void);int dcache_status (void );void dcache_enable (void );void dcache_disable (void ); +void mmu_disable (void );void relocate_code (ulong ,gd_t *,ulong ) __attribute__ ((noreturn));ulong get_endaddr (void );void trap_init (ulong );
@@ -603,9 +604,11 @@ ulong video_setmem (ulong);/* arch/$(ARCH)/lib/cache.c */ void flush_cache (unsigned long ,unsigned long ); +void flush_dcache_all (void );void flush_dcache_range (unsigned long start,unsigned long stop);void invalidate_dcache_range (unsigned long start,unsigned long stop); - +void invalidate_dcache_all (void ); +void invalidate_icache_all (void );/* arch/$(ARCH)/lib/ticks.S */ unsigned long long get_ticks (void );
Signature · 1 line
1.7.0.4
PATCH v2 4/10 armv7: replace CONFIG_L2_OFF with CONFIG_SYS_NO_L2CACHE
In reply to Aneesh Vreplace all occurences of CONFIG_L2_OFF with a more appropriate CONFIG_SYS_NO_L2CACHE
CONFIG_SYS_NO_L2CACHE has been chosen to be in line with CONFIG_SYS_NO_ICACHE and CONFIG_SYS_NO_DCACHE
--- arch/arm/cpu/armv7/cpu.c | 6 +----- include/configs/ca9x4_ct_vxp.h | 2 +- include/configs/efikamx.h | 2 +- include/configs/mx51evk.h | 2 +- include/configs/mx53evk.h | 2 +- include/configs/omap4_panda.h | 2 +- include/configs/omap4_sdp4430.h | 2 +- include/configs/s5pc210_universal.h | 2 +- include/configs/tegra2-common.h | 2 +- include/configs/vision2.h | 2 +- 10 files changed, 10 insertions(+), 14 deletions(-)
arch/arm/cpu/armv7/cpu.c +1 -5
@@ -35,11 +35,7 @@#include <command.h> #include <asm/system.h> #include <asm/cache.h> -#ifndef CONFIG_L2_OFF -#include <asm/arch/sys_proto.h> -#endif - -static void cache_flush (void ); +#include <asm/armv7.h> int cleanup_before_linux (void ) {
include/configs/ca9x4_ct_vxp.h +1 -1
@@ -40,7 +40,7 @@#define CONFIG_CMDLINE_TAG 1/* enable passing of ATAGs */ #define CONFIG_SETUP_MEMORY_TAGS 1 -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_NO_L2CACHE 1#define CONFIG_INITRD_TAG 1/* Size of malloc() pool */
include/configs/efikamx.h +1 -1
@@ -38,7 +38,7 @@#define CONFIG_DISPLAY_CPUINFO #define CONFIG_DISPLAY_BOARDINFO -#define CONFIG_L2_OFF +#define CONFIG_SYS_NO_L2CACHE /* * Bootloader Components Configuration
include/configs/mx51evk.h +1 -1
@@ -33,7 +33,7 @@#define CONFIG_DISPLAY_CPUINFO #define CONFIG_DISPLAY_BOARDINFO -#define CONFIG_L2_OFF +#define CONFIG_SYS_NO_L2CACHE #include <asm/arch/imx-regs.h> /*
include/configs/mx53evk.h +1 -1
@@ -29,7 +29,7 @@#define CONFIG_DISPLAY_CPUINFO #define CONFIG_DISPLAY_BOARDINFO -#define CONFIG_L2_OFF +#define CONFIG_SYS_NO_L2CACHE #include <asm/arch/imx-regs.h>
include/configs/omap4_panda.h +1 -1
@@ -46,7 +46,7 @@#define CONFIG_DISPLAY_BOARDINFO 1/* Keep L2 Cache Disabled */ -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_NO_L2CACHE 1/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */
include/configs/omap4_sdp4430.h +1 -1
@@ -47,7 +47,7 @@#define CONFIG_DISPLAY_BOARDINFO 1/* Keep L2 Cache Disabled */ -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_NO_L2CACHE 1/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */
include/configs/s5pc210_universal.h +1 -1
@@ -43,7 +43,7 @@#define CONFIG_DISPLAY_BOARDINFO /* Keep L2 Cache Disabled */ -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_NO_L2CACHE 1#define CONFIG_SYS_SDRAM_BASE 0x40000000#define CONFIG_SYS_TEXT_BASE 0x44800000
include/configs/tegra2-common.h +1 -1
@@ -31,7 +31,7 @@#define CONFIG_ARMCORTEXA9 /* This is an ARM V7 CPU core */ #define CONFIG_TEGRA2 /* in a NVidia Tegra2 core */ #define CONFIG_MACH_TEGRA_GENERIC /* which is a Tegra generic machine */ -#define CONFIG_L2_OFF /* No L2 cache */ +#define CONFIG_SYS_NO_L2CACHE /* No L2 cache */ #include <asm/arch/tegra2.h> /* get chip and board defs */
include/configs/vision2.h +1 -1
@@ -26,7 +26,7 @@#define CONFIG_MX51 /* in a mx51 */ -#define CONFIG_L2_OFF +#define CONFIG_SYS_NO_L2CACHE #include <asm/arch/imx-regs.h>
Signature · 1 line
1.7.0.4
PATCH v2 5/10 armv7: integrate cache maintenance support
In reply to Aneesh V- Enable I-cache on bootup
- Enable MMU and D-cache immediately after relocation
- Do necessary initialization before enabling d-cache and MMU
- Changes to cleanup_before_linux()
- Make changes according to the new framework
--- arch/arm/cpu/armv7/cpu.c | 45 +++++++++++++++++++------------------------ arch/arm/cpu/armv7/start.S | 18 ++++++++++++++++- arch/arm/lib/board.c | 6 +++++ arch/arm/lib/cache-cp15.c | 7 ++++++ arch/arm/lib/cache.c | 5 ---- 5 files changed, 50 insertions(+), 31 deletions(-)
arch/arm/cpu/armv7/cpu.c +20 -25
@@ -34,13 +34,10 @@#include <common.h> #include <command.h> #include <asm/system.h> -#include <asm/cache.h> #include <asm/armv7.h> int cleanup_before_linux (void ) { -unsigned int i; -/* * this function is called just before we call linux * it prepares the processor for linux
@@ -49,31 +46,29 @@ int cleanup_before_linux(void)*/ disable_interrupts (); -/* turn off I/D-cache */ +/* +* Turn off I-cache and invalidate it +*/ icache_disable (); -dcache_disable (); +invalidate_icache_all (); -/* invalidate I-cache */ -cache_flush (); - -#ifndef CONFIG_L2_OFF -/* turn off L2 cache */ -l2_cache_disable (); -/* invalidate L2 cache also */ -invalidate_dcache (get_device_type ()); -#endif - i =0 ; -/* mem barrier to sync up things */ - asm("mcr p15, 0, %0, c7, c10, 4" : :"r" (i)); +/* +* turn off D-cache +* dcache_disable() in turn flushes the d-cache and disables MMU +*/ +dcache_disable (); -#ifndef CONFIG_L2_OFF -l2_cache_enable (); -#endif +/* +* After D-cache is flushed and before it is disabled there may +* be some new valid entries brought into the cache. We are sure +* that these lines are not dirty and will not affect our execution. +* (because unwinding the call-stack and setting a bit in CP15 SCTRL +* is all we did during this. We have not pushed anything on to the +* stack. Neither have we affected any static data) +* So just invalidate the entire d-cache again to avoid coherency +* problems for kernel +*/ +invalidate_dcache_all ();return 0 ; } - -static void cache_flush (void ) -{ - asm ("mcr p15, 0, %0, c7, c5, 0" : :"r" (0 )); -}
arch/arm/cpu/armv7/start.S +17 -1
@@ -239,6 +239,14 @@ clbss_l:str r2, [r0] /* clear loop... */ * initialization, now running from RAM. */ jump_2_ram: +/* + * If I-cache is enabled invalidate it + */ +#ifndef CONFIG_SYS_NO_ICACHE + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB +#endif ldr r0, _board_init_r_ofs adr r1, _start add lr, r0, r1
@@ -274,6 +282,9 @@ cpu_init_crit: mov r0, #0 @ set up for MCR mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB /* * disable MMU stuff and caches
@@ -282,7 +293,12 @@ cpu_init_crit: bic r0, r0, #0x00002000 @ clear bits 13 (--V-) bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align - orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB +#ifdef CONFIG_SYS_NO_ICACHE + bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache +#else + orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache +#endif mcr p15, 0, r0, c1, c0, 0 /*
arch/arm/lib/board.c +6 -0
@@ -459,6 +459,12 @@ void board_init_r (gd_t *id, ulong dest_addr) gd->flags |=GD_FLG_RELOC ;/* tell others: relocation done */ +/* +* Enable D$: +* I$, if needed, must be already enabled in start.S +*/ +dcache_enable (); + monitor_flash_len = _bss_start_ofs;debug ("monitor flash len: %08lX\n" , monitor_flash_len);board_init ();/* Setup chipselects */
arch/arm/lib/cache-cp15.c +7 -0
@@ -34,6 +34,12 @@DECLARE_GLOBAL_DATA_PTR ; +void __arm_init_before_mmu (void ) +{ +} +void arm_init_before_mmu (void ) + __attribute__((weak,alias ("__arm_init_before_mmu" ))); +static void cp_delay (void ) {volatile int i;
@@ -65,6 +71,7 @@ static inline void mmu_setup(void)int i;u32 reg; +arm_init_before_mmu ();/* Set up an identity-mapping for all 4GB, rw for everyone */ for (i =0 ; i <4096 ; i++) page_table[i] = i <<20 | (3 <<10 ) |0x12 ;
arch/arm/lib/cache.c +0 -5
@@ -38,11 +38,6 @@ void __flush_cache(unsigned long start, unsigned long size)/* disable write buffer as well (page 2-22) */ asm("mcr p15, 0, %0, c7, c10, 4" : :"r" (0 ));#endif -#ifdef CONFIG_OMAP34XX -void v7_flush_cache_all (void ); - -v7_flush_cache_all (); -#endif return ; }void flush_cache (unsigned long start,unsigned long size)
Signature · 1 line
1.7.0.4
PATCH v2 6/10 arm: minor fixes for cache and mmu handling
In reply to Aneesh V1. make sure that page table setup is not done multiple times
2. flush_dcache_all() is more appropriate while disabling cache than a range flush on the entire memory(flush_cache())
Provide a default implementation for flush_dcache_all() for backward compatibility and to avoid build issues.
--- arch/arm/lib/cache-cp15.c | 9 +++++++-- arch/arm/lib/cache.c | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-)
arch/arm/lib/cache-cp15.c +7 -2
@@ -92,13 +92,18 @@ static inline void mmu_setup(void)set_cr (reg |CR_M ); } +static int mmu_enabled (void ) +{ +return get_cr () &CR_M ; +} +/* cache_bit must be either CR_I or CR_C */ static void cache_enable (uint32_t cache_bit) {uint32_t reg;/* The data cache is not active unless the mmu is enabled too */ -if (cache_bit ==CR_C ) +if ((cache_bit ==CR_C ) && !mmu_enabled ())mmu_setup (); reg =get_cr ();/* get control reg. */ cp_delay ();
@@ -117,7 +122,7 @@ static void cache_disable(uint32_t cache_bit)return ;/* if disabling data cache, disable mmu too */ cache_bit |=CR_M ; -flush_cache (0 , ~0 ); +flush_dcache_all (); } reg =get_cr ();cp_delay ();
arch/arm/lib/cache.c +11 -0
@@ -42,3 +42,14 @@ void __flush_cache(unsigned long start, unsigned long size) }void flush_cache (unsigned long start,unsigned long size) __attribute__((weak,alias ("__flush_cache" ))); + +/* +* Default implementation: +* do a range flush for the entire range +*/ +void __flush_dcache_all (void ) +{ +flush_cache (0 , ~0 ); +} +void flush_dcache_all (void ) + __attribute__((weak,alias ("__flush_dcache_all" )));
Signature · 1 line
1.7.0.4
PATCH v2 7/10 armv7: add PL310 support to u-boot
In reply to Aneesh VPL310 is the L2$ controller from ARM used in many SoCs including the Cortex-A9 based OMAP4430
Add support for some of the key PL310 operations
- Invalidate all
- Invalidate range
- Flush(clean & invalidate) all
- Flush range
--- README | 6 ++ arch/arm/include/asm/pl310.h | 74 +++++++++++++++++++++++++++ arch/arm/lib/Makefile | 1 + arch/arm/lib/cache-pl310.c | 116 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/pl310.h create mode 100644 arch/arm/lib/cache-pl310.c
README +6 -0
@@ -453,6 +453,12 @@ The following options need to be configured: CONFIG_SYS_NO_DCACHE - Do not enable data cache in U-Boot CONFIG_SYS_NO_L2CACHE- Do not enable L2 cache in U-Boot +- Cache Configuration for ARM: + CONFIG_SYS_L2_PL310 - Enable support for ARM PL310 L2 cache + controller + CONFIG_SYS_PL310_BASE - Physical base address of PL310 + controller register space + - Serial Ports: CONFIG_PL010_SERIAL
arch/arm/include/asm/pl310.h new file +74 -0
74 lines not on this page · raw message
arch/arm/lib/Makefile +1 -0
@@ -42,6 +42,7 @@ COBJS-y += cache.o ifndef CONFIG_SYS_NO_CP15_CACHE COBJS-y += cache-cp15.o endif +COBJS-$(CONFIG_SYS_L2_PL310) += cache-pl310.o COBJS-y += interrupts.o COBJS-y += reset.o
arch/arm/lib/cache-pl310.c new file +116 -0
116 lines not on this page · raw message
Signature · 1 line
1.7.0.4
PATCH v2 8/10 armv7: adapt omap4 to the new cache maintenance framework
In reply to Aneesh Vadapt omap4 to the new layered cache maintenance framework
--- arch/arm/cpu/armv7/omap4/lowlevel_init.S | 18 ++++++++++++++++++ arch/arm/include/asm/arch-omap4/sys_proto.h | 1 - include/configs/omap4_panda.h | 8 +++++--- include/configs/omap4_sdp4430.h | 8 +++++--- 4 files changed, 28 insertions(+), 7 deletions(-)
arch/arm/cpu/armv7/omap4/lowlevel_init.S +18 -0
@@ -45,3 +45,21 @@ lowlevel_init: */ bl s_init pop {ip, pc} + +set_pl310_ctrl_reg: + PUSH {r4-r11, lr} @ save registers - ROM code may pollute + @ our registers + LDR r12, =0x102 @ Set PL310 control register - value in R0 + .word 0xe1600070 @ SMC #0 - hand assembled because -march=armv5 + @ call ROM Code API to set control register + POP {r4-r11, pc} + +.globl v7_outer_cache_enable +v7_outer_cache_enable: + MOV r0, #1 + B set_pl310_ctrl_reg + +.globl v7_outer_cache_disable +v7_outer_cache_disable: + MOV r0, #0 + B set_pl310_ctrl_reg
arch/arm/include/asm/arch-omap4/sys_proto.h +0 -1
@@ -31,7 +31,6 @@ struct omap_sysinfo {void gpmc_init (void );void watchdog_init (void );u32 get_device_type (void ); -void invalidate_dcache (u32 );void set_muxconf_regs (void );void sr32 (void *,u32 ,u32 ,u32 );u32 wait_on_value (u32 ,u32 ,void *,u32 );
include/configs/omap4_panda.h +5 -3
@@ -45,9 +45,6 @@#define CONFIG_DISPLAY_CPUINFO 1#define CONFIG_DISPLAY_BOARDINFO 1 -/* Keep L2 Cache Disabled */ -#define CONFIG_SYS_NO_L2CACHE 1 -/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */ #define V_SCLK V_OSCK
@@ -234,4 +231,9 @@ CONFIG_SYS_INIT_RAM_SIZE - \ GENERATED_GBL_DATA_SIZE) +#ifndef CONFIG_SYS_NO_L2CACHE +#define CONFIG_SYS_L2_PL310 1 +#define CONFIG_SYS_PL310_BASE 0x48242000 +#endif +#endif /* __CONFIG_H */
include/configs/omap4_sdp4430.h +5 -3
@@ -46,9 +46,6 @@#define CONFIG_DISPLAY_CPUINFO 1#define CONFIG_DISPLAY_BOARDINFO 1 -/* Keep L2 Cache Disabled */ -#define CONFIG_SYS_NO_L2CACHE 1 -/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */ #define V_SCLK V_OSCK
@@ -240,4 +237,9 @@ CONFIG_SYS_INIT_RAM_SIZE - \ GENERATED_GBL_DATA_SIZE) +#ifndef CONFIG_SYS_NO_L2CACHE +#define CONFIG_SYS_L2_PL310 1 +#define CONFIG_SYS_PL310_BASE 0x48242000 +#endif +#endif /* __CONFIG_H */
Signature · 1 line
1.7.0.4
PATCH v2 9/10 armv7: adapt omap3 to the new cache maintenance framework
In reply to Aneesh Vadapt omap3 to the new layered cache maintenance framework
--- arch/arm/cpu/armv7/omap3/Makefile | 1 - arch/arm/cpu/armv7/omap3/board.c | 138 ++++++++++++-- arch/arm/cpu/armv7/omap3/cache.S | 263 --------------------------- arch/arm/cpu/armv7/omap3/lowlevel_init.S | 32 ++++ arch/arm/include/asm/arch-omap3/omap3.h | 20 ++ arch/arm/include/asm/arch-omap3/sys_proto.h | 10 +- 6 files changed, 178 insertions(+), 286 deletions(-) delete mode 100644 arch/arm/cpu/armv7/omap3/cache.S
arch/arm/cpu/armv7/omap3/Makefile +0 -1
@@ -26,7 +26,6 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).o SOBJS := lowlevel_init.o -SOBJS += cache.o COBJS += board.o COBJS += clock.o
arch/arm/cpu/armv7/omap3/board.c +119 -19
157 lines not on this page · raw message
arch/arm/cpu/armv7/omap3/cache.S deleted +0 -263
263 lines not on this page · raw message
arch/arm/cpu/armv7/omap3/lowlevel_init.S +32 -0
@@ -35,6 +35,38 @@ _TEXT_BASE: .word CONFIG_SYS_TEXT_BASE /* sdram load addr from config.mk */ +.global omap3_gp_romcode_call +omap3_gp_romcode_call: + PUSH {r4-r12, lr} @ Save all registers from ROM code! + MOV r12, r0 @ Copy the Service ID in R12 + MOV r0, r1 @ Copy parameter to R0 + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c10, 5 @ DMB + .word 0xe1600070 @ SMC #0 to enter monitor - hand assembled + @ because we use -march=armv5 + POP {r4-r12, pc} + +/* + * Funtion for making PPA HAL API calls in secure devices + * Input: + * R0 - Service ID + * R1 - paramer list + */ +.global do_omap3_emu_romcode_call +do_omap3_emu_romcode_call: + PUSH {r4-r12, lr} @ Save all registers from ROM code! + MOV r12, r0 @ Copy the Secure Service ID in R12 + MOV r3, r1 @ Copy the pointer to va_list in R3 + MOV r1, #0 @ Process ID - 0 + MOV r2, #OMAP3_EMU_HAL_START_HAL_CRITICAL @ Copy the pointer + @ to va_list in R3 + MOV r6, #0xFF @ Indicate new Task call + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c10, 5 @ DMB + .word 0xe1600071 @ SMC #1 to call PPA service - hand assembled + @ because we use -march=armv5 + POP {r4-r12, pc} + #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_NAND_BOOT) /************************************************************************** * cpy_clk_code: relocates clock code into SRAM where its safer to execute
arch/arm/include/asm/arch-omap3/omap3.h +20 -0
@@ -145,8 +145,14 @@ struct gpio {#define SRAM_VECT_CODE (SRAM_OFFSET0 | SRAM_OFFSET1 | \ SRAM_OFFSET2) +#define OMAP3_PUBLIC_SRAM_BASE 0x40208000/* Works for GP & EMU */ +#define OMAP3_PUBLIC_SRAM_END 0x40210000 +#define LOW_LEVEL_SRAM_STACK 0x4020FFFC +/* scratch area - accessible on both EMU and GP */ +#define OMAP3_PUBLIC_SRAM_SCRATCH_AREA OMAP3_PUBLIC_SRAM_BASE +#define DEBUG_LED1 149/* gpio */ #define DEBUG_LED2 150/* gpio */
@@ -213,4 +219,18 @@ struct gpio {#define OMAP3730 0x0c00 +/* +* ROM code API related flags +*/ +#define OMAP3_GP_ROMCODE_API_L2_INVAL 1 +#define OMAP3_GP_ROMCODE_API_WRITE_ACR 3 + +/* +* EMU device PPA HAL related flags +*/ +#define OMAP3_EMU_HAL_API_L2_INVAL 40 +#define OMAP3_EMU_HAL_API_WRITE_ACR 42 + +#define OMAP3_EMU_HAL_START_HAL_CRITICAL 4 +#endif
arch/arm/include/asm/arch-omap3/sys_proto.h +7 -3
@@ -27,6 +27,11 @@ typedef struct {char *nand_string; } omap3_sysinfo; +struct emu_hal_params { +u32 num_params; +u32 param1; +}; +void prcm_init (void );void per_clocks_enable (void );
@@ -53,9 +58,7 @@ u32 is_running_in_sdram(void);u32 is_running_in_sram (void );u32 is_running_in_flash (void );u32 get_device_type (void ); -void l2cache_enable (void );void secureworld_exit (void ); -void setup_auxcr (void );void try_unlock_memory (void );u32 get_boot_type (void );void invalidate_dcache (u32 );
@@ -66,5 +69,6 @@ void make_cs1_contiguous(void);void omap_nand_switch_ecc (int );void power_init_r (void );void dieid_num_r (void ); - +void do_omap3_emu_romcode_call (u32 service_id,u32 parameters); +void omap3_gp_romcode_call (u32 service_id,u32 parameter);#endif
Signature · 1 line
1.7.0.4
PATCH v2 10/10 armv7: adapt s5pc1xx to the new cache maintenance framework
In reply to Aneesh Vadapt s5pc1xx to the new layered cache maintenance framework
--- arch/arm/cpu/armv7/s5pc1xx/cache.S | 88 ++----------------------- arch/arm/include/asm/arch-s5pc1xx/sys_proto.h | 3 - 2 files changed, 7 insertions(+), 84 deletions(-)
arch/arm/cpu/armv7/s5pc1xx/cache.S +7 -81
@@ -23,98 +23,24 @@ * MA 02111-1307 USA */ -#include <asm/arch/cpu.h> - .align 5 -.global invalidate_dcache -.global l2_cache_enable -.global l2_cache_disable - -/* - * invalidate_dcache() - * Invalidate the whole D-cache. - * - * Corrupted registers: r0-r5, r7, r9-r11 - */ -invalidate_dcache: - stmfd r13!, {r0 - r5, r7, r9 - r12, r14} - - cmp r0, #0xC100 @ check if the cpu is s5pc100 - beq finished_inval @ s5pc100 doesn't need this - @ routine - mrc p15, 1, r0, c0, c0, 1 @ read clidr - ands r3, r0, #0x7000000 @ extract loc from clidr - mov r3, r3, lsr #23 @ left align loc bit field - beq finished_inval @ if loc is 0, then no need to - @ clean - mov r10, #0 @ start clean at cache level 0 -inval_loop1: - add r2, r10, r10, lsr #1 @ work out 3x current cache - @ level - mov r1, r0, lsr r2 @ extract cache type bits from - @ clidr - and r1, r1, #7 @ mask of the bits for current - @ cache only - cmp r1, #2 @ see what cache we have at - @ this level - blt skip_inval @ skip if no cache, or just - @ i-cache - mcr p15, 2, r10, c0, c0, 0 @ select current cache level - @ in cssr - mov r2, #0 @ operand for mcr SBZ - mcr p15, 0, r2, c7, c5, 4 @ flush prefetch buffer to - @ sych the new cssr&csidr, - @ with armv7 this is 'isb', - @ but we compile with armv5 - mrc p15, 1, r1, c0, c0, 0 @ read the new csidr - and r2, r1, #7 @ extract the length of the - @ cache lines - add r2, r2, #4 @ add 4 (line length offset) - ldr r4, =0x3ff - ands r4, r4, r1, lsr #3 @ find maximum number on the - @ way size - clz r5, r4 @ find bit position of way - @ size increment - ldr r7, =0x7fff - ands r7, r7, r1, lsr #13 @ extract max number of the - @ index size -inval_loop2: - mov r9, r4 @ create working copy of max - @ way size -inval_loop3: - orr r11, r10, r9, lsl r5 @ factor way and cache number - @ into r11 - orr r11, r11, r7, lsl r2 @ factor index number into r11 - mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way - subs r9, r9, #1 @ decrement the way - bge inval_loop3 - subs r7, r7, #1 @ decrement the index - bge inval_loop2 -skip_inval: - add r10, r10, #2 @ increment cache number - cmp r3, r10 - bgt inval_loop1 -finished_inval: - mov r10, #0 @ swith back to cache level 0 - mcr p15, 2, r10, c0, c0, 0 @ select current cache level - @ in cssr - mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, - @ with armv7 this is 'isb', - @ but we compile with armv5 +#if !defined(CONFIG_SYS_NO_DCACHE) && !defined(CONFIG_SYS_NO_L2CACHE) - ldmfd r13!, {r0 - r5, r7, r9 - r12, pc} - -l2_cache_enable: +.global v7_outer_cache_enable +v7_outer_cache_enable: push {r0, r1, r2, lr} mrc 15, 0, r3, cr1, cr0, 1 orr r3, r3, #2 mcr 15, 0, r3, cr1, cr0, 1 pop {r1, r2, r3, pc} -l2_cache_disable: +.global v7_outer_cache_disable +v7_outer_cache_disable: push {r0, r1, r2, lr} mrc 15, 0, r3, cr1, cr0, 1 bic r3, r3, #2 mcr 15, 0, r3, cr1, cr0, 1 pop {r1, r2, r3, pc} + +#endif
arch/arm/include/asm/arch-s5pc1xx/sys_proto.h +0 -3
@@ -25,8 +25,5 @@#define _SYS_PROTO_H_u32 get_device_type (void ); -void invalidate_dcache (u32 ); -void l2_cache_disable (void ); -void l2_cache_enable (void );#endif
Signature · 1 line
1.7.0.4
v2 cover armv7: cache maintenance operations
In reply to Aneesh VHi,
Can I inquire please what has happened with this patch series? Will it be applied? I have done some basic testing here on Tegra2 and it appears to work.
Regards,
Simon
Quoted 108 lines · Aneesh V
With D-cache and MMU enabled for ARM in u-boot it becomes imperative to support a minimal set of cache maintenance operations and necessary initializations before enabling MMU.
This series of patches attempt to do the following for armv7:
* Necessary initialization sequence before enabling MMU that includes invalidation of TLB, data caches, branch predictor array etc.
* Framework for supporting SOC specific outer caches in a generic manner (using a structure of function pointers - inspired by the Linux implementation)
* Generic armv7 cache maintenance operations for caches known to the CPU
* Support for ARM PL310 L2 cache controller used in OMAP4
* Cleanup of thecleanup_before_linux()function
* Adapting all armv7 SOCs to use the new framework and removing duplicated codeTesting:
* Extensive testing on OMAP4430SDP and OMAP3430SDP by creating coherency issues and solving them using the maintenance routines
- Eg: memfill a region of memory with a known pattern
- Invalidate the region
- Read back and compare the region with the original pattern
- If match fails it means that invalidate is successful
- Now add a flush call just before the invalidate
- If match succeeds it means that flush was successful
- Outer caches were tested with experiments involving making the function pointers NULL
* Kernel booting on OMAP4430SDP and OMAP3430SDP
Note: v2 has been tested only on OMAP4430SDPv2:
* Pointer based callback mechanism for outer cache operations changed to a weakly linked functions.
* Change -march=armv7-a back to armv5
* Moved utility macros out ofarmv7.h
* Added documentation for new CONFIG options.
* Changed implementation of log2n to not use CLZ instruction as armv4 doesn't support this instruction and newly added Tegra2 uses -march=armv4
* Blank line after local variable declarations - fixed globally
* Explicitly added an emptyflush_cache()under
#ifdefCONFIG_SYS_NO_DCACHE
* Removed the print inside the weakly linked stub function -__arm_init_before_mmu
* Fixed signature offlush_cacheincache.c
* More descriptive commit message for the PL310 support patch
* C struct for PL310 register accesses
* Fixed white space issuesAneesh V (10):
arm: make default implementation ofcache_flush()weakly linked
armv7: add miscellaneous utility macros
armv7: cache maintenance operations for armv7
armv7: replaceCONFIG_L2_OFFwithCONFIG_SYS_NO_L2CACHE
armv7: integrate cache maintenance support
arm: minor fixes for cache and mmu handling
armv7: add PL310 support to u-boot
armv7: adapt omap4 to the new cache maintenance framework
armv7: adapt omap3 to the new cache maintenance framework
armv7: adapt s5pc1xx to the new cache maintenance frameworkREADME | 11 + arch/arm/cpu/armv7/Makefile | 2 +- arch/arm/cpu/armv7/cache_v7.c | 390 +++++++++++++++++++++++++ arch/arm/cpu/armv7/cpu.c | 51 ++-- arch/arm/cpu/armv7/omap3/Makefile | 1 - arch/arm/cpu/armv7/omap3/board.c | 138 ++++++++-- arch/arm/cpu/armv7/omap3/cache.S | 263 ----------------- arch/arm/cpu/armv7/omap3/lowlevel_init.S | 32 ++ arch/arm/cpu/armv7/omap4/lowlevel_init.S | 18 ++ arch/arm/cpu/armv7/s5pc1xx/cache.S | 88 +----- arch/arm/cpu/armv7/start.S | 18 +- arch/arm/include/asm/arch-omap3/omap3.h | 20 ++ arch/arm/include/asm/arch-omap3/sys_proto.h | 10 +- arch/arm/include/asm/arch-omap4/sys_proto.h | 1 - arch/arm/include/asm/arch-s5pc1xx/sys_proto.h | 3 - arch/arm/include/asm/armv7.h | 68 +++++ arch/arm/include/asm/pl310.h | 74 +++++ arch/arm/include/asm/utils.h | 80 +++++ arch/arm/lib/Makefile | 1 + arch/arm/lib/board.c | 6 + arch/arm/lib/cache-cp15.c | 16 +- arch/arm/lib/cache-pl310.c | 116 ++++++++ arch/arm/lib/cache.c | 20 +- include/common.h | 5 +- include/configs/ca9x4_ct_vxp.h | 2 +- include/configs/efikamx.h | 2 +- include/configs/mx51evk.h | 2 +- include/configs/mx53evk.h | 2 +- include/configs/omap4_panda.h | 8 +- include/configs/omap4_sdp4430.h | 8 +- include/configs/s5pc210_universal.h | 2 +- include/configs/tegra2-common.h | 2 +- include/configs/vision2.h | 2 +- 33 files changed, 1037 insertions(+), 425 deletions(-) create mode 100644 arch/arm/cpu/armv7/cache_v7.c delete mode 100644 arch/arm/cpu/armv7/omap3/cache.S create mode 100644 arch/arm/include/asm/armv7.h create mode 100644 arch/arm/include/asm/pl310.h create mode 100644 arch/arm/include/asm/utils.h create mode 100644 arch/arm/lib/cache-pl310.c_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
v2 cover armv7: cache maintenance operations
Quoted 8 lines · Aneesh V
Quoted 5 lines
With D-cache and MMU enabled for ARM in u-boot it becomes imperative to support a minimal set of cache maintenance operations and necessary initializations before enabling MMU.
Quoted 13 lines
Quoted 13 lines
This series of patches attempt to do the following for armv7:
* Necessary initialization sequence before enabling MMU that includes invalidation of TLB, data caches, branch predictor array etc.
* Framework for supporting SOC specific outer caches in a generic manner (using a structure of function pointers - inspired by the Linux implementation)
* Generic armv7 cache maintenance operations for caches known to the CPU
* Support for ARM PL310 L2 cache controller used in OMAP4
* Cleanup of thecleanup_before_linux()function
* Adapting all armv7 SOCs to use the new framework and removing duplicated code
Any thoughts on this? What is the status please? Will this patch be applied, or if not, what is left to be done?
Regards,
Simon
v2 cover armv7: cache maintenance operations
Albert, Wolfgang,
Do you plan to take this series or do you expect some more changes?
best regards,
Aneesh
Quoted 33 lines · Simon Glass
On Tue, Mar 8, 2011 at 5:07 AM, Aneesh V <[email protected] <mailto:[email protected]>> wrote:
With D-cache and MMU enabled for ARM in u-boot it becomes imperative to
support a minimal set of cache maintenance operations and necessary initializations before enabling MMU.This series of patches attempt to do the following for armv7:
* Necessary initialization sequence before enabling MMU that includes
invalidation of TLB, data caches, branch predictor array etc.
* Framework for supporting SOC specific outer caches in a generic manner
(using a structure of function pointers - inspired by the Linux implementation)
* Generic armv7 cache maintenance operations for caches known to the CPU
* Support for ARM PL310 L2 cache controller used in OMAP4
* Cleanup of thecleanup_before_linux()function
* Adapting all armv7 SOCs to use the new framework and removing duplicated codeAny thoughts on this? What is the status please? Will this patch be applied, or if not, what is left to be done?
Regards,
Simon
v3 cover armv7: cache maintenance operations
In reply to Aneesh VWith D-cache and MMU enabled for ARM in u-boot it becomes imperative to support a minimal set of cache maintenance operations and necessary initializations before enabling MMU.
This series of patches attempt to do the following for armv7:
* Necessary initialization sequence before enabling MMU that includes invalidation of TLB, data caches, branch predictor array etc.
* Framework for supporting SOC specific outer caches in a generic manner (using a structure of function pointers - inspired by the Linux implementation)
* Generic armv7 cache maintenance operations for caches known to the CPU
* Support for ARM PL310 L2 cache controller used in OMAP4
* Cleanup of the cleanup_before_linux() function
* Adapting all armv7 SOCs to use the new framework and removing duplicated code
Testing:
* Extensive testing on OMAP4430SDP and OMAP3430SDP by creating coherency issues and solving them using the maintenance routines
- Eg: memfill a region of memory with a known pattern
- Invalidate the region
- Read back and compare the region with the original pattern
- If match fails it means that invalidate is successful
- Now add a flush call just before the invalidate
- If match succeeds it means that flush was successful
- Outer caches were tested with experiments involving making the function pointers NULL
* Kernel booting on OMAP4430SDP and OMAP3430SDP
Note: v2 has been tested only on OMAP4430SDP
V2:
* Pointer based callback mechanism for outer cache operations changed to a weakly linked functions.
* Change -march=armv7-a back to armv5
* Moved utility macros out of armv7.h
* Added documentation for new CONFIG options.
* Changed implementation of log2n to not use CLZ instruction as armv4 doesn't support this instruction and newly added Tegra2 uses -march=armv4
* Blank line after local variable declarations - fixed globally
* Explicitly added an empty flush_cache() under
#ifdef CONFIG_SYS_NO_DCACHE
* Removed the print inside the weakly linked stub function - __arm_init_before_mmu
* Fixed signature of flush_cache in cache.c
* More descriptive commit message for the PL310 support patch
* C struct for PL310 register accesses
* Fixed white space issues
V3:
* Rebased to latest HEAD of master
* Added comments on changes done in V2 in individual patch headers. This was missing in V2
Aneesh V (10):
arm: make default implementation of cache_flush() weakly linked
armv7: add miscellaneous utility macros
armv7: cache maintenance operations for armv7
armv7: replace CONFIG_L2_OFF with CONFIG_SYS_NO_L2CACHE
armv7: integrate cache maintenance support
arm: minor fixes for cache and mmu handling
armv7: add PL310 support to u-boot
armv7: adapt omap4 to the new cache maintenance framework
armv7: adapt omap3 to the new cache maintenance framework
armv7: adapt s5pc1xx to the new cache maintenance framework
README | 11 + arch/arm/cpu/armv7/Makefile | 2 +- arch/arm/cpu/armv7/cache_v7.c | 390 +++++++++++++++++++++++++ arch/arm/cpu/armv7/cpu.c | 51 ++-- arch/arm/cpu/armv7/omap3/Makefile | 1 - arch/arm/cpu/armv7/omap3/board.c | 138 ++++++++-- arch/arm/cpu/armv7/omap3/cache.S | 263 ----------------- arch/arm/cpu/armv7/omap3/lowlevel_init.S | 32 ++ arch/arm/cpu/armv7/omap4/lowlevel_init.S | 18 ++ arch/arm/cpu/armv7/s5pc1xx/cache.S | 88 +----- arch/arm/cpu/armv7/start.S | 18 +- arch/arm/include/asm/arch-omap3/omap3.h | 20 ++ arch/arm/include/asm/arch-omap3/sys_proto.h | 10 +- arch/arm/include/asm/arch-omap4/sys_proto.h | 1 - arch/arm/include/asm/arch-s5pc1xx/sys_proto.h | 3 - arch/arm/include/asm/armv7.h | 68 +++++ arch/arm/include/asm/pl310.h | 74 +++++ arch/arm/include/asm/utils.h | 80 +++++ arch/arm/lib/Makefile | 1 + arch/arm/lib/board.c | 6 + arch/arm/lib/cache-cp15.c | 16 +- arch/arm/lib/cache-pl310.c | 116 ++++++++ arch/arm/lib/cache.c | 20 +- include/common.h | 5 +- include/configs/ca9x4_ct_vxp.h | 2 +- include/configs/efikamx.h | 2 +- include/configs/mx51evk.h | 2 +- include/configs/mx53evk.h | 2 +- include/configs/omap4_panda.h | 8 +- include/configs/omap4_sdp4430.h | 8 +- include/configs/s5pc210_universal.h | 2 +- include/configs/tegra2-common.h | 2 +- include/configs/vision2.h | 2 +- 33 files changed, 1037 insertions(+), 425 deletions(-) create mode 100644 arch/arm/cpu/armv7/cache_v7.c delete mode 100644 arch/arm/cpu/armv7/omap3/cache.S create mode 100644 arch/arm/include/asm/armv7.h create mode 100644 arch/arm/include/asm/pl310.h create mode 100644 arch/arm/include/asm/utils.h create mode 100644 arch/arm/lib/cache-pl310.c
PATCH v3 1/10 arm: make default implementation of cache_flush() weakly linked
In reply to Aneesh Vmake default implementation of cache_flush() weakly linked so that sub-architectures can override it
--- arch/arm/lib/cache.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/arm/lib/cache.c +3 -1
@@ -25,7 +25,7 @@#include <common.h> -void flush_cache (unsigned long dummy1,unsigned long dummy2) +void __flush_cache (unsigned long start,unsigned long size) {#if defined(CONFIG_OMAP2420 ) || defined(CONFIG_ARM1136 )void arm1136_cache_flush (void );
@@ -45,3 +45,5 @@ void flush_cache (unsigned long dummy1, unsigned long dummy2)#endif return ; } +void flush_cache (unsigned long start,unsigned long size) + __attribute__((weak,alias ("__flush_cache" )));
Signature · 1 line
1.7.0.4
PATCH v3 2/10 armv7: add miscellaneous utility macros
In reply to Aneesh Vadd utility macros for:
* bit field operations
* log2n functions
---
V2:
* Newly added in v2
--- arch/arm/include/asm/utils.h | 80 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 80 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/utils.h
arch/arm/include/asm/utils.h new file +80 -0
@@ -0,0 +1,80 @@ +/* +* (C) Copyright 2010 +* Texas Instruments, <www.ti.com> +* +* Aneesh V <[email protected]> +* +* See file CREDITS for list of people who contributed to this +* project. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, +* MA 02111-1307 USA +*/ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +/* extract a bit field from a bit vector */ +#define get_bit_field (nr, start, mask)\ + (((nr) & (mask)) >> (start)) + +/* Set a field in a bit vector */ +#define set_bit_field (nr, start, mask, val)\ + do { \ + (nr) = ((nr) & ~(mask)) | (((val) << (start)) & (mask));\ + } while (0); + +/* +* Utility macro for read-modify-write of a hardware register +* addr - address of the register +* shift - starting bit position of the field to be modified +* msk - mask for the field +* val - value to be shifted masked and written to the field +*/ +#define modify_reg_32 (addr, shift, msk, val) \ + do {\ + writel(((readl(addr) & ~(msk))|(((val) << (shift)) & (msk))),\ + (addr));\ + } while (0); + +static inline s32 log_2_n_round_up (u32 n) +{ +s32 log2n =-1 ; +u32 temp = n; + +while (temp) { + log2n++; + temp >>=1 ; + } + +if (n & (n -1 )) +return log2n +1 ;/* not power of 2 - round up */ +else +return log2n;/* power of 2 */ +} + +static inline s32 log_2_n_round_down (u32 n) +{ +s32 log2n =-1 ; +u32 temp = n; + +while (temp) { + log2n++; + temp >>=1 ; + } + +return log2n; +} + +#endif /* _OMAP_COMMON_H_ */
Signature · 1 line
1.7.0.4
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Aneesh V,
Quoted 3 lines · In message <[email protected]> you wrote:
add utility macros for:
* bit field operations
* log2n functions
...
arch/arm/include/asm/utils.h line 36
Quoted 9 lines
arch/arm/include/asm/utils.h new file +9
-0+/* extract a bit field from a bit vector */ +#define get_bit_field (nr, start, mask)\ + (((nr) & (mask)) >> (start)) + +/* Set a field in a bit vector */ +#define set_bit_field (nr, start, mask, val)\ + do { \ + (nr) = ((nr) & ~(mask)) | (((val) << (start)) & (mask));\ + } while (0);
I really dislike such "useful" helpers, because they make the code unreadable. Being nonstandrd, nbody knows what they are doing, so you always will have to look up the implementation before you can continue reading the code. It's a waste of time an resources.
arch/arm/include/asm/utils.h line 49
Quoted 12 lines
arch/arm/include/asm/utils.h new file +12
-0+/* +* Utility macro for read-modify-write of a hardware register +* addr - address of the register +* shift - starting bit position of the field to be modified +* msk - mask for the field +* val - value to be shifted masked and written to the field +*/ +#define modify_reg_32 (addr, shift, msk, val) \ + do {\ + writel(((readl(addr) & ~(msk))|(((val) << (shift)) & (msk))),\ + (addr));\ + } while (0);
NAK again, for the same reasons.
Note that there are some semi-standardized I/O accessro macros available, at least for some architectures, like clrbits.*(), setbits_(), or clrsetbits().
See for example "arch/arm/include/asm/io.h",
"arch/powerpc/include/asm/io.h" for reference.
Instead of reinventing the wheel (just differently shaped) we should rather try and use a single, standardized set of such helpers.
So please use the existing macros instead of inventing new, non-standard ones.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
No journaling file system can recover your data if the disk dies.
- Steve Rago in <[email protected]>PATCH v3 2/10 armv7: add miscellaneous utility macros
Quoted 8 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 3 lines · In message <[email protected]> you wrote:
add utility macros for:
* bit field operations
* log2n functions...
Quoted 15 lines
arch/arm/include/asm/utils.h line 36
Quoted 9 lines
arch/arm/include/asm/utils.h new file +9
-0+/* extract a bit field from a bit vector */ +#define get_bit_field (nr, start, mask)\ + (((nr) & (mask)) >> (start)) + +/* Set a field in a bit vector */ +#define set_bit_field (nr, start, mask, val)\ + do { \ + (nr) = ((nr) & ~(mask)) | (((val) << (start)) & (mask));\ + } while (0);I really dislike such "useful" helpers, because they make the code unreadable. Being nonstandrd, nbody knows what they are doing, so you always will have to look up the implementation before you can continue reading the code. It's a waste of time an resources.
Hi Wolfgang,
Please consider my thoughts below on this subject.
It would be good to enhance these helpers to address the bitfield disaster which is a modern SOC.
I agree that having standard helpers is useful and in fact I don't believe the existing clrbits and setbits go far enough. I have noticed that various architectures have their own macros for handling bitfields. Since these are all different (thus you need to read each one to understand the code, as you say) and pan-U-Boot solutions appear to be rejected, we are stuck with bloated, error-prone code full of shifts and masks.
I believe that this problem is getting worse - e.g. USB on Tegra2 writes various fields of about 20 registers to get things up and running. I find translating SOC datasheet register definitions into C code with shifts and masks to be slow and error-prone work. Also we do need to maintain this code, and it gets reused for new SOC variants, etc. So it is not as if it is written once and then buried and forgotten. There is also a tendency to use 'magic' constants rather than #define values or something with a sensible name, then hopefully add a half-hearted comment. This requires constant return looks at the datasheet to see what bits were chosen.
Being a boot loader, charged with basic hardware initialisation, I believe bitfield access primitives should be well-supported by U-Boot.
Would you consider an RFC patch to add pan-U-Boot bitfield operations? Failing that, how about just for ARM?
Regards,
Simon
Quoted 45 lines
arch/arm/include/asm/utils.h
Quoted 11 lines
arch/arm/include/asm/utils.h new file +10
-0+/* +* Utility macro for read-modify-write of a hardware register +* addr - address of the register +* shift - starting bit position of the field to be modified +* msk - mask for the field +* val - value to be shifted masked and written to the field +*/ +#define modify_reg_32 (addr, shift, msk, val) \ + do {\ + writel(((readl(addr) & ~(msk))|(((val) << (shift)) &(msk))),\
arch/arm/include/asm/utils.h line 49
Quoted 2 lines
arch/arm/include/asm/utils.h new file +2
-0+ (addr));\ + }while (0 );NAK again, for the same reasons.
Note that there are some semi-standardized I/O accessro macros available, at least for some architectures, like clrbits.*(),
setbits_(), orclrsetbits().See for example "
arch/arm/include/asm/io.h",
"arch/powerpc/include/asm/io.h" for reference.Instead of reinventing the wheel (just differently shaped) we should rather try and use a single, standardized set of such helpers.
So please use the existing macros instead of inventing new, non-standard ones.
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de No journaling file system can recover your data if the disk dies.
- Steve Rago in <[email protected]>
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
PATCH v3 2/10 armv7: add miscellaneous utility macros
Quoted 9 lines · Simon Glass
I believe that this problem is getting worse - e.g. USB on Tegra2 writes various fields of about 20 registers to get things up and running. I find translating SOC datasheet register definitions into C code with shifts and masks to be slow and error-prone work. Also we do need to maintain this code, and it gets reused for new SOC variants, etc. So it is not as if it is written once and then buried and forgotten. There is also a tendency to use 'magic' constants rather than #define values or something with a sensible name, then hopefully add a half-hearted comment. This requires constant return looks at the datasheet to see what bits were chosen.
I have nothing against helper functions like this (although I think they should be inline functions, not macros, to guard against bugs due to side-effects in arguments).
But wouldn't it be even better to define the registers as C structures containing bitfields, so the C compiler can do the error-prone shifting and masking? Well-commented structure definitions for these registers also eliminate the need to refer back to the datasheet when working on the code.
Signature · 1 line
Eric Cooper e c c @ c m u . e d u
PATCH v3 2/10 armv7: add miscellaneous utility macros
Quoted 9 lines · Eric Cooper
Quoted 3 lines · Simon Glass
I believe that this problem is getting worse - e.g. USB on Tegra2 writes various fields of about 20 registers to get things up and running. I find translating SOC datasheet register definitions into C code with shifts
and
Quoted 2 lines
masks to be slow and error-prone work. Also we do need to maintain this code, and it gets reused for new SOC variants, etc. So it is not as if it
is
Quoted 1 line
written once and then buried and forgotten. There is also a tendency to
Quoted 9 lines
use
Quoted 3 lines
'magic' constants rather than #define values or something with a sensible name, then hopefully add a half-hearted comment. This requires constant return looks at the datasheet to see what bits were chosen.
I have nothing against helper functions like this (although I think they should be inline functions, not macros, to guard against bugs due to side-effects in arguments).
This does limits the functionality unfortunately. With macros it is possible to (for example) derive a shift and mask from a single base token.
Quoted 7 lines
But wouldn't it be even better to define the registers as C structures containing bitfields, so the C compiler can do the error-prone shifting and masking? Well-commented structure definitions for these registers also eliminate the need to refer back to the datasheet when working on the code.
I believe the problem here is the read/modify/write behaviour which is not well-defined in C. One ends up using volatile to ensure the right behaviour, and then this doesn't necessarily work either. Where one write must happen before the next read the compiler must have barriers to indicate this, which would then have to be inserted manually (rather than just in the writel() macro). The opposite problem is that if you update several fields at once the compiler may or may not optimise these into a single access, and this is not under programmer control. So writel() and readl() are preferred.
Perhaps in newer compilers bitfield semantics have been improved?
Quoted 8 lines
--
Eric Cooper e c c @ c m u . e d u
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Simon Glass,
Quoted 4 lines · In message <[email protected]> you wrote:
I believe the problem here is the read/modify/write behaviour which is not well-defined in C. One ends up using volatile to ensure the right behaviour, and then this doesn't necessarily work either. Where one write must happen
volatile does not help anything here. You MUST always make sure to use proper I/O accessors. Even in ARM code this has become mandatory by now, even if older ARM cores and compilers have been forgiving enough for a long time.
Quoted 1 line
Perhaps in newer compilers bitfield semantics have been improved?
Bitfields have always been a mess, and should be avoided like hell.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de There are three things I always forget. Names, faces - the third I can't remember. - Italo Svevo
PATCH v3 2/10 armv7: add miscellaneous utility macros
In reply to Simon GlassDear Simon Glass,
Quoted 3 lines · In message <[email protected]> you wrote:
Being a boot loader, charged with basic hardware initialisation, I believe bitfield access primitives should be well-supported by U-Boot.
I agree, and they are.
Quoted 2 lines
Would you consider an RFC patch to add pan-U-Boot bitfield operations? Failing that, how about just for ARM?
I fail to understand what you mean. We already have such implementations in place. I just oobject against adding new, non-standard ones when the existing ones perform the same purpose.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de I think it's a new feature. Don't tell anyone it was an accident. :-) -- Larry Wall on s/foo/bar/eieio in <[email protected]>
PATCH v3 2/10 armv7: add miscellaneous utility macros
Quoted 8 lines · Wolfgang Denk
Dear Simon Glass,
Quoted 3 lines · In message <[email protected]> you wrote:
Being a boot loader, charged with basic hardware initialisation, I believe bitfield access primitives should be well-supported by U-Boot.
I agree, and they are.
Hi Wolfgang,
Well there is something there, but we can always do better.
Quoted 7 lines
Quoted 3 lines
Would you consider an RFC patch to add pan-U-Boot bitfield operations? Failing that, how about just for ARM?
I fail to understand what you mean. ?We already have such implementations in place. ?I just oobject against adding new, non-standard ones when the existing ones perform the same purpose.
There are a few very primitive macros in setbits and clrbits. I would very much like to see at least:
- define a field once in a header in an easy format along with any enums which define allowable values if applicable
- pack and unpack a value into a field: so set a bitfield to 13, for example
- obtain a mask for a field (i.e. with all bits set)
- equivalent of writel and readl for a bitfield (writel in fact being read/modify/write so perhaps a different name)
Some of these exist, some don't.
Any thoughts? I we get something in there I suspect ARM people will use it at least, and that will reduce the number of ways this gets done. At present the local bitfield macros are not accessible to even other SOCs, let along other architectures. As this thread shows (and some of the code I have been reviewing recently) there is a demand for something more functional.
Regards,
Simon
Quoted 12 lines
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, ? ? MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de I think it's a new feature. Don't tell anyone it was an accident. :-) ?-- Larry Wall on s/foo/bar/eieio in <[email protected]>
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Simon Glass,
Quoted 3 lines · In message <[email protected]> you wrote:
There are a few very primitive macros in setbits and clrbits. I would very much like to see at least:
Maybe we can agree to use these existing macros then instead of inventing new ones with the same functionality.
Quoted 9 lines
- define a field once in a header in an easy format along with any enums which define allowable values if applicable
- pack and unpack a value into a field: so set a bitfield to 13, for exampl= e
- obtain a mask for a field (i.e. with all bits set)
- equivalent of writel and readl for a bitfield (writel in fact being read/modify/write so perhaps a different name)Some of these exist, some don't.
Do you know of examples of such more complex definitions in the Linux kernel code?
Quoted 2 lines
Any thoughts? I we get something in there I suspect ARM people will use it at least, and that will reduce the number of ways this gets
I doubt that. You can see that even the existing macros are unknown to many, and they also do not bother to check around or asdk. It's always so much easier to invent your own new shiny macro that fits your current purpose perfectly.
Quoted 4 lines
done. At present the local bitfield macros are not accessible to even other SOCs, let along other architectures. As this thread shows (and some of the code I have been reviewing recently) there is a demand for something more functional.
How is this problem being addressed in Linux? At the very minimum we should chose a compatible implementation.
Best regards,
Wolfgang Denk
Signature · 4 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Forty two.
PATCH v3 2/10 armv7: add miscellaneous utility macros
Hi Wolfgang,
Quoted 18 lines · Wolfgang Denk
Dear Simon Glass,
Quoted 3 lines · In message<[email protected]> you wrote:
There are a few very primitive macros in setbits and clrbits. I would very much like to see at least:
Maybe we can agree to use these existing macros then instead of inventing new ones with the same functionality.
Quoted 8 lines
- define a field once in a header in an easy format along with any enums which define allowable values if applicable
- pack and unpack a value into a field: so set a bitfield to 13, for exampl= e
- obtain a mask for a field (i.e. with all bits set)
- equivalent of writel and readl for a bitfield (writel in fact being read/modify/write so perhaps a different name)
Quoted 5 lines
Quoted 1 line
Some of these exist, some don't.
Do you know of examples of such more complex definitions in the Linux kernel code?
In fact I had searched for a macro for similar needs as my set_bit_field() is addressing in Linux Kernel too but didn't find any.
Please note that my requirement is not for doing IO but doing bit field operations on a C integer variable:
1. Prepare a variable field by field to be finally written to a register using writel()
2. Extract a field from a variable that typically holds the value of a register after a readl()
I couldn't find any utility macros/functions for doing something like this.
Please somebody correct me if I am wrong.
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Aneesh V,
Quoted 3 lines · In message <[email protected]> you wrote:
In fact I had searched for a macro for similar needs as my
set_bit_field()is addressing in Linux Kernel too but didn't find any.
...
Quoted 4 lines
I couldn't find any utility macros/functions for doing something like this.
Please somebody correct me if I am wrong.
I am not aware of such a functionality in the Linux kernel, either.
A quick search did not even show any attempts to introduce such macros to Linux. It appears they don't need such a feature ?
But I may easily be overlooking something.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de If I ever needed a brain transplant, I'd choose a teenager's because I'd want a brain that had never been used.
V
PATCH v3 2/10 armv7: add miscellaneous utility macros
Hi Wolfgang,
Quoted 10 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 3 lines · In message <[email protected]> you wrote:
In fact I had searched for a macro for similar needs as my
set_bit_field()is addressing in Linux Kernel too but didn't find any....
Quoted 3 lines
I couldn't find any utility macros/functions for doing something like this.
Quoted 6 lines
Quoted 1 line
Please somebody correct me if I am wrong.
I am not aware of such a functionality in the Linux kernel, either.
A quick search did not even show any attempts to introduce such macros to Linux. ?It appears they don't need such a feature ?
Wolfgang, what's your final take on this. Can I continue to use the utility macros given that I don't have any 'standard' alternative. For register accesses I shall move to setclrbits*() macros that you had suggested. But for bit operations I do not have any alternatives.
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
Quoted 20 lines · Aneesh
Hi Wolfgang,
Quoted 10 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 3 lines · In message <[email protected]> you wrote:
In fact I had searched for a macro for similar needs as my
set_bit_field()is addressing in Linux Kernel too but didn't find any....
Quoted 3 lines
I couldn't find any utility macros/functions for doing something like this.
Quoted 6 lines
Quoted 1 line
Please somebody correct me if I am wrong.
I am not aware of such a functionality in the Linux kernel, either.
A quick search did not even show any attempts to introduce such macros to Linux. ?It appears they don't need such a feature ?
Quoted 8 lines
Wolfgang, what's your final take on this. Can I continue to use the utility macros given that I don't have any 'standard' alternative. For register accesses I shall move to setclrbits*() macros that you had suggested. But for bit operations I do not have any alternatives.
best regards,
Aneesh
Hi Aneesh,
If it helps, I will email a cleaned up bitfield patch to the list tomorrow. I hoping that it will get a warm reception :-)
Regards,
Simon
PATCH v3 2/10 armv7: add miscellaneous utility macros
Hi Simon,
Quoted 26 lines · Simon Glass
Quoted 25 lines · Aneesh
Hi Wolfgang,
Quoted 10 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 3 lines · In message<[email protected]> you wrote:
In fact I had searched for a macro for similar needs as my
set_bit_field()is addressing in Linux Kernel too but didn't find any....
Quoted 3 lines
I couldn't find any utility macros/functions for doing something like this.
Quoted 6 lines
Quoted 1 line
Please somebody correct me if I am wrong.
I am not aware of such a functionality in the Linux kernel, either.
A quick search did not even show any attempts to introduce such macros to Linux. It appears they don't need such a feature ?
Wolfgang, what's your final take on this. Can I continue to use the utility macros given that I don't have any 'standard' alternative. For register accesses I shall move to setclrbits*() macros that you had suggested. But for bit operations I do not have any alternatives.
Quoted 8 lines
Quoted 3 lines
best regards,
AneeshHi Aneesh,
If it helps, I will email a cleaned up bitfield patch to the list tomorrow. I hoping that it will get a warm reception :-)
Thanks. That's great news at least for me.
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
In reply to Wolfgang DenkQuoted 8 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 3 lines · In message<[email protected]> you wrote:
add utility macros for:
* bit field operations
* log2n functions...
Quoted 15 lines
arch/arm/include/asm/utils.h line 36
Quoted 9 lines
arch/arm/include/asm/utils.h new file +9
-0+/* extract a bit field from a bit vector */ +#define get_bit_field (nr, start, mask)\ + (((nr)& (mask))>> (start)) + +/* Set a field in a bit vector */ +#define set_bit_field (nr, start, mask, val)\ + do { \ + (nr) = ((nr)& ~(mask)) | (((val)<< (start))& (mask));\ + } while (0);I really dislike such "useful" helpers, because they make the code unreadable. Being nonstandrd, nbody knows what they are doing, so you always will have to look up the implementation before you can continue reading the code. It's a waste of time an resources.
I will be very happy to use a standard one if one exists. I checked in bitops.h but couldn't find something that's equivalent to the above. Can you point me to a standard one that does something equivalent.
Yes, you may have to look-up the implementation, but maybe just once. That goes with any API, right?
On the other hand, doing shifting ORing, ANDing etc directly in the code is less readable in my opinion.
Quoted 19 lines
arch/arm/include/asm/utils.h line 49
Quoted 12 lines
arch/arm/include/asm/utils.h new file +12
-0+/* +* Utility macro for read-modify-write of a hardware register +* addr - address of the register +* shift - starting bit position of the field to be modified +* msk - mask for the field +* val - value to be shifted masked and written to the field +*/ +#define modify_reg_32 (addr, shift, msk, val) \ + do {\ + writel(((readl(addr)& ~(msk))|(((val)<< (shift))& (msk))),\ + (addr));\ + } while (0);NAK again, for the same reasons.
Note that there are some semi-standardized I/O accessro macros available, at least for some architectures, like clrbits.*(),
setbits_(), orclrsetbits().
Quoted 8 lines
See for example "
arch/arm/include/asm/io.h",
"arch/powerpc/include/asm/io.h" for reference.Instead of reinventing the wheel (just differently shaped) we should rather try and use a single, standardized set of such helpers.
So please use the existing macros instead of inventing new, non-standard ones.
clrsetbits will work for this need albeit not as clean as the above one. I will use that.
Quoted 5 lines
Best regards,
Wolfgang Denk
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Wolfgang,
Quoted 11 lines · Aneesh V
Quoted 8 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 3 lines · In message<[email protected]> you wrote:
add utility macros for:
* bit field operations
* log2n functions...
Quoted 15 lines
Quoted 6 lines
Quoted 6 lines
arch/arm/include/asm/utils.h new file +6
-0+/* extract a bit field from a bit vector */ +#define get_bit_field (nr, start, mask)\ + (((nr)& (mask))>> (start)) + +/* Set a field in a bit vector */ +#define set_bit_field (nr, start, mask, val)\Quoted 9 lines
Quoted 3 lines
+ do { \
+ (nr) = ((nr)& ~(mask)) | (((val)<< (start))& (mask));\
+ } while (0);I really dislike such "useful" helpers, because they make the code unreadable. Being nonstandrd, nbody knows what they are doing, so you always will have to look up the implementation before you can continue reading the code. It's a waste of time an resources.
What if I change the above to something like this(please note there isn't any Linux, U-Boot substitute for this):
+/* extract a bit field from a bit vector */
+#define get_bit_field(nr, field)\
+ (((nr) & (field##_MASK)) >> (field##_OFFSET))
+
+/* Set a field in a bit vector */
+#define set_bit_field(nr, field, val)\
+ do { \
+ (nr) = ((nr) & ~(field##_MASK)) | (((val) << (field##_OFFSET))\
+ & (field##_MASK));\
+ } while (0);
+
And use it like this:
assoc = get_bit_field(ccsidr, CCSIDR_ASSOCIATIVITY); set_bit_field(ccsidr, CCSIDR_ASSOCIATIVITY, assoc + 1);
Isn't it more intuitive and almost self-explanatory now.
If you still don't like these as standard generic macros, how about having these macros just for OMAP with these names and use them only for OMAP code?
omap_get_bit_field(nr, field)omap_set_bit_field(nr, field, val)
I can live without them for the ARM generic code but I use it extensively in my SPL series.
Please note that Simon's recent work for bitfield operations doesn't help me because the field definitions available to me are in shift/mask format and not in the range format that he uses. I will not be able to now generate the range format for the hundreds of registers I use.
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Aneesh V,
Quoted 21 lines · In message <[email protected]> you wrote:
Quoted 5 lines
Quoted 5 lines
I really dislike such "useful" helpers, because they make the code unreadable. Being nonstandrd, nbody knows what they are doing, so you always will have to look up the implementation before you can continue reading the code. It's a waste of time an resources.
What if I change the above to something like
this(please note there isn't any Linux, U-Boot substitute for this):arch/arm/include/asm/utils.h new file +11
-0+/* extract a bit field from a bit vector */ +#define get_bit_field (nr, field)\ + (((nr) & (field##_MASK)) >> (field##_OFFSET)) + +/* Set a field in a bit vector */ +#define set_bit_field (nr, field, val)\ + do { \ + (nr) = ((nr) & ~(field##_MASK)) | (((val) << (field##_OFFSET))\ + & (field##_MASK));\ + } while (0); +
Quoted 5 lines
And use it like this:
assoc =get_bit_field(ccsidr, CCSIDR_ASSOCIATIVITY);set_bit_field(ccsidr, CCSIDR_ASSOCIATIVITY, assoc + 1);Isn't it more intuitive and almost self-explanatory now.
To me it is definitely NOT self-explanatory.
Actually I cannot even understand the argument names, now how it's supposed to be used. I would interpret "nr" as "number"; in the context of a bit field probably a bit number? Wrong guess...
It's highly cryptic and will only work with very special #defines providing definitions of foo_MASK and foo_OFFSET.
It is not clear that you can use this on plain simple memory stored variables only, and that you must not use this on any device registers; yet your example looks as if this were intended to be used on registers - but then we would need proper I/O accessors.
And there are still many cases where you cannot use this because for example evaluating several bits from the same object will cause repeated accesses, which may have side effects (when accessing device registers).
And, last but not least: they are nonstandard. I still don't understand why you cannot use the standard macros that already exist in Linux and in U-Boot, here for example clrbits*(), setbits*() and clrsetbits*() ?
Quoted 3 lines
If you still don't like these as standard generic macros, how about having these macros just for OMAP with these names and use them only for OMAP code?
Would that make it anything better? If it's not good enough for general use, we can still use it for OMAP? Like: oh, it's ony OMAP, so code quality does not matter? I think that's not good reasoning.
Quoted 3 lines
Please note that Simon's recent work for bitfield operations doesn't help me because the field definitions available to me are in shift/mask format and not in the range format that he uses. I will not be
I don;t think I'm going to accept that code either.
Quoted 2 lines
able to now generate the range format for the hundreds of registers I use.
Ah! I thought you were talking about registers. See note above about I/O accessors.
Best regards,
Wolfgang Denk
Signature · 6 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
A Perl script is correct if it's halfway readable and gets the job
done before your boss fires you.
- L. Wall & R. L. Schwartz, _Programming Perl_PATCH v3 2/10 armv7: add miscellaneous utility macros
Hi Wolfgang,
Quoted 36 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 21 lines · In message<[email protected]> you wrote:
Quoted 5 lines
Quoted 5 lines
I really dislike such "useful" helpers, because they make the code unreadable. Being nonstandrd, nbody knows what they are doing, so you always will have to look up the implementation before you can continue reading the code. It's a waste of time an resources.
What if I change the above to something like
this(please note there isn't any Linux, U-Boot substitute for this):arch/arm/include/asm/utils.h new file +11
-0+/* extract a bit field from a bit vector */ +#define get_bit_field (nr, field)\ + (((nr)& (field##_MASK))>> (field##_OFFSET)) + +/* Set a field in a bit vector */ +#define set_bit_field (nr, field, val)\ + do { \ + (nr) = ((nr)& ~(field##_MASK)) | (((val)<< (field##_OFFSET))\ + & (field##_MASK));\ + } while (0); +Quoted 5 lines
And use it like this:
assoc =get_bit_field(ccsidr, CCSIDR_ASSOCIATIVITY);set_bit_field(ccsidr, CCSIDR_ASSOCIATIVITY, assoc + 1);Isn't it more intuitive and almost self-explanatory now.
To me it is definitely NOT self-explanatory.
Actually I cannot even understand the argument names, now how it's supposed to be used. I would interpret "nr" as "number"; in the context of a bit field probably a bit number? Wrong guess...
Quoted 7 lines
It's highly cryptic and will only work with very special #defines providing definitions of
foo_MASKandfoo_OFFSET.It is not clear that you can use this on plain simple memory stored variables only, and that you must not use this on any device registers; yet your example looks as if this were intended to be used on registers - but then we would need proper I/O accessors.
No. it's not meant to be directly used on registers. Please see below.
Quoted 10 lines
And there are still many cases where you cannot use this because for example evaluating several bits from the same object will cause repeated accesses, which may have side effects (when accessing device registers).
And, last but not least: they are nonstandard. I still don't understand why you cannot use the standard macros that already exist in Linux and in U-Boot, here for example clrbits*(), setbits*() and clrsetbits*() ?
As I had mentioned in a previous mail, please note that the above macros are not for the same use-case as clrsetbits*() or friends (I had one macro that did something similar to clrsetbits*() and I intent to remove that in the next revision)
The above macros are for bit-field manipulation in a C integer variable
- nothing more.
However, the typical use of this is for extracting bit-fields from an IO register that is already read into an integer variable (instead of reading the IO register multiple times). And similarly for write.
So, if I have to write 5 different fields in a register I first write them into a variable and finally call writel() instead of making 5 clrsetbits*() calls.
There aren't any standard routines available for this need in Linux or U-Boot. I think you had agreed on this fact sometime back.
Quoted 8 lines
Quoted 4 lines
If you still don't like these as standard generic macros, how about having these macros just for OMAP with these names and use them only for OMAP code?
Would that make it anything better? If it's not good enough for general use, we can still use it for OMAP? Like: oh, it's ony OMAP, so code quality does not matter? I think that's not good reasoning.
No. It was not about code quality. The question was whether these macros were generic enough to be used as the standard U-boot ones. The key question is how do you represent bit fields. There are different alternatives for this.
a. bit range (say 5:3)
b. shift(3) and field width(3)
c. shift(3) and mask(0x38)
We traditionally use (c) and we have auto-generated defines in this form. So, my macros use this format. I was not sure if other SoCs follow the same approach. That's why I suggested making them OMAP specific if you think (c) is not the standard approach.
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Aneesh V,
Quoted 8 lines · In message <[email protected]> you wrote:
As I had mentioned in a previous mail, please note that the above macros are not for the same use-case as clrsetbits*() or friends (I had one macro that did something similar to clrsetbits*() and I intent to remove that in the next revision)
The above macros are for bit-field manipulation in a C integer variable
- nothing more.
Why cannot we use the existing macros?
Quoted 3 lines
So, if I have to write 5 different fields in a register I first write them into a variable and finally call
writel()instead of making 5 clrsetbits*() calls.
It does not make much difference to me if you call one macro or another 5 times.
It does mater to me to have several incompatible implementations doing essentially the same thing.
Quoted 2 lines
There aren't any standard routines available for this need in Linux or U-Boot. I think you had agreed on this fact sometime back.
I agree in so far as I am not aware of any such macros in Linux either. But my conclusion is a different one - it boils down to:
Linux is way more complex than U-Boot, so if they don;t need this, we don't need it either.
Quoted 8 lines
No. It was not about code quality. The question was whether these macros were generic enough to be used as the standard U-boot ones. The key question is how do you represent bit fields. There are different alternatives for this.
a. bit range (say 5:3)
b. shift(3) and field width(3)
c. shift(3) and mask(0x38)
d) Value and mask
Quoted 4 lines
We traditionally use (c) and we have auto-generated defines in this form. So, my macros use this format. I was not sure if other SoCs follow the same approach. That's why I suggested making them OMAP specific if you think (c) is not the standard approach.
Actually it does not matter. See my previous message to Simon: you can cover all this with the existing macros, and without adding any significant overhead.
So far, I did not see a single good argument why any new, nonstandard macros would be needed.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de You can fool some of the people all of the time, and You can fool all of the people some of the time, but You can't fool mom.
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Wolfgang,
Quoted 12 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 8 lines · In message<[email protected]> you wrote:
As I had mentioned in a previous mail, please note that the above macros are not for the same use-case as clrsetbits*() or friends (I had one macro that did something similar to clrsetbits*() and I intent to remove that in the next revision)
The above macros are for bit-field manipulation in a C integer variable
- nothing more.
Quoted 9 lines
Why cannot we use the existing macros?
Quoted 3 lines
So, if I have to write 5 different fields in a register I first write them into a variable and finally call
writel()instead of making 5 clrsetbits*() calls.It does not make much difference to me if you call one macro or another 5 times.
No it makes a difference. It's 5 writes to a variable typically in an ARM register + 1 IO access vs 5 IO accesses. It's logically not equivalent.
Further if the 5 values are constants a smart compiler will fold the five writes into one write to the ARM register + 1 IO access, which won't happen if you used 5 clrsetbits*()
Let me give you a solid example:
Problem: We want to read-modify-write an IO register 'reg' affecting 3 different fields: a, b, and c. The values to be written to the fields are a_val, b_val, and c_val respectively:
Solution 1 - without any macros:
unsigned int r = readl(reg);
r = (r & ~a_mask) | ((a_val << a_shift) & a_mask) r = (r & ~b_mask) | ((b_val << b_shift) & b_mask) r = (r & ~c_mask) | ((c_val << c_shift) & c_mask)
writel(r, reg);
Solution2 - with my macros:
unsigned int r = readl(reg);set_bit_field(r, a, a_val);set_bit_field(r, b, b_val);set_bit_field(r, c, c_val);writel(r, reg);
Solution3 - with clrsetbits*():
clrsetbits_le32(reg, a_mask, a_val << a_shift);clrsetbits_le32(reg, b_mask, b_val << b_shift);clrsetbits_le32(reg, c_mask, c_val << c_shift);
Solution 3 is not acceptable to me because it's clearly not equivalent to what I want to do. Writing the register 3 times instead of once may have undesirable side-effects. Even if it worked, it's clearly not efficient.
If you are forcing me to use solution 1, IMHO you are essentially forcing me not to use a sub-routine for a task that is repeated many times in my code, leaving my code to be more error prone and less readable.
You accuse set_bit_field() of being cryptic. I would say the implementation of clrsetbits_le32() is even more cryptic with so many levels of indirection. I think that goes with any sub-routine/API. You need to read the code/documentation once to know what it does. After that you take it's functionality for granted and things become easier for you. If better documentation can improve readability I am happy to do that.
Also, If you don't like it as a generic API I am willing to make it a static inline function in my code. But I need a utility function for this need. If you think the implementation/documentation can be improved I am willing to work on that too. But please suggest a solution for this problem.
Quoted 2 lines
It does mater to me to have several incompatible implementations doing essentially the same thing.
They are not doing the same thing as explained above.
Quoted 8 lines
Quoted 3 lines
There aren't any standard routines available for this need in Linux or U-Boot. I think you had agreed on this fact sometime back.
I agree in so far as I am not aware of any such macros in Linux either. But my conclusion is a different one - it boils down to:
Linux is way more complex than U-Boot, so if they don;t need this, we don't need it either.
I am surprised why Linux doesn't have a solution for this. Perhaps the reason must be the confusion about the representation of a field that we discussed below. I suspect there may be non-standard local implementations in different modules.
Also, as somebody already mentioned, can't we do better than Linux?
Quoted 18 lines
Quoted 10 lines
No. It was not about code quality. The question was whether these macros were generic enough to be used as the standard U-boot ones. The key question is how do you represent bit fields. There are different alternatives for this.
a. bit range (say 5:3)
b. shift(3) and field width(3)
c. shift(3) and mask(0x38)d) Value and mask
Quoted 4 lines
We traditionally use (c) and we have auto-generated defines in this form. So, my macros use this format. I was not sure if other SoCs follow the same approach. That's why I suggested making them OMAP specific if you think (c) is not the standard approach.
Quoted 6 lines
Actually it does not matter. See my previous message to Simon: you can cover all this with the existing macros, and without adding any significant overhead.
So far, I did not see a single good argument why any new, nonstandard macros would be needed.
Please consider the above example and let me know if I missed any solution using the existing standard macros.
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
Hi Aneesh.
On Tue, Jun 7, 2011 at 5:14 AM, Aneesh V <[email protected]> wrote:
[snip]
Quoted 4 lines
I am surprised why Linux doesn't have a solution for this. Perhaps the reason must be the confusion about the representation of a field that we discussed below. I suspect there may be non-standard local implementations in different modules.
I think there are a few reasons. Linux tends to do a lot more processing in between bitfield accesses, so the problem is less apparent (bitfield access as a proportion of total code size is small). Also very often Linux supports all different values for a field, so computing values to put into fields (based on function parameters) is more common than just setting to a few selected values, which is common in U-Boot.
Quoted 2 lines
Also, as somebody already mentioned, can't we do better than Linux?
In this area, yes!
[snip]
Quoted 7 lines
Please consider the above example and let me know if I missed any solution using the existing standard macros.
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
In reply to Aneesh VDear Aneesh V,
Quoted 11 lines · In message <[email protected]> you wrote:
Quoted 7 lines
Quoted 4 lines
So, if I have to write 5 different fields in a register I first write them into a variable and finally call
writel()instead of making 5 clrsetbits*() calls.It does not make much difference to me if you call one macro or another 5 times.
No it makes a difference. It's 5 writes to a variable typically in an ARM register + 1 IO access vs 5 IO accesses. It's logically not equivalent.
You can use in_le32() to read the register in a variable, a number of macros operating on that variable, and then a out_le32() to write it back.
It's logically equivalent.
Quoted 3 lines
Further if the 5 values are constants a smart compiler will fold the five writes into one write to the ARM register + 1 IO access, which won't happen if you used 5 clrsetbits*()
See above.
If you ever want to use your macros on device registers, you MUST use proper memory barriers. This will probably ruin your idea to combine the access into a single write. So you can just work on a variable as suggested before.
Quoted 20 lines
Problem: We want to read-modify-write an IO register 'reg' affecting 3 different fields: a, b, and c. The values to be written to the fields are
a_val,b_val, andc_valrespectively:Solution 1 - without any macros:
unsigned int r = readl(reg);
r = (r & ~a_mask) | ((a_val << a_shift) & a_mask) r = (r & ~b_mask) | ((b_val << b_shift) & b_mask) r = (r & ~c_mask) | ((c_val << c_shift) & c_mask)
writel(r, reg);Solution2 - with my macros:
unsigned int r = readl(reg);
set_bit_field(r, a, a_val);set_bit_field(r, b, b_val);set_bit_field(r, c, c_val);writel(r, reg);
Quoted 5 lines
Solution3 - with clrsetbits*():
clrsetbits_le32(reg, a_mask, a_val << a_shift);clrsetbits_le32(reg, b_mask, b_val << b_shift);clrsetbits_le32(reg, c_mask, c_val << c_shift);
Solution 4 - with standard macros, and proper defines:
unsigned int r = in_le32(reg); /* or readl() if you like */ clrsetbits_le32(&r, a_mask, a_val); clrsetbits_le32(&r, b_mask, b_val); clrsetbits_le32(&r, c_mask, c_val); out_le32(reg, r);
Actually solution 3 looks best to me.
Quoted 4 lines
Solution 3 is not acceptable to me because it's clearly not equivalent to what I want to do. Writing the register 3 times instead of once may have undesirable side-effects. Even if it worked, it's clearly not efficient.
In case of side effects you can use solution 4.
We should not bother here about wether this is "efficient" or "not efficient". Probably none opf this code is ever time critical, not to the extent of a few additional instructions.
Quoted 4 lines
If you are forcing me to use solution 1, IMHO you are essentially forcing me not to use a sub-routine for a task that is repeated many times in my code, leaving my code to be more error prone and less readable.
I agree that 1 is ugly and error prone, but there is no need to use it.
I repeat: we have a set of powerful macros ready available. Just use them.
Quoted 3 lines
You accuse
set_bit_field()of being cryptic. I would say the implementation ofclrsetbits_le32()is even more cryptic with so many levels of indirection. I think that goes with any sub-routine/API.
Theimplementation is complex, indeed. But the interface is pretty simple, and portable.
Quoted 1 line
You need to read the code/documentation once to know what it does.
Ditto for set_bit_field().
Quoted 4 lines
Quoted 2 lines
It does mater to me to have several incompatible implementations doing essentially the same thing.
They are not doing the same thing as explained above.
I think they do. Could you please just give it a try with an open mind and not being too much focussed on your own code.
Best regards,
Wolfgang Denk
Signature · 4 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Backed up the system lately?
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Wolfgang,
Quoted 60 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 11 lines · In message<[email protected]> you wrote:
Quoted 7 lines
Quoted 4 lines
So, if I have to write 5 different fields in a register I first write them into a variable and finally call
writel()instead of making 5 clrsetbits*() calls.It does not make much difference to me if you call one macro or another 5 times.
No it makes a difference. It's 5 writes to a variable typically in an ARM register + 1 IO access vs 5 IO accesses. It's logically not equivalent.
You can use
in_le32()to read the register in a variable, a number of macros operating on that variable, and then aout_le32()to write it back.It's logically equivalent.
Quoted 3 lines
Further if the 5 values are constants a smart compiler will fold the five writes into one write to the ARM register + 1 IO access, which won't happen if you used 5 clrsetbits*()
See above.
If you ever want to use your macros on device registers, you MUST use proper memory barriers. This will probably ruin your idea to combine the access into a single write. So you can just work on a variable as suggested before.
Quoted 20 lines
Problem: We want to read-modify-write an IO register 'reg' affecting 3 different fields: a, b, and c. The values to be written to the fields are
a_val,b_val, andc_valrespectively:Solution 1 - without any macros:
unsigned int r = readl(reg);
r = (r& ~a_mask) | ((a_val<< a_shift)& a_mask) r = (r& ~b_mask) | ((b_val<< b_shift)& b_mask) r = (r& ~c_mask) | ((c_val<< c_shift)& c_mask)
writel(r, reg);Solution2 - with my macros:
unsigned int r = readl(reg);
set_bit_field(r, a, a_val);set_bit_field(r, b, b_val);set_bit_field(r, c, c_val);writel(r, reg);Quoted 5 lines
Solution3 - with clrsetbits*():
clrsetbits_le32(reg, a_mask, a_val<< a_shift); clrsetbits_le32(reg, b_mask, b_val<< b_shift); clrsetbits_le32(reg, c_mask, c_val<< c_shift);Solution 4 - with standard macros, and proper defines:
Quoted 7 lines
unsigned int r = in_le32(reg); /* or readl() if you like */ clrsetbits_le32(&r, a_mask, a_val); clrsetbits_le32(&r, b_mask, b_val); clrsetbits_le32(&r, c_mask, c_val); out_le32(reg, r);
I still don't think this is the 'right' solution for my problem. I don't like the fact that clrsetbits_le32() introduces a lot of un-necessary 'volatile's.
Yes, it's about the 'efficiency'. May be it doesn't count in some cases. But, may be it counts in some other cases. Basically, I don't like to sacrifice 'efficiency' unless the cost for achieving it is very high. I don't think having an extra helper function is a big cost. Neither do I believe that readability suffers in this case.
If you still insist, I can use clrsetbits_le32() in the interest of getting this to a closure.
Quoted 19 lines
Actually solution 3 looks best to me.
Quoted 4 lines
Solution 3 is not acceptable to me because it's clearly not equivalent to what I want to do. Writing the register 3 times instead of once may have undesirable side-effects. Even if it worked, it's clearly not efficient.
In case of side effects you can use solution 4.
We should not bother here about wether this is "efficient" or "not efficient". Probably none opf this code is ever time critical, not to the extent of a few additional instructions.
Quoted 4 lines
If you are forcing me to use solution 1, IMHO you are essentially forcing me not to use a sub-routine for a task that is repeated many times in my code, leaving my code to be more error prone and less readable.
Quoted 5 lines
I agree that 1 is ugly and error prone, but there is no need to use it.
I repeat: we have a set of powerful macros ready available. Just use them.
We have a set of powerful macros designed for bit-field accesses in IO egisters.
But, what I am looking for is a set of macros for bit-field operations on C integer variables without the un-necessary overhead of IO register accesses. I am looking for missing APIs in bitops.h not anything from io.h
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Aneesh V,
Quoted 4 lines · In message <[email protected]> you wrote:
I still don't think this is the 'right' solution for my problem. I don't like the fact that
clrsetbits_le32()introduces a lot of un-necessary 'volatile's.
Well, with this argument you would also have to refuse using readl() and writel() and all other I/O accessor macros. The only place where volatile is used is in the __arch_get*() and __arch_put*() macros, and ther eit is supposed to be ok.
Quoted 3 lines
Yes, it's about the 'efficiency'. May be it doesn't count in some cases. But, may be it counts in some other cases. Basically, I don't like to sacrifice 'efficiency' unless the cost for achieving it is very
Try and show me a single case where you see a measurable difference in performance.
Quoted 2 lines
If you still insist, I can use
clrsetbits_le32()in the interest of getting this to a closure.
Please do. Thanks.
Quoted 7 lines
We have a set of powerful macros designed for bit-field accesses in IO egisters.
But, what I am looking for is a set of macros for bit-field operations on C integer variables without the un-necessary overhead of IO register accesses. I am looking for missing APIs in
bitops.hnot anything fromio.h
All the overhead we have is a few memory barriers. Can you measure any difference in performance?
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Never underestimate the bandwidth of a station wagon full of tapes.
-- Dr. Warren Jackson, Director, UTCSPATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Wolfgang,
Quoted 18 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 4 lines · In message<[email protected]> you wrote:
I still don't think this is the 'right' solution for my problem. I don't like the fact that
clrsetbits_le32()introduces a lot of un-necessary 'volatile's.Well, with this argument you would also have to refuse using
readl()andwritel()and all other I/O accessor macros. The only place where volatile is used is in the __arch_get*() and __arch_put*() macros, and ther eit is supposed to be ok.Quoted 3 lines
Yes, it's about the 'efficiency'. May be it doesn't count in some cases. But, may be it counts in some other cases. Basically, I don't like to sacrifice 'efficiency' unless the cost for achieving it is very
Quoted 7 lines
Try and show me a single case where you see a measurable difference in performance.
Quoted 2 lines
If you still insist, I can use
clrsetbits_le32()in the interest of getting this to a closure.Please do. Thanks.
As I start re-working on my patches I realize that there is no alternative to get_bit_field(). clrsetbits_le32() works as an alternative for set_bit_field() but I couldn't find anything in io.h that could replace get_bit_field(). The only option I seem to have is to mask and shift directly every time. Is that what you prefer over get_bit_field()?
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Aneesh V,
Quoted 7 lines · In message <[email protected]> you wrote:
As I start re-working on my patches I realize that there is no alternative to
get_bit_field().clrsetbits_le32()works as an alternative forset_bit_field()but I couldn't find anything inio.hthat could replaceget_bit_field(). The only option I seem to have is to mask and shift directly every time. Is that what you prefer overget_bit_field()?
I don't understand this comment.
You should NOT use clrsetbits_*() instead of set_bit_field() - depending on what you want to do, clrbits_*() or setbits_*() are better choices for simple operations.
Also please notice that none of clrbits_*(), setbits_*() or clrsetbits_*() perform any masking or shifting. If you don't want to do this explicitly when using the macro, you can hide it in respective definitions of the mask values. I showed how this could be done in the examples I posted in the thread with Simon.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Cleverness and Style have no place in getting a project completed.
-- Tom ChristiansenPATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Wolfgang,
Quoted 11 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 7 lines · In message<[email protected]> you wrote:
As I start re-working on my patches I realize that there is no alternative to
get_bit_field().clrsetbits_le32()works as an alternative forset_bit_field()but I couldn't find anything inio.hthat could replaceget_bit_field(). The only option I seem to have is to mask and shift directly every time. Is that what you prefer overget_bit_field()?
Quoted 5 lines
I don't understand this comment.
You should NOT use clrsetbits_*() instead of
set_bit_field()- depending on what you want to do, clrbits_*() or setbits_*() are better choices for simple operations.
Yes. I have seen those macros. But more often than not the bit field is more than 1 bit wide and the value to be set is not necessarily all 0's or all 1's. That's why I have to use clrsetbits_*()
Quoted 7 lines
Also please notice that none of clrbits_*(), setbits_*() or clrsetbits_*() perform any masking or shifting. If you don't want to do this explicitly when using the macro, you can hide it in respective definitions of the mask values. I showed how this could be done in the examples I posted in the thread with Simon.
The problem I have to deal with is different. get_bit_field() was intended to extract bit fields from an integer. So, the target usage will be something like this(where a, b, and c are bit fields in register my_reg)
u32 my_reg, a_val, b_val, c_val;
u32 my_reg = readl(my_reg_addr);
a_val = get_bit_field(my_reg, a_mask);b_val = get_bit_field(my_reg, b_mask);c_val = get_bit_field(my_reg, c_mask);
Do you see an alternative method for doing this using the standard macros?
br,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Aneesh V,
Quoted 4 lines · In message <[email protected]> you wrote:
Yes. I have seen those macros. But more often than not the bit field is more than 1 bit wide and the value to be set is not necessarily all 0's or all 1's. That's why I have to use clrsetbits_*()
I see. In such a case (and only then) clrsetbits_*() is indeed the right choice.
Quoted 7 lines
The problem I have to deal with is different.
get_bit_field()was intended to extract bit fields from an integer. So, the target usage will be something likethis(where a, b, and c are bit fields in register my_reg)u32
my_reg,a_val,b_val,c_val;
Quoted 8 lines
u32
my_reg=readl(my_reg_addr);
a_val=get_bit_field(my_reg, a_mask);b_val=get_bit_field(my_reg, b_mask);c_val=get_bit_field(my_reg, c_mask);Do you see an alternative method for doing this using the standard macros?
Please see the example given here:
http://article.gmane.org/gmane.comp.boot-loaders.u-boot/101146
Looking closer, the "FIELD_VAL" macro alone will probably not suffice, as you need both shift directions, like that:
#define FIELD_SHIFT 16 #define FIELD_MASK 0xF #define FIELD_BITS(x) (x << 16) #define FIELD_MASK FIELD_BITS(0xF) #define FIELD_VAL(x) ((x & FIELD_MASK) >> 16)
The code would then look something like this:
my_reg = readl(my_reg_addr); a_val = A_VAL(my_reg); b_val = B_VAL(my_reg); c_val = C_VAL(my_reg);
...or similar.
Best regards,
Wolfgang Denk
Signature · 7 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de "I dislike companies that have a we-are-the-high-priests-of-hardware- so-you'll-like-what-we-give-you attitude. I like commodity markets in which iron-and-silicon hawkers know that they exist to provide fast toys for software types like me to play with..." - Eric S. Raymond
PATCH v3 2/10 armv7: add miscellaneous utility macros
Quoted 34 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 4 lines · In message <[email protected]> you wrote:
Yes. I have seen those macros. But more often than not the bit field is more than 1 bit wide and the value to be set is not necessarily all 0's or all 1's. That's why I have to use clrsetbits_*()
I see. ?In such a case (and only then) clrsetbits_*() is indeed the right choice.
Quoted 7 lines
The problem I have to deal with is different.
get_bit_field()was intended to extract bit fields from an integer. So, the target usage will be something likethis(where a, b, and c are bit fields in register my_reg)u32
my_reg,a_val,b_val,c_val;Quoted 8 lines
u32
my_reg=readl(my_reg_addr);
a_val=get_bit_field(my_reg, a_mask);b_val=get_bit_field(my_reg, b_mask);c_val=get_bit_field(my_reg, c_mask);Do you see an alternative method for doing this using the standard macros?
Please see the example given here:
http://article.gmane.org/gmane.comp.boot-loaders.u-boot/101146
Looking closer, the "
FIELD_VAL" macro alone will probably not suffice, as you need both shift directions, like that:
Quoted 7 lines
? ? ? ?#define
FIELD_SHIFT? ? 16
? ? ? ?#defineFIELD_MASK? ? ?0xF? ? ? ?#define
FIELD_BITS(x)(x << 16)
? ? ? ?#defineFIELD_MASKFIELD_BITS(0xF)
? ? ? ?#defineFIELD_VAL(x)((x &FIELD_MASK) >> 16)
Hi Wolfgang,
I think you have FIELD_MASK being two meanings: the un-shifted or 'raw' mask, and the shifted mask. So perhaps:
? ? ? ?#define FIELD_SHIFT ? ? 16
? ? ? ?#define FIELD_RAWMASK ? ? ?0xF
? ? ? ?#define FIELD_BITS(x) (x << 16)
? ? ? ?#define FIELD_MASK FIELD_BITS(FIELD_RAWMASK) ? ? ? ?#define FIELD_VAL(x) ((x & FIELD_MASK) >> 16)
or with the 16 factored properly, but even harder to read:
? ? ? ?#define FIELD_SHIFT ? ? 16
? ? ? ?#define FIELD_RAWMASK ? ? ?0xF
? ? ? ?#define FIELD_BITS(x) (x << FIELD_SHIFT)
? ? ? ?#define FIELD_MASK FIELD_BITS(FIELD_RAWMASK) ? ? ? ?#define FIELD_VAL(x) ((x & FIELD_MASK) >> FIELD_SHIFT)
(note that FIELD_BITS should arguably mask after the shift).
When you have a lot of these definitions in a row you have mentally check the bit width of the mask:
? ? ? ?#define FIELD1_RAWMASK ? ? ?0xF
? ? ? ?#define FIELD1_SHIFT ? ? 16
? ? ? ?#define FIELD2_RAWMASK ? ? ?0x1F
? ? ? ?#define FIELD2_SHIFT ? ? 11
? ? ? ?#define FIELD3_RAWMASK ? ? ?0x1F
? ? ? ?#define FIELD3_SHIFT ? ? 7
? ? ? ?#define FIELD4_RAWMASK ? ? ?0x1F
? ? ? ?#define FIELD4_SHIFT ? ? 1
? ? ? ?#define FIELD1_BITS(x) (x << FIELD1_SHIFT)
? ? ? ?#define FIELD1_MASK FIELD_BITS(FIELD1_RAWMASK) ? ? ? ?#define FIELD1_VAL(x) ((x & FIELD1_MASK) >> FIELD1_SHIFT) ? ? ? ?#define FIELD2_BITS(x) (x << FIELD2_SHIFT)
? ? ? ?#define FIELD2_MASK FIELD_BITS(FIELD2_RAWMASK) ? ? ? ?#define FIELD2_VAL(x) ((x & FIELD2_MASK) >> FIELD2_SHIFT)
...
Is the above correct, or do fields overlap or not cover fully? (exercise for reader) (see [1] below)
So I think is better to think of the width rather than the mask.
? ? ? ?#define FIELD_SHIFT ? ? 16
#define FIELD_RAWMASK (1U << FIELD_WIDTH) - 1
? ? ? ?#define FIELD_BITS(x) (x << FIELD_WIDTH)
? ? ? ?#define FIELD_MASK FIELD_BITS(FIELD_RAWMASK) ? ? ? ?#define FIELD_VAL(x) ((x & FIELD_MASK) >> FIELD_WIDTH)
because then it is more obvious:
? ? ? ?#define FIELD1_WIDTH ? ? ?4
? ? ? ?#define FIELD1_SHIFT ? ? 16
? ? ? ?#define FIELD2_WIDTH ? ? ?5
? ? ? ?#define FIELD2_SHIFT ? ? 11
? ? ? ?#define FIELD3_WIDTH ? ? ?5
? ? ? ?#define FIELD3_SHIFT ? ? 7
? ? ? ?#define FIELD4_WIDTH ? ? ?5
? ? ? ?#define FIELD4_SHIFT ? ? 1
And now it is a little easier to see that 11+5 = 16, so FIELD2 is ok; 7+5=12 so FIELD3 overlaps, 1+5=6 so FIELD4 isn't big enough. It's still not as good as just numbering your bits on little-endian archs, but I think we have had that discussion.
I think BITS and VAL are not very descriptive which is why I suggested pack and unpack at the time.
But don't get me started talking about bit fields.
Regards,
Simon
[1] This is why macros are so nice:
define once:
#define bf_mask(field) ((field ## _RAWMASK) << field ## _SHIFT) #define bf_val(field, val) (((val) & bf_mask(field)) >> field ## _SHIFT) #define bf_bits(field, val) (((val) << field ## _SHIFT) & bf_mask(field))
then:
? ? ? ?#define FIELD1_BITS(x) bf_bits(FIELD1, x)
? ? ? ?#define FIELD1_MASK bf_mask(FIELD1)
? ? ? ?#define FIELD1_VAL(x) bf_val(FIELD1, x)
? ? ? ?#define FIELD2_BITS(x) bf_bits(FIELD2, x)
? ? ? ?#define FIELD2_MASK bf_mask(FIELD2)
? ? ? ?#define FIELD2_VAL(x) bf_val(FIELD2, x)
...
Quoted 24 lines
The code would then look something like this:
? ? ? ?my_reg =
readl(my_reg_addr);? ? ? ?a_val =
A_VAL(my_reg);
? ? ? ?b_val =B_VAL(my_reg);
? ? ? ?c_val =C_VAL(my_reg);...or similar.
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, ? ? MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de "I dislike companies that have a we-are-the-high-priests-of-hardware- so-you'll-like-what-we-give-you attitude. I like commodity markets in which iron-and-silicon hawkers know that they exist to ?provide ?fast toys for software types like me to play with..." ? ?- Eric S. Raymond
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Simon Glass,
Quoted 8 lines · In message <[email protected]> you wrote:
Quoted 8 lines
Looking closer, the "
FIELD_VAL" macro alone will probably not suffice, as you need both shift directions, like that:#define FIELD_SHIFT 16 #define FIELD_MASK 0xF
Quoted 8 lines
Quoted 3 lines
#define FIELD_BITS(x) (x << 16) #define FIELD_MASK FIELD_BITS(0xF) #define FIELD_VAL(x) ((x & FIELD_MASK) >> 16)Hi Wolfgang,
I think you have
FIELD_MASKbeing two meanings: the un-shifted or 'raw' mask, and the shifted mask. So perhaps:
My intention was to have only the real mask, i. e. what you need to apply to the register data (in your language the shifted mask).
Quoted 2 lines
#define FIELD_SHIFT 16
#define FIELD_RAWMASK 0xFThis is never really needed - you only use it once.
Quoted 2 lines
When you have a lot of these definitions in a row you have mentally check the bit width of the mask:
Yes, this is one of the disadvantages of thinking in bit fields and one reason why I never write code like that.
I mentioned this before - I consider it error prone [like most other "clever" tricks that "make life easy" and allow you to stop thinking].
Quoted 1 line
Is the above correct, or do fields overlap or not cover fully?
All this is possible. There may be overlapping definitions, and there may be reserved bits that need special handling.
There may even be bits that cannot simply be re-writeen as we read them, but that must always be written as zeroes or ones.
I never claimed that these "bit field" juggling was a clever idea. It works for some cases, and causes major pita for others.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de In an organization, each person rises to the level of his own incom- petency - The Peter Principle
PATCH v3 2/10 armv7: add miscellaneous utility macros
Quoted 39 lines · Wolfgang Denk
Dear Simon Glass,
Quoted 8 lines · In message <[email protected]> you wrote:
Quoted 8 lines
Looking closer, the "
FIELD_VAL" macro alone will probably not suffice, as you need both shift directions, like that:? ? ? ?#define
FIELD_SHIFT? ? 16
? ? ? ?#defineFIELD_MASK? ? ?0xFQuoted 8 lines
Quoted 3 lines
? ? ? ?#define
FIELD_BITS(x)(x << 16)
? ? ? ?#defineFIELD_MASKFIELD_BITS(0xF)
? ? ? ?#defineFIELD_VAL(x)((x &FIELD_MASK) >> 16)Hi Wolfgang,
I think you have
FIELD_MASKbeing two meanings: the un-shifted or 'raw' mask, and the shifted mask. So perhaps:My intention was to have only the real mask, i. e. what you need to apply to the register data (in your language the shifted mask).
Quoted 2 lines
? ? ? ? #define
FIELD_SHIFT? ? 16
? ? ? ? #defineFIELD_RAWMASK? ? ?0xFThis is never really needed - you only use it once.
Quoted 2 lines
When you have a lot of these definitions in a row you have mentally check the bit width of the mask:
Yes, this is one of the disadvantages of thinking in bit fields and one reason why I never write code like that.
I mentioned this before - I consider it error prone [like most other "clever" tricks that "make life easy" and allow you to stop thinking].
Quoted 1 line
Is the above correct, or do fields overlap or not cover fully?
Quoted 8 lines
All this is possible. ?There may be overlapping definitions, and there may be reserved bits that need special handling.
There may even be bits that cannot simply be re-writeen as we read them, but that must always be written as zeroes or ones.
I never claimed that these "bit field" juggling was a clever idea. It works for some cases, and causes major pita for others.
Hi Wolfgang,
Yes I agree, but I think you might have missed both my points.
Regards,
Simon
Quoted 13 lines
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, ? ? MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de In an organization, each person rises to the level of his own ?incom- petency ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - The Peter Principle
PATCH v3 2/10 armv7: add miscellaneous utility macros
In reply to Wolfgang DenkDear Wolfgang,
Quoted 29 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 4 lines · In message<[email protected]> you wrote:
Yes. I have seen those macros. But more often than not the bit field is more than 1 bit wide and the value to be set is not necessarily all 0's or all 1's. That's why I have to use clrsetbits_*()
I see. In such a case (and only then) clrsetbits_*() is indeed the right choice.
Quoted 7 lines
The problem I have to deal with is different.
get_bit_field()was intended to extract bit fields from an integer. So, the target usage will be something likethis(where a, b, and c are bit fields in register my_reg)u32
my_reg,a_val,b_val,c_val;Quoted 8 lines
u32
my_reg=readl(my_reg_addr);
a_val=get_bit_field(my_reg, a_mask);b_val=get_bit_field(my_reg, b_mask);c_val=get_bit_field(my_reg, c_mask);Do you see an alternative method for doing this using the standard macros?
Please see the example given here:
Quoted 7 lines
http://article.gmane.org/gmane.comp.boot-loaders.u-boot/101146
Looking closer, the "
FIELD_VAL" macro alone will probably not suffice, as you need both shift directions, like that:#define FIELD_SHIFT 16 #define FIELD_MASK 0xF
When I said mask I meant the 'shifted mask' like:
#define FIELD_MASK (0xF << 16)
So, the shift information is embedded in this mask and can be extracted by finding the first set bit. But in reality my get_bit_field() function indeed takes both arguments. So it's something like this:
#define get_bit_field(x, shift, mask)\ (((x) & (mask)) >> (shift))
#define A_SHIFT 16
#define A_MASK (0xF << 16)
and then use it like:
a_val = get_bit_field(my_reg, A_SHIFT, A_MASK);
Quoted 5 lines
#define FIELD_BITS(x) (x<< 16) #define FIELD_MASK FIELD_BITS(0xF) #define FIELD_VAL(x) ((x& FIELD_MASK)>> 16)
Quoted 7 lines
The code would then look something like this:
my_reg = readl(my_reg_addr); a_val = A_VAL(my_reg); b_val = B_VAL(my_reg); c_val = C_VAL(my_reg);
If I have to do something like this I will have to now generate macros like A_VAL(x) for hundreds of fields. Is it really necessary when the following will do the job for me with the existing infrastructure I have:
a_val = get_bit_field(my_reg, A_SHIFT, A_MASK);b_val = get_bit_field(my_reg, B_SHIFT, B_MASK);
Please note that in this case I don't have an alternative with standard macros. If this is not possible I would rather prefer to keep it simple like this:
a_val = (my_reg & A_MASK) >> A_SHIFT;
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Aneesh V,
Quoted 4 lines · In message <[email protected]> you wrote:
So, the shift information is embedded in this mask and can be extracted by finding the first set bit. But in reality my
get_bit_field()function indeed takes both arguments. So it's something like this:
As stated before, I will not accept any bit filed macros like get_bit_field().
Best regards,
Wolfgang Denk
Signature · 6 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Far back in the mists of ancient time, in the great and glorious days of the former Galactic Empire, life was wild, rich and largely tax free. - Douglas Adams, _The Hitchhiker's Guide to the Galaxy_
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Wolfgang,
Quoted 10 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 4 lines · In message<[email protected]> you wrote:
So, the shift information is embedded in this mask and can be extracted by finding the first set bit. But in reality my
get_bit_field()function indeed takes both arguments. So it's something like this:As stated before, I will not accept any bit filed macros like
get_bit_field().
Will you accept something like this?
a_val = (reg & a_mask) >> a_shift;
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Aneesh V,
Quoted 4 lines · In message <[email protected]> you wrote:
Will you accept something like this?
a_val= (reg &a_mask) >>a_shift;
Yes, of course (that's what seems most natural to me).
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de The use of anthropomorphic terminology when dealing with computing systems is a symptom of professional immaturity. -- Edsger Dijkstra
PATCH v3 2/10 armv7: add miscellaneous utility macros
Quoted 10 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 4 lines · In message <[email protected]> you wrote:
Will you accept something like this?
a_val= (reg &a_mask) >>a_shift;Yes, of course (that's what seems most natural to me).
Me too - The code is obvious - the desired value is being masked out of a larger composite value and then shifted right to bit 0
And to set the value then you have:
reg &= ~a_mask; /* Clear a_val */ reg |= (a_val << a_shift) & a_mask; /* Set new a_val */
AND'ing with a_mask is required to prevent accidental clobbering when a_val is out-of-range. May give undesirable results by setting an illegal a_val, but@least you don't clobber unrelated bit fields
Regards,
Graeme
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Graeme Russ,
Quoted 5 lines · In message <[email protected]> you wrote:
And to set the value then you have:
reg &= ~a_mask; /* Clear a_val */ reg |= (a_val << a_shift) & a_mask; /* Set new a_val */
This could be done using
clrsetbits_le32(®, a_mask, a_val << a_shift);
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: [email protected] I think animal testing is a terrible idea; they get all nervous and give the wrong answers.
PATCH v3 2/10 armv7: add miscellaneous utility macros
Hi Wolfgang,
Quoted 4 lines · Wolfgang Denk
Dear Graeme Russ,
Quoted 1 line · In message <[email protected]> you wrote:
Quoted 9 lines
Quoted 4 lines
And to set the value then you have:
reg &= ~a_mask; /* Clear a_val */ reg |= (a_val << a_shift) & a_mask; /* Set new a_val */This could be done using
clrsetbits_le32(®, a_mask, a_val << a_shift);
Well the funny thing is, I find the former more obvious than the later ;) (but that's because I am not familiar with clrsetbits*) - But yes, 'I get it'
Regards,
Graeme
PATCH v3 2/10 armv7: add miscellaneous utility macros
In reply to Wolfgang DenkQuoted 4 lines · Wolfgang Denk
Dear Graeme Russ,
Quoted 1 line · In message <[email protected]> you wrote:
Quoted 8 lines
Quoted 4 lines
And to set the value then you have:
reg &= ~a_mask; /* Clear a_val */ reg |= (a_val << a_shift) & a_mask; /* Set new a_val */This could be done using
clrsetbits_le32(®, a_mask, a_val << a_shift);
Not quite:
clrsetbits_le32(®, a_mask, (a_val << a_shift) & a_mask);
is equivalent except that, as already pointed out, clrsetbits and friends:
a) Are not portable because only ARM and PPC define them which makes them, by definition, non-standard
b) Each invocation results in a read barrier plus a write barrier
c) If the hardware register is sensitive to partial updates (i.e. requires all bit-fields to be updated in on operation) this requires a read into a local variable, calls to clrsetbits against that variable and finally a write-back - Lots of memory barriers
I know I'm going over old ground, and it's not that I am against clrsetbits, it's just good to know the limitations up-front. So remember, clrsetbits is not platform independent, prevents the compiler from optimising and will most likely impose a performance hit
Regards,
Graeme
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Graeme Russ,
Quoted 5 lines · In message <[email protected]> you wrote:
is equivalent except that, as already pointed out, clrsetbits and friends:
a) Are not portable because only ARM and PPC define them which makes them, by definition, non-standard
They should be added to _any_ arch/<arch>/include/asm/io.h that doesn't use them yet.
Quoted 1 line
b) Each invocation results in a read barrier plus a write barrier
...which is intentionally (actually mandatory) when accessing I/O memory, and negligable overhead on plain memory.
Quoted 4 lines
c) If the hardware register is sensitive to partial updates (i.e. requires all bit-fields to be updated in on operation) this requires a read into a local variable, calls to clrsetbits against that variable and finally a write-back - Lots of memory barriers
Wrong. The macro does this automatically. There is only a single read and a single write per call.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Ernest asks Frank how long he has been working for the company.
"Ever since they threatened to fire me."PATCH v3 2/10 armv7: add miscellaneous utility macros
Hi Wolfgang,
Quoted 8 lines · Wolfgang Denk
Dear Graeme Russ,
Quoted 5 lines · In message <[email protected]> you wrote:
is equivalent except that, as already pointed out, clrsetbits and friends:
?a) Are not portable because only ARM and PPC define them which makes ? ? them, by definition, non-standard
Agreed - As mentioned in another post, I will look to implement clrsetbits and friends in x86 at some point
Quoted 7 lines
They should be added to _any_ arch/<arch>/include/asm/io.h that doesn't use them yet.
Quoted 1 line
?b) Each invocation results in a read barrier plus a write barrier
...which is intentionally (actually mandatory) when accessing I/O memory, and negligable overhead on plain memory.
Agreed - The raw performance overhead of the barriers is most likely negligible, although is there possibly a cache flush/sync operation or flush of the predictive branch cache that could have a more significant impact? I don't see this as such a huge problem since clrsetbits is (usually) used to update hardware registers, any flush will happen anyway
Quoted 7 lines
Quoted 4 lines
?c) If the hardware register is sensitive to partial updates (i.e. requires ? ? all bit-fields to be updated in on operation) this requires a read into ? ? a local variable, calls to clrsetbits against that variable and finally ? ? a write-back - Lots of memory barriers
Wrong. The macro does this automatically. ?There is only a single read and a single write per call.
I mean:
clrsetbits(&foo_reg, foo_val_1, foo_val_1_mask); clrsetbits(&foo_reg, foo_val_2, foo_val_2_mask); clrsetbits(&foo_reg, foo_val_3, foo_val_3_mask);
This could cause side-effects if foo_reg is sensitive to the three foo_val's being set independently. To ensure all three values are updated in a single write to foo_reg you would need to do:
foo_tmp = readl(&foo_reg); clrsetbits(&foo_tmp, foo_val_1, foo_val_1_mask); clrsetbits(&foo_tmp, foo_val_2, foo_val_2_mask); clrsetbits(&foo_tmp, foo_val_3, foo_val_3_mask); foo_tmp = writel(foo_tmp, &foo_reg);
Regards,
Graeme
PATCH v3 2/10 armv7: add miscellaneous utility macros
In reply to Graeme RussHi Grame,
Quoted 15 lines · Graeme Russ
Quoted 10 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 4 lines · In message<[email protected]> you wrote:
Will you accept something like this?
a_val= (reg&a_mask)>>a_shift;Yes, of course (that's what seems most natural to me).
Me too - The code is obvious - the desired value is being masked out of a larger composite value and then shifted right to bit 0
Quoted 8 lines
And to set the value then you have:
reg&= ~a_mask; /* Clear a_val */ reg |= (a_val<< a_shift)& a_mask; /* Set new a_val */AND'ing with
a_maskis required to prevent accidental clobbering whena_valis out-of-range. May give undesirable results by setting an illegala_val, but at least you don't clobber unrelated bit fields
These are exactly what my helper functions were doing. Are you suggesting that doing these directly is better than doing them using helper functions?
best regards,
Aneesh
PATCH v3 2/10 armv7: add miscellaneous utility macros
Hi Aneesh,
Quoted 25 lines · Aneesh V
Hi Grame,
Quoted 22 lines · Graeme Russ
Quoted 11 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 4 lines · In message<[email protected]> ?you wrote:
Will you accept something like this?
a_val= (reg& ?a_mask)>> ?a_shift;Yes, of course (that's what seems most natural to me).
Me too - The code is obvious - the desired value is being masked out of a larger composite value and then shifted right to bit 0
And to set the value then you have:
? ? ? ?reg&= ~a_mask; ? ? ? ? ? ? ? ? ? ? ? ? ?/* Clear
a_val*/ ? ? ? ?reg |= (a_val<< ?a_shift)& ?a_mask; ? ? /* Set newa_val*/
Quoted 8 lines
Quoted 4 lines
AND'ing with
a_maskis required to prevent accidental clobbering whena_val
is out-of-range. May give undesirable results by setting an illegala_val, but at least you don't clobber unrelated bit fieldsThese are exactly what my helper functions were doing. Are you suggesting that doing these directly is better than doing them using helper functions?
I (personally) think that the two lines of memberwise bit mask/shift is more obvious in its intent that even clrsetbits. I understand there is defensive programming issues that can be applied with macros or helper functions, but then the you loose 'obviousness' and sometimes this can make figuring out the problem even harder (one assumes the macro or helper function works properly).
When push comes to shove, the compiler will probably produce identical code anyway.
Sometimes I like seeing the raw elegance of what is going on under the hood :)
Now, that being said, I see no reason not to do the following if I had, for example, multiple serial port configuration registers which are all identical:
/* num data bits is stored in bits 2-4 of the serial config register */
#define DATA_BITS_MASK 0x001c
#define DATA_BITS_OFFSET 2
u32 set_serial_data_bits(u32 ser_cfg, u8 data_bits)
{
ser_cfg &= ~DATA_BITS_MASK;
ser_cfg |= ((u32)ser_cfg << DATA_BITS_OFFSET) & ?DATA_BITS_MASK;
return ser_cfg;
}void serial_init(void)
{
u32 ser_cfg;
for (i=0; i<NUM_SERIAL_PORTS; i++) {
ser_cfg = read_serial_cfg(i);
ser_cfg = set_serial_data_bits(ser_cfg, 7);
write_serial_cfg(i, ser_cfg);
}
}But that's just me - I tend to avoid #define macros
Regards,
Graeme
PATCH v3 2/10 armv7: add miscellaneous utility macros
Dear Graeme Russ,
Quoted 18 lines · In message <[email protected]> you wrote:
Now, that being said, I see no reason not to do the following if I had, for example, multiple serial port configuration registers which are all identical:
/* num data bits is stored in bits 2-4 of the serial config register */
#defineDATA_BITS_MASK0x001c
#defineDATA_BITS_OFFSET2u32
set_serial_data_bits(u32 ser_cfg, u8 data_bits){ ser_cfg &= ~DATA_BITS_MASK; ser_cfg |= ((u32)ser_cfg << DATA_BITS_OFFSET) & ?DATA_BITS_MASK; return ser_cfg; }void
serial_init(void)
Quoted 9 lines
{
u32 ser_cfg;
for (i=0; i<NUM_SERIAL_PORTS; i++) {
ser_cfg = read_serial_cfg(i);
ser_cfg = set_serial_data_bits(ser_cfg, 7);
write_serial_cfg(i, ser_cfg);
}
}One reason for not doing this is that we should not reinvent the wheel again and again, and instead use standard APIs.
I cannot find any such code in U-Boot, so I cannot check, but to me it smells a lot as if this code should rather use clrsetbits_*() and other proper I/O accessors.
Best regards,
Wolfgang Denk
Signature · 6 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Steal five dollars and you were a petty thief. Steal thousands of
dollars and you are either a government or a hero.
- Terry Pratchett, _Going_Postal_PATCH v3 2/10 armv7: add miscellaneous utility macros
Quoted 31 lines · Wolfgang Denk
Dear Graeme Russ,
Quoted 18 lines · In message <[email protected]> you wrote:
Now, that being said, I see no reason not to do the following if I had, for example, multiple serial port configuration registers which are all identical:
/* num data bits is stored in bits 2-4 of the serial config register */
#defineDATA_BITS_MASK0x001c
#defineDATA_BITS_OFFSET2u32
set_serial_data_bits(u32 ser_cfg, u8 data_bits){ ser_cfg &= ~DATA_BITS_MASK; ser_cfg |= ((u32)ser_cfg << DATA_BITS_OFFSET) & DATA_BITS_MASK; return ser_cfg; }void
serial_init(void)Quoted 9 lines
{ u32 ser_cfg; for (i=0; i<NUM_SERIAL_PORTS; i++) { ser_cfg = read_serial_cfg(i); ser_cfg = set_serial_data_bits(ser_cfg, 7); write_serial_cfg(i, ser_cfg); } }
Quoted 6 lines
One reason for not doing this is that we should not reinvent the wheel again and again, and instead use standard APIs.
I cannot find any such code in U-Boot, so I cannot check, but to me it smells a lot as if this code should rather use clrsetbits_*() and other proper I/O accessors.
Except nobody outside ARM and PPC knows about clrsetbits and friends, so I would not call them a standard API
I will, however, keep them in mind and implement them for x86 when I have a need for bit-field operations
Regards,
Graeme
PATCH v3 3/10 armv7: cache maintenance operations for armv7
In reply to Aneesh V- Add a framework for layered cache maintenance
- separate out SOC specific outer cache maintenance from maintenance of caches known to CPU
- Add generic ARMv7 cache maintenance operations that affect all caches known to ARMv7 CPUs. For instance in Cortex-A8 these opertions will affect both L1 and L2 caches. In Cortex-A9 these will affect only L1 cache
- D-cache operations supported:
- Invalidate entire D-cache
- Invalidate D-cache range
- Flush(clean & invalidate) entire D-cache
- Flush D-cache range
- I-cache operations supported:
- Invalidate entire I-cache
- Add maintenance functions for TLB, branch predictor array etc.
- Enable -march=armv7-a so that armv7 assembly instructions can be used
---
V2:
* Blank line after local variable declarations - fixed globally
* Change from pointers to weakly linked functions for outer cache operations
* Explicitly added a copy of flush_cache() under #ifdefCONFIG_SYS_NO_DCACHE
* Change -march=armv7-a back to armv5
* Update documentation with cache related CONFIG options
--- README | 5 + arch/arm/cpu/armv7/Makefile | 2 +- arch/arm/cpu/armv7/cache_v7.c | 390 +++++++++++++++++++++++++++++++++++++++++ arch/arm/include/asm/armv7.h | 68 +++++++ include/common.h | 5 +- 5 files changed, 468 insertions(+), 2 deletions(-) create mode 100644 arch/arm/cpu/armv7/cache_v7.c create mode 100644 arch/arm/include/asm/armv7.h
README +5 -0
@@ -455,6 +455,11 @@ The following options need to be configured: Note: If a "bootargs" environment is defined, it will overwride the defaults discussed just above. +- Cache Configuration: + CONFIG_SYS_NO_ICACHE - Do not enable instruction cache in U-Boot + CONFIG_SYS_NO_DCACHE - Do not enable data cache in U-Boot + CONFIG_SYS_NO_L2CACHE- Do not enable L2 cache in U-Boot + - Serial Ports: CONFIG_PL010_SERIAL
arch/arm/cpu/armv7/Makefile +1 -1
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).o START := start.o -COBJS := cpu.o +COBJS := cpu.o cache_v7.o COBJS += syslib.o SRCS := $(START:.o=.S) $(COBJS:.o=.c)
arch/arm/cpu/armv7/cache_v7.c new file +390 -0
390 lines not on this page · raw message
arch/arm/include/asm/armv7.h new file +68 -0
68 lines not on this page · raw message
include/common.h +4 -1
@@ -413,6 +413,7 @@ void icache_disable(void);int dcache_status (void );void dcache_enable (void );void dcache_disable (void ); +void mmu_disable (void );void relocate_code (ulong ,gd_t *,ulong ) __attribute__ ((noreturn));ulong get_endaddr (void );void trap_init (ulong );
@@ -614,9 +615,11 @@ ulong video_setmem (ulong);/* arch/$(ARCH)/lib/cache.c */ void flush_cache (unsigned long ,unsigned long ); +void flush_dcache_all (void );void flush_dcache_range (unsigned long start,unsigned long stop);void invalidate_dcache_range (unsigned long start,unsigned long stop); - +void invalidate_dcache_all (void ); +void invalidate_icache_all (void );/* arch/$(ARCH)/lib/ticks.S */ unsigned long long get_ticks (void );
Signature · 1 line
1.7.0.4
PATCH v3 3/10 armv7: cache maintenance operations for armv7
Dear Aneesh V,
Quoted 9 lines · In message <[email protected]> you wrote:
- Add a framework for layered cache maintenance
- separate out SOC specific outer cache maintenance from maintenance of caches known to CPU- Add generic ARMv7 cache maintenance operations that affect all caches known to ARMv7 CPUs. For instance in Cortex-A8 these opertions will affect both L1 and L2 caches. In Cortex-A9 these will affect only L1 cache
Quoted 5 lines
- D-cache operations supported:
- Invalidate entire D-cache
- Invalidate D-cache range
-Flush(clean & invalidate)entire D-cache
- Flush D-cache range
How much of this is actually needed in the context of U-Boot?
...
arch/arm/cpu/armv7/cache_v7.c line 82
Quoted 8 lines
arch/arm/cpu/armv7/cache_v7.c new file +8
-0+for (way = num_ways -1 ; way >=0 ; way--) +for (set = num_sets -1 ; set >=0 ; set--) { + setway = (level <<1 ) | (set << log2_line_len) | + (way << way_shift); +/* Invalidate data/unified cache line by set/way */ + asmvolatile (" mcr p15, 0, %0, c7, c6, 2" + : :"r" (setway)); + }
Braces needed for multiline for(). Please fix globally.
...
arch/arm/cpu/armv7/cache_v7.c line 144
Quoted 6 lines
arch/arm/cpu/armv7/cache_v7.c new file +6
-0+if (operation ==ARMV7_DCACHE_INVAL_ALL ) +v7_inval_dcache_level_setway (level, num_sets, num_ways, + way_shift, log2_line_len); +else if (operation ==ARMV7_DCACHE_CLEAN_INVAL_ALL ) +v7_clean_inval_dcache_level_setway (level, num_sets, num_ways, + way_shift, log2_line_len);
Braces needed for multiline statements. Please fix globally.
arch/arm/cpu/armv7/cache_v7.c line 173
Quoted 3 lines
arch/arm/cpu/armv7/cache_v7.c new file +3
-0+for (mva = start; mva < stop; mva = mva + line_len) +/* DCCIMVAC - Clean & Invalidate data cache by MVA to PoC */ + asmvolatile ("mcr p15, 0, %0, c7, c14, 1" : :"r" (mva));
And again etc. etc.
...
Quoted 13 lines
arch/arm/cpu/armv7/cache_v7.c new file +13
-0+void invalidate_dcache_all (void ) +{ +} + +void flush_dcache_all (void ) +{ +} + +void invalidate_dcache_range (unsigned long start,unsigned long stop) +{ +} + +void flush_dcache_range (unsigned long start,unsigned long stop)
arch/arm/cpu/armv7/cache_v7.c line 301
Quoted 10 lines
arch/arm/cpu/armv7/cache_v7.c new file +10
-0+{ +} + +void arm_init_before_mmu (void ) +{ +} + +void flush_cache (unsigned long start,unsigned long size) +{ +}
Please do not add dead code. I consider it misleading to have functions which promise to perform something, and actually do nothing.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Gods don't like people not doing much work. People who aren't busy all the time might start to _think_. - Terry Pratchett, _Small Gods_
PATCH v3 3/10 armv7: cache maintenance operations for armv7
Quoted 14 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 11 lines · In message<[email protected]> you wrote:
- Add a framework for layered cache maintenance
- separate out SOC specific outer cache maintenance from maintenance of caches known to CPU- Add generic ARMv7 cache maintenance operations that affect all caches known to ARMv7 CPUs. For instance in Cortex-A8 these opertions will affect both L1 and L2 caches. In Cortex-A9 these will affect only L1 cache
- D-cache operations supported:
- Invalidate entire D-cache
Needed before enabling the caches.
Quoted 1 line
Quoted 1 line
- Invalidate D-cache range
Needed if you are doing DMA.
Quoted 1 line
Quoted 1 line
-
Flush(clean& invalidate)entire D-cache
Needed before Linux before disabling the caches.
Quoted 1 line
Quoted 1 line
- Flush D-cache range
Needed in case of DMA out.
Quoted 2 lines
How much of this is actually needed in the context of U-Boot?
Please see above. As far as I know OMAP doesn't do DMA in U-Boot.
Quoted 12 lines
...
arch/arm/cpu/armv7/cache_v7.c line 82
Quoted 8 lines
arch/arm/cpu/armv7/cache_v7.c new file +8
-0+for (way = num_ways -1 ; way>=0 ; way--) +for (set = num_sets -1 ; set>=0 ; set--) { + setway = (level<<1 ) | (set<< log2_line_len) | + (way<< way_shift); +/* Invalidate data/unified cache line by set/way */ + asmvolatile (" mcr p15, 0, %0, c7, c6, 2" + : :"r" (setway)); + }Braces needed for multiline
for(). Please fix globally.
Ok.
Quoted 37 lines
...
arch/arm/cpu/armv7/cache_v7.c line 144
Quoted 6 lines
arch/arm/cpu/armv7/cache_v7.c new file +6
-0+if (operation ==ARMV7_DCACHE_INVAL_ALL ) +v7_inval_dcache_level_setway (level, num_sets, num_ways, + way_shift, log2_line_len); +else if (operation ==ARMV7_DCACHE_CLEAN_INVAL_ALL ) +v7_clean_inval_dcache_level_setway (level, num_sets, num_ways, + way_shift, log2_line_len);Braces needed for multiline statements. Please fix globally.
Review
Quoted 3 lines
(quoted diff) +3
-0+ for (mva = start; mva< stop; mva = mva + line_len) + /* DCCIMVAC - Clean& Invalidate data cache by MVA to PoC */ + asm volatile ("mcr p15, 0, %0, c7, c14, 1" : : "r" (mva));And again etc. etc.
...
Quoted 18 lines
arch/arm/cpu/armv7/cache_v7.c new file +18
-0+void invalidate_dcache_all (void ) +{ +} + +void flush_dcache_all (void ) +{ +} + +void invalidate_dcache_range (unsigned long start,unsigned long stop) +{ +} + +void flush_dcache_range (unsigned long start,unsigned long stop) +{ +} + +void arm_init_before_mmu (void ) +{
Quoted 8 lines
arch/arm/cpu/armv7/cache_v7.c line 301
Quoted 5 lines
arch/arm/cpu/armv7/cache_v7.c new file +5
-0+} + +void flush_cache (unsigned long start,unsigned long size) +{ +}Please do not add dead code. I consider it misleading to have functions which promise to perform something, and actually do nothing.
These are empty only in the else part of an #ifdef. When cache support is compiled out these need to be empty.
best regards,
Aneesh
PATCH v3 3/10 armv7: cache maintenance operations for armv7
Dear Aneesh V,
Quoted 4 lines · In message <[email protected]> you wrote:
Quoted 2 lines
How much of this is actually needed in the context of U-Boot?
Please see above. As far as I know OMAP doesn't do DMA in U-Boot.
Devices like USB oth Ethernet don't use DMA for data transfers?
Quoted 5 lines
Quoted 2 lines
Please do not add dead code. I consider it misleading to have functions which promise to perform something, and actually do nothing.
These are empty only in the else part of an #ifdef. When cache support is compiled out these need to be empty.
When cache support is compiled out there should be no callers to these functions, so maybe they can disappear?
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
No journaling file system can recover your data if the disk dies.
- Steve Rago in <[email protected]>PATCH v3 3/10 armv7: cache maintenance operations for armv7
Quoted 10 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 4 lines · In message<[email protected]> you wrote:
Quoted 2 lines
How much of this is actually needed in the context of U-Boot?
Please see above. As far as I know OMAP doesn't do DMA in U-Boot.
Devices like USB oth Ethernet don't use DMA for data transfers?
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
Please do not add dead code. I consider it misleading to have functions which promise to perform something, and actually do nothing.
These are empty only in the else part of an #ifdef. When cache support is compiled out these need to be empty.
When cache support is compiled out there should be no callers to these functions, so maybe they can disappear?
No, there may be callers in drivers. It will be ugly to keep all the calls in various drivers under #ifdef, right? Is it not better to have some empty functions and not worrying about the calls in various places.
best regards,
Aneesh
PATCH v3 3/10 armv7: cache maintenance operations for armv7
In reply to Wolfgang DenkHi Wolfgang,
Quoted 9 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 4 lines · In message<[email protected]> you wrote:
Quoted 2 lines
How much of this is actually needed in the context of U-Boot?
Please see above. As far as I know OMAP doesn't do DMA in U-Boot.
Devices like USB oth Ethernet don't use DMA for data transfers?
Ethernet support is not upstreamed yet. USB doesn't seem to be using DMA on a quick check.
best regards,
Aneesh
PATCH v3 3/10 armv7: cache maintenance operations for armv7
Hi,
I am picking up on this old thread. My main point is that I think the armv7 cache implementation is a good start and should go into U-Boot. Aneesh are you planning another patch set? Also see below:
Quoted 7 lines · Aneesh V
Hi Wolfgang,
Quoted 4 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 1 line · In message<[email protected]> ?you wrote:
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
How much of this is actually needed in the context of U-Boot?
Please see above. As far as I know OMAP doesn't do DMA in U-Boot.
Devices like USB oth Ethernet don't use DMA for data transfers?
Ethernet support is not upstreamed yet. USB doesn't seem to be using DMA on a quick check.
There is DMA in the USB EHCI side and this also does d cache range invalidate / flush.
Regards,
Simon
Quoted 8 lines
best regards,
Aneesh
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
PATCH v3 4/10 armv7: replace CONFIG_L2_OFF with CONFIG_SYS_NO_L2CACHE
In reply to Aneesh Vreplace all occurences of CONFIG_L2_OFF with a more appropriate CONFIG_SYS_NO_L2CACHE
CONFIG_SYS_NO_L2CACHE has been chosen to be in line with CONFIG_SYS_NO_ICACHE and CONFIG_SYS_NO_DCACHE
--- arch/arm/cpu/armv7/cpu.c | 6 +----- include/configs/ca9x4_ct_vxp.h | 2 +- include/configs/efikamx.h | 2 +- include/configs/mx51evk.h | 2 +- include/configs/mx53evk.h | 2 +- include/configs/omap4_panda.h | 2 +- include/configs/omap4_sdp4430.h | 2 +- include/configs/s5pc210_universal.h | 2 +- include/configs/tegra2-common.h | 2 +- include/configs/vision2.h | 2 +- 10 files changed, 10 insertions(+), 14 deletions(-)
arch/arm/cpu/armv7/cpu.c +1 -5
@@ -35,11 +35,7 @@#include <command.h> #include <asm/system.h> #include <asm/cache.h> -#ifndef CONFIG_L2_OFF -#include <asm/arch/sys_proto.h> -#endif - -static void cache_flush (void ); +#include <asm/armv7.h> int cleanup_before_linux (void ) {
include/configs/ca9x4_ct_vxp.h +1 -1
@@ -41,7 +41,7 @@#define CONFIG_CMDLINE_TAG 1/* enable passing of ATAGs */ #define CONFIG_SETUP_MEMORY_TAGS 1 -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_NO_L2CACHE 1#define CONFIG_INITRD_TAG 1#define CONFIG_OF_LIBFDT 1
include/configs/efikamx.h +1 -1
@@ -38,7 +38,7 @@#define CONFIG_DISPLAY_CPUINFO #define CONFIG_DISPLAY_BOARDINFO -#define CONFIG_L2_OFF +#define CONFIG_SYS_NO_L2CACHE /* * Bootloader Components Configuration
include/configs/mx51evk.h +1 -1
@@ -35,7 +35,7 @@#define CONFIG_SYS_TEXT_BASE 0x97800000 -#define CONFIG_L2_OFF +#define CONFIG_SYS_NO_L2CACHE #include <asm/arch/imx-regs.h> /*
include/configs/mx53evk.h +1 -1
@@ -29,7 +29,7 @@#define CONFIG_DISPLAY_CPUINFO #define CONFIG_DISPLAY_BOARDINFO -#define CONFIG_L2_OFF +#define CONFIG_SYS_NO_L2CACHE #include <asm/arch/imx-regs.h>
include/configs/omap4_panda.h +1 -1
@@ -46,7 +46,7 @@#define CONFIG_DISPLAY_BOARDINFO 1/* Keep L2 Cache Disabled */ -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_NO_L2CACHE 1/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */
include/configs/omap4_sdp4430.h +1 -1
@@ -47,7 +47,7 @@#define CONFIG_DISPLAY_BOARDINFO 1/* Keep L2 Cache Disabled */ -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_NO_L2CACHE 1/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */
include/configs/s5pc210_universal.h +1 -1
@@ -43,7 +43,7 @@#define CONFIG_DISPLAY_BOARDINFO /* Keep L2 Cache Disabled */ -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_NO_L2CACHE 1#define CONFIG_SYS_SDRAM_BASE 0x40000000#define CONFIG_SYS_TEXT_BASE 0x44800000
include/configs/tegra2-common.h +1 -1
@@ -31,7 +31,7 @@#define CONFIG_ARMCORTEXA9 /* This is an ARM V7 CPU core */ #define CONFIG_TEGRA2 /* in a NVidia Tegra2 core */ #define CONFIG_MACH_TEGRA_GENERIC /* which is a Tegra generic machine */ -#define CONFIG_L2_OFF /* No L2 cache */ +#define CONFIG_SYS_NO_L2CACHE /* No L2 cache */ #define CONFIG_ENABLE_CORTEXA9 /* enable CPU (A9 complex) */
include/configs/vision2.h +1 -1
@@ -26,7 +26,7 @@#define CONFIG_MX51 /* in a mx51 */ -#define CONFIG_L2_OFF +#define CONFIG_SYS_NO_L2CACHE #include <asm/arch/imx-regs.h>
Signature · 1 line
1.7.0.4
PATCH v3 4/10 armv7: replace CONFIG_L2_OFF with CONFIG_SYS_NO_L2CACHE
Dear Aneesh V,
Quoted 5 lines · In message <[email protected]> you wrote:
replace all occurences of
CONFIG_L2_OFFwith a more appropriateCONFIG_SYS_NO_L2CACHE
CONFIG_SYS_NO_L2CACHEhas been chosen to be in line withCONFIG_SYS_NO_ICACHEandCONFIG_SYS_NO_DCACHE
sorry, but these are ugly mis-nomers. The situation is not that there is no cache present (which "NO_*CACHE" suggestes), but that the cache is (kept) turned off.
CONFIG_SYS_L2CACHE_OFF is a _much_ better name than CONFIG_SYS_NO_L2CACHE.
Please fix all these names.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Not one hundred percent efficient, of course ... but nothing ever is. -- Kirk, "Metamorphosis", stardate 3219.8
PATCH v3 4/10 armv7: replace CONFIG_L2_OFF with CONFIG_SYS_NO_L2CACHE
Hi Wolfgang,
Quoted 9 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 5 lines · In message<[email protected]> you wrote:
replace all occurences of
CONFIG_L2_OFFwith a more appropriateCONFIG_SYS_NO_L2CACHE
CONFIG_SYS_NO_L2CACHEhas been chosen to be in line withCONFIG_SYS_NO_ICACHEandCONFIG_SYS_NO_DCACHE
Quoted 7 lines
sorry, but these are ugly mis-nomers. The situation is not that there is no cache present (which "NO_*CACHE" suggestes), but that the cache is (kept) turned off.
CONFIG_SYS_L2CACHE_OFFis a _much_ better name thanCONFIG_SYS_NO_L2CACHE.Please fix all these names.
Ok. Including the existing CONFIG_SYS_NO_DCACHE and CONFIG_SYS_NO_ICACHE too, right?
best regards,
Aneesh
PATCH v3 4/10 armv7: replace CONFIG_L2_OFF with CONFIG_SYS_NO_L2CACHE
Dear Aneesh V,
Quoted 5 lines · In message <[email protected]> you wrote:
Quoted 2 lines
Please fix all these names.
Ok. Including the existing
CONFIG_SYS_NO_DCACHEandCONFIG_SYS_NO_ICACHEtoo, right?
yes, please. Thanks a lot!
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de "A child is a person who can't understand why someone would give away a perfectly good kitten." - Doug Larson
PATCH v3 4/10 armv7: replace CONFIG_L2_OFF with CONFIG_SYS_NO_L2CACHE
Hi Wolfgang,
Quoted 10 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 5 lines · In message<[email protected]> you wrote:
Quoted 2 lines
Please fix all these names.
Ok. Including the existing
CONFIG_SYS_NO_DCACHEandCONFIG_SYS_NO_ICACHEtoo, right?yes, please. Thanks a lot!
How about the existing flag CONFIG_SYS_NO_CP15_CACHE
I think this flag should be simply removed. I think CONFIG_SYS_ICACHE_OFF and CONFIG_SYS_DCACHE_OFF together can serve all needs.
best regards,
Aneesh
PATCH v3 4/10 armv7: replace CONFIG_L2_OFF with CONFIG_SYS_NO_L2CACHE
Dear Aneesh V,
Quoted 12 lines · In message <[email protected]> you wrote:
Hi Wolfgang,
Quoted 9 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 5 lines · In message<[email protected]> you wrote:
Quoted 2 lines
Please fix all these names.
Ok. Including the existing
CONFIG_SYS_NO_DCACHEandCONFIG_SYS_NO_ICACHEtoo, right?
Quoted 7 lines
Quoted 1 line
yes, please. Thanks a lot!
How about the existing flag
CONFIG_SYS_NO_CP15_CACHEI think this flag should be simply removed. I think
CONFIG_SYS_ICACHE_OFFandCONFIG_SYS_DCACHE_OFFtogether can serve all needs.
Agreed. Thanks.
Best regards,
Wolfgang Denk
Signature · 4 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Monday is an awful way to spend one seventh of your life.
PATCH v3 5/10 armv7: integrate cache maintenance support
In reply to Aneesh V- Enable I-cache on bootup
- Enable MMU and D-cache immediately after relocation
- Do necessary initialization before enabling d-cache and MMU
- Changes to cleanup_before_linux()
- Make changes according to the new framework
---
V2:
* Changes for -march=armv7a -> armv5 change
* Removed the print inside the weakly linked stub function - __arm_init_before_mmu
--- arch/arm/cpu/armv7/cpu.c | 45 +++++++++++++++++++------------------------ arch/arm/cpu/armv7/start.S | 18 ++++++++++++++++- arch/arm/lib/board.c | 6 +++++ arch/arm/lib/cache-cp15.c | 7 ++++++ arch/arm/lib/cache.c | 5 ---- 5 files changed, 50 insertions(+), 31 deletions(-)
arch/arm/cpu/armv7/cpu.c +20 -25
@@ -34,13 +34,10 @@#include <common.h> #include <command.h> #include <asm/system.h> -#include <asm/cache.h> #include <asm/armv7.h> int cleanup_before_linux (void ) { -unsigned int i; -/* * this function is called just before we call linux * it prepares the processor for linux
@@ -49,31 +46,29 @@ int cleanup_before_linux(void)*/ disable_interrupts (); -/* turn off I/D-cache */ +/* +* Turn off I-cache and invalidate it +*/ icache_disable (); -dcache_disable (); +invalidate_icache_all (); -/* invalidate I-cache */ -cache_flush (); - -#ifndef CONFIG_L2_OFF -/* turn off L2 cache */ -l2_cache_disable (); -/* invalidate L2 cache also */ -invalidate_dcache (get_device_type ()); -#endif - i =0 ; -/* mem barrier to sync up things */ - asm("mcr p15, 0, %0, c7, c10, 4" : :"r" (i)); +/* +* turn off D-cache +* dcache_disable() in turn flushes the d-cache and disables MMU +*/ +dcache_disable (); -#ifndef CONFIG_L2_OFF -l2_cache_enable (); -#endif +/* +* After D-cache is flushed and before it is disabled there may +* be some new valid entries brought into the cache. We are sure +* that these lines are not dirty and will not affect our execution. +* (because unwinding the call-stack and setting a bit in CP15 SCTRL +* is all we did during this. We have not pushed anything on to the +* stack. Neither have we affected any static data) +* So just invalidate the entire d-cache again to avoid coherency +* problems for kernel +*/ +invalidate_dcache_all ();return 0 ; } - -static void cache_flush (void ) -{ - asm ("mcr p15, 0, %0, c7, c5, 0" : :"r" (0 )); -}
arch/arm/cpu/armv7/start.S +17 -1
@@ -255,6 +255,14 @@ clbss_l:str r2, [r0] /* clear loop... */ * initialization, now running from RAM. */ jump_2_ram: +/* + * If I-cache is enabled invalidate it + */ +#ifndef CONFIG_SYS_NO_ICACHE + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB +#endif ldr r0, _board_init_r_ofs adr r1, _start add lr, r0, r1
@@ -290,6 +298,9 @@ cpu_init_crit: mov r0, #0 @ set up for MCR mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB /* * disable MMU stuff and caches
@@ -298,7 +309,12 @@ cpu_init_crit: bic r0, r0, #0x00002000 @ clear bits 13 (--V-) bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align - orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB +#ifdef CONFIG_SYS_NO_ICACHE + bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache +#else + orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache +#endif mcr p15, 0, r0, c1, c0, 0 /*
arch/arm/lib/board.c +6 -0
@@ -464,6 +464,12 @@ void board_init_r (gd_t *id, ulong dest_addr) gd->flags |=GD_FLG_RELOC ;/* tell others: relocation done */ monitor_flash_len = _end_ofs; +/* +* Enable D$: +* I$, if needed, must be already enabled in start.S +*/ +dcache_enable (); +debug ("monitor flash len: %08lX\n" , monitor_flash_len);board_init ();/* Setup chipselects */
arch/arm/lib/cache-cp15.c +7 -0
@@ -34,6 +34,12 @@DECLARE_GLOBAL_DATA_PTR ; +void __arm_init_before_mmu (void ) +{ +} +void arm_init_before_mmu (void ) + __attribute__((weak,alias ("__arm_init_before_mmu" ))); +static void cp_delay (void ) {volatile int i;
@@ -65,6 +71,7 @@ static inline void mmu_setup(void)int i;u32 reg; +arm_init_before_mmu ();/* Set up an identity-mapping for all 4GB, rw for everyone */ for (i =0 ; i <4096 ; i++) page_table[i] = i <<20 | (3 <<10 ) |0x12 ;
arch/arm/lib/cache.c +0 -5
@@ -38,11 +38,6 @@ void __flush_cache(unsigned long start, unsigned long size)/* disable write buffer as well (page 2-22) */ asm("mcr p15, 0, %0, c7, c10, 4" : :"r" (0 ));#endif -#ifdef CONFIG_OMAP34XX -void v7_flush_cache_all (void ); - -v7_flush_cache_all (); -#endif return ; }void flush_cache (unsigned long start,unsigned long size)
Signature · 1 line
1.7.0.4
PATCH v3 5/10 armv7: integrate cache maintenance support
Dear Aneesh V,
Quoted 3 lines · In message <[email protected]> you wrote:
- Enable I-cache on bootup
- Enable MMU and D-cache immediately after relocation
- Do necessary initialization before enabling d-cache and MMU
Would it be possible to do this even _before_ relocation, so to speed up memory accesses during relocation? Of course, proper invalidates/ flushes will be needed before jumping to the RAM address, but I guess this would save a bit of boot times?
Best regards,
Wolfgang Denk
Signature · 6 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Q: How do you play religious roulette?
A: You stand around in a circle and blaspheme and see who gets
struck by lightning first.PATCH v3 5/10 armv7: integrate cache maintenance support
Hi Wolfgang,
Quoted 11 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 3 lines · In message<[email protected]> you wrote:
- Enable I-cache on bootup
- Enable MMU and D-cache immediately after relocation
- Do necessary initialization before enabling d-cache and MMUWould it be possible to do this even _before_ relocation, so to speed up memory accesses during relocation? Of course, proper invalidates/ flushes will be needed before jumping to the RAM address, but I guess this would save a bit of boot times?
I intentionally kept it after relocation to avoid un-necessary complexities.
Relocation is a case of self-modifying code. In Harvard architectures like armv7 there will be coherency issues unless we flush the entire D-cache(range based operation may be equally or more expensive) and invalidate the entire I-cache.
So, in effect everything has to be flushed to memory before you jump to the new location. There may be a small advantage because flushing from cache allows for bursting to the DDR where as bursting is not possible when d-cache is disabled. But I think this is not worth the trouble.
best regards,
Aneesh
PATCH v3 5/10 armv7: integrate cache maintenance support
Dear Aneesh V,
Quoted 8 lines · In message <[email protected]> you wrote:
Quoted 5 lines
Would it be possible to do this even _before_ relocation, so to speed up memory accesses during relocation? Of course, proper invalidates/ flushes will be needed before jumping to the RAM address, but I guess this would save a bit of boot times?
I intentionally kept it after relocation to avoid un-necessary complexities.
Yes, I can understand this. Do you plean to extend this to include relocation n a later step?
Quoted 4 lines
Relocation is a case of self-modifying code. In Harvard architectures like armv7 there will be coherency issues unless we flush the entire D-cache(range based operation may be equally or more expensive) and invalidate the entire I-cache.
I would not call this self-modifying code.
Regarding the need to flush/invalidate caches when jumping to RAM:
yes, we have to flush the D-cache to make sure all data actually has hit the memory. But there should be no need to invalidate the I-cache as we have never been fetching any instructions from this address range, so there cannot be any incorrect entries in cache.
Or am I missing something?
Quoted 4 lines
So, in effect everything has to be flushed to memory before you jump to the new location. There may be a small advantage because flushing from cache allows for bursting to the DDR where as bursting is not possible when d-cache is disabled. But I think this is not worth the trouble.
Well, all the data copy will also use cached writes, which are much faster. I think this will result in measurable time differences.
Best regards,
Wolfgang Denk
Signature · 6 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
The most exciting phrase to hear in science, the one that heralds new
discoveries, is not "Eureka!" (I found it!) but "That's funny ..."
-- Isaac AsimovPATCH v3 5/10 armv7: integrate cache maintenance support
Hi Wolfgang,
Quoted 15 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 8 lines · In message<[email protected]> you wrote:
Quoted 5 lines
Would it be possible to do this even _before_ relocation, so to speed up memory accesses during relocation? Of course, proper invalidates/ flushes will be needed before jumping to the RAM address, but I guess this would save a bit of boot times?
I intentionally kept it after relocation to avoid un-necessary complexities.
Yes, I can understand this. Do you plean to extend this to include relocation n a later step?
Quoted 6 lines
Quoted 4 lines
Relocation is a case of self-modifying code. In Harvard architectures like armv7 there will be coherency issues unless we flush the entire D-cache(range based operation may be equally or more expensive) and invalidate the entire I-cache.
I would not call this self-modifying code.
In ARM literature this kind of situations are also referred to as "self- modifying". Here is an excerpt from ARM manual gloassary:
Self-modifying code
Is code that writes one or more instructions to memory and then executes them.
Quoted 8 lines
Regarding the need to flush/invalidate caches when jumping to RAM:
yes, we have to flush the D-cache to make sure all data actually has hit the memory. But there should be no need to invalidate the I-cache as we have never been fetching any instructions from this address range, so there cannot be any incorrect entries in cache.Or am I missing something?
This should be largely ok, but not fool-proof for all processors. For processors such as Cortex-A9 that have speculative and out-of-order execution there is no guarantee that any given memory location is not cached at any given point of time as long as the cache is enabled. Here is an excerpt from the ARMv7 manual(section B2.2.2):
"If a memory location is marked as Cacheable there is no mechanism by which it can be guaranteed
not to be allocated to an enabled cache at any time. Any application must assume that any Cacheable
memory location can be allocated to any enabled cache at any time."
Quoted 7 lines
Quoted 5 lines
So, in effect everything has to be flushed to memory before you jump to the new location. There may be a small advantage because flushing from cache allows for bursting to the DDR where as bursting is not possible when d-cache is disabled. But I think this is not worth the trouble.
Well, all the data copy will also use cached writes, which are much
You mean, you will do a range-flush on only the .text section's area?
Quoted 1 line
faster. I think this will result in measurable time differences.
Relocation itself was not taking a huge amount of time in my measurement sometime back. It was about 16 ms for OMAP4.
best regards,
Aneesh
PATCH v3 5/10 armv7: integrate cache maintenance support
Dear Aneesh V,
Quoted 3 lines · In message <[email protected]> you wrote:
In ARM literature this kind of situations are also referred to as "self- modifying". Here is an excerpt from ARM manual gloassary:
I see. Thanks.
Quoted 3 lines
Quoted 1 line
Well, all the data copy will also use cached writes, which are much
You mean, you will do a range-flush on only the .text section's area?
That should indeed be sufficient.
Quoted 4 lines
Quoted 1 line
faster. I think this will result in measurable time differences.
Relocation itself was not taking a huge amount of time in my measurement sometime back. It was about 16 ms for OMAP4.
I was especially talking about the loading from external storage, not primarily relocation. This will even be mnore important if we had (much) bigger images - like when loading an OS kernel as second stage payload instead of U-Boot.
Best regards,
Wolfgang Denk
Signature · 8 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
I see that Microsoft's campaign to destroy all knowledge of any
operating environment but its own environment-of-the-year has
succeeded in creating a generation of users who don't understand the
concept of a shell...
-- L. Peter Deutsch in <[email protected]>PATCH v3 5/10 armv7: integrate cache maintenance support
Hi Wolfgang,
Quoted 17 lines · Wolfgang Denk
Dear Aneesh V,
Quoted 3 lines · In message<[email protected]> you wrote:
In ARM literature this kind of situations are also referred to as "self- modifying". Here is an excerpt from ARM manual gloassary:
I see. Thanks.
Quoted 3 lines
Quoted 1 line
Well, all the data copy will also use cached writes, which are much
You mean, you will do a range-flush on only the .text section's area?
That should indeed be sufficient.
Quoted 2 lines
Quoted 1 line
faster. I think this will result in measurable time differences.
Quoted 7 lines
Quoted 2 lines
Relocation itself was not taking a huge amount of time in my measurement sometime back. It was about 16 ms for OMAP4.
I was especially talking about the loading from external storage, not primarily relocation. This will even be mnore important if we had (much) bigger images - like when loading an OS kernel as second stage payload instead of U-Boot.
Are you talking about enabling D-cache in SPL? Technically, this should be possible as soon as DRAM is initialized(because internal RAMs typically do not have enough memory for page-tables(16KB) in addition to the SPL itself). But you might want to consider these.
1. We need to setup the page tables, invalidate the cache, enable it and before jumping to kernel flush and disable it again. Is that all worth just for speeding up the loading part? I think one must consider DMA for loading the image instead.
2. What happens if the payload is U-Boot? You still have the problem of flushing. Besides after reaching U-Boot do we setup MMU again or not? If we decide to retain the page-tables setup by SPL then U-Boot and SPL needs to align on the location of page-tables. This is difficult because U-Boot dynamically determines the memory for page-tables where as SPL doesn't have such intelligence. If we decide to do the MMU setup again, then it means setting up the page-tables twice in the bootloaders!
best regards,
Aneesh
PATCH v3 5/10 armv7: integrate cache maintenance support
Dear Aneesh V,
Quoted 7 lines · In message <[email protected]> you wrote:
Quoted 5 lines
I was especially talking about the loading from external storage, not primarily relocation. This will even be mnore important if we had (much) bigger images - like when loading an OS kernel as second stage payload instead of U-Boot.
Are you talking about enabling D-cache in SPL? Technically, this should
I + D cache, actually.
Quoted 3 lines
be possible as soon as DRAM is initialized(because internal RAMs typically do not have enough memory for page-tables(16KB) in addition to the SPL itself). But you might want to consider these.
Ah, I see. Well, you see, I have the big advantage over you that my imagination is not limited by the ugly details of the real ARM hardware in question here ;-)
Quoted 4 lines
1. We need to setup the page tables, invalidate the cache, enable it and before jumping to kernel flush and disable it again. Is that all worth just for speeding up the loading part? I think one must consider DMA for loading the image instead.
If it's available, for sure :-) But then, for example when loading from NAND flash (which is probably the most common use case these days), would DMA help?
Quoted 8 lines
2. What happens if the payload is U-Boot? You still have the problem of flushing. Besides after reaching U-Boot do we setup MMU again or not? If we decide to retain the page-tables setup by SPL then U-Boot and SPL needs to align on the location of page-tables. This is difficult because U-Boot dynamically determines the memory for page-tables where as SPL doesn't have such intelligence. If we decide to do the MMU setup again, then it means setting up the page-tables twice in the bootloaders!
I guess in the general case we will have to do this twice. And Linux will do it again. It would be nice if we canmake this optional, like we can avoid the copy operation of the relocation part when we know we load to the final address (all this keeping in mind the requirements for ultra short boot times).
Best regards,
Wolfgang Denk
Signature · 4 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Quantum Mechanics is God's version of "Trust me."
PATCH v3 6/10 arm: minor fixes for cache and mmu handling
In reply to Aneesh V1. make sure that page table setup is not done multiple times
2. flush_dcache_all() is more appropriate while disabling cache than a range flush on the entire memory(flush_cache())
Provide a default implementation for flush_dcache_all() for backward compatibility and to avoid build issues.
---
V2:
* Fixed signature of flush_cache in cache.c
--- arch/arm/lib/cache-cp15.c | 9 +++++++-- arch/arm/lib/cache.c | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-)
arch/arm/lib/cache-cp15.c +7 -2
@@ -92,13 +92,18 @@ static inline void mmu_setup(void)set_cr (reg |CR_M ); } +static int mmu_enabled (void ) +{ +return get_cr () &CR_M ; +} +/* cache_bit must be either CR_I or CR_C */ static void cache_enable (uint32_t cache_bit) {uint32_t reg;/* The data cache is not active unless the mmu is enabled too */ -if (cache_bit ==CR_C ) +if ((cache_bit ==CR_C ) && !mmu_enabled ())mmu_setup (); reg =get_cr ();/* get control reg. */ cp_delay ();
@@ -117,7 +122,7 @@ static void cache_disable(uint32_t cache_bit)return ;/* if disabling data cache, disable mmu too */ cache_bit |=CR_M ; -flush_cache (0 , ~0 ); +flush_dcache_all (); } reg =get_cr ();cp_delay ();
arch/arm/lib/cache.c +11 -0
@@ -42,3 +42,14 @@ void __flush_cache(unsigned long start, unsigned long size) }void flush_cache (unsigned long start,unsigned long size) __attribute__((weak,alias ("__flush_cache" ))); + +/* +* Default implementation: +* do a range flush for the entire range +*/ +void __flush_dcache_all (void ) +{ +flush_cache (0 , ~0 ); +} +void flush_dcache_all (void ) + __attribute__((weak,alias ("__flush_dcache_all" )));
Signature · 1 line
1.7.0.4
PATCH v3 7/10 armv7: add PL310 support to u-boot
In reply to Aneesh VPL310 is the L2$ controller from ARM used in many SoCs including the Cortex-A9 based OMAP4430
Add support for some of the key PL310 operations
- Invalidate all
- Invalidate range
- Flush(clean & invalidate) all
- Flush range
---
V2:
* More descriptive commit message
* Changes for function pointer to weakly linked change
* C struct for register accesses
--- README | 6 ++ arch/arm/include/asm/pl310.h | 74 +++++++++++++++++++++++++++ arch/arm/lib/Makefile | 1 + arch/arm/lib/cache-pl310.c | 116 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/pl310.h create mode 100644 arch/arm/lib/cache-pl310.c
README +6 -0
@@ -460,6 +460,12 @@ The following options need to be configured: CONFIG_SYS_NO_DCACHE - Do not enable data cache in U-Boot CONFIG_SYS_NO_L2CACHE- Do not enable L2 cache in U-Boot +- Cache Configuration for ARM: + CONFIG_SYS_L2_PL310 - Enable support for ARM PL310 L2 cache + controller + CONFIG_SYS_PL310_BASE - Physical base address of PL310 + controller register space + - Serial Ports: CONFIG_PL010_SERIAL
arch/arm/include/asm/pl310.h new file +74 -0
74 lines not on this page · raw message
arch/arm/lib/Makefile +1 -0
@@ -42,6 +42,7 @@ COBJS-y += cache.o ifndef CONFIG_SYS_NO_CP15_CACHE COBJS-y += cache-cp15.o endif +COBJS-$(CONFIG_SYS_L2_PL310) += cache-pl310.o COBJS-y += interrupts.o COBJS-y += reset.o SOBJS-$(CONFIG_USE_ARCH_MEMSET) += memset.o
arch/arm/lib/cache-pl310.c new file +116 -0
116 lines not on this page · raw message
Signature · 1 line
1.7.0.4
PATCH v3 8/10 armv7: adapt omap4 to the new cache maintenance framework
In reply to Aneesh Vadapt omap4 to the new layered cache maintenance framework
---
V2:
* Changes for the function pointer to weakly linked change
--- arch/arm/cpu/armv7/omap4/lowlevel_init.S | 18 ++++++++++++++++++ arch/arm/include/asm/arch-omap4/sys_proto.h | 1 - include/configs/omap4_panda.h | 8 +++++--- include/configs/omap4_sdp4430.h | 8 +++++--- 4 files changed, 28 insertions(+), 7 deletions(-)
arch/arm/cpu/armv7/omap4/lowlevel_init.S +18 -0
@@ -45,3 +45,21 @@ lowlevel_init: */ bl s_init pop {ip, pc} + +set_pl310_ctrl_reg: + PUSH {r4-r11, lr} @ save registers - ROM code may pollute + @ our registers + LDR r12, =0x102 @ Set PL310 control register - value in R0 + .word 0xe1600070 @ SMC #0 - hand assembled because -march=armv5 + @ call ROM Code API to set control register + POP {r4-r11, pc} + +.globl v7_outer_cache_enable +v7_outer_cache_enable: + MOV r0, #1 + B set_pl310_ctrl_reg + +.globl v7_outer_cache_disable +v7_outer_cache_disable: + MOV r0, #0 + B set_pl310_ctrl_reg
arch/arm/include/asm/arch-omap4/sys_proto.h +0 -1
@@ -31,7 +31,6 @@ struct omap_sysinfo {void gpmc_init (void );void watchdog_init (void );u32 get_device_type (void ); -void invalidate_dcache (u32 );void set_muxconf_regs (void );void sr32 (void *,u32 ,u32 ,u32 );u32 wait_on_value (u32 ,u32 ,void *,u32 );
include/configs/omap4_panda.h +5 -3
@@ -45,9 +45,6 @@#define CONFIG_DISPLAY_CPUINFO 1#define CONFIG_DISPLAY_BOARDINFO 1 -/* Keep L2 Cache Disabled */ -#define CONFIG_SYS_NO_L2CACHE 1 -/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */ #define V_SCLK V_OSCK
@@ -236,4 +233,9 @@ CONFIG_SYS_INIT_RAM_SIZE - \ GENERATED_GBL_DATA_SIZE) +#ifndef CONFIG_SYS_NO_L2CACHE +#define CONFIG_SYS_L2_PL310 1 +#define CONFIG_SYS_PL310_BASE 0x48242000 +#endif +#endif /* __CONFIG_H */
include/configs/omap4_sdp4430.h +5 -3
@@ -46,9 +46,6 @@#define CONFIG_DISPLAY_CPUINFO 1#define CONFIG_DISPLAY_BOARDINFO 1 -/* Keep L2 Cache Disabled */ -#define CONFIG_SYS_NO_L2CACHE 1 -/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */ #define V_SCLK V_OSCK
@@ -242,4 +239,9 @@ CONFIG_SYS_INIT_RAM_SIZE - \ GENERATED_GBL_DATA_SIZE) +#ifndef CONFIG_SYS_NO_L2CACHE +#define CONFIG_SYS_L2_PL310 1 +#define CONFIG_SYS_PL310_BASE 0x48242000 +#endif +#endif /* __CONFIG_H */
Signature · 1 line
1.7.0.4
PATCH v3 8/10 armv7: adapt omap4 to the new cache maintenance framework
Dear Aneesh V,
Quoted 1 line · In message <[email protected]> you wrote:
adapt omap4 to the new layered cache maintenance framework
NAK because of the CONFIG_SYS_NO_*CACHE names.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Schshschshchsch. -- The Gorn, "Arena", stardate 3046.2
PATCH v3 9/10 armv7: adapt omap3 to the new cache maintenance framework
In reply to Aneesh Vadapt omap3 to the new layered cache maintenance framework
---
V2:
* Changes for the function pointer to weakly linked change
--- arch/arm/cpu/armv7/omap3/Makefile | 1 - arch/arm/cpu/armv7/omap3/board.c | 138 ++++++++++++-- arch/arm/cpu/armv7/omap3/cache.S | 263 --------------------------- arch/arm/cpu/armv7/omap3/lowlevel_init.S | 32 ++++ arch/arm/include/asm/arch-omap3/omap3.h | 20 ++ arch/arm/include/asm/arch-omap3/sys_proto.h | 10 +- 6 files changed, 178 insertions(+), 286 deletions(-) delete mode 100644 arch/arm/cpu/armv7/omap3/cache.S
arch/arm/cpu/armv7/omap3/Makefile +0 -1
@@ -26,7 +26,6 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).o SOBJS := lowlevel_init.o -SOBJS += cache.o COBJS += board.o COBJS += clock.o
arch/arm/cpu/armv7/omap3/board.c +119 -19
157 lines not on this page · raw message
arch/arm/cpu/armv7/omap3/cache.S deleted +0 -263
263 lines not on this page · raw message
arch/arm/cpu/armv7/omap3/lowlevel_init.S +32 -0
@@ -35,6 +35,38 @@ _TEXT_BASE: .word CONFIG_SYS_TEXT_BASE /* sdram load addr from config.mk */ +.global omap3_gp_romcode_call +omap3_gp_romcode_call: + PUSH {r4-r12, lr} @ Save all registers from ROM code! + MOV r12, r0 @ Copy the Service ID in R12 + MOV r0, r1 @ Copy parameter to R0 + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c10, 5 @ DMB + .word 0xe1600070 @ SMC #0 to enter monitor - hand assembled + @ because we use -march=armv5 + POP {r4-r12, pc} + +/* + * Funtion for making PPA HAL API calls in secure devices + * Input: + * R0 - Service ID + * R1 - paramer list + */ +.global do_omap3_emu_romcode_call +do_omap3_emu_romcode_call: + PUSH {r4-r12, lr} @ Save all registers from ROM code! + MOV r12, r0 @ Copy the Secure Service ID in R12 + MOV r3, r1 @ Copy the pointer to va_list in R3 + MOV r1, #0 @ Process ID - 0 + MOV r2, #OMAP3_EMU_HAL_START_HAL_CRITICAL @ Copy the pointer + @ to va_list in R3 + MOV r6, #0xFF @ Indicate new Task call + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c10, 5 @ DMB + .word 0xe1600071 @ SMC #1 to call PPA service - hand assembled + @ because we use -march=armv5 + POP {r4-r12, pc} + #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_NAND_BOOT) /************************************************************************** * cpy_clk_code: relocates clock code into SRAM where its safer to execute
arch/arm/include/asm/arch-omap3/omap3.h +20 -0
@@ -159,8 +159,14 @@ struct gpio {#define SRAM_VECT_CODE (SRAM_OFFSET0 | SRAM_OFFSET1 | \ SRAM_OFFSET2) +#define OMAP3_PUBLIC_SRAM_BASE 0x40208000/* Works for GP & EMU */ +#define OMAP3_PUBLIC_SRAM_END 0x40210000 +#define LOW_LEVEL_SRAM_STACK 0x4020FFFC +/* scratch area - accessible on both EMU and GP */ +#define OMAP3_PUBLIC_SRAM_SCRATCH_AREA OMAP3_PUBLIC_SRAM_BASE +#define DEBUG_LED1 149/* gpio */ #define DEBUG_LED2 150/* gpio */
@@ -227,4 +233,18 @@ struct gpio {#define OMAP3730 0x0c00 +/* +* ROM code API related flags +*/ +#define OMAP3_GP_ROMCODE_API_L2_INVAL 1 +#define OMAP3_GP_ROMCODE_API_WRITE_ACR 3 + +/* +* EMU device PPA HAL related flags +*/ +#define OMAP3_EMU_HAL_API_L2_INVAL 40 +#define OMAP3_EMU_HAL_API_WRITE_ACR 42 + +#define OMAP3_EMU_HAL_START_HAL_CRITICAL 4 +#endif
arch/arm/include/asm/arch-omap3/sys_proto.h +7 -3
@@ -27,6 +27,11 @@ typedef struct {char *nand_string; } omap3_sysinfo; +struct emu_hal_params { +u32 num_params; +u32 param1; +}; +void prcm_init (void );void per_clocks_enable (void );
@@ -53,9 +58,7 @@ u32 is_running_in_sdram(void);u32 is_running_in_sram (void );u32 is_running_in_flash (void );u32 get_device_type (void ); -void l2cache_enable (void );void secureworld_exit (void ); -void setup_auxcr (void );void try_unlock_memory (void );u32 get_boot_type (void );void invalidate_dcache (u32 );
@@ -66,5 +69,6 @@ void make_cs1_contiguous(void);void omap_nand_switch_ecc (int );void power_init_r (void );void dieid_num_r (void ); - +void do_omap3_emu_romcode_call (u32 service_id,u32 parameters); +void omap3_gp_romcode_call (u32 service_id,u32 parameter);#endif
Signature · 1 line
1.7.0.4
PATCH v3 9/10 armv7: adapt omap3 to the new cache maintenance framework
Dear Aneesh V,
Quoted 6 lines · In message <[email protected]> you wrote:
adapt omap3 to the new layered cache maintenance framework
Signed-off-by Aneesh V <[email protected]>---
V2:
* Changes for the function pointer to weakly linked change
Quoted 9 lines
--- arch/arm/cpu/armv7/omap3/Makefile | 1 - arch/arm/cpu/armv7/omap3/board.c | 138 ++++++++++++-- arch/arm/cpu/armv7/omap3/cache.S | 263 --------------------------- arch/arm/cpu/armv7/omap3/lowlevel_init.S | 32 ++++ arch/arm/include/asm/arch-omap3/omap3.h | 20 ++ arch/arm/include/asm/arch-omap3/sys_proto.h | 10 +- 6 files changed, 178 insertions(+), 286 deletions(-) delete mode 100644 arch/arm/cpu/armv7/omap3/cache.S
NAK because of the CONFIG_SYS_NO_*CACHE names.
Best regards,
Wolfgang Denk
Signature · 7 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de I came home the other night and tried to open the door with my car keys...and the building started up. So I took it out for a drive. A cop pulled me over for speeding. He asked me where I live... "Right here". - Steven Wright
PATCH v3 10/10 armv7: adapt s5pc1xx to the new cache maintenance framework
In reply to Aneesh Vadapt s5pc1xx to the new layered cache maintenance framework
---
V2:
* Changes for the function pointer to weakly linked change
--- arch/arm/cpu/armv7/s5pc1xx/cache.S | 88 ++----------------------- arch/arm/include/asm/arch-s5pc1xx/sys_proto.h | 3 - 2 files changed, 7 insertions(+), 84 deletions(-)
arch/arm/cpu/armv7/s5pc1xx/cache.S +7 -81
@@ -23,98 +23,24 @@ * MA 02111-1307 USA */ -#include <asm/arch/cpu.h> - .align 5 -.global invalidate_dcache -.global l2_cache_enable -.global l2_cache_disable - -/* - * invalidate_dcache() - * Invalidate the whole D-cache. - * - * Corrupted registers: r0-r5, r7, r9-r11 - */ -invalidate_dcache: - stmfd r13!, {r0 - r5, r7, r9 - r12, r14} - - cmp r0, #0xC100 @ check if the cpu is s5pc100 - beq finished_inval @ s5pc100 doesn't need this - @ routine - mrc p15, 1, r0, c0, c0, 1 @ read clidr - ands r3, r0, #0x7000000 @ extract loc from clidr - mov r3, r3, lsr #23 @ left align loc bit field - beq finished_inval @ if loc is 0, then no need to - @ clean - mov r10, #0 @ start clean at cache level 0 -inval_loop1: - add r2, r10, r10, lsr #1 @ work out 3x current cache - @ level - mov r1, r0, lsr r2 @ extract cache type bits from - @ clidr - and r1, r1, #7 @ mask of the bits for current - @ cache only - cmp r1, #2 @ see what cache we have at - @ this level - blt skip_inval @ skip if no cache, or just - @ i-cache - mcr p15, 2, r10, c0, c0, 0 @ select current cache level - @ in cssr - mov r2, #0 @ operand for mcr SBZ - mcr p15, 0, r2, c7, c5, 4 @ flush prefetch buffer to - @ sych the new cssr&csidr, - @ with armv7 this is 'isb', - @ but we compile with armv5 - mrc p15, 1, r1, c0, c0, 0 @ read the new csidr - and r2, r1, #7 @ extract the length of the - @ cache lines - add r2, r2, #4 @ add 4 (line length offset) - ldr r4, =0x3ff - ands r4, r4, r1, lsr #3 @ find maximum number on the - @ way size - clz r5, r4 @ find bit position of way - @ size increment - ldr r7, =0x7fff - ands r7, r7, r1, lsr #13 @ extract max number of the - @ index size -inval_loop2: - mov r9, r4 @ create working copy of max - @ way size -inval_loop3: - orr r11, r10, r9, lsl r5 @ factor way and cache number - @ into r11 - orr r11, r11, r7, lsl r2 @ factor index number into r11 - mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way - subs r9, r9, #1 @ decrement the way - bge inval_loop3 - subs r7, r7, #1 @ decrement the index - bge inval_loop2 -skip_inval: - add r10, r10, #2 @ increment cache number - cmp r3, r10 - bgt inval_loop1 -finished_inval: - mov r10, #0 @ swith back to cache level 0 - mcr p15, 2, r10, c0, c0, 0 @ select current cache level - @ in cssr - mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, - @ with armv7 this is 'isb', - @ but we compile with armv5 +#if !defined(CONFIG_SYS_NO_DCACHE) && !defined(CONFIG_SYS_NO_L2CACHE) - ldmfd r13!, {r0 - r5, r7, r9 - r12, pc} - -l2_cache_enable: +.global v7_outer_cache_enable +v7_outer_cache_enable: push {r0, r1, r2, lr} mrc 15, 0, r3, cr1, cr0, 1 orr r3, r3, #2 mcr 15, 0, r3, cr1, cr0, 1 pop {r1, r2, r3, pc} -l2_cache_disable: +.global v7_outer_cache_disable +v7_outer_cache_disable: push {r0, r1, r2, lr} mrc 15, 0, r3, cr1, cr0, 1 bic r3, r3, #2 mcr 15, 0, r3, cr1, cr0, 1 pop {r1, r2, r3, pc} + +#endif
arch/arm/include/asm/arch-s5pc1xx/sys_proto.h +0 -3
@@ -25,8 +25,5 @@#define _SYS_PROTO_H_u32 get_device_type (void ); -void invalidate_dcache (u32 ); -void l2_cache_disable (void ); -void l2_cache_enable (void );#endif
Signature · 1 line
1.7.0.4
PATCH v3 10/10 armv7: adapt s5pc1xx to the new cache maintenance framework
Dear Aneesh V,
Quoted 10 lines · In message <[email protected]> you wrote:
adapt s5pc1xx to the new layered cache maintenance framework
Signed-off-by Aneesh V <[email protected]>---
V2:
* Changes for the function pointer to weakly linked change--- arch/arm/cpu/armv7/s5pc1xx/cache.S | 88 ++----------------------- arch/arm/include/asm/arch-s5pc1xx/sys_proto.h | 3 - 2 files changed, 7 insertions(+), 84 deletions(-)
NAK because of the CONFIG_SYS_NO_*CACHE names.
Best regards,
Wolfgang Denk
Signature · 6 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de This cultural mystique surrounding the biological function -- you realize humans are overly preoccupied with the subject. -- Kelinda the Kelvan, "By Any Other Name", stardate 4658.9
v4 cover armv7: cache maintenance operations
In reply to Aneesh VWith D-cache and MMU enabled for ARM in u-boot it becomes imperative to support a minimal set of cache maintenance operations and necessary initializations before enabling MMU.
This series of patches attempt to do the following for armv7:
* Necessary initialization sequence before enabling MMU that includes invalidation of TLB, data caches, branch predictor array etc.
* Framework for supporting SOC specific outer caches in a generic manner (using a structure of function pointers - inspired by the Linux implementation)
* Generic armv7 cache maintenance operations for caches known to the CPU
* Support for ARM PL310 L2 cache controller used in OMAP4
* Cleanup of the cleanup_before_linux() function
* Adapting all armv7 SOCs to use the new framework and removing duplicated code
Testing:
* Extensive testing on OMAP4430SDP and OMAP3430SDP by creating coherency issues and solving them using the maintenance routines
- Eg: memfill a region of memory with a known pattern
- Invalidate the region
- Read back and compare the region with the original pattern
- If match fails it means that invalidate is successful
- Now add a flush call just before the invalidate
- If match succeeds it means that flush was successful
- Outer caches were tested with experiments involving making the function pointers NULL
* Kernel booting on OMAP4430SDP and OMAP3430SDP
Note: v2 has been tested only on OMAP4430SDP
V2:
* Pointer based callback mechanism for outer cache operations changed to a weakly linked functions.
* Change -march=armv7-a back to armv5
* Moved utility macros out of armv7.h
* Added documentation for new CONFIG options.
* Changed implementation of log2n to not use CLZ instruction as armv4 doesn't support this instruction and newly added Tegra2 uses -march=armv4
* Blank line after local variable declarations - fixed globally
* Explicitly added an empty flush_cache() under
#ifdef CONFIG_SYS_NO_DCACHE
* Removed the print inside the weakly linked stub function - __arm_init_before_mmu
* Fixed signature of flush_cache in cache.c
* More descriptive commit message for the PL310 support patch
* C struct for PL310 register accesses
* Fixed white space issues
V3:
* Rebased to latest HEAD of master
* Added comments on changes done in V2 in individual patch headers. This was missing in V2
V4:
* Removed bit field manipulation macros
* Renamed CONFIG_SYS_NO_*CACHE flags to CONFIG_SYS_*CACHE_OFF globally
Aneesh V (9):
arm: make default implementation of cache_flush() weakly linked
armv7: cache maintenance operations for armv7
armv7: rename cache related CONFIG flags
armv7: integrate cache maintenance support
arm: minor fixes for cache and mmu handling
armv7: add PL310 support to u-boot
armv7: adapt omap4 to the new cache maintenance framework
armv7: adapt omap3 to the new cache maintenance framework
armv7: adapt s5pc1xx to the new cache maintenance framework
README | 11 +
arch/arm/cpu/arm1136/start.S | 4 +-
arch/arm/cpu/armv7/Makefile | 2 +-
arch/arm/cpu/armv7/cache_v7.c | 394 ++++++++++++++++++++
arch/arm/cpu/armv7/cpu.c | 50 +--
arch/arm/cpu/armv7/omap3/Makefile | 1 -
arch/arm/cpu/armv7/omap3/board.c | 136 ++++++-
arch/arm/cpu/armv7/omap3/cache.S | 263 -------------
arch/arm/cpu/armv7/omap3/lowlevel_init.S | 32 ++
arch/arm/cpu/armv7/omap4/board.c | 12 +
arch/arm/cpu/armv7/omap4/lowlevel_init.S | 9 +
arch/arm/cpu/armv7/s5pc1xx/cache.S | 88 +----
arch/arm/cpu/armv7/start.S | 18 +-
arch/arm/include/asm/arch-omap3/omap3.h | 20 +
arch/arm/include/asm/arch-omap3/sys_proto.h | 10 +-
arch/arm/include/asm/arch-omap4/sys_proto.h | 2 +-
arch/arm/include/asm/arch-s5pc1xx/sys_proto.h | 3 -
arch/arm/include/asm/armv7.h | 67 ++++
arch/arm/include/asm/global_data.h | 2 +-
arch/arm/include/asm/pl310.h | 73 ++++
.../omap4/lowlevel_init.S => include/asm/utils.h} | 51 ++-
arch/arm/lib/Makefile | 3 +-
arch/arm/lib/board.c | 8 +-
arch/arm/lib/cache-cp15.c | 22 +-
arch/arm/lib/cache-pl310.c | 115 ++++++
arch/arm/lib/cache.c | 20 +-
board/armltd/integrator/split_by_variant.sh | 8 +-
common/cmd_bdinfo.c | 2 +-
include/common.h | 5 +-
include/configs/B2.h | 3 +-
include/configs/assabet.h | 2 +-
include/configs/ca9x4_ct_vxp.h | 2 +-
include/configs/cerf250.h | 2 +-
include/configs/cradle.h | 2 +-
include/configs/csb226.h | 2 +-
include/configs/dnp1110.h | 2 +-
include/configs/efikamx.h | 2 +-
include/configs/evb4510.h | 3 +-
include/configs/gcplus.h | 2 +-
include/configs/innokom.h | 2 +-
include/configs/jornada.h | 2 +-
include/configs/lart.h | 2 +-
include/configs/lubbock.h | 2 +-
include/configs/mx51evk.h | 2 +-
include/configs/mx53evk.h | 2 +-
include/configs/omap4_panda.h | 8 +-
include/configs/omap4_sdp4430.h | 8 +-
include/configs/pleb2.h | 2 +-
include/configs/pxa255_idp.h | 2 +-
include/configs/s5pc210_universal.h | 2 +-
include/configs/shannon.h | 2 +-
include/configs/tegra2-common.h | 2 +-
include/configs/trizepsiv.h | 2 +-
include/configs/vision2.h | 2 +-
include/configs/xaeniax.h | 2 +-
include/configs/xm250.h | 2 +-
include/configs/zylonite.h | 2 +-
57 files changed, 1022 insertions(+), 479 deletions(-)
create mode 100644 arch/arm/cpu/armv7/cache_v7.c
delete mode 100644 arch/arm/cpu/armv7/omap3/cache.S
create mode 100644 arch/arm/include/asm/armv7.h
create mode 100644 arch/arm/include/asm/pl310.h
copy arch/arm/{cpu/armv7/omap4/lowlevel_init.S => include/asm/utils.h} (66%)
create mode 100644 arch/arm/lib/cache-pl310.cv4 cover armv7: cache maintenance operations
Hi All,
Le 17/06/2011 11:30, Aneesh V a ?crit :
Quoted 4 lines
With D-cache and MMU enabled for ARM in u-boot it becomes imperative to support a minimal set of cache maintenance operations and necessary initializations before enabling MMU.
Quoted 11 lines
This series of patches attempt to do the following for armv7:
* Necessary initialization sequence before enabling MMU that includes invalidation of TLB, data caches, branch predictor array etc.
* Framework for supporting SOC specific outer caches in a generic manner (using a structure of function pointers - inspired by the Linux implementation)
* Generic armv7 cache maintenance operations for caches known to the CPU
* Support for ARM PL310 L2 cache controller used in OMAP4
* Cleanup of thecleanup_before_linux()function
* Adapting all armv7 SOCs to use the new framework and removing duplicated code
Sandeep, Minkyu: is the patch series OK with you? If so I'll pull it all in ARM and issue a last pull request.
Amicalement,
Signature · 1 line
Albert.
V
v4 cover armv7: cache maintenance operations
Quoted 20 lines · Albert ARIBAUD
Hi All,
Le 17/06/2011 11:30, Aneesh V a ?crit :
Quoted 5 lines
With D-cache and MMU enabled for ARM in u-boot it becomes imperative to support a minimal set of cache maintenance operations and necessary initializations before enabling MMU.
Quoted 11 lines
This series of patches attempt to do the following for armv7:
* Necessary initialization sequence before enabling MMU that includes ? invalidation of TLB, data caches, branch predictor array etc.
* Framework for supporting SOC specific outer caches in a generic manner ? (using a structure of function pointers - inspired by the Linux ? implementation)
* Generic armv7 cache maintenance operations for caches known to the CPU
* Support for ARM PL310 L2 cache controller used in OMAP4
* Cleanup of thecleanup_before_linux()function
* Adapting all armv7 SOCs to use the new framework and removing ? duplicated code
Quoted 2 lines
Sandeep, Minkyu: is the patch series OK with you? If so I'll pull it all in ARM and issue a last pull request.
Sandeep, Minkyu,
Would you please let me know if you have any concerns about this series. If not, it will be good to see this going upstream this release. The necessary initializations before enabling the cache are missing today. Also, the absence of proper invalidate and flush functions will be missed by any driver that uses DMA.
best regards,
Aneesh
Paulraj
v4 cover armv7: cache maintenance operations
In reply to Albert ARIBAUDQuoted 22 lines
Hi All,
Le 17/06/2011 11:30, Aneesh V a ?crit :
Quoted 4 lines
With D-cache and MMU enabled for ARM in u-boot it becomes imperative to support a minimal set of cache maintenance operations and necessary initializations before enabling MMU.
Quoted 11 lines
This series of patches attempt to do the following for armv7:
* Necessary initialization sequence before enabling MMU that includes invalidation of TLB, data caches, branch predictor array etc.
* Framework for supporting SOC specific outer caches in a generic manner (using a structure of function pointers - inspired by the Linux implementation)
* Generic armv7 cache maintenance operations for caches known to the CPU
* Support for ARM PL310 L2 cache controller used in OMAP4
* Cleanup of thecleanup_before_linux()function
* Adapting all armv7 SOCs to use the new framework and removing duplicated code
Quoted 6 lines
Sandeep, Minkyu: is the patch series OK with you? If so I'll pull it all in ARM and issue a last pull request.
Amicalement,
--
Albert.
I am fine with it.
--Sandeep
v4 cover armv7: cache maintenance operations
Quoted 25 lines · Sandeep
Quoted 25 lines
Hi All,
Le 17/06/2011 11:30, Aneesh V a ?crit :
Quoted 4 lines
With D-cache and MMU enabled for ARM in u-boot it becomes imperative to support a minimal set of cache maintenance operations and necessary initializations before enabling MMU.
Quoted 11 lines
This series of patches attempt to do the following for armv7:
* Necessary initialization sequence before enabling MMU that includes ? ?invalidation of TLB, data caches, branch predictor array etc.
* Framework for supporting SOC specific outer caches in a generic manner ? ?(using a structure of function pointers - inspired by the Linux ? ?implementation)
* Generic armv7 cache maintenance operations for caches known to the CPU
* Support for ARM PL310 L2 cache controller used in OMAP4
* Cleanup of thecleanup_before_linux()function
* Adapting all armv7 SOCs to use the new framework and removing ? ?duplicated codeSandeep, Minkyu: is the patch series OK with you? If so I'll pull it all in ARM and issue a last pull request.
Quoted 8 lines
Quoted 3 lines
Amicalement,
--
Albert.I am fine with it.
Acked-by Sandeep Paulraj <[email protected]
Thanks
Minkyu Kang
Signature · 2 lines
from. prom. www.promsoft.net
v4 cover armv7: cache maintenance operations
In reply to Aneesh VLe 17/06/2011 11:30, Aneesh V a ?crit :
Quoted 127 lines
With D-cache and MMU enabled for ARM in u-boot it becomes imperative to support a minimal set of cache maintenance operations and necessary initializations before enabling MMU.
This series of patches attempt to do the following for armv7:
* Necessary initialization sequence before enabling MMU that includes invalidation of TLB, data caches, branch predictor array etc.
* Framework for supporting SOC specific outer caches in a generic manner (using a structure of function pointers - inspired by the Linux implementation)
* Generic armv7 cache maintenance operations for caches known to the CPU
* Support for ARM PL310 L2 cache controller used in OMAP4
* Cleanup of thecleanup_before_linux()function
* Adapting all armv7 SOCs to use the new framework and removing duplicated codeTesting:
* Extensive testing on OMAP4430SDP and OMAP3430SDP by creating coherency issues and solving them using the maintenance routines
- Eg: memfill a region of memory with a known pattern
- Invalidate the region
- Read back and compare the region with the original pattern
- If match fails it means that invalidate is successful
- Now add a flush call just before the invalidate
- If match succeeds it means that flush was successful
- Outer caches were tested with experiments involving making the function pointers NULL
* Kernel booting on OMAP4430SDP and OMAP3430SDP
Note: v2 has been tested only on OMAP4430SDPV2:
* Pointer based callback mechanism for outer cache operations changed to a weakly linked functions.
* Change -march=armv7-a back to armv5
* Moved utility macros out ofarmv7.h
* Added documentation for new CONFIG options.
* Changed implementation of log2n to not use CLZ instruction as armv4 doesn't support this instruction and newly added Tegra2 uses -march=armv4
* Blank line after local variable declarations - fixed globally
* Explicitly added an emptyflush_cache()under
#ifdefCONFIG_SYS_NO_DCACHE
* Removed the print inside the weakly linked stub function -__arm_init_before_mmu
* Fixed signature offlush_cacheincache.c
* More descriptive commit message for the PL310 support patch
* C struct for PL310 register accesses
* Fixed white space issuesV3:
* Rebased to latest HEAD of master
* Added comments on changes done in V2 in individual patch headers. This was missing in V2V4:
* Removed bit field manipulation macros
* Renamed CONFIG_SYS_NO_*CACHE flags to CONFIG_SYS_*CACHE_OFF globallyAneesh V (9):
arm: make default implementation ofcache_flush()weakly linked
armv7: cache maintenance operations for armv7
armv7: rename cache related CONFIG flags
armv7: integrate cache maintenance support
arm: minor fixes for cache and mmu handling
armv7: add PL310 support to u-boot
armv7: adapt omap4 to the new cache maintenance framework
armv7: adapt omap3 to the new cache maintenance framework
armv7: adapt s5pc1xx to the new cache maintenance frameworkREADME | 11 + arch/arm/cpu/arm1136/start.S | 4 +- arch/arm/cpu/armv7/Makefile | 2 +- arch/arm/cpu/armv7/cache_v7.c | 394 ++++++++++++++++++++ arch/arm/cpu/armv7/cpu.c | 50 +-- arch/arm/cpu/armv7/omap3/Makefile | 1 - arch/arm/cpu/armv7/omap3/board.c | 136 ++++++- arch/arm/cpu/armv7/omap3/cache.S | 263 ------------- arch/arm/cpu/armv7/omap3/lowlevel_init.S | 32 ++ arch/arm/cpu/armv7/omap4/board.c | 12 + arch/arm/cpu/armv7/omap4/lowlevel_init.S | 9 + arch/arm/cpu/armv7/s5pc1xx/cache.S | 88 +---- arch/arm/cpu/armv7/start.S | 18 +- arch/arm/include/asm/arch-omap3/omap3.h | 20 + arch/arm/include/asm/arch-omap3/sys_proto.h | 10 +- arch/arm/include/asm/arch-omap4/sys_proto.h | 2 +- arch/arm/include/asm/arch-s5pc1xx/sys_proto.h | 3 - arch/arm/include/asm/armv7.h | 67 ++++ arch/arm/include/asm/global_data.h | 2 +- arch/arm/include/asm/pl310.h | 73 ++++ .../omap4/lowlevel_init.S => include/asm/utils.h} | 51 ++- arch/arm/lib/Makefile | 3 +- arch/arm/lib/board.c | 8 +- arch/arm/lib/cache-cp15.c | 22 +- arch/arm/lib/cache-pl310.c | 115 ++++++ arch/arm/lib/cache.c | 20 +- board/armltd/integrator/split_by_variant.sh | 8 +- common/cmd_bdinfo.c | 2 +- include/common.h | 5 +- include/configs/B2.h | 3 +- include/configs/assabet.h | 2 +- include/configs/ca9x4_ct_vxp.h | 2 +- include/configs/cerf250.h | 2 +- include/configs/cradle.h | 2 +- include/configs/csb226.h | 2 +- include/configs/dnp1110.h | 2 +- include/configs/efikamx.h | 2 +- include/configs/evb4510.h | 3 +- include/configs/gcplus.h | 2 +- include/configs/innokom.h | 2 +- include/configs/jornada.h | 2 +- include/configs/lart.h | 2 +- include/configs/lubbock.h | 2 +- include/configs/mx51evk.h | 2 +- include/configs/mx53evk.h | 2 +- include/configs/omap4_panda.h | 8 +- include/configs/omap4_sdp4430.h | 8 +- include/configs/pleb2.h | 2 +- include/configs/pxa255_idp.h | 2 +- include/configs/s5pc210_universal.h | 2 +- include/configs/shannon.h | 2 +- include/configs/tegra2-common.h | 2 +- include/configs/trizepsiv.h | 2 +- include/configs/vision2.h | 2 +- include/configs/xaeniax.h | 2 +- include/configs/xm250.h | 2 +- include/configs/zylonite.h | 2 +- 57 files changed, 1022 insertions(+), 479 deletions(-)
Quoted 6 lines
create mode 100644
arch/arm/cpu/armv7/cache_v7.c
delete mode 100644arch/arm/cpu/armv7/omap3/cache.S
create mode 100644arch/arm/include/asm/armv7.h
create mode 100644arch/arm/include/asm/pl310.h
copyarch/arm/{cpu/armv7/omap4/lowlevel_init.S=>include/asm/utils.h} (66%) create mode 100644arch/arm/lib/cache-pl310.c
Applied to u-boot-arm/master, thanks.
Amicalement,
Signature · 1 line
Albert.
PATCH v4 1/9 arm: make default implementation of cache_flush() weakly linked
In reply to Aneesh Vmake default implementation of cache_flush() weakly linked so that sub-architectures can override it
--- arch/arm/lib/cache.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/arm/lib/cache.c +3 -1
@@ -25,7 +25,7 @@#include <common.h> -void flush_cache (unsigned long dummy1,unsigned long dummy2) +void __flush_cache (unsigned long start,unsigned long size) {#if defined(CONFIG_OMAP2420 ) || defined(CONFIG_ARM1136 )void arm1136_cache_flush (void );
@@ -45,3 +45,5 @@ void flush_cache (unsigned long dummy1, unsigned long dummy2)#endif return ; } +void flush_cache (unsigned long start,unsigned long size) + __attribute__((weak,alias ("__flush_cache" )));
Signature · 1 line
1.7.0.4
PATCH v4 2/9 armv7: cache maintenance operations for armv7
In reply to Aneesh V- Add a framework for layered cache maintenance
- separate out SOC specific outer cache maintenance from maintenance of caches known to CPU
- Add generic ARMv7 cache maintenance operations that affect all caches known to ARMv7 CPUs. For instance in Cortex-A8 these opertions will affect both L1 and L2 caches. In Cortex-A9 these will affect only L1 cache
- D-cache operations supported:
- Invalidate entire D-cache
- Invalidate D-cache range
- Flush(clean & invalidate) entire D-cache
- Flush D-cache range
- I-cache operations supported:
- Invalidate entire I-cache
- Add maintenance functions for TLB, branch predictor array etc.
- Enable -march=armv7-a so that armv7 assembly instructions can be used
---
V2:
* Blank line after local variable declarations - fixed globally
* Change from pointers to weakly linked functions for outer cache operations
* Explicitly added a copy of flush_cache() under #ifdef CONFIG_SYS_NO_DCACHE
* Change -march=armv7-a back to armv5
* Update documentation with cache related CONFIG options
---
V4:
* Squashed utility macros patch with this patch and removed the bit field operation functions
* Removed the usage of get_bit_field()
* Replaced CONFIG_SYS_NO_*CACHE flags with CONFIG_SYS_*CACHE_OFF
--- README | 5 + arch/arm/cpu/armv7/Makefile | 2 +- arch/arm/cpu/armv7/cache_v7.c | 394 +++++++++++++++++++++++++++++++++++++++++ arch/arm/include/asm/armv7.h | 67 +++++++ arch/arm/include/asm/utils.h | 56 ++++++ include/common.h | 5 +- 6 files changed, 527 insertions(+), 2 deletions(-) create mode 100644 arch/arm/cpu/armv7/cache_v7.c create mode 100644 arch/arm/include/asm/armv7.h create mode 100644 arch/arm/include/asm/utils.h
README +5 -0
@@ -460,6 +460,11 @@ The following options need to be configured: Note: If a "bootargs" environment is defined, it will overwride the defaults discussed just above. +- Cache Configuration: + CONFIG_SYS_ICACHE_OFF - Do not enable instruction cache in U-Boot + CONFIG_SYS_DCACHE_OFF - Do not enable data cache in U-Boot + CONFIG_SYS_L2CACHE_OFF- Do not enable L2 cache in U-Boot + - Serial Ports: CONFIG_PL010_SERIAL
arch/arm/cpu/armv7/Makefile +1 -1
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).o START := start.o -COBJS := cpu.o +COBJS := cpu.o cache_v7.o COBJS += syslib.o SRCS := $(START:.o=.S) $(COBJS:.o=.c)
arch/arm/cpu/armv7/cache_v7.c new file +394 -0
394 lines not on this page · raw message
arch/arm/include/asm/armv7.h new file +67 -0
67 lines not on this page · raw message
arch/arm/include/asm/utils.h new file +56 -0
56 lines not on this page · raw message
include/common.h +4 -1
@@ -413,6 +413,7 @@ void icache_disable(void);int dcache_status (void );void dcache_enable (void );void dcache_disable (void ); +void mmu_disable (void );void relocate_code (ulong ,gd_t *,ulong ) __attribute__ ((noreturn));ulong get_endaddr (void );void trap_init (ulong );
@@ -614,9 +615,11 @@ ulong video_setmem (ulong);/* arch/$(ARCH)/lib/cache.c */ void flush_cache (unsigned long ,unsigned long ); +void flush_dcache_all (void );void flush_dcache_range (unsigned long start,unsigned long stop);void invalidate_dcache_range (unsigned long start,unsigned long stop); - +void invalidate_dcache_all (void ); +void invalidate_icache_all (void );/* arch/$(ARCH)/lib/ticks.S */ unsigned long long get_ticks (void );
Signature · 1 line
1.7.0.4
PATCH v4 3/9 armv7: rename cache related CONFIG flags
In reply to Aneesh VReplace the cache related CONFIG flags with more meaningful names. Following are the changes:
CONFIG_L2_OFF -> CONFIG_SYS_L2CACHE_OFFCONFIG_SYS_NO_ICACHE -> CONFIG_SYS_ICACHE_OFFCONFIG_SYS_NO_DCACHE -> CONFIG_SYS_DCACHE_OFF
V2:
* Changed CONFIG_L2_OFF -> CONFIG_SYS_NO_L2CACHE
V4:
* Changed all three flags to the final names suggested as above and accordingly changed the commit message
--- arch/arm/cpu/arm1136/start.S | 4 ++-- arch/arm/cpu/armv7/cpu.c | 3 --- arch/arm/include/asm/global_data.h | 2 +- arch/arm/lib/Makefile | 2 -- arch/arm/lib/board.c | 2 +- arch/arm/lib/cache-cp15.c | 6 +++--- board/armltd/integrator/split_by_variant.sh | 8 ++++---- common/cmd_bdinfo.c | 2 +- include/configs/B2.h | 3 ++- include/configs/assabet.h | 2 +- include/configs/ca9x4_ct_vxp.h | 2 +- include/configs/cerf250.h | 2 +- include/configs/cradle.h | 2 +- include/configs/csb226.h | 2 +- include/configs/dnp1110.h | 2 +- include/configs/efikamx.h | 2 +- include/configs/evb4510.h | 3 ++- include/configs/gcplus.h | 2 +- include/configs/innokom.h | 2 +- include/configs/jornada.h | 2 +- include/configs/lart.h | 2 +- include/configs/lubbock.h | 2 +- include/configs/mx51evk.h | 2 +- include/configs/mx53evk.h | 2 +- include/configs/omap4_panda.h | 2 +- include/configs/omap4_sdp4430.h | 2 +- include/configs/pleb2.h | 2 +- include/configs/pxa255_idp.h | 2 +- include/configs/s5pc210_universal.h | 2 +- include/configs/shannon.h | 2 +- include/configs/tegra2-common.h | 2 +- include/configs/trizepsiv.h | 2 +- include/configs/vision2.h | 2 +- include/configs/xaeniax.h | 2 +- include/configs/xm250.h | 2 +- include/configs/zylonite.h | 2 +- 36 files changed, 42 insertions(+), 45 deletions(-)
arch/arm/cpu/arm1136/start.S +2 -2
@@ -512,10 +512,10 @@ fiq: .align 5 .global arm1136_cache_flush arm1136_cache_flush: -#if !defined(CONFIG_SYS_NO_ICACHE) +#if !defined(CONFIG_SYS_ICACHE_OFF) mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache #endif -#if !defined(CONFIG_SYS_NO_DCACHE) +#if !defined(CONFIG_SYS_DCACHE_OFF) mcr p15, 0, r1, c7, c14, 0 @ invalidate D cache #endif mov pc, lr @ back to caller
arch/arm/cpu/armv7/cpu.c +0 -3
@@ -35,9 +35,6 @@#include <command.h> #include <asm/system.h> #include <asm/cache.h> -#ifndef CONFIG_L2_OFF -#include <asm/arch/sys_proto.h> -#endif static void cache_flush (void );
arch/arm/include/asm/global_data.h +1 -1
@@ -70,7 +70,7 @@ typedef struct global_data {unsigned long irq_sp;/* irq stack pointer */ unsigned long start_addr_sp;/* start_addr_stackpointer */ unsigned long reloc_off; -#if !(defined(CONFIG_SYS_NO_ICACHE ) && defined(CONFIG_SYS_NO_DCACHE )) +#if !(defined(CONFIG_SYS_ICACHE_OFF ) && defined(CONFIG_SYS_DCACHE_OFF ))unsigned long tlb_addr;#endif void **jt;/* jump table */
arch/arm/lib/Makefile +0 -2
@@ -39,9 +39,7 @@ GLCOBJS += div0.o COBJS-y += board.o COBJS-y += bootm.o COBJS-y += cache.o -ifndef CONFIG_SYS_NO_CP15_CACHE COBJS-y += cache-cp15.o -endif COBJS-y += interrupts.o COBJS-y += reset.o SOBJS-$(CONFIG_USE_ARCH_MEMSET) += memset.o
arch/arm/lib/board.c +1 -1
@@ -329,7 +329,7 @@ void board_init_f (ulong bootflag)debug ("Reserving %ldk for protected RAM at %08lx\n" , reg, addr);#endif /* CONFIG_PRAM */ -#if !(defined(CONFIG_SYS_NO_ICACHE ) && defined(CONFIG_SYS_NO_DCACHE )) +#if !(defined(CONFIG_SYS_ICACHE_OFF ) && defined(CONFIG_SYS_DCACHE_OFF ))/* reserve TLB table */ addr -= (4096 *4 );
arch/arm/lib/cache-cp15.c +3 -3
@@ -24,7 +24,7 @@#include <common.h> #include <asm/system.h> -#if !(defined(CONFIG_SYS_NO_ICACHE ) && defined(CONFIG_SYS_NO_DCACHE )) +#if !(defined(CONFIG_SYS_ICACHE_OFF ) && defined(CONFIG_SYS_DCACHE_OFF ))#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH )#define CACHE_SETUP 0x1a
@@ -118,7 +118,7 @@ static void cache_disable(uint32_t cache_bit) }#endif -#ifdef CONFIG_SYS_NO_ICACHE +#ifdef CONFIG_SYS_ICACHE_OFF void icache_enable (void ) {return ;
@@ -150,7 +150,7 @@ int icache_status(void) }#endif -#ifdef CONFIG_SYS_NO_DCACHE +#ifdef CONFIG_SYS_DCACHE_OFF void dcache_enable (void ) {return ;
board/armltd/integrator/split_by_variant.sh +4 -4
@@ -103,16 +103,16 @@ case "$cpu" in #undef CONFIG_CM_INIT /* CM may not have initialization reg */ #undef CONFIG_CM_TCRAM /* CM may not have TCRAM */ /* May not be processor without cache support */ -#define CONFIG_SYS_NO_ICACHE 1 -#define CONFIG_SYS_NO_DCACHE 1 +#define CONFIG_SYS_ICACHE_OFF 1 +#define CONFIG_SYS_DCACHE_OFF 1 _EOF ;; arm720t) cat >> ${config_file} << _EOF /* May not be processor without cache support */ -#define CONFIG_SYS_NO_ICACHE 1 -#define CONFIG_SYS_NO_DCACHE 1 +#define CONFIG_SYS_ICACHE_OFF 1 +#define CONFIG_SYS_DCACHE_OFF 1 _EOF ;; esac
common/cmd_bdinfo.c +1 -1
@@ -345,7 +345,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])printf ("ip_addr = %pI4\n" , &bd->bi_ip_addr);#endif printf ("baudrate = %d bps\n" , bd->bi_baudrate); -#if !(defined(CONFIG_SYS_NO_ICACHE ) && defined(CONFIG_SYS_NO_DCACHE )) +#if !(defined(CONFIG_SYS_ICACHE_OFF ) && defined(CONFIG_SYS_DCACHE_OFF ))print_num ("TLB addr" , gd->tlb_addr);#endif print_num ("relocaddr" , gd->relocaddr);
include/configs/B2.h +2 -1
@@ -38,7 +38,8 @@#define CONFIG_B2 1/* on an B2 Board */ #define CONFIG_ARM_THUMB 1/* this is an ARM7TDMI */ #undef CONFIG_ARM7_REVD/* disable ARM720 REV.D Workarounds */ -#define CONFIG_SYS_NO_CP15_CACHE +#define CONFIG_SYS_ICACHE_OFF +#define CONFIG_SYS_DCACHE_OFF #define CONFIG_ARCH_CPU_INIT #define CONFIG_S3C44B0_CLOCK_SPEED 75/* we have a 75Mhz S3C44B0*/
include/configs/assabet.h +1 -1
@@ -38,7 +38,7 @@#undef CONFIG_USE_IRQ/* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF #define CONFIG_CMDLINE_TAG 1/* enable passing of ATAGs */ #define CONFIG_SETUP_MEMORY_TAGS 1
include/configs/ca9x4_ct_vxp.h +1 -1
@@ -41,7 +41,7 @@#define CONFIG_CMDLINE_TAG 1/* enable passing of ATAGs */ #define CONFIG_SETUP_MEMORY_TAGS 1 -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_L2CACHE_OFF 1#define CONFIG_INITRD_TAG 1#define CONFIG_OF_LIBFDT 1
include/configs/cerf250.h +1 -1
@@ -43,7 +43,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF /* * Size of malloc() pool
include/configs/cradle.h +1 -1
@@ -38,7 +38,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF #define CONFIG_SYS_TEXT_BASE 0x0/* * Size of malloc() pool
include/configs/csb226.h +1 -1
@@ -44,7 +44,7 @@/* for timer/console/ethernet */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF #define CONFIG_SYS_TEXT_BASE 0x0/* * Hardware drivers
include/configs/dnp1110.h +1 -1
@@ -42,7 +42,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF /* * Size of malloc() pool
include/configs/efikamx.h +1 -1
@@ -38,7 +38,7 @@#define CONFIG_DISPLAY_CPUINFO #define CONFIG_DISPLAY_BOARDINFO -#define CONFIG_L2_OFF +#define CONFIG_SYS_L2CACHE_OFF /* * Bootloader Components Configuration
include/configs/evb4510.h +2 -1
@@ -43,7 +43,8 @@#define CONFIG_ARM_THUMB 1/* this is an ARM7TDMI */ #define CONFIG_S3C4510B 1/* it's a S3C4510B chip */ #define CONFIG_EVB4510 1/* on an EVB4510 Board */ -#define CONFIG_SYS_NO_CP15_CACHE +#define CONFIG_SYS_ICACHE_OFF +#define CONFIG_SYS_DCACHE_OFF #define CONFIG_USE_IRQ #define CONFIG_STACKSIZE_IRQ (4*1024)
include/configs/gcplus.h +1 -1
@@ -49,7 +49,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF #define CONFIG_CMDLINE_TAG 1/* enable passing of ATAGs */ #define CONFIG_SETUP_MEMORY_TAGS 1
include/configs/innokom.h +1 -1
@@ -43,7 +43,7 @@#define CONFIG_SYS_TEXT_BASE 0x0/* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF /* * Hardware drivers
include/configs/jornada.h +1 -1
@@ -32,7 +32,7 @@#define CONFIG_SYS_TEXT_BASE 0xC1F00000/* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF #undef CONFIG_USE_IRQ/* Console setting */
include/configs/lart.h +1 -1
@@ -36,7 +36,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF /* * Size of malloc() pool
include/configs/lubbock.h +1 -1
@@ -47,7 +47,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF /* * Size of malloc() pool
include/configs/mx51evk.h +1 -1
@@ -35,7 +35,7 @@#define CONFIG_SYS_TEXT_BASE 0x97800000 -#define CONFIG_L2_OFF +#define CONFIG_SYS_L2CACHE_OFF #include <asm/arch/imx-regs.h> /*
include/configs/mx53evk.h +1 -1
@@ -29,7 +29,7 @@#define CONFIG_DISPLAY_CPUINFO #define CONFIG_DISPLAY_BOARDINFO -#define CONFIG_L2_OFF +#define CONFIG_SYS_L2CACHE_OFF #include <asm/arch/imx-regs.h>
include/configs/omap4_panda.h +1 -1
@@ -46,7 +46,7 @@#define CONFIG_DISPLAY_BOARDINFO 1/* Keep L2 Cache Disabled */ -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_L2CACHE_OFF 1/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */
include/configs/omap4_sdp4430.h +1 -1
@@ -47,7 +47,7 @@#define CONFIG_DISPLAY_BOARDINFO 1/* Keep L2 Cache Disabled */ -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_L2CACHE_OFF 1/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */
include/configs/pleb2.h +1 -1
@@ -44,7 +44,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF /* * Size of malloc() pool
include/configs/pxa255_idp.h +1 -1
@@ -69,7 +69,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF /* * Size of malloc() pool
include/configs/s5pc210_universal.h +1 -1
@@ -43,7 +43,7 @@#define CONFIG_DISPLAY_BOARDINFO /* Keep L2 Cache Disabled */ -#define CONFIG_L2_OFF 1 +#define CONFIG_SYS_L2CACHE_OFF 1#define CONFIG_SYS_SDRAM_BASE 0x40000000#define CONFIG_SYS_TEXT_BASE 0x44800000
include/configs/shannon.h +1 -1
@@ -44,7 +44,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF /* * Size of malloc() pool
include/configs/tegra2-common.h +1 -1
@@ -31,7 +31,7 @@#define CONFIG_ARMCORTEXA9 /* This is an ARM V7 CPU core */ #define CONFIG_TEGRA2 /* in a NVidia Tegra2 core */ #define CONFIG_MACH_TEGRA_GENERIC /* which is a Tegra generic machine */ -#define CONFIG_L2_OFF /* No L2 cache */ +#define CONFIG_SYS_L2CACHE_OFF /* No L2 cache */ #define CONFIG_ENABLE_CORTEXA9 /* enable CPU (A9 complex) */
include/configs/trizepsiv.h +1 -1
@@ -49,7 +49,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF #define RTC
include/configs/vision2.h +1 -1
@@ -26,7 +26,7 @@#define CONFIG_MX51 /* in a mx51 */ -#define CONFIG_L2_OFF +#define CONFIG_SYS_L2CACHE_OFF #define CONFIG_SYS_TEXT_BASE 0x97800000#include <asm/arch/imx-regs.h>
include/configs/xaeniax.h +1 -1
@@ -51,7 +51,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF /* * select serial console configuration
include/configs/xm250.h +1 -1
@@ -38,7 +38,7 @@#define CONFIG_SYS_TEXT_BASE 0x0/* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF /* * Size of malloc() pool; this lives below the uppermost 128 KiB which are
include/configs/zylonite.h +1 -1
@@ -48,7 +48,7 @@#undef CONFIG_USE_IRQ/* we don't need IRQ/FIQ stuff */ /* we will never enable dcache, because we have to setup MMU first */ -#define CONFIG_SYS_NO_DCACHE +#define CONFIG_SYS_DCACHE_OFF /* * Size of malloc() pool
Signature · 1 line
1.7.0.4
PATCH v4 4/9 armv7: integrate cache maintenance support
In reply to Aneesh V- Enable I-cache on bootup
- Enable MMU and D-cache immediately after relocation
- Do necessary initialization before enabling d-cache and MMU
- Changes to cleanup_before_linux()
- Make changes according to the new framework
---
V2:
* Changes for -march=armv7a -> armv5 change
* Removed the print inside the weakly linked stub function - __arm_init_before_mmu
* Replaced CONFIG_SYS_NO_*CACHE with CONFIG_SYS_*CACHE_OFF
--- arch/arm/cpu/armv7/cpu.c | 47 +++++++++++++++++++------------------------ arch/arm/cpu/armv7/start.S | 18 +++++++++++++++- arch/arm/lib/board.c | 6 +++++ arch/arm/lib/cache-cp15.c | 7 ++++++ arch/arm/lib/cache.c | 5 ---- 5 files changed, 51 insertions(+), 32 deletions(-)
arch/arm/cpu/armv7/cpu.c +21 -26
@@ -35,13 +35,10 @@#include <command.h> #include <asm/system.h> #include <asm/cache.h> - -static void cache_flush (void ); +#include <asm/armv7.h> int cleanup_before_linux (void ) { -unsigned int i; -/* * this function is called just before we call linux * it prepares the processor for linux
@@ -50,31 +47,29 @@ int cleanup_before_linux(void)*/ disable_interrupts (); -/* turn off I/D-cache */ +/* +* Turn off I-cache and invalidate it +*/ icache_disable (); -dcache_disable (); - -/* invalidate I-cache */ -cache_flush (); +invalidate_icache_all (); -#ifndef CONFIG_L2_OFF -/* turn off L2 cache */ -l2_cache_disable (); -/* invalidate L2 cache also */ -invalidate_dcache (get_device_type ()); -#endif - i =0 ; -/* mem barrier to sync up things */ - asm("mcr p15, 0, %0, c7, c10, 4" : :"r" (i)); +/* +* turn off D-cache +* dcache_disable() in turn flushes the d-cache and disables MMU +*/ +dcache_disable (); -#ifndef CONFIG_L2_OFF -l2_cache_enable (); -#endif +/* +* After D-cache is flushed and before it is disabled there may +* be some new valid entries brought into the cache. We are sure +* that these lines are not dirty and will not affect our execution. +* (because unwinding the call-stack and setting a bit in CP15 SCTRL +* is all we did during this. We have not pushed anything on to the +* stack. Neither have we affected any static data) +* So just invalidate the entire d-cache again to avoid coherency +* problems for kernel +*/ +invalidate_dcache_all ();return 0 ; } - -static void cache_flush (void ) -{ - asm ("mcr p15, 0, %0, c7, c5, 0" : :"r" (0 )); -}
arch/arm/cpu/armv7/start.S +17 -1
@@ -255,6 +255,14 @@ clbss_l:str r2, [r0] /* clear loop... */ * initialization, now running from RAM. */ jump_2_ram: +/* + * If I-cache is enabled invalidate it + */ +#ifndef CONFIG_SYS_ICACHE_OFF + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB +#endif ldr r0, _board_init_r_ofs adr r1, _start add lr, r0, r1
@@ -290,6 +298,9 @@ cpu_init_crit: mov r0, #0 @ set up for MCR mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB /* * disable MMU stuff and caches
@@ -298,7 +309,12 @@ cpu_init_crit: bic r0, r0, #0x00002000 @ clear bits 13 (--V-) bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align - orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB +#ifdef CONFIG_SYS_ICACHE_OFF + bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache +#else + orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache +#endif mcr p15, 0, r0, c1, c0, 0 /*
arch/arm/lib/board.c +6 -0
@@ -464,6 +464,12 @@ void board_init_r (gd_t *id, ulong dest_addr) gd->flags |=GD_FLG_RELOC ;/* tell others: relocation done */ monitor_flash_len = _end_ofs; +/* +* Enable D$: +* I$, if needed, must be already enabled in start.S +*/ +dcache_enable (); +debug ("monitor flash len: %08lX\n" , monitor_flash_len);board_init ();/* Setup chipselects */
arch/arm/lib/cache-cp15.c +7 -0
@@ -34,6 +34,12 @@DECLARE_GLOBAL_DATA_PTR ; +void __arm_init_before_mmu (void ) +{ +} +void arm_init_before_mmu (void ) + __attribute__((weak,alias ("__arm_init_before_mmu" ))); +static void cp_delay (void ) {volatile int i;
@@ -65,6 +71,7 @@ static inline void mmu_setup(void)int i;u32 reg; +arm_init_before_mmu ();/* Set up an identity-mapping for all 4GB, rw for everyone */ for (i =0 ; i <4096 ; i++) page_table[i] = i <<20 | (3 <<10 ) |0x12 ;
arch/arm/lib/cache.c +0 -5
@@ -38,11 +38,6 @@ void __flush_cache(unsigned long start, unsigned long size)/* disable write buffer as well (page 2-22) */ asm("mcr p15, 0, %0, c7, c10, 4" : :"r" (0 ));#endif -#ifdef CONFIG_OMAP34XX -void v7_flush_cache_all (void ); - -v7_flush_cache_all (); -#endif return ; }void flush_cache (unsigned long start,unsigned long size)
Signature · 1 line
1.7.0.4
PATCH v4 5/9 arm: minor fixes for cache and mmu handling
In reply to Aneesh V1. make sure that page table setup is not done multiple times
2. flush_dcache_all() is more appropriate while disabling cache than a range flush on the entire memory(flush_cache())
Provide a default implementation for flush_dcache_all() for backward compatibility and to avoid build issues.
---
V2:
* Fixed signature of flush_cache in cache.c
--- arch/arm/lib/cache-cp15.c | 9 +++++++-- arch/arm/lib/cache.c | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-)
arch/arm/lib/cache-cp15.c +7 -2
@@ -92,13 +92,18 @@ static inline void mmu_setup(void)set_cr (reg |CR_M ); } +static int mmu_enabled (void ) +{ +return get_cr () &CR_M ; +} +/* cache_bit must be either CR_I or CR_C */ static void cache_enable (uint32_t cache_bit) {uint32_t reg;/* The data cache is not active unless the mmu is enabled too */ -if (cache_bit ==CR_C ) +if ((cache_bit ==CR_C ) && !mmu_enabled ())mmu_setup (); reg =get_cr ();/* get control reg. */ cp_delay ();
@@ -117,7 +122,7 @@ static void cache_disable(uint32_t cache_bit)return ;/* if disabling data cache, disable mmu too */ cache_bit |=CR_M ; -flush_cache (0 , ~0 ); +flush_dcache_all (); } reg =get_cr ();cp_delay ();
arch/arm/lib/cache.c +11 -0
@@ -42,3 +42,14 @@ void __flush_cache(unsigned long start, unsigned long size) }void flush_cache (unsigned long start,unsigned long size) __attribute__((weak,alias ("__flush_cache" ))); + +/* +* Default implementation: +* do a range flush for the entire range +*/ +void __flush_dcache_all (void ) +{ +flush_cache (0 , ~0 ); +} +void flush_dcache_all (void ) + __attribute__((weak,alias ("__flush_dcache_all" )));
Signature · 1 line
1.7.0.4
PATCH v4 6/9 armv7: add PL310 support to u-boot
In reply to Aneesh VPL310 is the L2$ controller from ARM used in many SoCs including the Cortex-A9 based OMAP4430
Add support for some of the key PL310 operations
- Invalidate all
- Invalidate range
- Flush(clean & invalidate) all
- Flush range
---
V2:
* More descriptive commit message
* Changes for function pointer to weakly linked change
* C struct for register accesses
--- README | 6 ++ arch/arm/include/asm/pl310.h | 73 ++++++++++++++++++++++++++ arch/arm/lib/Makefile | 1 + arch/arm/lib/cache-pl310.c | 115 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/pl310.h create mode 100644 arch/arm/lib/cache-pl310.c
README +6 -0
@@ -465,6 +465,12 @@ The following options need to be configured: CONFIG_SYS_DCACHE_OFF - Do not enable data cache in U-Boot CONFIG_SYS_L2CACHE_OFF- Do not enable L2 cache in U-Boot +- Cache Configuration for ARM: + CONFIG_SYS_L2_PL310 - Enable support for ARM PL310 L2 cache + controller + CONFIG_SYS_PL310_BASE - Physical base address of PL310 + controller register space + - Serial Ports: CONFIG_PL010_SERIAL
arch/arm/include/asm/pl310.h new file +73 -0
73 lines not on this page · raw message
arch/arm/lib/Makefile +1 -0
@@ -40,6 +40,7 @@ COBJS-y += board.o COBJS-y += bootm.o COBJS-y += cache.o COBJS-y += cache-cp15.o +COBJS-$(CONFIG_SYS_L2_PL310) += cache-pl310.o COBJS-y += interrupts.o COBJS-y += reset.o SOBJS-$(CONFIG_USE_ARCH_MEMSET) += memset.o
arch/arm/lib/cache-pl310.c new file +115 -0
115 lines not on this page · raw message
Signature · 1 line
1.7.0.4
PATCH v4 7/9 armv7: adapt omap4 to the new cache maintenance framework
In reply to Aneesh Vadapt omap4 to the new layered cache maintenance framework
---
V2:
* Changes for the function pointer to weakly linked change
V4:
* Replaced CONFIG_SYS_NO_*CACHE with CONFIG_SYS_*CACHE_OFF
--- arch/arm/cpu/armv7/omap4/board.c | 12 ++++++++++++ arch/arm/cpu/armv7/omap4/lowlevel_init.S | 9 +++++++++ arch/arm/include/asm/arch-omap4/sys_proto.h | 2 +- include/configs/omap4_panda.h | 8 +++++--- include/configs/omap4_sdp4430.h | 8 +++++--- 5 files changed, 32 insertions(+), 7 deletions(-)
arch/arm/cpu/armv7/omap4/board.c +12 -0
@@ -127,3 +127,15 @@ int arch_cpu_init(void)set_muxconf_regs ();return 0 ; } + +#ifndef CONFIG_SYS_L2CACHE_OFF +void v7_outer_cache_enable (void ) +{ +set_pl310_ctrl_reg (1 ); +} + +void v7_outer_cache_disable (void ) +{ +set_pl310_ctrl_reg (0 ); +} +#endif
arch/arm/cpu/armv7/omap4/lowlevel_init.S +9 -0
@@ -45,3 +45,12 @@ lowlevel_init: */ bl s_init pop {ip, pc} + +.globl set_pl310_ctrl_reg +set_pl310_ctrl_reg: + PUSH {r4-r11, lr} @ save registers - ROM code may pollute + @ our registers + LDR r12, =0x102 @ Set PL310 control register - value in R0 + .word 0xe1600070 @ SMC #0 - hand assembled because -march=armv5 + @ call ROM Code API to set control register + POP {r4-r11, pc}
arch/arm/include/asm/arch-omap4/sys_proto.h +1 -1
@@ -31,11 +31,11 @@ struct omap_sysinfo {void gpmc_init (void );void watchdog_init (void );u32 get_device_type (void ); -void invalidate_dcache (u32 );void set_muxconf_regs (void );void sr32 (void *,u32 ,u32 ,u32 );u32 wait_on_value (u32 ,u32 ,void *,u32 );void sdelay (unsigned long ); +void set_pl310_ctrl_reg (u32 val);extern const struct omap_sysinfo sysinfo;
include/configs/omap4_panda.h +5 -3
@@ -45,9 +45,6 @@#define CONFIG_DISPLAY_CPUINFO 1#define CONFIG_DISPLAY_BOARDINFO 1 -/* Keep L2 Cache Disabled */ -#define CONFIG_SYS_L2CACHE_OFF 1 -/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */ #define V_SCLK V_OSCK
@@ -235,4 +232,9 @@ CONFIG_SYS_INIT_RAM_SIZE - \ GENERATED_GBL_DATA_SIZE) +#ifndef CONFIG_SYS_L2CACHE_OFF +#define CONFIG_SYS_L2_PL310 1 +#define CONFIG_SYS_PL310_BASE 0x48242000 +#endif +#endif /* __CONFIG_H */
include/configs/omap4_sdp4430.h +5 -3
@@ -46,9 +46,6 @@#define CONFIG_DISPLAY_CPUINFO 1#define CONFIG_DISPLAY_BOARDINFO 1 -/* Keep L2 Cache Disabled */ -#define CONFIG_SYS_L2CACHE_OFF 1 -/* Clock Defines */ #define V_OSCK 38400000/* Clock output from T2 */ #define V_SCLK V_OSCK
@@ -241,4 +238,9 @@ CONFIG_SYS_INIT_RAM_SIZE - \ GENERATED_GBL_DATA_SIZE) +#ifndef CONFIG_SYS_L2CACHE_OFF +#define CONFIG_SYS_L2_PL310 1 +#define CONFIG_SYS_PL310_BASE 0x48242000 +#endif +#endif /* __CONFIG_H */
Signature · 1 line
1.7.0.4
PATCH v4 8/9 armv7: adapt omap3 to the new cache maintenance framework
In reply to Aneesh Vadapt omap3 to the new layered cache maintenance framework
---
V2:
* Changes for the function pointer to weakly linked change
V4:
* Minor change in the conditional compilation of L2 related functions
* Replaced CONFIG_SYS_NO_*CACHE with CONFIG_SYS_*CACHE_OFF
--- arch/arm/cpu/armv7/omap3/Makefile | 1 - arch/arm/cpu/armv7/omap3/board.c | 136 ++++++++++++-- arch/arm/cpu/armv7/omap3/cache.S | 263 --------------------------- arch/arm/cpu/armv7/omap3/lowlevel_init.S | 32 ++++ arch/arm/include/asm/arch-omap3/omap3.h | 20 ++ arch/arm/include/asm/arch-omap3/sys_proto.h | 10 +- 6 files changed, 176 insertions(+), 286 deletions(-) delete mode 100644 arch/arm/cpu/armv7/omap3/cache.S
arch/arm/cpu/armv7/omap3/Makefile +0 -1
@@ -26,7 +26,6 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).o SOBJS := lowlevel_init.o -SOBJS += cache.o COBJS += board.o COBJS += clock.o
arch/arm/cpu/armv7/omap3/board.c +117 -19
155 lines not on this page · raw message
arch/arm/cpu/armv7/omap3/cache.S deleted +0 -263
263 lines not on this page · raw message
arch/arm/cpu/armv7/omap3/lowlevel_init.S +32 -0
@@ -35,6 +35,38 @@ _TEXT_BASE: .word CONFIG_SYS_TEXT_BASE /* sdram load addr from config.mk */ +.global omap3_gp_romcode_call +omap3_gp_romcode_call: + PUSH {r4-r12, lr} @ Save all registers from ROM code! + MOV r12, r0 @ Copy the Service ID in R12 + MOV r0, r1 @ Copy parameter to R0 + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c10, 5 @ DMB + .word 0xe1600070 @ SMC #0 to enter monitor - hand assembled + @ because we use -march=armv5 + POP {r4-r12, pc} + +/* + * Funtion for making PPA HAL API calls in secure devices + * Input: + * R0 - Service ID + * R1 - paramer list + */ +.global do_omap3_emu_romcode_call +do_omap3_emu_romcode_call: + PUSH {r4-r12, lr} @ Save all registers from ROM code! + MOV r12, r0 @ Copy the Secure Service ID in R12 + MOV r3, r1 @ Copy the pointer to va_list in R3 + MOV r1, #0 @ Process ID - 0 + MOV r2, #OMAP3_EMU_HAL_START_HAL_CRITICAL @ Copy the pointer + @ to va_list in R3 + MOV r6, #0xFF @ Indicate new Task call + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c10, 5 @ DMB + .word 0xe1600071 @ SMC #1 to call PPA service - hand assembled + @ because we use -march=armv5 + POP {r4-r12, pc} + #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_NAND_BOOT) /************************************************************************** * cpy_clk_code: relocates clock code into SRAM where its safer to execute
arch/arm/include/asm/arch-omap3/omap3.h +20 -0
@@ -159,8 +159,14 @@ struct gpio {#define SRAM_VECT_CODE (SRAM_OFFSET0 | SRAM_OFFSET1 | \ SRAM_OFFSET2) +#define OMAP3_PUBLIC_SRAM_BASE 0x40208000/* Works for GP & EMU */ +#define OMAP3_PUBLIC_SRAM_END 0x40210000 +#define LOW_LEVEL_SRAM_STACK 0x4020FFFC +/* scratch area - accessible on both EMU and GP */ +#define OMAP3_PUBLIC_SRAM_SCRATCH_AREA OMAP3_PUBLIC_SRAM_BASE +#define DEBUG_LED1 149/* gpio */ #define DEBUG_LED2 150/* gpio */
@@ -227,4 +233,18 @@ struct gpio {#define OMAP3730 0x0c00 +/* +* ROM code API related flags +*/ +#define OMAP3_GP_ROMCODE_API_L2_INVAL 1 +#define OMAP3_GP_ROMCODE_API_WRITE_ACR 3 + +/* +* EMU device PPA HAL related flags +*/ +#define OMAP3_EMU_HAL_API_L2_INVAL 40 +#define OMAP3_EMU_HAL_API_WRITE_ACR 42 + +#define OMAP3_EMU_HAL_START_HAL_CRITICAL 4 +#endif
arch/arm/include/asm/arch-omap3/sys_proto.h +7 -3
@@ -27,6 +27,11 @@ typedef struct {char *nand_string; } omap3_sysinfo; +struct emu_hal_params { +u32 num_params; +u32 param1; +}; +void prcm_init (void );void per_clocks_enable (void );
@@ -53,9 +58,7 @@ u32 is_running_in_sdram(void);u32 is_running_in_sram (void );u32 is_running_in_flash (void );u32 get_device_type (void ); -void l2cache_enable (void );void secureworld_exit (void ); -void setup_auxcr (void );void try_unlock_memory (void );u32 get_boot_type (void );void invalidate_dcache (u32 );
@@ -66,5 +69,6 @@ void make_cs1_contiguous(void);void omap_nand_switch_ecc (int );void power_init_r (void );void dieid_num_r (void ); - +void do_omap3_emu_romcode_call (u32 service_id,u32 parameters); +void omap3_gp_romcode_call (u32 service_id,u32 parameter);#endif
Signature · 1 line
1.7.0.4
PATCH v4 9/9 armv7: adapt s5pc1xx to the new cache maintenance framework
In reply to Aneesh Vadapt s5pc1xx to the new layered cache maintenance framework
---
V2:
* Changes for the function pointer to weakly linked change
V4:
* Minor change in the conditional compilation of L2 related code in cache.S
* Replaced CONFIG_SYS_NO_*CACHE with CONFIG_SYS_*CACHE_OFF
--- arch/arm/cpu/armv7/s5pc1xx/cache.S | 88 ++----------------------- arch/arm/include/asm/arch-s5pc1xx/sys_proto.h | 3 - 2 files changed, 6 insertions(+), 85 deletions(-)
arch/arm/cpu/armv7/s5pc1xx/cache.S +6 -82
@@ -23,98 +23,22 @@ * MA 02111-1307 USA */ -#include <asm/arch/cpu.h> - .align 5 -.global invalidate_dcache -.global l2_cache_enable -.global l2_cache_disable - -/* - * invalidate_dcache() - * Invalidate the whole D-cache. - * - * Corrupted registers: r0-r5, r7, r9-r11 - */ -invalidate_dcache: - stmfd r13!, {r0 - r5, r7, r9 - r12, r14} - - cmp r0, #0xC100 @ check if the cpu is s5pc100 - - beq finished_inval @ s5pc100 doesn't need this - @ routine - mrc p15, 1, r0, c0, c0, 1 @ read clidr - ands r3, r0, #0x7000000 @ extract loc from clidr - mov r3, r3, lsr #23 @ left align loc bit field - beq finished_inval @ if loc is 0, then no need to - @ clean - mov r10, #0 @ start clean at cache level 0 -inval_loop1: - add r2, r10, r10, lsr #1 @ work out 3x current cache - @ level - mov r1, r0, lsr r2 @ extract cache type bits from - @ clidr - and r1, r1, #7 @ mask of the bits for current - @ cache only - cmp r1, #2 @ see what cache we have at - @ this level - blt skip_inval @ skip if no cache, or just - @ i-cache - mcr p15, 2, r10, c0, c0, 0 @ select current cache level - @ in cssr - mov r2, #0 @ operand for mcr SBZ - mcr p15, 0, r2, c7, c5, 4 @ flush prefetch buffer to - @ sych the new cssr&csidr, - @ with armv7 this is 'isb', - @ but we compile with armv5 - mrc p15, 1, r1, c0, c0, 0 @ read the new csidr - and r2, r1, #7 @ extract the length of the - @ cache lines - add r2, r2, #4 @ add 4 (line length offset) - ldr r4, =0x3ff - ands r4, r4, r1, lsr #3 @ find maximum number on the - @ way size - clz r5, r4 @ find bit position of way - @ size increment - ldr r7, =0x7fff - ands r7, r7, r1, lsr #13 @ extract max number of the - @ index size -inval_loop2: - mov r9, r4 @ create working copy of max - @ way size -inval_loop3: - orr r11, r10, r9, lsl r5 @ factor way and cache number - @ into r11 - orr r11, r11, r7, lsl r2 @ factor index number into r11 - mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way - subs r9, r9, #1 @ decrement the way - bge inval_loop3 - subs r7, r7, #1 @ decrement the index - bge inval_loop2 -skip_inval: - add r10, r10, #2 @ increment cache number - cmp r3, r10 - bgt inval_loop1 -finished_inval: - mov r10, #0 @ swith back to cache level 0 - mcr p15, 2, r10, c0, c0, 0 @ select current cache level - @ in cssr - mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, - @ with armv7 this is 'isb', - @ but we compile with armv5 - - ldmfd r13!, {r0 - r5, r7, r9 - r12, pc} -l2_cache_enable: +#ifndef CONFIG_SYS_L2CACHE_OFF +.global v7_outer_cache_enable +v7_outer_cache_enable: push {r0, r1, r2, lr} mrc 15, 0, r3, cr1, cr0, 1 orr r3, r3, #2 mcr 15, 0, r3, cr1, cr0, 1 pop {r1, r2, r3, pc} -l2_cache_disable: +.global v7_outer_cache_disable +v7_outer_cache_disable: push {r0, r1, r2, lr} mrc 15, 0, r3, cr1, cr0, 1 bic r3, r3, #2 mcr 15, 0, r3, cr1, cr0, 1 pop {r1, r2, r3, pc} +#endif
arch/arm/include/asm/arch-s5pc1xx/sys_proto.h +0 -3
@@ -25,8 +25,5 @@#define _SYS_PROTO_H_u32 get_device_type (void ); -void invalidate_dcache (u32 ); -void l2_cache_disable (void ); -void l2_cache_enable (void );#endif
Signature · 1 line
1.7.0.4