Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * drivers/net/ethernet/ibm/emac/tah.c
0004  *
0005  * Driver for PowerPC 4xx on-chip ethernet controller, TAH support.
0006  *
0007  * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
0008  *                <benh@kernel.crashing.org>
0009  *
0010  * Based on the arch/ppc version of the driver:
0011  *
0012  * Copyright 2004 MontaVista Software, Inc.
0013  * Matt Porter <mporter@kernel.crashing.org>
0014  *
0015  * Copyright (c) 2005 Eugene Surovegin <ebs@ebshome.net>
0016  */
0017 #include <linux/of_address.h>
0018 #include <asm/io.h>
0019 
0020 #include "emac.h"
0021 #include "core.h"
0022 
0023 int tah_attach(struct platform_device *ofdev, int channel)
0024 {
0025     struct tah_instance *dev = platform_get_drvdata(ofdev);
0026 
0027     mutex_lock(&dev->lock);
0028     /* Reset has been done at probe() time... nothing else to do for now */
0029     ++dev->users;
0030     mutex_unlock(&dev->lock);
0031 
0032     return 0;
0033 }
0034 
0035 void tah_detach(struct platform_device *ofdev, int channel)
0036 {
0037     struct tah_instance *dev = platform_get_drvdata(ofdev);
0038 
0039     mutex_lock(&dev->lock);
0040     --dev->users;
0041     mutex_unlock(&dev->lock);
0042 }
0043 
0044 void tah_reset(struct platform_device *ofdev)
0045 {
0046     struct tah_instance *dev = platform_get_drvdata(ofdev);
0047     struct tah_regs __iomem *p = dev->base;
0048     int n;
0049 
0050     /* Reset TAH */
0051     out_be32(&p->mr, TAH_MR_SR);
0052     n = 100;
0053     while ((in_be32(&p->mr) & TAH_MR_SR) && n)
0054         --n;
0055 
0056     if (unlikely(!n))
0057         printk(KERN_ERR "%pOF: reset timeout\n", ofdev->dev.of_node);
0058 
0059     /* 10KB TAH TX FIFO accommodates the max MTU of 9000 */
0060     out_be32(&p->mr,
0061          TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP |
0062          TAH_MR_DIG);
0063 }
0064 
0065 int tah_get_regs_len(struct platform_device *ofdev)
0066 {
0067     return sizeof(struct emac_ethtool_regs_subhdr) +
0068         sizeof(struct tah_regs);
0069 }
0070 
0071 void *tah_dump_regs(struct platform_device *ofdev, void *buf)
0072 {
0073     struct tah_instance *dev = platform_get_drvdata(ofdev);
0074     struct emac_ethtool_regs_subhdr *hdr = buf;
0075     struct tah_regs *regs = (struct tah_regs *)(hdr + 1);
0076 
0077     hdr->version = 0;
0078     hdr->index = 0; /* for now, are there chips with more than one
0079              * zmii ? if yes, then we'll add a cell_index
0080              * like we do for emac
0081              */
0082     memcpy_fromio(regs, dev->base, sizeof(struct tah_regs));
0083     return regs + 1;
0084 }
0085 
0086 static int tah_probe(struct platform_device *ofdev)
0087 {
0088     struct device_node *np = ofdev->dev.of_node;
0089     struct tah_instance *dev;
0090     struct resource regs;
0091     int rc;
0092 
0093     rc = -ENOMEM;
0094     dev = kzalloc(sizeof(struct tah_instance), GFP_KERNEL);
0095     if (dev == NULL)
0096         goto err_gone;
0097 
0098     mutex_init(&dev->lock);
0099     dev->ofdev = ofdev;
0100 
0101     rc = -ENXIO;
0102     if (of_address_to_resource(np, 0, &regs)) {
0103         printk(KERN_ERR "%pOF: Can't get registers address\n", np);
0104         goto err_free;
0105     }
0106 
0107     rc = -ENOMEM;
0108     dev->base = (struct tah_regs __iomem *)ioremap(regs.start,
0109                            sizeof(struct tah_regs));
0110     if (dev->base == NULL) {
0111         printk(KERN_ERR "%pOF: Can't map device registers!\n", np);
0112         goto err_free;
0113     }
0114 
0115     platform_set_drvdata(ofdev, dev);
0116 
0117     /* Initialize TAH and enable IPv4 checksum verification, no TSO yet */
0118     tah_reset(ofdev);
0119 
0120     printk(KERN_INFO "TAH %pOF initialized\n", ofdev->dev.of_node);
0121     wmb();
0122 
0123     return 0;
0124 
0125  err_free:
0126     kfree(dev);
0127  err_gone:
0128     return rc;
0129 }
0130 
0131 static int tah_remove(struct platform_device *ofdev)
0132 {
0133     struct tah_instance *dev = platform_get_drvdata(ofdev);
0134 
0135     WARN_ON(dev->users != 0);
0136 
0137     iounmap(dev->base);
0138     kfree(dev);
0139 
0140     return 0;
0141 }
0142 
0143 static const struct of_device_id tah_match[] =
0144 {
0145     {
0146         .compatible = "ibm,tah",
0147     },
0148     /* For backward compat with old DT */
0149     {
0150         .type       = "tah",
0151     },
0152     {},
0153 };
0154 
0155 static struct platform_driver tah_driver = {
0156     .driver = {
0157         .name = "emac-tah",
0158         .of_match_table = tah_match,
0159     },
0160     .probe = tah_probe,
0161     .remove = tah_remove,
0162 };
0163 
0164 int __init tah_init(void)
0165 {
0166     return platform_driver_register(&tah_driver);
0167 }
0168 
0169 void tah_exit(void)
0170 {
0171     platform_driver_unregister(&tah_driver);
0172 }