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