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