root/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hclge_mdio_write
  2. hclge_mdio_read
  3. hclge_mac_mdio_config
  4. hclge_mac_adjust_link
  5. hclge_mac_connect_phy
  6. hclge_mac_disconnect_phy
  7. hclge_mac_start_phy
  8. hclge_mac_stop_phy

   1 // SPDX-License-Identifier: GPL-2.0+
   2 // Copyright (c) 2016-2017 Hisilicon Limited.
   3 
   4 #include <linux/etherdevice.h>
   5 #include <linux/kernel.h>
   6 #include <linux/marvell_phy.h>
   7 
   8 #include "hclge_cmd.h"
   9 #include "hclge_main.h"
  10 #include "hclge_mdio.h"
  11 
  12 enum hclge_mdio_c22_op_seq {
  13         HCLGE_MDIO_C22_WRITE = 1,
  14         HCLGE_MDIO_C22_READ = 2
  15 };
  16 
  17 #define HCLGE_MDIO_CTRL_START_B         0
  18 #define HCLGE_MDIO_CTRL_ST_S            1
  19 #define HCLGE_MDIO_CTRL_ST_M            (0x3 << HCLGE_MDIO_CTRL_ST_S)
  20 #define HCLGE_MDIO_CTRL_OP_S            3
  21 #define HCLGE_MDIO_CTRL_OP_M            (0x3 << HCLGE_MDIO_CTRL_OP_S)
  22 
  23 #define HCLGE_MDIO_PHYID_S              0
  24 #define HCLGE_MDIO_PHYID_M              (0x1f << HCLGE_MDIO_PHYID_S)
  25 
  26 #define HCLGE_MDIO_PHYREG_S             0
  27 #define HCLGE_MDIO_PHYREG_M             (0x1f << HCLGE_MDIO_PHYREG_S)
  28 
  29 #define HCLGE_MDIO_STA_B                0
  30 
  31 struct hclge_mdio_cfg_cmd {
  32         u8 ctrl_bit;
  33         u8 phyid;
  34         u8 phyad;
  35         u8 rsvd;
  36         __le16 reserve;
  37         __le16 data_wr;
  38         __le16 data_rd;
  39         __le16 sta;
  40 };
  41 
  42 static int hclge_mdio_write(struct mii_bus *bus, int phyid, int regnum,
  43                             u16 data)
  44 {
  45         struct hclge_mdio_cfg_cmd *mdio_cmd;
  46         struct hclge_dev *hdev = bus->priv;
  47         struct hclge_desc desc;
  48         int ret;
  49 
  50         if (test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state))
  51                 return 0;
  52 
  53         hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, false);
  54 
  55         mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data;
  56 
  57         hnae3_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M,
  58                         HCLGE_MDIO_PHYID_S, (u32)phyid);
  59         hnae3_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M,
  60                         HCLGE_MDIO_PHYREG_S, (u32)regnum);
  61 
  62         hnae3_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1);
  63         hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M,
  64                         HCLGE_MDIO_CTRL_ST_S, 1);
  65         hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M,
  66                         HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_WRITE);
  67 
  68         mdio_cmd->data_wr = cpu_to_le16(data);
  69 
  70         ret = hclge_cmd_send(&hdev->hw, &desc, 1);
  71         if (ret) {
  72                 dev_err(&hdev->pdev->dev,
  73                         "mdio write fail when sending cmd, status is %d.\n",
  74                         ret);
  75                 return ret;
  76         }
  77 
  78         return 0;
  79 }
  80 
  81 static int hclge_mdio_read(struct mii_bus *bus, int phyid, int regnum)
  82 {
  83         struct hclge_mdio_cfg_cmd *mdio_cmd;
  84         struct hclge_dev *hdev = bus->priv;
  85         struct hclge_desc desc;
  86         int ret;
  87 
  88         if (test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state))
  89                 return 0;
  90 
  91         hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, true);
  92 
  93         mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data;
  94 
  95         hnae3_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M,
  96                         HCLGE_MDIO_PHYID_S, (u32)phyid);
  97         hnae3_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M,
  98                         HCLGE_MDIO_PHYREG_S, (u32)regnum);
  99 
 100         hnae3_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1);
 101         hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M,
 102                         HCLGE_MDIO_CTRL_ST_S, 1);
 103         hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M,
 104                         HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_READ);
 105 
 106         /* Read out phy data */
 107         ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 108         if (ret) {
 109                 dev_err(&hdev->pdev->dev,
 110                         "mdio read fail when get data, status is %d.\n",
 111                         ret);
 112                 return ret;
 113         }
 114 
 115         if (hnae3_get_bit(le16_to_cpu(mdio_cmd->sta), HCLGE_MDIO_STA_B)) {
 116                 dev_err(&hdev->pdev->dev, "mdio read data error\n");
 117                 return -EIO;
 118         }
 119 
 120         return le16_to_cpu(mdio_cmd->data_rd);
 121 }
 122 
 123 int hclge_mac_mdio_config(struct hclge_dev *hdev)
 124 {
 125 #define PHY_INEXISTENT  255
 126 
 127         struct hclge_mac *mac = &hdev->hw.mac;
 128         struct phy_device *phydev;
 129         struct mii_bus *mdio_bus;
 130         int ret;
 131 
 132         if (hdev->hw.mac.phy_addr == PHY_INEXISTENT) {
 133                 dev_info(&hdev->pdev->dev,
 134                          "no phy device is connected to mdio bus\n");
 135                 return 0;
 136         } else if (hdev->hw.mac.phy_addr >= PHY_MAX_ADDR) {
 137                 dev_err(&hdev->pdev->dev, "phy_addr(%d) is too large.\n",
 138                         hdev->hw.mac.phy_addr);
 139                 return -EINVAL;
 140         }
 141 
 142         mdio_bus = devm_mdiobus_alloc(&hdev->pdev->dev);
 143         if (!mdio_bus)
 144                 return -ENOMEM;
 145 
 146         mdio_bus->name = "hisilicon MII bus";
 147         mdio_bus->read = hclge_mdio_read;
 148         mdio_bus->write = hclge_mdio_write;
 149         snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "mii",
 150                  dev_name(&hdev->pdev->dev));
 151 
 152         mdio_bus->parent = &hdev->pdev->dev;
 153         mdio_bus->priv = hdev;
 154         mdio_bus->phy_mask = ~(1 << mac->phy_addr);
 155         ret = mdiobus_register(mdio_bus);
 156         if (ret) {
 157                 dev_err(mdio_bus->parent,
 158                         "Failed to register MDIO bus ret = %#x\n", ret);
 159                 return ret;
 160         }
 161 
 162         phydev = mdiobus_get_phy(mdio_bus, mac->phy_addr);
 163         if (!phydev) {
 164                 dev_err(mdio_bus->parent, "Failed to get phy device\n");
 165                 mdiobus_unregister(mdio_bus);
 166                 return -EIO;
 167         }
 168 
 169         mac->phydev = phydev;
 170         mac->mdio_bus = mdio_bus;
 171 
 172         return 0;
 173 }
 174 
 175 static void hclge_mac_adjust_link(struct net_device *netdev)
 176 {
 177         struct hnae3_handle *h = *((void **)netdev_priv(netdev));
 178         struct hclge_vport *vport = hclge_get_vport(h);
 179         struct hclge_dev *hdev = vport->back;
 180         int duplex, speed;
 181         int ret;
 182 
 183         /* When phy link down, do nothing */
 184         if (netdev->phydev->link == 0)
 185                 return;
 186 
 187         speed = netdev->phydev->speed;
 188         duplex = netdev->phydev->duplex;
 189 
 190         ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex);
 191         if (ret)
 192                 netdev_err(netdev, "failed to adjust link.\n");
 193 
 194         ret = hclge_cfg_flowctrl(hdev);
 195         if (ret)
 196                 netdev_err(netdev, "failed to configure flow control.\n");
 197 }
 198 
 199 int hclge_mac_connect_phy(struct hnae3_handle *handle)
 200 {
 201         struct hclge_vport *vport = hclge_get_vport(handle);
 202         struct hclge_dev *hdev = vport->back;
 203         struct net_device *netdev = hdev->vport[0].nic.netdev;
 204         struct phy_device *phydev = hdev->hw.mac.phydev;
 205         __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
 206         int ret;
 207 
 208         if (!phydev)
 209                 return 0;
 210 
 211         linkmode_clear_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported);
 212 
 213         phydev->dev_flags |= MARVELL_PHY_LED0_LINK_LED1_ACTIVE;
 214 
 215         ret = phy_connect_direct(netdev, phydev,
 216                                  hclge_mac_adjust_link,
 217                                  PHY_INTERFACE_MODE_SGMII);
 218         if (ret) {
 219                 netdev_err(netdev, "phy_connect_direct err.\n");
 220                 return ret;
 221         }
 222 
 223         linkmode_copy(mask, hdev->hw.mac.supported);
 224         linkmode_and(phydev->supported, phydev->supported, mask);
 225         linkmode_copy(phydev->advertising, phydev->supported);
 226 
 227         /* supported flag is Pause and Asym Pause, but default advertising
 228          * should be rx on, tx on, so need clear Asym Pause in advertising
 229          * flag
 230          */
 231         linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
 232                            phydev->advertising);
 233 
 234         phy_attached_info(phydev);
 235 
 236         return 0;
 237 }
 238 
 239 void hclge_mac_disconnect_phy(struct hnae3_handle *handle)
 240 {
 241         struct hclge_vport *vport = hclge_get_vport(handle);
 242         struct hclge_dev *hdev = vport->back;
 243         struct phy_device *phydev = hdev->hw.mac.phydev;
 244 
 245         if (!phydev)
 246                 return;
 247 
 248         phy_disconnect(phydev);
 249 }
 250 
 251 void hclge_mac_start_phy(struct hclge_dev *hdev)
 252 {
 253         struct phy_device *phydev = hdev->hw.mac.phydev;
 254 
 255         if (!phydev)
 256                 return;
 257 
 258         phy_start(phydev);
 259 }
 260 
 261 void hclge_mac_stop_phy(struct hclge_dev *hdev)
 262 {
 263         struct net_device *netdev = hdev->vport[0].nic.netdev;
 264         struct phy_device *phydev = netdev->phydev;
 265 
 266         if (!phydev)
 267                 return;
 268 
 269         phy_stop(phydev);
 270 }

/* [<][>][^][v][top][bottom][index][help] */