Home | History | Annotate | Line # | Download | only in marvell
armadaxp.c revision 1.7
      1 /*	$NetBSD: armadaxp.c,v 1.7 2014/03/15 10:54:40 kiyohara 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.7 2014/03/15 10:54:40 kiyohara 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 
     62 #include <dev/marvell/marvellreg.h>
     63 
     64 #define EXTRACT_XP_CPU_FREQ_FIELD(sar)	(((0x01 & (sar >> 52)) << 3) | \
     65 					    (0x07 & (sar >> 21)))
     66 #define EXTRACT_XP_FAB_FREQ_FIELD(sar)	(((0x01 & (sar >> 51)) << 4) | \
     67 					    (0x0F & (sar >> 24)))
     68 #define EXTRACT_370_CPU_FREQ_FIELD(sar)	((sar >> 11) & 0xf)
     69 #define EXTRACT_370_FAB_FREQ_FIELD(sar)	((sar >> 15) & 0x1f)
     70 
     71 #define	MPIC_WRITE(reg, val)		(bus_space_write_4(&mvsoc_bs_tag, \
     72 					    mpic_handle, reg, val))
     73 #define	MPIC_CPU_WRITE(reg, val)	(bus_space_write_4(&mvsoc_bs_tag, \
     74 					    mpic_cpu_handle, reg, val))
     75 
     76 #define	MPIC_READ(reg)			(bus_space_read_4(&mvsoc_bs_tag, \
     77 					    mpic_handle, reg))
     78 #define	MPIC_CPU_READ(reg)		(bus_space_read_4(&mvsoc_bs_tag, \
     79 					    mpic_cpu_handle, reg))
     80 
     81 #define	L2_WRITE(reg, val)		(bus_space_write_4(&mvsoc_bs_tag, \
     82 					    l2_handle, reg, val))
     83 #define	L2_READ(reg)			(bus_space_read_4(&mvsoc_bs_tag, \
     84 					    l2_handle, reg))
     85 bus_space_handle_t mpic_cpu_handle;
     86 static bus_space_handle_t mpic_handle, l2_handle;
     87 int l2cache_state = 0;
     88 int iocc_state = 0;
     89 #define read_miscreg(r)		(*(volatile uint32_t *)(misc_base + (r)))
     90 vaddr_t misc_base;
     91 
     92 extern void (*mvsoc_intr_init)(void);
     93 static void armadaxp_intr_init(void);
     94 
     95 static void armadaxp_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
     96 static void armadaxp_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
     97 static void armadaxp_pic_establish_irq(struct pic_softc *, struct intrsource *);
     98 static void armadaxp_pic_set_priority(struct pic_softc *, int);
     99 
    100 static int armadaxp_find_pending_irqs(void);
    101 static void armadaxp_pic_block_irq(struct pic_softc *, size_t);
    102 void armadaxp_io_coherency_init(void);
    103 int armadaxp_l2_init(bus_addr_t);
    104 
    105 struct vco_freq_ratio {
    106 	uint8_t	vco_cpu;	/* VCO to CLK0(CPU) clock ratio */
    107 	uint8_t	vco_l2c;	/* VCO to NB(L2 cache) clock ratio */
    108 	uint8_t	vco_hcl;	/* VCO to HCLK(DDR controller) clock ratio */
    109 	uint8_t	vco_ddr;	/* VCO to DR(DDR memory) clock ratio */
    110 };
    111 
    112 static struct vco_freq_ratio freq_conf_table[] = {
    113 /*00*/	{ 1, 1,	 4,  2 },
    114 /*01*/	{ 1, 2,	 2,  2 },
    115 /*02*/	{ 2, 2,	 6,  3 },
    116 /*03*/	{ 2, 2,	 3,  3 },
    117 /*04*/	{ 1, 2,	 3,  3 },
    118 /*05*/	{ 1, 2,	 4,  2 },
    119 /*06*/	{ 1, 1,	 2,  2 },
    120 /*07*/	{ 2, 3,	 6,  6 },
    121 /*08*/	{ 2, 3,	 5,  5 },
    122 /*09*/	{ 1, 2,	 6,  3 },
    123 /*10*/	{ 2, 4,	10,  5 },
    124 /*11*/	{ 1, 3,	 6,  6 },
    125 /*12*/	{ 1, 2,	 5,  5 },
    126 /*13*/	{ 1, 3,	 6,  3 },
    127 /*14*/	{ 1, 2,	 5,  5 },
    128 /*15*/	{ 2, 2,	 5,  5 },
    129 /*16*/	{ 1, 1,	 3,  3 },
    130 /*17*/	{ 2, 5,	10, 10 },
    131 /*18*/	{ 1, 3,	 8,  4 },
    132 /*19*/	{ 1, 1,	 2,  1 },
    133 /*20*/	{ 2, 3,	 6,  3 },
    134 /*21*/	{ 1, 2,	 8,  4 },
    135 /*22*/	{ 2, 5,	10,  5 }
    136 };
    137 
    138 static uint16_t clock_table_xp[] = {
    139 	1000, 1066, 1200, 1333, 1500, 1666, 1800, 2000,
    140 	 600,  667,  800, 1600, 2133, 2200, 2400
    141 };
    142 static uint16_t clock_table_370[] = {
    143 	 400,  533,  667,  800, 1000, 1067, 1200, 1333,
    144 	1500, 1600, 1667, 1800, 2000,  333,  600,  900,
    145 	   0
    146 };
    147 
    148 static struct pic_ops armadaxp_picops = {
    149 	.pic_unblock_irqs = armadaxp_pic_unblock_irqs,
    150 	.pic_block_irqs = armadaxp_pic_block_irqs,
    151 	.pic_establish_irq = armadaxp_pic_establish_irq,
    152 	.pic_set_priority = armadaxp_pic_set_priority,
    153 };
    154 
    155 static struct pic_softc armadaxp_pic = {
    156 	.pic_ops = &armadaxp_picops,
    157 	.pic_name = "armadaxp",
    158 };
    159 
    160 static struct {
    161 	bus_size_t offset;
    162 	uint32_t bits;
    163 } clkgatings[]= {
    164 	{ ARMADAXP_GBE3_BASE,	(1 << 1) },
    165 	{ ARMADAXP_GBE2_BASE,	(1 << 2) },
    166 	{ ARMADAXP_GBE1_BASE,	(1 << 3) },
    167 	{ ARMADAXP_GBE0_BASE,	(1 << 4) },
    168 	{ MVSOC_PEX_BASE,	(1 << 5) },
    169 	{ ARMADAXP_PEX01_BASE,	(1 << 6) },
    170 	{ ARMADAXP_PEX02_BASE,	(1 << 7) },
    171 	{ ARMADAXP_PEX03_BASE,	(1 << 8) },
    172 	{ ARMADAXP_PEX10_BASE,	(1 << 9) },
    173 	{ ARMADAXP_PEX11_BASE,	(1 << 10) },
    174 	{ ARMADAXP_PEX12_BASE,	(1 << 11) },
    175 	{ ARMADAXP_PEX13_BASE,	(1 << 12) },
    176 #if 0
    177 	{ NetA, (1 << 13) },
    178 #endif
    179 	{ ARMADAXP_SATAHC_BASE,	(1 << 14) | (1 << 15) | (1 << 29) | (1 << 30) },
    180 	{ ARMADAXP_LCD_BASE,	(1 << 16) },
    181 	{ ARMADAXP_SDIO_BASE,	(1 << 17) },
    182 	{ ARMADAXP_USB1_BASE,	(1 << 19) },
    183 	{ ARMADAXP_USB2_BASE,	(1 << 20) },
    184 	{ ARMADAXP_PEX2_BASE,	(1 << 26) },
    185 	{ ARMADAXP_PEX3_BASE,	(1 << 27) },
    186 #if 0
    187 	{ DDR, (1 << 28) },
    188 #endif
    189 };
    190 
    191 /*
    192  * armadaxp_intr_bootstrap:
    193  *
    194  *	Initialize the rest of the interrupt subsystem, making it
    195  *	ready to handle interrupts from devices.
    196  */
    197 void
    198 armadaxp_intr_bootstrap(bus_addr_t pbase)
    199 {
    200 	int i;
    201 
    202 	/* Map MPIC base and MPIC percpu base registers */
    203 	if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_BASE,
    204 	    0x500, 0, &mpic_handle) != 0)
    205 		panic("%s: Could not map MPIC registers", __func__);
    206 	if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_CPU_BASE,
    207 	    0x800, 0, &mpic_cpu_handle) != 0)
    208 		panic("%s: Could not map MPIC percpu registers", __func__);
    209 
    210 	/* Disable all interrupts */
    211 	for (i = 0; i < 116; i++)
    212 		MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, i);
    213 
    214 	mvsoc_intr_init = armadaxp_intr_init;
    215 }
    216 
    217 static void
    218 armadaxp_intr_init(void)
    219 {
    220 	int ctrl;
    221 
    222 	/* Get max interrupts */
    223 	armadaxp_pic.pic_maxsources =
    224 	    ((MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL) >> 2) & 0x7FF);
    225 
    226 	if (!armadaxp_pic.pic_maxsources)
    227 		armadaxp_pic.pic_maxsources = 116;
    228 
    229 	pic_add(&armadaxp_pic, 0);
    230 
    231 	ctrl = MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL);
    232 	/* Enable IRQ prioritization */
    233 	ctrl |= (1 << 0);
    234 	MPIC_WRITE(ARMADAXP_MLMB_MPIC_CTRL, ctrl);
    235 
    236 	find_pending_irqs = armadaxp_find_pending_irqs;
    237 }
    238 
    239 static void
    240 armadaxp_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
    241     uint32_t irq_mask)
    242 {
    243 	int n;
    244 
    245 	while (irq_mask != 0) {
    246 		n = ffs(irq_mask) - 1;
    247 		KASSERT(pic->pic_maxsources >= n + irqbase);
    248 		MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISE, n + irqbase);
    249 		MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ICM, n + irqbase);
    250 		if ((n + irqbase) == 0)
    251 			MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_DOORBELL_MASK,
    252 			    0xffffffff);
    253 		irq_mask &= ~__BIT(n);
    254 	}
    255 }
    256 
    257 static void
    258 armadaxp_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
    259     uint32_t irq_mask)
    260 {
    261 	int n;
    262 
    263 	while (irq_mask != 0) {
    264 		n = ffs(irq_mask) - 1;
    265 		KASSERT(pic->pic_maxsources >= n + irqbase);
    266 		MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, n + irqbase);
    267 		MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, n + irqbase);
    268 		irq_mask &= ~__BIT(n);
    269 	}
    270 }
    271 
    272 static void
    273 armadaxp_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
    274 {
    275 	int tmp;
    276 	KASSERT(pic->pic_maxsources >= is->is_irq);
    277 	tmp = MPIC_READ(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4);
    278 	/* Clear previous priority */
    279 	tmp &= ~(0xf << MPIC_ISCR_SHIFT);
    280 	MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4,
    281 	    tmp | (is->is_ipl << MPIC_ISCR_SHIFT));
    282 }
    283 
    284 static void
    285 armadaxp_pic_set_priority(struct pic_softc *pic, int ipl)
    286 {
    287 	int ctp;
    288 
    289 	ctp = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_CTP);
    290 	ctp &= ~(0xf << MPIC_CTP_SHIFT);
    291 	ctp |= (ipl << MPIC_CTP_SHIFT);
    292 	MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_CTP, ctp);
    293 }
    294 
    295 static int
    296 armadaxp_find_pending_irqs(void)
    297 {
    298 	struct intrsource *is;
    299 	int irq;
    300 
    301 	irq = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_IIACK) & 0x3ff;
    302 
    303 	/* Is it a spurious interrupt ?*/
    304 	if (irq == 0x3ff)
    305 		return 0;
    306 	is = armadaxp_pic.pic_sources[irq];
    307 	if (is == NULL) {
    308 		printf("stray interrupt: %d\n", irq);
    309 		return 0;
    310 	}
    311 
    312 	armadaxp_pic_block_irq(&armadaxp_pic, irq);
    313 	pic_mark_pending(&armadaxp_pic, irq);
    314 
    315 	return is->is_ipl;
    316 }
    317 
    318 static void
    319 armadaxp_pic_block_irq(struct pic_softc *pic, size_t irq)
    320 {
    321 
    322 	KASSERT(pic->pic_maxsources >= irq);
    323 	MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, irq);
    324 	MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, irq);
    325 }
    326 
    327 /*
    328  * Clock functions
    329  */
    330 
    331 void
    332 armadaxp_getclks(void)
    333 {
    334 	uint64_t sar_reg;
    335 	uint8_t  sar_cpu_freq, sar_fab_freq;
    336 
    337 	if (cputype == CPU_ID_MV88SV584X_V7)
    338 		mvTclk = 250000000; /* 250 MHz */
    339 	else
    340 		mvTclk = 200000000; /* 200 MHz */
    341 
    342 	sar_reg = (read_miscreg(ARMADAXP_MISC_SAR_HI) << 31) |
    343 	    read_miscreg(ARMADAXP_MISC_SAR_LO);
    344 
    345 	sar_cpu_freq = EXTRACT_XP_CPU_FREQ_FIELD(sar_reg);
    346 	sar_fab_freq = EXTRACT_XP_FAB_FREQ_FIELD(sar_reg);
    347 
    348 	/* Check if CPU frequency field has correct value */
    349 	if (sar_cpu_freq >= __arraycount(clock_table_xp))
    350 		panic("Reserved value in cpu frequency configuration field: "
    351 		    "%d", sar_cpu_freq);
    352 
    353 	/* Check if fabric frequency field has correct value */
    354 	if (sar_fab_freq >= __arraycount(freq_conf_table))
    355 		panic("Reserved value in fabric frequency configuration field: "
    356 		    "%d", sar_fab_freq);
    357 
    358 	/* Get CPU clock frequency */
    359 	mvPclk = clock_table_xp[sar_cpu_freq] *
    360 	    freq_conf_table[sar_fab_freq].vco_cpu;
    361 
    362 	/* Get L2CLK clock frequency and use as system clock (mvSysclk) */
    363 	mvSysclk = mvPclk / freq_conf_table[sar_fab_freq].vco_l2c;
    364 
    365 	/* Round mvSysclk value to integer MHz */
    366 	if (((mvPclk % freq_conf_table[sar_fab_freq].vco_l2c) * 10 /
    367 	    freq_conf_table[sar_fab_freq].vco_l2c) >= 5)
    368 		mvSysclk++;
    369 
    370 	mvPclk *= 1000000;
    371 	mvSysclk *= 1000000;
    372 }
    373 
    374 void
    375 armada370_getclks(void)
    376 {
    377 	uint32_t sar;
    378 	uint8_t  cpu_freq, fab_freq;
    379 
    380 	sar = read_miscreg(ARMADAXP_MISC_SAR_LO);
    381 	if (sar & 0x00100000)
    382 		mvTclk = 200000000; /* 200 MHz */
    383 	else
    384 		mvTclk = 166666667; /* 166 MHz */
    385 
    386 	cpu_freq = EXTRACT_370_CPU_FREQ_FIELD(sar);
    387 	fab_freq = EXTRACT_370_FAB_FREQ_FIELD(sar);
    388 
    389 	/* Check if CPU frequency field has correct value */
    390 	if (cpu_freq >= __arraycount(clock_table_370))
    391 		panic("Reserved value in cpu frequency configuration field: "
    392 		    "%d", cpu_freq);
    393 
    394 	/* Check if fabric frequency field has correct value */
    395 	if (fab_freq >= __arraycount(freq_conf_table))
    396 		panic("Reserved value in fabric frequency configuration field: "
    397 		    "%d", fab_freq);
    398 
    399 	/* Get CPU clock frequency */
    400 	mvPclk = clock_table_370[cpu_freq] *
    401 	    freq_conf_table[fab_freq].vco_cpu;
    402 
    403 	/* Get L2CLK clock frequency and use as system clock (mvSysclk) */
    404 	mvSysclk = mvPclk / freq_conf_table[fab_freq].vco_l2c;
    405 
    406 	/* Round mvSysclk value to integer MHz */
    407 	if (((mvPclk % freq_conf_table[fab_freq].vco_l2c) * 10 /
    408 	    freq_conf_table[fab_freq].vco_l2c) >= 5)
    409 		mvSysclk++;
    410 
    411 	mvPclk *= 1000000;
    412 	mvSysclk *= 1000000;
    413 }
    414 
    415 /*
    416  * L2 Cache initialization
    417  */
    418 
    419 int
    420 armadaxp_l2_init(bus_addr_t pbase)
    421 {
    422 	u_int32_t reg;
    423 	int ret;
    424 
    425 	/* Map L2 space */
    426 	ret = bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_L2_BASE,
    427 	    0x1000, 0, &l2_handle);
    428 	if (ret) {
    429 		printf("%s: Cannot map L2 register space, ret:%d\n",
    430 		    __func__, ret);
    431 		return (-1);
    432 	}
    433 
    434 	/* Set L2 policy */
    435 	reg = L2_READ(ARMADAXP_L2_AUX_CTRL);
    436 	reg &= ~(L2_WBWT_MODE_MASK);
    437 	reg &= ~(L2_REP_STRAT_MASK);
    438 	reg |= L2_REP_STRAT_SEMIPLRU;
    439 	L2_WRITE(ARMADAXP_L2_AUX_CTRL, reg);
    440 
    441 	/* Invalidate L2 cache */
    442 	L2_WRITE(ARMADAXP_L2_INV_WAY, L2_ALL_WAYS);
    443 
    444 	/* Clear pending L2 interrupts */
    445 	L2_WRITE(ARMADAXP_L2_INT_CAUSE, 0x1ff);
    446 
    447 	/* Enable Cache and TLB maintenance broadcast */
    448 	__asm__ __volatile__ ("mrc p15, 1, %0, c15, c2, 0" : "=r"(reg));
    449 	reg |= (1 << 8);
    450 	__asm__ __volatile__ ("mcr p15, 1, %0, c15, c2, 0" : :"r"(reg));
    451 
    452 	/*
    453 	 * Set the Point of Coherency and Point of Unification to DRAM.
    454 	 * This is a reset value but anyway, configure this just in case.
    455 	 */
    456 	reg = read_mlmbreg(ARMADAXP_L2_CFU);
    457 	reg |= (1 << 17) | (1 << 18);
    458 	write_mlmbreg(ARMADAXP_L2_CFU, reg);
    459 
    460 	/* Enable L2 cache */
    461 	reg = L2_READ(ARMADAXP_L2_CTRL);
    462 	L2_WRITE(ARMADAXP_L2_CTRL, reg | L2_ENABLE);
    463 
    464 	/* Mark as enabled */
    465 	l2cache_state = 1;
    466 
    467 #ifdef DEBUG
    468 	/* Configure and enable counter */
    469 	L2_WRITE(ARMADAXP_L2_CNTR_CONF(0), 0xf0000 | (4 << 2));
    470 	L2_WRITE(ARMADAXP_L2_CNTR_CONF(1), 0xf0000 | (2 << 2));
    471 	L2_WRITE(ARMADAXP_L2_CNTR_CTRL, 0x303);
    472 #endif
    473 
    474 	return (0);
    475 }
    476 
    477 void
    478 armadaxp_io_coherency_init(void)
    479 {
    480 	uint32_t reg;
    481 
    482 	/* set CIB read snoop command to ReadUnique */
    483 	reg = read_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG);
    484 	reg &= ~(7 << 16);
    485 	reg |= (7 << 16);
    486 	write_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG, reg);
    487 	/* enable CPUs in SMP group on Fabric coherency */
    488 	reg = read_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CTRL);
    489 	reg &= ~(0x3 << 24);
    490 	reg |= (1 << 24);
    491 	write_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CTRL, reg);
    492 
    493 	reg = read_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CFG);
    494 	reg &= ~(0x3 << 24);
    495 	reg |= (1 << 24);
    496 	write_mlmbreg(MVSOC_MLMB_COHERENCY_FABRIC_CFG, reg);
    497 
    498 	/* Mark as enabled */
    499 	iocc_state = 1;
    500 }
    501 
    502 int
    503 armadaxp_clkgating(struct marvell_attach_args *mva)
    504 {
    505 	uint32_t val;
    506 	int i;
    507 
    508 	for (i = 0; i < __arraycount(clkgatings); i++) {
    509 		if (clkgatings[i].offset == mva->mva_offset) {
    510 			val = read_miscreg(ARMADAXP_MISC_PMCGC);
    511 			if ((val & clkgatings[i].bits) == clkgatings[i].bits)
    512 				/* Clock enabled */
    513 				return 0;
    514 			return 1;
    515 		}
    516 	}
    517 	/* Clock Gating not support */
    518 	return 0;
    519 }
    520