splash: Introduce default_splash_locations
[oweals/u-boot.git] / arch / arm / mach-uniphier / arm32 / cache_uniphier.c
1 /*
2  * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <linux/io.h>
9 #include <asm/armv7.h>
10
11 #include "ssc-regs.h"
12
13 #ifdef CONFIG_UNIPHIER_L2CACHE_ON
14 static void uniphier_cache_sync(void)
15 {
16         writel(SSCOPE_CM_SYNC, SSCOPE); /* drain internal buffers */
17         readl(SSCOPE); /* need a read back to confirm */
18 }
19
20 static void uniphier_cache_maint_all(u32 operation)
21 {
22         /* try until the command is successfully set */
23         do {
24                 writel(SSCOQM_S_ALL | SSCOQM_CE | operation, SSCOQM);
25         } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
26
27         /* wait until the operation is completed */
28         while (readl(SSCOLPQS) != SSCOLPQS_EF)
29                 ;
30
31         /* clear the complete notification flag */
32         writel(SSCOLPQS_EF, SSCOLPQS);
33
34         uniphier_cache_sync();
35 }
36
37 void v7_outer_cache_flush_all(void)
38 {
39         uniphier_cache_maint_all(SSCOQM_CM_WB_INV);
40 }
41
42 void v7_outer_cache_inval_all(void)
43 {
44         uniphier_cache_maint_all(SSCOQM_CM_INV);
45 }
46
47 static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation)
48 {
49         /* try until the command is successfully set */
50         do {
51                 writel(SSCOQM_S_ADDRESS | SSCOQM_CE | operation, SSCOQM);
52                 writel(start, SSCOQAD);
53                 writel(size, SSCOQSZ);
54
55         } while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
56
57         /* wait until the operation is completed */
58         while (readl(SSCOLPQS) != SSCOLPQS_EF)
59                 ;
60
61         /* clear the complete notification flag */
62         writel(SSCOLPQS_EF, SSCOLPQS);
63 }
64
65 static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
66 {
67         u32 size;
68
69         /*
70          * If start address is not aligned to cache-line,
71          * do cache operation for the first cache-line
72          */
73         start = start & ~(SSC_LINE_SIZE - 1);
74
75         size = end - start;
76
77         if (unlikely(size >= (u32)(-SSC_LINE_SIZE))) {
78                 /* this means cache operation for all range */
79                 uniphier_cache_maint_all(operation);
80                 return;
81         }
82
83         /*
84          * If end address is not aligned to cache-line,
85          * do cache operation for the last cache-line
86          */
87         size = ALIGN(size, SSC_LINE_SIZE);
88
89         while (size) {
90                 u32 chunk_size = size > SSC_RANGE_OP_MAX_SIZE ?
91                                                 SSC_RANGE_OP_MAX_SIZE : size;
92                 __uniphier_cache_maint_range(start, chunk_size, operation);
93
94                 start += chunk_size;
95                 size -= chunk_size;
96         }
97
98         uniphier_cache_sync();
99 }
100
101 void v7_outer_cache_flush_range(u32 start, u32 end)
102 {
103         uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV);
104 }
105
106 void v7_outer_cache_inval_range(u32 start, u32 end)
107 {
108         if (start & (SSC_LINE_SIZE - 1)) {
109                 start &= ~(SSC_LINE_SIZE - 1);
110                 __uniphier_cache_maint_range(start, SSC_LINE_SIZE,
111                                              SSCOQM_CM_WB_INV);
112                 start += SSC_LINE_SIZE;
113         }
114
115         if (start >= end) {
116                 uniphier_cache_sync();
117                 return;
118         }
119
120         if (end & (SSC_LINE_SIZE - 1)) {
121                 end &= ~(SSC_LINE_SIZE - 1);
122                 __uniphier_cache_maint_range(end, SSC_LINE_SIZE,
123                                              SSCOQM_CM_WB_INV);
124         }
125
126         if (start >= end) {
127                 uniphier_cache_sync();
128                 return;
129         }
130
131         uniphier_cache_maint_range(start, end, SSCOQM_CM_INV);
132 }
133
134 void v7_outer_cache_enable(void)
135 {
136         u32 tmp;
137
138         writel(U32_MAX, SSCLPDAWCR);    /* activate all ways */
139         tmp = readl(SSCC);
140         tmp |= SSCC_ON;
141         writel(tmp, SSCC);
142 }
143 #endif
144
145 void v7_outer_cache_disable(void)
146 {
147         u32 tmp;
148         tmp = readl(SSCC);
149         tmp &= ~SSCC_ON;
150         writel(tmp, SSCC);
151 }
152
153 void enable_caches(void)
154 {
155         dcache_enable();
156 }