net/i40e/base: add clause22 and clause45 implementation
authorJingjing Wu <jingjing.wu@intel.com>
Sat, 10 Dec 2016 11:24:30 +0000 (19:24 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 17 Jan 2017 18:39:27 +0000 (19:39 +0100)
Some external PHYs require Clause22 and Clause45 method for
accessing registers. Mostly used for X722 support.

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
drivers/net/i40e/base/i40e_common.c
drivers/net/i40e/base/i40e_prototype.h
drivers/net/i40e/base/i40e_type.h

index 7eea189..85c1c11 100644 (file)
@@ -6022,7 +6022,92 @@ enum i40e_status_code 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
+ **/
+enum i40e_status_code i40e_read_phy_register_clause22(struct i40e_hw *hw,
+                                       u16 reg, u8 phy_addr, u16 *value)
+{
+       enum i40e_status_code 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 = I40E_SUCCESS;
+                       break;
+               }
+               i40e_usec_delay(10);
+               retry--;
+       } while (retry);
+
+       if (status) {
+               i40e_debug(hw, I40E_DEBUG_PHY,
+                          "PHY: Can't write command to external PHY.\n");
+       } else {
+               command = rd32(hw, I40E_GLGEN_MSRWD(port_num));
+               *value = (command & I40E_GLGEN_MSRWD_MDIRDDATA_MASK) >>
+                        I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT;
+       }
+
+       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
+ **/
+enum i40e_status_code i40e_write_phy_register_clause22(struct i40e_hw *hw,
+                                       u16 reg, u8 phy_addr, u16 value)
+{
+       enum i40e_status_code 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 = I40E_SUCCESS;
+                       break;
+               }
+               i40e_usec_delay(10);
+               retry--;
+       } while (retry);
+
+       return status;
+}
+
+/**
+ * i40e_read_phy_register_clause45
  * @hw: pointer to the HW structure
  * @page: registers page number
  * @reg: register address in the page
@@ -6031,9 +6116,8 @@ enum i40e_status_code i40e_aq_configure_partition_bw(struct i40e_hw *hw,
  *
  * Reads specified PHY register value
  **/
-enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
-                                            u8 page, u16 reg, u8 phy_addr,
-                                            u16 *value)
+enum i40e_status_code i40e_read_phy_register_clause45(struct i40e_hw *hw,
+                               u8 page, u16 reg, u8 phy_addr, u16 *value)
 {
        enum i40e_status_code status = I40E_ERR_TIMEOUT;
        u32 command  = 0;
@@ -6043,8 +6127,8 @@ enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
        command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
                  (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
                  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-                 (I40E_MDIO_OPCODE_ADDRESS) |
-                 (I40E_MDIO_STCODE) |
+                 (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
+                 (I40E_MDIO_CLAUSE45_STCODE_MASK) |
                  (I40E_GLGEN_MSCA_MDICMD_MASK) |
                  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
        wr32(hw, I40E_GLGEN_MSCA(port_num), command);
@@ -6066,8 +6150,8 @@ enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
 
        command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
                  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-                 (I40E_MDIO_OPCODE_READ) |
-                 (I40E_MDIO_STCODE) |
+                 (I40E_MDIO_CLAUSE45_OPCODE_READ_MASK) |
+                 (I40E_MDIO_CLAUSE45_STCODE_MASK) |
                  (I40E_GLGEN_MSCA_MDICMD_MASK) |
                  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
        status = I40E_ERR_TIMEOUT;
@@ -6097,7 +6181,7 @@ phy_read_end:
 }
 
 /**
- * i40e_write_phy_register
+ * i40e_write_phy_register_clause45
  * @hw: pointer to the HW structure
  * @page: registers page number
  * @reg: register address in the page
@@ -6106,9 +6190,8 @@ phy_read_end:
  *
  * Writes value to specified PHY register
  **/
-enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
-                                             u8 page, u16 reg, u8 phy_addr,
-                                             u16 value)
+enum i40e_status_code i40e_write_phy_register_clause45(struct i40e_hw *hw,
+                               u8 page, u16 reg, u8 phy_addr, u16 value)
 {
        enum i40e_status_code status = I40E_ERR_TIMEOUT;
        u32 command  = 0;
@@ -6118,8 +6201,8 @@ enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
        command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
                  (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
                  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-                 (I40E_MDIO_OPCODE_ADDRESS) |
-                 (I40E_MDIO_STCODE) |
+                 (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
+                 (I40E_MDIO_CLAUSE45_STCODE_MASK) |
                  (I40E_GLGEN_MSCA_MDICMD_MASK) |
                  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
        wr32(hw, I40E_GLGEN_MSCA(port_num), command);
@@ -6143,8 +6226,8 @@ enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
 
        command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
                  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-                 (I40E_MDIO_OPCODE_WRITE) |
-                 (I40E_MDIO_STCODE) |
+                 (I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK) |
+                 (I40E_MDIO_CLAUSE45_STCODE_MASK) |
                  (I40E_GLGEN_MSCA_MDICMD_MASK) |
                  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
        status = I40E_ERR_TIMEOUT;
@@ -6164,6 +6247,78 @@ phy_write_end:
        return status;
 }
 
+/**
+ * i40e_write_phy_register
+ * @hw: pointer to the HW structure
+ * @page: registers page number
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Writes value to specified PHY register
+ **/
+enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
+                               u8 page, u16 reg, u8 phy_addr, u16 value)
+{
+       enum i40e_status_code status;
+
+       switch (hw->device_id) {
+       case I40E_DEV_ID_1G_BASE_T_X722:
+               status = i40e_write_phy_register_clause22(hw,
+                       reg, phy_addr, value);
+               break;
+       case I40E_DEV_ID_10G_BASE_T:
+       case I40E_DEV_ID_10G_BASE_T4:
+       case I40E_DEV_ID_10G_BASE_T_X722:
+       case I40E_DEV_ID_25G_B:
+       case I40E_DEV_ID_25G_SFP28:
+               status = i40e_write_phy_register_clause45(hw,
+                       page, reg, phy_addr, value);
+               break;
+       default:
+               status = I40E_ERR_UNKNOWN_PHY;
+               break;
+       }
+
+       return status;
+}
+
+/**
+ * i40e_read_phy_register
+ * @hw: pointer to the HW structure
+ * @page: registers page number
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Reads specified PHY register value
+ **/
+enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
+                               u8 page, u16 reg, u8 phy_addr, u16 *value)
+{
+       enum i40e_status_code status;
+
+       switch (hw->device_id) {
+       case I40E_DEV_ID_1G_BASE_T_X722:
+               status = i40e_read_phy_register_clause22(hw, reg, phy_addr,
+                                                        value);
+               break;
+       case I40E_DEV_ID_10G_BASE_T:
+       case I40E_DEV_ID_10G_BASE_T4:
+       case I40E_DEV_ID_10G_BASE_T_X722:
+       case I40E_DEV_ID_25G_B:
+       case I40E_DEV_ID_25G_SFP28:
+               status = i40e_read_phy_register_clause45(hw, page, reg,
+                                                        phy_addr, value);
+               break;
+       default:
+               status = I40E_ERR_UNKNOWN_PHY;
+               break;
+       }
+
+       return status;
+}
+
 /**
  * i40e_get_phy_address
  * @hw: pointer to the HW structure
@@ -6206,14 +6361,16 @@ enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
 
        for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
             led_addr++) {
-               status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-                                               led_addr, phy_addr, &led_reg);
+               status = i40e_read_phy_register_clause45(hw,
+                                                        I40E_PHY_COM_REG_PAGE,
+                                                        led_addr, phy_addr,
+                                                        &led_reg);
                if (status)
                        goto phy_blinking_end;
                led_ctl = led_reg;
                if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
                        led_reg = 0;
-                       status = i40e_write_phy_register(hw,
+                       status = i40e_write_phy_register_clause45(hw,
                                                         I40E_PHY_COM_REG_PAGE,
                                                         led_addr, phy_addr,
                                                         led_reg);
@@ -6225,20 +6382,18 @@ enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
 
        if (time > 0 && interval > 0) {
                for (i = 0; i < time * 1000; i += interval) {
-                       status = i40e_read_phy_register(hw,
-                                                       I40E_PHY_COM_REG_PAGE,
-                                                       led_addr, phy_addr,
-                                                       &led_reg);
+                       status = i40e_read_phy_register_clause45(hw,
+                                               I40E_PHY_COM_REG_PAGE,
+                                               led_addr, phy_addr, &led_reg);
                        if (status)
                                goto restore_config;
                        if (led_reg & I40E_PHY_LED_MANUAL_ON)
                                led_reg = 0;
                        else
                                led_reg = I40E_PHY_LED_MANUAL_ON;
-                       status = i40e_write_phy_register(hw,
-                                                        I40E_PHY_COM_REG_PAGE,
-                                                        led_addr, phy_addr,
-                                                        led_reg);
+                       status = i40e_write_phy_register_clause45(hw,
+                                               I40E_PHY_COM_REG_PAGE,
+                                               led_addr, phy_addr, led_reg);
                        if (status)
                                goto restore_config;
                        i40e_msec_delay(interval);
@@ -6246,8 +6401,9 @@ enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
        }
 
 restore_config:
-       status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
-                                        phy_addr, led_ctl);
+       status = i40e_write_phy_register_clause45(hw,
+                                                 I40E_PHY_COM_REG_PAGE,
+                                                 led_addr, phy_addr, led_ctl);
 
 phy_blinking_end:
        return status;
@@ -6278,8 +6434,10 @@ enum i40e_status_code i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
 
        for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
             temp_addr++) {
-               status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-                                               temp_addr, phy_addr, &reg_val);
+               status = i40e_read_phy_register_clause45(hw,
+                                                        I40E_PHY_COM_REG_PAGE,
+                                                        temp_addr, phy_addr,
+                                                        &reg_val);
                if (status)
                        return status;
                *val = reg_val;
@@ -6312,41 +6470,42 @@ enum i40e_status_code i40e_led_set_phy(struct i40e_hw *hw, bool on,
        i = rd32(hw, I40E_PFGEN_PORTNUM);
        port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
        phy_addr = i40e_get_phy_address(hw, port_num);
-
-       status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
-                                       phy_addr, &led_reg);
+       status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+                                                led_addr, phy_addr, &led_reg);
        if (status)
                return status;
        led_ctl = led_reg;
        if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
                led_reg = 0;
-               status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-                                                led_addr, phy_addr, led_reg);
+               status = i40e_write_phy_register_clause45(hw,
+                                                         I40E_PHY_COM_REG_PAGE,
+                                                         led_addr, phy_addr,
+                                                         led_reg);
                if (status)
                        return status;
        }
-       status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-                                       led_addr, phy_addr, &led_reg);
+       status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+                                                led_addr, phy_addr, &led_reg);
        if (status)
                goto restore_config;
        if (on)
                led_reg = I40E_PHY_LED_MANUAL_ON;
        else
                led_reg = 0;
-       status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-                                        led_addr, phy_addr, led_reg);
+       status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+                                                 led_addr, phy_addr, led_reg);
        if (status)
                goto restore_config;
        if (mode & I40E_PHY_LED_MODE_ORIG) {
                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,
                                                 led_addr, phy_addr, led_ctl);
        }
        return status;
 restore_config:
-       status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
-                                        phy_addr, led_ctl);
+       status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+                                                 led_addr, phy_addr, led_ctl);
        return status;
 }
 #endif /* PF_DRIVER */
index 3aab5ca..9109cfc 100644 (file)
@@ -538,10 +538,18 @@ enum i40e_status_code i40e_aq_get_wake_event_reason(struct i40e_hw *hw,
                        u16 *wake_reason,
                        struct i40e_asq_cmd_details *cmd_details);
 #endif
-enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw, u8 page,
-                                            u16 reg, u8 phy_addr, u16 *value);
-enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw, u8 page,
-                                             u16 reg, u8 phy_addr, u16 value);
+enum i40e_status_code i40e_read_phy_register_clause22(struct i40e_hw *hw,
+                                       u16 reg, u8 phy_addr, u16 *value);
+enum i40e_status_code i40e_write_phy_register_clause22(struct i40e_hw *hw,
+                                       u16 reg, u8 phy_addr, u16 value);
+enum i40e_status_code i40e_read_phy_register_clause45(struct i40e_hw *hw,
+                               u8 page, u16 reg, u8 phy_addr, u16 *value);
+enum i40e_status_code i40e_write_phy_register_clause45(struct i40e_hw *hw,
+                               u8 page, u16 reg, u8 phy_addr, u16 value);
+enum i40e_status_code i40e_read_phy_register(struct i40e_hw *hw,
+                               u8 page, u16 reg, u8 phy_addr, u16 *value);
+enum i40e_status_code i40e_write_phy_register(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);
 enum i40e_status_code i40e_blink_phy_link_led(struct i40e_hw *hw,
                                              u32 time, u32 interval);
