Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * jazzsonic.c
0004  *
0005  * (C) 2005 Finn Thain
0006  *
0007  * Converted to DMA API, and (from the mac68k project) introduced
0008  * dhd's support for 16-bit cards.
0009  *
0010  * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
0011  *
0012  * This driver is based on work from Andreas Busse, but most of
0013  * the code is rewritten.
0014  *
0015  * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
0016  *
0017  * A driver for the onboard Sonic ethernet controller on Mips Jazz
0018  * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and
0019  * perhaps others, too)
0020  */
0021 
0022 #include <linux/kernel.h>
0023 #include <linux/module.h>
0024 #include <linux/types.h>
0025 #include <linux/fcntl.h>
0026 #include <linux/gfp.h>
0027 #include <linux/interrupt.h>
0028 #include <linux/ioport.h>
0029 #include <linux/in.h>
0030 #include <linux/string.h>
0031 #include <linux/delay.h>
0032 #include <linux/errno.h>
0033 #include <linux/netdevice.h>
0034 #include <linux/etherdevice.h>
0035 #include <linux/skbuff.h>
0036 #include <linux/platform_device.h>
0037 #include <linux/dma-mapping.h>
0038 #include <linux/slab.h>
0039 #include <linux/pgtable.h>
0040 
0041 #include <asm/bootinfo.h>
0042 #include <asm/io.h>
0043 #include <asm/dma.h>
0044 #include <asm/jazz.h>
0045 #include <asm/jazzdma.h>
0046 
0047 static char jazz_sonic_string[] = "jazzsonic";
0048 
0049 #define SONIC_MEM_SIZE  0x100
0050 
0051 #include "sonic.h"
0052 
0053 /*
0054  * Macros to access SONIC registers
0055  */
0056 #define SONIC_READ(reg) (*((volatile unsigned int *)dev->base_addr+reg))
0057 
0058 #define SONIC_WRITE(reg,val)                        \
0059 do {                                    \
0060     *((volatile unsigned int *)dev->base_addr+(reg)) = (val);       \
0061 } while (0)
0062 
0063 /*
0064  * We cannot use station (ethernet) address prefixes to detect the
0065  * sonic controller since these are board manufacturer depended.
0066  * So we check for known Silicon Revision IDs instead.
0067  */
0068 static unsigned short known_revisions[] =
0069 {
0070     0x04,           /* Mips Magnum 4000 */
0071     0xffff          /* end of list */
0072 };
0073 
0074 static int jazzsonic_open(struct net_device* dev)
0075 {
0076     int retval;
0077 
0078     retval = request_irq(dev->irq, sonic_interrupt, 0, "sonic", dev);
0079     if (retval) {
0080         printk(KERN_ERR "%s: unable to get IRQ %d.\n",
0081                 dev->name, dev->irq);
0082         return retval;
0083     }
0084 
0085     retval = sonic_open(dev);
0086     if (retval)
0087         free_irq(dev->irq, dev);
0088     return retval;
0089 }
0090 
0091 static int jazzsonic_close(struct net_device* dev)
0092 {
0093     int err;
0094     err = sonic_close(dev);
0095     free_irq(dev->irq, dev);
0096     return err;
0097 }
0098 
0099 static const struct net_device_ops sonic_netdev_ops = {
0100     .ndo_open       = jazzsonic_open,
0101     .ndo_stop       = jazzsonic_close,
0102     .ndo_start_xmit     = sonic_send_packet,
0103     .ndo_get_stats      = sonic_get_stats,
0104     .ndo_set_rx_mode    = sonic_multicast_list,
0105     .ndo_tx_timeout     = sonic_tx_timeout,
0106     .ndo_validate_addr  = eth_validate_addr,
0107     .ndo_set_mac_address    = eth_mac_addr,
0108 };
0109 
0110 static int sonic_probe1(struct net_device *dev)
0111 {
0112     unsigned int silicon_revision;
0113     unsigned int val;
0114     struct sonic_local *lp = netdev_priv(dev);
0115     int err = -ENODEV;
0116     int i;
0117     unsigned char addr[ETH_ALEN];
0118 
0119     if (!request_mem_region(dev->base_addr, SONIC_MEM_SIZE, jazz_sonic_string))
0120         return -EBUSY;
0121 
0122     /*
0123      * get the Silicon Revision ID. If this is one of the known
0124      * one assume that we found a SONIC ethernet controller at
0125      * the expected location.
0126      */
0127     silicon_revision = SONIC_READ(SONIC_SR);
0128     i = 0;
0129     while (known_revisions[i] != 0xffff &&
0130            known_revisions[i] != silicon_revision)
0131         i++;
0132 
0133     if (known_revisions[i] == 0xffff) {
0134         pr_info("SONIC ethernet controller not found (0x%4x)\n",
0135             silicon_revision);
0136         goto out;
0137     }
0138 
0139     /*
0140      * Put the sonic into software reset, then
0141      * retrieve and print the ethernet address.
0142      */
0143     SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
0144     SONIC_WRITE(SONIC_CEP,0);
0145     for (i=0; i<3; i++) {
0146         val = SONIC_READ(SONIC_CAP0-i);
0147         addr[i*2] = val;
0148         addr[i*2+1] = val >> 8;
0149     }
0150     eth_hw_addr_set(dev, addr);
0151 
0152     lp->dma_bitmode = SONIC_BITMODE32;
0153 
0154     err = sonic_alloc_descriptors(dev);
0155     if (err)
0156         goto out;
0157 
0158     dev->netdev_ops = &sonic_netdev_ops;
0159     dev->watchdog_timeo = TX_TIMEOUT;
0160 
0161     /*
0162      * clear tally counter
0163      */
0164     SONIC_WRITE(SONIC_CRCT,0xffff);
0165     SONIC_WRITE(SONIC_FAET,0xffff);
0166     SONIC_WRITE(SONIC_MPT,0xffff);
0167 
0168     return 0;
0169 out:
0170     release_mem_region(dev->base_addr, SONIC_MEM_SIZE);
0171     return err;
0172 }
0173 
0174 /*
0175  * Probe for a SONIC ethernet controller on a Mips Jazz board.
0176  * Actually probing is superfluous but we're paranoid.
0177  */
0178 static int jazz_sonic_probe(struct platform_device *pdev)
0179 {
0180     struct net_device *dev;
0181     struct sonic_local *lp;
0182     struct resource *res;
0183     int err = 0;
0184 
0185     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0186     if (!res)
0187         return -ENODEV;
0188 
0189     dev = alloc_etherdev(sizeof(struct sonic_local));
0190     if (!dev)
0191         return -ENOMEM;
0192 
0193     lp = netdev_priv(dev);
0194     lp->device = &pdev->dev;
0195     SET_NETDEV_DEV(dev, &pdev->dev);
0196     platform_set_drvdata(pdev, dev);
0197 
0198     dev->base_addr = res->start;
0199     dev->irq = platform_get_irq(pdev, 0);
0200     err = sonic_probe1(dev);
0201     if (err)
0202         goto out;
0203 
0204     pr_info("SONIC ethernet @%08lx, MAC %pM, IRQ %d\n",
0205         dev->base_addr, dev->dev_addr, dev->irq);
0206 
0207     sonic_msg_init(dev);
0208 
0209     err = register_netdev(dev);
0210     if (err)
0211         goto undo_probe1;
0212 
0213     return 0;
0214 
0215 undo_probe1:
0216     dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
0217               lp->descriptors, lp->descriptors_laddr);
0218     release_mem_region(dev->base_addr, SONIC_MEM_SIZE);
0219 out:
0220     free_netdev(dev);
0221 
0222     return err;
0223 }
0224 
0225 MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
0226 MODULE_ALIAS("platform:jazzsonic");
0227 
0228 #include "sonic.c"
0229 
0230 static int jazz_sonic_device_remove(struct platform_device *pdev)
0231 {
0232     struct net_device *dev = platform_get_drvdata(pdev);
0233     struct sonic_local* lp = netdev_priv(dev);
0234 
0235     unregister_netdev(dev);
0236     dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
0237                       lp->descriptors, lp->descriptors_laddr);
0238     release_mem_region(dev->base_addr, SONIC_MEM_SIZE);
0239     free_netdev(dev);
0240 
0241     return 0;
0242 }
0243 
0244 static struct platform_driver jazz_sonic_driver = {
0245     .probe  = jazz_sonic_probe,
0246     .remove = jazz_sonic_device_remove,
0247     .driver = {
0248         .name   = jazz_sonic_string,
0249     },
0250 };
0251 
0252 module_platform_driver(jazz_sonic_driver);