armadaxp.c revision 1.13 1 1.13 hsuenaga /* $NetBSD: armadaxp.c,v 1.13 2015/05/14 05:39:32 hsuenaga 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.13 hsuenaga __KERNEL_RCSID(0, "$NetBSD: armadaxp.c,v 1.13 2015/05/14 05:39:32 hsuenaga 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 #include <arm/pic/picvar.h>
53 1.1 rkujawa
54 1.1 rkujawa #include <arm/armreg.h>
55 1.1 rkujawa #include <arm/cpu.h>
56 1.1 rkujawa #include <arm/cpufunc.h>
57 1.1 rkujawa
58 1.1 rkujawa #include <arm/marvell/mvsocreg.h>
59 1.1 rkujawa #include <arm/marvell/mvsocvar.h>
60 1.3 kiyohara #include <arm/marvell/armadaxpreg.h>
61 1.9 hsuenaga #include <arm/marvell/armadaxpvar.h>
62 1.1 rkujawa
63 1.1 rkujawa #include <dev/marvell/marvellreg.h>
64 1.1 rkujawa
65 1.7 kiyohara #define EXTRACT_XP_CPU_FREQ_FIELD(sar) (((0x01 & (sar >> 52)) << 3) | \
66 1.1 rkujawa (0x07 & (sar >> 21)))
67 1.7 kiyohara #define EXTRACT_XP_FAB_FREQ_FIELD(sar) (((0x01 & (sar >> 51)) << 4) | \
68 1.1 rkujawa (0x0F & (sar >> 24)))
69 1.7 kiyohara #define EXTRACT_370_CPU_FREQ_FIELD(sar) ((sar >> 11) & 0xf)
70 1.7 kiyohara #define EXTRACT_370_FAB_FREQ_FIELD(sar) ((sar >> 15) & 0x1f)
71 1.1 rkujawa
72 1.1 rkujawa #define MPIC_WRITE(reg, val) (bus_space_write_4(&mvsoc_bs_tag, \
73 1.1 rkujawa mpic_handle, reg, val))
74 1.1 rkujawa #define MPIC_CPU_WRITE(reg, val) (bus_space_write_4(&mvsoc_bs_tag, \
75 1.1 rkujawa mpic_cpu_handle, reg, val))
76 1.1 rkujawa
77 1.1 rkujawa #define MPIC_READ(reg) (bus_space_read_4(&mvsoc_bs_tag, \
78 1.1 rkujawa mpic_handle, reg))
79 1.1 rkujawa #define MPIC_CPU_READ(reg) (bus_space_read_4(&mvsoc_bs_tag, \
80 1.1 rkujawa mpic_cpu_handle, reg))
81 1.1 rkujawa
82 1.1 rkujawa #define L2_WRITE(reg, val) (bus_space_write_4(&mvsoc_bs_tag, \
83 1.1 rkujawa l2_handle, reg, val))
84 1.1 rkujawa #define L2_READ(reg) (bus_space_read_4(&mvsoc_bs_tag, \
85 1.1 rkujawa l2_handle, reg))
86 1.1 rkujawa bus_space_handle_t mpic_cpu_handle;
87 1.1 rkujawa static bus_space_handle_t mpic_handle, l2_handle;
88 1.1 rkujawa int l2cache_state = 0;
89 1.1 rkujawa int iocc_state = 0;
90 1.5 kiyohara #define read_miscreg(r) (*(volatile uint32_t *)(misc_base + (r)))
91 1.5 kiyohara vaddr_t misc_base;
92 1.13 hsuenaga vaddr_t armadaxp_l2_barrier_reg;
93 1.1 rkujawa
94 1.1 rkujawa extern void (*mvsoc_intr_init)(void);
95 1.1 rkujawa static void armadaxp_intr_init(void);
96 1.1 rkujawa
97 1.1 rkujawa static void armadaxp_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
98 1.1 rkujawa static void armadaxp_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
99 1.1 rkujawa static void armadaxp_pic_establish_irq(struct pic_softc *, struct intrsource *);
100 1.4 kiyohara static void armadaxp_pic_set_priority(struct pic_softc *, int);
101 1.1 rkujawa
102 1.4 kiyohara static int armadaxp_find_pending_irqs(void);
103 1.4 kiyohara static void armadaxp_pic_block_irq(struct pic_softc *, size_t);
104 1.1 rkujawa
105 1.1 rkujawa struct vco_freq_ratio {
106 1.1 rkujawa uint8_t vco_cpu; /* VCO to CLK0(CPU) clock ratio */
107 1.1 rkujawa uint8_t vco_l2c; /* VCO to NB(L2 cache) clock ratio */
108 1.1 rkujawa uint8_t vco_hcl; /* VCO to HCLK(DDR controller) clock ratio */
109 1.1 rkujawa uint8_t vco_ddr; /* VCO to DR(DDR memory) clock ratio */
110 1.1 rkujawa };
111 1.1 rkujawa
112 1.1 rkujawa static struct vco_freq_ratio freq_conf_table[] = {
113 1.1 rkujawa /*00*/ { 1, 1, 4, 2 },
114 1.1 rkujawa /*01*/ { 1, 2, 2, 2 },
115 1.1 rkujawa /*02*/ { 2, 2, 6, 3 },
116 1.1 rkujawa /*03*/ { 2, 2, 3, 3 },
117 1.1 rkujawa /*04*/ { 1, 2, 3, 3 },
118 1.1 rkujawa /*05*/ { 1, 2, 4, 2 },
119 1.1 rkujawa /*06*/ { 1, 1, 2, 2 },
120 1.1 rkujawa /*07*/ { 2, 3, 6, 6 },
121 1.1 rkujawa /*08*/ { 2, 3, 5, 5 },
122 1.1 rkujawa /*09*/ { 1, 2, 6, 3 },
123 1.1 rkujawa /*10*/ { 2, 4, 10, 5 },
124 1.1 rkujawa /*11*/ { 1, 3, 6, 6 },
125 1.1 rkujawa /*12*/ { 1, 2, 5, 5 },
126 1.1 rkujawa /*13*/ { 1, 3, 6, 3 },
127 1.1 rkujawa /*14*/ { 1, 2, 5, 5 },
128 1.1 rkujawa /*15*/ { 2, 2, 5, 5 },
129 1.1 rkujawa /*16*/ { 1, 1, 3, 3 },
130 1.1 rkujawa /*17*/ { 2, 5, 10, 10 },
131 1.1 rkujawa /*18*/ { 1, 3, 8, 4 },
132 1.1 rkujawa /*19*/ { 1, 1, 2, 1 },
133 1.1 rkujawa /*20*/ { 2, 3, 6, 3 },
134 1.1 rkujawa /*21*/ { 1, 2, 8, 4 },
135 1.1 rkujawa /*22*/ { 2, 5, 10, 5 }
136 1.1 rkujawa };
137 1.1 rkujawa
138 1.7 kiyohara static uint16_t clock_table_xp[] = {
139 1.7 kiyohara 1000, 1066, 1200, 1333, 1500, 1666, 1800, 2000,
140 1.7 kiyohara 600, 667, 800, 1600, 2133, 2200, 2400
141 1.7 kiyohara };
142 1.7 kiyohara static uint16_t clock_table_370[] = {
143 1.7 kiyohara 400, 533, 667, 800, 1000, 1067, 1200, 1333,
144 1.7 kiyohara 1500, 1600, 1667, 1800, 2000, 333, 600, 900,
145 1.7 kiyohara 0
146 1.7 kiyohara };
147 1.1 rkujawa
148 1.1 rkujawa static struct pic_ops armadaxp_picops = {
149 1.1 rkujawa .pic_unblock_irqs = armadaxp_pic_unblock_irqs,
150 1.1 rkujawa .pic_block_irqs = armadaxp_pic_block_irqs,
151 1.1 rkujawa .pic_establish_irq = armadaxp_pic_establish_irq,
152 1.4 kiyohara .pic_set_priority = armadaxp_pic_set_priority,
153 1.1 rkujawa };
154 1.1 rkujawa
155 1.1 rkujawa static struct pic_softc armadaxp_pic = {
156 1.1 rkujawa .pic_ops = &armadaxp_picops,
157 1.1 rkujawa .pic_name = "armadaxp",
158 1.1 rkujawa };
159 1.1 rkujawa
160 1.6 kiyohara static struct {
161 1.6 kiyohara bus_size_t offset;
162 1.6 kiyohara uint32_t bits;
163 1.6 kiyohara } clkgatings[]= {
164 1.6 kiyohara { ARMADAXP_GBE3_BASE, (1 << 1) },
165 1.6 kiyohara { ARMADAXP_GBE2_BASE, (1 << 2) },
166 1.6 kiyohara { ARMADAXP_GBE1_BASE, (1 << 3) },
167 1.6 kiyohara { ARMADAXP_GBE0_BASE, (1 << 4) },
168 1.6 kiyohara { MVSOC_PEX_BASE, (1 << 5) },
169 1.6 kiyohara { ARMADAXP_PEX01_BASE, (1 << 6) },
170 1.6 kiyohara { ARMADAXP_PEX02_BASE, (1 << 7) },
171 1.6 kiyohara { ARMADAXP_PEX03_BASE, (1 << 8) },
172 1.6 kiyohara { ARMADAXP_PEX10_BASE, (1 << 9) },
173 1.6 kiyohara { ARMADAXP_PEX11_BASE, (1 << 10) },
174 1.6 kiyohara { ARMADAXP_PEX12_BASE, (1 << 11) },
175 1.6 kiyohara { ARMADAXP_PEX13_BASE, (1 << 12) },
176 1.6 kiyohara #if 0
177 1.6 kiyohara { NetA, (1 << 13) },
178 1.6 kiyohara #endif
179 1.6 kiyohara { ARMADAXP_SATAHC_BASE, (1 << 14) | (1 << 15) | (1 << 29) | (1 << 30) },
180 1.6 kiyohara { ARMADAXP_LCD_BASE, (1 << 16) },
181 1.6 kiyohara { ARMADAXP_SDIO_BASE, (1 << 17) },
182 1.6 kiyohara { ARMADAXP_USB1_BASE, (1 << 19) },
183 1.6 kiyohara { ARMADAXP_USB2_BASE, (1 << 20) },
184 1.6 kiyohara { ARMADAXP_PEX2_BASE, (1 << 26) },
185 1.6 kiyohara { ARMADAXP_PEX3_BASE, (1 << 27) },
186 1.6 kiyohara #if 0
187 1.6 kiyohara { DDR, (1 << 28) },
188 1.6 kiyohara #endif
189 1.6 kiyohara };
190 1.6 kiyohara
191 1.1 rkujawa /*
192 1.1 rkujawa * armadaxp_intr_bootstrap:
193 1.1 rkujawa *
194 1.1 rkujawa * Initialize the rest of the interrupt subsystem, making it
195 1.1 rkujawa * ready to handle interrupts from devices.
196 1.1 rkujawa */
197 1.1 rkujawa void
198 1.3 kiyohara armadaxp_intr_bootstrap(bus_addr_t pbase)
199 1.1 rkujawa {
200 1.1 rkujawa int i;
201 1.1 rkujawa
202 1.1 rkujawa /* Map MPIC base and MPIC percpu base registers */
203 1.3 kiyohara if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_BASE,
204 1.3 kiyohara 0x500, 0, &mpic_handle) != 0)
205 1.1 rkujawa panic("%s: Could not map MPIC registers", __func__);
206 1.3 kiyohara if (bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_MLMB_MPIC_CPU_BASE,
207 1.3 kiyohara 0x800, 0, &mpic_cpu_handle) != 0)
208 1.1 rkujawa panic("%s: Could not map MPIC percpu registers", __func__);
209 1.1 rkujawa
210 1.1 rkujawa /* Disable all interrupts */
211 1.1 rkujawa for (i = 0; i < 116; i++)
212 1.1 rkujawa MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, i);
213 1.1 rkujawa
214 1.1 rkujawa mvsoc_intr_init = armadaxp_intr_init;
215 1.1 rkujawa }
216 1.1 rkujawa
217 1.1 rkujawa static void
218 1.1 rkujawa armadaxp_intr_init(void)
219 1.1 rkujawa {
220 1.1 rkujawa int ctrl;
221 1.1 rkujawa
222 1.1 rkujawa /* Get max interrupts */
223 1.1 rkujawa armadaxp_pic.pic_maxsources =
224 1.1 rkujawa ((MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL) >> 2) & 0x7FF);
225 1.1 rkujawa
226 1.1 rkujawa if (!armadaxp_pic.pic_maxsources)
227 1.1 rkujawa armadaxp_pic.pic_maxsources = 116;
228 1.1 rkujawa
229 1.1 rkujawa pic_add(&armadaxp_pic, 0);
230 1.1 rkujawa
231 1.1 rkujawa ctrl = MPIC_READ(ARMADAXP_MLMB_MPIC_CTRL);
232 1.1 rkujawa /* Enable IRQ prioritization */
233 1.1 rkujawa ctrl |= (1 << 0);
234 1.1 rkujawa MPIC_WRITE(ARMADAXP_MLMB_MPIC_CTRL, ctrl);
235 1.4 kiyohara
236 1.4 kiyohara find_pending_irqs = armadaxp_find_pending_irqs;
237 1.1 rkujawa }
238 1.1 rkujawa
239 1.1 rkujawa static void
240 1.1 rkujawa armadaxp_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
241 1.1 rkujawa uint32_t irq_mask)
242 1.1 rkujawa {
243 1.1 rkujawa int n;
244 1.1 rkujawa
245 1.1 rkujawa while (irq_mask != 0) {
246 1.1 rkujawa n = ffs(irq_mask) - 1;
247 1.1 rkujawa KASSERT(pic->pic_maxsources >= n + irqbase);
248 1.1 rkujawa MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISE, n + irqbase);
249 1.1 rkujawa MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ICM, n + irqbase);
250 1.1 rkujawa if ((n + irqbase) == 0)
251 1.1 rkujawa MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_DOORBELL_MASK,
252 1.1 rkujawa 0xffffffff);
253 1.1 rkujawa irq_mask &= ~__BIT(n);
254 1.1 rkujawa }
255 1.1 rkujawa }
256 1.1 rkujawa
257 1.1 rkujawa static void
258 1.1 rkujawa armadaxp_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
259 1.1 rkujawa uint32_t irq_mask)
260 1.1 rkujawa {
261 1.1 rkujawa int n;
262 1.1 rkujawa
263 1.1 rkujawa while (irq_mask != 0) {
264 1.1 rkujawa n = ffs(irq_mask) - 1;
265 1.1 rkujawa KASSERT(pic->pic_maxsources >= n + irqbase);
266 1.1 rkujawa MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, n + irqbase);
267 1.1 rkujawa MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, n + irqbase);
268 1.1 rkujawa irq_mask &= ~__BIT(n);
269 1.1 rkujawa }
270 1.1 rkujawa }
271 1.1 rkujawa
272 1.1 rkujawa static void
273 1.1 rkujawa armadaxp_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
274 1.1 rkujawa {
275 1.1 rkujawa int tmp;
276 1.1 rkujawa KASSERT(pic->pic_maxsources >= is->is_irq);
277 1.1 rkujawa tmp = MPIC_READ(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4);
278 1.1 rkujawa /* Clear previous priority */
279 1.1 rkujawa tmp &= ~(0xf << MPIC_ISCR_SHIFT);
280 1.1 rkujawa MPIC_WRITE(ARMADAXP_MLMB_MPIC_ISCR_BASE + is->is_irq * 4,
281 1.1 rkujawa tmp | (is->is_ipl << MPIC_ISCR_SHIFT));
282 1.1 rkujawa }
283 1.1 rkujawa
284 1.4 kiyohara static void
285 1.4 kiyohara armadaxp_pic_set_priority(struct pic_softc *pic, int ipl)
286 1.4 kiyohara {
287 1.4 kiyohara int ctp;
288 1.4 kiyohara
289 1.4 kiyohara ctp = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_CTP);
290 1.4 kiyohara ctp &= ~(0xf << MPIC_CTP_SHIFT);
291 1.4 kiyohara ctp |= (ipl << MPIC_CTP_SHIFT);
292 1.4 kiyohara MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_CTP, ctp);
293 1.4 kiyohara }
294 1.4 kiyohara
295 1.4 kiyohara static int
296 1.4 kiyohara armadaxp_find_pending_irqs(void)
297 1.1 rkujawa {
298 1.1 rkujawa struct intrsource *is;
299 1.1 rkujawa int irq;
300 1.1 rkujawa
301 1.1 rkujawa irq = MPIC_CPU_READ(ARMADAXP_MLMB_MPIC_IIACK) & 0x3ff;
302 1.1 rkujawa
303 1.1 rkujawa /* Is it a spurious interrupt ?*/
304 1.1 rkujawa if (irq == 0x3ff)
305 1.4 kiyohara return 0;
306 1.1 rkujawa is = armadaxp_pic.pic_sources[irq];
307 1.4 kiyohara if (is == NULL) {
308 1.4 kiyohara printf("stray interrupt: %d\n", irq);
309 1.4 kiyohara return 0;
310 1.1 rkujawa }
311 1.4 kiyohara
312 1.4 kiyohara armadaxp_pic_block_irq(&armadaxp_pic, irq);
313 1.4 kiyohara pic_mark_pending(&armadaxp_pic, irq);
314 1.4 kiyohara
315 1.4 kiyohara return is->is_ipl;
316 1.4 kiyohara }
317 1.4 kiyohara
318 1.4 kiyohara static void
319 1.4 kiyohara armadaxp_pic_block_irq(struct pic_softc *pic, size_t irq)
320 1.4 kiyohara {
321 1.4 kiyohara
322 1.4 kiyohara KASSERT(pic->pic_maxsources >= irq);
323 1.4 kiyohara MPIC_WRITE(ARMADAXP_MLMB_MPIC_ICE, irq);
324 1.4 kiyohara MPIC_CPU_WRITE(ARMADAXP_MLMB_MPIC_ISM, irq);
325 1.1 rkujawa }
326 1.1 rkujawa
327 1.1 rkujawa /*
328 1.1 rkujawa * Clock functions
329 1.1 rkujawa */
330 1.1 rkujawa
331 1.1 rkujawa void
332 1.1 rkujawa armadaxp_getclks(void)
333 1.1 rkujawa {
334 1.1 rkujawa uint64_t sar_reg;
335 1.7 kiyohara uint8_t sar_cpu_freq, sar_fab_freq;
336 1.1 rkujawa
337 1.1 rkujawa if (cputype == CPU_ID_MV88SV584X_V7)
338 1.1 rkujawa mvTclk = 250000000; /* 250 MHz */
339 1.1 rkujawa else
340 1.1 rkujawa mvTclk = 200000000; /* 200 MHz */
341 1.1 rkujawa
342 1.1 rkujawa sar_reg = (read_miscreg(ARMADAXP_MISC_SAR_HI) << 31) |
343 1.1 rkujawa read_miscreg(ARMADAXP_MISC_SAR_LO);
344 1.1 rkujawa
345 1.7 kiyohara sar_cpu_freq = EXTRACT_XP_CPU_FREQ_FIELD(sar_reg);
346 1.7 kiyohara sar_fab_freq = EXTRACT_XP_FAB_FREQ_FIELD(sar_reg);
347 1.1 rkujawa
348 1.1 rkujawa /* Check if CPU frequency field has correct value */
349 1.7 kiyohara if (sar_cpu_freq >= __arraycount(clock_table_xp))
350 1.1 rkujawa panic("Reserved value in cpu frequency configuration field: "
351 1.1 rkujawa "%d", sar_cpu_freq);
352 1.1 rkujawa
353 1.1 rkujawa /* Check if fabric frequency field has correct value */
354 1.7 kiyohara if (sar_fab_freq >= __arraycount(freq_conf_table))
355 1.1 rkujawa panic("Reserved value in fabric frequency configuration field: "
356 1.1 rkujawa "%d", sar_fab_freq);
357 1.1 rkujawa
358 1.1 rkujawa /* Get CPU clock frequency */
359 1.7 kiyohara mvPclk = clock_table_xp[sar_cpu_freq] *
360 1.1 rkujawa freq_conf_table[sar_fab_freq].vco_cpu;
361 1.1 rkujawa
362 1.1 rkujawa /* Get L2CLK clock frequency and use as system clock (mvSysclk) */
363 1.1 rkujawa mvSysclk = mvPclk / freq_conf_table[sar_fab_freq].vco_l2c;
364 1.1 rkujawa
365 1.1 rkujawa /* Round mvSysclk value to integer MHz */
366 1.1 rkujawa if (((mvPclk % freq_conf_table[sar_fab_freq].vco_l2c) * 10 /
367 1.1 rkujawa freq_conf_table[sar_fab_freq].vco_l2c) >= 5)
368 1.1 rkujawa mvSysclk++;
369 1.1 rkujawa
370 1.7 kiyohara mvPclk *= 1000000;
371 1.7 kiyohara mvSysclk *= 1000000;
372 1.8 matt
373 1.8 matt curcpu()->ci_data.cpu_cc_freq = mvPclk;
374 1.7 kiyohara }
375 1.7 kiyohara
376 1.7 kiyohara void
377 1.7 kiyohara armada370_getclks(void)
378 1.7 kiyohara {
379 1.7 kiyohara uint32_t sar;
380 1.7 kiyohara uint8_t cpu_freq, fab_freq;
381 1.7 kiyohara
382 1.7 kiyohara sar = read_miscreg(ARMADAXP_MISC_SAR_LO);
383 1.7 kiyohara if (sar & 0x00100000)
384 1.7 kiyohara mvTclk = 200000000; /* 200 MHz */
385 1.7 kiyohara else
386 1.7 kiyohara mvTclk = 166666667; /* 166 MHz */
387 1.7 kiyohara
388 1.7 kiyohara cpu_freq = EXTRACT_370_CPU_FREQ_FIELD(sar);
389 1.7 kiyohara fab_freq = EXTRACT_370_FAB_FREQ_FIELD(sar);
390 1.7 kiyohara
391 1.7 kiyohara /* Check if CPU frequency field has correct value */
392 1.7 kiyohara if (cpu_freq >= __arraycount(clock_table_370))
393 1.7 kiyohara panic("Reserved value in cpu frequency configuration field: "
394 1.7 kiyohara "%d", cpu_freq);
395 1.7 kiyohara
396 1.7 kiyohara /* Check if fabric frequency field has correct value */
397 1.7 kiyohara if (fab_freq >= __arraycount(freq_conf_table))
398 1.7 kiyohara panic("Reserved value in fabric frequency configuration field: "
399 1.7 kiyohara "%d", fab_freq);
400 1.7 kiyohara
401 1.7 kiyohara /* Get CPU clock frequency */
402 1.7 kiyohara mvPclk = clock_table_370[cpu_freq] *
403 1.7 kiyohara freq_conf_table[fab_freq].vco_cpu;
404 1.7 kiyohara
405 1.7 kiyohara /* Get L2CLK clock frequency and use as system clock (mvSysclk) */
406 1.7 kiyohara mvSysclk = mvPclk / freq_conf_table[fab_freq].vco_l2c;
407 1.7 kiyohara
408 1.7 kiyohara /* Round mvSysclk value to integer MHz */
409 1.7 kiyohara if (((mvPclk % freq_conf_table[fab_freq].vco_l2c) * 10 /
410 1.7 kiyohara freq_conf_table[fab_freq].vco_l2c) >= 5)
411 1.7 kiyohara mvSysclk++;
412 1.7 kiyohara
413 1.7 kiyohara mvPclk *= 1000000;
414 1.7 kiyohara mvSysclk *= 1000000;
415 1.1 rkujawa }
416 1.1 rkujawa
417 1.1 rkujawa /*
418 1.1 rkujawa * L2 Cache initialization
419 1.1 rkujawa */
420 1.1 rkujawa
421 1.1 rkujawa int
422 1.3 kiyohara armadaxp_l2_init(bus_addr_t pbase)
423 1.1 rkujawa {
424 1.1 rkujawa u_int32_t reg;
425 1.1 rkujawa int ret;
426 1.1 rkujawa
427 1.1 rkujawa /* Map L2 space */
428 1.3 kiyohara ret = bus_space_map(&mvsoc_bs_tag, pbase + ARMADAXP_L2_BASE,
429 1.3 kiyohara 0x1000, 0, &l2_handle);
430 1.1 rkujawa if (ret) {
431 1.1 rkujawa printf("%s: Cannot map L2 register space, ret:%d\n",
432 1.1 rkujawa __func__, ret);
433 1.1 rkujawa return (-1);
434 1.1 rkujawa }
435 1.1 rkujawa
436 1.13 hsuenaga /* Variables for cpufunc_asm_pj4b.S */
437 1.13 hsuenaga armadaxp_l2_barrier_reg = mlmb_base + MVSOC_MLMB_CIB_BARRIER_TRIGGER;
438 1.13 hsuenaga
439 1.1 rkujawa /* Set L2 policy */
440 1.1 rkujawa reg = L2_READ(ARMADAXP_L2_AUX_CTRL);
441 1.13 hsuenaga reg &= ~(L2_AUX_WBWT_MODE_MASK);
442 1.13 hsuenaga reg &= ~(L2_AUX_REP_STRAT_MASK);
443 1.13 hsuenaga reg |= L2_AUX_WBWT_MODE_WB;
444 1.13 hsuenaga reg |= L2_AUX_ECC_ENABLE;
445 1.13 hsuenaga reg |= L2_AUX_PARITY_ENABLE;
446 1.13 hsuenaga reg |= L2_AUX_FORCE_WA;
447 1.13 hsuenaga reg |= L2_AUX_REP_STRAT_SEMIPLRU;
448 1.1 rkujawa L2_WRITE(ARMADAXP_L2_AUX_CTRL, reg);
449 1.1 rkujawa
450 1.1 rkujawa /* Invalidate L2 cache */
451 1.1 rkujawa L2_WRITE(ARMADAXP_L2_INV_WAY, L2_ALL_WAYS);
452 1.1 rkujawa
453 1.1 rkujawa /* Clear pending L2 interrupts */
454 1.1 rkujawa L2_WRITE(ARMADAXP_L2_INT_CAUSE, 0x1ff);
455 1.1 rkujawa
456 1.1 rkujawa /* Enable Cache and TLB maintenance broadcast */
457 1.1 rkujawa __asm__ __volatile__ ("mrc p15, 1, %0, c15, c2, 0" : "=r"(reg));
458 1.1 rkujawa reg |= (1 << 8);
459 1.1 rkujawa __asm__ __volatile__ ("mcr p15, 1, %0, c15, c2, 0" : :"r"(reg));
460 1.1 rkujawa
461 1.1 rkujawa /*
462 1.1 rkujawa * Set the Point of Coherency and Point of Unification to DRAM.
463 1.1 rkujawa * This is a reset value but anyway, configure this just in case.
464 1.1 rkujawa */
465 1.1 rkujawa reg = read_mlmbreg(ARMADAXP_L2_CFU);
466 1.1 rkujawa reg |= (1 << 17) | (1 << 18);
467 1.1 rkujawa write_mlmbreg(ARMADAXP_L2_CFU, reg);
468 1.1 rkujawa
469 1.1 rkujawa /* Enable L2 cache */
470 1.1 rkujawa reg = L2_READ(ARMADAXP_L2_CTRL);
471 1.13 hsuenaga L2_WRITE(ARMADAXP_L2_CTRL, reg | L2_CTRL_ENABLE);
472 1.1 rkujawa
473 1.1 rkujawa /* Mark as enabled */
474 1.1 rkujawa l2cache_state = 1;
475 1.1 rkujawa
476 1.1 rkujawa #ifdef DEBUG
477 1.1 rkujawa /* Configure and enable counter */
478 1.1 rkujawa L2_WRITE(ARMADAXP_L2_CNTR_CONF(0), 0xf0000 | (4 << 2));
479 1.1 rkujawa L2_WRITE(ARMADAXP_L2_CNTR_CONF(1), 0xf0000 | (2 << 2));
480 1.1 rkujawa L2_WRITE(ARMADAXP_L2_CNTR_CTRL, 0x303);
481 1.1 rkujawa #endif
482 1.1 rkujawa
483 1.1 rkujawa return (0);
484 1.1 rkujawa }
485 1.1 rkujawa
486 1.1 rkujawa void
487 1.9 hsuenaga armadaxp_sdcache_inv_all(void)
488 1.9 hsuenaga {
489 1.9 hsuenaga L2_WRITE(ARMADAXP_L2_INV_WAY, L2_ALL_WAYS);
490 1.9 hsuenaga }
491 1.9 hsuenaga
492 1.9 hsuenaga void
493 1.9 hsuenaga armadaxp_sdcache_wb_all(void)
494 1.9 hsuenaga {
495 1.9 hsuenaga L2_WRITE(ARMADAXP_L2_WB_WAY, L2_ALL_WAYS);
496 1.10 hsuenaga L2_WRITE(ARMADAXP_L2_SYNC, 0);
497 1.9 hsuenaga __asm__ __volatile__("dsb");
498 1.9 hsuenaga }
499 1.9 hsuenaga
500 1.9 hsuenaga void
501 1.9 hsuenaga armadaxp_sdcache_wbinv_all(void)
502 1.9 hsuenaga {
503 1.9 hsuenaga L2_WRITE(ARMADAXP_L2_WBINV_WAY, L2_ALL_WAYS);
504 1.10 hsuenaga L2_WRITE(ARMADAXP_L2_SYNC, 0);
505 1.9 hsuenaga __asm__ __volatile__("dsb");
506 1.9 hsuenaga }
507 1.9 hsuenaga
508 1.13 hsuenaga static paddr_t
509 1.13 hsuenaga armadaxp_sdcache_wbalign_base(vaddr_t va, paddr_t pa, psize_t sz)
510 1.13 hsuenaga {
511 1.13 hsuenaga paddr_t line_start = pa & ~ARMADAXP_L2_ALIGN;
512 1.13 hsuenaga vaddr_t save_start;
513 1.13 hsuenaga uint8_t save_buf[ARMADAXP_L2_LINE_SIZE];
514 1.13 hsuenaga size_t unalign;
515 1.13 hsuenaga
516 1.13 hsuenaga unalign = va & ARMADAXP_L2_ALIGN;
517 1.13 hsuenaga if (unalign == 0)
518 1.13 hsuenaga return line_start; /* request is aligned to cache line size */
519 1.13 hsuenaga
520 1.13 hsuenaga /* save data that is not intended to invalidate */
521 1.13 hsuenaga save_start = va & ~ARMADAXP_L2_ALIGN;
522 1.13 hsuenaga memcpy(save_buf, (void *)save_start, unalign);
523 1.13 hsuenaga
524 1.13 hsuenaga /* invalidate include saved data */
525 1.13 hsuenaga L2_WRITE(ARMADAXP_L2_INV_PHYS, line_start);
526 1.13 hsuenaga
527 1.13 hsuenaga /* write back saved data */
528 1.13 hsuenaga memcpy((void *)save_start, save_buf, unalign);
529 1.13 hsuenaga L2_WRITE(ARMADAXP_L2_WB_PHYS, line_start);
530 1.13 hsuenaga L2_WRITE(ARMADAXP_L2_SYNC, 0);
531 1.13 hsuenaga __asm__ __volatile__("dsb");
532 1.13 hsuenaga
533 1.13 hsuenaga return line_start;
534 1.13 hsuenaga }
535 1.13 hsuenaga
536 1.13 hsuenaga static paddr_t
537 1.13 hsuenaga armadaxp_sdcache_wbalign_end(vaddr_t va, paddr_t pa, psize_t sz)
538 1.13 hsuenaga {
539 1.13 hsuenaga paddr_t line_start = (pa + sz - 1) & ~ARMADAXP_L2_ALIGN;
540 1.13 hsuenaga vaddr_t save_start = va + sz;
541 1.13 hsuenaga uint8_t save_buf[ARMADAXP_L2_LINE_SIZE];
542 1.13 hsuenaga size_t save_len;
543 1.13 hsuenaga size_t unalign;
544 1.13 hsuenaga
545 1.13 hsuenaga unalign = save_start & ARMADAXP_L2_ALIGN;
546 1.13 hsuenaga if (unalign == 0)
547 1.13 hsuenaga return line_start; /* request is aligned to cache line size */
548 1.13 hsuenaga
549 1.13 hsuenaga /* save data that is not intended to invalidate */
550 1.13 hsuenaga save_len = ARMADAXP_L2_LINE_SIZE - unalign;
551 1.13 hsuenaga memcpy(save_buf, (void *)save_start, save_len);
552 1.13 hsuenaga
553 1.13 hsuenaga /* invalidate include saved data */
554 1.13 hsuenaga L2_WRITE(ARMADAXP_L2_INV_PHYS, line_start);
555 1.13 hsuenaga
556 1.13 hsuenaga /* write back saved data */
557 1.13 hsuenaga memcpy((void *)save_start, save_buf, save_len);
558 1.13 hsuenaga L2_WRITE(ARMADAXP_L2_WB_PHYS, line_start);
559 1.13 hsuenaga __asm__ __volatile__("dsb");
560 1.13 hsuenaga
561 1.13 hsuenaga return line_start;
562 1.13 hsuenaga }
563 1.13 hsuenaga
564 1.9 hsuenaga void
565 1.9 hsuenaga armadaxp_sdcache_inv_range(vaddr_t va, paddr_t pa, psize_t sz)
566 1.9 hsuenaga {
567 1.13 hsuenaga paddr_t pa_base;
568 1.13 hsuenaga paddr_t pa_end;
569 1.9 hsuenaga
570 1.13 hsuenaga /* align and write-back the boundary */
571 1.13 hsuenaga pa_base = armadaxp_sdcache_wbalign_base(va, pa, sz);
572 1.13 hsuenaga pa_end = armadaxp_sdcache_wbalign_end(va, pa, sz);
573 1.12 hsuenaga
574 1.12 hsuenaga /* invalidate other cache */
575 1.13 hsuenaga if (pa_base == pa_end) {
576 1.12 hsuenaga L2_WRITE(ARMADAXP_L2_INV_PHYS, pa_base);
577 1.13 hsuenaga return;
578 1.12 hsuenaga }
579 1.13 hsuenaga
580 1.13 hsuenaga L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
581 1.13 hsuenaga L2_WRITE(ARMADAXP_L2_INV_RANGE, pa_end);
582 1.9 hsuenaga }
583 1.9 hsuenaga
584 1.9 hsuenaga void
585 1.9 hsuenaga armadaxp_sdcache_wb_range(vaddr_t va, paddr_t pa, psize_t sz)
586 1.9 hsuenaga {
587 1.13 hsuenaga paddr_t pa_base = pa & ~ARMADAXP_L2_ALIGN;
588 1.13 hsuenaga paddr_t pa_end = (pa + sz - 1) & ~ARMADAXP_L2_ALIGN;
589 1.9 hsuenaga
590 1.12 hsuenaga if (pa_base == pa_end)
591 1.12 hsuenaga L2_WRITE(ARMADAXP_L2_WB_PHYS, pa_base);
592 1.12 hsuenaga else {
593 1.12 hsuenaga L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
594 1.12 hsuenaga L2_WRITE(ARMADAXP_L2_WB_RANGE, pa_end);
595 1.12 hsuenaga }
596 1.10 hsuenaga L2_WRITE(ARMADAXP_L2_SYNC, 0);
597 1.9 hsuenaga __asm__ __volatile__("dsb");
598 1.9 hsuenaga }
599 1.9 hsuenaga
600 1.9 hsuenaga void
601 1.9 hsuenaga armadaxp_sdcache_wbinv_range(vaddr_t va, paddr_t pa, psize_t sz)
602 1.9 hsuenaga {
603 1.13 hsuenaga paddr_t pa_base = pa & ~ARMADAXP_L2_ALIGN;;
604 1.13 hsuenaga paddr_t pa_end = (pa + sz - 1) & ~ARMADAXP_L2_ALIGN;
605 1.9 hsuenaga
606 1.12 hsuenaga if (pa_base == pa_end)
607 1.12 hsuenaga L2_WRITE(ARMADAXP_L2_WBINV_PHYS, pa_base);
608 1.12 hsuenaga else {
609 1.12 hsuenaga L2_WRITE(ARMADAXP_L2_RANGE_BASE, pa_base);
610 1.12 hsuenaga L2_WRITE(ARMADAXP_L2_WBINV_RANGE, pa_end);
611 1.12 hsuenaga }
612 1.10 hsuenaga L2_WRITE(ARMADAXP_L2_SYNC, 0);
613 1.9 hsuenaga __asm__ __volatile__("dsb");
614 1.9 hsuenaga }
615 1.9 hsuenaga
616 1.9 hsuenaga void
617 1.1 rkujawa armadaxp_io_coherency_init(void)
618 1.1 rkujawa {
619 1.1 rkujawa uint32_t reg;
620 1.1 rkujawa
621 1.1 rkujawa /* set CIB read snoop command to ReadUnique */
622 1.1 rkujawa reg = read_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG);
623 1.13 hsuenaga reg |= MVSOC_MLMB_CIB_CTRL_CFG_WB_EN;
624 1.1 rkujawa write_mlmbreg(MVSOC_MLMB_CIB_CTRL_CFG, reg);
625 1.13 hsuenaga
626 1.1 rkujawa /* enable CPUs in SMP group on Fabric coherency */
627 1.13 hsuenaga reg = read_mlmbreg(MVSOC_MLMB_CFU_CTRL);
628 1.13 hsuenaga reg |= MVSOC_MLMB_CFU_CTRL_SNOOP_CPU0;
629 1.13 hsuenaga write_mlmbreg(MVSOC_MLMB_CFU_CTRL, reg);
630 1.13 hsuenaga
631 1.13 hsuenaga /* send all snoop request to L2 cache */
632 1.13 hsuenaga reg = read_mlmbreg(MVSOC_MLMB_CFU_CFG);
633 1.13 hsuenaga #ifdef L2CACHE_ENABLE
634 1.13 hsuenaga reg |= MVSOC_MLMB_CFU_CFG_L2_NOTIFY;
635 1.13 hsuenaga #else
636 1.13 hsuenaga reg &= ~MVSOC_MLMB_CFU_CFG_L2_NOTIFY;
637 1.13 hsuenaga #endif
638 1.13 hsuenaga write_mlmbreg(MVSOC_MLMB_CFU_CFG, reg);
639 1.1 rkujawa
640 1.1 rkujawa /* Mark as enabled */
641 1.1 rkujawa iocc_state = 1;
642 1.1 rkujawa }
643 1.6 kiyohara
644 1.7 kiyohara int
645 1.6 kiyohara armadaxp_clkgating(struct marvell_attach_args *mva)
646 1.6 kiyohara {
647 1.6 kiyohara uint32_t val;
648 1.6 kiyohara int i;
649 1.6 kiyohara
650 1.6 kiyohara for (i = 0; i < __arraycount(clkgatings); i++) {
651 1.6 kiyohara if (clkgatings[i].offset == mva->mva_offset) {
652 1.6 kiyohara val = read_miscreg(ARMADAXP_MISC_PMCGC);
653 1.6 kiyohara if ((val & clkgatings[i].bits) == clkgatings[i].bits)
654 1.6 kiyohara /* Clock enabled */
655 1.7 kiyohara return 0;
656 1.6 kiyohara return 1;
657 1.6 kiyohara }
658 1.7 kiyohara }
659 1.6 kiyohara /* Clock Gating not support */
660 1.6 kiyohara return 0;
661 1.6 kiyohara }
662