linux/drivers/net/ethernet/marvell/mvmdio.c
<<
>>
Prefs
   1/*
   2 * Driver for the MDIO interface of Marvell network interfaces.
   3 *
   4 * Since the MDIO interface of Marvell network interfaces is shared
   5 * between all network interfaces, having a single driver allows to
   6 * handle concurrent accesses properly (you may have four Ethernet
   7 * ports, but they in fact share the same SMI interface to access
   8 * the MDIO bus). This driver is currently used by the mvneta and
   9 * mv643xx_eth drivers.
  10 *
  11 * Copyright (C) 2012 Marvell
  12 *
  13 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
  14 *
  15 * This file is licensed under the terms of the GNU General Public
  16 * License version 2. This program is licensed "as is" without any
  17 * warranty of any kind, whether express or implied.
  18 */
  19
  20#include <linux/clk.h>
  21#include <linux/delay.h>
  22#include <linux/interrupt.h>
  23#include <linux/io.h>
  24#include <linux/kernel.h>
  25#include <linux/module.h>
  26#include <linux/of_device.h>
  27#include <linux/of_mdio.h>
  28#include <linux/phy.h>
  29#include <linux/platform_device.h>
  30#include <linux/sched.h>
  31#include <linux/wait.h>
  32
  33#define MVMDIO_SMI_DATA_SHIFT           0
  34#define MVMDIO_SMI_PHY_ADDR_SHIFT       16
  35#define MVMDIO_SMI_PHY_REG_SHIFT        21
  36#define MVMDIO_SMI_READ_OPERATION       BIT(26)
  37#define MVMDIO_SMI_WRITE_OPERATION      0
  38#define MVMDIO_SMI_READ_VALID           BIT(27)
  39#define MVMDIO_SMI_BUSY                 BIT(28)
  40#define MVMDIO_ERR_INT_CAUSE            0x007C
  41#define  MVMDIO_ERR_INT_SMI_DONE        0x00000010
  42#define MVMDIO_ERR_INT_MASK             0x0080
  43
  44#define MVMDIO_XSMI_MGNT_REG            0x0
  45#define  MVMDIO_XSMI_PHYADDR_SHIFT      16
  46#define  MVMDIO_XSMI_DEVADDR_SHIFT      21
  47#define  MVMDIO_XSMI_WRITE_OPERATION    (0x5 << 26)
  48#define  MVMDIO_XSMI_READ_OPERATION     (0x7 << 26)
  49#define  MVMDIO_XSMI_READ_VALID         BIT(29)
  50#define  MVMDIO_XSMI_BUSY               BIT(30)
  51#define MVMDIO_XSMI_ADDR_REG            0x8
  52
  53/*
  54 * SMI Timeout measurements:
  55 * - Kirkwood 88F6281 (Globalscale Dreamplug): 45us to 95us (Interrupt)
  56 * - Armada 370       (Globalscale Mirabox):   41us to 43us (Polled)
  57 */
  58#define MVMDIO_SMI_TIMEOUT              1000 /* 1000us = 1ms */
  59#define MVMDIO_SMI_POLL_INTERVAL_MIN    45
  60#define MVMDIO_SMI_POLL_INTERVAL_MAX    55
  61
  62#define MVMDIO_XSMI_POLL_INTERVAL_MIN   150
  63#define MVMDIO_XSMI_POLL_INTERVAL_MAX   160
  64
  65struct orion_mdio_dev {
  66        void __iomem *regs;
  67        struct clk *clk[4];
  68        /*
  69         * If we have access to the error interrupt pin (which is
  70         * somewhat misnamed as it not only reflects internal errors
  71         * but also reflects SMI completion), use that to wait for
  72         * SMI access completion instead of polling the SMI busy bit.
  73         */
  74        int err_interrupt;
  75        wait_queue_head_t smi_busy_wait;
  76};
  77
  78enum orion_mdio_bus_type {
  79        BUS_TYPE_SMI,
  80        BUS_TYPE_XSMI
  81};
  82
  83struct orion_mdio_ops {
  84        int (*is_done)(struct orion_mdio_dev *);
  85        unsigned int poll_interval_min;
  86        unsigned int poll_interval_max;
  87};
  88
  89/* Wait for the SMI unit to be ready for another operation
  90 */
  91static int orion_mdio_wait_ready(const struct orion_mdio_ops *ops,
  92                                 struct mii_bus *bus)
  93{
  94        struct orion_mdio_dev *dev = bus->priv;
  95        unsigned long timeout = usecs_to_jiffies(MVMDIO_SMI_TIMEOUT);
  96        unsigned long end = jiffies + timeout;
  97        int timedout = 0;
  98
  99        while (1) {
 100                if (ops->is_done(dev))
 101                        return 0;
 102                else if (timedout)
 103                        break;
 104
 105                if (dev->err_interrupt <= 0) {
 106                        usleep_range(ops->poll_interval_min,
 107                                     ops->poll_interval_max);
 108
 109                        if (time_is_before_jiffies(end))
 110                                ++timedout;
 111                } else {
 112                        /* wait_event_timeout does not guarantee a delay of at
 113                         * least one whole jiffie, so timeout must be no less
 114                         * than two.
 115                         */
 116                        if (timeout < 2)
 117                                timeout = 2;
 118                        wait_event_timeout(dev->smi_busy_wait,
 119                                           ops->is_done(dev), timeout);
 120
 121                        ++timedout;
 122                }
 123        }
 124
 125        dev_err(bus->parent, "Timeout: SMI busy for too long\n");
 126        return  -ETIMEDOUT;
 127}
 128
 129static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
 130{
 131        return !(readl(dev->regs) & MVMDIO_SMI_BUSY);
 132}
 133
 134static const struct orion_mdio_ops orion_mdio_smi_ops = {
 135        .is_done = orion_mdio_smi_is_done,
 136        .poll_interval_min = MVMDIO_SMI_POLL_INTERVAL_MIN,
 137        .poll_interval_max = MVMDIO_SMI_POLL_INTERVAL_MAX,
 138};
 139
 140static int orion_mdio_smi_read(struct mii_bus *bus, int mii_id,
 141                               int regnum)
 142{
 143        struct orion_mdio_dev *dev = bus->priv;
 144        u32 val;
 145        int ret;
 146
 147        if (regnum & MII_ADDR_C45)
 148                return -EOPNOTSUPP;
 149
 150        ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus);
 151        if (ret < 0)
 152                return ret;
 153
 154        writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
 155                (regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
 156                MVMDIO_SMI_READ_OPERATION),
 157               dev->regs);
 158
 159        ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus);
 160        if (ret < 0)
 161                return ret;
 162
 163        val = readl(dev->regs);
 164        if (!(val & MVMDIO_SMI_READ_VALID)) {
 165                dev_err(bus->parent, "SMI bus read not valid\n");
 166                return -ENODEV;
 167        }
 168
 169        return val & GENMASK(15, 0);
 170}
 171
 172static int orion_mdio_smi_write(struct mii_bus *bus, int mii_id,
 173                                int regnum, u16 value)
 174{
 175        struct orion_mdio_dev *dev = bus->priv;
 176        int ret;
 177
 178        if (regnum & MII_ADDR_C45)
 179                return -EOPNOTSUPP;
 180
 181        ret = orion_mdio_wait_ready(&orion_mdio_smi_ops, bus);
 182        if (ret < 0)
 183                return ret;
 184
 185        writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
 186                (regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
 187                MVMDIO_SMI_WRITE_OPERATION            |
 188                (value << MVMDIO_SMI_DATA_SHIFT)),
 189               dev->regs);
 190
 191        return 0;
 192}
 193
 194static int orion_mdio_xsmi_is_done(struct orion_mdio_dev *dev)
 195{
 196        return !(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & MVMDIO_XSMI_BUSY);
 197}
 198
 199static const struct orion_mdio_ops orion_mdio_xsmi_ops = {
 200        .is_done = orion_mdio_xsmi_is_done,
 201        .poll_interval_min = MVMDIO_XSMI_POLL_INTERVAL_MIN,
 202        .poll_interval_max = MVMDIO_XSMI_POLL_INTERVAL_MAX,
 203};
 204
 205static int orion_mdio_xsmi_read(struct mii_bus *bus, int mii_id,
 206                                int regnum)
 207{
 208        struct orion_mdio_dev *dev = bus->priv;
 209        u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
 210        int ret;
 211
 212        if (!(regnum & MII_ADDR_C45))
 213                return -EOPNOTSUPP;
 214
 215        ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus);
 216        if (ret < 0)
 217                return ret;
 218
 219        writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
 220        writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
 221               (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
 222               MVMDIO_XSMI_READ_OPERATION,
 223               dev->regs + MVMDIO_XSMI_MGNT_REG);
 224
 225        ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus);
 226        if (ret < 0)
 227                return ret;
 228
 229        if (!(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) &
 230              MVMDIO_XSMI_READ_VALID)) {
 231                dev_err(bus->parent, "XSMI bus read not valid\n");
 232                return -ENODEV;
 233        }
 234
 235        return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0);
 236}
 237
 238static int orion_mdio_xsmi_write(struct mii_bus *bus, int mii_id,
 239                                int regnum, u16 value)
 240{
 241        struct orion_mdio_dev *dev = bus->priv;
 242        u16 dev_addr = (regnum >> 16) & GENMASK(4, 0);
 243        int ret;
 244
 245        if (!(regnum & MII_ADDR_C45))
 246                return -EOPNOTSUPP;
 247
 248        ret = orion_mdio_wait_ready(&orion_mdio_xsmi_ops, bus);
 249        if (ret < 0)
 250                return ret;
 251
 252        writel(regnum & GENMASK(15, 0), dev->regs + MVMDIO_XSMI_ADDR_REG);
 253        writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
 254               (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
 255               MVMDIO_XSMI_WRITE_OPERATION | value,
 256               dev->regs + MVMDIO_XSMI_MGNT_REG);
 257
 258        return 0;
 259}
 260
 261static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id)
 262{
 263        struct orion_mdio_dev *dev = dev_id;
 264
 265        if (readl(dev->regs + MVMDIO_ERR_INT_CAUSE) &
 266                        MVMDIO_ERR_INT_SMI_DONE) {
 267                writel(~MVMDIO_ERR_INT_SMI_DONE,
 268                                dev->regs + MVMDIO_ERR_INT_CAUSE);
 269                wake_up(&dev->smi_busy_wait);
 270                return IRQ_HANDLED;
 271        }
 272
 273        return IRQ_NONE;
 274}
 275
 276static int orion_mdio_probe(struct platform_device *pdev)
 277{
 278        enum orion_mdio_bus_type type;
 279        struct resource *r;
 280        struct mii_bus *bus;
 281        struct orion_mdio_dev *dev;
 282        int i, ret;
 283
 284        type = (enum orion_mdio_bus_type)of_device_get_match_data(&pdev->dev);
 285
 286        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 287        if (!r) {
 288                dev_err(&pdev->dev, "No SMI register address given\n");
 289                return -ENODEV;
 290        }
 291
 292        bus = devm_mdiobus_alloc_size(&pdev->dev,
 293                                      sizeof(struct orion_mdio_dev));
 294        if (!bus)
 295                return -ENOMEM;
 296
 297        switch (type) {
 298        case BUS_TYPE_SMI:
 299                bus->read = orion_mdio_smi_read;
 300                bus->write = orion_mdio_smi_write;
 301                break;
 302        case BUS_TYPE_XSMI:
 303                bus->read = orion_mdio_xsmi_read;
 304                bus->write = orion_mdio_xsmi_write;
 305                break;
 306        }
 307
 308        bus->name = "orion_mdio_bus";
 309        snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii",
 310                 dev_name(&pdev->dev));
 311        bus->parent = &pdev->dev;
 312
 313        dev = bus->priv;
 314        dev->regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
 315        if (!dev->regs) {
 316                dev_err(&pdev->dev, "Unable to remap SMI register\n");
 317                return -ENODEV;
 318        }
 319
 320        init_waitqueue_head(&dev->smi_busy_wait);
 321
 322        if (pdev->dev.of_node) {
 323                for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
 324                        dev->clk[i] = of_clk_get(pdev->dev.of_node, i);
 325                        if (PTR_ERR(dev->clk[i]) == -EPROBE_DEFER) {
 326                                ret = -EPROBE_DEFER;
 327                                goto out_clk;
 328                        }
 329                        if (IS_ERR(dev->clk[i]))
 330                                break;
 331                        clk_prepare_enable(dev->clk[i]);
 332                }
 333
 334                if (!IS_ERR(of_clk_get(pdev->dev.of_node,
 335                                       ARRAY_SIZE(dev->clk))))
 336                        dev_warn(&pdev->dev,
 337                                 "unsupported number of clocks, limiting to the first "
 338                                 __stringify(ARRAY_SIZE(dev->clk)) "\n");
 339        } else {
 340                dev->clk[0] = clk_get(&pdev->dev, NULL);
 341                if (PTR_ERR(dev->clk[0]) == -EPROBE_DEFER) {
 342                        ret = -EPROBE_DEFER;
 343                        goto out_clk;
 344                }
 345                if (!IS_ERR(dev->clk[0]))
 346                        clk_prepare_enable(dev->clk[0]);
 347        }
 348
 349
 350        dev->err_interrupt = platform_get_irq(pdev, 0);
 351        if (dev->err_interrupt > 0 &&
 352            resource_size(r) < MVMDIO_ERR_INT_MASK + 4) {
 353                dev_err(&pdev->dev,
 354                        "disabling interrupt, resource size is too small\n");
 355                dev->err_interrupt = 0;
 356        }
 357        if (dev->err_interrupt > 0) {
 358                ret = devm_request_irq(&pdev->dev, dev->err_interrupt,
 359                                        orion_mdio_err_irq,
 360                                        IRQF_SHARED, pdev->name, dev);
 361                if (ret)
 362                        goto out_mdio;
 363
 364                writel(MVMDIO_ERR_INT_SMI_DONE,
 365                        dev->regs + MVMDIO_ERR_INT_MASK);
 366
 367        } else if (dev->err_interrupt == -EPROBE_DEFER) {
 368                ret = -EPROBE_DEFER;
 369                goto out_mdio;
 370        }
 371
 372        ret = of_mdiobus_register(bus, pdev->dev.of_node);
 373        if (ret < 0) {
 374                dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret);
 375                goto out_mdio;
 376        }
 377
 378        platform_set_drvdata(pdev, bus);
 379
 380        return 0;
 381
 382out_mdio:
 383        if (dev->err_interrupt > 0)
 384                writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
 385
 386out_clk:
 387        for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
 388                if (IS_ERR(dev->clk[i]))
 389                        break;
 390                clk_disable_unprepare(dev->clk[i]);
 391                clk_put(dev->clk[i]);
 392        }
 393
 394        return ret;
 395}
 396
 397static int orion_mdio_remove(struct platform_device *pdev)
 398{
 399        struct mii_bus *bus = platform_get_drvdata(pdev);
 400        struct orion_mdio_dev *dev = bus->priv;
 401        int i;
 402
 403        if (dev->err_interrupt > 0)
 404                writel(0, dev->regs + MVMDIO_ERR_INT_MASK);
 405        mdiobus_unregister(bus);
 406
 407        for (i = 0; i < ARRAY_SIZE(dev->clk); i++) {
 408                if (IS_ERR(dev->clk[i]))
 409                        break;
 410                clk_disable_unprepare(dev->clk[i]);
 411                clk_put(dev->clk[i]);
 412        }
 413
 414        return 0;
 415}
 416
 417static const struct of_device_id orion_mdio_match[] = {
 418        { .compatible = "marvell,orion-mdio", .data = (void *)BUS_TYPE_SMI },
 419        { .compatible = "marvell,xmdio", .data = (void *)BUS_TYPE_XSMI },
 420        { }
 421};
 422MODULE_DEVICE_TABLE(of, orion_mdio_match);
 423
 424static struct platform_driver orion_mdio_driver = {
 425        .probe = orion_mdio_probe,
 426        .remove = orion_mdio_remove,
 427        .driver = {
 428                .name = "orion-mdio",
 429                .of_match_table = orion_mdio_match,
 430        },
 431};
 432
 433module_platform_driver(orion_mdio_driver);
 434
 435MODULE_DESCRIPTION("Marvell MDIO interface driver");
 436MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
 437MODULE_LICENSE("GPL");
 438MODULE_ALIAS("platform:orion-mdio");
 439