/* * Should only be called after the calling cpus knows its cpu * number and main/secondary status. Should be called first * by the main processor, before the others are started. */ void m8820x_cpu_configuration_print(int main) { struct m8820x_cmmu *cmmu; int pid = get_cpu_pid(); int proctype = (pid & PID_ARN) >> ARN_SHIFT; int procvers = (pid & PID_VN) >> VN_SHIFT; int reported, nmmu, mmu, cnt, cpu = cpu_number(); #ifdef M88200_HAS_SPLIT_ADDRESS int aline, abit, amask; #endif printf("cpu%d: ", cpu); switch (proctype) { default: printf("unknown model arch 0x%x rev 0x%x", proctype, procvers); break; case ARN_88100: printf("M88100 rev 0x%x", procvers); #ifdef MULTIPROCESSOR if (main == 0) printf(", secondary"); #endif nmmu = 1 << cmmu_shift; #ifdef M88200_HAS_ASYMMETRICAL_ASSOCIATION mmu = cpu << cmmu_shift; cmmu = m8820x_cmmu + mmu; for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) if (cmmu->cmmu_regs == NULL) nmmu--; #endif printf(", %d CMMU", nmmu); mmu = cpu << cmmu_shift; cmmu = m8820x_cmmu + mmu; reported = 0; for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, mmu++, cmmu++) { int idr, mmuid; #ifdef M88200_HAS_ASYMMETRICAL_ASSOCIATION if (cmmu->cmmu_regs == NULL) continue; #endif idr = cmmu->cmmu_regs[CMMU_IDR]; mmuid = CMMU_TYPE(idr); if (reported++ % 2 == 0) printf("\ncpu%d: ", cpu); else printf(", "); switch (mmuid) { case M88200_ID: printf("M88200 (16K)"); break; case M88204_ID: printf("M88204 (64K)"); break; default: printf("unknown CMMU id 0x%x", mmuid); break; } printf(" rev 0x%x,", CMMU_VERSION(idr)); #ifdef M88200_HAS_SPLIT_ADDRESS /* * Print address lines */ amask = cmmu->cmmu_addr_mask; if (amask != 0) { aline = 0; while (amask != 0) { abit = ff1(amask); if ((cmmu->cmmu_addr & (1 << abit)) != 0) printf("%cA%02d", aline != 0 ? '/' : ' ', abit); else printf("%cA%02d*", aline != 0 ? '/' : ' ', abit); amask ^= 1 << abit; } } else if (cmmu_shift != 1) { /* unknown split scheme */ printf(" split"); } else #endif printf(" full"); printf(" %ccache", CMMU_MODE(mmu) == INST_CMMU ? 'I' : 'D'); } break; } printf("\n"); #ifndef ERRATA__XXX_USR { static int errata_warn = 0; if (proctype == ARN_88100 && procvers <= 10) { if (!errata_warn++) printf("WARNING: M88100 bug workaround code " "not enabled.\nPlease recompile the kernel " "with option ERRATA__XXX_USR !\n"); } } #endif }
/* * Initialize the set of CMMUs tied to a particular CPU. */ void m8820x_initialize_cpu(cpuid_t cpu) { struct cpu_info *ci; struct m8820x_cmmu *cmmu; u_int line, cnt; int cssp, type; apr_t apr; apr = ((0x00000 << PG_BITS) | CACHE_WT | CACHE_GLOBAL | CACHE_INH) & ~APR_V; cmmu = m8820x_cmmu + (cpu << cmmu_shift); /* * Setup CMMU pointers for faster exception processing. * This relies on the board-dependent code putting instruction * CMMUs and data CMMUs interleaved with instruction CMMUs first. */ ci = &m88k_cpus[cpu]; switch (cmmu_shift) { default: /* exception code may not use ci_pfsr fields, compute anyway */ /* FALLTHROUGH */ case 2: ci->ci_pfsr_d1 = (u_int)cmmu[3].cmmu_regs + CMMU_PFSR * 4; ci->ci_pfsr_i1 = (u_int)cmmu[2].cmmu_regs + CMMU_PFSR * 4; /* FALLTHROUGH */ case 1: ci->ci_pfsr_d0 = (u_int)cmmu[1].cmmu_regs + CMMU_PFSR * 4; ci->ci_pfsr_i0 = (u_int)cmmu[0].cmmu_regs + CMMU_PFSR * 4; break; } for (cnt = 1 << cmmu_shift; cnt != 0; cnt--, cmmu++) { #ifdef M88200_HAS_ASYMMETRICAL_ASSOCIATION if (cmmu->cmmu_regs == NULL) continue; #endif type = CMMU_TYPE(cmmu->cmmu_regs[CMMU_IDR]); /* * Reset cache */ for (cssp = type == M88204_ID ? 3 : 0; cssp >= 0; cssp--) for (line = 0; line <= 255; line++) { cmmu->cmmu_regs[CMMU_SAR] = line << MC88200_CACHE_SHIFT; if (cmmu->cmmu_regs[CMMU_CSSP(cssp)] & (CMMU_CSSP_D3 | CMMU_CSSP_D2 | CMMU_CSSP_D1 | CMMU_CSSP_D0)) { printf("cpu%d: CMMU@%p has disabled" " cache lines in set 0x%03x," " cssp %08x\n", cpu, cmmu->cmmu_regs, (cssp << 8) | line, cmmu->cmmu_regs[CMMU_CSSP(cssp)]); } cmmu->cmmu_regs[CMMU_CSSP(cssp)] = (cmmu->cmmu_regs[CMMU_CSSP(cssp)] & ~(CMMU_CSSP_D3 | CMMU_CSSP_D2 | CMMU_CSSP_D1 | CMMU_CSSP_D0)) | CMMU_CSSP_L5 | CMMU_CSSP_L4 | CMMU_CSSP_L3 | CMMU_CSSP_L2 | CMMU_CSSP_L1 | CMMU_CSSP_L0 | CMMU_CSSP_VV(3, CMMU_VV_INVALID) | CMMU_CSSP_VV(2, CMMU_VV_INVALID) | CMMU_CSSP_VV(1, CMMU_VV_INVALID) | CMMU_CSSP_VV(0, CMMU_VV_INVALID); } /* * Set the SCTR, SAPR, and UAPR to some known state. * Snooping is always enabled, so that we do not need to * writeback userland code pages when they first get filled * as data pages. */ cmmu->cmmu_regs[CMMU_SCTR] = CMMU_SCTR_SE; cmmu->cmmu_regs[CMMU_SAPR] = cmmu->cmmu_regs[CMMU_UAPR] = apr; cmmu->cmmu_regs[CMMU_BWP0] = cmmu->cmmu_regs[CMMU_BWP1] = cmmu->cmmu_regs[CMMU_BWP2] = cmmu->cmmu_regs[CMMU_BWP3] = cmmu->cmmu_regs[CMMU_BWP4] = cmmu->cmmu_regs[CMMU_BWP5] = cmmu->cmmu_regs[CMMU_BWP6] = cmmu->cmmu_regs[CMMU_BWP7] = 0; cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_CACHE_INV_ALL; (void)cmmu->cmmu_regs[CMMU_SSR]; cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_SUPER_ALL; cmmu->cmmu_regs[CMMU_SCR] = CMMU_FLUSH_USER_ALL; } /* * Enable instruction cache. * Data cache will be enabled later. */ apr &= ~CACHE_INH; m8820x_cmmu_set_reg(CMMU_SAPR, apr, MODE_VAL, cpu, INST_CMMU); ci->ci_zeropage = m8820x_zeropage; ci->ci_copypage = m8820x_copypage; }
/* * This routine sets up the CPU/CMMU configuration. */ void m8820x_setup_board_config() { struct m8820x_cmmu *cmmu; int num; master_cpu = 0; /* temp to get things going */ m8820x_cmmu[0].cmmu_regs = (void *)CMMU_I0; m8820x_cmmu[1].cmmu_regs = (void *)CMMU_D0; m8820x_cmmu[2].cmmu_regs = (void *)CMMU_I1; m8820x_cmmu[3].cmmu_regs = (void *)CMMU_D1; m8820x_cmmu[4].cmmu_regs = (void *)CMMU_I2; m8820x_cmmu[5].cmmu_regs = (void *)CMMU_D2; m8820x_cmmu[6].cmmu_regs = (void *)CMMU_I3; m8820x_cmmu[7].cmmu_regs = (void *)CMMU_D3; /* * Probe all CMMU address to discover if the CPU slots are populated. */ cmmu = m8820x_cmmu; for (max_cmmus = 0; max_cmmus < 8; max_cmmus++, cmmu++) { if (badwordaddr((vaddr_t)cmmu->cmmu_regs) != 0) break; } max_cpus = max_cmmus >> 1; max_cmmus = max_cpus << 1; cmmu_shift = 1; /* fixed 2:1 configuration */ #ifdef DEBUG /* * Check CMMU type */ for (num = 0; num < max_cmmus; num++) { volatile unsigned *cr = m8820x_cmmu[num].cmmu_regs; if (badwordaddr((vaddr_t)cr) == 0) { int type; type = CMMU_TYPE(cr[CMMU_IDR]); if (type != M88200_ID && type != M88204_ID) { printf("WARNING: non M8820x circuit found " "at CMMU address %p\n", cr); continue; /* will probably die quickly */ } } } #endif /* * Now that we know which CMMUs are there, report every association */ for (num = 0; num < max_cpus; num++) { int type; cpu_sets[num] = 1; /* This cpu installed... */ type = CMMU_TYPE(m8820x_cmmu[num << cmmu_shift]. cmmu_regs[CMMU_IDR]); printf("CPU%d is associated to %d MC8820%c CMMUs\n", num, 1 << cmmu_shift, type == M88204_ID ? '4' : '0'); } }