linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
<<
>>
Prefs
   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
  12enum 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
  31struct 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
  42static 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
  81static 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
 123int 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(%u) 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 = %d\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
 175static 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
 199int 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
 239void 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
 251void 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_loopback(phydev, false);
 259
 260        phy_start(phydev);
 261}
 262
 263void hclge_mac_stop_phy(struct hclge_dev *hdev)
 264{
 265        struct net_device *netdev = hdev->vport[0].nic.netdev;
 266        struct phy_device *phydev = netdev->phydev;
 267
 268        if (!phydev)
 269                return;
 270
 271        phy_stop(phydev);
 272}
 273
 274u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr)
 275{
 276        struct hclge_phy_reg_cmd *req;
 277        struct hclge_desc desc;
 278        int ret;
 279
 280        hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PHY_REG, true);
 281
 282        req = (struct hclge_phy_reg_cmd *)desc.data;
 283        req->reg_addr = cpu_to_le16(reg_addr);
 284
 285        ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 286        if (ret)
 287                dev_err(&hdev->pdev->dev,
 288                        "failed to read phy reg, ret = %d.\n", ret);
 289
 290        return le16_to_cpu(req->reg_val);
 291}
 292
 293int hclge_write_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 val)
 294{
 295        struct hclge_phy_reg_cmd *req;
 296        struct hclge_desc desc;
 297        int ret;
 298
 299        hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PHY_REG, false);
 300
 301        req = (struct hclge_phy_reg_cmd *)desc.data;
 302        req->reg_addr = cpu_to_le16(reg_addr);
 303        req->reg_val = cpu_to_le16(val);
 304
 305        ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 306        if (ret)
 307                dev_err(&hdev->pdev->dev,
 308                        "failed to write phy reg, ret = %d.\n", ret);
 309
 310        return ret;
 311}
 312