Commit c8e7db6d authored by Peter Jansweijer's avatar Peter Jansweijer

Add SPEC7 board files, ltc6950 init and phy_calibration for gtx_lp

parent 5a1c839c
......@@ -4,6 +4,7 @@ obj-$(CONFIG_TARGET_WR_SWITCH) += boards/wr-switch/main.o boards/wr-switch/gpio-
obj-$(CONFIG_TARGET_AFCZ) += boards/afcz/board.o
obj-$(CONFIG_TARGET_SIS8300KU) += boards/sis8300ku/board.o
obj-$(CONFIG_TARGET_ERTM14) += boards/ertm14/board.o boards/ertm14/ertm15_rf_distr.o boards/ertm14/phy_calibration.o boards/ertm14/rf_frame_transceiver.o boards/ertm14/cmd_ertm14.o
obj-$(CONFIG_TARGET_SPEC7) += boards/spec7/board.o boards/spec7/phy_calibration.o
obj-$(CONFIG_TARGET_PXIE_FMC) += boards/pxie-fmc/board.o
#boards/sis8300ku/board.o: boards/sis8300ku/sdbfs-image.h
......
#include "board.h"
#include "dev/bb_spi.h"
#include "dev/spi_flash.h"
#include "dev/bb_i2c.h"
#include "dev/i2c_eeprom.h"
#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;
static struct gpio_pin pin_pll_cs_n_o = { &board.gpio_aux, 0 };
static struct gpio_pin pin_pll_mosi_o = { &board.gpio_aux, 1 };
static struct gpio_pin pin_pll_miso_i = { &board.gpio_aux, 2 };
static struct gpio_pin pin_pll_sck_o = { &board.gpio_aux, 3 };
static struct gpio_pin pin_pll_reset_n_o = { &board.gpio_aux, 4 };
static struct gpio_pin pin_pll_lock_i = { &board.gpio_aux, 5 };
static struct gpio_pin pin_pll_status_i = { &board.gpio_aux, 6 };
static struct gpio_pin pin_pll_sync_o = { &board.gpio_aux, 7 };
static struct gpio_pin pin_pll_wr_mode0_o = { &board.gpio_aux, 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 =
#include "configs/ltc6950_base_config.h"
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;
int mode_hpsec_gm = 0;
// Set clock multiplexers (U63, U64) depending on wrc_ptp_mode
switch(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;
}
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);
// ltc6950 initialization depending on wrc_ptp_mode
board_dbg("Initialize ltc6950.\n");
if (wrc_ptp_mode == WRC_MODE_MASTER | mode_hpsec_gm == 1) {
// 10 MHZ from TCXO (WRC_MODE_MASTER) on outputs 0, 1, 2
// or (for HPSEC in WRC_MODE GM) External 10 MHZ In (Bulls-Eye B03/B04) => 125 MHz
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);
}
board_dbg("Select ltc6950 output as clk_sys source.\n");
/* ltc6950 now initialized so switch clk_sys from free running clk_dmtd to ltc6950 output */
gen_gpio_out( &pin_pll_clk_sel, 1);
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
initialize the GPIO controller they're connected to */
wb_gpio_create( &board.gpio_aux, BASE_GPIO );
// Use free running dmtd clock for bootstrapping
gen_gpio_out( &pin_pll_clk_sel, 0);
board_dbg("Use free running dmtd clock for bootstrapping.\n");
// PLL reset (although not connected at top level) de-asserted
gen_gpio_out( &pin_pll_reset_n_o, 1);
// 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) */
bb_spi_create( &board.spi_ltc6950,
&pin_pll_cs_n_o,
&pin_pll_mosi_o,
&pin_pll_miso_i,
&pin_pll_sck_o,
100 );
ltc6950_init(&board.ltc6950_pll, &board.spi_ltc6950);
// Reset the PLL (RES6950 clears itself)
ltc6950_write( &board.ltc6950_pll, 0x03, 4);
timer_delay_ms(1);
int id = ltc6950_read( &board.ltc6950_pll, 0x16 );
if( id != 0x65 )
{
board_dbg("detect LTC6950: ID %x should be %x\n", id, 0x65 );
} else {
spec7_set_pll_wr_mode(WRC_MODE_SLAVE);
}
return 0;
}
struct i2c_bus dev_i2c_eeprom;
struct i2c_eeprom_device wrc_eeprom_dev;
int wrc_board_early_init()
{
/* Initialize SPEC7 clocking */
spec7_init();
/* create and initialize eeprom I2C bus */
bb_i2c_create(&dev_i2c_eeprom,
&pin_eeprom_scl,
&pin_eeprom_sda );
bb_i2c_init(&dev_i2c_eeprom);
i2c_eeprom_create(&wrc_eeprom_dev, &dev_i2c_eeprom, 0x50, 2);
storage_i2ceeprom_create( &wrc_storage_dev, &wrc_eeprom_dev );
/*
* Mount SDBFS filesystem from storage.
*/
storage_mount( &wrc_storage_dev );
return 0;
}
int wrc_board_init()
{
uint8_t mac_addr[6];
/*
* Try reading MAC addr stored in flash
*/
if (storage_get_persistent_mac(0, mac_addr) == -1) {
board_dbg("Failed to get MAC address from the flash. Using fallback address.\n");
mac_addr[0] = 0x22;
mac_addr[1] = 0x33;
mac_addr[2] = 0x44; /* fallback MAC if get_persistent_mac fails */
mac_addr[3] = 0x55;
mac_addr[4] = 0x66;
mac_addr[5] = 0x77;
}
ep_set_mac_addr(&wrc_endpoint_dev, mac_addr);
ep_pfilter_init_default(&wrc_endpoint_dev);
return 0;
}
extern int phy_calibration_poll();
extern void phy_calibration_init();
int wrc_board_create_tasks()
{
wrc_task_create( "phy-cal", phy_calibration_init, phy_calibration_poll );
return 0;
}
/*
* This work is part of the White Rabbit project
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#ifndef __BOARD_SPEC7_H
#define __BOARD_SPEC7_H
#include "dev/gpio.h"
#include "dev/ltc6950.h"
/*
* This is meant to be automatically included by the Makefile,
* when wrpc-sw is build for wrc (node) -- as opposed to wrs (switch)
*/
/* Fixed base addresses */
#define BASE_MINIC 0x40000
#define BASE_EP 0x40100
#define BASE_SOFTPLL 0x40200
#define BASE_PPS_GEN 0x40300
#define BASE_SYSCON 0x40400
#define BASE_UART 0x40500
#define BASE_ONEWIRE 0x40600
//#define BASE_ETHERNOBE_CFG 0x40700
#define BASE_AUXWB 0x48000
/* SPEC7 WB bus behind wr-cores Aux WB bus */
#define BASE_GPIO (BASE_AUXWB + 0x000)
/* Board-specific parameters */
#define TICS_PER_SECOND 1000
/* WR Core system/CPU clock frequency in Hz */
#define CPU_CLOCK 62500000ULL
/* WR Reference clock period (picoseconds) and frequency (Hz) */
/* GENERIC_PHY_16BIT */
#define NS_PER_CLOCK 16
#define REF_CLOCK_PERIOD_PS 16000
#define REF_CLOCK_FREQ_HZ 62500000
/* Baud rate of the builtin UART (does not apply to the VUART) */
#define UART_BAUDRATE 115200ULL
/* Maximum number of simultaneously created sockets */
#define NET_MAX_SOCKETS 12
/* Socket buffer size, determines the max. RX packet size */
#define NET_MAX_SKBUF_SIZE 512
/* Number of auxillary clock channels - usually equal to the number of FMCs */
#define NUM_AUX_CLOCKS 1
/* spll parameter that are board-specific */
// SPEC7 has GENERIC_PHY_16BIT
# define BOARD_DIVIDE_DMTD_CLOCKS 0
#define BOARD_MAX_CHAN_REF 1
#define BOARD_MAX_CHAN_AUX 2
#define BOARD_MAX_PTRACKERS 1
#ifdef CONFIG_IP
#define HAS_IP 1
#else
#define HAS_IP 0
#endif
#ifdef CONFIG_ABSCAL
#define HAS_ABSCAL 1
#else
#define HAS_ABSCAL 0
#endif
#define CONFIG_DISALLOW_LONG_DIVISION
#define BOARD_MAX_CONSOLE_DEVICES 1
#define CONSOLE_UART_BAUDRATE 115200
#define SDB_ADDRESS 0x30000
#define FMC_EEPROM_ADR 0x50
#define SDBFS_REC 5
// PLL WR_MODE options:
# define PLL_WR_MODE_MASTER 1
# define PLL_WR_MODE_SLAVE 2
# define PLL_WR_MODE_GM 3
void spec7_set_pll_wr_mode(int pll_wr_mode);
int spec7_init(void);
struct spec7_board
{
struct gpio_device gpio_aux;
struct spi_bus spi_ltc6950;
struct ltc6950_device ltc6950_pll;
int pll_wr_mode;
};
void sdb_find_devices(void);
void sdb_print_devices(void);
#endif /* __BOARD_SPEC7_H */
/* Configuration for the SPEC7: Forward 125 MHz VCXO_REFCLK at CLK input to outputs 0, 1, 2 */
{
21,
{
//{0x0000, 0x08}, /* Reg 0 = status info, read only */
{0x0001, 0x00}, /* STAT1 mask */
{0x0002, 0x00}, /* STAT2 mask */
{0x0003, 0x70}, /* Power Down PLL, VCO and REF, no LKEN, Enable OUT[0] */
{0x0004, 0xf0}, /* Power Down OUT[4:3]; Enable OUT[2:1]*/
{0x0005, 0x98}, /* LKWIN = 30ns; LKCT = 128 cycles; cp = 4mA */
{0x0006, 0x00}, /* No ChargePump intervention */
{0x0007, 0x00}, /* No REST_R = 0 */
{0x0008, 0x02}, /* R divider = 2 */
{0x0009, 0x00}, /* No REST_N = 0 */
{0x000A, 0x19}, /* N divider = 25 */
{0x000B, 0x41}, /* SYNCMD = StandAlone; No FILTV/R */
{0x000C, 0x80}, /* set SYNC_EN0; DEL0=0 */
{0x000D, 0x81}, /* set IBIAS0; output divider M0 = 1 */
{0x000E, 0x80}, /* set SYNC_EN1; DEL1=0 */
{0x000F, 0x81}, /* set IBIAS1; output divider M1 = 1 */
{0x0010, 0x80}, /* set SYNC_EN2; DEL2=0 */
{0x0011, 0x81}, /* set IBIAS2; output divider M2 = 1 */
{0x0012, 0x00}, /* no SYNC_EN2; DEL3=0 */
{0x0013, 0x01}, /* no IBIAS3; output divider M3 = 1 */
{0x0014, 0x00}, /* no SYNC_EN4; DEL0=0 */
{0x0015, 0x01} /* no RDIVOUT; output divider M4 = 1 */
//{0x0016, 0x65} /* Reg 16 = REVision and PARTnumber, read only => 0x65 */
}
};
/* Define ltc6950 bit names */
#define LTC6950_LOCK 4
/* Configuration for the SPEC7: External 10 MHZ In (Bulls-Eye B03/B04) => 125 MHz on outputs 0, 1, 2 */
{
21,
{
//{0x0000, 0x04}, /* Reg 0 = status info, read only */
{0x0001, 0x04}, /* STAT1 mask LOCK */
{0x0002, 0x3b}, /* STAT2 mask NO_VCO, NO_REF, UNLOCK, THI, TLO*/
{0x0003, 0x08}, /* Power PLL, VCO and REF, set LKEN, Enable OUT[0] */
{0x0004, 0xf0}, /* Power Down OUT[4:3]; Enable OUT[2:1]*/
{0x0005, 0x98}, /* LKWIN = 30ns; LKCT = 128 cycles; cp = 4mA */
{0x0006, 0x00}, /* No ChargePump intervention */
{0x0007, 0x00}, /* No REST_R = 0 */
{0x0008, 0x02}, /* R divider = 2 */
{0x0009, 0x00}, /* No REST_N = 0 */
{0x000A, 0x19}, /* N divider = 25 */
{0x000B, 0x41}, /* SYNCMD = StandAlone; No FILTV/R */
{0x000C, 0x80}, /* set SYNC_EN0; DEL0=0 */
{0x000D, 0x81}, /* set IBIAS0; output divider M0 = 1 */
{0x000E, 0x80}, /* set SYNC_EN1; DEL1=0 */
{0x000F, 0x81}, /* set IBIAS1; output divider M1 = 1 */
{0x0010, 0x80}, /* set SYNC_EN2; DEL2=0 */
{0x0011, 0x81}, /* set IBIAS2; output divider M2 = 1 */
{0x0012, 0x00}, /* no SYNC_EN2; DEL3=0 */
{0x0013, 0x01}, /* no IBIAS3; output divider M3 = 1 */
{0x0014, 0x00}, /* no SYNC_EN4; DEL0=0 */
{0x0015, 0x01} /* no RDIVOUT; output divider M4 = 1 */
//{0x0016, 0x65} /* Reg 16 = REVision and PARTnumber, read only => 0x65 */
}
};
\ No newline at end of file
This diff is collapsed.
......@@ -27,6 +27,8 @@
# include "boards/ertm14/board.h"
#elif defined(CONFIG_TARGET_SIS8300KU)
# include "boards/sis8300ku/board.h"
#elif defined(CONFIG_TARGET_SPEC7)
# include "boards/spec7/board.h"
#elif defined(CONFIG_TARGET_PXIE_FMC)
# include "boards/pxie-fmc/board.h"
#endif
......
Subproject commit dc1c7d268968cbb37a6ab5655e4cd683b25b7a50
Subproject commit 58d7be5686e98e938018a0cca8627a8ad1e88386
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