static bool lapic_tmr_init(tmr_cb_t master) { if(intr_state()) fatal("interrupts may not be enabled in lapic_tmr_init()!\n"); _master = master; // fastest possible rate: 0xB (1011) -> FSB tick rate. on modern // systems, this should allow near nanoseconds resolution. APIC_REG(APIC_REG_DIVIDE_CONFIG) = 0xB; uint8_t old_rate = rtc_set_rate(RTC_RATE_128HZ); rtc_calibrate(lapic_tmr_calibrate); // enable interrupts for this to work, disable the again afterwards. intr_enable(true); // wait for calibration to finish. while(!_lapic_hz) asm volatile("hlt"); intr_disable(); rtc_set_rate(old_rate); info("local apic timer calibrated to %ld hz\n", _lapic_hz); intr_add(IRQ_LAPIC_TIMER, lapic_tmr_handler); APIC_REG(APIC_REG_LVT_TIMER) = IRQ_LAPIC_TIMER; return true; }
/* Init RTC */ void rtc_init_osc(int use_32khz) { __use_32khz = use_32khz; if (use_32khz) { uint32_t old; /* You have to hold its hand with this one */ /* once you start the 32KHz crystal it can only be * stopped with a reset (hard or soft). */ /* first, disable the ring osc */ CRM->RINGOSC_CNTLbits.ROSC_EN = 0; /* enable the 32kHZ crystal */ CRM->XTAL32_CNTLbits.XTAL32_EN = 1; /* set the XTAL32_EXISTS bit */ /* the datasheet says to do this after you check that RTC_COUNT is changing, but it is not correct; it needs to be set first */ CRM->SYS_CNTLbits.XTAL32_EXISTS = 1; { old = CRM->RTC_COUNT; while (CRM->RTC_COUNT == old) continue; /* RTC has started up */ CRM->SYS_CNTLbits.XTAL32_EXISTS = 1; rtc_freq = 32000; } } else { /* Enable ring osc */ CRM->RINGOSC_CNTLbits.ROSC_EN = 1; CRM->XTAL32_CNTLbits.XTAL32_EN = 0; /* Set default tune values from datasheet */ CRM->RINGOSC_CNTLbits.ROSC_CTUNE = 0x6; CRM->RINGOSC_CNTLbits.ROSC_FTUNE = 0x17; /* Trigger calibration */ rtc_calibrate(); } }