Commit 97fbe7b0 authored by baujc's avatar baujc Committed by Adam Wujek

Export PPS generation and control of the timing mode in PPSi

parent e472fac3
OBJS = init.o fpga_io.o util.o pps_gen.o i2c.o shw_io.o i2c_bitbang.o \
i2c_fpga_reg.o pio.o libshw_i2c.o i2c_sfp.o fan.o i2c_io.o hwiu.o \
ptpd_netif.o hal_client.o \
ptpd_netif.o hal_client.o hal_minirpc.o\
shmem.o rt_client.o \
dot-config.o wrs-msg.o \
mac.o \
......
#include <minipc.h>
#include <hal_exports.h> /* for exported structs/function protos */
/* Export structures, shared by server and client for argument matching */
//int halexp_lock_cmd(const char *port_name, int command, int priority);
struct minipc_pd __rpcdef_lock_cmd = {
.name = "lock_cmd",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
.args = {
MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRING, char *),
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_END,
},
};
//int halexp_pps_cmd(int cmd, hexp_pps_params_t *params);
struct minipc_pd __rpcdef_pps_cmd = {
.name = "pps_cmd",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
.args = {
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_ENCODE(MINIPC_ATYPE_STRUCT, hexp_pps_params_t),
MINIPC_ARG_END,
},
};
......@@ -42,4 +42,14 @@ int shw_pps_gen_in_term_read(void);
/* Enables PPS_IN 50Ohm termination based on dot-config option */
int shw_pps_gen_in_term_init(void);
/* Get the timing mode state */
int shw_pps_get_timing_mode_state(void);
/* Get the timing mode */
int shw_pps_get_timing_mode(void);
/* Set the timing mode */
int shw_pps_set_timing_mode(int tm);
#endif /* __LIBWR_PPS_GEN_H */
......@@ -11,6 +11,7 @@
#include <sys/time.h>
#include <fpga_io.h>
#include <rt_ipc.h>
#include <regs/ppsg-regs.h>
#include <libwr/switch_hw.h>
......@@ -95,6 +96,62 @@ int shw_pps_gen_enable_output_read(void)
PPSG_PPS_OUT_ENABLE : PPSG_PPS_OUT_DISABLE;
}
int shw_pps_set_timing_mode(int tm) {
int mode=-1;
switch (tm) {
case HAL_TIMING_MODE_GRAND_MASTER:
mode=RTS_MODE_GM_EXTERNAL;
break;
case HAL_TIMING_MODE_FREE_MASTER:
mode=RTS_MODE_GM_FREERUNNING;
break;
case HAL_TIMING_MODE_BC:
mode=RTS_MODE_BC;
break;
default :
pr_error("%s: Invalid timing mode %d\n", __func__, tm);
return -1;
}
if ( rts_set_mode(mode)==-1) {
pr_error("%s: Cannot set timing mode to %d (HAL_TIMING_...)\n", __func__, tm);
return -1;
}
return tm;
}
int shw_pps_get_timing_mode(void) {
struct rts_pll_state state;
if ( rts_get_state(&state)==-1 ) {
return -1;
}
switch ( state.mode ) {
case RTS_MODE_GM_EXTERNAL :
return HAL_TIMING_MODE_GRAND_MASTER;
break;
case RTS_MODE_GM_FREERUNNING :
return RTS_MODE_GM_FREERUNNING;
break;
case RTS_MODE_BC :
return HAL_TIMING_MODE_BC;
break;
case RTS_MODE_DISABLED :
return HAL_TIMING_MODE_DISABLED;
default :
return -1;
}
}
int shw_pps_get_timing_mode_state(void) {
struct rts_pll_state state;
if ( rts_get_state(&state)==-1 ) {
return -1;
}
/* In the future, we should be able to provide also the state HAL_TIMING_MODE_TMDT_HOLDOVER */
return (state.flags & RTS_DMTD_LOCKED) ? HAL_TIMING_MODE_TMDT_LOCKED : HAL_TIMING_MODE_TMDT_UNLOCKED;
}
void shw_pps_gen_read_time(uint64_t * seconds, uint32_t * nanoseconds)
{
uint32_t ns_cnt;
......
......@@ -54,8 +54,8 @@ static struct hal_port_state *ports;
static int hal_port_fd;
/* RT subsystem PLL state, polled regularly via mini-ipc */
static struct rts_pll_state hal_port_rts_state;
static int hal_port_rts_state_valid = 0;
struct rts_pll_state hal_port_rts_state;
int hal_port_rts_state_valid = 0;
/* Polling timeouts (RT Subsystem & SFP detection) */
static timeout_t hal_port_tmo_rts, hal_port_tmo_sfp;
......@@ -336,15 +336,14 @@ int hal_port_pshifter_busy()
/* Updates the current value of the phase shift on a given
* port. Called by the main update function regularly. */
static void poll_rts_state(void)
int hal_port_poll_rts_state(void)
{
struct rts_pll_state *hs = &hal_port_rts_state;
if (libwr_tmo_expired(&hal_port_tmo_rts)) {
hal_port_rts_state_valid = rts_get_state(hs) < 0 ? 0 : 1;
if (!hal_port_rts_state_valid)
printf("rts_get_state failure, weird...\n");
}
hal_port_rts_state_valid = rts_get_state(hs) < 0 ? 0 : 1;
if (!hal_port_rts_state_valid)
printf("rts_get_state failure, weird...\n");
return hal_port_rts_state_valid;
}
static uint32_t pcs_readl(struct hal_port_state * p, int reg)
......@@ -374,8 +373,10 @@ static int hal_port_link_down(struct hal_port_state * p, int link_up)
if (p->locked) {
pr_info("Switching RTS to use local reference\n");
if (hal_get_timing_mode()
!= HAL_TIMING_MODE_GRAND_MASTER)
rts_set_mode(RTS_MODE_GM_FREERUNNING);
!= HAL_TIMING_MODE_GRAND_MASTER) {
shw_pps_set_timing_mode(HAL_TIMING_MODE_FREE_MASTER);
hal_update_timing_mode();
}
}
/* turn off synced LED */
......@@ -621,7 +622,6 @@ static void hal_port_remove_sfp(struct hal_port_state * p)
/* detects insertion/removal of SFP transceivers */
static void hal_port_poll_sfp(void)
{
if (libwr_tmo_expired(&hal_port_tmo_sfp)) {
uint32_t mask = shw_sfp_module_scan();
static int old_mask = 0;
......@@ -645,7 +645,6 @@ static void hal_port_poll_sfp(void)
}
}
old_mask = mask;
}
}
/* Executes the port FSM for all ports. Called regularly by the main loop. */
......@@ -654,11 +653,13 @@ void hal_port_update_all()
int i;
/* poll_rts_state does not write to shmem */
poll_rts_state();
if (libwr_tmo_expired(&hal_port_tmo_rts))
hal_port_poll_rts_state();
/* lock shmem */
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_BEGIN);
hal_port_poll_sfp();
if (libwr_tmo_expired(&hal_port_tmo_sfp))
hal_port_poll_sfp();
for (i = 0; i < HAL_MAX_PORTS; i++)
if (ports[i].in_use)
......@@ -713,25 +714,24 @@ int hal_port_start_lock(const char *port_name, int priority)
{
struct hal_port_state *p = hal_lookup_port(ports, hal_port_nports,
port_name);
int ret=-1;
if (!p)
return -1;
/* can't lock to a disconnected port */
if (p->state != HAL_PORT_STATE_UP)
return -1;
/* lock shmem */
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_BEGIN);
/* fixme: check the main FSM state before */
p->state = HAL_PORT_STATE_LOCKING;
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_END);
if (!p && p->state != HAL_PORT_STATE_UP )
return -1; /* can't lock to a disconnected port */
pr_info("Locking to port: %s\n", port_name);
rts_set_mode(RTS_MODE_BC);
hal_port_poll_rts_state(); // update rts state
if ( (hal_get_timing_mode()==HAL_TIMING_MODE_BC) &&
(ret=rts_lock_channel(p->hw_index, 0))>0 ) {
/* lock shmem */
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_BEGIN);
/* fixme: check the main FSM state before */
p->state = HAL_PORT_STATE_LOCKING;
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_END);
}
return ret;
return rts_lock_channel(p->hw_index, 0); /* 0 or -1 already */
}
/* Returns 1 if the port is locked */
......@@ -750,7 +750,8 @@ int hal_port_check_lock(const char *port_name)
if (hs->delock_count > 0)
return 0;
return (hs->current_ref == p->hw_index &&
return ( hs->mode==RTS_MODE_BC &&
hs->current_ref == p->hw_index &&
(hs->flags & RTS_DMTD_LOCKED) &&
(hs->flags & RTS_REF_LOCKED));
}
......@@ -765,12 +766,6 @@ int hal_port_reset(const char *port_name)
if (p->state != HAL_PORT_STATE_LINK_DOWN
&& p->state != HAL_PORT_STATE_DISABLED) {
if (p->locked) {
pr_info("Switching RTS to use local reference\n");
if (hal_get_timing_mode()
!= HAL_TIMING_MODE_GRAND_MASTER)
rts_set_mode(RTS_MODE_GM_FREERUNNING);
}
/* turn off synced LED */
set_led_synced(p->hw_index, 0);
......@@ -1052,3 +1047,5 @@ static int try_open_ppsi_shmem(void)
return 1;
}
......@@ -15,107 +15,44 @@
#include <rt_ipc.h>
#include <hal_exports.h>
static int timing_mode;
#define LOCK_TIMEOUT_EXT 60000
#define LOCK_TIMEOUT_INT 10000
extern struct rts_pll_state hal_port_rts_state;
extern int hal_port_rts_state_valid;
int hal_init_timing_mode(void)
{
static struct {
char *cfgname;
int modevalue;
} *m, modes[] = {
{"TIME_GM", HAL_TIMING_MODE_GRAND_MASTER},
{"TIME_FM", HAL_TIMING_MODE_FREE_MASTER},
{"TIME_BC", HAL_TIMING_MODE_BC},
{NULL, HAL_TIMING_MODE_BC /* default */},
};
if (rts_connect(NULL) < 0) {
pr_error(
"Failed to establish communication with the RT subsystem.\n");
return -1;
}
/* Read the mode from dot-config */
for (m = modes; m->cfgname; m++)
if (libwr_cfg_get(m->cfgname))
break;
timing_mode = m->modevalue;
if (!m->cfgname)
pr_error("%s: no config variable set, defaults used\n",
__func__);
return 0;
}
int hal_init_timing(char *filename)
{
timeout_t lock_tmo;
/* initialize the RT Subsys */
switch (timing_mode) {
case HAL_TIMING_MODE_GRAND_MASTER:
rts_set_mode(RTS_MODE_GM_EXTERNAL);
libwr_tmo_init(&lock_tmo, LOCK_TIMEOUT_EXT, 0);
break;
default: /* never hit, but having it here prevents a warning */
pr_error("%s: Unable to determine HAL mode! Use BC as"
" default\n", __func__);
case HAL_TIMING_MODE_FREE_MASTER:
case HAL_TIMING_MODE_BC:
rts_set_mode(RTS_MODE_GM_FREERUNNING);
libwr_tmo_init(&lock_tmo, LOCK_TIMEOUT_INT, 0);
break;
}
while (1) {
struct rts_pll_state pstate;
if (libwr_tmo_expired(&lock_tmo)) {
pr_error("Can't lock the PLL. "
"If running in the GrandMaster mode, "
"are you sure the 1-PPS and 10 MHz "
"reference clock signals are properly connected?,"
" retrying...\n");
if (timing_mode == HAL_TIMING_MODE_GRAND_MASTER) {
/*ups... something went wrong, try again */
rts_set_mode(RTS_MODE_GM_EXTERNAL);
libwr_tmo_init(&lock_tmo, LOCK_TIMEOUT_EXT, 0);
} else {
pr_error("Got timeout\n");
return -1;
}
}
if (rts_get_state(&pstate) < 0) {
/* Don't give up when rts_get_state fails, it may be
* due to race with ppsi at boot. No problems seen
* because of waiting here. */
pr_error("rts_get_state failed try again\n");
continue;
}
if (pstate.flags & RTS_DMTD_LOCKED) {
if (timing_mode == HAL_TIMING_MODE_GRAND_MASTER)
pr_info("GrandMaster locked to external "
"reference\n");
break;
}
usleep(100000);
}
/*
* We had "timing.use_nmea", but it was hardwired to /dev/ttyS2
* which is not wired out any more, so this is removed after v4.1
*/
return 0;
}
int hal_get_timing_mode()
int hal_get_timing_mode(void)
{
return timing_mode;
struct rts_pll_state *hs = &hal_port_rts_state;
if (hal_port_rts_state_valid)
switch (hs->mode) {
case RTS_MODE_GM_EXTERNAL:
return HAL_TIMING_MODE_GRAND_MASTER;
case RTS_MODE_GM_FREERUNNING:
return HAL_TIMING_MODE_FREE_MASTER;
case RTS_MODE_BC:
return HAL_TIMING_MODE_BC;
case RTS_MODE_DISABLED:
return HAL_TIMING_MODE_DISABLED;
}
return -1;
}
int hal_update_timing_mode(void) {
return hal_port_poll_rts_state();
}
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