Commit 91dc1e5d authored by Michal Kosiarz's avatar Michal Kosiarz Committed by Jeff Kirsher

i40e: Add Clause22 implementation

Some external PHYs require Clause22 method for accessing registers.
This patch also adds some defines to support blink led on devices using
10CBaseT PHY.

Change-ID: I868a4326911900f6c89e7e522fda4968b0825f14
Signed-off-by: default avatarMichal Kosiarz <michal.kosiarz@intel.com>
Signed-off-by: default avatarMatt Jared <matthew.a.jared@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent d182a5ca
...@@ -4396,7 +4396,99 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw, ...@@ -4396,7 +4396,99 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw,
} }
/** /**
* i40e_read_phy_register * i40e_read_phy_register_clause22
* @hw: pointer to the HW structure
* @reg: register address in the page
* @phy_adr: PHY address on MDIO interface
* @value: PHY register value
*
* Reads specified PHY register value
**/
i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw,
u16 reg, u8 phy_addr, u16 *value)
{
i40e_status status = I40E_ERR_TIMEOUT;
u8 port_num = (u8)hw->func_caps.mdio_port_num;
u32 command = 0;
u16 retry = 1000;
command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_CLAUSE22_OPCODE_READ_MASK) |
(I40E_MDIO_CLAUSE22_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command);
do {
command = rd32(hw, I40E_GLGEN_MSCA(port_num));
if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
status = 0;
break;
}
udelay(10);
retry--;
} while (retry);
if (status) {
i40e_debug(hw, I40E_DEBUG_PHY,
"PHY: Can't write command to external PHY.\n");
goto phy_read_end;
}
if (!status) {
command = rd32(hw, I40E_GLGEN_MSRWD(port_num));
*value = (command & I40E_GLGEN_MSRWD_MDIRDDATA_MASK) >>
I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT;
} else {
i40e_debug(hw, I40E_DEBUG_PHY,
"PHY: Can't read register value from external PHY.\n");
}
phy_read_end:
return status;
}
/**
* i40e_write_phy_register_clause22
* @hw: pointer to the HW structure
* @reg: register address in the page
* @phy_adr: PHY address on MDIO interface
* @value: PHY register value
*
* Writes specified PHY register value
**/
i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
u16 reg, u8 phy_addr, u16 value)
{
i40e_status status = I40E_ERR_TIMEOUT;
u8 port_num = (u8)hw->func_caps.mdio_port_num;
u32 command = 0;
u16 retry = 1000;
command = value << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT;
wr32(hw, I40E_GLGEN_MSRWD(port_num), command);
command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK) |
(I40E_MDIO_CLAUSE22_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command);
do {
command = rd32(hw, I40E_GLGEN_MSCA(port_num));
if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
status = 0;
break;
}
udelay(10);
retry--;
} while (retry);
return status;
}
/**
* i40e_read_phy_register_clause45
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
* @page: registers page number * @page: registers page number
* @reg: register address in the page * @reg: register address in the page
...@@ -4405,9 +4497,8 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw, ...@@ -4405,9 +4497,8 @@ i40e_status i40e_aq_configure_partition_bw(struct i40e_hw *hw,
* *
* Reads specified PHY register value * Reads specified PHY register value
**/ **/
i40e_status i40e_read_phy_register(struct i40e_hw *hw, i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u8 page, u16 reg, u8 phy_addr, u16 *value)
u16 *value)
{ {
i40e_status status = I40E_ERR_TIMEOUT; i40e_status status = I40E_ERR_TIMEOUT;
u32 command = 0; u32 command = 0;
...@@ -4417,8 +4508,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw, ...@@ -4417,8 +4508,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,
command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) | command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
(page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_ADDRESS) | (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
(I40E_MDIO_STCODE) | (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) | (I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK); (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command); wr32(hw, I40E_GLGEN_MSCA(port_num), command);
...@@ -4440,8 +4531,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw, ...@@ -4440,8 +4531,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,
command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_READ) | (I40E_MDIO_CLAUSE45_OPCODE_READ_MASK) |
(I40E_MDIO_STCODE) | (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) | (I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK); (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
status = I40E_ERR_TIMEOUT; status = I40E_ERR_TIMEOUT;
...@@ -4471,7 +4562,7 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw, ...@@ -4471,7 +4562,7 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,
} }
/** /**
* i40e_write_phy_register * i40e_write_phy_register_clause45
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
* @page: registers page number * @page: registers page number
* @reg: register address in the page * @reg: register address in the page
...@@ -4480,9 +4571,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw, ...@@ -4480,9 +4571,8 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw,
* *
* Writes value to specified PHY register * Writes value to specified PHY register
**/ **/
i40e_status i40e_write_phy_register(struct i40e_hw *hw, i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u8 page, u16 reg, u8 phy_addr, u16 value)
u16 value)
{ {
i40e_status status = I40E_ERR_TIMEOUT; i40e_status status = I40E_ERR_TIMEOUT;
u32 command = 0; u32 command = 0;
...@@ -4492,8 +4582,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw, ...@@ -4492,8 +4582,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw,
command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) | command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
(page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_ADDRESS) | (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
(I40E_MDIO_STCODE) | (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) | (I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK); (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
wr32(hw, I40E_GLGEN_MSCA(port_num), command); wr32(hw, I40E_GLGEN_MSCA(port_num), command);
...@@ -4517,8 +4607,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw, ...@@ -4517,8 +4607,8 @@ i40e_status i40e_write_phy_register(struct i40e_hw *hw,
command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) | command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
(phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) | (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
(I40E_MDIO_OPCODE_WRITE) | (I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK) |
(I40E_MDIO_STCODE) | (I40E_MDIO_CLAUSE45_STCODE_MASK) |
(I40E_GLGEN_MSCA_MDICMD_MASK) | (I40E_GLGEN_MSCA_MDICMD_MASK) |
(I40E_GLGEN_MSCA_MDIINPROGEN_MASK); (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
status = I40E_ERR_TIMEOUT; status = I40E_ERR_TIMEOUT;
...@@ -4580,14 +4670,16 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw, ...@@ -4580,14 +4670,16 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++, for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
led_addr++) { led_addr++) {
status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, status = i40e_read_phy_register_clause45(hw,
led_addr, phy_addr, &led_reg); I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr,
&led_reg);
if (status) if (status)
goto phy_blinking_end; goto phy_blinking_end;
led_ctl = led_reg; led_ctl = led_reg;
if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) { if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
led_reg = 0; led_reg = 0;
status = i40e_write_phy_register(hw, status = i40e_write_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_addr, phy_addr,
led_reg); led_reg);
...@@ -4599,20 +4691,18 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw, ...@@ -4599,20 +4691,18 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
if (time > 0 && interval > 0) { if (time > 0 && interval > 0) {
for (i = 0; i < time * 1000; i += interval) { for (i = 0; i < time * 1000; i += interval) {
status = i40e_read_phy_register(hw, status = i40e_read_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_addr, phy_addr, &led_reg);
&led_reg);
if (status) if (status)
goto restore_config; goto restore_config;
if (led_reg & I40E_PHY_LED_MANUAL_ON) if (led_reg & I40E_PHY_LED_MANUAL_ON)
led_reg = 0; led_reg = 0;
else else
led_reg = I40E_PHY_LED_MANUAL_ON; led_reg = I40E_PHY_LED_MANUAL_ON;
status = i40e_write_phy_register(hw, status = i40e_write_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_addr, phy_addr, led_reg);
led_reg);
if (status) if (status)
goto restore_config; goto restore_config;
msleep(interval); msleep(interval);
...@@ -4620,8 +4710,9 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw, ...@@ -4620,8 +4710,9 @@ i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
} }
restore_config: restore_config:
status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, status = i40e_write_phy_register_clause45(hw,
phy_addr, led_ctl); I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_ctl);
phy_blinking_end: phy_blinking_end:
return status; return status;
...@@ -4652,8 +4743,10 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr, ...@@ -4652,8 +4743,10 @@ i40e_status i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++, for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
temp_addr++) { temp_addr++) {
status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, status = i40e_read_phy_register_clause45(hw,
temp_addr, phy_addr, &reg_val); I40E_PHY_COM_REG_PAGE,
temp_addr, phy_addr,
&reg_val);
if (status) if (status)
return status; return status;
*val = reg_val; *val = reg_val;
...@@ -4686,20 +4779,21 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on, ...@@ -4686,20 +4779,21 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on,
i = rd32(hw, I40E_PFGEN_PORTNUM); i = rd32(hw, I40E_PFGEN_PORTNUM);
port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK); port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
phy_addr = i40e_get_phy_address(hw, port_num); phy_addr = i40e_get_phy_address(hw, port_num);
status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, led_addr, phy_addr, &led_reg);
phy_addr, &led_reg);
if (status) if (status)
return status; return status;
led_ctl = led_reg; led_ctl = led_reg;
if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) { if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
led_reg = 0; led_reg = 0;
status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, status = i40e_write_phy_register_clause45(hw,
led_addr, phy_addr, led_reg); I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr,
led_reg);
if (status) if (status)
return status; return status;
} }
status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, &led_reg); led_addr, phy_addr, &led_reg);
if (status) if (status)
goto restore_config; goto restore_config;
...@@ -4707,20 +4801,20 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on, ...@@ -4707,20 +4801,20 @@ i40e_status i40e_led_set_phy(struct i40e_hw *hw, bool on,
led_reg = I40E_PHY_LED_MANUAL_ON; led_reg = I40E_PHY_LED_MANUAL_ON;
else else
led_reg = 0; led_reg = 0;
status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_reg); led_addr, phy_addr, led_reg);
if (status) if (status)
goto restore_config; goto restore_config;
if (mode & I40E_PHY_LED_MODE_ORIG) { if (mode & I40E_PHY_LED_MODE_ORIG) {
led_ctl = (mode & I40E_PHY_LED_MODE_MASK); led_ctl = (mode & I40E_PHY_LED_MODE_MASK);
status = i40e_write_phy_register(hw, status = i40e_write_phy_register_clause45(hw,
I40E_PHY_COM_REG_PAGE, I40E_PHY_COM_REG_PAGE,
led_addr, phy_addr, led_ctl); led_addr, phy_addr, led_ctl);
} }
return status; return status;
restore_config: restore_config:
status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr, status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
phy_addr, led_ctl); led_addr, phy_addr, led_ctl);
return status; return status;
} }
......
...@@ -362,10 +362,14 @@ i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw, ...@@ -362,10 +362,14 @@ i40e_status i40e_aq_rx_ctl_write_register(struct i40e_hw *hw,
u32 reg_addr, u32 reg_val, u32 reg_addr, u32 reg_val,
struct i40e_asq_cmd_details *cmd_details); struct i40e_asq_cmd_details *cmd_details);
void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val); void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page, i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw,
u16 reg, u8 phy_addr, u16 *value); u16 reg, u8 phy_addr, u16 *value);
i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page, i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
u16 reg, u8 phy_addr, u16 value); u16 reg, u8 phy_addr, u16 value);
i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u16 *value);
i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u16 value);
u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num); u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw, i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
u32 time, u32 interval); u32 time, u32 interval);
......
...@@ -90,13 +90,22 @@ enum i40e_debug_mask { ...@@ -90,13 +90,22 @@ enum i40e_debug_mask {
I40E_DEBUG_ALL = 0xFFFFFFFF I40E_DEBUG_ALL = 0xFFFFFFFF
}; };
#define I40E_MDIO_STCODE 0 #define I40E_MDIO_CLAUSE22_STCODE_MASK I40E_MASK(1, \
#define I40E_MDIO_OPCODE_ADDRESS 0 I40E_GLGEN_MSCA_STCODE_SHIFT)
#define I40E_MDIO_OPCODE_WRITE I40E_MASK(1, \ #define I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK I40E_MASK(1, \
I40E_GLGEN_MSCA_OPCODE_SHIFT) I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_OPCODE_READ_INC_ADDR I40E_MASK(2, \ #define I40E_MDIO_CLAUSE22_OPCODE_READ_MASK I40E_MASK(2, \
I40E_GLGEN_MSCA_OPCODE_SHIFT) I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_OPCODE_READ I40E_MASK(3, \
#define I40E_MDIO_CLAUSE45_STCODE_MASK I40E_MASK(0, \
I40E_GLGEN_MSCA_STCODE_SHIFT)
#define I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK I40E_MASK(0, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK I40E_MASK(1, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_CLAUSE45_OPCODE_READ_INC_ADDR_MASK I40E_MASK(2, \
I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_MDIO_CLAUSE45_OPCODE_READ_MASK I40E_MASK(3, \
I40E_GLGEN_MSCA_OPCODE_SHIFT) I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_PHY_COM_REG_PAGE 0x1E #define I40E_PHY_COM_REG_PAGE 0x1E
......
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