Commit 52d9d4bc authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

softpll: 'source tracking' mode for aux clocks (observe phase shift between…

softpll: 'source tracking' mode for aux clocks (observe phase shift between local WR clock and a number of external clocks)
parent dae45335
Pipeline #261 failed with stages
in 9 seconds
......@@ -99,7 +99,7 @@ int wrc_mon_gui(void)
static uint32_t last_servo_count;
struct hal_port_state state;
int tx, rx;
int aux_stat;
struct spll_aux_clock_status aux_stat;
uint64_t sec;
uint32_t nsec;
struct wr_servo_state *s =
......@@ -209,16 +209,28 @@ int wrc_mon_gui(void)
spll_get_num_channels(NULL, &n_out);
for(i = 0; i < n_out; i++) {
for(i = 0; i < n_out - 1; i++) {
cprintf(C_GREY, "Aux clock %d status: ", i);
aux_stat = spll_get_aux_status(i);
if (aux_stat & SPLL_AUX_ENABLED)
if (aux_stat.flags & SPLL_AUX_SLAVE_ENABLED)
cprintf(C_GREEN, "enabled");
if (aux_stat & SPLL_AUX_LOCKED)
if (aux_stat.flags & SPLL_AUX_TRACKING_ENABLED )
cprintf(C_GREEN, "tracking source");
if (aux_stat.flags & SPLL_AUX_SLAVE_LOCKED)
cprintf(C_GREEN, ", locked");
if( aux_stat.flags & SPLL_AUX_TRACKING_READY )
{
cprintf(C_GREEN, ", ready");
cprintf(C_WHITE, " (AUX-to-WR offset: %d ps)", aux_stat.phase );
}
pp_printf("\n");
}
......@@ -310,7 +322,7 @@ int wrc_log_stats(void)
{
struct hal_port_state state;
int tx, rx;
int aux_stat;
struct spll_aux_clock_status aux_stat;
uint64_t sec;
uint32_t nsec;
struct wr_servo_state *s =
......@@ -354,7 +366,7 @@ int wrc_log_stats(void)
for(i = 0; i < n_out; i++) {
aux_stat = spll_get_aux_status(i);
pp_printf("aux%d:%x ", i, aux_stat);
pp_printf("aux%d:%x %x", i, aux_stat.flags, aux_stat.phase);
}
/* fixme: clock is not always 125 MHz */
......@@ -486,7 +498,7 @@ int wrc_wr_diags(void)
spll_get_num_channels(NULL, &n_out);
if (n_out > 8) n_out = 8; /* hardware limit. */
for(i = 0; i < n_out; i++) {
aux_stat |= (0x1 & spll_get_aux_status(i)) << i;
aux_stat |= (( SPLL_AUX_SLAVE_LOCKED | SPLL_AUX_TRACKING_READY ) & spll_get_aux_status(i).flags) << i;
}
wdiags_write_aux_state(aux_stat);
......
......@@ -43,7 +43,9 @@
#define AUX_DISABLED 1
#define AUX_LOCK_PLL 2
#define AUX_ALIGN_PHASE 3
#define AUX_READY 4
#define AUX_SLAVE_READY 4
#define AUX_WAIT_TRACKING_LOCK 5
#define AUX_TRACKING_READY 6
#define ALIGN_STATE_EXT_OFF 0
#define ALIGN_STATE_START 1
......
......@@ -84,10 +84,20 @@ static inline void start_ptrackers(struct softpll_state *s)
static inline void update_ptrackers(struct softpll_state *s, int tag_value, int tag_source)
{
if(tag_source > spll_n_chan_ref)
return;
ptrackers_update(s->ptrackers, tag_value, tag_source);
int i;
if(tag_source <= spll_n_chan_ref)
ptrackers_update(s->ptrackers, tag_value, tag_source);
for( i = 0; i < spll_n_chan_out - 1; i++ )
{
struct spll_aux_state *aux = &s->aux[i];
if( aux->mode != SPLL_AUX_MODE_TRACKING_SOURCE )
continue;
if( tag_source == spll_n_chan_ref + i + 1)
ptrackers_update( &aux->pll.tracker, tag_value, 0 );
}
}
static inline void sequencing_fsm(struct softpll_state *s, int tag_value, int tag_source)
......@@ -304,6 +314,8 @@ void spll_init(int mode, int slave_ref_channel, int flags)
spll_n_chan_ref = SPLL_CSR_N_REF_R(csr);
spll_n_chan_out = SPLL_CSR_N_OUT_R(csr);
if( spll_n_chan_out > 3 ) // fixme: bug in HDL?
spll_n_chan_out = 3;
spll_ljd_present = (flags & SPLL_FLAG_USE_LJD ? 1 : 0);
s->mode = mode;
......@@ -454,7 +466,7 @@ void spll_set_phase_shift(int channel, int32_t value_picoseconds)
if (channel == SPLL_ALL_CHANNELS) {
set_phase_shift(0, value_picoseconds);
for (i = 0; i < spll_n_chan_out - 1; i++)
if (softpll.aux[i].seq_state == AUX_READY)
if (softpll.aux[i].seq_state == AUX_SLAVE_READY)
set_phase_shift(i + 1, value_picoseconds);
} else
set_phase_shift(channel, value_picoseconds);
......@@ -508,6 +520,7 @@ void spll_set_ptracker_average_samples(int channel, int nsamples)
void spll_get_num_channels(int *n_ref, int *n_out)
{
pp_printf("NUM CHAN: %d %d %x\n\n", spll_n_chan_ref, spll_n_chan_out, SPLL->CSR );
if (n_ref)
*n_ref = spll_n_chan_ref;
if (n_out)
......@@ -573,7 +586,7 @@ static int spll_update_aux_clocks(void)
if(s->seq_state != AUX_DISABLED && !aux_locking_enabled(ch))
{
pll_verbose("softpll: disabled aux channel %d\n", ch);
pp_printf("softpll: disabled aux channel %d\n", ch);
spll_stop_channel(ch);
set_channel_status(ch, 0);
s->seq_state = AUX_DISABLED;
......@@ -583,10 +596,46 @@ static int spll_update_aux_clocks(void)
switch (s->seq_state) {
case AUX_DISABLED:
if (softpll.mpll.locked && aux_locking_enabled(ch)) {
pll_verbose("softpll: enabled aux channel %d\n", ch);
spll_start_channel(ch);
s->seq_state = AUX_LOCK_PLL;
if( s->mode == SPLL_AUX_MODE_SLAVE )
{
pll_verbose("softpll: enabled slave aux channel %d\n", ch);
spll_start_channel(ch);
s->seq_state = AUX_LOCK_PLL;
done_sth++;
}
else if ( s->mode == SPLL_AUX_MODE_TRACKING_SOURCE )
{
pll_verbose("softpll: enabled tracking aux channel %d\n", ch);
s->seq_state = AUX_WAIT_TRACKING_LOCK;
ptracker_init( &s->pll.tracker, ch + spll_n_chan_ref, PTRACKER_AVERAGE_SAMPLES );
ptracker_start( &s->pll.tracker );
done_sth++;
}
}
break;
case AUX_WAIT_TRACKING_LOCK:
if( s->pll.tracker.ready )
{
s->seq_state = AUX_TRACKING_READY;
s->phase_value = s->pll.tracker.phase_val;
set_channel_status(ch, 1);
done_sth++;
break;
}
case AUX_TRACKING_READY:
if (!softpll.mpll.locked)
{
pp_printf("softpll: aux tracking channel %d disabled due to PLL LOS\n", ch);
set_channel_status(ch, 0);
s->seq_state = AUX_DISABLED;
done_sth++;
}
else
{
s->phase_value = s->pll.tracker.phase_val;
}
break;
......@@ -603,12 +652,12 @@ static int spll_update_aux_clocks(void)
if (!mpll_shifter_busy(&s->pll.dmtd)) {
pll_verbose("softpll: channel %d phase aligned\n", ch);
set_channel_status(ch, 1);
s->seq_state = AUX_READY;
s->seq_state = AUX_SLAVE_READY;
done_sth++;
}
break;
case AUX_READY:
case AUX_SLAVE_READY:
if (!softpll.mpll.locked || !s->pll.dmtd.ld.locked) {
pll_verbose("softpll: aux channel %d or mpll lost lock\n", ch);
set_channel_status(ch, 0);
......@@ -621,15 +670,33 @@ static int spll_update_aux_clocks(void)
return done_sth != 0;
}
int spll_get_aux_status(int channel)
struct spll_aux_clock_status spll_get_aux_status(int channel )
{
int rval = 0;
struct spll_aux_clock_status rval;
rval.flags = 0;
if (softpll.aux[channel].seq_state != AUX_DISABLED)
rval |= SPLL_AUX_ENABLED;
int state = softpll.aux[channel].seq_state;
if (softpll.aux[channel].seq_state == AUX_READY)
rval |= SPLL_AUX_LOCKED;
switch ( state )
{
case AUX_DISABLED:
rval.flags = 0;
break;
case AUX_LOCK_PLL:
rval.flags = SPLL_AUX_SLAVE_ENABLED;
break;
case AUX_WAIT_TRACKING_LOCK:
rval.flags = SPLL_AUX_TRACKING_ENABLED;
break;
case AUX_TRACKING_READY:
rval.flags = SPLL_AUX_TRACKING_ENABLED | SPLL_AUX_TRACKING_READY;
break;
case AUX_SLAVE_READY:
rval.flags = SPLL_AUX_SLAVE_ENABLED | SPLL_AUX_SLAVE_LOCKED;
break;
}
rval.phase = softpll.aux[channel].phase_value;
return rval;
}
......@@ -818,3 +885,7 @@ int spll_get_debug_queue_samples( uint32_t *buf, int count, int undersample )
return n_ents;
}
void spll_set_aux_mode( int channel, int mode )
{
softpll.aux[channel].mode = mode;
}
......@@ -23,13 +23,18 @@
#include "spll_ptracker.h"
#include "spll_external.h"
/* Shortcut for 'channels' parameter in various API functions to perform operation on all channels */
#define SPLL_ALL_CHANNELS 0xffffffff
#define SPLL_AUX_MODE_SLAVE 0 /* Aux clock is disciplined from the local WR time base */
#define SPLL_AUX_MODE_TRACKING_SOURCE 1 /* Aux clock is a tracking source for the local WR time base */
/* Aux clock flags */
#define SPLL_AUX_ENABLED (1<<0) /* Locking the particular aux channel to the WR reference is enabled */
#define SPLL_AUX_LOCKED (1<<1) /* The particular aux clock is already locked to WR reference */
#define SPLL_AUX_SLAVE_ENABLED (1<<0) /* Locking the particular aux channel to the WR reference is enabled */
#define SPLL_AUX_SLAVE_LOCKED (1<<1) /* The particular aux clock is already locked to WR reference */
#define SPLL_AUX_TRACKING_ENABLED (1<<2) /* The particilar aux clock is used as a tracking source for a WR reference */
#define SPLL_AUX_TRACKING_READY (1<<3) /* The particilar aux clock is used as a tracking source for a WR reference */
/* Channels for spll_measure_frequency() */
#define SPLL_OSC_REF 0
......@@ -48,6 +53,12 @@
index 0 and is compared against all reference channels by the phase tracking mechanism.
*/
struct spll_aux_clock_status
{
uint32_t flags;
int phase;
};
/* PUBLIC API */
/*
......@@ -96,7 +107,7 @@ int spll_read_ptracker(int ref_channel, int32_t *phase_ps, int *enabled);
int spll_update(void);
/* Returns the status of given aux clock output (SPLL_AUX_) */
int spll_get_aux_status(int out_channel);
struct spll_aux_clock_status spll_get_aux_status(int channel );
/* Debug/testing functions */
......@@ -119,16 +130,21 @@ void spll_set_ptracker_average_samples(int channel, int nsamples);
int spll_get_debug_queue_samples( uint32_t *buf, int size, int undersample );
void spll_debug_queue_purge(void);
void spll_set_aux_mode( int channel, int mode );
/*
* Aux and main state:
* used to be in .c file, but we need it here for memory dumping
*/
/* NOTE: Please increment WRPC_SHMEM_VERSION if you change this structure */
struct spll_aux_state {
int mode; /* SPLL_AUX_MODE* */
int seq_state;
int32_t phase_target;
int32_t phase_value;
union {
struct spll_main_state dmtd;
struct spll_ptracker_state tracker;
/* spll_external_state ch_bb */
} pll;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment