linux/drivers/net/ethernet/ibm/emac/rgmii.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * drivers/net/ethernet/ibm/emac/rgmii.c
   4 *
   5 * Driver for PowerPC 4xx on-chip ethernet controller, RGMII bridge support.
   6 *
   7 * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
   8 *                <benh@kernel.crashing.org>
   9 *
  10 * Based on the arch/ppc version of the driver:
  11 *
  12 * Copyright (c) 2004, 2005 Zultys Technologies.
  13 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
  14 *
  15 * Based on original work by
  16 *      Matt Porter <mporter@kernel.crashing.org>
  17 *      Copyright 2004 MontaVista Software, Inc.
  18 */
  19#include <linux/slab.h>
  20#include <linux/kernel.h>
  21#include <linux/ethtool.h>
  22#include <linux/of_address.h>
  23#include <asm/io.h>
  24
  25#include "emac.h"
  26#include "debug.h"
  27
  28// XXX FIXME: Axon seems to support a subset of the RGMII, we
  29// thus need to take that into account and possibly change some
  30// of the bit settings below that don't seem to quite match the
  31// AXON spec
  32
  33/* RGMIIx_FER */
  34#define RGMII_FER_MASK(idx)     (0x7 << ((idx) * 4))
  35#define RGMII_FER_RTBI(idx)     (0x4 << ((idx) * 4))
  36#define RGMII_FER_RGMII(idx)    (0x5 << ((idx) * 4))
  37#define RGMII_FER_TBI(idx)      (0x6 << ((idx) * 4))
  38#define RGMII_FER_GMII(idx)     (0x7 << ((idx) * 4))
  39#define RGMII_FER_MII(idx)      RGMII_FER_GMII(idx)
  40
  41/* RGMIIx_SSR */
  42#define RGMII_SSR_MASK(idx)     (0x7 << ((idx) * 8))
  43#define RGMII_SSR_10(idx)       (0x1 << ((idx) * 8))
  44#define RGMII_SSR_100(idx)      (0x2 << ((idx) * 8))
  45#define RGMII_SSR_1000(idx)     (0x4 << ((idx) * 8))
  46
  47/* RGMII bridge supports only GMII/TBI and RGMII/RTBI PHYs */
  48static inline int rgmii_valid_mode(int phy_mode)
  49{
  50        return  phy_interface_mode_is_rgmii(phy_mode) ||
  51                phy_mode == PHY_INTERFACE_MODE_GMII ||
  52                phy_mode == PHY_INTERFACE_MODE_MII ||
  53                phy_mode == PHY_INTERFACE_MODE_TBI ||
  54                phy_mode == PHY_INTERFACE_MODE_RTBI;
  55}
  56
  57static inline u32 rgmii_mode_mask(int mode, int input)
  58{
  59        switch (mode) {
  60        case PHY_INTERFACE_MODE_RGMII:
  61        case PHY_INTERFACE_MODE_RGMII_ID:
  62        case PHY_INTERFACE_MODE_RGMII_RXID:
  63        case PHY_INTERFACE_MODE_RGMII_TXID:
  64                return RGMII_FER_RGMII(input);
  65        case PHY_INTERFACE_MODE_TBI:
  66                return RGMII_FER_TBI(input);
  67        case PHY_INTERFACE_MODE_GMII:
  68                return RGMII_FER_GMII(input);
  69        case PHY_INTERFACE_MODE_MII:
  70                return RGMII_FER_MII(input);
  71        case PHY_INTERFACE_MODE_RTBI:
  72                return RGMII_FER_RTBI(input);
  73        default:
  74                BUG();
  75        }
  76}
  77
  78int rgmii_attach(struct platform_device *ofdev, int input, int mode)
  79{
  80        struct rgmii_instance *dev = platform_get_drvdata(ofdev);
  81        struct rgmii_regs __iomem *p = dev->base;
  82
  83        RGMII_DBG(dev, "attach(%d)" NL, input);
  84
  85        /* Check if we need to attach to a RGMII */
  86        if (input < 0 || !rgmii_valid_mode(mode)) {
  87                printk(KERN_ERR "%pOF: unsupported settings !\n",
  88                       ofdev->dev.of_node);
  89                return -ENODEV;
  90        }
  91
  92        mutex_lock(&dev->lock);
  93
  94        /* Enable this input */
  95        out_be32(&p->fer, in_be32(&p->fer) | rgmii_mode_mask(mode, input));
  96
  97        printk(KERN_NOTICE "%pOF: input %d in %s mode\n",
  98               ofdev->dev.of_node, input, phy_modes(mode));
  99
 100        ++dev->users;
 101
 102        mutex_unlock(&dev->lock);
 103
 104        return 0;
 105}
 106
 107void rgmii_set_speed(struct platform_device *ofdev, int input, int speed)
 108{
 109        struct rgmii_instance *dev = platform_get_drvdata(ofdev);
 110        struct rgmii_regs __iomem *p = dev->base;
 111        u32 ssr;
 112
 113        mutex_lock(&dev->lock);
 114
 115        ssr = in_be32(&p->ssr) & ~RGMII_SSR_MASK(input);
 116
 117        RGMII_DBG(dev, "speed(%d, %d)" NL, input, speed);
 118
 119        if (speed == SPEED_1000)
 120                ssr |= RGMII_SSR_1000(input);
 121        else if (speed == SPEED_100)
 122                ssr |= RGMII_SSR_100(input);
 123        else if (speed == SPEED_10)
 124                ssr |= RGMII_SSR_10(input);
 125
 126        out_be32(&p->ssr, ssr);
 127
 128        mutex_unlock(&dev->lock);
 129}
 130
 131void rgmii_get_mdio(struct platform_device *ofdev, int input)
 132{
 133        struct rgmii_instance *dev = platform_get_drvdata(ofdev);
 134        struct rgmii_regs __iomem *p = dev->base;
 135        u32 fer;
 136
 137        RGMII_DBG2(dev, "get_mdio(%d)" NL, input);
 138
 139        if (!(dev->flags & EMAC_RGMII_FLAG_HAS_MDIO))
 140                return;
 141
 142        mutex_lock(&dev->lock);
 143
 144        fer = in_be32(&p->fer);
 145        fer |= 0x00080000u >> input;
 146        out_be32(&p->fer, fer);
 147        (void)in_be32(&p->fer);
 148
 149        DBG2(dev, " fer = 0x%08x\n", fer);
 150}
 151
 152void rgmii_put_mdio(struct platform_device *ofdev, int input)
 153{
 154        struct rgmii_instance *dev = platform_get_drvdata(ofdev);
 155        struct rgmii_regs __iomem *p = dev->base;
 156        u32 fer;
 157
 158        RGMII_DBG2(dev, "put_mdio(%d)" NL, input);
 159
 160        if (!(dev->flags & EMAC_RGMII_FLAG_HAS_MDIO))
 161                return;
 162
 163        fer = in_be32(&p->fer);
 164        fer &= ~(0x00080000u >> input);
 165        out_be32(&p->fer, fer);
 166        (void)in_be32(&p->fer);
 167
 168        DBG2(dev, " fer = 0x%08x\n", fer);
 169
 170        mutex_unlock(&dev->lock);
 171}
 172
 173void rgmii_detach(struct platform_device *ofdev, int input)
 174{
 175        struct rgmii_instance *dev = platform_get_drvdata(ofdev);
 176        struct rgmii_regs __iomem *p;
 177
 178        BUG_ON(!dev || dev->users == 0);
 179        p = dev->base;
 180
 181        mutex_lock(&dev->lock);
 182
 183        RGMII_DBG(dev, "detach(%d)" NL, input);
 184
 185        /* Disable this input */
 186        out_be32(&p->fer, in_be32(&p->fer) & ~RGMII_FER_MASK(input));
 187
 188        --dev->users;
 189
 190        mutex_unlock(&dev->lock);
 191}
 192
 193int rgmii_get_regs_len(struct platform_device *ofdev)
 194{
 195        return sizeof(struct emac_ethtool_regs_subhdr) +
 196                sizeof(struct rgmii_regs);
 197}
 198
 199void *rgmii_dump_regs(struct platform_device *ofdev, void *buf)
 200{
 201        struct rgmii_instance *dev = platform_get_drvdata(ofdev);
 202        struct emac_ethtool_regs_subhdr *hdr = buf;
 203        struct rgmii_regs *regs = (struct rgmii_regs *)(hdr + 1);
 204
 205        hdr->version = 0;
 206        hdr->index = 0; /* for now, are there chips with more than one
 207                         * rgmii ? if yes, then we'll add a cell_index
 208                         * like we do for emac
 209                         */
 210        memcpy_fromio(regs, dev->base, sizeof(struct rgmii_regs));
 211        return regs + 1;
 212}
 213
 214
 215static int rgmii_probe(struct platform_device *ofdev)
 216{
 217        struct device_node *np = ofdev->dev.of_node;
 218        struct rgmii_instance *dev;
 219        struct resource regs;
 220        int rc;
 221
 222        rc = -ENOMEM;
 223        dev = kzalloc(sizeof(struct rgmii_instance), GFP_KERNEL);
 224        if (dev == NULL)
 225                goto err_gone;
 226
 227        mutex_init(&dev->lock);
 228        dev->ofdev = ofdev;
 229
 230        rc = -ENXIO;
 231        if (of_address_to_resource(np, 0, &regs)) {
 232                printk(KERN_ERR "%pOF: Can't get registers address\n", np);
 233                goto err_free;
 234        }
 235
 236        rc = -ENOMEM;
 237        dev->base = (struct rgmii_regs __iomem *)ioremap(regs.start,
 238                                                 sizeof(struct rgmii_regs));
 239        if (dev->base == NULL) {
 240                printk(KERN_ERR "%pOF: Can't map device registers!\n", np);
 241                goto err_free;
 242        }
 243
 244        /* Check for RGMII flags */
 245        if (of_get_property(ofdev->dev.of_node, "has-mdio", NULL))
 246                dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO;
 247
 248        /* CAB lacks the right properties, fix this up */
 249        if (of_device_is_compatible(ofdev->dev.of_node, "ibm,rgmii-axon"))
 250                dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO;
 251
 252        DBG2(dev, " Boot FER = 0x%08x, SSR = 0x%08x\n",
 253             in_be32(&dev->base->fer), in_be32(&dev->base->ssr));
 254
 255        /* Disable all inputs by default */
 256        out_be32(&dev->base->fer, 0);
 257
 258        printk(KERN_INFO
 259               "RGMII %pOF initialized with%s MDIO support\n",
 260               ofdev->dev.of_node,
 261               (dev->flags & EMAC_RGMII_FLAG_HAS_MDIO) ? "" : "out");
 262
 263        wmb();
 264        platform_set_drvdata(ofdev, dev);
 265
 266        return 0;
 267
 268 err_free:
 269        kfree(dev);
 270 err_gone:
 271        return rc;
 272}
 273
 274static int rgmii_remove(struct platform_device *ofdev)
 275{
 276        struct rgmii_instance *dev = platform_get_drvdata(ofdev);
 277
 278        WARN_ON(dev->users != 0);
 279
 280        iounmap(dev->base);
 281        kfree(dev);
 282
 283        return 0;
 284}
 285
 286static const struct of_device_id rgmii_match[] =
 287{
 288        {
 289                .compatible     = "ibm,rgmii",
 290        },
 291        {
 292                .type           = "emac-rgmii",
 293        },
 294        {},
 295};
 296
 297static struct platform_driver rgmii_driver = {
 298        .driver = {
 299                .name = "emac-rgmii",
 300                .of_match_table = rgmii_match,
 301        },
 302        .probe = rgmii_probe,
 303        .remove = rgmii_remove,
 304};
 305
 306int __init rgmii_init(void)
 307{
 308        return platform_driver_register(&rgmii_driver);
 309}
 310
 311void rgmii_exit(void)
 312{
 313        platform_driver_unregister(&rgmii_driver);
 314}
 315