armadaxp.c revision 1.12 1 /* $NetBSD: armadaxp.c,v 1.12 2015/05/03 06:29:31 hsuenaga Exp $ */
2 /*******************************************************************************
3 Copyright (C) Marvell International Ltd. and its affiliates
4
5 Developed by Semihalf
6
7 ********************************************************************************
8 Marvell BSD License
9
10 If you received this File from Marvell, you may opt to use, redistribute and/or
11 modify this File under the following licensing terms.
12 Redistribution and use in source and binary forms, with or without modification,
13 are permitted provided that the following conditions are met:
14
15 * Redistributions of source code must retain the above copyright notice,
16 this list of conditions and the following disclaimer.
17
18 * Redistributions in binary form must reproduce the above copyright
19 notice, this list of conditions and the following disclaimer in the
20 documentation and/or other materials provided with the distribution.
21
22 * Neither the name of Marvell nor the names of its contributors may be
23 used to endorse or promote products derived from this software without
24 specific prior written permission.
25
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
30 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
33 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
37 *******************************************************************************/
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: armadaxp.c,v 1.12 2015/05/03 06:29:31 hsuenaga Exp $");
41
42 #define _INTR_PRIVATE
43
44 #include "opt_mvsoc.h"
45
46 #include <sys/param.h>
47 #include <sys/bus.h>
48
49 #include <machine/intr.h>
50
51 #include <arm/pic/picvar.h>
52 #include <arm/pic/picvar.h>
53
54 #include <arm/armreg.h>
55 #include <arm/cpu.h>
56 #include <arm/cpufunc.h>
57
58 #include <arm/marvell/mvsocreg.h>
59 #include <arm/marvell/mvsocvar.h>
60 #include <arm/marvell/armadaxpreg.h>
61 #include <arm/marvell/armadaxpvar.h>
62
63 #include <dev/marvell/marvellreg.h>
64
65 #define EXTRACT_XP_CPU_FREQ_FIELD(sar) (((0x01 & (sar >> 52)) << 3) | \
66 (0x07 & (sar >> 21)))
67 #define EXTRACT_XP_FAB_FREQ_FIELD(sar) (((0x01 & (sar >> 51)) << 4) | \
68 (0x0F & (sar >> 24)))
69 #define EXTRACT_370_CPU_FREQ_FIELD(sar) ((sar >> 11) & 0xf)
70 #define EXTRACT_370_FAB_FREQ_FIELD(sar) ((sar >> 15) & 0x1f)
71
72 #define MPIC_WRITE(reg, val) (bus_space_write_4(&mvsoc_bs_tag, \
73 mpic_handle, reg, val))
74 #define MPIC_CPU_WRITE(reg, val) (bus_space_write_4(&mvsoc_bs_tag, \
75 mpic_cpu_handle, reg, val))
76
77 #define MPIC_READ(reg) (bus_space_read_4(&mvsoc_bs_tag, \
78 mpic_handle, reg))
79 #define MPIC_CPU_READ(reg) (bus_space_read_4(&mvsoc_bs_tag, \
80 mpic_cpu_handle, reg))
81
82 #define L2_WRITE(reg, val) (bus_space_write_4(&mvsoc_bs_tag, \
83 l2_handle, reg, val))
84 #define L2_READ(reg) (bus_space_read_4(&mvsoc_bs_tag, \
85 l2_handle, reg))
86 bus_space_handle_t mpic_cpu_handle;
87 static bus_space_handle_t mpic_handle, l2_handle;
88 int l2cache_state = 0;
89 int iocc_state = 0;
90 #define read_miscreg(r) (*(volatile uint32_t *)(misc_base + (r)))
91 vaddr_t misc_base;
92
93 extern void (*mvsoc_intr_init)(void);
94 static void armadaxp_intr_init(void);
95
96 static void armadaxp_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
97 static void armadaxp_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
98 static void armadaxp_pic_establish_irq(struct pic_softc *, struct intrsource *);
99 static void armadaxp_pic_set_priority(struct pic_softc *, int);
100
101 static int armadaxp_find_pending_irqs(void);
102 static void armadaxp_pic_block_irq(struct pic_softc *, size_t);
103
104 struct vco_freq_ratio {
105 uint8_t vco_cpu; /* VCO to CLK0(CPU) clock ratio */
106 uint8_t vco_l2c; /* VCO to NB(L2 cache) clock ratio */
107 uint8_t vco_hcl; /* VCO to HCLK(DDR controller) clock ratio */
108 uint8_t vco_ddr; /* VCO to DR(DDR memory) clock ratio */
109 };
110
111 static struct vco_freq_ratio freq_conf_table[] = {
112 /*00*/ { 1, 1, 4, 2 },
113 /*01*/ { 1, 2, 2, 2 },
114 /*02*/ { 2, 2, 6, 3 },
115 /*03*/ { 2, 2, 3, 3 },
116 /*04*/ { 1, 2, 3, 3 },
117 /*05*/ { 1, 2, 4, 2 },
118 /*06*/ { 1, 1, 2, 2 },
119 /*07*/ { 2, 3, 6, 6 },
120 /*08*/ { 2, 3, 5, 5 },
121 /*09*/ { 1, 2, 6, 3 },
122 /*10*/ { 2, 4, 10, 5 },
123 /*11*/ { 1, 3, 6, 6 },
124 /*12*/ { 1, 2, 5, 5 },
125 /*13*/ { 1, 3, 6, 3 },
126 /*14*/ { 1, 2, 5, 5 },
127 /*15*/ { 2, 2, 5, 5 },
128 /*16*/ { 1, 1, 3, 3 },
129 /*17*/ { 2, 5, 10, 10 },
130 /*18*/ { 1, 3, 8, 4 },
131 /*19*/ { 1, 1, 2, 1 },
132 /*20*/ { 2, 3, 6, 3 },
133 /*21*/ { 1, 2, 8, 4 },
134 /*22*/ { 2, 5, 10, 5 }
135 };
136
137 static uint16_t clock_table_xp[] = {
138 1000, 1066, 1200, 1333, 1500, 1666, 1800, 2000,
139 600, 667, 800, 1600, 2133, 2200, 2400
140 };
141 static uint16_t clock_table_370[] = {
142 400, 533, 667, 800, 1000, 1067, 1200, 1333,
143 1500, 1600, 1667, 1800, 2000, 333, 600, 900,
144 0
145 };
146
147 static struct pic_ops armadaxp_picops = {
148 .pic_unblock_irqs = armadaxp_pic_unblock_irqs,
149 .pic_block_irqs = armadaxp_pic_block_irqs,
150 .pic_establish_irq = armadaxp_pic_establish_irq,
151 .pic_set_priority = armadaxp_pic_set_priority,
152 };
153
154 static struct pic_softc armadaxp_pic = {
155 .pic_ops = &armadaxp_picops,
156 .pic_name = "armadaxp",
157 };
158
159 static struct {
160 bus_size_t offset;
161 uint32_t bits;
162 } clkgatings[]= {
163 { ARMADAXP_GBE3_BASE, (1 << 1) },
164 { ARMADAXP_GBE2_BASE, (1 << 2) },
165 { ARMADAXP_GBE1_BASE, (1 << 3) },
166 { ARMADAXP_GBE0_BASE, (1 << 4) },
167 { MVSOC_PEX_BASE, (1 << 5) },
168 { ARMADAXP_PEX01_BASE, (1 << 6) },
169 { ARMADAXP_PEX02_BASE, (1 << 7) },
170 { ARMADAXP_PEX03_BASE, (1 << 8) },
171 { ARMADAXP_PEX10_BASE, (1 << 9) },
172 { ARMADAXP_PEX11_BASE, (1 << 10) },
173 { ARMADAXP_PEX12_BASE, (1 << 11) },
174 { ARMADAXP_PEX13_BASE, (1 << 12) },
175 #if 0
176 { NetA, (1 << 13) },
177 #endif
178 { ARMADAXP_SATAHC_BASE, (1 << 14) | (1 << 15) | (1 << 29) | (1 << 30) },
179 { ARMADAXP_LCD_BASE, (1 << 16) },
180 { ARMADAXP_SDIO_BASE, (1 << 17) },
181 { ARMADAXP_USB1_BASE, (1 << 19) },
182 { ARMADAXP_USB2_BASE, (1 << 20) },
183 { ARMADAXP_PEX2_BASE, (1 << 26) },
184 { ARMADAXP_PEX3_BASE, (1 << 27) },
185 #if 0
186 { DDR, (1 << 28) },
187 #endif
188 };
189
190 /*
191 * armadaxp_intr_bootstrap:
192 *
193 * Initialize the rest of the interrupt subsystem, making it
194 * ready to handle interrupts from devices.
195 */
196 void
197 armadaxp_intr_bootstrap(bus_addr_t pbase)
198 {
199 int i;
200
201 /* Map MPIC base and MPIC percpu base registers */
202 if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_BASE,
203 0x500, 0, &mpic_handle) != 0)
204 panic("%s: Could not map MPIC registers", __func__);
205 if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_CPU_BASE,
206 0x800, 0, &mpic_cpu_handle) != 0)
207 panic("%s: Could not map MPIC percpu registers", __func__);
208
209 /* Disable all interrupts */
210 for (i = 0; i < 116; i++)
211 MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, i);
212
213 mvsoc_intr_init = armadaxp_intr_init;
214 }
215
216 static void
217 armadaxp_intr_init(void)
218 {
219 int ctrl;
220
221 /* Get max interrupts */
222 armadaxp_pic.pic_maxsources =
223 ((MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL) >> 2) & 0x7FF);
224
225 if (!armadaxp_pic.pic_maxsources)
226 armadaxp_pic.pic_maxsources = 116;
227
228 pic_add(&armadaxp_pic, 0);
229
230 ctrl = MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL);
231 /* Enable IRQ prioritization */
232 ctrl |= (1 << 0);
233 MPIC_WRITE(ARMADAXP_MLMB_MPIC_CTRL, ctrl);
234
235 find_pending_irqs = armadaxp_find_pending_irqs;
236 }
237
238 static void
239 armadaxp_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
240 uint32_t irq_mask)
241 {
242 int n;
243
244 while (irq_mask != 0) {
245 n = ffs(irq_mask) - 1;
246 KASSERT(pic->pic_maxsources >= n + irqbase);
247 MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISE, n + irqbase);
248 MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ICM, n + irqbase);
249 if ((n + irqbase) == 0)
250 MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_DOORBELL_MASK,
251 0xffffffff);
252 irq_mask &= ~__BIT(n);
253 }
254 }
255
256 static void
257 armadaxp_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
258 uint32_t irq_mask)
259 {
260 int n;
261
262 while (irq_mask != 0) {
263 n = ffs(irq_mask) - 1;
264 KASSERT(pic->pic_maxsources >= n + irqbase);
265 MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, n + irqbase);
266 MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, n + irqbase);
267 irq_mask &= ~__BIT(n);
268 }
269 }
270
271 static void
272 armadaxp_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
273 {
274 int tmp;
275 KASSERT(pic->pic_maxsources >= is->is_irq);
276 tmp = MPIC_READ(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4);
277 /* Clear previous priority */
278 tmp &= ~(0xf << MPIC_ISCR_SHIFT);
279 MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4,
280 tmp | (is->is_ipl << MPIC_ISCR_SHIFT));
281 }
282
283 static void
284 armadaxp_pic_set_priority(struct pic_softc *pic, int ipl)
285 {
286 int ctp;
287
288 ctp = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_CTP);
289 ctp &= ~(0xf << MPIC_CTP_SHIFT);
290 ctp |= (ipl << MPIC_CTP_SHIFT);
291 MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_CTP, ctp);
292 }
293
294 static int
295 armadaxp_find_pending_irqs(void)
296 {
297 struct intrsource *is;
298 int irq;
299
300 irq = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_IIACK) & 0x3ff;
301
302 /* Is it a spurious interrupt ?*/
303 if (irq == 0x3ff)
304 return 0;
305 is = armadaxp_pic.pic_sources[irq];
306 if (is == NULL) {
307 printf("stray interrupt: %d\n", irq);
308 return 0;
309 }
310
311 armadaxp_pic_block_irq(&armadaxp_pic, irq);
312 pic_mark_pending(&armadaxp_pic, irq);
313
314 return is->is_ipl;
315 }
316
317 static void
318 armadaxp_pic_block_irq(struct pic_softc *pic, size_t irq)
319 {
320
321 KASSERT(pic->pic_maxsources >= irq);
322 MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, irq);
323 MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, irq);
324 }
325
326 /*
327 * Clock functions
328 */
329
330 void
331 armadaxp_getclks(void)
332 {
333 uint64_t sar_reg;
334 uint8_t sar_cpu_freq, sar_fab_freq;
335
336 if (cputype == CPU_ID_MV88SV584X_V7)
337 mvTclk = 250000000; /* 250 MHz */
338 else
339 mvTclk = 200000000; /* 200 MHz */
340
341 sar_reg = (read_miscreg(ARMADAXP_MISC_SAR_HI) << 31) |
342 read_miscreg(ARMADAXP_MISC_SAR_LO);
343
344 sar_cpu_freq = EXTRACT_XP_CPU_FREQ_FIELD(sar_reg);
345 sar_fab_freq = EXTRACT_XP_FAB_FREQ_FIELD(sar_reg);
346
347 /* Check if CPU frequency field has correct value */
348 if (sar_cpu_freq >= __arraycount(clock_table_xp))
349 panic("Reserved value in cpu frequency configuration field: "
350 "%d", sar_cpu_freq);
351
352 /* Check if fabric frequency field has correct value */
353 if (sar_fab_freq >= __arraycount(freq_conf_table))
354 panic("Reserved value in fabric frequency configuration field: "
355 "%d", sar_fab_freq);
356
357 /* Get CPU clock frequency */
358 mvPclk = clock_table_xp[sar_cpu_freq] *
359 freq_conf_table[sar_fab_freq].vco_cpu;
360
361 /* Get L2CLK clock frequency and use as system clock (mvSysclk) */
362 mvSysclk = mvPclk / freq_conf_table[sar_fab_freq].vco_l2c;
363
364 /* Round mvSysclk value to integer MHz */
365 if (((mvPclk % freq_conf_table[sar_fab_freq].vco_l2c) * 10 /
366 freq_conf_table[sar_fab_freq].vco_l2c) >= 5)
367 mvSysclk++;
368
369 mvPclk *= 1000000;
370 mvSysclk *= 1000000;
371
372 curcpu()->ci_data.cpu_cc_freq = mvPclk;
373 }
374
375 void
376 armada370_getclks(void)
377 {
378 uint32_t sar;
379 uint8_t cpu_freq, fab_freq;
380
381 sar = read_miscreg(ARMADAXP_MISC_SAR_LO);
382 if (sar & 0x00100000)
383 mvTclk = 200000000; /* 200 MHz */
384 else
385 mvTclk = 166666667; /* 166 MHz */
386
387 cpu_freq = EXTRACT_370_CPU_FREQ_FIELD(sar);
388 fab_freq = EXTRACT_370_FAB_FREQ_FIELD(sar);
389
390 /* Check if CPU frequency field has correct value */
391 if (cpu_freq >= __arraycount(clock_table_370))
392 panic("Reserved value in cpu frequency configuration field: "
393 "%d", cpu_freq);
394
395 /* Check if fabric frequency field has correct value */
396 if (fab_freq >= __arraycount(freq_conf_table))
397 panic("Reserved value in fabric frequency configuration field: "
398 "%d", fab_freq);
399
400 /* Get CPU clock frequency */
401 mvPclk = clock_table_370[cpu_freq] *
402 freq_conf_table[fab_freq].vco_cpu;
403
404 /* Get L2CLK clock frequency and use as system clock (mvSysclk) */
405 mvSysclk = mvPclk / freq_conf_table[fab_freq].vco_l2c;
406
407 /* Round mvSysclk value to integer MHz */
408 if (((mvPclk % freq_conf_table[fab_freq].vco_l2c) * 10 /
409 freq_conf_table[fab_freq].vco_l2c) >= 5)
410 mvSysclk++;
411
412 mvPclk *= 1000000;
413 mvSysclk *= 1000000;
414 }
415
416 /*
417 * L2 Cache initialization
418 */
419
420 int
421 armadaxp_l2_init(bus_addr_t pbase)
422 {
423 u_int32_t reg;
424 int ret;
425
426 /* Map L2 space */
427 ret = bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_L2_BASE,
428 0x1000, 0, &l2_handle);
429 if (ret) {
430 printf("%s: Cannot map L2 register space, ret:%d\n",
431 __func__, ret);
432 return (-1);
433 }
434
435 /* Set L2 policy */
436 reg = L2_READ(ARMADAXP_L2_AUX_CTRL);
437 reg &= ~(L2_WBWT_MODE_MASK);
438 reg &= ~(L2_REP_STRAT_MASK);
439 reg |= L2_REP_STRAT_SEMIPLRU;
440 L2_WRITE(ARMADAXP_L2_AUX_CTRL, reg);
441
442 /* Invalidate L2 cache */
443 L2_WRITE(ARMADAXP_L2_INV_WAY, L2_ALL_WAYS);
444
445 /* Clear pending L2 interrupts */
446 L2_WRITE(ARMADAXP_L2_INT_CAUSE, 0x1ff);
447
448 /* Enable Cache and TLB maintenance broadcast */
449 __asm__ __volatile__ ("mrc p15, 1, %0, c15, c2, 0" : "=r"(reg));
450 reg |= (1 << 8);
451 __asm__ __volatile__ ("mcr p15, 1, %0, c15, c2, 0" : :"r"(reg));
452
453 /*
454 * Set the Point of Coherency and Point of Unification to DRAM.
455 * This is a reset value but anyway, configure this just in case.
456 */
457 reg = read_mlmbreg(ARMADAXP_L2_CFU);
458 reg |= (1 << 17) | (1 << 18);
459 write_mlmbreg(ARMADAXP_L2_CFU, reg);
460
461 /* Enable L2 cache */
462 reg = L2_READ(ARMADAXP_L2_CTRL);
463 L2_WRITE(ARMADAXP_L2_CTRL, reg | L2_ENABLE);
464
465 /* Mark as enabled */
466 l2cache_state = 1;
467
468 #ifdef DEBUG
469 /* Configure and enable counter */
470 L2_WRITE(ARMADAXP_L2_CNTR_CONF(0), 0xf0000 | (4 << 2));
471 L2_WRITE(ARMADAXP_L2_CNTR_CONF(1), 0xf0000 | (2 << 2));
472 L2_WRITE(ARMADAXP_L2_CNTR_CTRL, 0x303);
473 #endif
474
475 return (0);
476 }
477
478 void
479 armadaxp_sdcache_inv_all(void)
480 {
481 L2_WRITE(ARMADAXP_L2_INV_WAY, L2_ALL_WAYS);
482 }
483
484 void
485 armadaxp_sdcache_wb_all(void)
486 {
487 L2_WRITE(ARMADAXP_L2_WB_WAY, L2_ALL_WAYS);
488 L2_WRITE(ARMADAXP_L2_SYNC, 0);
489 __asm__ __volatile__("dsb");
490 }
491
492 void
493 armadaxp_sdcache_wbinv_all(void)
494 {
495 L2_WRITE(ARMADAXP_L2_WBINV_WAY, L2_ALL_WAYS);
496 L2_WRITE(ARMADAXP_L2_SYNC, 0);
497 __asm__ __volatile__("dsb");
498 }
499
500 void
501 armadaxp_sdcache_inv_range(vaddr_t va, paddr_t pa, psize_t sz)
502 {
503 paddr_t pa_base = pa;
504 paddr_t pa_end = pa + sz - 1;
505
506 /* need write back if boundary is not aligned */
507 if (pa_base & 0x1f)
508 L2_WRITE(ARMADAXP_L2_WB_PHYS, (pa_base & ~0x1f));
509 if (pa_end & 0x1f)
510 L2_WRITE(ARMADAXP_L2_WB_PHYS, (pa_end & ~0x1f));
511 L2_WRITE(ARMADAXP_L2_SYNC, 0);
512 __asm__ __volatile__("dsb");
513
514 /* invalidate other cache */
515 pa_base &= ~0x1f;
516 pa_end &= ~0x1f;
517 if (pa_base == pa_end)
518 L2_WRITE(ARMADAXP_L2_INV_PHYS, pa_base);
519 else {
520 L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
521 L2_WRITE(ARMADAXP_L2_INV_RANGE, pa_end);
522 }
523 }
524
525 void
526 armadaxp_sdcache_wb_range(vaddr_t va, paddr_t pa, psize_t sz)
527 {
528 paddr_t pa_base = pa;
529 paddr_t pa_end = pa + sz - 1;
530
531 pa_base &= ~0x1f;
532 pa_end &= ~0x1f;
533 if (pa_base == pa_end)
534 L2_WRITE(ARMADAXP_L2_WB_PHYS, pa_base);
535 else {
536 L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
537 L2_WRITE(ARMADAXP_L2_WB_RANGE, pa_end);
538 }
539 L2_WRITE(ARMADAXP_L2_SYNC, 0);
540 __asm__ __volatile__("dsb");
541 }
542
543 void
544 armadaxp_sdcache_wbinv_range(vaddr_t va, paddr_t pa, psize_t sz)
545 {
546 paddr_t pa_base = pa;
547 paddr_t pa_end = pa + sz - 1;
548
549 pa_base &= ~0x1f;
550 pa_end &= ~0x1f;
551 if (pa_base == pa_end)
552 L2_WRITE(ARMADAXP_L2_WBINV_PHYS, pa_base);
553 else {
554 L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
555 L2_WRITE(ARMADAXP_L2_WBINV_RANGE, pa_end);
556 }
557 L2_WRITE(ARMADAXP_L2_SYNC, 0);
558 __asm__ __volatile__("dsb");
559 }
560
561 void
562 armadaxp_io_coherency_init(void)
563 {
564 uint32_t reg;
565
566 /* set CIB read snoop command to ReadUnique */
567 reg = read_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG);
568 reg &= ~(7 << 16);
569 reg |= (7 << 16);
570 write_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG, reg);
571 /* enable CPUs in SMP group on Fabric coherency */
572 reg = read_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CTRL);
573 reg &= ~(0x3 << 24);
574 reg |= (1 << 24);
575 write_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CTRL, reg);
576
577 reg = read_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CFG);
578 reg &= ~(0x3 << 24);
579 reg |= (1 << 24);
580 write_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CFG, reg);
581
582 /* Mark as enabled */
583 iocc_state = 1;
584 }
585
586 int
587 armadaxp_clkgating(struct marvell_attach_args *mva)
588 {
589 uint32_t val;
590 int i;
591
592 for (i = 0; i < __arraycount(clkgatings); i++) {
593 if (clkgatings[i].offset == mva->mva_offset) {
594 val = read_miscreg(ARMADAXP_MISC_PMCGC);
595 if ((val & clkgatings[i].bits) == clkgatings[i].bits)
596 /* Clock enabled */
597 return 0;
598 return 1;
599 }
600 }
601 /* Clock Gating not support */
602 return 0;
603 }
604