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