/* Updates RX timestamper state machine. Non-zero return value means that calibration is done. */ int rxts_calibration_update(uint32_t *t24p_value) { int32_t ttrans = 0; if (spll_shifter_busy(0)) return 0; /* generate a fake RX timestamp and check if falling edge counter is ahead of rising edge counter */ int flip = ep_timestamper_cal_pulse(); /* look for transitions (with deglitching) */ lookup_transition(&det_rising, flip, cal_cur_phase, 1); lookup_transition(&det_falling, flip, cal_cur_phase, 0); if (cal_cur_phase >= CAL_SCAN_RANGE) { if (det_rising.state != TD_DONE || det_falling.state != TD_DONE) { TRACE_DEV("RXTS calibration error.\n"); return -1; } /* normalize */ while (det_falling.trans_phase >= REF_CLOCK_PERIOD_PS) det_falling.trans_phase -= REF_CLOCK_PERIOD_PS; while (det_rising.trans_phase >= REF_CLOCK_PERIOD_PS) det_rising.trans_phase -= REF_CLOCK_PERIOD_PS; /* Use falling edge as second sample of rising edge */ if (det_falling.trans_phase > det_rising.trans_phase) ttrans = det_falling.trans_phase - REF_CLOCK_PERIOD_PS/2; else if(det_falling.trans_phase < det_rising.trans_phase) ttrans = det_falling.trans_phase + REF_CLOCK_PERIOD_PS/2; ttrans += det_rising.trans_phase; ttrans /= 2; /*normalize ttrans*/ if(ttrans < 0) ttrans += REF_CLOCK_PERIOD_PS; if(ttrans >= REF_CLOCK_PERIOD_PS) ttrans -= REF_CLOCK_PERIOD_PS; TRACE_DEV("RXTS calibration: R@%dps, F@%dps, transition@%dps\n", det_rising.trans_phase, det_falling.trans_phase, ttrans); *t24p_value = (uint32_t)ttrans; return 1; } cal_cur_phase += CAL_SCAN_STEP; spll_set_phase_shift(0, cal_cur_phase); return 0; }
void pps_gen_adjust_utc(int32_t how_much) { uint32_t cr; #if 1 TRACE_DEV("ADJ: utc %d seconds\n", how_much); ppsg_writel( PPSG_REG_ADJ_UTCLO, how_much); ppsg_writel( PPSG_REG_ADJ_UTCHI, 0); ppsg_writel( PPSG_REG_ADJ_NSEC, 0); ppsg_writel( PPSG_REG_CR, PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_PULSE_WIDTH) | PPSG_CR_CNT_ADJ); #endif }
void pps_gen_adjust_nsec(int32_t how_much) { uint32_t cr; TRACE_DEV("ADJ: nsec %d nanoseconds\n", how_much); #if 1 ppsg_writel( PPSG_REG_ADJ_UTCLO, 0); ppsg_writel( PPSG_REG_ADJ_UTCHI, 0); ppsg_writel( PPSG_REG_ADJ_NSEC, ( how_much / 8 )); ppsg_writel( PPSG_REG_CR, PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_PULSE_WIDTH) | PPSG_CR_CNT_ADJ); #endif }