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_init() { uint32_t cr; cr = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_PULSE_WIDTH); ppsg_writel( PPSG_REG_CR, cr); ppsg_writel( PPSG_REG_ADJ_UTCLO, 100 ); ppsg_writel( PPSG_REG_ADJ_UTCHI, 0); ppsg_writel( PPSG_REG_ADJ_NSEC, 0); ppsg_writel( PPSG_REG_CR, cr | PPSG_CR_CNT_SET); ppsg_writel( PPSG_REG_CR, cr); }
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 }
int external_align_fsm(volatile struct spll_external_state *s) { int v, done_sth = 0; switch(s->align_state) { case ALIGN_STATE_EXT_OFF: break; case ALIGN_STATE_WAIT_CLKIN: if( !(SPLL->ECCR & SPLL_ECCR_EXT_REF_STOPPED) ) { SPLL->ECCR |= SPLL_ECCR_EXT_REF_PLLRST; s->align_state = ALIGN_STATE_WAIT_PLOCK; done_sth++; } break; case ALIGN_STATE_WAIT_PLOCK: SPLL->ECCR &= (~SPLL_ECCR_EXT_REF_PLLRST); if( SPLL->ECCR & SPLL_ECCR_EXT_REF_STOPPED ) s->align_state = ALIGN_STATE_WAIT_CLKIN; else if( SPLL->ECCR & SPLL_ECCR_EXT_REF_LOCKED ) s->align_state = ALIGN_STATE_START; done_sth++; break; case ALIGN_STATE_START: if(s->helper->ld.locked) { disable_irq(); mpll_start(s->main); enable_irq(); s->align_state = ALIGN_STATE_START_MAIN; done_sth++; } break; case ALIGN_STATE_START_MAIN: SPLL->AL_CR = 2; if(s->helper->ld.locked && s->main->ld.locked) { PPSG->CR = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(10); PPSG->ADJ_NSEC = 3; PPSG->ESCR = PPSG_ESCR_SYNC; s->align_state = ALIGN_STATE_INIT_CSYNC; pll_verbose("EXT: DMTD locked.\n"); done_sth++; } break; case ALIGN_STATE_INIT_CSYNC: if (PPSG->ESCR & PPSG_ESCR_SYNC) { PPSG->ESCR = PPSG_ESCR_PPS_VALID; // enable PPS output (even though it's not aligned yet) s->align_timer = timer_get_tics() + 2 * TICS_PER_SECOND; s->align_state = ALIGN_STATE_WAIT_CSYNC; done_sth++; } break; case ALIGN_STATE_WAIT_CSYNC: if(time_after_eq(timer_get_tics(), s->align_timer)) { s->align_state = ALIGN_STATE_START_ALIGNMENT; s->align_shift = 0; pll_verbose("EXT: CSync complete.\n"); done_sth++; } break; case ALIGN_STATE_START_ALIGNMENT: if(align_sample(1, &v)) { v %= ALIGN_SAMPLE_PERIOD; if(v == 0 || v >= ALIGN_SAMPLE_PERIOD / 2) { s->align_target = EXT_PERIOD_NS; s->align_step = -100; } else if (s > 0) { s->align_target = 0; s->align_step = 100; } pll_verbose("EXT: Align target %d, step %d.\n", s->align_target, s->align_step); s->align_state = ALIGN_STATE_WAIT_SAMPLE; done_sth++; } break; case ALIGN_STATE_WAIT_SAMPLE: if(!mpll_shifter_busy(s->main) && align_sample(1, &v)) { v %= ALIGN_SAMPLE_PERIOD; if(v != s->align_target) { s->align_shift += s->align_step; mpll_set_phase_shift(s->main, s->align_shift); } else if (v == s->align_target) { s->align_shift += EXT_PPS_LATENCY_PS; mpll_set_phase_shift(s->main, s->align_shift); s->align_state = ALIGN_STATE_COMPENSATE_DELAY; } done_sth++; } break; case ALIGN_STATE_COMPENSATE_DELAY: if(!mpll_shifter_busy(s->main)) { pll_verbose("EXT: Align done.\n"); s->align_state = ALIGN_STATE_LOCKED; done_sth++; } break; case ALIGN_STATE_LOCKED: if(!external_locked(s)) { s->align_state = ALIGN_STATE_WAIT_CLKIN; done_sth++; } break; default: break; } return done_sth != 0; }