1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

ice: Fix quad registers read on E825

Quad registers are read/written incorrectly. E825 devices always use
quad 0 address and differentiate between the PHYs by changing SBQ
destination device (phy_0 or phy_0_peer).

Add helpers for reading/writing PTP registers shared per quad and use
correct quad address and SBQ destination device based on port.

Fixes: 7cab44f1c3 ("ice: Introduce ETH56G PHY model for E825C products")
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
Karol Kolacinski 2024-11-05 13:29:14 +01:00 committed by Tony Nguyen
parent d79c304c76
commit dc26548d72
2 changed files with 133 additions and 87 deletions

View file

@ -900,31 +900,46 @@ static void ice_ptp_exec_tmr_cmd(struct ice_hw *hw)
* The following functions operate on devices with the ETH 56G PHY. * The following functions operate on devices with the ETH 56G PHY.
*/ */
/**
* ice_ptp_get_dest_dev_e825 - get destination PHY for given port number
* @hw: pointer to the HW struct
* @port: destination port
*
* Return: destination sideband queue PHY device.
*/
static enum ice_sbq_msg_dev ice_ptp_get_dest_dev_e825(struct ice_hw *hw,
u8 port)
{
/* On a single complex E825, PHY 0 is always destination device phy_0
* and PHY 1 is phy_0_peer.
*/
if (port >= hw->ptp.ports_per_phy)
return eth56g_phy_1;
else
return eth56g_phy_0;
}
/** /**
* ice_write_phy_eth56g - Write a PHY port register * ice_write_phy_eth56g - Write a PHY port register
* @hw: pointer to the HW struct * @hw: pointer to the HW struct
* @phy_idx: PHY index * @port: destination port
* @addr: PHY register address * @addr: PHY register address
* @val: Value to write * @val: Value to write
* *
* Return: 0 on success, other error codes when failed to write to PHY * Return: 0 on success, other error codes when failed to write to PHY
*/ */
static int ice_write_phy_eth56g(struct ice_hw *hw, u8 phy_idx, u32 addr, static int ice_write_phy_eth56g(struct ice_hw *hw, u8 port, u32 addr, u32 val)
u32 val)
{ {
struct ice_sbq_msg_input phy_msg; struct ice_sbq_msg_input msg = {
.dest_dev = ice_ptp_get_dest_dev_e825(hw, port),
.opcode = ice_sbq_msg_wr,
.msg_addr_low = lower_16_bits(addr),
.msg_addr_high = upper_16_bits(addr),
.data = val
};
int err; int err;
phy_msg.opcode = ice_sbq_msg_wr; err = ice_sbq_rw_reg(hw, &msg, ICE_AQ_FLAG_RD);
phy_msg.msg_addr_low = lower_16_bits(addr);
phy_msg.msg_addr_high = upper_16_bits(addr);
phy_msg.data = val;
phy_msg.dest_dev = hw->ptp.phy.eth56g.phy_addr[phy_idx];
err = ice_sbq_rw_reg(hw, &phy_msg, ICE_AQ_FLAG_RD);
if (err) if (err)
ice_debug(hw, ICE_DBG_PTP, "PTP failed to send msg to phy %d\n", ice_debug(hw, ICE_DBG_PTP, "PTP failed to send msg to phy %d\n",
err); err);
@ -935,41 +950,36 @@ static int ice_write_phy_eth56g(struct ice_hw *hw, u8 phy_idx, u32 addr,
/** /**
* ice_read_phy_eth56g - Read a PHY port register * ice_read_phy_eth56g - Read a PHY port register
* @hw: pointer to the HW struct * @hw: pointer to the HW struct
* @phy_idx: PHY index * @port: destination port
* @addr: PHY register address * @addr: PHY register address
* @val: Value to write * @val: Value to write
* *
* Return: 0 on success, other error codes when failed to read from PHY * Return: 0 on success, other error codes when failed to read from PHY
*/ */
static int ice_read_phy_eth56g(struct ice_hw *hw, u8 phy_idx, u32 addr, static int ice_read_phy_eth56g(struct ice_hw *hw, u8 port, u32 addr, u32 *val)
u32 *val)
{ {
struct ice_sbq_msg_input phy_msg; struct ice_sbq_msg_input msg = {
.dest_dev = ice_ptp_get_dest_dev_e825(hw, port),
.opcode = ice_sbq_msg_rd,
.msg_addr_low = lower_16_bits(addr),
.msg_addr_high = upper_16_bits(addr)
};
int err; int err;
phy_msg.opcode = ice_sbq_msg_rd; err = ice_sbq_rw_reg(hw, &msg, ICE_AQ_FLAG_RD);
if (err)
phy_msg.msg_addr_low = lower_16_bits(addr);
phy_msg.msg_addr_high = upper_16_bits(addr);
phy_msg.data = 0;
phy_msg.dest_dev = hw->ptp.phy.eth56g.phy_addr[phy_idx];
err = ice_sbq_rw_reg(hw, &phy_msg, ICE_AQ_FLAG_RD);
if (err) {
ice_debug(hw, ICE_DBG_PTP, "PTP failed to send msg to phy %d\n", ice_debug(hw, ICE_DBG_PTP, "PTP failed to send msg to phy %d\n",
err); err);
else
*val = msg.data;
return err; return err;
} }
*val = phy_msg.data;
return 0;
}
/** /**
* ice_phy_res_address_eth56g - Calculate a PHY port register address * ice_phy_res_address_eth56g - Calculate a PHY port register address
* @port: Port number to be written * @hw: pointer to the HW struct
* @lane: Lane number to be written
* @res_type: resource type (register/memory) * @res_type: resource type (register/memory)
* @offset: Offset from PHY port register base * @offset: Offset from PHY port register base
* @addr: The result address * @addr: The result address
@ -978,17 +988,19 @@ static int ice_read_phy_eth56g(struct ice_hw *hw, u8 phy_idx, u32 addr,
* * %0 - success * * %0 - success
* * %EINVAL - invalid port number or resource type * * %EINVAL - invalid port number or resource type
*/ */
static int ice_phy_res_address_eth56g(u8 port, enum eth56g_res_type res_type, static int ice_phy_res_address_eth56g(struct ice_hw *hw, u8 lane,
u32 offset, u32 *addr) enum eth56g_res_type res_type,
u32 offset,
u32 *addr)
{ {
u8 lane = port % ICE_PORTS_PER_QUAD;
u8 phy = ICE_GET_QUAD_NUM(port);
if (res_type >= NUM_ETH56G_PHY_RES) if (res_type >= NUM_ETH56G_PHY_RES)
return -EINVAL; return -EINVAL;
*addr = eth56g_phy_res[res_type].base[phy] + /* Lanes 4..7 are in fact 0..3 on a second PHY */
lane %= hw->ptp.ports_per_phy;
*addr = eth56g_phy_res[res_type].base[0] +
lane * eth56g_phy_res[res_type].step + offset; lane * eth56g_phy_res[res_type].step + offset;
return 0; return 0;
} }
@ -1008,19 +1020,17 @@ static int ice_phy_res_address_eth56g(u8 port, enum eth56g_res_type res_type,
static int ice_write_port_eth56g(struct ice_hw *hw, u8 port, u32 offset, static int ice_write_port_eth56g(struct ice_hw *hw, u8 port, u32 offset,
u32 val, enum eth56g_res_type res_type) u32 val, enum eth56g_res_type res_type)
{ {
u8 phy_port = port % hw->ptp.ports_per_phy;
u8 phy_idx = port / hw->ptp.ports_per_phy;
u32 addr; u32 addr;
int err; int err;
if (port >= hw->ptp.num_lports) if (port >= hw->ptp.num_lports)
return -EINVAL; return -EINVAL;
err = ice_phy_res_address_eth56g(phy_port, res_type, offset, &addr); err = ice_phy_res_address_eth56g(hw, port, res_type, offset, &addr);
if (err) if (err)
return err; return err;
return ice_write_phy_eth56g(hw, phy_idx, addr, val); return ice_write_phy_eth56g(hw, port, addr, val);
} }
/** /**
@ -1039,19 +1049,17 @@ static int ice_write_port_eth56g(struct ice_hw *hw, u8 port, u32 offset,
static int ice_read_port_eth56g(struct ice_hw *hw, u8 port, u32 offset, static int ice_read_port_eth56g(struct ice_hw *hw, u8 port, u32 offset,
u32 *val, enum eth56g_res_type res_type) u32 *val, enum eth56g_res_type res_type)
{ {
u8 phy_port = port % hw->ptp.ports_per_phy;
u8 phy_idx = port / hw->ptp.ports_per_phy;
u32 addr; u32 addr;
int err; int err;
if (port >= hw->ptp.num_lports) if (port >= hw->ptp.num_lports)
return -EINVAL; return -EINVAL;
err = ice_phy_res_address_eth56g(phy_port, res_type, offset, &addr); err = ice_phy_res_address_eth56g(hw, port, res_type, offset, &addr);
if (err) if (err)
return err; return err;
return ice_read_phy_eth56g(hw, phy_idx, addr, val); return ice_read_phy_eth56g(hw, port, addr, val);
} }
/** /**
@ -1200,6 +1208,56 @@ static int ice_write_port_mem_eth56g(struct ice_hw *hw, u8 port, u16 offset,
return ice_write_port_eth56g(hw, port, offset, val, ETH56G_PHY_MEM_PTP); return ice_write_port_eth56g(hw, port, offset, val, ETH56G_PHY_MEM_PTP);
} }
/**
* ice_write_quad_ptp_reg_eth56g - Write a PHY quad register
* @hw: pointer to the HW struct
* @offset: PHY register offset
* @port: Port number
* @val: Value to write
*
* Return:
* * %0 - success
* * %EIO - invalid port number or resource type
* * %other - failed to write to PHY
*/
static int ice_write_quad_ptp_reg_eth56g(struct ice_hw *hw, u8 port,
u32 offset, u32 val)
{
u32 addr;
if (port >= hw->ptp.num_lports)
return -EIO;
addr = eth56g_phy_res[ETH56G_PHY_REG_PTP].base[0] + offset;
return ice_write_phy_eth56g(hw, port, addr, val);
}
/**
* ice_read_quad_ptp_reg_eth56g - Read a PHY quad register
* @hw: pointer to the HW struct
* @offset: PHY register offset
* @port: Port number
* @val: Value to read
*
* Return:
* * %0 - success
* * %EIO - invalid port number or resource type
* * %other - failed to read from PHY
*/
static int ice_read_quad_ptp_reg_eth56g(struct ice_hw *hw, u8 port,
u32 offset, u32 *val)
{
u32 addr;
if (port >= hw->ptp.num_lports)
return -EIO;
addr = eth56g_phy_res[ETH56G_PHY_REG_PTP].base[0] + offset;
return ice_read_phy_eth56g(hw, port, addr, val);
}
/** /**
* ice_is_64b_phy_reg_eth56g - Check if this is a 64bit PHY register * ice_is_64b_phy_reg_eth56g - Check if this is a 64bit PHY register
* @low_addr: the low address to check * @low_addr: the low address to check
@ -1919,7 +1977,6 @@ ice_phy_get_speed_eth56g(struct ice_link_status *li)
*/ */
static int ice_phy_cfg_parpcs_eth56g(struct ice_hw *hw, u8 port) static int ice_phy_cfg_parpcs_eth56g(struct ice_hw *hw, u8 port)
{ {
u8 port_blk = port & ~(ICE_PORTS_PER_QUAD - 1);
u32 val; u32 val;
int err; int err;
@ -1934,7 +1991,7 @@ static int ice_phy_cfg_parpcs_eth56g(struct ice_hw *hw, u8 port)
switch (ice_phy_get_speed_eth56g(&hw->port_info->phy.link_info)) { switch (ice_phy_get_speed_eth56g(&hw->port_info->phy.link_info)) {
case ICE_ETH56G_LNK_SPD_1G: case ICE_ETH56G_LNK_SPD_1G:
case ICE_ETH56G_LNK_SPD_2_5G: case ICE_ETH56G_LNK_SPD_2_5G:
err = ice_read_ptp_reg_eth56g(hw, port_blk, err = ice_read_quad_ptp_reg_eth56g(hw, port,
PHY_GPCS_CONFIG_REG0, &val); PHY_GPCS_CONFIG_REG0, &val);
if (err) { if (err) {
ice_debug(hw, ICE_DBG_PTP, "Failed to read PHY_GPCS_CONFIG_REG0, status: %d", ice_debug(hw, ICE_DBG_PTP, "Failed to read PHY_GPCS_CONFIG_REG0, status: %d",
@ -1946,7 +2003,7 @@ static int ice_phy_cfg_parpcs_eth56g(struct ice_hw *hw, u8 port)
val |= FIELD_PREP(PHY_GPCS_CONFIG_REG0_TX_THR_M, val |= FIELD_PREP(PHY_GPCS_CONFIG_REG0_TX_THR_M,
ICE_ETH56G_NOMINAL_TX_THRESH); ICE_ETH56G_NOMINAL_TX_THRESH);
err = ice_write_ptp_reg_eth56g(hw, port_blk, err = ice_write_quad_ptp_reg_eth56g(hw, port,
PHY_GPCS_CONFIG_REG0, val); PHY_GPCS_CONFIG_REG0, val);
if (err) { if (err) {
ice_debug(hw, ICE_DBG_PTP, "Failed to write PHY_GPCS_CONFIG_REG0, status: %d", ice_debug(hw, ICE_DBG_PTP, "Failed to write PHY_GPCS_CONFIG_REG0, status: %d",
@ -1988,50 +2045,47 @@ static int ice_phy_cfg_parpcs_eth56g(struct ice_hw *hw, u8 port)
*/ */
int ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port) int ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port)
{ {
u8 port_blk = port & ~(ICE_PORTS_PER_QUAD - 1); u8 quad_lane = port % ICE_PORTS_PER_QUAD;
u8 blk_port = port & (ICE_PORTS_PER_QUAD - 1); u32 addr, val, peer_delay;
bool enable, sfd_ena; bool enable, sfd_ena;
u32 val, peer_delay;
int err; int err;
enable = hw->ptp.phy.eth56g.onestep_ena; enable = hw->ptp.phy.eth56g.onestep_ena;
peer_delay = hw->ptp.phy.eth56g.peer_delay; peer_delay = hw->ptp.phy.eth56g.peer_delay;
sfd_ena = hw->ptp.phy.eth56g.sfd_ena; sfd_ena = hw->ptp.phy.eth56g.sfd_ena;
/* PHY_PTP_1STEP_CONFIG */ addr = PHY_PTP_1STEP_CONFIG;
err = ice_read_ptp_reg_eth56g(hw, port_blk, PHY_PTP_1STEP_CONFIG, &val); err = ice_read_quad_ptp_reg_eth56g(hw, port, addr, &val);
if (err) if (err)
return err; return err;
if (enable) if (enable)
val |= blk_port; val |= BIT(quad_lane);
else else
val &= ~blk_port; val &= ~BIT(quad_lane);
val &= ~(PHY_PTP_1STEP_T1S_UP64_M | PHY_PTP_1STEP_T1S_DELTA_M); val &= ~(PHY_PTP_1STEP_T1S_UP64_M | PHY_PTP_1STEP_T1S_DELTA_M);
err = ice_write_ptp_reg_eth56g(hw, port_blk, PHY_PTP_1STEP_CONFIG, val); err = ice_write_quad_ptp_reg_eth56g(hw, port, addr, val);
if (err) if (err)
return err; return err;
/* PHY_PTP_1STEP_PEER_DELAY */ addr = PHY_PTP_1STEP_PEER_DELAY(quad_lane);
val = FIELD_PREP(PHY_PTP_1STEP_PD_DELAY_M, peer_delay); val = FIELD_PREP(PHY_PTP_1STEP_PD_DELAY_M, peer_delay);
if (peer_delay) if (peer_delay)
val |= PHY_PTP_1STEP_PD_ADD_PD_M; val |= PHY_PTP_1STEP_PD_ADD_PD_M;
val |= PHY_PTP_1STEP_PD_DLY_V_M; val |= PHY_PTP_1STEP_PD_DLY_V_M;
err = ice_write_ptp_reg_eth56g(hw, port_blk, err = ice_write_quad_ptp_reg_eth56g(hw, port, addr, val);
PHY_PTP_1STEP_PEER_DELAY(blk_port), val);
if (err) if (err)
return err; return err;
val &= ~PHY_PTP_1STEP_PD_DLY_V_M; val &= ~PHY_PTP_1STEP_PD_DLY_V_M;
err = ice_write_ptp_reg_eth56g(hw, port_blk, err = ice_write_quad_ptp_reg_eth56g(hw, port, addr, val);
PHY_PTP_1STEP_PEER_DELAY(blk_port), val);
if (err) if (err)
return err; return err;
/* PHY_MAC_XIF_MODE */ addr = PHY_MAC_XIF_MODE;
err = ice_read_mac_reg_eth56g(hw, port, PHY_MAC_XIF_MODE, &val); err = ice_read_mac_reg_eth56g(hw, port, addr, &val);
if (err) if (err)
return err; return err;
@ -2051,7 +2105,7 @@ int ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port)
FIELD_PREP(PHY_MAC_XIF_TS_BIN_MODE_M, enable) | FIELD_PREP(PHY_MAC_XIF_TS_BIN_MODE_M, enable) |
FIELD_PREP(PHY_MAC_XIF_TS_SFD_ENA_M, sfd_ena); FIELD_PREP(PHY_MAC_XIF_TS_SFD_ENA_M, sfd_ena);
return ice_write_mac_reg_eth56g(hw, port, PHY_MAC_XIF_MODE, val); return ice_write_mac_reg_eth56g(hw, port, addr, val);
} }
/** /**
@ -2093,21 +2147,22 @@ static u32 ice_ptp_calc_bitslip_eth56g(struct ice_hw *hw, u8 port, u32 bs,
bool fc, bool rs, bool fc, bool rs,
enum ice_eth56g_link_spd spd) enum ice_eth56g_link_spd spd)
{ {
u8 port_offset = port & (ICE_PORTS_PER_QUAD - 1);
u8 port_blk = port & ~(ICE_PORTS_PER_QUAD - 1);
u32 bitslip; u32 bitslip;
int err; int err;
if (!bs || rs) if (!bs || rs)
return 0; return 0;
if (spd == ICE_ETH56G_LNK_SPD_1G || spd == ICE_ETH56G_LNK_SPD_2_5G) if (spd == ICE_ETH56G_LNK_SPD_1G || spd == ICE_ETH56G_LNK_SPD_2_5G) {
err = ice_read_gpcs_reg_eth56g(hw, port, PHY_GPCS_BITSLIP, err = ice_read_gpcs_reg_eth56g(hw, port, PHY_GPCS_BITSLIP,
&bitslip); &bitslip);
else } else {
err = ice_read_ptp_reg_eth56g(hw, port_blk, u8 quad_lane = port % ICE_PORTS_PER_QUAD;
PHY_REG_SD_BIT_SLIP(port_offset), u32 addr;
&bitslip);
addr = PHY_REG_SD_BIT_SLIP(quad_lane);
err = ice_read_quad_ptp_reg_eth56g(hw, port, addr, &bitslip);
}
if (err) if (err)
return 0; return 0;
@ -2702,8 +2757,6 @@ static void ice_ptp_init_phy_e825(struct ice_hw *hw)
params->onestep_ena = false; params->onestep_ena = false;
params->peer_delay = 0; params->peer_delay = 0;
params->sfd_ena = false; params->sfd_ena = false;
params->phy_addr[0] = eth56g_phy_0;
params->phy_addr[1] = eth56g_phy_1;
params->num_phys = 2; params->num_phys = 2;
ptp->ports_per_phy = 4; ptp->ports_per_phy = 4;
ptp->num_lports = params->num_phys * ptp->ports_per_phy; ptp->num_lports = params->num_phys * ptp->ports_per_phy;
@ -2734,10 +2787,9 @@ static void ice_fill_phy_msg_e82x(struct ice_hw *hw,
struct ice_sbq_msg_input *msg, u8 port, struct ice_sbq_msg_input *msg, u8 port,
u16 offset) u16 offset)
{ {
int phy_port, phy, quadtype; int phy_port, quadtype;
phy_port = port % hw->ptp.ports_per_phy; phy_port = port % hw->ptp.ports_per_phy;
phy = port / hw->ptp.ports_per_phy;
quadtype = ICE_GET_QUAD_NUM(port) % quadtype = ICE_GET_QUAD_NUM(port) %
ICE_GET_QUAD_NUM(hw->ptp.ports_per_phy); ICE_GET_QUAD_NUM(hw->ptp.ports_per_phy);
@ -2749,12 +2801,7 @@ static void ice_fill_phy_msg_e82x(struct ice_hw *hw,
msg->msg_addr_high = P_Q1_H(P_4_BASE + offset, phy_port); msg->msg_addr_high = P_Q1_H(P_4_BASE + offset, phy_port);
} }
if (phy == 0)
msg->dest_dev = rmn_0; msg->dest_dev = rmn_0;
else if (phy == 1)
msg->dest_dev = rmn_1;
else
msg->dest_dev = rmn_2;
} }
/** /**

View file

@ -850,7 +850,6 @@ struct ice_mbx_data {
struct ice_eth56g_params { struct ice_eth56g_params {
u8 num_phys; u8 num_phys;
u8 phy_addr[2];
bool onestep_ena; bool onestep_ena;
bool sfd_ena; bool sfd_ena;
u32 peer_delay; u32 peer_delay;