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