Annotation of sys/arch/m88k/m88k/m8820x_machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: m8820x_machdep.c,v 1.26 2007/05/20 20:12:32 miod Exp $ */
2: /*
3: * Copyright (c) 2004, Miodrag Vallat.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
18: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
23: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24: * POSSIBILITY OF SUCH DAMAGE.
25: */
26: /*
27: * Copyright (c) 2001 Steve Murphree, Jr.
28: * Copyright (c) 1996 Nivas Madhur
29: * All rights reserved.
30: *
31: * Redistribution and use in source and binary forms, with or without
32: * modification, are permitted provided that the following conditions
33: * are met:
34: * 1. Redistributions of source code must retain the above copyright
35: * notice, this list of conditions and the following disclaimer.
36: * 2. Redistributions in binary form must reproduce the above copyright
37: * notice, this list of conditions and the following disclaimer in the
38: * documentation and/or other materials provided with the distribution.
39: * 3. All advertising materials mentioning features or use of this software
40: * must display the following acknowledgement:
41: * This product includes software developed by Nivas Madhur.
42: * 4. The name of the author may not be used to endorse or promote products
43: * derived from this software without specific prior written permission
44: *
45: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
46: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
49: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
51: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
52: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
53: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
54: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55: *
56: */
57: /*
58: * Mach Operating System
59: * Copyright (c) 1993-1991 Carnegie Mellon University
60: * Copyright (c) 1991 OMRON Corporation
61: * All Rights Reserved.
62: *
63: * Permission to use, copy, modify and distribute this software and its
64: * documentation is hereby granted, provided that both the copyright
65: * notice and this permission notice appear in all copies of the
66: * software, derivative works or modified versions, and any portions
67: * thereof, and that both notices appear in supporting documentation.
68: *
69: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
70: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
71: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
72: *
73: * Carnegie Mellon requests users of this software to return to
74: *
75: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
76: * School of Computer Science
77: * Carnegie Mellon University
78: * Pittsburgh PA 15213-3890
79: *
80: * any improvements or extensions that they make and grant Carnegie the
81: * rights to redistribute these changes.
82: */
83:
84: #include <sys/param.h>
85: #include <sys/systm.h>
86:
87: #include <uvm/uvm_extern.h>
88:
89: #include <machine/asm_macro.h>
90: #include <machine/cmmu.h>
91: #include <machine/cpu.h>
92: #include <machine/lock.h>
93: #include <machine/m8820x.h>
94: #include <machine/psl.h>
95:
96: cpuid_t m8820x_init(void);
97: void m8820x_cpu_configuration_print(int);
98: void m8820x_shutdown(void);
99: void m8820x_set_sapr(cpuid_t, apr_t);
100: void m8820x_set_uapr(apr_t);
101: void m8820x_flush_tlb(cpuid_t, u_int, vaddr_t, u_int);
102: void m8820x_flush_cache(cpuid_t, paddr_t, psize_t);
103: void m8820x_flush_inst_cache(cpuid_t, paddr_t, psize_t);
104: void m8820x_flush_data_page(cpuid_t, paddr_t);
105: void m8820x_dma_cachectl(pmap_t, vaddr_t, vsize_t, int);
106: void m8820x_dma_cachectl_pa(paddr_t, psize_t, int);
107: void m8820x_initialize_cpu(cpuid_t);
108:
109: /* This is the function table for the MC8820x CMMUs */
110: struct cmmu_p cmmu8820x = {
111: m8820x_init,
112: m8820x_setup_board_config,
113: m8820x_cpu_configuration_print,
114: m8820x_shutdown,
115: m8820x_cpu_number,
116: m8820x_set_sapr,
117: m8820x_set_uapr,
118: m8820x_flush_tlb,
119: m8820x_flush_cache,
120: m8820x_flush_inst_cache,
121: m8820x_flush_data_page,
122: m8820x_dma_cachectl,
123: m8820x_dma_cachectl_pa,
124: #ifdef MULTIPROCESSOR
125: m8820x_initialize_cpu,
126: #endif
127: };
128:
129: /*
130: * Systems with more than 2 CMMUs per CPU use programmable split schemes.
131: *
132: * The following schemes are available on MVME188 boards:
133: * - split on A12 address bit (A14 for 88204)
134: * - split on supervisor/user access
135: * - split on SRAM/non-SRAM addresses, with either supervisor-only or all
136: * access to SRAM.
137: *
138: * MVME188 configuration 6, with 4 CMMUs par CPU, also forces a split on
139: * A14 address bit (A16 for 88204).
140: *
141: * Under OpenBSD, we will only split on A12 and A14 address bits, since we
142: * do not want to waste CMMU resources on the SRAM, and user/supervisor
143: * splits seem less efficient.
144: *
145: * The really nasty part of this choice is in the exception handling code,
146: * when it needs to get error information from up to 4 CMMUs. See eh.S on
147: * mvme88k for the gory details, luna88k is more sane.
148: */
149:
150: struct m8820x_cmmu m8820x_cmmu[MAX_CMMUS];
151: u_int max_cmmus;
152: u_int cmmu_shift;
153:
154: /* local prototypes */
155: void m8820x_cmmu_set_reg(int, u_int, int, int, int);
156: void m8820x_cmmu_set_cmd(u_int, int, int, int, vaddr_t);
157: void m8820x_cmmu_wait(int);
158: void m8820x_cmmu_sync_cache(int, paddr_t, psize_t);
159: void m8820x_cmmu_sync_inval_cache(int, paddr_t, psize_t);
160: void m8820x_cmmu_inval_cache(int, paddr_t, psize_t);
161:
162: /* Flags passed to m8820x_cmmu_set() */
163: #define MODE_VAL 0x01
164: #define ADDR_VAL 0x02
165:
166: /*
167: * Helper functions to poke values into the appropriate CMMU registers.
168: */
169:
170: void
171: m8820x_cmmu_set_reg(int reg, u_int val, int flags, int cpu, int mode)
172: {
173: struct m8820x_cmmu *cmmu;
174: int mmu, cnt;
175:
176: mmu = cpu << cmmu_shift;
177: cmmu = m8820x_cmmu + mmu;
178:
179: /*
180: * We scan all CMMUs to find the matching ones and store the
181: * values there.
182: */
183: for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
184: if ((flags & MODE_VAL) != 0) {
185: if (CMMU_MODE(mmu) != mode)
186: continue;
187: }
188: cmmu->cmmu_regs[reg] = val;
189: }
190: }
191:
192: void
193: m8820x_cmmu_set_cmd(u_int cmd, int flags, int cpu, int mode, vaddr_t addr)
194: {
195: struct m8820x_cmmu *cmmu;
196: int mmu, cnt;
197:
198: mmu = cpu << cmmu_shift;
199: cmmu = m8820x_cmmu + mmu;
200:
201: /*
202: * We scan all CMMUs to find the matching ones and store the
203: * values there.
204: */
205: for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
206: if ((flags & MODE_VAL) != 0) {
207: if (CMMU_MODE(mmu) != mode)
208: continue;
209: }
210: #ifdef M88200_HAS_SPLIT_ADDRESS
211: if ((flags & ADDR_VAL) != 0 && cmmu->cmmu_addr_mask != 0) {
212: if ((addr & cmmu->cmmu_addr_mask) != cmmu->cmmu_addr)
213: continue;
214: }
215: #endif
216: cmmu->cmmu_regs[CMMU_SAR] = addr;
217: cmmu->cmmu_regs[CMMU_SCR] = cmd;
218: }
219: }
220:
221: /*
222: * Force a read from the CMMU status register, thereby forcing execution to
223: * stop until all pending CMMU operations are finished.
224: * This is used by the various cache invalidation functions.
225: */
226: void
227: m8820x_cmmu_wait(int cpu)
228: {
229: struct m8820x_cmmu *cmmu;
230: int mmu, cnt;
231:
232: mmu = cpu << cmmu_shift;
233: cmmu = m8820x_cmmu + mmu;
234:
235: /*
236: * We scan all related CMMUs and read their status register.
237: */
238: for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
239: #ifdef DEBUG
240: if (cmmu->cmmu_regs[CMMU_SSR] & CMMU_SSR_BE) {
241: panic("cache flush failed!");
242: }
243: #else
244: /* force the read access, but do not issue this statement... */
245: __asm__ __volatile__ ("|or r0, r0, %0" ::
246: "r" (cmmu->cmmu_regs[CMMU_SSR]));
247: #endif
248: }
249: }
250:
251: /*
252: * Should only be called after the calling cpus knows its cpu
253: * number and main/secondary status. Should be called first
254: * by the main processor, before the others are started.
255: */
256: void
257: m8820x_cpu_configuration_print(int main)
258: {
259: struct m8820x_cmmu *cmmu;
260: int pid = get_cpu_pid();
261: int proctype = (pid & PID_ARN) >> ARN_SHIFT;
262: int procvers = (pid & PID_VN) >> VN_SHIFT;
263: int mmu, cnt, cpu = cpu_number();
264: #ifdef M88200_HAS_SPLIT_ADDRESS
265: int aline, abit, amask;
266: #endif
267:
268: printf("cpu%d: ", cpu);
269: switch (proctype) {
270: default:
271: printf("unknown model arch 0x%x rev 0x%x",
272: proctype, procvers);
273: break;
274: case ARN_88100:
275: printf("M88100 rev 0x%x", procvers);
276: #ifdef MULTIPROCESSOR
277: if (main == 0)
278: printf(", secondary");
279: #endif
280: printf(", %d CMMU", 1 << cmmu_shift);
281:
282: mmu = cpu << cmmu_shift;
283: cmmu = m8820x_cmmu + mmu;
284: for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) {
285: int idr = cmmu->cmmu_regs[CMMU_IDR];
286: int mmuid = CMMU_TYPE(idr);
287:
288: if (mmu % 2 == 0)
289: printf("\ncpu%d: ", cpu);
290: else
291: printf(", ");
292:
293: switch (mmuid) {
294: case M88200_ID:
295: printf("M88200 (16K)");
296: break;
297: case M88204_ID:
298: printf("M88204 (64K)");
299: break;
300: default:
301: printf("unknown CMMU id 0x%x", mmuid);
302: break;
303: }
304: printf(" rev 0x%x,", CMMU_VERSION(idr));
305: #ifdef M88200_HAS_SPLIT_ADDRESS
306: /*
307: * Print address lines
308: */
309: amask = cmmu->cmmu_addr_mask;
310: if (amask != 0) {
311: aline = 0;
312: while (amask != 0) {
313: abit = ff1(amask);
314: if ((cmmu->cmmu_addr &
315: (1 << abit)) != 0)
316: printf("%cA%02d",
317: aline != 0 ? '/' : ' ',
318: abit);
319: else
320: printf("%cA%02d*",
321: aline != 0 ? '/' : ' ',
322: abit);
323: amask ^= 1 << abit;
324: }
325: } else
326: #endif
327: printf(" full");
328: printf(" %ccache",
329: CMMU_MODE(mmu) == INST_CMMU ? 'I' : 'D');
330: }
331: break;
332: }
333: printf("\n");
334:
335: #ifndef ERRATA__XXX_USR
336: {
337: static int errata_warn = 0;
338:
339: if (proctype == ARN_88100 && procvers <= 10) {
340: if (!errata_warn++)
341: printf("WARNING: M88100 bug workaround code "
342: "not enabled.\nPlease recompile the kernel "
343: "with option ERRATA__XXX_USR !\n");
344: }
345: }
346: #endif
347: }
348:
349: /*
350: * CMMU initialization routine
351: */
352: cpuid_t
353: m8820x_init()
354: {
355: cpuid_t cpu;
356:
357: cpu = m8820x_cpu_number();
358: m8820x_initialize_cpu(cpu);
359: return (cpu);
360: }
361:
362: /*
363: * Initialize the set of CMMUs tied to a particular CPU.
364: */
365: void
366: m8820x_initialize_cpu(cpuid_t cpu)
367: {
368: struct cpu_info *ci;
369: struct m8820x_cmmu *cmmu;
370: u_int line, cnt;
371: int cssp, sctr, type;
372: apr_t apr;
373:
374: apr = ((0x00000 << PG_BITS) | CACHE_WT | CACHE_GLOBAL | CACHE_INH) &
375: ~APR_V;
376:
377: cmmu = m8820x_cmmu + (cpu << cmmu_shift);
378:
379: /*
380: * Setup CMMU pointers for faster exception processing.
381: * This relies on the board-dependent code putting instruction
382: * CMMUs and data CMMUs interleaved with instruction CMMUs first.
383: */
384: ci = &m88k_cpus[cpu];
385: switch (cmmu_shift) {
386: default:
387: /* exception code does not use ci_pfsr_* fields */
388: break;
389: case 2:
390: ci->ci_pfsr_d1 = (u_int)cmmu[3].cmmu_regs + CMMU_PFSR * 4;
391: ci->ci_pfsr_i1 = (u_int)cmmu[2].cmmu_regs + CMMU_PFSR * 4;
392: /* FALLTHROUGH */
393: case 1:
394: ci->ci_pfsr_d0 = (u_int)cmmu[1].cmmu_regs + CMMU_PFSR * 4;
395: ci->ci_pfsr_i0 = (u_int)cmmu[0].cmmu_regs + CMMU_PFSR * 4;
396: break;
397: }
398:
399: for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, cmmu++) {
400: type = CMMU_TYPE(cmmu->cmmu_regs[CMMU_IDR]);
401:
402: /*
403: * Reset cache
404: */
405: for (cssp = type == M88204_ID ? 3 : 0; cssp >= 0; cssp--)
406: for (line = 0; line <= 255; line++) {
407: cmmu->cmmu_regs[CMMU_SAR] =
408: line << MC88200_CACHE_SHIFT;
409: cmmu->cmmu_regs[CMMU_CSSP(cssp)] =
410: CMMU_CSSP_L5 | CMMU_CSSP_L4 |
411: CMMU_CSSP_L3 | CMMU_CSSP_L2 |
412: CMMU_CSSP_L1 | CMMU_CSSP_L0 |
413: CMMU_CSSP_VV(3, CMMU_VV_INVALID) |
414: CMMU_CSSP_VV(2, CMMU_VV_INVALID) |
415: CMMU_CSSP_VV(1, CMMU_VV_INVALID) |
416: CMMU_CSSP_VV(0, CMMU_VV_INVALID);
417: }
418:
419: /*
420: * Set the SCTR, SAPR, and UAPR to some known state.
421: * Snooping is enabled on multiprocessor systems; for
422: * instruction CMMUs as well so that we can share breakpoints.
423: * XXX Investigate why enabling parity at this point
424: * doesn't work.
425: */
426: sctr = cmmu->cmmu_regs[CMMU_SCTR] &
427: ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR);
428: #ifdef MULTIPROCESSOR
429: if (max_cpus > 1)
430: sctr |= CMMU_SCTR_SE;
431: #endif
432: cmmu->cmmu_regs[CMMU_SCTR] = sctr;
433:
434: cmmu->cmmu_regs[CMMU_SAPR] = cmmu->cmmu_regs[CMMU_UAPR] = apr;
435:
436: cmmu->cmmu_regs[CMMU_BWP0] = cmmu->cmmu_regs[CMMU_BWP1] =
437: cmmu->cmmu_regs[CMMU_BWP2] = cmmu->cmmu_regs[CMMU_BWP3] =
438: cmmu->cmmu_regs[CMMU_BWP4] = cmmu->cmmu_regs[CMMU_BWP5] =
439: cmmu->cmmu_regs[CMMU_BWP6] = cmmu->cmmu_regs[CMMU_BWP7] = 0;
440: cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_CACHE_INV_ALL;
441: __asm__ __volatile__ ("|or r0, r0, %0" ::
442: "r" (cmmu->cmmu_regs[CMMU_SSR]));
443: cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_SUPER_ALL;
444: cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_USER_ALL;
445: }
446:
447: /*
448: * Enable instruction cache.
449: * Data cache will be enabled later.
450: */
451: apr &= ~CACHE_INH;
452: m8820x_cmmu_set_reg(CMMU_SAPR, apr, MODE_VAL, cpu, INST_CMMU);
453: }
454:
455: /*
456: * Just before poweroff or reset....
457: */
458: void
459: m8820x_shutdown()
460: {
461: unsigned cmmu_num;
462: struct m8820x_cmmu *cmmu;
463:
464: CMMU_LOCK;
465:
466: cmmu = m8820x_cmmu;
467: for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++, cmmu++) {
468: cmmu->cmmu_regs[CMMU_SCTR] &=
469: ~(CMMU_SCTR_PE | CMMU_SCTR_SE | CMMU_SCTR_PR);
470: cmmu->cmmu_regs[CMMU_SAPR] = cmmu->cmmu_regs[CMMU_UAPR] =
471: ((0x00000 << PG_BITS) | CACHE_INH) &
472: ~(CACHE_WT | CACHE_GLOBAL | APR_V);
473: }
474:
475: CMMU_UNLOCK;
476: }
477:
478: void
479: m8820x_set_sapr(cpuid_t cpu, apr_t ap)
480: {
481: CMMU_LOCK;
482:
483: m8820x_cmmu_set_reg(CMMU_SAPR, ap, 0, cpu, 0);
484:
485: CMMU_UNLOCK;
486: }
487:
488: void
489: m8820x_set_uapr(apr_t ap)
490: {
491: u_int32_t psr;
492: int cpu = cpu_number();
493:
494: disable_interrupt(psr);
495: CMMU_LOCK;
496:
497: m8820x_cmmu_set_reg(CMMU_UAPR, ap, 0, cpu, 0);
498:
499: CMMU_UNLOCK;
500: set_psr(psr);
501: }
502:
503: /*
504: * Functions that invalidate TLB entries.
505: */
506:
507: /*
508: * flush any tlb
509: */
510: void
511: m8820x_flush_tlb(cpuid_t cpu, unsigned kernel, vaddr_t vaddr, u_int count)
512: {
513: u_int32_t psr;
514:
515: disable_interrupt(psr);
516: CMMU_LOCK;
517:
518: /*
519: * Since segment operations are horribly expensive, don't
520: * do any here. Invalidations of up to three pages are performed
521: * as page invalidations, otherwise the entire tlb is flushed.
522: *
523: * Note that this code relies upon vaddr being page-aligned.
524: */
525: switch (count) {
526: default:
527: m8820x_cmmu_set_reg(CMMU_SCR,
528: kernel ? CMMU_FLUSH_SUPER_ALL : CMMU_FLUSH_USER_ALL,
529: 0, cpu, 0);
530: break;
531: case 3:
532: m8820x_cmmu_set_cmd(
533: kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
534: ADDR_VAL, cpu, 0, vaddr);
535: vaddr += PAGE_SIZE;
536: /* FALLTHROUGH */
537: case 2:
538: m8820x_cmmu_set_cmd(
539: kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
540: ADDR_VAL, cpu, 0, vaddr);
541: vaddr += PAGE_SIZE;
542: /* FALLTHROUGH */
543: case 1: /* most frequent situation */
544: case 0:
545: m8820x_cmmu_set_cmd(
546: kernel ? CMMU_FLUSH_SUPER_PAGE : CMMU_FLUSH_USER_PAGE,
547: ADDR_VAL, cpu, 0, vaddr);
548: break;
549: }
550:
551: CMMU_UNLOCK;
552: set_psr(psr);
553: }
554:
555: /*
556: * Functions that invalidate caches.
557: *
558: * Cache invalidates require physical addresses.
559: *
560: * We don't push Instruction Caches prior to invalidate because they are not
561: * snooped and never modified (I guess it doesn't matter then which form
562: * of the command we use then).
563: *
564: * XXX On systems with more than two CMMUs per CPU, we do not honor the
565: * address split - this does not work...
566: */
567:
568: #define trunc_cache_line(a) ((a) & ~(MC88200_CACHE_LINE - 1))
569: #define round_cache_line(a) trunc_cache_line((a) + MC88200_CACHE_LINE - 1)
570:
571: /*
572: * flush both Instruction and Data caches
573: */
574: void
575: m8820x_flush_cache(cpuid_t cpu, paddr_t pa, psize_t size)
576: {
577: u_int32_t psr;
578: psize_t count;
579:
580: size = round_cache_line(pa + size) - trunc_cache_line(pa);
581: pa = trunc_cache_line(pa);
582:
583: disable_interrupt(psr);
584: CMMU_LOCK;
585:
586: while (size != 0) {
587: count = (pa & PAGE_MASK) == 0 && size >= PAGE_SIZE ?
588: PAGE_SIZE : MC88200_CACHE_LINE;
589:
590: if (count <= MC88200_CACHE_LINE)
591: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CBI_LINE,
592: 0 /* ADDR_VAL */, cpu, 0, pa);
593: else
594: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CBI_PAGE,
595: 0 /* ADDR_VAL */, cpu, 0, pa);
596:
597: pa += count;
598: size -= count;
599: }
600: m8820x_cmmu_wait(cpu);
601:
602: CMMU_UNLOCK;
603: set_psr(psr);
604: }
605:
606: /*
607: * flush Instruction caches
608: */
609: void
610: m8820x_flush_inst_cache(cpuid_t cpu, paddr_t pa, psize_t size)
611: {
612: u_int32_t psr;
613: psize_t count;
614:
615: size = round_cache_line(pa + size) - trunc_cache_line(pa);
616: pa = trunc_cache_line(pa);
617:
618: disable_interrupt(psr);
619: CMMU_LOCK;
620:
621: while (size != 0) {
622: count = (pa & PAGE_MASK) == 0 && size >= PAGE_SIZE ?
623: PAGE_SIZE : MC88200_CACHE_LINE;
624:
625: if (count <= MC88200_CACHE_LINE)
626: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_LINE,
627: MODE_VAL /* | ADDR_VAL */, cpu, INST_CMMU, pa);
628: else
629: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_PAGE,
630: MODE_VAL /* | ADDR_VAL */, cpu, INST_CMMU, pa);
631:
632: pa += count;
633: size -= count;
634: }
635: m8820x_cmmu_wait(cpu);
636:
637: CMMU_UNLOCK;
638: set_psr(psr);
639: }
640:
641: void
642: m8820x_flush_data_page(cpuid_t cpu, paddr_t pa)
643: {
644: u_int32_t psr;
645:
646: disable_interrupt(psr);
647: CMMU_LOCK;
648:
649: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CBI_PAGE,
650: MODE_VAL /* | ADDR_VAL */, cpu, DATA_CMMU, pa);
651: m8820x_cmmu_wait(cpu);
652:
653: CMMU_UNLOCK;
654: set_psr(psr);
655: }
656:
657: /*
658: * sync dcache - icache is never dirty but needs to be invalidated as well.
659: */
660: void
661: m8820x_cmmu_sync_cache(int cpu, paddr_t pa, psize_t size)
662: {
663: if (size <= MC88200_CACHE_LINE) {
664: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CB_LINE,
665: MODE_VAL /* | ADDR_VAL */, cpu, DATA_CMMU, pa);
666: } else {
667: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CB_PAGE,
668: MODE_VAL /* | ADDR_VAL */, cpu, DATA_CMMU, pa);
669: }
670: m8820x_cmmu_wait(cpu);
671: }
672:
673: void
674: m8820x_cmmu_sync_inval_cache(int cpu, paddr_t pa, psize_t size)
675: {
676: if (size <= MC88200_CACHE_LINE) {
677: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_LINE,
678: MODE_VAL /* | ADDR_VAL */, cpu, INST_CMMU, pa);
679: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CBI_LINE,
680: MODE_VAL /* | ADDR_VAL */, cpu, DATA_CMMU, pa);
681: } else {
682: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_PAGE,
683: MODE_VAL /* | ADDR_VAL */, cpu, INST_CMMU, pa);
684: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_CBI_PAGE,
685: MODE_VAL /* | ADDR_VAL */, cpu, DATA_CMMU, pa);
686: }
687: m8820x_cmmu_wait(cpu);
688: }
689:
690: void
691: m8820x_cmmu_inval_cache(int cpu, paddr_t pa, psize_t size)
692: {
693: if (size <= MC88200_CACHE_LINE) {
694: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_LINE,
695: 0 /* ADDR_VAL */, cpu, 0, pa);
696: } else {
697: m8820x_cmmu_set_cmd(CMMU_FLUSH_CACHE_INV_PAGE,
698: 0 /* ADDR_VAL */, cpu, 0, pa);
699: }
700: m8820x_cmmu_wait(cpu);
701: }
702:
703: void
704: m8820x_dma_cachectl(pmap_t pmap, vaddr_t _va, vsize_t _size, int op)
705: {
706: u_int32_t psr;
707: int cpu = cpu_number();
708: vaddr_t va;
709: paddr_t pa;
710: psize_t size, count;
711: void (*flusher)(int, paddr_t, psize_t);
712:
713: va = trunc_cache_line(_va);
714: size = round_cache_line(_va + _size) - va;
715:
716: switch (op) {
717: case DMA_CACHE_SYNC:
718: flusher = m8820x_cmmu_sync_cache;
719: break;
720: case DMA_CACHE_SYNC_INVAL:
721: flusher = m8820x_cmmu_sync_inval_cache;
722: break;
723: default:
724: if (va != _va || size != _size)
725: flusher = m8820x_cmmu_sync_inval_cache;
726: else
727: flusher = m8820x_cmmu_inval_cache;
728: break;
729: }
730:
731: disable_interrupt(psr);
732: CMMU_LOCK;
733:
734: while (size != 0) {
735: count = (va & PAGE_MASK) == 0 && size >= PAGE_SIZE ?
736: PAGE_SIZE : MC88200_CACHE_LINE;
737:
738: if (pmap_extract(pmap, va, &pa) != FALSE)
739: (*flusher)(cpu, pa, count);
740:
741: va += count;
742: size -= count;
743: }
744:
745: CMMU_UNLOCK;
746: set_psr(psr);
747: }
748:
749: void
750: m8820x_dma_cachectl_pa(paddr_t _pa, psize_t _size, int op)
751: {
752: u_int32_t psr;
753: int cpu = cpu_number();
754: paddr_t pa;
755: psize_t size, count;
756: void (*flusher)(int, paddr_t, psize_t);
757:
758: pa = trunc_cache_line(_pa);
759: size = round_cache_line(_pa + _size) - pa;
760:
761: switch (op) {
762: case DMA_CACHE_SYNC:
763: flusher = m8820x_cmmu_sync_cache;
764: break;
765: case DMA_CACHE_SYNC_INVAL:
766: flusher = m8820x_cmmu_sync_inval_cache;
767: break;
768: default:
769: if (pa != _pa || size != _size)
770: flusher = m8820x_cmmu_sync_inval_cache;
771: else
772: flusher = m8820x_cmmu_inval_cache;
773: break;
774: }
775:
776: disable_interrupt(psr);
777: CMMU_LOCK;
778:
779: while (size != 0) {
780: count = (pa & PAGE_MASK) == 0 && size >= PAGE_SIZE ?
781: PAGE_SIZE : MC88200_CACHE_LINE;
782:
783: (*flusher)(cpu, pa, count);
784:
785: pa += count;
786: size -= count;
787: }
788:
789: CMMU_UNLOCK;
790: set_psr(psr);
791: }
CVSweb