static int jz4780_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period) { struct jz4780_timer_softc *sc = (struct jz4780_timer_softc *)et->et_priv; uint32_t ticks; ticks = (first * et->et_frequency) / SBT_1S; if (ticks == 0) return (EINVAL); CSR_WRITE_4(sc, JZ_TC_TDFR(5), ticks); CSR_WRITE_4(sc, JZ_TC_TCNT(5), 0); CSR_WRITE_4(sc, JZ_TC_TESR, TESR_TCST5); return (0); }
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 }