armadaxp.c revision 1.5 1 1.5 kiyohara /* $NetBSD: armadaxp.c,v 1.5 2013/12/23 03:19:43 kiyohara Exp $ */
2 1.1 rkujawa /*******************************************************************************
3 1.1 rkujawa Copyright (C) Marvell International Ltd. and its affiliates
4 1.1 rkujawa
5 1.1 rkujawa Developed by Semihalf
6 1.1 rkujawa
7 1.1 rkujawa ********************************************************************************
8 1.1 rkujawa Marvell BSD License
9 1.1 rkujawa
10 1.1 rkujawa If you received this File from Marvell, you may opt to use, redistribute and/or
11 1.1 rkujawa modify this File under the following licensing terms.
12 1.1 rkujawa Redistribution and use in source and binary forms, with or without modification,
13 1.1 rkujawa are permitted provided that the following conditions are met:
14 1.1 rkujawa
15 1.1 rkujawa * Redistributions of source code must retain the above copyright notice,
16 1.1 rkujawa this list of conditions and the following disclaimer.
17 1.1 rkujawa
18 1.1 rkujawa * Redistributions in binary form must reproduce the above copyright
19 1.1 rkujawa notice, this list of conditions and the following disclaimer in the
20 1.1 rkujawa documentation and/or other materials provided with the distribution.
21 1.1 rkujawa
22 1.1 rkujawa * Neither the name of Marvell nor the names of its contributors may be
23 1.1 rkujawa used to endorse or promote products derived from this software without
24 1.1 rkujawa specific prior written permission.
25 1.1 rkujawa
26 1.1 rkujawa THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27 1.1 rkujawa ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 1.1 rkujawa WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 1.1 rkujawa DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
30 1.1 rkujawa ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 1.1 rkujawa (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 1.1 rkujawa LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
33 1.1 rkujawa ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 1.1 rkujawa (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 1.1 rkujawa SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 1.1 rkujawa
37 1.1 rkujawa *******************************************************************************/
38 1.1 rkujawa
39 1.1 rkujawa #include <sys/cdefs.h>
40 1.5 kiyohara __KERNEL_RCSID(0, "$NetBSD: armadaxp.c,v 1.5 2013/12/23 03:19:43 kiyohara Exp $");
41 1.1 rkujawa
42 1.1 rkujawa #define _INTR_PRIVATE
43 1.1 rkujawa
44 1.1 rkujawa #include "opt_mvsoc.h"
45 1.1 rkujawa
46 1.1 rkujawa #include <sys/param.h>
47 1.1 rkujawa #include <sys/bus.h>
48 1.1 rkujawa
49 1.1 rkujawa #include <machine/intr.h>
50 1.1 rkujawa
51 1.1 rkujawa #include <arm/pic/picvar.h>
52 1.1 rkujawa #include <arm/pic/picvar.h>
53 1.1 rkujawa
54 1.1 rkujawa #include <arm/armreg.h>
55 1.1 rkujawa #include <arm/cpu.h>
56 1.1 rkujawa #include <arm/cpufunc.h>
57 1.1 rkujawa
58 1.1 rkujawa #include <arm/marvell/mvsocreg.h>
59 1.1 rkujawa #include <arm/marvell/mvsocvar.h>
60 1.3 kiyohara #include <arm/marvell/armadaxpreg.h>
61 1.1 rkujawa
62 1.1 rkujawa #include <dev/marvell/marvellreg.h>
63 1.1 rkujawa
64 1.1 rkujawa #define EXTRACT_CPU_FREQ_FIELD(sar) (((0x01 & (sar >> 52)) << 3) | \
65 1.1 rkujawa (0x07 & (sar >> 21)))
66 1.1 rkujawa #define EXTRACT_FAB_FREQ_FIELD(sar) (((0x01 & (sar >> 51)) << 4) | \
67 1.1 rkujawa (0x0F & (sar >> 24)))
68 1.1 rkujawa
69 1.1 rkujawa #define MPIC_WRITE(reg, val) (bus_space_write_4(&mvsoc_bs_tag, \
70 1.1 rkujawa mpic_handle, reg, val))
71 1.1 rkujawa #define MPIC_CPU_WRITE(reg, val) (bus_space_write_4(&mvsoc_bs_tag, \
72 1.1 rkujawa mpic_cpu_handle, reg, val))
73 1.1 rkujawa
74 1.1 rkujawa #define MPIC_READ(reg) (bus_space_read_4(&mvsoc_bs_tag, \
75 1.1 rkujawa mpic_handle, reg))
76 1.1 rkujawa #define MPIC_CPU_READ(reg) (bus_space_read_4(&mvsoc_bs_tag, \
77 1.1 rkujawa mpic_cpu_handle, reg))
78 1.1 rkujawa
79 1.1 rkujawa #define L2_WRITE(reg, val) (bus_space_write_4(&mvsoc_bs_tag, \
80 1.1 rkujawa l2_handle, reg, val))
81 1.1 rkujawa #define L2_READ(reg) (bus_space_read_4(&mvsoc_bs_tag, \
82 1.1 rkujawa l2_handle, reg))
83 1.1 rkujawa bus_space_handle_t mpic_cpu_handle;
84 1.1 rkujawa static bus_space_handle_t mpic_handle, l2_handle;
85 1.1 rkujawa int l2cache_state = 0;
86 1.1 rkujawa int iocc_state = 0;
87 1.5 kiyohara #define read_miscreg(r) (*(volatile uint32_t *)(misc_base + (r)))
88 1.5 kiyohara vaddr_t misc_base;
89 1.1 rkujawa
90 1.1 rkujawa extern void (*mvsoc_intr_init)(void);
91 1.1 rkujawa static void armadaxp_intr_init(void);
92 1.1 rkujawa
93 1.1 rkujawa static void armadaxp_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
94 1.1 rkujawa static void armadaxp_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
95 1.1 rkujawa static void armadaxp_pic_establish_irq(struct pic_softc *, struct intrsource *);
96 1.4 kiyohara static void armadaxp_pic_set_priority(struct pic_softc *, int);
97 1.1 rkujawa
98 1.4 kiyohara static int armadaxp_find_pending_irqs(void);
99 1.4 kiyohara static void armadaxp_pic_block_irq(struct pic_softc *, size_t);
100 1.1 rkujawa void armadaxp_io_coherency_init(void);
101 1.3 kiyohara int armadaxp_l2_init(bus_addr_t);
102 1.1 rkujawa
103 1.1 rkujawa struct vco_freq_ratio {
104 1.1 rkujawa uint8_t vco_cpu; /* VCO to CLK0(CPU) clock ratio */
105 1.1 rkujawa uint8_t vco_l2c; /* VCO to NB(L2 cache) clock ratio */
106 1.1 rkujawa uint8_t vco_hcl; /* VCO to HCLK(DDR controller) clock ratio */
107 1.1 rkujawa uint8_t vco_ddr; /* VCO to DR(DDR memory) clock ratio */
108 1.1 rkujawa };
109 1.1 rkujawa
110 1.1 rkujawa static struct vco_freq_ratio freq_conf_table[] = {
111 1.1 rkujawa /*00*/ { 1, 1, 4, 2 },
112 1.1 rkujawa /*01*/ { 1, 2, 2, 2 },
113 1.1 rkujawa /*02*/ { 2, 2, 6, 3 },
114 1.1 rkujawa /*03*/ { 2, 2, 3, 3 },
115 1.1 rkujawa /*04*/ { 1, 2, 3, 3 },
116 1.1 rkujawa /*05*/ { 1, 2, 4, 2 },
117 1.1 rkujawa /*06*/ { 1, 1, 2, 2 },
118 1.1 rkujawa /*07*/ { 2, 3, 6, 6 },
119 1.1 rkujawa /*08*/ { 2, 3, 5, 5 },
120 1.1 rkujawa /*09*/ { 1, 2, 6, 3 },
121 1.1 rkujawa /*10*/ { 2, 4, 10, 5 },
122 1.1 rkujawa /*11*/ { 1, 3, 6, 6 },
123 1.1 rkujawa /*12*/ { 1, 2, 5, 5 },
124 1.1 rkujawa /*13*/ { 1, 3, 6, 3 },
125 1.1 rkujawa /*14*/ { 1, 2, 5, 5 },
126 1.1 rkujawa /*15*/ { 2, 2, 5, 5 },
127 1.1 rkujawa /*16*/ { 1, 1, 3, 3 },
128 1.1 rkujawa /*17*/ { 2, 5, 10, 10 },
129 1.1 rkujawa /*18*/ { 1, 3, 8, 4 },
130 1.1 rkujawa /*19*/ { 1, 1, 2, 1 },
131 1.1 rkujawa /*20*/ { 2, 3, 6, 3 },
132 1.1 rkujawa /*21*/ { 1, 2, 8, 4 },
133 1.1 rkujawa /*22*/ { 2, 5, 10, 5 }
134 1.1 rkujawa };
135 1.1 rkujawa
136 1.1 rkujawa static uint16_t cpu_clock_table[] = {
137 1.1 rkujawa 1000, 1066, 1200, 1333, 1500, 1666, 1800, 2000, 600, 667, 800, 1600,
138 1.1 rkujawa 2133, 2200, 2400 };
139 1.1 rkujawa
140 1.1 rkujawa static struct pic_ops armadaxp_picops = {
141 1.1 rkujawa .pic_unblock_irqs = armadaxp_pic_unblock_irqs,
142 1.1 rkujawa .pic_block_irqs = armadaxp_pic_block_irqs,
143 1.1 rkujawa .pic_establish_irq = armadaxp_pic_establish_irq,
144 1.4 kiyohara .pic_set_priority = armadaxp_pic_set_priority,
145 1.1 rkujawa };
146 1.1 rkujawa
147 1.1 rkujawa static struct pic_softc armadaxp_pic = {
148 1.1 rkujawa .pic_ops = &armadaxp_picops,
149 1.1 rkujawa .pic_name = "armadaxp",
150 1.1 rkujawa };
151 1.1 rkujawa
152 1.1 rkujawa /*
153 1.1 rkujawa * armadaxp_intr_bootstrap:
154 1.1 rkujawa *
155 1.1 rkujawa * Initialize the rest of the interrupt subsystem, making it
156 1.1 rkujawa * ready to handle interrupts from devices.
157 1.1 rkujawa */
158 1.1 rkujawa void
159 1.3 kiyohara armadaxp_intr_bootstrap(bus_addr_t pbase)
160 1.1 rkujawa {
161 1.1 rkujawa int i;
162 1.1 rkujawa
163 1.1 rkujawa /* Map MPIC base and MPIC percpu base registers */
164 1.3 kiyohara if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_BASE,
165 1.3 kiyohara 0x500, 0, &mpic_handle) != 0)
166 1.1 rkujawa panic("%s: Could not map MPIC registers", __func__);
167 1.3 kiyohara if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_CPU_BASE,
168 1.3 kiyohara 0x800, 0, &mpic_cpu_handle) != 0)
169 1.1 rkujawa panic("%s: Could not map MPIC percpu registers", __func__);
170 1.1 rkujawa
171 1.1 rkujawa /* Disable all interrupts */
172 1.1 rkujawa for (i = 0; i < 116; i++)
173 1.1 rkujawa MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, i);
174 1.1 rkujawa
175 1.1 rkujawa mvsoc_intr_init = armadaxp_intr_init;
176 1.1 rkujawa }
177 1.1 rkujawa
178 1.1 rkujawa static void
179 1.1 rkujawa armadaxp_intr_init(void)
180 1.1 rkujawa {
181 1.1 rkujawa int ctrl;
182 1.1 rkujawa
183 1.1 rkujawa /* Get max interrupts */
184 1.1 rkujawa armadaxp_pic.pic_maxsources =
185 1.1 rkujawa ((MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL) >> 2) & 0x7FF);
186 1.1 rkujawa
187 1.1 rkujawa if (!armadaxp_pic.pic_maxsources)
188 1.1 rkujawa armadaxp_pic.pic_maxsources = 116;
189 1.1 rkujawa
190 1.1 rkujawa pic_add(&armadaxp_pic, 0);
191 1.1 rkujawa
192 1.1 rkujawa ctrl = MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL);
193 1.1 rkujawa /* Enable IRQ prioritization */
194 1.1 rkujawa ctrl |= (1 << 0);
195 1.1 rkujawa MPIC_WRITE(ARMADAXP_MLMB_MPIC_CTRL, ctrl);
196 1.4 kiyohara
197 1.4 kiyohara find_pending_irqs = armadaxp_find_pending_irqs;
198 1.1 rkujawa }
199 1.1 rkujawa
200 1.1 rkujawa static void
201 1.1 rkujawa armadaxp_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
202 1.1 rkujawa uint32_t irq_mask)
203 1.1 rkujawa {
204 1.1 rkujawa int n;
205 1.1 rkujawa
206 1.1 rkujawa while (irq_mask != 0) {
207 1.1 rkujawa n = ffs(irq_mask) - 1;
208 1.1 rkujawa KASSERT(pic->pic_maxsources >= n + irqbase);
209 1.1 rkujawa MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISE, n + irqbase);
210 1.1 rkujawa MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ICM, n + irqbase);
211 1.1 rkujawa if ((n + irqbase) == 0)
212 1.1 rkujawa MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_DOORBELL_MASK,
213 1.1 rkujawa 0xffffffff);
214 1.1 rkujawa irq_mask &= ~__BIT(n);
215 1.1 rkujawa }
216 1.1 rkujawa }
217 1.1 rkujawa
218 1.1 rkujawa static void
219 1.1 rkujawa armadaxp_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
220 1.1 rkujawa uint32_t irq_mask)
221 1.1 rkujawa {
222 1.1 rkujawa int n;
223 1.1 rkujawa
224 1.1 rkujawa while (irq_mask != 0) {
225 1.1 rkujawa n = ffs(irq_mask) - 1;
226 1.1 rkujawa KASSERT(pic->pic_maxsources >= n + irqbase);
227 1.1 rkujawa MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, n + irqbase);
228 1.1 rkujawa MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, n + irqbase);
229 1.1 rkujawa irq_mask &= ~__BIT(n);
230 1.1 rkujawa }
231 1.1 rkujawa }
232 1.1 rkujawa
233 1.1 rkujawa static void
234 1.1 rkujawa armadaxp_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
235 1.1 rkujawa {
236 1.1 rkujawa int tmp;
237 1.1 rkujawa KASSERT(pic->pic_maxsources >= is->is_irq);
238 1.1 rkujawa tmp = MPIC_READ(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4);
239 1.1 rkujawa /* Clear previous priority */
240 1.1 rkujawa tmp &= ~(0xf << MPIC_ISCR_SHIFT);
241 1.1 rkujawa MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4,
242 1.1 rkujawa tmp | (is->is_ipl << MPIC_ISCR_SHIFT));
243 1.1 rkujawa }
244 1.1 rkujawa
245 1.4 kiyohara static void
246 1.4 kiyohara armadaxp_pic_set_priority(struct pic_softc *pic, int ipl)
247 1.4 kiyohara {
248 1.4 kiyohara int ctp;
249 1.4 kiyohara
250 1.4 kiyohara ctp = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_CTP);
251 1.4 kiyohara ctp &= ~(0xf << MPIC_CTP_SHIFT);
252 1.4 kiyohara ctp |= (ipl << MPIC_CTP_SHIFT);
253 1.4 kiyohara MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_CTP, ctp);
254 1.4 kiyohara }
255 1.4 kiyohara
256 1.4 kiyohara static int
257 1.4 kiyohara armadaxp_find_pending_irqs(void)
258 1.1 rkujawa {
259 1.1 rkujawa struct intrsource *is;
260 1.1 rkujawa int irq;
261 1.1 rkujawa
262 1.1 rkujawa irq = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_IIACK) & 0x3ff;
263 1.1 rkujawa
264 1.1 rkujawa /* Is it a spurious interrupt ?*/
265 1.1 rkujawa if (irq == 0x3ff)
266 1.4 kiyohara return 0;
267 1.1 rkujawa is = armadaxp_pic.pic_sources[irq];
268 1.4 kiyohara if (is == NULL) {
269 1.4 kiyohara printf("stray interrupt: %d\n", irq);
270 1.4 kiyohara return 0;
271 1.1 rkujawa }
272 1.4 kiyohara
273 1.4 kiyohara armadaxp_pic_block_irq(&armadaxp_pic, irq);
274 1.4 kiyohara pic_mark_pending(&armadaxp_pic, irq);
275 1.4 kiyohara
276 1.4 kiyohara return is->is_ipl;
277 1.4 kiyohara }
278 1.4 kiyohara
279 1.4 kiyohara static void
280 1.4 kiyohara armadaxp_pic_block_irq(struct pic_softc *pic, size_t irq)
281 1.4 kiyohara {
282 1.4 kiyohara
283 1.4 kiyohara KASSERT(pic->pic_maxsources >= irq);
284 1.4 kiyohara MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, irq);
285 1.4 kiyohara MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, irq);
286 1.1 rkujawa }
287 1.1 rkujawa
288 1.1 rkujawa /*
289 1.1 rkujawa * Clock functions
290 1.1 rkujawa */
291 1.1 rkujawa
292 1.1 rkujawa void
293 1.1 rkujawa armadaxp_getclks(void)
294 1.1 rkujawa {
295 1.1 rkujawa uint64_t sar_reg;
296 1.1 rkujawa uint8_t sar_cpu_freq, sar_fab_freq, array_size;
297 1.1 rkujawa
298 1.1 rkujawa if (cputype == CPU_ID_MV88SV584X_V7)
299 1.1 rkujawa mvTclk = 250000000; /* 250 MHz */
300 1.1 rkujawa else
301 1.1 rkujawa mvTclk = 200000000; /* 200 MHz */
302 1.1 rkujawa
303 1.1 rkujawa sar_reg = (read_miscreg(ARMADAXP_MISC_SAR_HI) << 31) |
304 1.1 rkujawa read_miscreg(ARMADAXP_MISC_SAR_LO);
305 1.1 rkujawa
306 1.1 rkujawa sar_cpu_freq = EXTRACT_CPU_FREQ_FIELD(sar_reg);
307 1.1 rkujawa sar_fab_freq = EXTRACT_FAB_FREQ_FIELD(sar_reg);
308 1.1 rkujawa
309 1.1 rkujawa /* Check if CPU frequency field has correct value */
310 1.1 rkujawa array_size = sizeof(cpu_clock_table) / sizeof(cpu_clock_table[0]);
311 1.1 rkujawa if (sar_cpu_freq >= array_size)
312 1.1 rkujawa panic("Reserved value in cpu frequency configuration field: "
313 1.1 rkujawa "%d", sar_cpu_freq);
314 1.1 rkujawa
315 1.1 rkujawa /* Check if fabric frequency field has correct value */
316 1.1 rkujawa array_size = sizeof(freq_conf_table) / sizeof(freq_conf_table[0]);
317 1.1 rkujawa if (sar_fab_freq >= array_size)
318 1.1 rkujawa panic("Reserved value in fabric frequency configuration field: "
319 1.1 rkujawa "%d", sar_fab_freq);
320 1.1 rkujawa
321 1.1 rkujawa /* Get CPU clock frequency */
322 1.1 rkujawa mvPclk = cpu_clock_table[sar_cpu_freq] *
323 1.1 rkujawa freq_conf_table[sar_fab_freq].vco_cpu;
324 1.1 rkujawa
325 1.1 rkujawa /* Get L2CLK clock frequency and use as system clock (mvSysclk) */
326 1.1 rkujawa mvSysclk = mvPclk / freq_conf_table[sar_fab_freq].vco_l2c;
327 1.1 rkujawa
328 1.1 rkujawa /* Round mvSysclk value to integer MHz */
329 1.1 rkujawa if (((mvPclk % freq_conf_table[sar_fab_freq].vco_l2c) * 10 /
330 1.1 rkujawa freq_conf_table[sar_fab_freq].vco_l2c) >= 5)
331 1.1 rkujawa mvSysclk++;
332 1.1 rkujawa
333 1.1 rkujawa mvPclk = mvPclk * 1000000;
334 1.1 rkujawa mvSysclk = mvSysclk * 1000000;
335 1.1 rkujawa }
336 1.1 rkujawa
337 1.1 rkujawa /*
338 1.1 rkujawa * L2 Cache initialization
339 1.1 rkujawa */
340 1.1 rkujawa
341 1.1 rkujawa int
342 1.3 kiyohara armadaxp_l2_init(bus_addr_t pbase)
343 1.1 rkujawa {
344 1.1 rkujawa u_int32_t reg;
345 1.1 rkujawa int ret;
346 1.1 rkujawa
347 1.1 rkujawa /* Map L2 space */
348 1.3 kiyohara ret = bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_L2_BASE,
349 1.3 kiyohara 0x1000, 0, &l2_handle);
350 1.1 rkujawa if (ret) {
351 1.1 rkujawa printf("%s: Cannot map L2 register space, ret:%d\n",
352 1.1 rkujawa __func__, ret);
353 1.1 rkujawa return (-1);
354 1.1 rkujawa }
355 1.1 rkujawa
356 1.1 rkujawa /* Set L2 policy */
357 1.1 rkujawa reg = L2_READ(ARMADAXP_L2_AUX_CTRL);
358 1.1 rkujawa reg &= ~(L2_WBWT_MODE_MASK);
359 1.1 rkujawa reg &= ~(L2_REP_STRAT_MASK);
360 1.1 rkujawa reg |= L2_REP_STRAT_SEMIPLRU;
361 1.1 rkujawa L2_WRITE(ARMADAXP_L2_AUX_CTRL, reg);
362 1.1 rkujawa
363 1.1 rkujawa /* Invalidate L2 cache */
364 1.1 rkujawa L2_WRITE(ARMADAXP_L2_INV_WAY, L2_ALL_WAYS);
365 1.1 rkujawa
366 1.1 rkujawa /* Clear pending L2 interrupts */
367 1.1 rkujawa L2_WRITE(ARMADAXP_L2_INT_CAUSE, 0x1ff);
368 1.1 rkujawa
369 1.1 rkujawa /* Enable Cache and TLB maintenance broadcast */
370 1.1 rkujawa __asm__ __volatile__ ("mrc p15, 1, %0, c15, c2, 0" : "=r"(reg));
371 1.1 rkujawa reg |= (1 << 8);
372 1.1 rkujawa __asm__ __volatile__ ("mcr p15, 1, %0, c15, c2, 0" : :"r"(reg));
373 1.1 rkujawa
374 1.1 rkujawa /*
375 1.1 rkujawa * Set the Point of Coherency and Point of Unification to DRAM.
376 1.1 rkujawa * This is a reset value but anyway, configure this just in case.
377 1.1 rkujawa */
378 1.1 rkujawa reg = read_mlmbreg(ARMADAXP_L2_CFU);
379 1.1 rkujawa reg |= (1 << 17) | (1 << 18);
380 1.1 rkujawa write_mlmbreg(ARMADAXP_L2_CFU, reg);
381 1.1 rkujawa
382 1.1 rkujawa /* Enable L2 cache */
383 1.1 rkujawa reg = L2_READ(ARMADAXP_L2_CTRL);
384 1.1 rkujawa L2_WRITE(ARMADAXP_L2_CTRL, reg | L2_ENABLE);
385 1.1 rkujawa
386 1.1 rkujawa /* Mark as enabled */
387 1.1 rkujawa l2cache_state = 1;
388 1.1 rkujawa
389 1.1 rkujawa #ifdef DEBUG
390 1.1 rkujawa /* Configure and enable counter */
391 1.1 rkujawa L2_WRITE(ARMADAXP_L2_CNTR_CONF(0), 0xf0000 | (4 << 2));
392 1.1 rkujawa L2_WRITE(ARMADAXP_L2_CNTR_CONF(1), 0xf0000 | (2 << 2));
393 1.1 rkujawa L2_WRITE(ARMADAXP_L2_CNTR_CTRL, 0x303);
394 1.1 rkujawa #endif
395 1.1 rkujawa
396 1.1 rkujawa return (0);
397 1.1 rkujawa }
398 1.1 rkujawa
399 1.1 rkujawa void
400 1.1 rkujawa armadaxp_io_coherency_init(void)
401 1.1 rkujawa {
402 1.1 rkujawa uint32_t reg;
403 1.1 rkujawa
404 1.1 rkujawa /* set CIB read snoop command to ReadUnique */
405 1.1 rkujawa reg = read_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG);
406 1.1 rkujawa reg &= ~(7 << 16);
407 1.1 rkujawa reg |= (7 << 16);
408 1.1 rkujawa write_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG, reg);
409 1.1 rkujawa /* enable CPUs in SMP group on Fabric coherency */
410 1.1 rkujawa reg = read_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CTRL);
411 1.1 rkujawa reg &= ~(0x3 << 24);
412 1.1 rkujawa reg |= (1 << 24);
413 1.1 rkujawa write_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CTRL, reg);
414 1.1 rkujawa
415 1.1 rkujawa reg = read_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CFG);
416 1.1 rkujawa reg &= ~(0x3 << 24);
417 1.1 rkujawa reg |= (1 << 24);
418 1.1 rkujawa write_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CFG, reg);
419 1.1 rkujawa
420 1.1 rkujawa /* Mark as enabled */
421 1.1 rkujawa iocc_state = 1;
422 1.1 rkujawa }
423