Home | History | Annotate | Line # | Download | only in marvell
armadaxp.c revision 1.15
      1 /*	$NetBSD: armadaxp.c,v 1.15 2015/06/03 02:53:19 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.15 2015/06/03 02:53:19 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 
     53 #include <arm/armreg.h>
     54 #include <arm/cpu.h>
     55 #include <arm/cpufunc.h>
     56 
     57 #include <arm/marvell/mvsocreg.h>
     58 #include <arm/marvell/mvsocvar.h>
     59 #include <arm/marvell/armadaxpreg.h>
     60 #include <arm/marvell/armadaxpvar.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 vaddr_t armadaxp_l2_barrier_reg;
     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 static void armadaxp_pic_source_name(struct pic_softc *, int, char*, size_t);
    101 
    102 static int armadaxp_find_pending_irqs(void);
    103 static void armadaxp_pic_block_irq(struct pic_softc *, size_t);
    104 
    105 /* handle error cause */
    106 static void armadaxp_err_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
    107 static void armadaxp_err_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
    108 static void armadaxp_err_pic_establish_irq(struct pic_softc *,
    109     struct intrsource *);
    110 static void armadaxp_err_pic_source_name(struct pic_softc *,
    111     int, char*, size_t);
    112 static int armadaxp_err_pic_pending_irqs(struct pic_softc *);
    113 
    114 struct vco_freq_ratio {
    115 	uint8_t	vco_cpu;	/* VCO to CLK0(CPU) clock ratio */
    116 	uint8_t	vco_l2c;	/* VCO to NB(L2 cache) clock ratio */
    117 	uint8_t	vco_hcl;	/* VCO to HCLK(DDR controller) clock ratio */
    118 	uint8_t	vco_ddr;	/* VCO to DR(DDR memory) clock ratio */
    119 };
    120 
    121 /*
    122  * Interrupt names for ARMADA XP
    123  */
    124 static const char * const armadaxp_pic_source_names[] = {
    125 	/* Main Interrupt Cause Per-CPU (IRQ 0-29) */
    126 	"InDBLowSum", "InDBHighSum", "OutDBSum", "CFU_LocalSum",
    127 	"SoC_ErrorSum", "LTimer0", "LTimer1", "LWDT", "GbE0_TH_RxTx",
    128 	"GbE0_RxTx", "GbE1_RxTxTh", "GbE1_RxTx", "GbE2_RxTxTh", "GbE2_RxTx",
    129 	"GbE3_RxTxTh", "GbE3_RxTx", "GPIO0_7", "GPIO8_15", "GPIO16_23",
    130 	"GPIO24_31", "GPIO32_39", "GPIO40_47", "GPIO48_55", "GPIO56_63",
    131 	"GPIO64_66", "SCNT", "PCNT", "Reserved27", "VCNT", "Reserved29",
    132 	/* Main Interrupt Cause Global-Shared (IRQ 30-115) */
    133 	"SPI0", "I2C0", "I2C1", "IDMA0", "IDMA1", "IDMA2", "IDMA3", "GTimer0",
    134 	"GTimer1", "GTimer2", "GTimer3", "UART0", "UART1", "UART2", "UART3",
    135 	"USB0", "USB1", "USB2", "CESA0", "CESA1", "RTC", "XOR0_Ch0",
    136 	"XOR0_Ch1", "BM", "SDIO", "SATA0", "TDM", "SATA1", "PEX0_0", "PEX0_1",
    137 	"PEX0_2", "PEX0_3", "PEX1_0", "PEX1_1", "PEX1_2", "PEX1_3",
    138 	"GbE0_Sum", "GbE0_Rx", "GbE0_Tx", "GbE0_Misc", "GbE1_Sum", "GbE1_Rx",
    139 	"GbE1_Tx", "GbE1_Misc", "GbE2_Sum", "GbE2_Rx", "GbE2_Tx", "GbE2_Misc",
    140 	"GbE3_Sum", "GbE3_Rx", "GbE3_Tx", "GbE3_Misc", "GPIO0_7", "GPIO8_15",
    141 	"GPIO16_23", "GPIO24_31", "Reserved86", "GPIO32_39", "GPIO40_47",
    142 	"GPIO48_55", "GPIO56_63", "GPIO64_66", "SPI1", "WDT", "XOR1_Ch2",
    143 	"XOR1_Ch3", "SharedDB1Sum", "SharedDB2Sum", "SharedDB3Sum", "PEX2_0",
    144 	"Reserved100", "Reserved101", "Reserved102", "PEX3_0", "Reserved104",
    145 	"Reserved105", "Reserved106", "PMU", "DRAM", "GbE0_Wakeup",
    146 	"GbE1_Wakeup", "GbE2_Wakeup", "GbE3_Wakeup", "NAND", "Reserved114",
    147 	"Reserved115"
    148 };
    149 static const char * const armadaxp_err_pic_source_names[] = {
    150 	/*
    151 	 * IRQ 120-151 (bit 0-31 in SoC Error Interrupt Cause register)
    152 	 * connected to SoC_ErrorSum in Main Interrupt Cause
    153 	 */
    154 	"ERR_CESA0", "ERR_DevBus", "ERR_IDMA", "ERR_XOR1",
    155 	"ERR_PEX0", "ERR_PEX1", "ERR_GbE", "ERR_CESA1",
    156 	"ERR_USB", "ERR_DRAM", "ERR_XOR0", "ERR_Reserved11",
    157 	"ERR_BM", "ERR_CIB", "ERR_Reserved14", "ERR_PEX2",
    158 	"ERR_PEX3", "ERR_SATA0", "ERR_SATA1", "ERR_Reserved19",
    159 	"ERR_TDM", "ERR_NAND", "ERR_Reserved22",
    160 	"ERR_Reserved23", "ERR_Reserved24", "ERR_Reserved25",
    161 	"ERR_Reserved26", "ERR_Reserved27", "ERR_Reserved28",
    162 	"ERR_Reserved29", "ERR_Reserved30", "ERR_Reserved31",
    163 };
    164 
    165 /*
    166  * Mbus Target and Attribute bindings for ARMADA XP
    167  */
    168 static struct mbus_description {
    169 	uint8_t target;
    170 	uint8_t attr;
    171 	const char *string;
    172 } mbus_desc[] = {
    173 	/* DDR */
    174 	{ ARMADAXP_UNITID_DDR, ARMADAXP_ATTR_DDR_CS0,
    175 	       	"DDR(M_CS[0])" },
    176 	{ ARMADAXP_UNITID_DDR, ARMADAXP_ATTR_DDR_CS1,
    177 	       	"DDR(M_CS[1])" },
    178 	{ ARMADAXP_UNITID_DDR, ARMADAXP_ATTR_DDR_CS2,
    179 	       	"DDR(M_CS[2])" },
    180 	{ ARMADAXP_UNITID_DDR, ARMADAXP_ATTR_DDR_CS3,
    181 	       	"DDR(M_CS[3])" },
    182 
    183 	/* DEVBUS */
    184 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI0_CS0,
    185 	       	"DEVBUS(SPI0 CS0)" },
    186 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI0_CS1,
    187 	       	"DEVBUS(SPI0 CS1)" },
    188 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI0_CS2,
    189 	       	"DEVBUS(SPI0 CS2)" },
    190 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI0_CS3,
    191 	       	"DEVBUS(SPI0 CS3)" },
    192 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI0_CS4,
    193 	       	"DEVBUS(SPI0 CS4)" },
    194 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI0_CS5,
    195 	       	"DEVBUS(SPI0 CS5)" },
    196 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI0_CS6,
    197 	       	"DEVBUS(SPI0 CS6)" },
    198 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI0_CS7,
    199 	       	"DEVBUS(SPI0 CS7)" },
    200 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI1_CS0,
    201 	       	"DEVBUS(SPI1 CS0)" },
    202 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI1_CS1,
    203 	       	"DEVBUS(SPI1 CS1)" },
    204 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI1_CS2,
    205 	       	"DEVBUS(SPI1 CS2)" },
    206 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI1_CS3,
    207 	       	"DEVBUS(SPI1 CS3)" },
    208 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI1_CS4,
    209 	       	"DEVBUS(SPI1 CS4)" },
    210 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI1_CS5,
    211 	       	"DEVBUS(SPI1 CS5)" },
    212 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI1_CS6,
    213 	       	"DEVBUS(SPI1 CS6)" },
    214 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI1_CS7,
    215 	       	"DEVBUS(SPI1 CS7)" },
    216 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_DEV_CS0,
    217 	       	"DEVBUS(DevCS[0])" },
    218 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_DEV_CS1,
    219 	       	"DEVBUS(DevCS[1])" },
    220 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_DEV_CS2,
    221 	       	"DEVBUS(DevCS[2])" },
    222 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_DEV_CS3,
    223 	       	"DEVBUS(DevCS[3])" },
    224 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_BOOT_CS,
    225 	       	"DEVBUS(BootCS)" },
    226 	{ ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_BOOT_ROM,
    227 	       	"DEVBUS(BootROM)" },
    228 
    229 	/* GbE */
    230 	{ ARMADAXP_UNITID_GBE0, ARMADAXP_ATTR_GBE_RESERVED,
    231 	       	"GBE0 GBE1" },
    232 	{ ARMADAXP_UNITID_GBE2, ARMADAXP_ATTR_GBE_RESERVED,
    233 	       	"GBE2 GBE3" },
    234 
    235 	/* PEX(PCIe) */
    236 	{ ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx0_MEM,
    237 	       	"PEX0(Lane0, Memory)" },
    238 	{ ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx1_MEM,
    239 	       	"PEX0(Lane1, Memory)" },
    240 	{ ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx2_MEM,
    241 	       	"PEX0(Lane2, Memory)" },
    242 	{ ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx3_MEM,
    243 	       	"PEX0(Lane3, Memory)" },
    244 	{ ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEX2_MEM,
    245 	       	"PEX2(Lane0, Memory)" },
    246 	{ ARMADAXP_UNITID_PEX1, ARMADAXP_ATTR_PEXx0_MEM,
    247 	       	"PEX1(Lane0, Memory)" },
    248 	{ ARMADAXP_UNITID_PEX1, ARMADAXP_ATTR_PEXx1_MEM,
    249 	       	"PEX1(Lane1, Memory)" },
    250 	{ ARMADAXP_UNITID_PEX1, ARMADAXP_ATTR_PEXx2_MEM,
    251 	       	"PEX1(Lane2, Memory)" },
    252 	{ ARMADAXP_UNITID_PEX1, ARMADAXP_ATTR_PEXx3_MEM,
    253 	       	"PEX1(Lane3, Memory)" },
    254 	{ ARMADAXP_UNITID_PEX1, ARMADAXP_ATTR_PEX2_MEM,
    255 	       	"PEX3(Lane0, Memory)" },
    256 	{ ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx0_IO,
    257 	       	"PEX0(Lane0, I/O)" },
    258 	{ ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx1_IO,
    259 	       	"PEX0(Lane1, I/O)" },
    260 	{ ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx2_IO,
    261 	       	"PEX0(Lane2, I/O)" },
    262 	{ ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx3_IO,
    263 	       	"PEX0(Lane3, I/O)" },
    264 	{ ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEX2_IO,
    265 	       	"PEX2(Lane0, I/O)" },
    266 	{ ARMADAXP_UNITID_PEX1, ARMADAXP_ATTR_PEXx0_IO,
    267 	       	"PEX1(Lane0, I/O)" },
    268 	{ ARMADAXP_UNITID_PEX1, ARMADAXP_ATTR_PEXx1_IO,
    269 	       	"PEX1(Lane1, I/O)" },
    270 	{ ARMADAXP_UNITID_PEX1, ARMADAXP_ATTR_PEXx2_IO,
    271 	       	"PEX1(Lane2, I/O)" },
    272 	{ ARMADAXP_UNITID_PEX1, ARMADAXP_ATTR_PEXx3_IO,
    273 	       	"PEX1(Lane3, I/O)" },
    274 	{ ARMADAXP_UNITID_PEX1, ARMADAXP_ATTR_PEX2_IO,
    275 	       	"PEX3(Lane0, I/O)" },
    276 
    277 	/* CRYPT */
    278 	{ ARMADAXP_UNITID_CRYPT, ARMADAXP_ATTR_CRYPT0_NOSWAP,
    279 	       	"CESA0(No swap)" },
    280 	{ ARMADAXP_UNITID_CRYPT, ARMADAXP_ATTR_CRYPT0_SWAP_BYTE,
    281 	       	"CESA0(Byte swap)" },
    282 	{ ARMADAXP_UNITID_CRYPT, ARMADAXP_ATTR_CRYPT0_SWAP_BYTE_WORD,
    283 	       	"CESA0(Byte and word swap)" },
    284 	{ ARMADAXP_UNITID_CRYPT, ARMADAXP_ATTR_CRYPT0_SWAP_WORD,
    285 	       	"CESA0(Word swap)" },
    286 	{ ARMADAXP_UNITID_CRYPT, ARMADAXP_ATTR_CRYPT1_NOSWAP,
    287 	       	"CESA1(No swap)" },
    288 	{ ARMADAXP_UNITID_CRYPT, ARMADAXP_ATTR_CRYPT1_SWAP_BYTE,
    289 	       	"CESA1(Byte swap)" },
    290 	{ ARMADAXP_UNITID_CRYPT, ARMADAXP_ATTR_CRYPT1_SWAP_BYTE_WORD,
    291 	       	"CESA1(Byte and word swap)" },
    292 	{ ARMADAXP_UNITID_CRYPT, ARMADAXP_ATTR_CRYPT1_SWAP_WORD,
    293 	       	"CESA1(Word swap)" },
    294 
    295 	/* BM */
    296 	{ ARMADAXP_UNITID_BM, ARMADAXP_ATTR_BM_RESERVED,
    297 		"BM" },
    298 
    299 	/* NAND */
    300 	{ ARMADAXP_UNITID_NAND, ARMADAXP_ATTR_NAND_RESERVED,
    301 		"NAND" },
    302 };
    303 
    304 /*
    305  * Default Mbus addrss decoding table for ARMADA XP
    306  * this table may changed by device drivers.
    307  *
    308  * NOTE: some version of u-boot is broken. it writes old decoding table.
    309  *       probably, it's designed for Kirkwood SoC or older. we need to restore
    310  *       ARMADA XP's parameter set.
    311  */
    312 static struct mbus_table_def {
    313 	int window;	/* index of address decoding window registers */
    314 	uint32_t base;	/* base address of the window */
    315 	uint32_t size;	/* size of the window */
    316 	uint8_t target;	/* target unit of the window */
    317 	uint8_t attr;	/* target attribute of the window */
    318 } mbus_table[] = {
    319 	/*
    320 	 * based on 'default address mapping' described in Marvell's document
    321 	 * 'ARMADA XP Functional Specifications.'
    322 	 *
    323 	 * some windows are modified to get compatibility with old codes.
    324 	 */
    325 	{
    326 		/* PCIe 0 lane0 MEM */
    327 		/* MODIFIED (moved to MARVELL_PEXMEM_PBASE) */
    328 		 0, 0xe0000000, 0x01000000,
    329 		 ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx0_MEM
    330 	},
    331 	{
    332 		/* PCIe 0 lane1 MEM */
    333 		 1, 0x88000000, 0x08000000,
    334 		 ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx1_MEM
    335 	},
    336 	{
    337 		/* PCIe 0 lane2 MEM */
    338 		 2, 0x90000000, 0x08000000,
    339 		 ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx2_MEM
    340 	},
    341 	{
    342 		/* PCIe 0 lane3 MEM */
    343 		 3, 0x98000000, 0x08000000,
    344 		 ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx3_MEM
    345 	},
    346 	{
    347 		/* PCIe 1 lane0 MEM */
    348 		 4, 0xa0000000, 0x08000000,
    349 		 ARMADAXP_UNITID_PEX1, ARMADAXP_ATTR_PEXx0_MEM
    350 	},
    351 	{	5, 0, 0, 0, 0 /* disabled */ },
    352 	{	6, 0, 0, 0, 0 /* disabled */ },
    353 	{	7, 0, 0, 0, 0 /* disabled */ },
    354 	{
    355 		/* Security Accelerator SRAM, Engine 0, no data swap */
    356 		 8, 0xc8010000, 0x00010000,
    357 		 ARMADAXP_UNITID_CRYPT, ARMADAXP_ATTR_CRYPT0_NOSWAP,
    358 	},
    359 	{
    360 		/* Device bus, BOOT_CS */
    361 		 9, 0xd8000000, 0x08000000,
    362 		 ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_BOOT_CS,
    363 	},
    364 	{
    365 		/* Device bus, DEV_CS[0] */
    366 		/* MODIFIED (moved, conflict to MARVELL_PEXMEM_PBASE here.) */
    367 		10, 0x80000000, 0x08000000,
    368 		ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_DEV_CS0
    369 	},
    370 	{
    371 		/* Device bus, DEV_CS[1] */
    372 		11, 0xe8000000, 0x08000000,
    373 		ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_DEV_CS1
    374 	},
    375 	{
    376 		/* Device bus, DEV_CS[2] */
    377 		/* MODIFIED: (disabled, conflict to MARVELL_PEXIO_PBASE) */
    378 		12, 0xf0000000, 0x00000000,
    379 		ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_DEV_CS2
    380 	},
    381 	{
    382 		/* Device bus, BOOT_ROM */
    383 		13, 0xf8000000, 0x08000000,
    384 		ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_BOOT_ROM
    385 	},
    386 	{
    387 		/* Device bus, SPI0_CS[0] */
    388 		14, 0xd4000000, 0x04000000,
    389 		ARMADAXP_UNITID_DEVBUS, ARMADAXP_ATTR_DEVBUS_SPI0_CS0
    390 	},
    391 	{
    392 		/* Security Accelerator SRAM, Engine 1, no data swap */
    393 		/* MODIFIED (added, 0xd0300000-0xd030ffff) */
    394 		15, 0xd0300000, 0x00010000,
    395 	       	ARMADAXP_UNITID_CRYPT, ARMADAXP_ATTR_CRYPT1_NOSWAP
    396 	},
    397 	{
    398 		/* PCIe 0 lane 0 I/O */
    399 		/* MODIFIED (added, MARVELL_PEXIO_PBASE) */
    400 		16, 0xf2000000, 0x00100000,
    401 	       	ARMADAXP_UNITID_PEX0, ARMADAXP_ATTR_PEXx0_IO
    402        	},
    403 	{	17, 0xd0320000, 0, 0, 0 /* disabled */ },
    404 	{
    405 		/* Buffer Manamgement unit */
    406 		18, 0xd3800000, 0x00800000,
    407 		ARMADAXP_UNITID_BM, ARMADAXP_ATTR_BM_RESERVED
    408 	},
    409 	{
    410 		/* DDR */
    411 		/* MODIFIED (up to 2GB memory space) */
    412 		19, 0x00000000, 0x80000000,
    413 		ARMADAXP_UNITID_DDR, ARMADAXP_ATTR_DDR_CS0
    414 	},
    415 
    416 };
    417 
    418 static struct vco_freq_ratio freq_conf_table[] = {
    419 /*00*/	{ 1, 1,	 4,  2 },
    420 /*01*/	{ 1, 2,	 2,  2 },
    421 /*02*/	{ 2, 2,	 6,  3 },
    422 /*03*/	{ 2, 2,	 3,  3 },
    423 /*04*/	{ 1, 2,	 3,  3 },
    424 /*05*/	{ 1, 2,	 4,  2 },
    425 /*06*/	{ 1, 1,	 2,  2 },
    426 /*07*/	{ 2, 3,	 6,  6 },
    427 /*08*/	{ 2, 3,	 5,  5 },
    428 /*09*/	{ 1, 2,	 6,  3 },
    429 /*10*/	{ 2, 4,	10,  5 },
    430 /*11*/	{ 1, 3,	 6,  6 },
    431 /*12*/	{ 1, 2,	 5,  5 },
    432 /*13*/	{ 1, 3,	 6,  3 },
    433 /*14*/	{ 1, 2,	 5,  5 },
    434 /*15*/	{ 2, 2,	 5,  5 },
    435 /*16*/	{ 1, 1,	 3,  3 },
    436 /*17*/	{ 2, 5,	10, 10 },
    437 /*18*/	{ 1, 3,	 8,  4 },
    438 /*19*/	{ 1, 1,	 2,  1 },
    439 /*20*/	{ 2, 3,	 6,  3 },
    440 /*21*/	{ 1, 2,	 8,  4 },
    441 /*22*/	{ 2, 5,	10,  5 }
    442 };
    443 
    444 static uint16_t clock_table_xp[] = {
    445 	1000, 1066, 1200, 1333, 1500, 1666, 1800, 2000,
    446 	 600,  667,  800, 1600, 2133, 2200, 2400
    447 };
    448 static uint16_t clock_table_370[] = {
    449 	 400,  533,  667,  800, 1000, 1067, 1200, 1333,
    450 	1500, 1600, 1667, 1800, 2000,  333,  600,  900,
    451 	   0
    452 };
    453 
    454 static struct pic_ops armadaxp_picops = {
    455 	.pic_unblock_irqs = armadaxp_pic_unblock_irqs,
    456 	.pic_block_irqs = armadaxp_pic_block_irqs,
    457 	.pic_establish_irq = armadaxp_pic_establish_irq,
    458 	.pic_set_priority = armadaxp_pic_set_priority,
    459 	.pic_source_name = armadaxp_pic_source_name,
    460 };
    461 
    462 static struct pic_softc armadaxp_pic = {
    463 	.pic_ops = &armadaxp_picops,
    464 	.pic_name = "armadaxp",
    465 };
    466 
    467 static struct pic_ops armadaxp_err_picops = {
    468 	.pic_unblock_irqs = armadaxp_err_pic_unblock_irqs,
    469 	.pic_block_irqs = armadaxp_err_pic_block_irqs,
    470 	.pic_establish_irq = armadaxp_err_pic_establish_irq,
    471 	.pic_find_pending_irqs = armadaxp_err_pic_pending_irqs,
    472 	.pic_source_name = armadaxp_err_pic_source_name,
    473 };
    474 
    475 static struct pic_softc armadaxp_err_pic = {
    476 	.pic_ops = &armadaxp_err_picops,
    477 	.pic_name = "armadaxp_err",
    478 };
    479 
    480 static struct {
    481 	bus_size_t offset;
    482 	uint32_t bits;
    483 } clkgatings[]= {
    484 	{ ARMADAXP_GBE3_BASE,	(1 << 1) },
    485 	{ ARMADAXP_GBE2_BASE,	(1 << 2) },
    486 	{ ARMADAXP_GBE1_BASE,	(1 << 3) },
    487 	{ ARMADAXP_GBE0_BASE,	(1 << 4) },
    488 	{ MVSOC_PEX_BASE,	(1 << 5) },
    489 	{ ARMADAXP_PEX01_BASE,	(1 << 6) },
    490 	{ ARMADAXP_PEX02_BASE,	(1 << 7) },
    491 	{ ARMADAXP_PEX03_BASE,	(1 << 8) },
    492 	{ ARMADAXP_PEX10_BASE,	(1 << 9) },
    493 	{ ARMADAXP_PEX11_BASE,	(1 << 10) },
    494 	{ ARMADAXP_PEX12_BASE,	(1 << 11) },
    495 	{ ARMADAXP_PEX13_BASE,	(1 << 12) },
    496 #if 0
    497 	{ NetA, (1 << 13) },
    498 #endif
    499 	{ ARMADAXP_SATAHC_BASE,	(1 << 14) | (1 << 15) | (1 << 29) | (1 << 30) },
    500 	{ ARMADAXP_LCD_BASE,	(1 << 16) },
    501 	{ ARMADAXP_SDIO_BASE,	(1 << 17) },
    502 	{ ARMADAXP_USB1_BASE,	(1 << 19) },
    503 	{ ARMADAXP_USB2_BASE,	(1 << 20) },
    504 	{ ARMADAXP_CESA0_BASE,	(1 << 23) },
    505 	{ ARMADAXP_CESA1_BASE,	(1 << 23) },
    506 	{ ARMADAXP_PEX2_BASE,	(1 << 26) },
    507 	{ ARMADAXP_PEX3_BASE,	(1 << 27) },
    508 #if 0
    509 	{ DDR, (1 << 28) },
    510 #endif
    511 };
    512 
    513 /*
    514  * armadaxp_intr_bootstrap:
    515  *
    516  *	Initialize the rest of the interrupt subsystem, making it
    517  *	ready to handle interrupts from devices.
    518  */
    519 void
    520 armadaxp_intr_bootstrap(bus_addr_t pbase)
    521 {
    522 	int i;
    523 
    524 	/* Map MPIC base and MPIC percpu base registers */
    525 	if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_BASE,
    526 	    0x500, 0, &mpic_handle) != 0)
    527 		panic("%s: Could not map MPIC registers", __func__);
    528 	if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_CPU_BASE,
    529 	    0x800, 0, &mpic_cpu_handle) != 0)
    530 		panic("%s: Could not map MPIC percpu registers", __func__);
    531 
    532 	/* Disable all interrupts */
    533 	for (i = 0; i < ARMADAXP_IRQ_SOURCES; i++)
    534 		MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, i);
    535 
    536 	mvsoc_intr_init = armadaxp_intr_init;
    537 }
    538 
    539 static void
    540 armadaxp_intr_init(void)
    541 {
    542 	int ctrl;
    543 	void *ih __diagused;
    544 
    545 	/* Get max interrupts */
    546 	armadaxp_pic.pic_maxsources =
    547 	    ((MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL) >> 2) & 0x7FF);
    548 
    549 	if (!armadaxp_pic.pic_maxsources)
    550 		armadaxp_pic.pic_maxsources = ARMADAXP_IRQ_SOURCES;
    551 
    552 	pic_add(&armadaxp_pic, 0);
    553 
    554 	/* Chain error interrupts controller */
    555 	MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ERR_MASK, 0);
    556 	armadaxp_err_pic.pic_maxsources = ARMADAXP_IRQ_ERROR_SOURCES;
    557 	pic_add(&armadaxp_err_pic, ARMADAXP_IRQ_ERROR_BASE);
    558 	ih = intr_establish(ARMADAXP_IRQ_ERR_SUMMARY, IPL_HIGH, IST_LEVEL_HIGH,
    559 	    pic_handle_intr, &armadaxp_err_pic);
    560 	KASSERT(ih != NULL);
    561 
    562 	ctrl = MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL);
    563 	/* Enable IRQ prioritization */
    564 	ctrl |= (1 << 0);
    565 	MPIC_WRITE(ARMADAXP_MLMB_MPIC_CTRL, ctrl);
    566 
    567 	find_pending_irqs = armadaxp_find_pending_irqs;
    568 }
    569 
    570 static void
    571 armadaxp_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
    572     uint32_t irq_mask)
    573 {
    574 	int n;
    575 
    576 	while (irq_mask != 0) {
    577 		n = ffs(irq_mask) - 1;
    578 		KASSERT(pic->pic_maxsources >= n + irqbase);
    579 		MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISE, n + irqbase);
    580 		MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ICM, n + irqbase);
    581 		if ((n + irqbase) == 0)
    582 			MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_DOORBELL_MASK,
    583 			    0xffffffff);
    584 		irq_mask &= ~__BIT(n);
    585 	}
    586 }
    587 
    588 static void
    589 armadaxp_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
    590     uint32_t irq_mask)
    591 {
    592 	int n;
    593 
    594 	while (irq_mask != 0) {
    595 		n = ffs(irq_mask) - 1;
    596 		KASSERT(pic->pic_maxsources >= n + irqbase);
    597 		MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, n + irqbase);
    598 		MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, n + irqbase);
    599 		irq_mask &= ~__BIT(n);
    600 	}
    601 }
    602 
    603 static void
    604 armadaxp_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
    605 {
    606 	int tmp;
    607 	KASSERT(pic->pic_maxsources >= is->is_irq);
    608 	tmp = MPIC_READ(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4);
    609 	/* Clear previous priority */
    610 	tmp &= ~(0xf << MPIC_ISCR_SHIFT);
    611 	MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4,
    612 	    tmp | (is->is_ipl << MPIC_ISCR_SHIFT));
    613 }
    614 
    615 static void
    616 armadaxp_pic_set_priority(struct pic_softc *pic, int ipl)
    617 {
    618 	int ctp;
    619 
    620 	ctp = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_CTP);
    621 	ctp &= ~(0xf << MPIC_CTP_SHIFT);
    622 	ctp |= (ipl << MPIC_CTP_SHIFT);
    623 	MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_CTP, ctp);
    624 }
    625 
    626 static void
    627 armadaxp_pic_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
    628 {
    629 	if (irq > __arraycount(armadaxp_pic_source_names)) {
    630 		snprintf(buf, len, "Unknown IRQ %d", irq);
    631 		return;
    632 	}
    633 	strlcpy(buf, armadaxp_pic_source_names[irq], len);
    634 }
    635 
    636 static int
    637 armadaxp_find_pending_irqs(void)
    638 {
    639 	struct intrsource *is;
    640 	int irq;
    641 
    642 	irq = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_IIACK) & 0x3ff;
    643 
    644 	/* Is it a spurious interrupt ?*/
    645 	if (irq == 0x3ff)
    646 		return 0;
    647 	is = armadaxp_pic.pic_sources[irq];
    648 	if (is == NULL) {
    649 		printf("stray interrupt: %d\n", irq);
    650 		return 0;
    651 	}
    652 
    653 	armadaxp_pic_block_irq(&armadaxp_pic, irq);
    654 	pic_mark_pending(&armadaxp_pic, irq);
    655 
    656 	return is->is_ipl;
    657 }
    658 
    659 static void
    660 armadaxp_pic_block_irq(struct pic_softc *pic, size_t irq)
    661 {
    662 
    663 	KASSERT(pic->pic_maxsources >= irq);
    664 	MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, irq);
    665 	MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, irq);
    666 }
    667 
    668 static void
    669 armadaxp_err_pic_source_name(struct pic_softc *pic, int irq,
    670     char *buf, size_t len)
    671 {
    672 	if (irq > __arraycount(armadaxp_err_pic_source_names)) {
    673 		snprintf(buf, len, "Unknown IRQ %d", irq);
    674 		return;
    675 	}
    676 	strlcpy(buf, armadaxp_err_pic_source_names[irq], len);
    677 }
    678 
    679 
    680 /*
    681  * ARMADAXP_MLMB_MPIC_ERR_CAUSE
    682  */
    683 static void
    684 armadaxp_err_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
    685     uint32_t irq_mask)
    686 {
    687 	uint32_t reg;
    688 
    689 	KASSERT(irqbase == 0); /* XXX: support offset */
    690 
    691 	reg = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_ERR_MASK);
    692 	reg |= irq_mask;
    693 	MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ERR_MASK, reg);
    694 }
    695 
    696 static void
    697 armadaxp_err_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
    698     uint32_t irq_mask)
    699 {
    700 	uint32_t reg;
    701 
    702 	KASSERT(irqbase == 0); /* XXX: support offset */
    703 
    704 	reg = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_ERR_MASK);
    705 	reg &= ~irq_mask;
    706 	MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ERR_MASK, reg);
    707 }
    708 
    709 static void
    710 armadaxp_err_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
    711 {
    712 	uint32_t reg;
    713 
    714 	KASSERT(pic->pic_maxsources >= is->is_irq);
    715 
    716 	reg = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_ERR_MASK);
    717 	reg |= ARMADAXP_IRQ_ERROR_BIT(is->is_irq);
    718 	MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ERR_MASK, reg);
    719 }
    720 
    721 static int
    722 armadaxp_err_pic_pending_irqs(struct pic_softc *pic)
    723 {
    724 	struct intrsource *is;
    725 	uint32_t reg;
    726 	int irq;
    727 
    728 	reg = MPIC_READ(ARMADAXP_MLMB_MPIC_ERR_CAUSE);
    729 	irq = ffs(reg);
    730 	if (irq == 0)
    731 		return 0;
    732 	irq--; /* bit number to index */
    733 
    734 	is = pic->pic_sources[irq];
    735 	if (is == NULL) {
    736 		printf("stray interrupt: %d\n", irq);
    737 		return 0;
    738 	}
    739 	return pic_mark_pending_sources(pic, 0, irq);
    740 }
    741 
    742 
    743 /*
    744  * Clock functions
    745  */
    746 
    747 void
    748 armadaxp_getclks(void)
    749 {
    750 	uint64_t sar_reg;
    751 	uint8_t  sar_cpu_freq, sar_fab_freq;
    752 
    753 	if (cputype == CPU_ID_MV88SV584X_V7)
    754 		mvTclk = 250000000; /* 250 MHz */
    755 	else
    756 		mvTclk = 200000000; /* 200 MHz */
    757 
    758 	sar_reg = (read_miscreg(ARMADAXP_MISC_SAR_HI) << 31) |
    759 	    read_miscreg(ARMADAXP_MISC_SAR_LO);
    760 
    761 	sar_cpu_freq = EXTRACT_XP_CPU_FREQ_FIELD(sar_reg);
    762 	sar_fab_freq = EXTRACT_XP_FAB_FREQ_FIELD(sar_reg);
    763 
    764 	/* Check if CPU frequency field has correct value */
    765 	if (sar_cpu_freq >= __arraycount(clock_table_xp))
    766 		panic("Reserved value in cpu frequency configuration field: "
    767 		    "%d", sar_cpu_freq);
    768 
    769 	/* Check if fabric frequency field has correct value */
    770 	if (sar_fab_freq >= __arraycount(freq_conf_table))
    771 		panic("Reserved value in fabric frequency configuration field: "
    772 		    "%d", sar_fab_freq);
    773 
    774 	/* Get CPU clock frequency */
    775 	mvPclk = clock_table_xp[sar_cpu_freq] *
    776 	    freq_conf_table[sar_fab_freq].vco_cpu;
    777 
    778 	/* Get L2CLK clock frequency and use as system clock (mvSysclk) */
    779 	mvSysclk = mvPclk / freq_conf_table[sar_fab_freq].vco_l2c;
    780 
    781 	/* Round mvSysclk value to integer MHz */
    782 	if (((mvPclk % freq_conf_table[sar_fab_freq].vco_l2c) * 10 /
    783 	    freq_conf_table[sar_fab_freq].vco_l2c) >= 5)
    784 		mvSysclk++;
    785 
    786 	mvPclk *= 1000000;
    787 	mvSysclk *= 1000000;
    788 
    789 	curcpu()->ci_data.cpu_cc_freq = mvPclk;
    790 }
    791 
    792 void
    793 armada370_getclks(void)
    794 {
    795 	uint32_t sar;
    796 	uint8_t  cpu_freq, fab_freq;
    797 
    798 	sar = read_miscreg(ARMADAXP_MISC_SAR_LO);
    799 	if (sar & 0x00100000)
    800 		mvTclk = 200000000; /* 200 MHz */
    801 	else
    802 		mvTclk = 166666667; /* 166 MHz */
    803 
    804 	cpu_freq = EXTRACT_370_CPU_FREQ_FIELD(sar);
    805 	fab_freq = EXTRACT_370_FAB_FREQ_FIELD(sar);
    806 
    807 	/* Check if CPU frequency field has correct value */
    808 	if (cpu_freq >= __arraycount(clock_table_370))
    809 		panic("Reserved value in cpu frequency configuration field: "
    810 		    "%d", cpu_freq);
    811 
    812 	/* Check if fabric frequency field has correct value */
    813 	if (fab_freq >= __arraycount(freq_conf_table))
    814 		panic("Reserved value in fabric frequency configuration field: "
    815 		    "%d", fab_freq);
    816 
    817 	/* Get CPU clock frequency */
    818 	mvPclk = clock_table_370[cpu_freq] *
    819 	    freq_conf_table[fab_freq].vco_cpu;
    820 
    821 	/* Get L2CLK clock frequency and use as system clock (mvSysclk) */
    822 	mvSysclk = mvPclk / freq_conf_table[fab_freq].vco_l2c;
    823 
    824 	/* Round mvSysclk value to integer MHz */
    825 	if (((mvPclk % freq_conf_table[fab_freq].vco_l2c) * 10 /
    826 	    freq_conf_table[fab_freq].vco_l2c) >= 5)
    827 		mvSysclk++;
    828 
    829 	mvPclk *= 1000000;
    830 	mvSysclk *= 1000000;
    831 }
    832 
    833 /*
    834  * L2 Cache initialization
    835  */
    836 
    837 int
    838 armadaxp_l2_init(bus_addr_t pbase)
    839 {
    840 	u_int32_t reg;
    841 	int ret;
    842 
    843 	/* Map L2 space */
    844 	ret = bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_L2_BASE,
    845 	    0x1000, 0, &l2_handle);
    846 	if (ret) {
    847 		printf("%s: Cannot map L2 register space, ret:%d\n",
    848 		    __func__, ret);
    849 		return (-1);
    850 	}
    851 
    852 	/* Variables for cpufunc_asm_pj4b.S */
    853 	/* XXX: per cpu register. need to support SMP */
    854 	armadaxp_l2_barrier_reg = mlmb_base + MVSOC_MLMB_CIB_BARRIER(0);
    855 
    856 	/* Set L2 policy */
    857 	reg = L2_READ(ARMADAXP_L2_AUX_CTRL);
    858 	reg &= ~(L2_AUX_WBWT_MODE_MASK);
    859 	reg &= ~(L2_AUX_REP_STRAT_MASK);
    860 	reg |= L2_AUX_ECC_ENABLE;
    861 	reg |= L2_AUX_PARITY_ENABLE;
    862 	reg |= L2_AUX_WBWT_MODE_BY_ATTR;
    863 	reg |= L2_AUX_FORCE_WA_BY_ATTR;
    864 	reg |= L2_AUX_REP_STRAT_SEMIPLRU;
    865 	L2_WRITE(ARMADAXP_L2_AUX_CTRL, reg);
    866 
    867 	/* Invalidate L2 cache */
    868 	L2_WRITE(ARMADAXP_L2_INV_WAY, L2_ALL_WAYS);
    869 
    870 	/* Clear pending L2 interrupts */
    871 	L2_WRITE(ARMADAXP_L2_INT_CAUSE, 0x1ff);
    872 
    873 	/* Enable Cache and TLB maintenance broadcast */
    874 	__asm__ __volatile__ ("mrc p15, 1, %0, c15, c2, 0" : "=r"(reg));
    875 	reg |= (1 << 8);
    876 	__asm__ __volatile__ ("mcr p15, 1, %0, c15, c2, 0" : :"r"(reg));
    877 
    878 	/*
    879 	 * Set the Point of Coherency and Point of Unification to DRAM.
    880 	 * This is a reset value but anyway, configure this just in case.
    881 	 */
    882 	reg = read_mlmbreg(ARMADAXP_L2_CFU);
    883 	reg |= (1 << 17) | (1 << 18);
    884 	write_mlmbreg(ARMADAXP_L2_CFU, reg);
    885 
    886 	/* Enable L2 cache */
    887 	reg = L2_READ(ARMADAXP_L2_CTRL);
    888 	L2_WRITE(ARMADAXP_L2_CTRL, reg | L2_CTRL_ENABLE);
    889 
    890 	/* Mark as enabled */
    891 	l2cache_state = 1;
    892 
    893 #ifdef DEBUG
    894 	/* Configure and enable counter */
    895 	L2_WRITE(ARMADAXP_L2_CNTR_CONF(0), 0xf0000 | (4 << 2));
    896 	L2_WRITE(ARMADAXP_L2_CNTR_CONF(1), 0xf0000 | (2 << 2));
    897 	L2_WRITE(ARMADAXP_L2_CNTR_CTRL, 0x303);
    898 #endif
    899 
    900 	return (0);
    901 }
    902 
    903 void
    904 armadaxp_sdcache_inv_all(void)
    905 {
    906 	L2_WRITE(ARMADAXP_L2_INV_WAY, L2_ALL_WAYS);
    907 }
    908 
    909 void
    910 armadaxp_sdcache_wb_all(void)
    911 {
    912 	L2_WRITE(ARMADAXP_L2_WB_WAY, L2_ALL_WAYS);
    913 	L2_WRITE(ARMADAXP_L2_SYNC, 0);
    914 	__asm__ __volatile__("dsb");
    915 }
    916 
    917 void
    918 armadaxp_sdcache_wbinv_all(void)
    919 {
    920 	L2_WRITE(ARMADAXP_L2_WBINV_WAY, L2_ALL_WAYS);
    921 	L2_WRITE(ARMADAXP_L2_SYNC, 0);
    922 	__asm__ __volatile__("dsb");
    923 }
    924 
    925 static paddr_t
    926 armadaxp_sdcache_wbalign_base(vaddr_t va, paddr_t pa, psize_t sz)
    927 {
    928 	paddr_t line_start = pa & ~ARMADAXP_L2_ALIGN;
    929 	vaddr_t save_start;
    930 	uint8_t save_buf[ARMADAXP_L2_LINE_SIZE];
    931 	size_t unalign;
    932 
    933 	unalign = va & ARMADAXP_L2_ALIGN;
    934 	if (unalign == 0)
    935 		return line_start;  /* request is aligned to cache line size */
    936 
    937 	/* save data that is not intended to invalidate */
    938 	save_start = va & ~ARMADAXP_L2_ALIGN;
    939 	memcpy(save_buf, (void *)save_start, unalign);
    940 
    941 	/* invalidate include saved data */
    942 	L2_WRITE(ARMADAXP_L2_INV_PHYS, line_start);
    943 
    944 	/* write back saved data */
    945 	memcpy((void *)save_start, save_buf, unalign);
    946 	L2_WRITE(ARMADAXP_L2_WB_PHYS, line_start);
    947 	L2_WRITE(ARMADAXP_L2_SYNC, 0);
    948 	__asm__ __volatile__("dsb");
    949 
    950 	return line_start;
    951 }
    952 
    953 static paddr_t
    954 armadaxp_sdcache_wbalign_end(vaddr_t va, paddr_t pa, psize_t sz)
    955 {
    956 	paddr_t line_start = (pa + sz - 1) & ~ARMADAXP_L2_ALIGN;
    957 	vaddr_t save_start = va + sz;
    958 	uint8_t save_buf[ARMADAXP_L2_LINE_SIZE];
    959 	size_t save_len;
    960 	size_t unalign;
    961 
    962 	unalign = save_start & ARMADAXP_L2_ALIGN;
    963 	if (unalign == 0)
    964 		return line_start; /* request is aligned to cache line size */
    965 
    966 	/* save data that is not intended to invalidate */
    967 	save_len = ARMADAXP_L2_LINE_SIZE - unalign;
    968 	memcpy(save_buf, (void *)save_start, save_len);
    969 
    970 	/* invalidate include saved data */
    971 	L2_WRITE(ARMADAXP_L2_INV_PHYS, line_start);
    972 
    973 	/* write back saved data */
    974 	memcpy((void *)save_start, save_buf, save_len);
    975 	L2_WRITE(ARMADAXP_L2_WB_PHYS, line_start);
    976 	__asm__ __volatile__("dsb");
    977 
    978 	return line_start;
    979 }
    980 
    981 void
    982 armadaxp_sdcache_inv_range(vaddr_t va, paddr_t pa, psize_t sz)
    983 {
    984 	paddr_t pa_base;
    985 	paddr_t pa_end;
    986 
    987 	/* align and write-back the boundary */
    988 	pa_base = armadaxp_sdcache_wbalign_base(va, pa, sz);
    989 	pa_end = armadaxp_sdcache_wbalign_end(va, pa, sz);
    990 
    991 	/* invalidate other cache */
    992 	if (pa_base == pa_end) {
    993 		L2_WRITE(ARMADAXP_L2_INV_PHYS, pa_base);
    994 		return;
    995 	}
    996 
    997 	L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
    998 	L2_WRITE(ARMADAXP_L2_INV_RANGE, pa_end);
    999 }
   1000 
   1001 void
   1002 armadaxp_sdcache_wb_range(vaddr_t va, paddr_t pa, psize_t sz)
   1003 {
   1004 	paddr_t pa_base = pa & ~ARMADAXP_L2_ALIGN;
   1005 	paddr_t pa_end  = (pa + sz - 1) & ~ARMADAXP_L2_ALIGN;
   1006 
   1007 	if (pa_base == pa_end)
   1008 		L2_WRITE(ARMADAXP_L2_WB_PHYS, pa_base);
   1009 	else {
   1010 		L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
   1011 		L2_WRITE(ARMADAXP_L2_WB_RANGE, pa_end);
   1012 	}
   1013 	L2_WRITE(ARMADAXP_L2_SYNC, 0);
   1014 	__asm__ __volatile__("dsb");
   1015 }
   1016 
   1017 void
   1018 armadaxp_sdcache_wbinv_range(vaddr_t va, paddr_t pa, psize_t sz)
   1019 {
   1020 	paddr_t pa_base = pa & ~ARMADAXP_L2_ALIGN;;
   1021 	paddr_t pa_end  = (pa + sz - 1) & ~ARMADAXP_L2_ALIGN;
   1022 
   1023 	if (pa_base == pa_end)
   1024 		L2_WRITE(ARMADAXP_L2_WBINV_PHYS, pa_base);
   1025 	else {
   1026 		L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
   1027 		L2_WRITE(ARMADAXP_L2_WBINV_RANGE, pa_end);
   1028 	}
   1029 	L2_WRITE(ARMADAXP_L2_SYNC, 0);
   1030 	__asm__ __volatile__("dsb");
   1031 }
   1032 
   1033 void
   1034 armadaxp_io_coherency_init(void)
   1035 {
   1036 	uint32_t reg;
   1037 
   1038 	/* set CIB read snoop command to ReadUnique */
   1039 	reg = read_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG);
   1040 	reg |= MVSOC_MLMB_CIB_CTRL_CFG_WB_EN;
   1041 	write_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG, reg);
   1042 
   1043 	/* enable CPUs in SMP group on Fabric coherency */
   1044 	reg = read_mlmbreg(MVSOC_MLMB_CFU_FAB_CTRL);
   1045 	reg |= MVSOC_MLMB_CFU_FAB_CTRL_SNOOP_CPU0;
   1046 	write_mlmbreg(MVSOC_MLMB_CFU_FAB_CTRL, reg);
   1047 
   1048 	/* send all snoop request to L2 cache */
   1049 	reg = read_mlmbreg(MVSOC_MLMB_CFU_CFG);
   1050 #ifdef L2CACHE_ENABLE
   1051 	reg |= MVSOC_MLMB_CFU_CFG_L2_NOTIFY;
   1052 #else
   1053 	reg &= ~MVSOC_MLMB_CFU_CFG_L2_NOTIFY;
   1054 #endif
   1055 	write_mlmbreg(MVSOC_MLMB_CFU_CFG, reg);
   1056 
   1057 	/* Mark as enabled */
   1058 	iocc_state = 1;
   1059 }
   1060 
   1061 int
   1062 armadaxp_clkgating(struct marvell_attach_args *mva)
   1063 {
   1064 	uint32_t val;
   1065 	int i;
   1066 
   1067 	for (i = 0; i < __arraycount(clkgatings); i++) {
   1068 		if (clkgatings[i].offset == mva->mva_offset) {
   1069 			val = read_miscreg(ARMADAXP_MISC_PMCGC);
   1070 			if ((val & clkgatings[i].bits) == clkgatings[i].bits)
   1071 				/* Clock enabled */
   1072 				return 0;
   1073 			return 1;
   1074 		}
   1075 	}
   1076 	/* Clock Gating not support */
   1077 	return 0;
   1078 }
   1079 
   1080 int
   1081 armadaxp_init_mbus(void)
   1082 {
   1083 	struct mbus_table_def *def;
   1084 	uint32_t reg;
   1085 	int i;
   1086 
   1087 	for (i = 0; i < nwindow; i++) {
   1088 		/* disable all windows */
   1089 		reg = read_mlmbreg(MVSOC_MLMB_WCR(i));
   1090 		reg &= ~MVSOC_MLMB_WCR_WINEN;
   1091 		write_mlmbreg(MVSOC_MLMB_WCR(i), reg);
   1092 		write_mlmbreg(MVSOC_MLMB_WBR(i), 0);
   1093 	}
   1094 
   1095 	for (i = 0; i < __arraycount(mbus_table); i++) {
   1096 		def = &mbus_table[i];
   1097 		if (def->window >= nwindow)
   1098 			continue;
   1099 		if (def->size == 0)
   1100 			continue;
   1101 
   1102 		/* restore window base */
   1103 		reg = def->base & MVSOC_MLMB_WBR_BASE_MASK;
   1104 		write_mlmbreg(MVSOC_MLMB_WBR(def->window), reg);
   1105 
   1106 		/* restore window configuration */
   1107 		reg  = MVSOC_MLMB_WCR_SIZE(def->size);
   1108 		reg |= MVSOC_MLMB_WCR_TARGET(def->target);
   1109 		reg |= MVSOC_MLMB_WCR_ATTR(def->attr);
   1110 #ifdef AURORA_IO_CACHE_COHERENCY
   1111 		reg |= MVSOC_MLMB_WCR_SYNC; /* enbale I/O coherency barrior */
   1112 #endif
   1113 		reg |= MVSOC_MLMB_WCR_WINEN;
   1114 		write_mlmbreg(MVSOC_MLMB_WCR(def->window), reg);
   1115 	}
   1116 
   1117 	return 0;
   1118 }
   1119 
   1120 int
   1121 armadaxp_attr_dump(struct mvsoc_softc *sc, uint32_t target, uint32_t attr)
   1122 {
   1123 	struct mbus_description *desc;
   1124 	int i;
   1125 
   1126 	for (i = 0; i < __arraycount(mbus_desc); i++) {
   1127 		desc = &mbus_desc[i];
   1128 		if (desc->target != target)
   1129 			continue;
   1130 		if (desc->attr != attr)
   1131 			continue;
   1132 		aprint_verbose_dev(sc->sc_dev, "%s", desc->string);
   1133 		return 0;
   1134 	}
   1135 
   1136 	/* unknown decoding target/attribute pair */
   1137 	aprint_verbose_dev(sc->sc_dev, "target 0x%x(attr 0x%x)", target, attr);
   1138 	return -1;
   1139 }
   1140