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