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