diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_ptp_hw.c')
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 438 |
1 files changed, 232 insertions, 206 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c index a38614d21ea8..f818dd215c05 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c @@ -131,6 +131,8 @@ static void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) case READ_TIME: cmd_val |= GLTSYN_CMD_READ_TIME; break; + case ICE_PTP_NOP: + break; } wr32(hw, GLTSYN_CMD, cmd_val); @@ -293,7 +295,7 @@ static bool ice_is_40b_phy_reg_e822(u16 low_addr, u16 *high_addr) * * Read a PHY register for the given port over the device sideband queue. */ -int +static int ice_read_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 *val) { struct ice_sbq_msg_input msg = {0}; @@ -370,7 +372,7 @@ ice_read_64b_phy_reg_e822(struct ice_hw *hw, u8 port, u16 low_addr, u64 *val) * * Write a PHY register for the given port over the device sideband queue. */ -int +static int ice_write_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 val) { struct ice_sbq_msg_input msg = {0}; @@ -1079,7 +1081,7 @@ exit_err: * * Negative adjustments are supported using 2s complement arithmetic. */ -int +static int ice_ptp_prep_port_adj_e822(struct ice_hw *hw, u8 port, s64 time) { u32 l_time, u_time; @@ -1226,18 +1228,18 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts) } /** - * ice_ptp_one_port_cmd - Prepare a single PHY port for a timer command + * ice_ptp_write_port_cmd_e822 - Prepare a single PHY port for a timer command * @hw: pointer to HW struct * @port: Port to which cmd has to be sent * @cmd: Command to be sent to the port * * Prepare the requested port for an upcoming timer sync command. * - * Note there is no equivalent of this operation on E810, as that device - * always handles all external PHYs internally. + * Do not use this function directly. If you want to configure exactly one + * port, use ice_ptp_one_port_cmd() instead. */ static int -ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) +ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) { u32 cmd_val, val; u8 tmr_idx; @@ -1261,6 +1263,8 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) case ADJ_TIME_AT_TIME: cmd_val |= PHY_CMD_ADJ_TIME_AT_TIME; break; + case ICE_PTP_NOP: + break; } /* Tx case */ @@ -1307,6 +1311,39 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) } /** + * ice_ptp_one_port_cmd - Prepare one port for a timer command + * @hw: pointer to the HW struct + * @configured_port: the port to configure with configured_cmd + * @configured_cmd: timer command to prepare on the configured_port + * + * Prepare the configured_port for the configured_cmd, and prepare all other + * ports for ICE_PTP_NOP. This causes the configured_port to execute the + * desired command while all other ports perform no operation. + */ +static int +ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port, + enum ice_ptp_tmr_cmd configured_cmd) +{ + u8 port; + + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { + enum ice_ptp_tmr_cmd cmd; + int err; + + if (port == configured_port) + cmd = configured_cmd; + else + cmd = ICE_PTP_NOP; + + err = ice_ptp_write_port_cmd_e822(hw, port, cmd); + if (err) + return err; + } + + return 0; +} + +/** * ice_ptp_port_cmd_e822 - Prepare all ports for a timer command * @hw: pointer to the HW struct * @cmd: timer command to prepare @@ -1322,7 +1359,7 @@ ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { int err; - err = ice_ptp_one_port_cmd(hw, port, cmd); + err = ice_ptp_write_port_cmd_e822(hw, port, cmd); if (err) return err; } @@ -2252,6 +2289,9 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) if (err) goto err_unlock; + /* Do not perform any action on the main timer */ + ice_ptp_src_cmd(hw, ICE_PTP_NOP); + /* Issue the sync to activate the time adjustment */ ice_ptp_exec_tmr_cmd(hw); @@ -2372,6 +2412,9 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) if (err) return err; + /* Do not perform any action on the main timer */ + ice_ptp_src_cmd(hw, ICE_PTP_NOP); + ice_ptp_exec_tmr_cmd(hw); err = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val); @@ -2847,6 +2890,8 @@ static int ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) case ADJ_TIME_AT_TIME: cmd_val = GLTSYN_CMD_ADJ_INIT_TIME; break; + case ICE_PTP_NOP: + return 0; } /* Read, modify, write */ @@ -2869,6 +2914,185 @@ static int ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) return 0; } +/** + * ice_get_phy_tx_tstamp_ready_e810 - Read Tx memory status register + * @hw: pointer to the HW struct + * @port: the PHY port to read + * @tstamp_ready: contents of the Tx memory status register + * + * E810 devices do not use a Tx memory status register. Instead simply + * indicate that all timestamps are currently ready. + */ +static int +ice_get_phy_tx_tstamp_ready_e810(struct ice_hw *hw, u8 port, u64 *tstamp_ready) +{ + *tstamp_ready = 0xFFFFFFFFFFFFFFFF; + return 0; +} + +/* E810T SMA functions + * + * The following functions operate specifically on E810T hardware and are used + * to access the extended GPIOs available. + */ + +/** + * ice_get_pca9575_handle + * @hw: pointer to the hw struct + * @pca9575_handle: GPIO controller's handle + * + * Find and return the GPIO controller's handle in the netlist. + * When found - the value will be cached in the hw structure and following calls + * will return cached value + */ +static int +ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle) +{ + struct ice_aqc_get_link_topo *cmd; + struct ice_aq_desc desc; + int status; + u8 idx; + + /* If handle was read previously return cached value */ + if (hw->io_expander_handle) { + *pca9575_handle = hw->io_expander_handle; + return 0; + } + + /* If handle was not detected read it from the netlist */ + cmd = &desc.params.get_link_topo; + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo); + + /* Set node type to GPIO controller */ + cmd->addr.topo_params.node_type_ctx = + (ICE_AQC_LINK_TOPO_NODE_TYPE_M & + ICE_AQC_LINK_TOPO_NODE_TYPE_GPIO_CTRL); + +#define SW_PCA9575_SFP_TOPO_IDX 2 +#define SW_PCA9575_QSFP_TOPO_IDX 1 + + /* Check if the SW IO expander controlling SMA exists in the netlist. */ + if (hw->device_id == ICE_DEV_ID_E810C_SFP) + idx = SW_PCA9575_SFP_TOPO_IDX; + else if (hw->device_id == ICE_DEV_ID_E810C_QSFP) + idx = SW_PCA9575_QSFP_TOPO_IDX; + else + return -EOPNOTSUPP; + + cmd->addr.topo_params.index = idx; + + status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); + if (status) + return -EOPNOTSUPP; + + /* Verify if we found the right IO expander type */ + if (desc.params.get_link_topo.node_part_num != + ICE_AQC_GET_LINK_TOPO_NODE_NR_PCA9575) + return -EOPNOTSUPP; + + /* If present save the handle and return it */ + hw->io_expander_handle = + le16_to_cpu(desc.params.get_link_topo.addr.handle); + *pca9575_handle = hw->io_expander_handle; + + return 0; +} + +/** + * ice_read_sma_ctrl_e810t + * @hw: pointer to the hw struct + * @data: pointer to data to be read from the GPIO controller + * + * Read the SMA controller state. It is connected to pins 3-7 of Port 1 of the + * PCA9575 expander, so only bits 3-7 in data are valid. + */ +int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data) +{ + int status; + u16 handle; + u8 i; + + status = ice_get_pca9575_handle(hw, &handle); + if (status) + return status; + + *data = 0; + + for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) { + bool pin; + + status = ice_aq_get_gpio(hw, handle, i + ICE_PCA9575_P1_OFFSET, + &pin, NULL); + if (status) + break; + *data |= (u8)(!pin) << i; + } + + return status; +} + +/** + * ice_write_sma_ctrl_e810t + * @hw: pointer to the hw struct + * @data: data to be written to the GPIO controller + * + * Write the data to the SMA controller. It is connected to pins 3-7 of Port 1 + * of the PCA9575 expander, so only bits 3-7 in data are valid. + */ +int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data) +{ + int status; + u16 handle; + u8 i; + + status = ice_get_pca9575_handle(hw, &handle); + if (status) + return status; + + for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) { + bool pin; + + pin = !(data & (1 << i)); + status = ice_aq_set_gpio(hw, handle, i + ICE_PCA9575_P1_OFFSET, + pin, NULL); + if (status) + break; + } + + return status; +} + +/** + * ice_read_pca9575_reg_e810t + * @hw: pointer to the hw struct + * @offset: GPIO controller register offset + * @data: pointer to data to be read from the GPIO controller + * + * Read the register from the GPIO controller + */ +int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data) +{ + struct ice_aqc_link_topo_addr link_topo; + __le16 addr; + u16 handle; + int err; + + memset(&link_topo, 0, sizeof(link_topo)); + + err = ice_get_pca9575_handle(hw, &handle); + if (err) + return err; + + link_topo.handle = cpu_to_le16(handle); + link_topo.topo_params.node_type_ctx = + FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, + ICE_AQC_LINK_TOPO_NODE_CTX_PROVIDED); + + addr = cpu_to_le16((u16)offset); + + return ice_aq_read_i2c(hw, link_topo, 0, addr, 1, data, NULL); +} + /* Device agnostic functions * * The following functions implement shared behavior common to both E822 and @@ -3130,204 +3354,6 @@ int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx) } /** - * ice_get_phy_tx_tstamp_ready_e810 - Read Tx memory status register - * @hw: pointer to the HW struct - * @port: the PHY port to read - * @tstamp_ready: contents of the Tx memory status register - * - * E810 devices do not use a Tx memory status register. Instead simply - * indicate that all timestamps are currently ready. - */ -static int -ice_get_phy_tx_tstamp_ready_e810(struct ice_hw *hw, u8 port, u64 *tstamp_ready) -{ - *tstamp_ready = 0xFFFFFFFFFFFFFFFF; - return 0; -} - -/* E810T SMA functions - * - * The following functions operate specifically on E810T hardware and are used - * to access the extended GPIOs available. - */ - -/** - * ice_get_pca9575_handle - * @hw: pointer to the hw struct - * @pca9575_handle: GPIO controller's handle - * - * Find and return the GPIO controller's handle in the netlist. - * When found - the value will be cached in the hw structure and following calls - * will return cached value - */ -static int -ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle) -{ - struct ice_aqc_get_link_topo *cmd; - struct ice_aq_desc desc; - int status; - u8 idx; - - /* If handle was read previously return cached value */ - if (hw->io_expander_handle) { - *pca9575_handle = hw->io_expander_handle; - return 0; - } - - /* If handle was not detected read it from the netlist */ - cmd = &desc.params.get_link_topo; - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_link_topo); - - /* Set node type to GPIO controller */ - cmd->addr.topo_params.node_type_ctx = - (ICE_AQC_LINK_TOPO_NODE_TYPE_M & - ICE_AQC_LINK_TOPO_NODE_TYPE_GPIO_CTRL); - -#define SW_PCA9575_SFP_TOPO_IDX 2 -#define SW_PCA9575_QSFP_TOPO_IDX 1 - - /* Check if the SW IO expander controlling SMA exists in the netlist. */ - if (hw->device_id == ICE_DEV_ID_E810C_SFP) - idx = SW_PCA9575_SFP_TOPO_IDX; - else if (hw->device_id == ICE_DEV_ID_E810C_QSFP) - idx = SW_PCA9575_QSFP_TOPO_IDX; - else - return -EOPNOTSUPP; - - cmd->addr.topo_params.index = idx; - - status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); - if (status) - return -EOPNOTSUPP; - - /* Verify if we found the right IO expander type */ - if (desc.params.get_link_topo.node_part_num != - ICE_AQC_GET_LINK_TOPO_NODE_NR_PCA9575) - return -EOPNOTSUPP; - - /* If present save the handle and return it */ - hw->io_expander_handle = - le16_to_cpu(desc.params.get_link_topo.addr.handle); - *pca9575_handle = hw->io_expander_handle; - - return 0; -} - -/** - * ice_read_sma_ctrl_e810t - * @hw: pointer to the hw struct - * @data: pointer to data to be read from the GPIO controller - * - * Read the SMA controller state. It is connected to pins 3-7 of Port 1 of the - * PCA9575 expander, so only bits 3-7 in data are valid. - */ -int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data) -{ - int status; - u16 handle; - u8 i; - - status = ice_get_pca9575_handle(hw, &handle); - if (status) - return status; - - *data = 0; - - for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) { - bool pin; - - status = ice_aq_get_gpio(hw, handle, i + ICE_PCA9575_P1_OFFSET, - &pin, NULL); - if (status) - break; - *data |= (u8)(!pin) << i; - } - - return status; -} - -/** - * ice_write_sma_ctrl_e810t - * @hw: pointer to the hw struct - * @data: data to be written to the GPIO controller - * - * Write the data to the SMA controller. It is connected to pins 3-7 of Port 1 - * of the PCA9575 expander, so only bits 3-7 in data are valid. - */ -int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data) -{ - int status; - u16 handle; - u8 i; - - status = ice_get_pca9575_handle(hw, &handle); - if (status) - return status; - - for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) { - bool pin; - - pin = !(data & (1 << i)); - status = ice_aq_set_gpio(hw, handle, i + ICE_PCA9575_P1_OFFSET, - pin, NULL); - if (status) - break; - } - - return status; -} - -/** - * ice_read_pca9575_reg_e810t - * @hw: pointer to the hw struct - * @offset: GPIO controller register offset - * @data: pointer to data to be read from the GPIO controller - * - * Read the register from the GPIO controller - */ -int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data) -{ - struct ice_aqc_link_topo_addr link_topo; - __le16 addr; - u16 handle; - int err; - - memset(&link_topo, 0, sizeof(link_topo)); - - err = ice_get_pca9575_handle(hw, &handle); - if (err) - return err; - - link_topo.handle = cpu_to_le16(handle); - link_topo.topo_params.node_type_ctx = - FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, - ICE_AQC_LINK_TOPO_NODE_CTX_PROVIDED); - - addr = cpu_to_le16((u16)offset); - - return ice_aq_read_i2c(hw, link_topo, 0, addr, 1, data, NULL); -} - -/** - * ice_is_pca9575_present - * @hw: pointer to the hw struct - * - * Check if the SW IO expander is present in the netlist - */ -bool ice_is_pca9575_present(struct ice_hw *hw) -{ - u16 handle = 0; - int status; - - if (!ice_is_e810t(hw)) - return false; - - status = ice_get_pca9575_handle(hw, &handle); - - return !status && handle; -} - -/** * ice_ptp_reset_ts_memory - Reset timestamp memory for all blocks * @hw: pointer to the HW struct */ |