summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv8/fsl-lsch3
diff options
context:
space:
mode:
authorYork Sun <yorksun@freescale.com>2015-01-06 13:18:42 -0800
committerYork Sun <yorksun@freescale.com>2015-02-24 13:08:46 -0800
commitdcd468b8f43c5077c42c75b15cf3204e6b6be46c (patch)
tree2be7011207c86f70368e7372302366b2bb6e2770 /arch/arm/cpu/armv8/fsl-lsch3
parent60385d94e56513b50b87724fb9a3878ee5086da9 (diff)
downloadu-boot-imx-dcd468b8f43c5077c42c75b15cf3204e6b6be46c.zip
u-boot-imx-dcd468b8f43c5077c42c75b15cf3204e6b6be46c.tar.gz
u-boot-imx-dcd468b8f43c5077c42c75b15cf3204e6b6be46c.tar.bz2
armv8/fsl-lsch3: Convert flushing L3 to assembly to avoid using stack
Flushing L3 cache in CCN-504 requries d-cache to be disabled. Using assembly function to guarantee stack is not used before flushing is completed. Timeout is needed for simualtor on which CCN-504 is not implemented. Return value can be checked for timeout situation. Change bootm.c to disable dcache instead of simply flushing, required by flushing L3. Signed-off-by: York Sun <yorksun@freescale.com>
Diffstat (limited to 'arch/arm/cpu/armv8/fsl-lsch3')
-rw-r--r--arch/arm/cpu/armv8/fsl-lsch3/cpu.c53
-rw-r--r--arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S78
2 files changed, 78 insertions, 53 deletions
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
index ada1690..2aaac01 100644
--- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
@@ -243,59 +243,6 @@ int arch_cpu_init(void)
}
/*
- * flush_l3_cache
- * Dickens L3 cache can be flushed by transitioning from FAM to SFONLY power
- * state, by writing to HP-F P-state request register.
- * Fixme: This function should moved to a common file if other SoCs also use
- * the same Dickens.
- */
-#define HNF0_PSTATE_REQ 0x04200010
-#define HNF1_PSTATE_REQ 0x04210010
-#define HNF2_PSTATE_REQ 0x04220010
-#define HNF3_PSTATE_REQ 0x04230010
-#define HNF4_PSTATE_REQ 0x04240010
-#define HNF5_PSTATE_REQ 0x04250010
-#define HNF6_PSTATE_REQ 0x04260010
-#define HNF7_PSTATE_REQ 0x04270010
-#define HNFPSTAT_MASK (0xFFFFFFFFFFFFFFFC)
-#define HNFPSTAT_FAM 0x3
-#define HNFPSTAT_SFONLY 0x01
-
-static void hnf_pstate_req(u64 *ptr, u64 state)
-{
- int timeout = 1000;
- out_le64(ptr, (in_le64(ptr) & HNFPSTAT_MASK) | (state & 0x3));
- ptr++;
- /* checking if the transition is completed */
- while (timeout > 0) {
- if (((in_le64(ptr) & 0x0c) >> 2) == (state & 0x3))
- break;
- udelay(100);
- timeout--;
- }
-}
-
-void flush_l3_cache(void)
-{
- hnf_pstate_req((u64 *)HNF0_PSTATE_REQ, HNFPSTAT_SFONLY);
- hnf_pstate_req((u64 *)HNF1_PSTATE_REQ, HNFPSTAT_SFONLY);
- hnf_pstate_req((u64 *)HNF2_PSTATE_REQ, HNFPSTAT_SFONLY);
- hnf_pstate_req((u64 *)HNF3_PSTATE_REQ, HNFPSTAT_SFONLY);
- hnf_pstate_req((u64 *)HNF4_PSTATE_REQ, HNFPSTAT_SFONLY);
- hnf_pstate_req((u64 *)HNF5_PSTATE_REQ, HNFPSTAT_SFONLY);
- hnf_pstate_req((u64 *)HNF6_PSTATE_REQ, HNFPSTAT_SFONLY);
- hnf_pstate_req((u64 *)HNF7_PSTATE_REQ, HNFPSTAT_SFONLY);
- hnf_pstate_req((u64 *)HNF0_PSTATE_REQ, HNFPSTAT_FAM);
- hnf_pstate_req((u64 *)HNF1_PSTATE_REQ, HNFPSTAT_FAM);
- hnf_pstate_req((u64 *)HNF2_PSTATE_REQ, HNFPSTAT_FAM);
- hnf_pstate_req((u64 *)HNF3_PSTATE_REQ, HNFPSTAT_FAM);
- hnf_pstate_req((u64 *)HNF4_PSTATE_REQ, HNFPSTAT_FAM);
- hnf_pstate_req((u64 *)HNF5_PSTATE_REQ, HNFPSTAT_FAM);
- hnf_pstate_req((u64 *)HNF6_PSTATE_REQ, HNFPSTAT_FAM);
- hnf_pstate_req((u64 *)HNF7_PSTATE_REQ, HNFPSTAT_FAM);
-}
-
-/*
* This function is called from lib/board.c.
* It recreates MMU table in main memory. MMU and d-cache are enabled earlier.
* There is no need to disable d-cache for this operation.
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S
index c283787..886576e 100644
--- a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S
+++ b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S
@@ -100,6 +100,84 @@ ENTRY(lowlevel_init)
ret
ENDPROC(lowlevel_init)
+hnf_pstate_poll:
+ /* x0 has the desired status, return 0 for success, 1 for timeout
+ * clobber x1, x2, x3, x4, x6, x7
+ */
+ mov x1, x0
+ mov x7, #0 /* flag for timeout */
+ mrs x3, cntpct_el0 /* read timer */
+ add x3, x3, #1200 /* timeout after 100 microseconds */
+ mov x0, #0x18
+ movk x0, #0x420, lsl #16 /* HNF0_PSTATE_STATUS */
+ mov w6, #8 /* HN-F node count */
+1:
+ ldr x2, [x0]
+ cmp x2, x1 /* check status */
+ b.eq 2f
+ mrs x4, cntpct_el0
+ cmp x4, x3
+ b.ls 1b
+ mov x7, #1 /* timeout */
+ b 3f
+2:
+ add x0, x0, #0x10000 /* move to next node */
+ subs w6, w6, #1
+ cbnz w6, 1b
+3:
+ mov x0, x7
+ ret
+
+hnf_set_pstate:
+ /* x0 has the desired state, clobber x1, x2, x6 */
+ mov x1, x0
+ /* power state to SFONLY */
+ mov w6, #8 /* HN-F node count */
+ mov x0, #0x10
+ movk x0, #0x420, lsl #16 /* HNF0_PSTATE_REQ */
+1: /* set pstate to sfonly */
+ ldr x2, [x0]
+ and x2, x2, #0xfffffffffffffffc /* & HNFPSTAT_MASK */
+ orr x2, x2, x1
+ str x2, [x0]
+ add x0, x0, #0x10000 /* move to next node */
+ subs w6, w6, #1
+ cbnz w6, 1b
+
+ ret
+
+ENTRY(__asm_flush_l3_cache)
+ /*
+ * Return status in x0
+ * success 0
+ * tmeout 1 for setting SFONLY, 2 for FAM, 3 for both
+ */
+ mov x29, lr
+ mov x8, #0
+
+ dsb sy
+ mov x0, #0x1 /* HNFPSTAT_SFONLY */
+ bl hnf_set_pstate
+
+ mov x0, #0x4 /* SFONLY status */
+ bl hnf_pstate_poll
+ cbz x0, 1f
+ mov x8, #1 /* timeout */
+1:
+ dsb sy
+ mov x0, #0x3 /* HNFPSTAT_FAM */
+ bl hnf_set_pstate
+
+ mov x0, #0xc /* FAM status */
+ bl hnf_pstate_poll
+ cbz x0, 1f
+ add x8, x8, #0x2
+1:
+ mov x0, x8
+ mov lr, x29
+ ret
+ENDPROC(__asm_flush_l3_cache)
+
/* Keep literals not used by the secondary boot code outside it */
.ltorg