diff --git a/userspace/wrsw_hal/driver_stuff.h b/userspace/wrsw_hal/driver_stuff.h index b1c1a4d173a61373935405a9357015e9233e9d9a..0715bf0d4b059089ad567a14b39ad6cef8eadd66 100644 --- a/userspace/wrsw_hal/driver_stuff.h +++ b/userspace/wrsw_hal/driver_stuff.h @@ -1,8 +1,10 @@ +#include <regs/lpdc_mdio_regs.h> #define PRIV_IOCGCALIBRATE (SIOCDEVPRIVATE + 1) #define PRIV_IOCGGETPHASE (SIOCDEVPRIVATE + 2) #define PRIV_IOCREADREG (SIOCDEVPRIVATE + 3) #define PRIV_IOCPHYREG (SIOCDEVPRIVATE + 4) +#define PRIV_IOCLPDCREG (SIOCDEVPRIVATE + 5) #define NIC_READ_PHY_CMD(addr) (((addr) & 0xff) << 16) #define NIC_RESULT_DATA(val) ((val) & 0xffff) @@ -10,32 +12,9 @@ | (1 << 31) \ | ((value) & 0xffff)) -/* - * MDIO registers used in Low Phase Drift Calibration - * See kernel/wbgen-regs/endpoint-mdio.h - */ - -// address of status and control registers -#define MDIO_LPC_STAT 18 -#define MDIO_LPC_CTRL 19 - -// flags for status and control registers -#define MDIO_LPC_STAT_RESET_TX_DONE (1 << 0) -#define MDIO_LPC_STAT_LINK_UP (1 << 1) -#define MDIO_LPC_STAT_LINK_ALIGNED (1 << 2) -#define MDIO_LPC_STAT_RESET_RX_DONE (1 << 3) - -#define MDIO_LPC_CTRL_RESET_TX (1 << 0) -#define MDIO_LPC_CTRL_TX_ENABLE (1 << 1) -#define MDIO_LPC_CTRL_RX_ENABLE (1 << 2) -#define MDIO_LPC_CTRL_RESET_RX (1 << 3) - -#define MDIO_LPC_CTRL_DMTD_SOURCE_TXOUTCLK (1 << 14) -#define MDIO_LPC_CTRL_DMTD_SOURCE_RXRECCLK (0 << 14) -#define MDIO_LPC_STAT_DBG_DATA (1 << 4) +#define LPDC_MDIO_CTRL_DMTD_SOURCE_TXOUTCLK (1 << LPDC_MDIO_CTRL_DMTD_CLK_SEL_SHIFT) +#define LPDC_MDIO_CTRL_DMTD_SOURCE_RXRECCLK (0 << LPDC_MDIO_CTRL_DMTD_CLK_SEL_SHIFT) -#define MDIO_LPC_CTRL_DBG_SHIFT_EN (1 << 8) -#define MDIO_LPC_CTRL_DBG_TRIG (1 << 10) /* * Address and mask to discover support for Low Phase Drift * Calibration, taken from endpoint-regs.h diff --git a/userspace/wrsw_hal/hal_port_fsm.c b/userspace/wrsw_hal/hal_port_fsm.c index 651592c5e825fe463e2ecf9f7b0608dd9268aa40..26c809d10bd198c416c88167d9bc61e1a7ab4615 100644 --- a/userspace/wrsw_hal/hal_port_fsm.c +++ b/userspace/wrsw_hal/hal_port_fsm.c @@ -158,9 +158,11 @@ static int port_fsm_state_disabled(fsm_t *fsm, int eventMsk, int isNewState) { // make sure the PHY calibration circuitry is put in a KNOWN state if( ps->lpdc.isSupported ) { - pcs_writel(ps, - MDIO_LPC_CTRL_RESET_RX | MDIO_LPC_CTRL_DMTD_SOURCE_RXRECCLK - | MDIO_LPC_CTRL_TX_ENABLE, MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_RX_SW_RESET + | LPDC_MDIO_CTRL_DMTD_SOURCE_RXRECCLK + | LPDC_MDIO_CTRL_TX_ENABLE, + LPDC_MDIO_CTRL); } // Disable tracker @@ -209,14 +211,16 @@ static int port_fsm_state_link_down(fsm_t *fsm, int eventMsk, int isNewState) { led_set_wrmode(ps->hw_index, SFP_LED_WRMODE_OFF); led_set_synched(ps->hw_index, 0); - pcs_writel(ps, MDIO_LPC_CTRL_RESET_RX | - MDIO_LPC_CTRL_TX_ENABLE | - MDIO_LPC_CTRL_DMTD_SOURCE_RXRECCLK, - MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_RX_SW_RESET + | LPDC_MDIO_CTRL_TX_ENABLE + | LPDC_MDIO_CTRL_DMTD_SOURCE_RXRECCLK, + LPDC_MDIO_CTRL); shw_udelay(1); - pcs_writel(ps, MDIO_LPC_CTRL_TX_ENABLE | - MDIO_LPC_CTRL_DMTD_SOURCE_RXRECCLK, - MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_TX_ENABLE + | LPDC_MDIO_CTRL_DMTD_SOURCE_RXRECCLK, + LPDC_MDIO_CTRL); } /* if final state reached for tx setup state machine then @@ -350,10 +354,10 @@ static int port_fsm_build_events(fsm_t *fsm) { if ( ps->lpdc.isSupported ) { uint32_t mioLpcStat; - if ( pcs_readl(ps, MDIO_LPC_STAT,&mioLpcStat) >= 0 ) { - if (mioLpcStat & MDIO_LPC_STAT_LINK_UP) + if (lpdc_readl(ps, LPDC_MDIO_STAT, &mioLpcStat) >= 0 ) { + if (mioLpcStat & LPDC_MDIO_STAT_LINK_UP) portEventMask |= HAL_PORT_EVENT_EARLY_LINK_UP; - if (mioLpcStat & MDIO_LPC_STAT_LINK_ALIGNED) + if (mioLpcStat & LPDC_MDIO_STAT_LINK_ALIGNED) portEventMask |= HAL_PORT_EVENT_RX_ALIGNED; } } diff --git a/userspace/wrsw_hal/hal_port_fsm_rx.c b/userspace/wrsw_hal/hal_port_fsm_rx.c index ddc2ab0ddcac19bbe85e38802d5215285e9e4088..4050be72b3aa6812b43ed4ff7c10cb9797850189 100644 --- a/userspace/wrsw_hal/hal_port_fsm_rx.c +++ b/userspace/wrsw_hal/hal_port_fsm_rx.c @@ -182,9 +182,10 @@ static int _hal_port_rx_setup_state_start(fsm_t *fsm, int eventMsk, int isNewSta return 0; } // LPDC support - pcs_writel(ps, MDIO_LPC_CTRL_TX_ENABLE | - MDIO_LPC_CTRL_DMTD_SOURCE_RXRECCLK, - MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_TX_ENABLE + | LPDC_MDIO_CTRL_DMTD_SOURCE_RXRECCLK, + LPDC_MDIO_CTRL); if (_isHalRxSetupEventEarlyLinkUp(eventMsk)) { halPortLpdcRx_t *rxSetup = ps->lpdc.rxSetup; @@ -220,14 +221,16 @@ static int _hal_port_rx_setup_state_reset_pcs(fsm_t *fsm, int eventMsk, int isNe if( _isHalRxSetupEventEarlyLinkUp(eventMsk)) { halPortLpdcRx_t *rxSetup=ps->lpdc.rxSetup; - pcs_writel(ps, MDIO_LPC_CTRL_RESET_RX | - MDIO_LPC_CTRL_TX_ENABLE | - MDIO_LPC_CTRL_DMTD_SOURCE_RXRECCLK, - MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_RX_SW_RESET + | LPDC_MDIO_CTRL_TX_ENABLE + | LPDC_MDIO_CTRL_DMTD_SOURCE_RXRECCLK, + LPDC_MDIO_CTRL); shw_udelay(1); - pcs_writel(ps, MDIO_LPC_CTRL_TX_ENABLE | - MDIO_LPC_CTRL_DMTD_SOURCE_RXRECCLK, - MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_TX_ENABLE + | LPDC_MDIO_CTRL_DMTD_SOURCE_RXRECCLK, + LPDC_MDIO_CTRL); rxSetup->attempts++; fsm_fire_state(fsm, HAL_PORT_RX_SETUP_STATE_WAIT_LOCK); @@ -290,10 +293,11 @@ static int _hal_port_rx_setup_state_validate(fsm_t *fsm, int eventMsk, int isNew int phase = _pll_state.channels[ps->hw_index].phase_loopback; halPortLpdcRx_t *rxSetup=ps->lpdc.rxSetup; - pcs_writel(ps, MDIO_LPC_CTRL_RX_ENABLE | - MDIO_LPC_CTRL_TX_ENABLE | - MDIO_LPC_CTRL_DMTD_SOURCE_RXRECCLK, - MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_RX_ENABLE + | LPDC_MDIO_CTRL_TX_ENABLE + | LPDC_MDIO_CTRL_DMTD_SOURCE_RXRECCLK, + LPDC_MDIO_CTRL); pcs_writel(ps, BMCR_ANENABLE | BMCR_ANRESTART, MII_BMCR); pr_info("wri%d: RX calibration complete at phase %d " @@ -322,8 +326,10 @@ static int _hal_port_rx_setup_state_restart(fsm_t *fsm, int eventMsk, int isNewS if ( isNewState ) { // This timer is used to leave enough time to the FSM in the other side to detect a link down libwr_tmo_restart(&ps->lpdc.rxSetup->restart_timeout); - pcs_writel(ps, MDIO_LPC_CTRL_TX_ENABLE | MDIO_LPC_CTRL_DMTD_SOURCE_TXOUTCLK, - MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_TX_ENABLE + | LPDC_MDIO_CTRL_DMTD_SOURCE_TXOUTCLK, + LPDC_MDIO_CTRL); } else { if( libwr_tmo_expired( &ps->lpdc.rxSetup->restart_timeout ) ) { fsm_fire_state(fsm, HAL_PORT_RX_SETUP_STATE_INIT); @@ -397,10 +403,10 @@ static int port_rx_setup_fsm_build_events (fsm_t *fsm) { if ( ps->lpdc.isSupported ) { uint32_t mioLpcStat; - if ( pcs_readl(ps, MDIO_LPC_STAT,&mioLpcStat) >= 0 ) { - if (mioLpcStat & MDIO_LPC_STAT_LINK_UP) + if (lpdc_readl(ps, LPDC_MDIO_STAT,&mioLpcStat) >= 0 ) { + if (mioLpcStat & LPDC_MDIO_STAT_LINK_UP) portEventMask |= HAL_PORT_RX_SETUP_EVENT_EARLY_LINK_UP; - if (mioLpcStat & MDIO_LPC_STAT_LINK_ALIGNED) + if (mioLpcStat & LPDC_MDIO_STAT_LINK_ALIGNED) portEventMask |= HAL_PORT_RX_SETUP_EVENT_RX_ALIGNED; } } diff --git a/userspace/wrsw_hal/hal_port_fsm_tx.c b/userspace/wrsw_hal/hal_port_fsm_tx.c index bb766291ec8850b5f91929ee92340b580cdf353d..5bc5163030f3aecee9ddcbd2ac32cac814c45402 100644 --- a/userspace/wrsw_hal/hal_port_fsm_tx.c +++ b/userspace/wrsw_hal/hal_port_fsm_tx.c @@ -162,9 +162,10 @@ static int port_tx_setup_fsm_state_start(fsm_t *fsm, int eventMsk, int isNewStat rts_enable_ptracker(ps->hw_index, 0); rts_ptracker_set_average_samples(ps->hw_index, HAL_CAL_DMTD_SAMPLES); - pcs_writel(ps, MDIO_LPC_CTRL_RESET_RX | - MDIO_LPC_CTRL_DMTD_SOURCE_TXOUTCLK, - MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_RX_SW_RESET + | LPDC_MDIO_CTRL_DMTD_SOURCE_TXOUTCLK, + LPDC_MDIO_CTRL); /* start indicating LPDC rx calibration. */ led_set_wrmode(ps->hw_index,SFP_LED_WRMODE_CALIB); @@ -180,16 +181,18 @@ static int port_tx_setup_fsm_state_start(fsm_t *fsm, int eventMsk, int isNewStat */ static int port_tx_setup_fsm_state_reset_pcs(fsm_t *fsm, int eventMsk, int isNewState) { struct hal_port_state * ps = (struct hal_port_state*) fsm->priv; - + rts_enable_ptracker(ps->hw_index, 0); - pcs_writel(ps, MDIO_LPC_CTRL_RESET_TX | - MDIO_LPC_CTRL_RESET_RX | - MDIO_LPC_CTRL_DMTD_SOURCE_TXOUTCLK, - MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_TX_SW_RESET + | LPDC_MDIO_CTRL_RX_SW_RESET + | LPDC_MDIO_CTRL_DMTD_SOURCE_TXOUTCLK, + LPDC_MDIO_CTRL); shw_udelay(1); - pcs_writel(ps, MDIO_LPC_CTRL_RESET_RX | - MDIO_LPC_CTRL_DMTD_SOURCE_TXOUTCLK, - MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_RX_SW_RESET + | LPDC_MDIO_CTRL_DMTD_SOURCE_TXOUTCLK, + LPDC_MDIO_CTRL); fsm_fire_state(fsm,HAL_PORT_TX_SETUP_STATE_WAIT_LOCK); return 0; @@ -203,9 +206,8 @@ static int port_tx_setup_fsm_state_reset_pcs(fsm_t *fsm, int eventMsk, int isNew static int port_tx_setup_fsm_state_wait_lock(fsm_t *fsm, int eventMsk, int isNewState) { struct hal_port_state * ps = (struct hal_port_state*) fsm->priv; uint32_t value; - - if ( pcs_readl(ps, MDIO_LPC_STAT,&value)>=0 ) { - if ( (value & MDIO_LPC_STAT_RESET_TX_DONE)!=0 ) { + if (lpdc_readl(ps, LPDC_MDIO_STAT,&value) >= 0 ) { + if ( (value & LPDC_MDIO_STAT_TX_RST_DONE)!=0 ) { ps->lpdc.txSetup->attempts++; rts_enable_ptracker(ps->hw_index, 1); @@ -307,10 +309,11 @@ static int port_tx_setup_fsm_state_validate(fsm_t *fsm, int eventMsk, int isNewS rts_enable_ptracker(ps->hw_index, 0); // enable the PCS on the port - pcs_writel(ps, MDIO_LPC_CTRL_RESET_RX | - MDIO_LPC_CTRL_TX_ENABLE | - MDIO_LPC_CTRL_DMTD_SOURCE_RXRECCLK, - MDIO_LPC_CTRL); + lpdc_writel(ps, + LPDC_MDIO_CTRL_RX_SW_RESET + | LPDC_MDIO_CTRL_TX_ENABLE + | LPDC_MDIO_CTRL_DMTD_SOURCE_RXRECCLK, + LPDC_MDIO_CTRL); led_set_wrmode(ps->hw_index,SFP_LED_WRMODE_OFF); diff --git a/userspace/wrsw_hal/hal_ports.c b/userspace/wrsw_hal/hal_ports.c index 166a4f7b57441a1bfa05fbc78db8961659a26207..f7ea3a92fb40fdb1db9e1f733fa62b782fa74dff 100644 --- a/userspace/wrsw_hal/hal_ports.c +++ b/userspace/wrsw_hal/hal_ports.c @@ -295,6 +295,43 @@ int hal_port_shmem_init(char *logfilename) return 0; } +int lpdc_writel(struct hal_port_state *ps, uint16_t value, int reg) +{ + struct ifreq ifr; + uint32_t rv; + + strncpy(ifr.ifr_name, ps->name, sizeof(ifr.ifr_name)); + + rv = NIC_WRITE_PHY_CMD(reg, value); + ifr.ifr_data = (void *)&rv; + if (ioctl(halPorts.hal_port_fd, PRIV_IOCLPDCREG, &ifr) < 0) { + pr_error("%s: ioctl failed writing at register adress %d\n", + __func__,reg); + return -1; + }; + + return 0; +} + +int lpdc_readl(struct hal_port_state * p, int reg, uint32_t *value) +{ + struct ifreq ifr; + + strncpy(ifr.ifr_name, p->name, sizeof(ifr.ifr_name)); + + *value = NIC_READ_PHY_CMD(reg); + ifr.ifr_data = (void *)value; + if (ioctl(halPorts.hal_port_fd, PRIV_IOCLPDCREG, &ifr) < 0) { + pr_error("%s: ioctl failed reading register at address %d\n", + __func__, reg); + return -1; + } + + *value = NIC_RESULT_DATA(*value); + return 0; +} + + int pcs_writel(struct hal_port_state *ps, uint16_t value, int reg) { struct ifreq ifr; diff --git a/userspace/wrsw_hal/hal_ports.h b/userspace/wrsw_hal/hal_ports.h index e188f64245628c0d6c42364e3694560ac0e3796e..d964452de28b814e549948b8a2784ad7744a9736 100644 --- a/userspace/wrsw_hal/hal_ports.h +++ b/userspace/wrsw_hal/hal_ports.h @@ -68,6 +68,8 @@ extern int hal_check_running(void); extern int hal_add_cleanup_callback(hal_cleanup_callback_t cb); extern int pcs_writel(struct hal_port_state *p, uint16_t value, int reg); extern int pcs_readl(struct hal_port_state * p, int reg, uint32_t *value); +extern int lpdc_writel(struct hal_port_state *p, uint16_t value, int reg); +extern int lpdc_readl(struct hal_port_state * p, int reg, uint32_t *value); #endif