Commit c41e1cd5 authored by Jean-Claude BAU's avatar Jean-Claude BAU

Initialization corrections and HAL share memory changes

- HAL shared memory modified to hide and remove some dependencies not
needed by PPSi
- LPDC structures are now stored in HAL shared memory. They are then
accessible by the share memory dump tool
- Improve the initialization procedure
parent c0be77c7
......@@ -76,7 +76,7 @@ typedef struct {
int cal_saved_phase_valid;
int measured_phase;
int expected_phase;
int tollerance;
int tolerance;
int update_cnt;
int expected_phase_valid;
timeout_t calib_timeout;
......@@ -86,17 +86,17 @@ typedef struct {
typedef struct {
timeout_t link_timeout;
timeout_t align_timeout;
timeout_t earlyup_timeout;
timeout_t earlyup_timeout;
int attempts;
}halPortLpdcRx_t;
struct halGlobalLPDC {
typedef struct {
int numberOfLpdcPorts;
int numberOfTxSetupDonePorts;
int firstLpdcPort;
int lastLpdcPort;
int calFileSynced;
}; /* Global data for Low phase drift calibration */
}halGlobalLPDC_t; /* Global data for Low phase drift calibration */
typedef struct {
int isSupported; /* Set if Low Phase Drift Calibration is supported */
......@@ -104,7 +104,7 @@ typedef struct {
halPortFsmState_t rxSetupStates;
halPortLpdcTx_t *txSetup;
halPortLpdcRx_t *rxSetup;
struct halGlobalLPDC *globalLpdc;
halGlobalLPDC_t *globalLpdc;
}halPortLPDC_t; /* per-port data for Low phase drift calibration */
/* Internal port state structure */
......@@ -161,10 +161,10 @@ struct hal_port_state {
/* Events to process */
int evt_reset; /* Set if a reset is requested */
int evt_lock; /* Set if the ptracker must be activated*/
int evt_linkUp; /* Set if link is up ( driver call */
int evt_linkUp; /* Set if link is up ( driver call )*/
/* Low phase drift calibration data */
halPortLPDC_t lpdc;
halPortLPDC_t *lpdc; /* Use a pointer to avoid to export this structure to PPSi */
/* Pll FSM */
halPortFsmState_t pllStates;
......
......@@ -309,20 +309,21 @@ static int _builPortEvents(void * vpfg) {
/* Init the FSM on all ports. Called one time at startup */
void hal_port_state_fsm_init( struct hal_port_state * ps ) {
void hal_port_state_fsm_init( struct hal_port_state * ps, halGlobalLPDC_t *globalLpdc) {
int portIndex;
struct hal_port_state * _ps=ps;
for (portIndex = 0; portIndex < HAL_MAX_PORTS; portIndex++) {
if ( ps->in_use)
if ( _ps->in_use)
{
_portFsm.ps=ps;
_portFsm.st=&ps->portStates;
ps->portStates.state=-1;
_portFsm.ps=_ps;
_portFsm.st=&_ps->portStates;
_ps->portStates.state=-1;
_fireState(&_portFsm,HAL_PORT_STATE_INIT);
}
ps++; /* Next port */
_ps++; /* Next port */
}
hal_port_tx_setup_init(ps, globalLpdc); // Global init for tx_setup
}
/* Call FSM for on all ports */
......
......@@ -16,6 +16,6 @@
/* Prototypes */
void fsm_state_machine( struct hal_port_state * ps );
void hal_port_state_fsm( struct hal_port_state * ps );
void hal_port_state_fsm_init( struct hal_port_state * ps );
void hal_port_state_fsm_init( struct hal_port_state * ps,halGlobalLPDC_t *globalLpdc);
#endif
......@@ -125,19 +125,19 @@ static __inline__ void updatePllState(struct hal_port_state * ps) {
*/
static int _hal_port_rx_setup_state_start(void *vpfg, int eventMsk, int isNewState) {
struct hal_port_state * ps=((halPortFsmGen_t *)vpfg)->ps;
halPortLpdcRx_t *rxSetup=ps->lpdc.rxSetup;
halPortLpdcRx_t *rxSetup=ps->lpdc->rxSetup;
// prevent RX FSM from starting up when the TX path calibration of the port is
// not completed.
if( ps->lpdc.txSetupStates.state != HAL_PORT_TX_SETUP_STATE_DONE) {
if( ps->lpdc->txSetupStates.state != HAL_PORT_TX_SETUP_STATE_DONE) {
pr_warning("rx_setup FSM is attempted to be started before the"
"tx_setup FSM has finished (in state %d) - this should"
"never happen, in theory.\n",
ps->lpdc.txSetupStates.state);
ps->lpdc->txSetupStates.state);
return 0;
}
if ( ps->lpdc.isSupported ) {
if ( ps->lpdc->isSupported ) {
/* Wait a bit to make sure early_link_up is resetted. This
timeout is initialized in hal_port_rx_setup_init_fsm(),
see detailed description there. */
......@@ -169,7 +169,7 @@ static int _hal_port_rx_setup_state_reset_pcs(void *vpfg, int eventMsk, int isNe
struct hal_port_state * ps=((halPortFsmGen_t *)vpfg)->ps;
if( _isHalRxSetupEventEarlyLinkUp(eventMsk)) {
halPortLpdcRx_t *rxSetup=ps->lpdc.rxSetup;
halPortLpdcRx_t *rxSetup=ps->lpdc->rxSetup;
libwr_tmo_init(&rxSetup->link_timeout, 100, 1);
// establish a 1ms wait for the LINK_ALIGNED flag -
......@@ -199,7 +199,7 @@ static int _hal_port_rx_setup_state_reset_pcs(void *vpfg, int eventMsk, int isNe
*/
static int _hal_port_rx_setup_state_wait_lock(void *vpfg, int eventMsk, int isNewState) {
struct hal_port_state * ps=((halPortFsmGen_t *)vpfg)->ps;
halPortLpdcRx_t *rxSetup=ps->lpdc.rxSetup;
halPortLpdcRx_t *rxSetup=ps->lpdc->rxSetup;
if ( _isHalRxSetupEventEarlyLinkUp(eventMsk)) {
// 1ms rx align detection window, described in previous state.
......@@ -234,8 +234,7 @@ static int _hal_port_rx_setup_state_validate(void *vpfg, int eventMsk, int isNew
if (_pll_state.channels[ps->hw_index].flags & CHAN_PMEAS_READY) {
int phase = _pll_state.channels[ps->hw_index].phase_loopback;
halPortLpdcRx_t *rxSetup=ps->lpdc.rxSetup;
uint32_t value;
halPortLpdcRx_t *rxSetup=ps->lpdc->rxSetup;
pcs_writel(ps, MDIO_LPC_CTRL_RX_ENABLE |
MDIO_LPC_CTRL_TX_ENABLE |
......@@ -266,7 +265,7 @@ static int _hal_port_rx_setup_state_done(void *vpfg, int eventMsk, int isNewStat
struct hal_port_state * ps=((halPortFsmGen_t *)vpfg)->ps;
/* earlyLinkUp detection only if LPDC support */
if ( ps->lpdc.isSupported ) {
if ( ps->lpdc->isSupported ) {
if ( !_isHalRxSetupEventEarlyLinkUp(eventMsk)) {
// Port went done
pr_info("rxcal: early link flag lost on port wri%d\n",
......@@ -292,7 +291,7 @@ static int _buildEvents(void *vpfg) {
HAL_PORT_RX_SETUP_EVENT_LINK_UP : HAL_PORT_RX_SETUP_EVENT_LINK_DOWN;
}
if ( ps->lpdc.isSupported ) {
if ( ps->lpdc->isSupported ) {
uint32_t mioLpcStat;
if ( pcs_readl(ps, MDIO_LPC_STAT,&mioLpcStat) >= 0 ) {
......@@ -311,9 +310,9 @@ static int _buildEvents(void *vpfg) {
*/
void hal_port_rx_setup_init_fsm(struct hal_port_state * ps ) {
_portFsm.ps=ps;
_portFsm.st=&ps->lpdc.rxSetupStates;
ps->lpdc.rxSetupStates.state=-1;
if ( ps->lpdc.isSupported ) {
_portFsm.st=&ps->lpdc->rxSetupStates;
ps->lpdc->rxSetupStates.state=-1;
if ( ps->lpdc->isSupported ) {
/* This timeout is needed when link goes down. In such case
the link_down flag is set earlier than the early_link_up
flag is reseted. So, after the link goes down, we need to
......@@ -326,7 +325,7 @@ void hal_port_rx_setup_init_fsm(struct hal_port_state * ps ) {
a reason. If it was done in _hal_port_rx_setup_state_start(),
the timeout would also kick in when the START state is
entered from WAIT_LOCK*/
halPortLpdcRx_t *rxSetup=ps->lpdc.rxSetup;
halPortLpdcRx_t *rxSetup=ps->lpdc->rxSetup;
libwr_tmo_init(&rxSetup->earlyup_timeout, 10, 1);
}
_fireState(&_portFsm,HAL_PORT_RX_SETUP_STATE_START);
......@@ -341,7 +340,7 @@ void hal_port_rx_setup_init_fsm(struct hal_port_state * ps ) {
int hal_port_rx_setup_state_fsm( struct hal_port_state * ps ) {
_portFsm.ps=ps;
_portFsm.st=&ps->lpdc.rxSetupStates;
_portFsm.st=&ps->lpdc->rxSetupStates;
return hal_port_generic_fsm(&_portFsm);
}
......@@ -103,12 +103,12 @@ static __inline__ void updatePllState(struct hal_port_state * ps) {
}
static __inline__ void txSetupDone(struct hal_port_state * ps) {
struct halGlobalLPDC * gl = ps->lpdc.globalLpdc;
halGlobalLPDC_t * gl = ps->lpdc->globalLpdc;
gl->numberOfTxSetupDonePorts++;
}
int txSetupDoneOnAllPorts(struct hal_port_state * ps) {
struct halGlobalLPDC * gl = ps->lpdc.globalLpdc;
halGlobalLPDC_t * gl = ps->lpdc->globalLpdc;
return gl->numberOfTxSetupDonePorts == gl->numberOfLpdcPorts;
}
......@@ -128,18 +128,18 @@ static int _within_range(int x, int minval, int maxval, int wrap);
static int _hal_port_tx_setup_state_start(void *vpfg, int eventMsk, int isNewState) {
struct hal_port_state * ps=((halPortFsmGen_t *)vpfg)->ps;
if ( !ps->lpdc.isSupported ) {
if ( !ps->lpdc->isSupported ) {
// NO LPDC support
_fireState(vpfg,HAL_PORT_TX_SETUP_STATE_WAIT_OTHER_PORTS);
return 0;
} else {
// LPDC support
halPortLpdcTx_t *txSetup=ps->lpdc.txSetup;
halPortLpdcTx_t *txSetup=ps->lpdc->txSetup;
txSetup->attempts=0;
txSetup->expected_phase = 0;
txSetup->expected_phase_valid = 0;
txSetup->tollerance = TX_CAL_TOLLERANCE;
txSetup->tolerance = TX_CAL_TOLLERANCE;
txSetup->update_cnt = 0;
_pll_state.channels[ps->hw_index].flags = 0;
......@@ -186,12 +186,12 @@ static int _hal_port_tx_setup_state_reset_pcs(void *vpfg, int eventMsk, int isNe
*/
static int _hal_port_tx_setup_state_wait_lock(void *vpfg, int eventMsk, int isNewState) {
struct hal_port_state * ps=((halPortFsmGen_t *)vpfg)->ps;
halPortLpdcTx_t *txSetup=ps->lpdc.txSetup;
halPortLpdcTx_t *txSetup=ps->lpdc->txSetup;
uint32_t value;
if ( pcs_readl(ps, MDIO_LPC_STAT,&value)>=0 ) {
if ( (value & MDIO_LPC_STAT_RESET_TX_DONE)!=0 ) {
ps->lpdc.txSetup->attempts++;
ps->lpdc->txSetup->attempts++;
rts_enable_ptracker(ps->hw_index, 1);
_pll_state.channels[ps->hw_index].flags = 0;
libwr_tmo_init(&txSetup->calib_timeout,
......@@ -210,7 +210,7 @@ static int _hal_port_tx_setup_state_wait_lock(void *vpfg, int eventMsk, int isNe
*/
static int _hal_port_tx_setup_state_measure_phase(void *vpfg, int eventMsk, int isNewState) {
struct hal_port_state * ps = ((halPortFsmGen_t *) vpfg)->ps;
halPortLpdcTx_t *txSetup=ps->lpdc.txSetup;
halPortLpdcTx_t *txSetup=ps->lpdc->txSetup;
updatePllState(ps);
if (!(_pll_state.channels[ps->hw_index].flags & CHAN_PMEAS_READY)) {
......@@ -224,7 +224,7 @@ static int _hal_port_tx_setup_state_measure_phase(void *vpfg, int eventMsk, int
return 0; // keep waiting
}
txSetup = ps->lpdc.txSetup;
txSetup = ps->lpdc->txSetup;
int phase = _pll_state.channels[ps->hw_index].phase_loopback;
txSetup->measured_phase = phase;
......@@ -239,19 +239,19 @@ static int _hal_port_tx_setup_state_measure_phase(void *vpfg, int eventMsk, int
// let's say the first 1.5 ns of the 16 ns ref clock
// cycle, so that we have enough setup time
txSetup->tollerance = TX_CAL_FIRST_CAL_TOLLERANCE;
txSetup->tolerance = TX_CAL_FIRST_CAL_TOLLERANCE;
txSetup->expected_phase = TX_CAL_FIRST_CAL_EXPECTED_PHASE;
}
txSetup->expected_phase_valid = 1;
}
int phase_min = txSetup->expected_phase - txSetup->tollerance;
int phase_max = txSetup->expected_phase + txSetup->tollerance;
int phase_min = txSetup->expected_phase - txSetup->tolerance;
int phase_max = txSetup->expected_phase + txSetup->tolerance;
pr_info("TX Calibration: upd wri%d phase %d after %d "
"attempts target %d tollerance %d\n",
"attempts target %d tolerance %d\n",
ps->hw_index+1, txSetup->measured_phase,
txSetup->attempts, txSetup->expected_phase, txSetup->tollerance);
txSetup->attempts, txSetup->expected_phase, txSetup->tolerance);
if(_within_range(phase, phase_min, phase_max, 16000)) {
pr_info("FIX port %d phase %d after %d attempts "
......@@ -282,7 +282,7 @@ static int _hal_port_tx_setup_state_validate(void *vpfg, int eventMsk, int isNew
if (!(_pll_state.channels[ps->hw_index].flags & CHAN_PMEAS_READY))
return 0; // keep waiting
txSetup = ps->lpdc.txSetup;
txSetup = ps->lpdc->txSetup;
txSetup->measured_phase = _pll_state.channels[ps->hw_index].phase_loopback;
pr_info("Port %d: TX calibration complete\n", ps->hw_index + 1);
rts_enable_ptracker(ps->hw_index, 0);
......@@ -335,38 +335,37 @@ static int _buildEvents(void *vpfg) {
- initializing a global structure and filling it in - this structure is
needed by tx calibration only (so far)
*/
void hal_port_tx_setup_init(struct hal_port_state * ps, struct halGlobalLPDC *globalLpdc) {
void hal_port_tx_setup_init(struct hal_port_state * ps, halGlobalLPDC_t *globalLpdc) {
int index;
struct hal_port_state * _ps = ps;
int numberOfLpdcPorts = 0;
int firstLpdcPort = -1;
int lastLpdcPort = -1;
/* Allocate memory for the global struct */
globalLpdc = malloc(sizeof(struct halGlobalLPDC));
/* Initialize pointer to the global structure for each port.
Check whether there is any port that supports LPDC,
if there is/are such port(s), remember index of the first/last and
their number. We need this info in operation.*/
for (index = 0; index < HAL_MAX_PORTS; index++){
/* Link the global structure from each port.
NOTE: Even ports that do not support LPDC require access to
this global structre as they need to know whether all
the LPDC-supporting ports have been calibrated */
_ps->lpdc.globalLpdc = globalLpdc;
/* Fill in global info needed for operation */
if(_ps->in_use && _ps->lpdc.isSupported){
/* if this ist he first supporetd port, save its index*/
if (firstLpdcPort < 0)
firstLpdcPort = index;
/*remember the index, just in case it is the last LPDC port*/
lastLpdcPort = index;
/* count number of supported ports*/
numberOfLpdcPorts++;
if (_ps->in_use ) {
/* Link the global structure from each port.
NOTE: Even ports that do not support LPDC require access to
this global structure as they need to know whether all
the LPDC-supporting ports have been calibrated */
_ps->lpdc->globalLpdc = globalLpdc;
/* Fill in global info needed for operation */
if (_ps->lpdc->isSupported) {
/* if this ist he first supporetd port, save its index*/
if (firstLpdcPort < 0)
firstLpdcPort = index;
/*remember the index, just in case it is the last LPDC port*/
lastLpdcPort = index;
/* count number of supported ports*/
numberOfLpdcPorts++;
}
}
_ps++;
}
......@@ -394,8 +393,8 @@ void hal_port_tx_setup_init(struct hal_port_state * ps, struct halGlobalLPDC *g
/* Init the TX SETUP FSM on a given port */
void hal_port_tx_setup_init_fsm(struct hal_port_state * ps ) {
_portFsm.ps=ps;
_portFsm.st=&ps->lpdc.txSetupStates;
ps->lpdc.txSetupStates.state=-1;
_portFsm.st=&ps->lpdc->txSetupStates;
ps->lpdc->txSetupStates.state=-1;
_fireState(&_portFsm,HAL_PORT_TX_SETUP_STATE_START);
}
......@@ -408,14 +407,14 @@ void hal_port_tx_setup_init_fsm(struct hal_port_state * ps ) {
int hal_port_tx_setup_state_fsm( struct hal_port_state * ps ) {
_portFsm.ps=ps;
_portFsm.st=&ps->lpdc.txSetupStates;
_portFsm.st=&ps->lpdc->txSetupStates;
return hal_port_generic_fsm(&_portFsm);
}
/* if config is present then update the calibration data */
static void _load_tx_calibration_file(struct hal_port_state * ps) {
int i = 0;
struct halGlobalLPDC * gl = ps->lpdc.globalLpdc;
halGlobalLPDC_t * gl = ps->lpdc->globalLpdc;
// Read calibration file, if it exists
_calibrationConfig = cfg_load(_calibrationFileName, 0);
......@@ -431,7 +430,7 @@ static void _load_tx_calibration_file(struct hal_port_state * ps) {
pr_info("Loading LPCD config data from %s\n", _calibrationFileName);
for (i = 0; i < HAL_MAX_PORTS; i++){
if (ps->in_use && ps->lpdc.isSupported)
if (ps->in_use && ps->lpdc->isSupported)
{
char key_name[80];
int value;
......@@ -441,8 +440,8 @@ static void _load_tx_calibration_file(struct hal_port_state * ps) {
if(cfg_get_int( _calibrationConfig, key_name, &value) )
{
pr_info("cal: wri%d %d\n", ps->hw_index+1, value);
ps->lpdc.txSetup->cal_saved_phase = value;
ps->lpdc.txSetup->cal_saved_phase_valid = 1;
ps->lpdc->txSetup->cal_saved_phase = value;
ps->lpdc->txSetup->cal_saved_phase_valid = 1;
}
}
ps++;
......@@ -468,7 +467,7 @@ static void _write_tx_calibration_file(struct hal_port_state * _ps)
{
int i;
struct hal_port_state * ps=_ps;
struct halGlobalLPDC * gl = ps->lpdc.globalLpdc;
halGlobalLPDC_t * gl = ps->lpdc->globalLpdc;
/* Only the first LPDC-supporting port writes the file. Otherwise,
there is problem with pointers when looping through port structures
......@@ -490,11 +489,11 @@ static void _write_tx_calibration_file(struct hal_port_state * _ps)
ps=_ps;
for (i = gl->firstLpdcPort; i <= gl->lastLpdcPort; i++) {
if (ps->in_use && ps->lpdc.isSupported)
if (ps->in_use && ps->lpdc->isSupported)
{
char key_name[80];
snprintf(key_name, sizeof(key_name), "TX_PHASE_PORT%d", ps->hw_index);
cfg_set_int(cfg, key_name, ps->lpdc.txSetup->measured_phase);
cfg_set_int(cfg, key_name, ps->lpdc->txSetup->measured_phase);
}
ps++;
}
......
......@@ -12,7 +12,7 @@
/* prototypes */
void hal_port_tx_setup_init_fsm(struct hal_port_state * ps );
void hal_port_tx_setup_init(struct hal_port_state * ps, struct halGlobalLPDC *globalLpdc );
void hal_port_tx_setup_init(struct hal_port_state * ps, halGlobalLPDC_t *globalLpdc );
int hal_port_tx_setup_state_fsm( struct hal_port_state * ps);
#endif
......@@ -134,13 +134,23 @@ static int hal_port_init(struct hal_port_state *ps, int index)
if (!hal_port_check_presence(ps->name, ps->hw_addr))
return -1;
/* Allocate LPDC structure */
if ( (ps->lpdc = wrs_shm_alloc(hal_shmem_hdr, sizeof(halPortLPDC_t)))==NULL ) {
pr_error("Can't allocate LPDC structure in shmem\n");
return -1;
}
ps->in_use = 1;
ps->lpdc.isSupported = hal_port_check_lpdc_support(ps);
ps->lpdc->isSupported = hal_port_check_lpdc_support(ps);
if ( ps->lpdc.isSupported ) {
if ( ps->lpdc->isSupported ) {
// Allocate memory for tx/rx setup
ps->lpdc.txSetup = malloc(sizeof(halPortLpdcTx_t));
ps->lpdc.rxSetup = malloc(sizeof(halPortLpdcRx_t));
ps->lpdc->txSetup = wrs_shm_alloc(hal_shmem_hdr,sizeof(halPortLpdcTx_t));
ps->lpdc->rxSetup = wrs_shm_alloc(hal_shmem_hdr,sizeof(halPortLpdcRx_t));
if ( ps->lpdc->rxSetup==NULL || ps->lpdc->txSetup==NULL) {
pr_error("Can't allocate LPDC (rx/tx) structures in shmem\n");
return -1;
}
}
/* get the number of a port from notation wriX */
sscanf(ps->name + 3, "%d", &ps->hw_index);
......@@ -247,8 +257,8 @@ int hal_port_shmem_init(char *logfilename)
for (index = 0; index < HAL_MAX_PORTS; index++)
if (hal_port_init(&halPorts.ports[index],index) < 0)
break;
hal_port_state_fsm_init(halPorts.ports); // Init fsm
hal_port_tx_setup_init(halPorts.ports, halPorts.globalLpdc); // Global init for tx_setup
hal_port_state_fsm_init(halPorts.ports,&halPorts.globalLpdc); // Init fsm
led_init_all_ports(halPorts.ports); // Reset all leds
halPorts.numberOfPorts = index;
......@@ -342,11 +352,11 @@ static int hal_port_check_lpdc_support(struct hal_port_state * ps)
return 0;
} else {
if (rv & EP_ECR_FEAT_LPC) {
pr_info("Supports for Low Phase Drift Calibration detected"
pr_info("Supports for Low Phase Drift Calibration detected "
"at port %s\n", ps->name);
return 1;
} else {
pr_info("NO supports for Low Phase Drift Calibration detected"
pr_info("NO supports for Low Phase Drift Calibration detected "
"at port %s\n", ps->name);
return 0;
}
......
......@@ -11,6 +11,7 @@
#define HAL_PORTS_H
#include <rt_ipc.h>
#include <libwr/hal_shmem.h>
typedef struct {
struct hal_port_state *ports;
......@@ -22,7 +23,7 @@ typedef struct {
int rts_state_valid;
/* Global information needed by LPDC (tx setup) */
struct halGlobalLPDC *globalLpdc;
halGlobalLPDC_t globalLpdc;
}hal_ports_t;
......
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