Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (c) 2014-2015 Hisilicon Limited.
0004  */
0005 
0006 #include <linux/acpi.h>
0007 #include <linux/errno.h>
0008 #include <linux/etherdevice.h>
0009 #include <linux/init.h>
0010 #include <linux/kernel.h>
0011 #include <linux/mfd/syscon.h>
0012 #include <linux/module.h>
0013 #include <linux/mutex.h>
0014 #include <linux/netdevice.h>
0015 #include <linux/of_address.h>
0016 #include <linux/of.h>
0017 #include <linux/of_mdio.h>
0018 #include <linux/of_platform.h>
0019 #include <linux/phy.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/regmap.h>
0022 
0023 #define MDIO_DRV_NAME "Hi-HNS_MDIO"
0024 #define MDIO_BUS_NAME "Hisilicon MII Bus"
0025 
0026 #define MDIO_TIMEOUT            1000000
0027 
0028 struct hns_mdio_sc_reg {
0029     u16 mdio_clk_en;
0030     u16 mdio_clk_dis;
0031     u16 mdio_reset_req;
0032     u16 mdio_reset_dreq;
0033     u16 mdio_clk_st;
0034     u16 mdio_reset_st;
0035 };
0036 
0037 struct hns_mdio_device {
0038     u8 __iomem *vbase;      /* mdio reg base address */
0039     struct regmap *subctrl_vbase;
0040     struct hns_mdio_sc_reg sc_reg;
0041 };
0042 
0043 /* mdio reg */
0044 #define MDIO_COMMAND_REG        0x0
0045 #define MDIO_ADDR_REG           0x4
0046 #define MDIO_WDATA_REG          0x8
0047 #define MDIO_RDATA_REG          0xc
0048 #define MDIO_STA_REG            0x10
0049 
0050 /* cfg phy bit map */
0051 #define MDIO_CMD_DEVAD_M    0x1f
0052 #define MDIO_CMD_DEVAD_S    0
0053 #define MDIO_CMD_PRTAD_M    0x1f
0054 #define MDIO_CMD_PRTAD_S    5
0055 #define MDIO_CMD_OP_S       10
0056 #define MDIO_CMD_ST_S       12
0057 #define MDIO_CMD_START_B    14
0058 
0059 #define MDIO_ADDR_DATA_M    0xffff
0060 #define MDIO_ADDR_DATA_S    0
0061 
0062 #define MDIO_WDATA_DATA_M   0xffff
0063 #define MDIO_WDATA_DATA_S   0
0064 
0065 #define MDIO_RDATA_DATA_M   0xffff
0066 #define MDIO_RDATA_DATA_S   0
0067 
0068 #define MDIO_STATE_STA_B    0
0069 
0070 enum mdio_st_clause {
0071     MDIO_ST_CLAUSE_45 = 0,
0072     MDIO_ST_CLAUSE_22
0073 };
0074 
0075 enum mdio_c22_op_seq {
0076     MDIO_C22_WRITE = 1,
0077     MDIO_C22_READ = 2
0078 };
0079 
0080 enum mdio_c45_op_seq {
0081     MDIO_C45_WRITE_ADDR = 0,
0082     MDIO_C45_WRITE_DATA,
0083     MDIO_C45_READ_INCREMENT,
0084     MDIO_C45_READ
0085 };
0086 
0087 /* peri subctrl reg */
0088 #define MDIO_SC_CLK_EN      0x338
0089 #define MDIO_SC_CLK_DIS     0x33C
0090 #define MDIO_SC_RESET_REQ   0xA38
0091 #define MDIO_SC_RESET_DREQ  0xA3C
0092 #define MDIO_SC_CLK_ST      0x531C
0093 #define MDIO_SC_RESET_ST    0x5A1C
0094 
0095 static void mdio_write_reg(u8 __iomem *base, u32 reg, u32 value)
0096 {
0097     writel_relaxed(value, base + reg);
0098 }
0099 
0100 #define MDIO_WRITE_REG(a, reg, value) \
0101     mdio_write_reg((a)->vbase, (reg), (value))
0102 
0103 static u32 mdio_read_reg(u8 __iomem *base, u32 reg)
0104 {
0105     return readl_relaxed(base + reg);
0106 }
0107 
0108 #define mdio_set_field(origin, mask, shift, val) \
0109     do { \
0110         (origin) &= (~((mask) << (shift))); \
0111         (origin) |= (((val) & (mask)) << (shift)); \
0112     } while (0)
0113 
0114 #define mdio_get_field(origin, mask, shift) (((origin) >> (shift)) & (mask))
0115 
0116 static void mdio_set_reg_field(u8 __iomem *base, u32 reg, u32 mask, u32 shift,
0117                    u32 val)
0118 {
0119     u32 origin = mdio_read_reg(base, reg);
0120 
0121     mdio_set_field(origin, mask, shift, val);
0122     mdio_write_reg(base, reg, origin);
0123 }
0124 
0125 #define MDIO_SET_REG_FIELD(dev, reg, mask, shift, val) \
0126     mdio_set_reg_field((dev)->vbase, (reg), (mask), (shift), (val))
0127 
0128 static u32 mdio_get_reg_field(u8 __iomem *base, u32 reg, u32 mask, u32 shift)
0129 {
0130     u32 origin;
0131 
0132     origin = mdio_read_reg(base, reg);
0133     return mdio_get_field(origin, mask, shift);
0134 }
0135 
0136 #define MDIO_GET_REG_FIELD(dev, reg, mask, shift) \
0137         mdio_get_reg_field((dev)->vbase, (reg), (mask), (shift))
0138 
0139 #define MDIO_GET_REG_BIT(dev, reg, bit) \
0140         mdio_get_reg_field((dev)->vbase, (reg), 0x1ull, (bit))
0141 
0142 #define MDIO_CHECK_SET_ST   1
0143 #define MDIO_CHECK_CLR_ST   0
0144 
0145 static int mdio_sc_cfg_reg_write(struct hns_mdio_device *mdio_dev,
0146                  u32 cfg_reg, u32 set_val,
0147                  u32 st_reg, u32 st_msk, u8 check_st)
0148 {
0149     u32 time_cnt;
0150     u32 reg_value;
0151     int ret;
0152 
0153     regmap_write(mdio_dev->subctrl_vbase, cfg_reg, set_val);
0154 
0155     for (time_cnt = MDIO_TIMEOUT; time_cnt; time_cnt--) {
0156         ret = regmap_read(mdio_dev->subctrl_vbase, st_reg, &reg_value);
0157         if (ret)
0158             return ret;
0159 
0160         reg_value &= st_msk;
0161         if ((!!check_st) == (!!reg_value))
0162             break;
0163     }
0164 
0165     if ((!!check_st) != (!!reg_value))
0166         return -EBUSY;
0167 
0168     return 0;
0169 }
0170 
0171 static int hns_mdio_wait_ready(struct mii_bus *bus)
0172 {
0173     struct hns_mdio_device *mdio_dev = bus->priv;
0174     u32 cmd_reg_value;
0175     int i;
0176 
0177     /* waiting for MDIO_COMMAND_REG's mdio_start==0 */
0178     /* after that can do read or write*/
0179     for (i = 0; i < MDIO_TIMEOUT; i++) {
0180         cmd_reg_value = MDIO_GET_REG_BIT(mdio_dev,
0181                          MDIO_COMMAND_REG,
0182                          MDIO_CMD_START_B);
0183         if (!cmd_reg_value)
0184             break;
0185     }
0186     if ((i == MDIO_TIMEOUT) && cmd_reg_value)
0187         return -ETIMEDOUT;
0188 
0189     return 0;
0190 }
0191 
0192 static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev,
0193                    u8 is_c45, u8 op, u8 phy_id, u16 cmd)
0194 {
0195     u32 cmd_reg_value;
0196     u8 st = is_c45 ? MDIO_ST_CLAUSE_45 : MDIO_ST_CLAUSE_22;
0197 
0198     cmd_reg_value = st << MDIO_CMD_ST_S;
0199     cmd_reg_value |= op << MDIO_CMD_OP_S;
0200     cmd_reg_value |=
0201         (phy_id & MDIO_CMD_PRTAD_M) << MDIO_CMD_PRTAD_S;
0202     cmd_reg_value |= (cmd & MDIO_CMD_DEVAD_M) << MDIO_CMD_DEVAD_S;
0203     cmd_reg_value |= 1 << MDIO_CMD_START_B;
0204 
0205     MDIO_WRITE_REG(mdio_dev, MDIO_COMMAND_REG, cmd_reg_value);
0206 }
0207 
0208 /**
0209  * hns_mdio_write - access phy register
0210  * @bus: mdio bus
0211  * @phy_id: phy id
0212  * @regnum: register num
0213  * @data: register value
0214  *
0215  * Return 0 on success, negative on failure
0216  */
0217 static int hns_mdio_write(struct mii_bus *bus,
0218               int phy_id, int regnum, u16 data)
0219 {
0220     int ret;
0221     struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
0222     u8 devad = ((regnum >> 16) & 0x1f);
0223     u8 is_c45 = !!(regnum & MII_ADDR_C45);
0224     u16 reg = (u16)(regnum & 0xffff);
0225     u8 op;
0226     u16 cmd_reg_cfg;
0227 
0228     dev_dbg(&bus->dev, "mdio write %s,base is %p\n",
0229         bus->id, mdio_dev->vbase);
0230     dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x, write data=%d\n",
0231         phy_id, is_c45, devad, reg, data);
0232 
0233     /* wait for ready */
0234     ret = hns_mdio_wait_ready(bus);
0235     if (ret) {
0236         dev_err(&bus->dev, "MDIO bus is busy\n");
0237         return ret;
0238     }
0239 
0240     if (!is_c45) {
0241         cmd_reg_cfg = reg;
0242         op = MDIO_C22_WRITE;
0243     } else {
0244         /* config the cmd-reg to write addr*/
0245         MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
0246                    MDIO_ADDR_DATA_S, reg);
0247 
0248         hns_mdio_cmd_write(mdio_dev, is_c45,
0249                    MDIO_C45_WRITE_ADDR, phy_id, devad);
0250 
0251         /* check for read or write opt is finished */
0252         ret = hns_mdio_wait_ready(bus);
0253         if (ret) {
0254             dev_err(&bus->dev, "MDIO bus is busy\n");
0255             return ret;
0256         }
0257 
0258         /* config the data needed writing */
0259         cmd_reg_cfg = devad;
0260         op = MDIO_C45_WRITE_DATA;
0261     }
0262 
0263     MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M,
0264                MDIO_WDATA_DATA_S, data);
0265 
0266     hns_mdio_cmd_write(mdio_dev, is_c45, op, phy_id, cmd_reg_cfg);
0267 
0268     return 0;
0269 }
0270 
0271 /**
0272  * hns_mdio_read - access phy register
0273  * @bus: mdio bus
0274  * @phy_id: phy id
0275  * @regnum: register num
0276  *
0277  * Return phy register value
0278  */
0279 static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
0280 {
0281     int ret;
0282     u16 reg_val;
0283     u8 devad = ((regnum >> 16) & 0x1f);
0284     u8 is_c45 = !!(regnum & MII_ADDR_C45);
0285     u16 reg = (u16)(regnum & 0xffff);
0286     struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
0287 
0288     dev_dbg(&bus->dev, "mdio read %s,base is %p\n",
0289         bus->id, mdio_dev->vbase);
0290     dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x!\n",
0291         phy_id, is_c45, devad, reg);
0292 
0293     /* Step 1: wait for ready */
0294     ret = hns_mdio_wait_ready(bus);
0295     if (ret) {
0296         dev_err(&bus->dev, "MDIO bus is busy\n");
0297         return ret;
0298     }
0299 
0300     if (!is_c45) {
0301         hns_mdio_cmd_write(mdio_dev, is_c45,
0302                    MDIO_C22_READ, phy_id, reg);
0303     } else {
0304         MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M,
0305                    MDIO_ADDR_DATA_S, reg);
0306 
0307         /* Step 2; config the cmd-reg to write addr*/
0308         hns_mdio_cmd_write(mdio_dev, is_c45,
0309                    MDIO_C45_WRITE_ADDR, phy_id, devad);
0310 
0311         /* Step 3: check for read or write opt is finished */
0312         ret = hns_mdio_wait_ready(bus);
0313         if (ret) {
0314             dev_err(&bus->dev, "MDIO bus is busy\n");
0315             return ret;
0316         }
0317 
0318         hns_mdio_cmd_write(mdio_dev, is_c45,
0319                    MDIO_C45_READ, phy_id, devad);
0320     }
0321 
0322     /* Step 5: waiting for MDIO_COMMAND_REG's mdio_start==0,*/
0323     /* check for read or write opt is finished */
0324     ret = hns_mdio_wait_ready(bus);
0325     if (ret) {
0326         dev_err(&bus->dev, "MDIO bus is busy\n");
0327         return ret;
0328     }
0329 
0330     reg_val = MDIO_GET_REG_BIT(mdio_dev, MDIO_STA_REG, MDIO_STATE_STA_B);
0331     if (reg_val) {
0332         dev_err(&bus->dev, " ERROR! MDIO Read failed!\n");
0333         return -EBUSY;
0334     }
0335 
0336     /* Step 6; get out data*/
0337     reg_val = (u16)MDIO_GET_REG_FIELD(mdio_dev, MDIO_RDATA_REG,
0338                       MDIO_RDATA_DATA_M, MDIO_RDATA_DATA_S);
0339 
0340     return reg_val;
0341 }
0342 
0343 /**
0344  * hns_mdio_reset - reset mdio bus
0345  * @bus: mdio bus
0346  *
0347  * Return 0 on success, negative on failure
0348  */
0349 static int hns_mdio_reset(struct mii_bus *bus)
0350 {
0351     struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv;
0352     const struct hns_mdio_sc_reg *sc_reg;
0353     int ret;
0354 
0355     if (dev_of_node(bus->parent)) {
0356         if (!mdio_dev->subctrl_vbase) {
0357             dev_err(&bus->dev, "mdio sys ctl reg has not mapped\n");
0358             return -ENODEV;
0359         }
0360 
0361         sc_reg = &mdio_dev->sc_reg;
0362         /* 1. reset req, and read reset st check */
0363         ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_reset_req,
0364                         0x1, sc_reg->mdio_reset_st, 0x1,
0365                         MDIO_CHECK_SET_ST);
0366         if (ret) {
0367             dev_err(&bus->dev, "MDIO reset fail\n");
0368             return ret;
0369         }
0370 
0371         /* 2. dis clk, and read clk st check */
0372         ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_clk_dis,
0373                         0x1, sc_reg->mdio_clk_st, 0x1,
0374                         MDIO_CHECK_CLR_ST);
0375         if (ret) {
0376             dev_err(&bus->dev, "MDIO dis clk fail\n");
0377             return ret;
0378         }
0379 
0380         /* 3. reset dreq, and read reset st check */
0381         ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_reset_dreq,
0382                         0x1, sc_reg->mdio_reset_st, 0x1,
0383                         MDIO_CHECK_CLR_ST);
0384         if (ret) {
0385             dev_err(&bus->dev, "MDIO dis clk fail\n");
0386             return ret;
0387         }
0388 
0389         /* 4. en clk, and read clk st check */
0390         ret = mdio_sc_cfg_reg_write(mdio_dev, sc_reg->mdio_clk_en,
0391                         0x1, sc_reg->mdio_clk_st, 0x1,
0392                         MDIO_CHECK_SET_ST);
0393         if (ret)
0394             dev_err(&bus->dev, "MDIO en clk fail\n");
0395     } else if (is_acpi_node(bus->parent->fwnode)) {
0396         acpi_status s;
0397 
0398         s = acpi_evaluate_object(ACPI_HANDLE(bus->parent),
0399                      "_RST", NULL, NULL);
0400         if (ACPI_FAILURE(s)) {
0401             dev_err(&bus->dev, "Reset failed, return:%#x\n", s);
0402             ret = -EBUSY;
0403         } else {
0404             ret = 0;
0405         }
0406     } else {
0407         dev_err(&bus->dev, "Can not get cfg data from DT or ACPI\n");
0408         ret = -ENXIO;
0409     }
0410     return ret;
0411 }
0412 
0413 /**
0414  * hns_mdio_probe - probe mdio device
0415  * @pdev: mdio platform device
0416  *
0417  * Return 0 on success, negative on failure
0418  */
0419 static int hns_mdio_probe(struct platform_device *pdev)
0420 {
0421     struct hns_mdio_device *mdio_dev;
0422     struct mii_bus *new_bus;
0423     int ret;
0424 
0425     if (!pdev) {
0426         dev_err(NULL, "pdev is NULL!\r\n");
0427         return -ENODEV;
0428     }
0429 
0430     mdio_dev = devm_kzalloc(&pdev->dev, sizeof(*mdio_dev), GFP_KERNEL);
0431     if (!mdio_dev)
0432         return -ENOMEM;
0433 
0434     new_bus = devm_mdiobus_alloc(&pdev->dev);
0435     if (!new_bus) {
0436         dev_err(&pdev->dev, "mdiobus_alloc fail!\n");
0437         return -ENOMEM;
0438     }
0439 
0440     new_bus->name = MDIO_BUS_NAME;
0441     new_bus->read = hns_mdio_read;
0442     new_bus->write = hns_mdio_write;
0443     new_bus->reset = hns_mdio_reset;
0444     new_bus->priv = mdio_dev;
0445     new_bus->parent = &pdev->dev;
0446 
0447     mdio_dev->vbase = devm_platform_ioremap_resource(pdev, 0);
0448     if (IS_ERR(mdio_dev->vbase)) {
0449         ret = PTR_ERR(mdio_dev->vbase);
0450         return ret;
0451     }
0452 
0453     platform_set_drvdata(pdev, new_bus);
0454     snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%s", "Mii",
0455          dev_name(&pdev->dev));
0456     if (dev_of_node(&pdev->dev)) {
0457         struct of_phandle_args reg_args;
0458 
0459         ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
0460                                "subctrl-vbase",
0461                                4,
0462                                0,
0463                                &reg_args);
0464         if (!ret) {
0465             mdio_dev->subctrl_vbase =
0466                 syscon_node_to_regmap(reg_args.np);
0467             if (IS_ERR(mdio_dev->subctrl_vbase)) {
0468                 dev_warn(&pdev->dev, "syscon_node_to_regmap error\n");
0469                 mdio_dev->subctrl_vbase = NULL;
0470             } else {
0471                 if (reg_args.args_count == 4) {
0472                     mdio_dev->sc_reg.mdio_clk_en =
0473                         (u16)reg_args.args[0];
0474                     mdio_dev->sc_reg.mdio_clk_dis =
0475                         (u16)reg_args.args[0] + 4;
0476                     mdio_dev->sc_reg.mdio_reset_req =
0477                         (u16)reg_args.args[1];
0478                     mdio_dev->sc_reg.mdio_reset_dreq =
0479                         (u16)reg_args.args[1] + 4;
0480                     mdio_dev->sc_reg.mdio_clk_st =
0481                         (u16)reg_args.args[2];
0482                     mdio_dev->sc_reg.mdio_reset_st =
0483                         (u16)reg_args.args[3];
0484                 } else {
0485                     /* for compatible */
0486                     mdio_dev->sc_reg.mdio_clk_en =
0487                         MDIO_SC_CLK_EN;
0488                     mdio_dev->sc_reg.mdio_clk_dis =
0489                         MDIO_SC_CLK_DIS;
0490                     mdio_dev->sc_reg.mdio_reset_req =
0491                         MDIO_SC_RESET_REQ;
0492                     mdio_dev->sc_reg.mdio_reset_dreq =
0493                         MDIO_SC_RESET_DREQ;
0494                     mdio_dev->sc_reg.mdio_clk_st =
0495                         MDIO_SC_CLK_ST;
0496                     mdio_dev->sc_reg.mdio_reset_st =
0497                         MDIO_SC_RESET_ST;
0498                 }
0499             }
0500         } else {
0501             dev_warn(&pdev->dev, "find syscon ret = %#x\n", ret);
0502             mdio_dev->subctrl_vbase = NULL;
0503         }
0504 
0505         ret = of_mdiobus_register(new_bus, pdev->dev.of_node);
0506     } else if (is_acpi_node(pdev->dev.fwnode)) {
0507         /* Clear all the IRQ properties */
0508         memset(new_bus->irq, PHY_POLL, 4 * PHY_MAX_ADDR);
0509 
0510         /* Mask out all PHYs from auto probing. */
0511         new_bus->phy_mask = ~0;
0512 
0513         /* Register the MDIO bus */
0514         ret = mdiobus_register(new_bus);
0515     } else {
0516         dev_err(&pdev->dev, "Can not get cfg data from DT or ACPI\n");
0517         ret = -ENXIO;
0518     }
0519 
0520     if (ret) {
0521         dev_err(&pdev->dev, "Cannot register as MDIO bus!\n");
0522         platform_set_drvdata(pdev, NULL);
0523         return ret;
0524     }
0525 
0526     return 0;
0527 }
0528 
0529 /**
0530  * hns_mdio_remove - remove mdio device
0531  * @pdev: mdio platform device
0532  *
0533  * Return 0 on success, negative on failure
0534  */
0535 static int hns_mdio_remove(struct platform_device *pdev)
0536 {
0537     struct mii_bus *bus;
0538 
0539     bus = platform_get_drvdata(pdev);
0540 
0541     mdiobus_unregister(bus);
0542     platform_set_drvdata(pdev, NULL);
0543     return 0;
0544 }
0545 
0546 static const struct of_device_id hns_mdio_match[] = {
0547     {.compatible = "hisilicon,mdio"},
0548     {.compatible = "hisilicon,hns-mdio"},
0549     {}
0550 };
0551 MODULE_DEVICE_TABLE(of, hns_mdio_match);
0552 
0553 static const struct acpi_device_id hns_mdio_acpi_match[] = {
0554     { "HISI0141", 0 },
0555     { },
0556 };
0557 MODULE_DEVICE_TABLE(acpi, hns_mdio_acpi_match);
0558 
0559 static struct platform_driver hns_mdio_driver = {
0560     .probe = hns_mdio_probe,
0561     .remove = hns_mdio_remove,
0562     .driver = {
0563            .name = MDIO_DRV_NAME,
0564            .of_match_table = hns_mdio_match,
0565            .acpi_match_table = ACPI_PTR(hns_mdio_acpi_match),
0566            },
0567 };
0568 
0569 module_platform_driver(hns_mdio_driver);
0570 
0571 MODULE_LICENSE("GPL");
0572 MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
0573 MODULE_DESCRIPTION("Hisilicon HNS MDIO driver");
0574 MODULE_ALIAS("platform:" MDIO_DRV_NAME);