linux/drivers/net/ethernet/ibm/emac/zmii.c
<<
>>
Prefs
   1/*
   2 * drivers/net/ethernet/ibm/emac/zmii.c
   3 *
   4 * Driver for PowerPC 4xx on-chip ethernet controller, ZMII 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 *      Armin Kuster <akuster@mvista.com>
  16 *      Copyright 2001 MontaVista Softare 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/slab.h>
  25#include <linux/kernel.h>
  26#include <linux/ethtool.h>
  27#include <asm/io.h>
  28
  29#include "emac.h"
  30#include "core.h"
  31
  32/* ZMIIx_FER */
  33#define ZMII_FER_MDI(idx)       (0x80000000 >> ((idx) * 4))
  34#define ZMII_FER_MDI_ALL        (ZMII_FER_MDI(0) | ZMII_FER_MDI(1) | \
  35                                 ZMII_FER_MDI(2) | ZMII_FER_MDI(3))
  36
  37#define ZMII_FER_SMII(idx)      (0x40000000 >> ((idx) * 4))
  38#define ZMII_FER_RMII(idx)      (0x20000000 >> ((idx) * 4))
  39#define ZMII_FER_MII(idx)       (0x10000000 >> ((idx) * 4))
  40
  41/* ZMIIx_SSR */
  42#define ZMII_SSR_SCI(idx)       (0x40000000 >> ((idx) * 4))
  43#define ZMII_SSR_FSS(idx)       (0x20000000 >> ((idx) * 4))
  44#define ZMII_SSR_SP(idx)        (0x10000000 >> ((idx) * 4))
  45
  46/* ZMII only supports MII, RMII and SMII
  47 * we also support autodetection for backward compatibility
  48 */
  49static inline int zmii_valid_mode(int mode)
  50{
  51        return  mode == PHY_MODE_MII ||
  52                mode == PHY_MODE_RMII ||
  53                mode == PHY_MODE_SMII ||
  54                mode == PHY_MODE_NA;
  55}
  56
  57static inline const char *zmii_mode_name(int mode)
  58{
  59        switch (mode) {
  60        case PHY_MODE_MII:
  61                return "MII";
  62        case PHY_MODE_RMII:
  63                return "RMII";
  64        case PHY_MODE_SMII:
  65                return "SMII";
  66        default:
  67                BUG();
  68        }
  69}
  70
  71static inline u32 zmii_mode_mask(int mode, int input)
  72{
  73        switch (mode) {
  74        case PHY_MODE_MII:
  75                return ZMII_FER_MII(input);
  76        case PHY_MODE_RMII:
  77                return ZMII_FER_RMII(input);
  78        case PHY_MODE_SMII:
  79                return ZMII_FER_SMII(input);
  80        default:
  81                return 0;
  82        }
  83}
  84
  85int zmii_attach(struct platform_device *ofdev, int input, int *mode)
  86{
  87        struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
  88        struct zmii_regs __iomem *p = dev->base;
  89
  90        ZMII_DBG(dev, "init(%d, %d)" NL, input, *mode);
  91
  92        if (!zmii_valid_mode(*mode)) {
  93                /* Probably an EMAC connected to RGMII,
  94                 * but it still may need ZMII for MDIO so
  95                 * we don't fail here.
  96                 */
  97                dev->users++;
  98                return 0;
  99        }
 100
 101        mutex_lock(&dev->lock);
 102
 103        /* Autodetect ZMII mode if not specified.
 104         * This is only for backward compatibility with the old driver.
 105         * Please, always specify PHY mode in your board port to avoid
 106         * any surprises.
 107         */
 108        if (dev->mode == PHY_MODE_NA) {
 109                if (*mode == PHY_MODE_NA) {
 110                        u32 r = dev->fer_save;
 111
 112                        ZMII_DBG(dev, "autodetecting mode, FER = 0x%08x" NL, r);
 113
 114                        if (r & (ZMII_FER_MII(0) | ZMII_FER_MII(1)))
 115                                dev->mode = PHY_MODE_MII;
 116                        else if (r & (ZMII_FER_RMII(0) | ZMII_FER_RMII(1)))
 117                                dev->mode = PHY_MODE_RMII;
 118                        else
 119                                dev->mode = PHY_MODE_SMII;
 120                } else
 121                        dev->mode = *mode;
 122
 123                printk(KERN_NOTICE "%s: bridge in %s mode\n",
 124                       ofdev->dev.of_node->full_name,
 125                       zmii_mode_name(dev->mode));
 126        } else {
 127                /* All inputs must use the same mode */
 128                if (*mode != PHY_MODE_NA && *mode != dev->mode) {
 129                        printk(KERN_ERR
 130                               "%s: invalid mode %d specified for input %d\n",
 131                               ofdev->dev.of_node->full_name, *mode, input);
 132                        mutex_unlock(&dev->lock);
 133                        return -EINVAL;
 134                }
 135        }
 136
 137        /* Report back correct PHY mode,
 138         * it may be used during PHY initialization.
 139         */
 140        *mode = dev->mode;
 141
 142        /* Enable this input */
 143        out_be32(&p->fer, in_be32(&p->fer) | zmii_mode_mask(dev->mode, input));
 144        ++dev->users;
 145
 146        mutex_unlock(&dev->lock);
 147
 148        return 0;
 149}
 150
 151void zmii_get_mdio(struct platform_device *ofdev, int input)
 152{
 153        struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
 154        u32 fer;
 155
 156        ZMII_DBG2(dev, "get_mdio(%d)" NL, input);
 157
 158        mutex_lock(&dev->lock);
 159
 160        fer = in_be32(&dev->base->fer) & ~ZMII_FER_MDI_ALL;
 161        out_be32(&dev->base->fer, fer | ZMII_FER_MDI(input));
 162}
 163
 164void zmii_put_mdio(struct platform_device *ofdev, int input)
 165{
 166        struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
 167
 168        ZMII_DBG2(dev, "put_mdio(%d)" NL, input);
 169        mutex_unlock(&dev->lock);
 170}
 171
 172
 173void zmii_set_speed(struct platform_device *ofdev, int input, int speed)
 174{
 175        struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
 176        u32 ssr;
 177
 178        mutex_lock(&dev->lock);
 179
 180        ssr = in_be32(&dev->base->ssr);
 181
 182        ZMII_DBG(dev, "speed(%d, %d)" NL, input, speed);
 183
 184        if (speed == SPEED_100)
 185                ssr |= ZMII_SSR_SP(input);
 186        else
 187                ssr &= ~ZMII_SSR_SP(input);
 188
 189        out_be32(&dev->base->ssr, ssr);
 190
 191        mutex_unlock(&dev->lock);
 192}
 193
 194void zmii_detach(struct platform_device *ofdev, int input)
 195{
 196        struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
 197
 198        BUG_ON(!dev || dev->users == 0);
 199
 200        mutex_lock(&dev->lock);
 201
 202        ZMII_DBG(dev, "detach(%d)" NL, input);
 203
 204        /* Disable this input */
 205        out_be32(&dev->base->fer,
 206                 in_be32(&dev->base->fer) & ~zmii_mode_mask(dev->mode, input));
 207
 208        --dev->users;
 209
 210        mutex_unlock(&dev->lock);
 211}
 212
 213int zmii_get_regs_len(struct platform_device *ofdev)
 214{
 215        return sizeof(struct emac_ethtool_regs_subhdr) +
 216                sizeof(struct zmii_regs);
 217}
 218
 219void *zmii_dump_regs(struct platform_device *ofdev, void *buf)
 220{
 221        struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
 222        struct emac_ethtool_regs_subhdr *hdr = buf;
 223        struct zmii_regs *regs = (struct zmii_regs *)(hdr + 1);
 224
 225        hdr->version = 0;
 226        hdr->index = 0; /* for now, are there chips with more than one
 227                         * zmii ? if yes, then we'll add a cell_index
 228                         * like we do for emac
 229                         */
 230        memcpy_fromio(regs, dev->base, sizeof(struct zmii_regs));
 231        return regs + 1;
 232}
 233
 234static int zmii_probe(struct platform_device *ofdev)
 235{
 236        struct device_node *np = ofdev->dev.of_node;
 237        struct zmii_instance *dev;
 238        struct resource regs;
 239        int rc;
 240
 241        rc = -ENOMEM;
 242        dev = kzalloc(sizeof(struct zmii_instance), GFP_KERNEL);
 243        if (dev == NULL)
 244                goto err_gone;
 245
 246        mutex_init(&dev->lock);
 247        dev->ofdev = ofdev;
 248        dev->mode = PHY_MODE_NA;
 249
 250        rc = -ENXIO;
 251        if (of_address_to_resource(np, 0, &regs)) {
 252                printk(KERN_ERR "%s: Can't get registers address\n",
 253                       np->full_name);
 254                goto err_free;
 255        }
 256
 257        rc = -ENOMEM;
 258        dev->base = (struct zmii_regs __iomem *)ioremap(regs.start,
 259                                                sizeof(struct zmii_regs));
 260        if (dev->base == NULL) {
 261                printk(KERN_ERR "%s: Can't map device registers!\n",
 262                       np->full_name);
 263                goto err_free;
 264        }
 265
 266        /* We may need FER value for autodetection later */
 267        dev->fer_save = in_be32(&dev->base->fer);
 268
 269        /* Disable all inputs by default */
 270        out_be32(&dev->base->fer, 0);
 271
 272        printk(KERN_INFO
 273               "ZMII %s initialized\n", ofdev->dev.of_node->full_name);
 274        wmb();
 275        dev_set_drvdata(&ofdev->dev, dev);
 276
 277        return 0;
 278
 279 err_free:
 280        kfree(dev);
 281 err_gone:
 282        return rc;
 283}
 284
 285static int zmii_remove(struct platform_device *ofdev)
 286{
 287        struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
 288
 289        dev_set_drvdata(&ofdev->dev, NULL);
 290
 291        WARN_ON(dev->users != 0);
 292
 293        iounmap(dev->base);
 294        kfree(dev);
 295
 296        return 0;
 297}
 298
 299static struct of_device_id zmii_match[] =
 300{
 301        {
 302                .compatible     = "ibm,zmii",
 303        },
 304        /* For backward compat with old DT */
 305        {
 306                .type           = "emac-zmii",
 307        },
 308        {},
 309};
 310
 311static struct platform_driver zmii_driver = {
 312        .driver = {
 313                .name = "emac-zmii",
 314                .owner = THIS_MODULE,
 315                .of_match_table = zmii_match,
 316        },
 317        .probe = zmii_probe,
 318        .remove = zmii_remove,
 319};
 320
 321int __init zmii_init(void)
 322{
 323        return platform_driver_register(&zmii_driver);
 324}
 325
 326void zmii_exit(void)
 327{
 328        platform_driver_unregister(&zmii_driver);
 329}
 330