linux/drivers/net/ethernet/hisilicon/hns_mdio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (c) 2014-2015 Hisilicon Limited.
   4 */
   5
   6#include <linux/acpi.h>
   7#include <linux/errno.h>
   8#include <linux/etherdevice.h>
   9#include <linux/init.h>
  10#include <linux/kernel.h>
  11#include <linux/mfd/syscon.h>
  12#include <linux/module.h>
  13#include <linux/mutex.h>
  14#include <linux/netdevice.h>
  15#include <linux/of_address.h>
  16#include <linux/of.h>
  17#include <linux/of_mdio.h>
  18#include <linux/of_platform.h>
  19#include <linux/phy.h>
  20#include <linux/platform_device.h>
  21#include <linux/regmap.h>
  22
  23#define MDIO_DRV_NAME "Hi-HNS_MDIO"
  24#define MDIO_BUS_NAME "Hisilicon MII Bus"
  25
  26#define MDIO_TIMEOUT                    1000000
  27
  28struct hns_mdio_sc_reg {
  29        u16 mdio_clk_en;
  30        u16 mdio_clk_dis;
  31        u16 mdio_reset_req;
  32        u16 mdio_reset_dreq;
  33        u16 mdio_clk_st;
  34        u16 mdio_reset_st;
  35};
  36
  37struct hns_mdio_device {
  38        u8 __iomem *vbase;              /* mdio reg base address */
  39        struct regmap *subctrl_vbase;
  40        struct hns_mdio_sc_reg sc_reg;
  41};
  42
  43/* mdio reg */
  44#define MDIO_COMMAND_REG                0x0
  45#define MDIO_ADDR_REG                   0x4
  46#define MDIO_WDATA_REG                  0x8
  47#define MDIO_RDATA_REG                  0xc
  48#define MDIO_STA_REG                    0x10
  49
  50/* cfg phy bit map */
  51#define MDIO_CMD_DEVAD_M        0x1f
  52#define MDIO_CMD_DEVAD_S        0
  53#define MDIO_CMD_PRTAD_M        0x1f
  54#define MDIO_CMD_PRTAD_S        5
  55#define MDIO_CMD_OP_S           10
  56#define MDIO_CMD_ST_S           12
  57#define MDIO_CMD_START_B        14
  58
  59#define MDIO_ADDR_DATA_M        0xffff
  60#define MDIO_ADDR_DATA_S        0
  61
  62#define MDIO_WDATA_DATA_M       0xffff
  63#define MDIO_WDATA_DATA_S       0
  64
  65#define MDIO_RDATA_DATA_M       0xffff
  66#define MDIO_RDATA_DATA_S       0
  67
  68#define MDIO_STATE_STA_B        0
  69
  70enum mdio_st_clause {
  71        MDIO_ST_CLAUSE_45 = 0,
  72        MDIO_ST_CLAUSE_22
  73};
  74
  75enum mdio_c22_op_seq {
  76        MDIO_C22_WRITE = 1,
  77        MDIO_C22_READ = 2
  78};
  79
  80enum mdio_c45_op_seq {
  81        MDIO_C45_WRITE_ADDR = 0,
  82        MDIO_C45_WRITE_DATA,
  83        MDIO_C45_READ_INCREMENT,
  84        MDIO_C45_READ
  85};
  86
  87/* peri subctrl reg */
  88#define MDIO_SC_CLK_EN          0x338
  89#define MDIO_SC_CLK_DIS         0x33C
  90#define MDIO_SC_RESET_REQ       0xA38
  91#define MDIO_SC_RESET_DREQ      0xA3C
  92#define MDIO_SC_CLK_ST          0x531C
  93#define MDIO_SC_RESET_ST        0x5A1C
  94
  95static void mdio_write_reg(u8 __iomem *base, u32 reg, u32 value)
  96{
  97        writel_relaxed(value, base + reg);
  98}
  99
 100#define MDIO_WRITE_REG(a, reg, value) \
 101        mdio_write_reg((a)->vbase, (reg), (value))
 102
 103static u32 mdio_read_reg(u8 __iomem *base, u32 reg)
 104{
 105        return readl_relaxed(base + reg);
 106}
 107
 108#define mdio_set_field(origin, mask, shift, val) \
 109        do { \
 110                (origin) &= (~((mask) << (shift))); \
 111                (origin) |= (((val) & (mask)) << (shift)); \
 112        } while (0)
 113
 114#define mdio_get_field(origin, mask, shift) (((origin) >> (shift)) & (mask))
 115
 116static void mdio_set_reg_field(u8 __iomem *base, u32 reg, u32 mask, u32 shift,
 117                               u32 val)
 118{
 119        u32 origin = mdio_read_reg(base, reg);
 120
 121        mdio_set_field(origin, mask, shift, val);
 122        mdio_write_reg(base, reg, origin);
 123}
 124
 125#define MDIO_SET_REG_FIELD(dev, reg, mask, shift, val) \
 126        mdio_set_reg_field((dev)->vbase, (reg), (mask), (shift), (val))
 127
 128static u32 mdio_get_reg_field(u8 __iomem *base, u32 reg, u32 mask, u32 shift)
 129{
 130        u32 origin;
 131
 132        origin = mdio_read_reg(base, reg);
 133        return mdio_get_field(origin, mask, shift);
 134}
 135
 136#define MDIO_GET_REG_FIELD(dev, reg, mask, shift) \
 137                mdio_get_reg_field((dev)->vbase, (reg), (mask), (shift))
 138
 139#define MDIO_GET_REG_BIT(dev, reg, bit) \
 140                mdio_get_reg_field((dev)->vbase, (reg), 0x1ull, (bit))
 141
 142#define MDIO_CHECK_SET_ST       1
 143#define MDIO_CHECK_CLR_ST       0
 144
 145static int mdio_sc_cfg_reg_write(struct hns_mdio_device *mdio_dev,
 146                                 u32 cfg_reg, u32 set_val,
 147                                 u32 st_reg, u32 st_msk, u8 check_st)
 148{
 149        u32 time_cnt;
 150        u32 reg_value;
 151        int ret;
 152
 153        regmap_write(mdio_dev->subctrl_vbase, cfg_reg, set_val);
 154
 155        for (time_cnt = MDIO_TIMEOUT; time_cnt; time_cnt--) {
 156                ret = regmap_read(mdio_dev->subctrl_vbase, st_reg, &reg_value);
 157                if (ret)
 158                        return ret;
 159
 160                reg_value &= st_msk;
 161                if ((!!check_st) == (!!reg_value))
 162                        break;
 163        }
 164
 165        if ((!!check_st) != (!!reg_value))
 166                return -EBUSY;
 167
 168        return 0;
 169}
 170
 171static int hns_mdio_wait_ready(struct mii_bus *bus)
 172{
 173        struct hns_mdio_device *mdio_dev = bus->priv;
 174        u32 cmd_reg_value;
 175        int i;
 176
 177        /* waitting for MDIO_COMMAND_REG 's mdio_start==0 */
 178        /* after that can do read or write*/
 179        for (i = 0; i < MDIO_TIMEOUT; i++) {
 180                cmd_reg_value = MDIO_GET_REG_BIT(mdio_dev,
 181                                                 MDIO_COMMAND_REG,
 182                                                 MDIO_CMD_START_B);
 183                if (!cmd_reg_value)
 184                        break;
 185        }
 186        if ((i == MDIO_TIMEOUT) && cmd_reg_value)
 187                return -ETIMEDOUT;
 188
 189        return 0;
 190}
 191
 192static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev,
 193                               u8 is_c45, u8 op, u8 phy_id, u16 cmd)
 194{
 195        u32 cmd_reg_value;
 196        u8 st = is_c45 ? MDIO_ST_CLAUSE_45 : MDIO_ST_CLAUSE_22;
 197
 198        cmd_reg_value = st << MDIO_CMD_ST_S;
 199        cmd_reg_value |= op << MDIO_CMD_OP_S;
 200        cmd_reg_value |=
 201                (phy_id & MDIO_CMD_PRTAD_M) << MDIO_CMD_PRTAD_S;
 202        cmd_reg_value |= (cmd & MDIO_CMD_DEVAD_M) << MDIO_CMD_DEVAD_S;
 203        cmd_reg_value |= 1 << MDIO_CMD_START_B;
 204
 205        MDIO_WRITE_REG(mdio_dev, MDIO_COMMAND_REG, cmd_reg_value);
 206}
 207
 208/**
 209 * hns_mdio_write - access phy register
 210 * @bus: mdio bus
 211 * @phy_id: phy id
 212 * @regnum: register num
 213 * @value: register value
 214 *
 215 * Return 0 on success, negative on failure
 216 */
 217static int hns_mdio_write(struct mii_bus *bus,
 218                          int phy_id, int regnum, u16 data)
 219{
 220        int ret;
 221        struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
 222        u8 devad = ((regnum >> 16) & 0x1f);
 223        u8 is_c45 = !!(regnum & MII_ADDR_C45);
 224        u16 reg = (u16)(regnum & 0xffff);
 225        u8 op;
 226        u16 cmd_reg_cfg;
 227
 228        dev_dbg(&bus->dev, "mdio write %s,base is %p\n",
 229                bus->id, mdio_dev->vbase);
 230        dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x, write data=%d\n",
 231                phy_id, is_c45, devad, reg, data);
 232
 233        /* wait for ready */
 234        ret = hns_mdio_wait_ready(bus);
 235        if (ret) {
 236                dev_err(&bus->dev, "MDIO bus is busy\n");
 237                return ret;
 238        }
 239
 240        if (!is_c45) {
 241                cmd_reg_cfg = reg;
 242                op = MDIO_C22_WRITE;
 243        } else {
 244                /* config the cmd-reg to write addr*/
 245                MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
 246                                   MDIO_ADDR_DATA_S, reg);
 247
 248                hns_mdio_cmd_write(mdio_dev, is_c45,
 249                                   MDIO_C45_WRITE_ADDR, phy_id, devad);
 250
 251                /* check for read or write opt is finished */
 252                ret = hns_mdio_wait_ready(bus);
 253                if (ret) {
 254                        dev_err(&bus->dev, "MDIO bus is busy\n");
 255                        return ret;
 256                }
 257
 258                /* config the data needed writing */
 259                cmd_reg_cfg = devad;
 260                op = MDIO_C45_WRITE_DATA;
 261        }
 262
 263        MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M,
 264                           MDIO_WDATA_DATA_S, data);
 265
 266        hns_mdio_cmd_write(mdio_dev, is_c45, op, phy_id, cmd_reg_cfg);
 267
 268        return 0;
 269}
 270
 271/**
 272 * hns_mdio_read - access phy register
 273 * @bus: mdio bus
 274 * @phy_id: phy id
 275 * @regnum: register num
 276 * @value: register value
 277 *
 278 * Return phy register value
 279 */
 280static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
 281{
 282        int ret;
 283        u16 reg_val = 0;
 284        u8 devad = ((regnum >> 16) & 0x1f);
 285        u8 is_c45 = !!(regnum & MII_ADDR_C45);
 286        u16 reg = (u16)(regnum & 0xffff);
 287        struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
 288
 289        dev_dbg(&bus->dev, "mdio read %s,base is %p\n",
 290                bus->id, mdio_dev->vbase);
 291        dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x!\n",
 292                phy_id, is_c45, devad, reg);
 293
 294        /* Step 1: wait for ready */
 295        ret = hns_mdio_wait_ready(bus);
 296        if (ret) {
 297                dev_err(&bus->dev, "MDIO bus is busy\n");
 298                return ret;
 299        }
 300
 301        if (!is_c45) {
 302                hns_mdio_cmd_write(mdio_dev, is_c45,
 303                                   MDIO_C22_READ, phy_id, reg);
 304        } else {
 305                MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
 306                                   MDIO_ADDR_DATA_S, reg);
 307
 308                /* Step 2; config the cmd-reg to write addr*/
 309                hns_mdio_cmd_write(mdio_dev, is_c45,
 310                                   MDIO_C45_WRITE_ADDR, phy_id, devad);
 311
 312                /* Step 3: check for read or write opt is finished */
 313                ret = hns_mdio_wait_ready(bus);
 314                if (ret) {
 315                        dev_err(&bus->dev, "MDIO bus is busy\n");
 316                        return ret;
 317                }
 318
 319                hns_mdio_cmd_write(mdio_dev, is_c45,
 320                                   MDIO_C45_READ, phy_id, devad);
 321        }
 322
 323        /* Step 5: waitting for MDIO_COMMAND_REG 's mdio_start==0,*/
 324        /* check for read or write opt is finished */
 325        ret = hns_mdio_wait_ready(bus);
 326        if (ret) {
 327                dev_err(&bus->dev, "MDIO bus is busy\n");
 328                return ret;
 329        }
 330
 331        reg_val = MDIO_GET_REG_BIT(mdio_dev, MDIO_STA_REG, MDIO_STATE_STA_B);
 332        if (reg_val) {
 333                dev_err(&bus->dev, " ERROR! MDIO Read failed!\n");
 334                return -EBUSY;
 335        }
 336
 337        /* Step 6; get out data*/
 338        reg_val = (u16)MDIO_GET_REG_FIELD(mdio_dev, MDIO_RDATA_REG,
 339                                          MDIO_RDATA_DATA_M, MDIO_RDATA_DATA_S);
 340
 341        return reg_val;
 342}
 343
 344/**
 345 * hns_mdio_reset - reset mdio bus
 346 * @bus: mdio bus
 347 *
 348 * Return 0 on success, negative on failure
 349 */
 350static int hns_mdio_reset(struct mii_bus *bus)
 351{
 352        struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
 353        const struct hns_mdio_sc_reg *sc_reg;
 354        int ret;
 355
 356        if (dev_of_node(bus->parent)) {
 357                if (!mdio_dev->subctrl_vbase) {
 358                        dev_err(&bus->dev, "mdio sys ctl reg has not maped\n");
 359                        return -ENODEV;
 360                }
 361
 362                sc_reg = &mdio_dev->sc_reg;
 363                /* 1. reset req, and read reset st check */
 364                ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_reset_req,
 365                                            0x1, sc_reg->mdio_reset_st, 0x1,
 366                                            MDIO_CHECK_SET_ST);
 367                if (ret) {
 368                        dev_err(&bus->dev, "MDIO reset fail\n");
 369                        return ret;
 370                }
 371
 372                /* 2. dis clk, and read clk st check */
 373                ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_clk_dis,
 374                                            0x1, sc_reg->mdio_clk_st, 0x1,
 375                                            MDIO_CHECK_CLR_ST);
 376                if (ret) {
 377                        dev_err(&bus->dev, "MDIO dis clk fail\n");
 378                        return ret;
 379                }
 380
 381                /* 3. reset dreq, and read reset st check */
 382                ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_reset_dreq,
 383                                            0x1, sc_reg->mdio_reset_st, 0x1,
 384                                            MDIO_CHECK_CLR_ST);
 385                if (ret) {
 386                        dev_err(&bus->dev, "MDIO dis clk fail\n");
 387                        return ret;
 388                }
 389
 390                /* 4. en clk, and read clk st check */
 391                ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_clk_en,
 392                                            0x1, sc_reg->mdio_clk_st, 0x1,
 393                                            MDIO_CHECK_SET_ST);
 394                if (ret)
 395                        dev_err(&bus->dev, "MDIO en clk fail\n");
 396        } else if (is_acpi_node(bus->parent->fwnode)) {
 397                acpi_status s;
 398
 399                s = acpi_evaluate_object(ACPI_HANDLE(bus->parent),
 400                                         "_RST", NULL, NULL);
 401                if (ACPI_FAILURE(s)) {
 402                        dev_err(&bus->dev, "Reset failed, return:%#x\n", s);
 403                        ret = -EBUSY;
 404                } else {
 405                        ret = 0;
 406                }
 407        } else {
 408                dev_err(&bus->dev, "Can not get cfg data from DT or ACPI\n");
 409                ret = -ENXIO;
 410        }
 411        return ret;
 412}
 413
 414/**
 415 * hns_mdio_probe - probe mdio device
 416 * @pdev: mdio platform device
 417 *
 418 * Return 0 on success, negative on failure
 419 */
 420static int hns_mdio_probe(struct platform_device *pdev)
 421{
 422        struct hns_mdio_device *mdio_dev;
 423        struct mii_bus *new_bus;
 424        int ret = -ENODEV;
 425
 426        if (!pdev) {
 427                dev_err(NULL, "pdev is NULL!\r\n");
 428                return -ENODEV;
 429        }
 430
 431        mdio_dev = devm_kzalloc(&pdev->dev, sizeof(*mdio_dev), GFP_KERNEL);
 432        if (!mdio_dev)
 433                return -ENOMEM;
 434
 435        new_bus = devm_mdiobus_alloc(&pdev->dev);
 436        if (!new_bus) {
 437                dev_err(&pdev->dev, "mdiobus_alloc fail!\n");
 438                return -ENOMEM;
 439        }
 440
 441        new_bus->name = MDIO_BUS_NAME;
 442        new_bus->read = hns_mdio_read;
 443        new_bus->write = hns_mdio_write;
 444        new_bus->reset = hns_mdio_reset;
 445        new_bus->priv = mdio_dev;
 446        new_bus->parent = &pdev->dev;
 447
 448        mdio_dev->vbase = devm_platform_ioremap_resource(pdev, 0);
 449        if (IS_ERR(mdio_dev->vbase)) {
 450                ret = PTR_ERR(mdio_dev->vbase);
 451                return ret;
 452        }
 453
 454        platform_set_drvdata(pdev, new_bus);
 455        snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%s", "Mii",
 456                 dev_name(&pdev->dev));
 457        if (dev_of_node(&pdev->dev)) {
 458                struct of_phandle_args reg_args;
 459
 460                ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
 461                                                       "subctrl-vbase",
 462                                                       4,
 463                                                       0,
 464                                                       &reg_args);
 465                if (!ret) {
 466                        mdio_dev->subctrl_vbase =
 467                                syscon_node_to_regmap(reg_args.np);
 468                        if (IS_ERR(mdio_dev->subctrl_vbase)) {
 469                                dev_warn(&pdev->dev, "syscon_node_to_regmap error\n");
 470                                mdio_dev->subctrl_vbase = NULL;
 471                        } else {
 472                                if (reg_args.args_count == 4) {
 473                                        mdio_dev->sc_reg.mdio_clk_en =
 474                                                (u16)reg_args.args[0];
 475                                        mdio_dev->sc_reg.mdio_clk_dis =
 476                                                (u16)reg_args.args[0] + 4;
 477                                        mdio_dev->sc_reg.mdio_reset_req =
 478                                                (u16)reg_args.args[1];
 479                                        mdio_dev->sc_reg.mdio_reset_dreq =
 480                                                (u16)reg_args.args[1] + 4;
 481                                        mdio_dev->sc_reg.mdio_clk_st =
 482                                                (u16)reg_args.args[2];
 483                                        mdio_dev->sc_reg.mdio_reset_st =
 484                                                (u16)reg_args.args[3];
 485                                } else {
 486                                        /* for compatible */
 487                                        mdio_dev->sc_reg.mdio_clk_en =
 488                                                MDIO_SC_CLK_EN;
 489                                        mdio_dev->sc_reg.mdio_clk_dis =
 490                                                MDIO_SC_CLK_DIS;
 491                                        mdio_dev->sc_reg.mdio_reset_req =
 492                                                MDIO_SC_RESET_REQ;
 493                                        mdio_dev->sc_reg.mdio_reset_dreq =
 494                                                MDIO_SC_RESET_DREQ;
 495                                        mdio_dev->sc_reg.mdio_clk_st =
 496                                                MDIO_SC_CLK_ST;
 497                                        mdio_dev->sc_reg.mdio_reset_st =
 498                                                MDIO_SC_RESET_ST;
 499                                }
 500                        }
 501                } else {
 502                        dev_warn(&pdev->dev, "find syscon ret = %#x\n", ret);
 503                        mdio_dev->subctrl_vbase = NULL;
 504                }
 505
 506                ret = of_mdiobus_register(new_bus, pdev->dev.of_node);
 507        } else if (is_acpi_node(pdev->dev.fwnode)) {
 508                /* Clear all the IRQ properties */
 509                memset(new_bus->irq, PHY_POLL, 4 * PHY_MAX_ADDR);
 510
 511                /* Mask out all PHYs from auto probing. */
 512                new_bus->phy_mask = ~0;
 513
 514                /* Register the MDIO bus */
 515                ret = mdiobus_register(new_bus);
 516        } else {
 517                dev_err(&pdev->dev, "Can not get cfg data from DT or ACPI\n");
 518                ret = -ENXIO;
 519        }
 520
 521        if (ret) {
 522                dev_err(&pdev->dev, "Cannot register as MDIO bus!\n");
 523                platform_set_drvdata(pdev, NULL);
 524                return ret;
 525        }
 526
 527        return 0;
 528}
 529
 530/**
 531 * hns_mdio_remove - remove mdio device
 532 * @pdev: mdio platform device
 533 *
 534 * Return 0 on success, negative on failure
 535 */
 536static int hns_mdio_remove(struct platform_device *pdev)
 537{
 538        struct mii_bus *bus;
 539
 540        bus = platform_get_drvdata(pdev);
 541
 542        mdiobus_unregister(bus);
 543        platform_set_drvdata(pdev, NULL);
 544        return 0;
 545}
 546
 547static const struct of_device_id hns_mdio_match[] = {
 548        {.compatible = "hisilicon,mdio"},
 549        {.compatible = "hisilicon,hns-mdio"},
 550        {}
 551};
 552MODULE_DEVICE_TABLE(of, hns_mdio_match);
 553
 554static const struct acpi_device_id hns_mdio_acpi_match[] = {
 555        { "HISI0141", 0 },
 556        { },
 557};
 558MODULE_DEVICE_TABLE(acpi, hns_mdio_acpi_match);
 559
 560static struct platform_driver hns_mdio_driver = {
 561        .probe = hns_mdio_probe,
 562        .remove = hns_mdio_remove,
 563        .driver = {
 564                   .name = MDIO_DRV_NAME,
 565                   .of_match_table = hns_mdio_match,
 566                   .acpi_match_table = ACPI_PTR(hns_mdio_acpi_match),
 567                   },
 568};
 569
 570module_platform_driver(hns_mdio_driver);
 571
 572MODULE_LICENSE("GPL");
 573MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
 574MODULE_DESCRIPTION("Hisilicon HNS MDIO driver");
 575MODULE_ALIAS("platform:" MDIO_DRV_NAME);
 576