Home | History | Annotate | Line # | Download | only in marvell
armadaxp.c revision 1.9
      1 /*	$NetBSD: armadaxp.c,v 1.9 2015/04/15 10:40:36 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.9 2015/04/15 10:40:36 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 	__asm__ __volatile__("dsb");
    489 }
    490 
    491 void
    492 armadaxp_sdcache_wbinv_all(void)
    493 {
    494 	L2_WRITE(ARMADAXP_L2_WBINV_WAY, L2_ALL_WAYS);
    495 	__asm__ __volatile__("dsb");
    496 }
    497 
    498 void
    499 armadaxp_sdcache_inv_range(vaddr_t va, paddr_t pa, psize_t sz)
    500 {
    501 	paddr_t pa_base, pa_end;
    502 
    503 	pa_base = pa & ~0x1f;
    504 	pa_end = (pa_base + sz) & ~0x1f;
    505 	L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
    506 	L2_WRITE(ARMADAXP_L2_INV_RANGE, pa_end);
    507 }
    508 
    509 void
    510 armadaxp_sdcache_wb_range(vaddr_t va, paddr_t pa, psize_t sz)
    511 {
    512 	paddr_t pa_base, pa_end;
    513 
    514 	pa_base = pa & ~0x1f;
    515 	pa_end = (pa_base + sz) & ~0x1f;
    516 	L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
    517 	L2_WRITE(ARMADAXP_L2_WB_RANGE, pa_end);
    518 	__asm__ __volatile__("dsb");
    519 }
    520 
    521 void
    522 armadaxp_sdcache_wbinv_range(vaddr_t va, paddr_t pa, psize_t sz)
    523 {
    524 	paddr_t pa_base, pa_end;
    525 
    526 	pa_base = pa & ~0x1f;
    527 	pa_end = (pa_base + sz) & ~0x1f;
    528 	L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
    529 	L2_WRITE(ARMADAXP_L2_WBINV_RANGE, pa_end);
    530 	__asm__ __volatile__("dsb");
    531 }
    532 
    533 void
    534 armadaxp_io_coherency_init(void)
    535 {
    536 	uint32_t reg;
    537 
    538 	/* set CIB read snoop command to ReadUnique */
    539 	reg = read_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG);
    540 	reg &= ~(7 << 16);
    541 	reg |= (7 << 16);
    542 	write_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG, reg);
    543 	/* enable CPUs in SMP group on Fabric coherency */
    544 	reg = read_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CTRL);
    545 	reg &= ~(0x3 << 24);
    546 	reg |= (1 << 24);
    547 	write_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CTRL, reg);
    548 
    549 	reg = read_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CFG);
    550 	reg &= ~(0x3 << 24);
    551 	reg |= (1 << 24);
    552 	write_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CFG, reg);
    553 
    554 	/* Mark as enabled */
    555 	iocc_state = 1;
    556 }
    557 
    558 int
    559 armadaxp_clkgating(struct marvell_attach_args *mva)
    560 {
    561 	uint32_t val;
    562 	int i;
    563 
    564 	for (i = 0; i < __arraycount(clkgatings); i++) {
    565 		if (clkgatings[i].offset == mva->mva_offset) {
    566 			val = read_miscreg(ARMADAXP_MISC_PMCGC);
    567 			if ((val & clkgatings[i].bits) == clkgatings[i].bits)
    568 				/* Clock enabled */
    569 				return 0;
    570 			return 1;
    571 		}
    572 	}
    573 	/* Clock Gating not support */
    574 	return 0;
    575 }
    576