linux/drivers/net/ethernet/ibm/emac/tah.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * drivers/net/ethernet/ibm/emac/tah.c
   4 *
   5 * Driver for PowerPC 4xx on-chip ethernet controller, TAH 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 2004 MontaVista Software, Inc.
  13 * Matt Porter <mporter@kernel.crashing.org>
  14 *
  15 * Copyright (c) 2005 Eugene Surovegin <ebs@ebshome.net>
  16 */
  17#include <linux/of_address.h>
  18#include <asm/io.h>
  19
  20#include "emac.h"
  21#include "core.h"
  22
  23int tah_attach(struct platform_device *ofdev, int channel)
  24{
  25        struct tah_instance *dev = platform_get_drvdata(ofdev);
  26
  27        mutex_lock(&dev->lock);
  28        /* Reset has been done at probe() time... nothing else to do for now */
  29        ++dev->users;
  30        mutex_unlock(&dev->lock);
  31
  32        return 0;
  33}
  34
  35void tah_detach(struct platform_device *ofdev, int channel)
  36{
  37        struct tah_instance *dev = platform_get_drvdata(ofdev);
  38
  39        mutex_lock(&dev->lock);
  40        --dev->users;
  41        mutex_unlock(&dev->lock);
  42}
  43
  44void tah_reset(struct platform_device *ofdev)
  45{
  46        struct tah_instance *dev = platform_get_drvdata(ofdev);
  47        struct tah_regs __iomem *p = dev->base;
  48        int n;
  49
  50        /* Reset TAH */
  51        out_be32(&p->mr, TAH_MR_SR);
  52        n = 100;
  53        while ((in_be32(&p->mr) & TAH_MR_SR) && n)
  54                --n;
  55
  56        if (unlikely(!n))
  57                printk(KERN_ERR "%pOF: reset timeout\n", ofdev->dev.of_node);
  58
  59        /* 10KB TAH TX FIFO accommodates the max MTU of 9000 */
  60        out_be32(&p->mr,
  61                 TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP |
  62                 TAH_MR_DIG);
  63}
  64
  65int tah_get_regs_len(struct platform_device *ofdev)
  66{
  67        return sizeof(struct emac_ethtool_regs_subhdr) +
  68                sizeof(struct tah_regs);
  69}
  70
  71void *tah_dump_regs(struct platform_device *ofdev, void *buf)
  72{
  73        struct tah_instance *dev = platform_get_drvdata(ofdev);
  74        struct emac_ethtool_regs_subhdr *hdr = buf;
  75        struct tah_regs *regs = (struct tah_regs *)(hdr + 1);
  76
  77        hdr->version = 0;
  78        hdr->index = 0; /* for now, are there chips with more than one
  79                         * zmii ? if yes, then we'll add a cell_index
  80                         * like we do for emac
  81                         */
  82        memcpy_fromio(regs, dev->base, sizeof(struct tah_regs));
  83        return regs + 1;
  84}
  85
  86static int tah_probe(struct platform_device *ofdev)
  87{
  88        struct device_node *np = ofdev->dev.of_node;
  89        struct tah_instance *dev;
  90        struct resource regs;
  91        int rc;
  92
  93        rc = -ENOMEM;
  94        dev = kzalloc(sizeof(struct tah_instance), GFP_KERNEL);
  95        if (dev == NULL)
  96                goto err_gone;
  97
  98        mutex_init(&dev->lock);
  99        dev->ofdev = ofdev;
 100
 101        rc = -ENXIO;
 102        if (of_address_to_resource(np, 0, &regs)) {
 103                printk(KERN_ERR "%pOF: Can't get registers address\n", np);
 104                goto err_free;
 105        }
 106
 107        rc = -ENOMEM;
 108        dev->base = (struct tah_regs __iomem *)ioremap(regs.start,
 109                                               sizeof(struct tah_regs));
 110        if (dev->base == NULL) {
 111                printk(KERN_ERR "%pOF: Can't map device registers!\n", np);
 112                goto err_free;
 113        }
 114
 115        platform_set_drvdata(ofdev, dev);
 116
 117        /* Initialize TAH and enable IPv4 checksum verification, no TSO yet */
 118        tah_reset(ofdev);
 119
 120        printk(KERN_INFO "TAH %pOF initialized\n", ofdev->dev.of_node);
 121        wmb();
 122
 123        return 0;
 124
 125 err_free:
 126        kfree(dev);
 127 err_gone:
 128        return rc;
 129}
 130
 131static int tah_remove(struct platform_device *ofdev)
 132{
 133        struct tah_instance *dev = platform_get_drvdata(ofdev);
 134
 135        WARN_ON(dev->users != 0);
 136
 137        iounmap(dev->base);
 138        kfree(dev);
 139
 140        return 0;
 141}
 142
 143static const struct of_device_id tah_match[] =
 144{
 145        {
 146                .compatible     = "ibm,tah",
 147        },
 148        /* For backward compat with old DT */
 149        {
 150                .type           = "tah",
 151        },
 152        {},
 153};
 154
 155static struct platform_driver tah_driver = {
 156        .driver = {
 157                .name = "emac-tah",
 158                .of_match_table = tah_match,
 159        },
 160        .probe = tah_probe,
 161        .remove = tah_remove,
 162};
 163
 164int __init tah_init(void)
 165{
 166        return platform_driver_register(&tah_driver);
 167}
 168
 169void tah_exit(void)
 170{
 171        platform_driver_unregister(&tah_driver);
 172}
 173