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