index b5f72c3..5a59ce2 100644 (file)
@@ -157,15 +157,22 @@ enum i40e_debug_mask {
 #define I40E_PCI_LINK_SPEED_5000       0x2
 #define I40E_PCI_LINK_SPEED_8000       0x3
 
-#define I40E_MDIO_STCODE               I40E_MASK(0, \
+#define I40E_MDIO_CLAUSE22_STCODE_MASK I40E_MASK(1, \
                                                  I40E_GLGEN_MSCA_STCODE_SHIFT)
-#define I40E_MDIO_OPCODE_ADDRESS       I40E_MASK(0, \
+#define I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK   I40E_MASK(1, \
                                                  I40E_GLGEN_MSCA_OPCODE_SHIFT)
-#define I40E_MDIO_OPCODE_WRITE         I40E_MASK(1, \
+#define I40E_MDIO_CLAUSE22_OPCODE_READ_MASK    I40E_MASK(2, \
                                                  I40E_GLGEN_MSCA_OPCODE_SHIFT)
-#define I40E_MDIO_OPCODE_READ_INC_ADDR I40E_MASK(2, \
+
+#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_OPCODE_READ          I40E_MASK(3, \
+#define I40E_MDIO_CLAUSE45_OPCODE_READ_MASK    I40E_MASK(3, \
                                                  I40E_GLGEN_MSCA_OPCODE_SHIFT)
 
 #define I40E_PHY_COM_REG_PAGE                  0x1E