Commit b2161598 authored by Peter Jansweijer's avatar Peter Jansweijer

add even_odd detector. Detect alignment of 10MHz and 125MHz at the first 10MHz…

add even_odd detector. Detect alignment of 10MHz and 125MHz at the first 10MHz edge after PPS-in. Software reset LTC6950 when misaligned
parent 53d927f2
Pipeline #360 failed with stages
in 9 seconds
......@@ -6,6 +6,9 @@
#include "dev/syscon.h"
#include "storage.h"
#include <wrc_ptp.h>
#include "spll_defs.h"
#include "spll_common.h"
#include "hw/pps_gen_regs.h"
struct spec7_board board;
......@@ -22,6 +25,8 @@ static struct gpio_pin pin_pll_wr_mode1_o = { &board.gpio_aux, 9 };
static struct gpio_pin pin_pll_clk_sel = { &board.gpio_aux, 10 };
static struct gpio_pin pin_eeprom_scl = { &board.gpio_aux, 11 };
static struct gpio_pin pin_eeprom_sda = { &board.gpio_aux, 12 };
static struct gpio_pin pin_pll_even_odd_n_i = { &board.gpio_aux, 13 };
static struct gpio_pin pin_pll_sync_done_i = { &board.gpio_aux, 14 };
#include "configs/ltc6950_defs.h"
static struct ltc6950_config ltc6950_base_config =
......@@ -29,9 +34,17 @@ static struct ltc6950_config ltc6950_base_config =
static struct ltc6950_config ltc6950_ext_10mhz_config =
#include "configs/ltc6950_ext_10mhz_config.h"
#define PLL_EVEN_ODD_TIMEOUT_MS 10000
#define PLL_SYNC_TIMEOUT_MS 4000
timeout_t pll_even_odd_timeout;
timeout_t pll_sync_timeout;
//#define CONFIG_HPSEC_GM
#undef CONFIG_HPSEC_GM
//volatile struct softpll_state softpll;
void spec7_set_pll_wr_mode(int wrc_ptp_mode)
{
int pll_wr_mode;
......@@ -42,27 +55,27 @@ void spec7_set_pll_wr_mode(int wrc_ptp_mode)
case WRC_MODE_GM || WRC_MODE_ABSCAL:
// Default reference design locks local VCXO to external 10 MHz
pll_wr_mode = PLL_WR_MODE_SLAVE;
#if defined(CONFIG_HPSEC_GM)
// When HPSEC is used in GM mode then HPSEC locks to external
// 10 MHz via LTC6950 and WRC_MODE *must* be free running master.
// Note: WRC_MODE_GM tries to align the local VCXO with the
// external 10 MHz but in HPSEC_GM case the VCXO is not used.
pp_printf("ERROR: HPSEC_GM must use WRC_MODE_MASTER.\n");
#endif
break;
case WRC_MODE_MASTER:
pll_wr_mode = PLL_WR_MODE_MASTER;
#if defined(CONFIG_HPSEC_GM)
// When HPSEC is used in GM mode then HPSEC locks to external
// 10 MHz via LTC6950 and WRC_MODE *must* be free running master.
pll_wr_mode = PLL_WR_MODE_GM;
mode_hpsec_gm = 1;
#endif
break;
default:
pll_wr_mode = PLL_WR_MODE_SLAVE;
}
#if defined(CONFIG_HPSEC_GM)
// When HPSEC is used in GM mode then HPSEC locks to external
// 10 MHz via LTC6950 and WRC_MODE *must* be free running master.
// Note: WRC_MODE_GM tries to align the local VCXO with the
// external 10 MHz but in HPSEC_GM case the VCXO is not used.
if (wrc_ptp_mode != WRC_MODE_MASTER)
pp_printf("ERROR: HPSEC_GM must use WRC_MODE_MASTER.\n");
else {
pll_wr_mode = PLL_WR_MODE_GM;
mode_hpsec_gm = 1;
}
#endif
gen_gpio_out( &pin_pll_wr_mode0_o, (pll_wr_mode & 0x1) ? 1 : 0);
gen_gpio_out( &pin_pll_wr_mode1_o, (pll_wr_mode & 0x2) ? 1 : 0);
board_dbg("wr_mode: %d\n", pll_wr_mode);
......@@ -75,6 +88,9 @@ void spec7_set_pll_wr_mode(int wrc_ptp_mode)
ltc6950_configure(&board.ltc6950_pll, &ltc6950_ext_10mhz_config);
while ((ltc6950_read(&board.ltc6950_pll, 0x00) & LTC6950_LOCK) == 0);
board_dbg("ltc6950 locked.\n");
#if defined(CONFIG_HPSEC_GM)
pll_sync();
#endif
} else {
// Forward 125 MHz VCXO_REFCLK at CLK input to outputs 0, 1, 2
ltc6950_configure(&board.ltc6950_pll, &ltc6950_base_config);
......@@ -86,6 +102,85 @@ void spec7_set_pll_wr_mode(int wrc_ptp_mode)
timer_delay_ms(10);
}
int pll_sync()
{
// Used in HPSEC Grand Master mode where external 10MHz generates 125MHz.
// 125MHz is not an integer multiple of 10MHz so it has two lock modes: even/odd.
// The generated 125MHz must be even/odd alligned with the external 10MHz/1PPS.
tmo_init(&pll_even_odd_timeout, PLL_EVEN_ODD_TIMEOUT_MS);
while (gen_gpio_in( &pin_pll_even_odd_n_i ) == 0) {
// Reset the PLL (RES6950 clears itself)
board_dbg("Reset ltc6950...\n");
ltc6950_write( &board.ltc6950_pll, 0x03, 4);
timer_delay_ms(1);
ltc6950_configure(&board.ltc6950_pll, &ltc6950_ext_10mhz_config);
while ((ltc6950_read(&board.ltc6950_pll, 0x00) & LTC6950_LOCK) == 0);
timer_delay_ms(1000); // wait for next PPS
if ( tmo_expired(&pll_even_odd_timeout)) {
pp_printf("TIMEOUT: External 10MHz/1PPS lock to \"even\" 125MHz clock cycle.\n");
return 0;
}
}
board_dbg("HPSEC_GM mode: External 10MHz/1PPS lock achieved on \"even\" 125MHz clock cycle\n");
// Trigger a clk_ref_125m to clk_ref_62m5 divider synchronisation
gen_gpio_out( &pin_pll_sync_o, 1);
gen_gpio_out( &pin_pll_sync_o, 0);
tmo_init(&pll_sync_timeout, PLL_SYNC_TIMEOUT_MS);
// Wait for sync sequence done
while (gen_gpio_in( &pin_pll_sync_done_i ) == 0) {
if ( tmo_expired(&pll_sync_timeout)) {
pp_printf("TIMEOUT: clk_ref_125m to clk_ref_62m5 divider synchronization.\n");
return 0;
}
}
board_dbg("HPSEC_GM mode: clk_ref_125m to clk_ref_62m5 divider synchronization done\n");
/*
PPSG->ESCR = PPSG_ESCR_SYNC;
tmo_init(&pll_sync_timeout, PLL_SYNC_TIMEOUT_MS);
// Wait for PPS sync sequence done
while (PPSG->ESCR & PPSG_ESCR_SYNC == 0) {
if ( tmo_expired(&pll_sync_timeout)) {
pp_printf("TIMEOUT: External PPS alignment.\n");
return 0;
}
}
board_dbg("HPSEC_GM mode: synced to external PPS.\n");
*/
phy_calibration_init();
while (!phy_calibration_done()) {
phy_calibration_poll();
}
return 1;
}
int post_pll_lock(int wrc_ptp_mode)
{
#if defined(CONFIG_HPSEC_GM)
// Sync external PPS when in HPSEC_GM mode
PPSG->ESCR = PPSG_ESCR_SYNC;
tmo_init(&pll_sync_timeout, PLL_SYNC_TIMEOUT_MS);
// Wait for PPS sync sequence done
while (PPSG->ESCR & PPSG_ESCR_SYNC == 0) {
if ( tmo_expired(&pll_sync_timeout)) {
pp_printf("TIMEOUT: External PPS alignment.\n");
return 0;
}
}
board_dbg("HPSEC_GM mode: synced to external PPS.\n");
#endif
if (wrc_ptp_mode == WRC_MODE_MASTER)
//phy_calibration_init();
return 1;
}
int spec7_init()
{
/* most of the I/Os of the slow peripherals (i2c, spi) are bitbanged. First, let's
......@@ -99,7 +194,7 @@ int spec7_init()
// PLL reset (although not connected at top level) de-asserted
gen_gpio_out( &pin_pll_reset_n_o, 1);
// PLL sync de-asserted
// Do not (yet) sync the clk_ref_125m to clk_ref_62m5 divider
gen_gpio_out( &pin_pll_sync_o, 0);
/* initialize the SPI bus for the SPEC7 PLL (LTC6950 U66) */
......
......@@ -482,7 +482,11 @@ int phy_calibration_poll()
return 0;
}
int phy_calibration_done()
{
struct wrc_port_rx_setup_state *fsm_rx = &rx_state;
return (fsm_rx->state == RX_SETUP_DONE);
}
void phy_calibration_init()
{
......
Subproject commit 038da90b9556ead6f34a0e6a61a4b950e4a9424c
Subproject commit bcb58179de2977215770f7b412e734237ffa4561
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