[source] bcm53xx: switch back to standalone ASM entry flushing cache

LEDE Commits lede-commits at lists.infradead.org
Fri Aug 19 02:48:41 PDT 2016


rmilecki pushed a commit to source.git, branch master:
https://git.lede-project.org/?p=source.git;a=commitdiff;h=5e885c09c625c22d2995d477ef6cc8ee7595a817

commit 5e885c09c625c22d2995d477ef6cc8ee7595a817
Author: Rafał Miłecki <rafal at milecki.pl>
AuthorDate: Fri Jul 22 17:26:33 2016 +0200

    bcm53xx: switch back to standalone ASM entry flushing cache
    
    Over a year ago in a commit ac96a1665ac7 ("bcm53xx: update Disable MMU
    and Dcache during decompression") we switched to Florian's patch for
    workarounding CFE bug. The main difference was using a part of existing
    __armv7_mmu_cache_flush instead of implementing flushing separately.
    
    This worked well for Northstar devices but doesn't work for BCM53573 as
    these devices simply don't start booting with Florian's patch. It's
    because of the ldmfd ASM instruction in the __armv7_mmu_cache_flush.
    
    So this commit switches back to using standalone implementation. This
    time instead of copying Broadcom's copy of cache-v7.S, we just make a
    copy of the original file on our own. Unfortunately we can't cross-dir
    compile cache-v7.S from ../../mm/ as that one also adds __INITDATA with
    define_cache_functions v7 which would just trigger
    > Error: unrecognized/unsupported machine ID (r1 = 0x0000007f).
    
    The only real change Broadcom did in copied .S file was modifying mcr
    instruction to use c6 instead of c14. It isn't clear to me if we really
    need it, but let's use it for now.
    
    By the way we also update commit message of the
    [PATCH] ARM: BCM5301X: Disable MMU and Dcache during decompression
    
    This makes kernel booting on BCM53573 successfully.
    
    Signed-off-by: Rafał Miłecki <rafal at milecki.pl>
---
 .../files/arch/arm/boot/compressed/cache-v7-min.S  |  67 ++++++++++++++
 ...X-Disable-MMU-and-Dcache-during-decompres.patch | 100 +++++++++++++++++++++
 ...-Disable-MMU-and-Dcache-for-decompression.patch |  86 ------------------
 3 files changed, 167 insertions(+), 86 deletions(-)

diff --git a/target/linux/bcm53xx/files/arch/arm/boot/compressed/cache-v7-min.S b/target/linux/bcm53xx/files/arch/arm/boot/compressed/cache-v7-min.S
new file mode 100644
index 0000000..945e5a1
--- /dev/null
+++ b/target/linux/bcm53xx/files/arch/arm/boot/compressed/cache-v7-min.S
@@ -0,0 +1,67 @@
+/*
+ * This is a part of mm/cache-v7.S with extracted entry flushing D-cache. We
+ * need it for Broadcom devices with broken bootloader leaving cache enabled.
+ *
+ * Copyright (C) 2001 Deep Blue Solutions Ltd.
+ * Copyright (C) 2005 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+	__INIT
+
+/*
+ *	v7_flush_dcache_all()
+ *
+ *	Flush the whole D-cache.
+ *
+ *	Corrupted registers: r0-r5, r7, r9-r11
+ *
+ *	- mm    - mm_struct describing address space
+ */
+ENTRY(v7_flush_dcache_all)
+	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			@ if loc is 0, then no need to clean
+	mov	r10, #0				@ start clean at cache level 0
+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				@ skip if no cache, or just i-cache
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	isb					@ isb to sych the new cssr&csidr
+	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
+loop2:
+	mov	r9, r4				@ create working copy of max way size
+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, c14, 2		@ clean & invalidate by set/way
+	subs	r9, r9, #1			@ decrement the way
+	bge	loop3
+	subs	r7, r7, #1			@ decrement the index
+	bge	loop2
+skip:
+	add	r10, r10, #2			@ increment cache number
+	cmp	r3, r10
+	bgt	loop1
+finished:
+	mov	r10, #0				@ swith back to cache level 0
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	isb
+	mov	pc, lr
diff --git a/target/linux/bcm53xx/patches-4.4/300-ARM-BCM5301X-Disable-MMU-and-Dcache-during-decompres.patch b/target/linux/bcm53xx/patches-4.4/300-ARM-BCM5301X-Disable-MMU-and-Dcache-during-decompres.patch
new file mode 100644
index 0000000..5dba027
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.4/300-ARM-BCM5301X-Disable-MMU-and-Dcache-during-decompres.patch
@@ -0,0 +1,100 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal at milecki.pl>
+Date: Wed, 24 Sep 2014 22:14:07 +0200
+Subject: [PATCH] ARM: BCM5301X: Disable MMU and Dcache during decompression
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Broadcom devices have broken CFE (bootloader) that leaves hardware in an
+invalid state. It causes problems with booting Linux. On Northstar
+devices kernel was randomly hanging in ~25% of tries during early init.
+Hangs used to happen at random places in the start_kernel. On BCM53573
+kernel doesn't even seem to start booting.
+
+To workaround this problem we need to do following very early:
+1) Clear 2 following bits in the SCTLR register:
+#define CR_M    (1 << 0)        /* MMU enable */
+#define CR_C    (1 << 2)        /* Dcache enable */
+2) Flush the whole D-cache
+3) Disable L2 cache
+
+Unfortunately this patch is not upstreamable as it does above things
+unconditionally. We can't check if we are running on Broadcom platform
+in any safe way and doing such hacks with ARCH_MULTI_V7 is unacceptable
+as it could break other devices support.
+
+Signed-off-by: Rafał Miłecki <rafal at milecki.pl>
+---
+
+--- a/arch/arm/boot/compressed/Makefile
++++ b/arch/arm/boot/compressed/Makefile
+@@ -31,6 +31,11 @@ ifeq ($(CONFIG_ARCH_ACORN),y)
+ OBJS		+= ll_char_wr.o font.o
+ endif
+ 
++ifeq ($(CONFIG_ARCH_BCM_5301X),y)
++OBJS		+= head-bcm_5301x-mpcore.o
++OBJS		+= cache-v7-min.o
++endif
++
+ ifeq ($(CONFIG_ARCH_SA1100),y)
+ OBJS		+= head-sa1100.o
+ endif
+--- /dev/null
++++ b/arch/arm/boot/compressed/head-bcm_5301x-mpcore.S
+@@ -0,0 +1,37 @@
++/*
++ *
++ * Platform specific tweaks.  This is merged into head.S by the linker.
++ *
++ */
++
++#include <linux/linkage.h>
++#include <asm/assembler.h>
++#include <asm/cp15.h>
++
++		.section        ".start", "ax"
++
++/*
++ * This code section is spliced into the head code by the linker
++ */
++
++__plat_uncompress_start:
++
++	@ Preserve r8/r7 i.e. kernel entry values
++	mov	r12, r8
++
++	@ Clear MMU enable and Dcache enable bits
++	mrc	p15, 0, r0, c1, c0, 0		@ Read SCTLR
++	bic	r0, #CR_C|CR_M
++	mcr	p15, 0, r0, c1, c0, 0		@ Write SCTLR
++	nop
++
++	@ Call the cache invalidation routine
++	bl	v7_flush_dcache_all
++	nop
++	mov	r0,#0
++	ldr	r3, =0x19022000			@ L2 cache controller, control reg
++	str	r0, [r3, #0x100]		@ Disable L2 cache
++	nop
++
++	@ Restore
++	mov	r8, r12
+--- a/arch/arm/boot/compressed/cache-v7-min.S
++++ b/arch/arm/boot/compressed/cache-v7-min.S
+@@ -51,7 +51,7 @@ loop2:
+ 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, c14, 2		@ clean & invalidate by set/way
++	mcr     p15, 0, r11, c7, c6, 2		@ Invalidate line
+ 	subs	r9, r9, #1			@ decrement the way
+ 	bge	loop3
+ 	subs	r7, r7, #1			@ decrement the index
+@@ -63,5 +63,6 @@ skip:
+ finished:
+ 	mov	r10, #0				@ swith back to cache level 0
+ 	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
++	dsb
+ 	isb
+ 	mov	pc, lr
diff --git a/target/linux/bcm53xx/patches-4.4/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch b/target/linux/bcm53xx/patches-4.4/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch
deleted file mode 100644
index 62bda2e..0000000
--- a/target/linux/bcm53xx/patches-4.4/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-From: Florian Fainelli <f.fainelli at gmail.com>
-Subject: [PATCH] ARM: BCM5301x: Disable MMU and Dcache during decompression
-Date: Tue, 14 Jul 2015 16:12:08 -0700
-
-Use the existing __armv7_mmu_cache_flush() to perform the cache flush
-since this does what we are after.
-
-Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
----
- arch/arm/boot/compressed/Makefile                |  4 +++
- arch/arm/boot/compressed/head-bcm_5301x-mpcore.S | 37 ++++++++++++++++++++++++
- arch/arm/boot/compressed/head.S                  |  2 ++
- 3 files changed, 43 insertions(+)
- create mode 100644 arch/arm/boot/compressed/head-bcm_5301x-mpcore.S
-
---- a/arch/arm/boot/compressed/Makefile
-+++ b/arch/arm/boot/compressed/Makefile
-@@ -31,6 +31,10 @@ ifeq ($(CONFIG_ARCH_ACORN),y)
- OBJS		+= ll_char_wr.o font.o
- endif
- 
-+ifeq ($(CONFIG_ARCH_BCM_5301X),y)
-+OBJS		+= head-bcm_5301x-mpcore.o
-+endif
-+
- ifeq ($(CONFIG_ARCH_SA1100),y)
- OBJS		+= head-sa1100.o
- endif
---- /dev/null
-+++ b/arch/arm/boot/compressed/head-bcm_5301x-mpcore.S
-@@ -0,0 +1,37 @@
-+/*
-+ *
-+ * Platform specific tweaks.  This is merged into head.S by the linker.
-+ *
-+ */
-+
-+#include <linux/linkage.h>
-+#include <asm/assembler.h>
-+#include <asm/cp15.h>
-+
-+		.section        ".start", "ax"
-+
-+/*
-+ * This code section is spliced into the head code by the linker
-+ */
-+
-+__plat_uncompress_start:
-+
-+	@ Preserve r8/r7 i.e. kernel entry values
-+	mov	r12, r8
-+
-+	@ Clear MMU enable and Dcache enable bits
-+	mrc	p15, 0, r0, c1, c0, 0		@ Read SCTLR
-+	bic	r0, #CR_C|CR_M
-+	mcr	p15, 0, r0, c1, c0, 0		@ Write SCTLR
-+	nop
-+
-+	@ Call the cache invalidation routine
-+	bl	__armv7_mmu_cache_flush_fn
-+	nop
-+	mov	r0,#0
-+	ldr	r3, =0x19022000			@ L2 cache controller, control reg
-+	str	r0, [r3, #0x100]		@ Disable L2 cache
-+	nop
-+
-+	@ Restore
-+	mov	r8, r12
---- a/arch/arm/boot/compressed/head.S
-+++ b/arch/arm/boot/compressed/head.S
-@@ -1152,6 +1152,7 @@ __armv7_mmu_cache_flush:
- hierarchical:
- 		mcr	p15, 0, r10, c7, c10, 5	@ DMB
- 		stmfd	sp!, {r0-r7, r9-r11}
-+ENTRY(__armv7_mmu_cache_flush_fn)
- 		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
-@@ -1201,6 +1202,7 @@ iflush:
- 		mcr	p15, 0, r10, c7, c10, 4	@ DSB
- 		mcr	p15, 0, r10, c7, c5, 4	@ ISB
- 		mov	pc, lr
-+ENDPROC(__armv7_mmu_cache_flush_fn)
- 
- __armv5tej_mmu_cache_flush:
- 		tst	r4, #1



More information about the lede-commits mailing list