blob: e47f977fe5a50e368c39c4136da5e2375305dd60 [file] [log] [blame]
Masahiro Yamadabb2ff9d2014-10-03 19:21:06 +09001/*
2 * Copyright (C) 2012-2014 Panasonic Corporation
3 * Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
9#include <asm/io.h>
10#include <asm/armv7.h>
11#include <asm/arch/ssc-regs.h>
12
13#ifdef CONFIG_UNIPHIER_L2CACHE_ON
14static void uniphier_cache_maint_all(u32 operation)
15{
16 /* try until the command is successfully set */
17 do {
18 writel(SSCOQM_S_ALL | SSCOQM_CE | operation, SSCOQM);
19 } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
20
21 /* wait until the operation is completed */
22 while (readl(SSCOLPQS) != SSCOLPQS_EF)
23 ;
24
25 /* clear the complete notification flag */
26 writel(SSCOLPQS_EF, SSCOLPQS);
27
28 writel(SSCOPE_CM_SYNC, SSCOPE); /* drain internal buffers */
29 readl(SSCOPE); /* need a read back to confirm */
30}
31
32void v7_outer_cache_flush_all(void)
33{
34 uniphier_cache_maint_all(SSCOQM_CM_WB_INV);
35}
36
37void v7_outer_cache_inval_all(void)
38{
39 uniphier_cache_maint_all(SSCOQM_CM_INV);
40}
41
42static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation)
43{
44 /* try until the command is successfully set */
45 do {
46 writel(SSCOQM_S_ADDRESS | SSCOQM_CE | operation, SSCOQM);
47 writel(start, SSCOQAD);
48 writel(size, SSCOQSZ);
49
50 } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
51
52 /* wait until the operation is completed */
53 while (readl(SSCOLPQS) != SSCOLPQS_EF)
54 ;
55
56 /* clear the complete notification flag */
57 writel(SSCOLPQS_EF, SSCOLPQS);
58}
59
60static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
61{
62 u32 size;
63
64 /*
65 * If start address is not aligned to cache-line,
66 * do cache operation for the first cache-line
67 */
68 start = start & ~(SSC_LINE_SIZE - 1);
69
70 if (start == 0 && end >= (u32)(-SSC_LINE_SIZE)) {
71 /* this means cache operation for all range */
72 uniphier_cache_maint_all(operation);
73 return;
74 }
75
76 /*
77 * If end address is not aligned to cache-line,
78 * do cache operation for the last cache-line
79 */
80 size = (end - start + SSC_LINE_SIZE - 1) & ~(SSC_LINE_SIZE - 1);
81
82 while (size) {
83 u32 chunk_size = size > SSC_RANGE_OP_MAX_SIZE ?
84 SSC_RANGE_OP_MAX_SIZE : size;
85 __uniphier_cache_maint_range(start, chunk_size, operation);
86
87 start += chunk_size;
88 size -= chunk_size;
89 }
90
91 writel(SSCOPE_CM_SYNC, SSCOPE); /* drain internal buffers */
92 readl(SSCOPE); /* need a read back to confirm */
93}
94
95void v7_outer_cache_flush_range(u32 start, u32 end)
96{
97 uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV);
98}
99
100void v7_outer_cache_inval_range(u32 start, u32 end)
101{
102 uniphier_cache_maint_range(start, end, SSCOQM_CM_INV);
103}
104
105void v7_outer_cache_enable(void)
106{
107 u32 tmp;
108 tmp = readl(SSCC);
109 tmp |= SSCC_ON;
110 writel(tmp, SSCC);
111}
112#endif
113
114void v7_outer_cache_disable(void)
115{
116 u32 tmp;
117 tmp = readl(SSCC);
118 tmp &= ~SSCC_ON;
119 writel(tmp, SSCC);
120}
121
122void wakeup_secondary(void);
123
124void enable_caches(void)
125{
126 uint32_t reg;
127
128#ifdef CONFIG_UNIPHIER_SMP
129 /*
130 * The secondary CPU must move to DDR,
131 * before L2 disable.
132 * On SPL, the Page Table is located on the L2.
133 */
134 wakeup_secondary();
135#endif
136 /*
137 * UniPhier SoCs must use L2 cache for init stack pointer.
138 * We disable L2 and L1 in this order.
139 * If CONFIG_SYS_DCACHE_OFF is not defined,
140 * caches are enabled again with a new page table.
141 */
142
143 /* L2 disable */
144 v7_outer_cache_disable();
145
146 /* L1 disable */
147 reg = get_cr();
148 reg &= ~(CR_C | CR_M);
149 set_cr(reg);
150
151#ifndef CONFIG_SYS_DCACHE_OFF
152 dcache_enable();
153#endif
154}