void caches_on(void) { uint32 config1; uint start, end, size, lsize; /* Save cache config */ config1 = MFC0(C0_CONFIG, 1); icache_probe(config1, &size, &lsize); icache_size = size; ic_lsize = lsize; dcache_probe(config1, &size, &lsize); dcache_size = size; dc_lsize = lsize; /* If caches are not in the default state then * presume that caches are already init'd */ if ((MFC0(C0_CONFIG, 0) & CONF_CM_CMASK) != CONF_CM_UNCACHED) { blast_dcache(); blast_icache(); return; } /* init icache */ start = KSEG0; end = (start + icache_size); MTC0(C0_TAGLO, 0, 0); MTC0(C0_TAGHI, 0, 0); while (start < end) { cache_op(start, Index_Store_Tag_I); start += ic_lsize; } /* init dcache */ start = KSEG0; end = (start + dcache_size); MTC0(C0_TAGLO, 0, 0); MTC0(C0_TAGHI, 0, 0); while (start < end) { cache_op(start, Index_Store_Tag_D); start += dc_lsize; } /* Must be in KSEG1 to change cachability */ change_cachability = (void (*)(uint32)) KSEG1ADDR(_change_cachability); change_cachability(CONF_CM_CACHABLE_NONCOHERENT); }
static void _change_cachability(uint32 cm) { uint32 prid, c0reg; c0reg = MFC0(C0_CONFIG, 0); c0reg &= ~CONF_CM_CMASK; c0reg |= (cm & CONF_CM_CMASK); MTC0(C0_CONFIG, 0, c0reg); prid = MFC0(C0_PRID, 0); if ((prid & (PRID_COMP_MASK | PRID_IMP_MASK)) == (PRID_COMP_BROADCOM | PRID_IMP_BCM3302)) { c0reg = MFC0(C0_BROADCOM, 0); /* Enable icache & dcache */ c0reg |= BRCM_IC_ENABLE | BRCM_DC_ENABLE; MTC0(C0_BROADCOM, 0, c0reg); } }
static void ingenic_cpu_init(struct cpu_info *ci) { uint32_t reg; /* enable IPIs for this core */ reg = MFC0(12, 4); /* reset entry and interrupts */ if (cpu_index(ci) == 1) { reg |= REIM_MIRQ1_M; } else reg |= REIM_MIRQ0_M; MTC0(reg, 12, 4); printf("%s %d %08x\n", __func__, cpu_index(ci), reg); }
void * osl_init() { uint32 c0reg; sb_t *sbh; /* Disable interrupts */ c0reg = MFC0(C0_STATUS, 0); c0reg &= ~ST0_IE; MTC0(C0_STATUS, 0, c0reg); /* Scan backplane */ sbh = sb_kattach(SB_OSH); sb_mips_init(sbh, 0); sb_serial_init(sbh, serial_add); /* Init malloc */ free_mem_ptr = (ulong) bss_end; free_mem_ptr_end = ((ulong)&c0reg) - 8192; /* Enough stack? */ return ((void *)sbh); }
void cpu_initclocks(void) { struct cpu_info * const ci = curcpu(); uint32_t cnt; static struct timecounter tc = { ingenic_count_read, /* get_timecount */ 0, /* no poll_pps */ ~0u, /* counter_mask */ 12000000, /* frequency */ "Ingenic OS timer", /* name */ 100, /* quality */ }; curcpu()->ci_cctr_freq = tc.tc_frequency; tc_init(&tc); printf("starting timer interrupt...\n"); /* start the timer interrupt */ cnt = readreg(JZ_OST_CNT_LO); ci->ci_next_cp0_clk_intr = cnt + ci->ci_cycles_per_hz; writereg(JZ_TC_TFCR, TFR_OSTFLAG); writereg(JZ_OST_DATA, ci->ci_next_cp0_clk_intr); /* * XXX * We can use OST or one of the regular timers to generate the 100hz * interrupt. OST interrupts need to be rescheduled every time and by * only one core, the regular timer can be programmed to fire every * 10ms without rescheduling and we'd still use the OST as time base. * OST is supposed to fire on INT2 although I haven't been able to get * that to work yet ( all I get is INT0 which is for hardware interrupts * in general ) * So if we can get OST to fire on INT2 we can just block INT0 on core1 * and have a timer interrupt on both cores, if not the regular timer * would be more convenient but we'd have to shoot an IPI to core1 on * every tick. * For now, use OST and hope we'll figure out how to make it fire on * INT2. */ #ifdef USE_OST writereg(JZ_TC_TMCR, TFR_OSTFLAG); #else writereg(JZ_TC_TECR, TESR_TCST5); /* disable timer 5 */ writereg(JZ_TC_TCNT(5), 0); writereg(JZ_TC_TDFR(5), 30000); /* 10ms at 48MHz / 16 */ writereg(JZ_TC_TDHR(5), 60000); /* not reached */ writereg(JZ_TC_TCSR(5), TCSR_EXT_EN| TCSR_DIV_16); writereg(JZ_TC_TMCR, TFR_FFLAG5); writereg(JZ_TC_TFCR, TFR_FFLAG5); writereg(JZ_TC_TESR, TESR_TCST5); /* enable timer 5 */ #endif #ifdef INGENIC_CLOCK_DEBUG printf("INTC %08x %08x\n", readreg(JZ_ICSR0), readreg(JZ_ICSR1)); printf("ICMR0 %08x\n", readreg(JZ_ICMR0)); #endif writereg(JZ_ICMCR0, 0x0c000000); /* TCU2, OST */ spl0(); #ifdef INGENIC_CLOCK_DEBUG printf("TFR: %08x\n", readreg(JZ_TC_TFR)); printf("TMR: %08x\n", readreg(JZ_TC_TMR)); printf("cnt5: %08x\n", readreg(JZ_TC_TCNT(5))); printf("CR: %08x\n", MFC0(MIPS_COP_0_CAUSE, 0)); printf("SR: %08x\n", MFC0(MIPS_COP_0_STATUS, 0)); delay(100000); printf("TFR: %08x\n", readreg(JZ_TC_TFR)); printf("TMR: %08x\n", readreg(JZ_TC_TMR)); printf("cnt5: %08x\n", readreg(JZ_TC_TCNT(5))); printf("CR: %08x\n", MFC0(MIPS_COP_0_CAUSE, 0)); printf("SR: %08x\n", MFC0(MIPS_COP_0_STATUS, 0)); printf("TFR: %08x\n", readreg(JZ_TC_TFR)); printf("TMR: %08x\n", readreg(JZ_TC_TMR)); printf("cnt5: %08x\n", readreg(JZ_TC_TCNT(5))); printf("CR: %08x\n", MFC0(MIPS_COP_0_CAUSE, 0)); printf("SR: %08x\n", MFC0(MIPS_COP_0_STATUS, 0)); printf("INTC %08x %08x\n", readreg(JZ_ICSR0), readreg(JZ_ICSR1)); delay(3000000); printf("%s %d\n", __func__, MFC0(12, 3)); printf("%s %08x\n", __func__, MFC0(12, 4)); #endif }