]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/armv7/uniphier/cache_uniphier.c
Merge branch 'karo-tx-uboot' into kc-merge
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / uniphier / cache_uniphier.c
1 /*
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
14 static 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
32 void v7_outer_cache_flush_all(void)
33 {
34         uniphier_cache_maint_all(SSCOQM_CM_WB_INV);
35 }
36
37 void v7_outer_cache_inval_all(void)
38 {
39         uniphier_cache_maint_all(SSCOQM_CM_INV);
40 }
41
42 static 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
60 static 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
95 void v7_outer_cache_flush_range(u32 start, u32 end)
96 {
97         uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV);
98 }
99
100 void v7_outer_cache_inval_range(u32 start, u32 end)
101 {
102         uniphier_cache_maint_range(start, end, SSCOQM_CM_INV);
103 }
104
105 void 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
114 void v7_outer_cache_disable(void)
115 {
116         u32 tmp;
117         tmp = readl(SSCC);
118         tmp &= ~SSCC_ON;
119         writel(tmp, SSCC);
120 }
121
122 void wakeup_secondary(void);
123
124 void 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 }