linux/drivers/net/ethernet/netx-eth.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * drivers/net/ethernet/netx-eth.c
   4 *
   5 * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
   6 */
   7
   8#include <linux/init.h>
   9#include <linux/interrupt.h>
  10#include <linux/module.h>
  11#include <linux/kernel.h>
  12#include <linux/delay.h>
  13
  14#include <linux/netdevice.h>
  15#include <linux/platform_device.h>
  16#include <linux/etherdevice.h>
  17#include <linux/skbuff.h>
  18#include <linux/mii.h>
  19
  20#include <asm/io.h>
  21#include <mach/hardware.h>
  22#include <mach/netx-regs.h>
  23#include <mach/pfifo.h>
  24#include <mach/xc.h>
  25#include <linux/platform_data/eth-netx.h>
  26
  27/* XC Fifo Offsets */
  28#define EMPTY_PTR_FIFO(xcno)    (0 + ((xcno) << 3))     /* Index of the empty pointer FIFO */
  29#define IND_FIFO_PORT_HI(xcno)  (1 + ((xcno) << 3))     /* Index of the FIFO where received */
  30                                                        /* Data packages are indicated by XC */
  31#define IND_FIFO_PORT_LO(xcno)  (2 + ((xcno) << 3))     /* Index of the FIFO where received */
  32                                                        /* Data packages are indicated by XC */
  33#define REQ_FIFO_PORT_HI(xcno)  (3 + ((xcno) << 3))     /* Index of the FIFO where Data packages */
  34                                                        /* have to be indicated by ARM which */
  35                                                        /* shall be sent */
  36#define REQ_FIFO_PORT_LO(xcno)  (4 + ((xcno) << 3))     /* Index of the FIFO where Data packages */
  37                                                        /* have to be indicated by ARM which shall */
  38                                                        /* be sent */
  39#define CON_FIFO_PORT_HI(xcno)  (5 + ((xcno) << 3))     /* Index of the FIFO where sent Data packages */
  40                                                        /* are confirmed */
  41#define CON_FIFO_PORT_LO(xcno)  (6 + ((xcno) << 3))     /* Index of the FIFO where sent Data */
  42                                                        /* packages are confirmed */
  43#define PFIFO_MASK(xcno)        (0x7f << (xcno*8))
  44
  45#define FIFO_PTR_FRAMELEN_SHIFT 0
  46#define FIFO_PTR_FRAMELEN_MASK  (0x7ff << 0)
  47#define FIFO_PTR_FRAMELEN(len)  (((len) << 0) & FIFO_PTR_FRAMELEN_MASK)
  48#define FIFO_PTR_TIMETRIG       (1<<11)
  49#define FIFO_PTR_MULTI_REQ
  50#define FIFO_PTR_ORIGIN         (1<<14)
  51#define FIFO_PTR_VLAN           (1<<15)
  52#define FIFO_PTR_FRAMENO_SHIFT  16
  53#define FIFO_PTR_FRAMENO_MASK   (0x3f << 16)
  54#define FIFO_PTR_FRAMENO(no)    (((no) << 16) & FIFO_PTR_FRAMENO_MASK)
  55#define FIFO_PTR_SEGMENT_SHIFT  22
  56#define FIFO_PTR_SEGMENT_MASK   (0xf << 22)
  57#define FIFO_PTR_SEGMENT(seg)   (((seg) & 0xf) << 22)
  58#define FIFO_PTR_ERROR_SHIFT    28
  59#define FIFO_PTR_ERROR_MASK     (0xf << 28)
  60
  61#define ISR_LINK_STATUS_CHANGE (1<<4)
  62#define ISR_IND_LO             (1<<3)
  63#define ISR_CON_LO             (1<<2)
  64#define ISR_IND_HI             (1<<1)
  65#define ISR_CON_HI             (1<<0)
  66
  67#define ETH_MAC_LOCAL_CONFIG 0x1560
  68#define ETH_MAC_4321         0x1564
  69#define ETH_MAC_65           0x1568
  70
  71#define MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT 16
  72#define MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK (0xf<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT)
  73#define MAC_TRAFFIC_CLASS_ARRANGEMENT(x) (((x)<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT) & MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK)
  74#define LOCAL_CONFIG_LINK_STATUS_IRQ_EN (1<<24)
  75#define LOCAL_CONFIG_CON_LO_IRQ_EN (1<<23)
  76#define LOCAL_CONFIG_CON_HI_IRQ_EN (1<<22)
  77#define LOCAL_CONFIG_IND_LO_IRQ_EN (1<<21)
  78#define LOCAL_CONFIG_IND_HI_IRQ_EN (1<<20)
  79
  80#define CARDNAME "netx-eth"
  81
  82/* LSB must be zero */
  83#define INTERNAL_PHY_ADR 0x1c
  84
  85struct netx_eth_priv {
  86        void                    __iomem *sram_base, *xpec_base, *xmac_base;
  87        int                     id;
  88        struct mii_if_info      mii;
  89        u32                     msg_enable;
  90        struct xc               *xc;
  91        spinlock_t              lock;
  92};
  93
  94static void netx_eth_set_multicast_list(struct net_device *ndev)
  95{
  96        /* implement me */
  97}
  98
  99static int
 100netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 101{
 102        struct netx_eth_priv *priv = netdev_priv(ndev);
 103        unsigned char *buf = skb->data;
 104        unsigned int len = skb->len;
 105
 106        spin_lock_irq(&priv->lock);
 107        memcpy_toio(priv->sram_base + 1560, (void *)buf, len);
 108        if (len < 60) {
 109                memset_io(priv->sram_base + 1560 + len, 0, 60 - len);
 110                len = 60;
 111        }
 112
 113        pfifo_push(REQ_FIFO_PORT_LO(priv->id),
 114                   FIFO_PTR_SEGMENT(priv->id) |
 115                   FIFO_PTR_FRAMENO(1) |
 116                   FIFO_PTR_FRAMELEN(len));
 117
 118        ndev->stats.tx_packets++;
 119        ndev->stats.tx_bytes += skb->len;
 120
 121        netif_stop_queue(ndev);
 122        spin_unlock_irq(&priv->lock);
 123        dev_kfree_skb(skb);
 124
 125        return NETDEV_TX_OK;
 126}
 127
 128static void netx_eth_receive(struct net_device *ndev)
 129{
 130        struct netx_eth_priv *priv = netdev_priv(ndev);
 131        unsigned int val, frameno, seg, len;
 132        unsigned char *data;
 133        struct sk_buff *skb;
 134
 135        val = pfifo_pop(IND_FIFO_PORT_LO(priv->id));
 136
 137        frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT;
 138        seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT;
 139        len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT;
 140
 141        skb = netdev_alloc_skb(ndev, len);
 142        if (unlikely(skb == NULL)) {
 143                ndev->stats.rx_dropped++;
 144                return;
 145        }
 146
 147        data = skb_put(skb, len);
 148
 149        memcpy_fromio(data, priv->sram_base + frameno * 1560, len);
 150
 151        pfifo_push(EMPTY_PTR_FIFO(priv->id),
 152                FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno));
 153
 154        skb->protocol = eth_type_trans(skb, ndev);
 155        netif_rx(skb);
 156        ndev->stats.rx_packets++;
 157        ndev->stats.rx_bytes += len;
 158}
 159
 160static irqreturn_t
 161netx_eth_interrupt(int irq, void *dev_id)
 162{
 163        struct net_device *ndev = dev_id;
 164        struct netx_eth_priv *priv = netdev_priv(ndev);
 165        int status;
 166        unsigned long flags;
 167
 168        spin_lock_irqsave(&priv->lock, flags);
 169
 170        status = readl(NETX_PFIFO_XPEC_ISR(priv->id));
 171        while (status) {
 172                int fill_level;
 173                writel(status, NETX_PFIFO_XPEC_ISR(priv->id));
 174
 175                if ((status & ISR_CON_HI) || (status & ISR_IND_HI))
 176                        printk("%s: unexpected status: 0x%08x\n",
 177                            __func__, status);
 178
 179                fill_level =
 180                    readl(NETX_PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(priv->id)));
 181                while (fill_level--)
 182                        netx_eth_receive(ndev);
 183
 184                if (status & ISR_CON_LO)
 185                        netif_wake_queue(ndev);
 186
 187                if (status & ISR_LINK_STATUS_CHANGE)
 188                        mii_check_media(&priv->mii, netif_msg_link(priv), 1);
 189
 190                status = readl(NETX_PFIFO_XPEC_ISR(priv->id));
 191        }
 192        spin_unlock_irqrestore(&priv->lock, flags);
 193        return IRQ_HANDLED;
 194}
 195
 196static int netx_eth_open(struct net_device *ndev)
 197{
 198        struct netx_eth_priv *priv = netdev_priv(ndev);
 199
 200        if (request_irq
 201            (ndev->irq, netx_eth_interrupt, IRQF_SHARED, ndev->name, ndev))
 202                return -EAGAIN;
 203
 204        writel(ndev->dev_addr[0] |
 205               ndev->dev_addr[1]<<8 |
 206               ndev->dev_addr[2]<<16 |
 207               ndev->dev_addr[3]<<24,
 208               priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321);
 209        writel(ndev->dev_addr[4] |
 210               ndev->dev_addr[5]<<8,
 211               priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_65);
 212
 213        writel(LOCAL_CONFIG_LINK_STATUS_IRQ_EN |
 214                LOCAL_CONFIG_CON_LO_IRQ_EN |
 215                LOCAL_CONFIG_CON_HI_IRQ_EN |
 216                LOCAL_CONFIG_IND_LO_IRQ_EN |
 217                LOCAL_CONFIG_IND_HI_IRQ_EN,
 218                priv->xpec_base + NETX_XPEC_RAM_START_OFS +
 219                ETH_MAC_LOCAL_CONFIG);
 220
 221        mii_check_media(&priv->mii, netif_msg_link(priv), 1);
 222        netif_start_queue(ndev);
 223
 224        return 0;
 225}
 226
 227static int netx_eth_close(struct net_device *ndev)
 228{
 229        struct netx_eth_priv *priv = netdev_priv(ndev);
 230
 231        netif_stop_queue(ndev);
 232
 233        writel(0,
 234            priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_LOCAL_CONFIG);
 235
 236        free_irq(ndev->irq, ndev);
 237
 238        return 0;
 239}
 240
 241static void netx_eth_timeout(struct net_device *ndev)
 242{
 243        struct netx_eth_priv *priv = netdev_priv(ndev);
 244        int i;
 245
 246        printk(KERN_ERR "%s: transmit timed out, resetting\n", ndev->name);
 247
 248        spin_lock_irq(&priv->lock);
 249
 250        xc_reset(priv->xc);
 251        xc_start(priv->xc);
 252
 253        for (i=2; i<=18; i++)
 254                pfifo_push(EMPTY_PTR_FIFO(priv->id),
 255                        FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id));
 256
 257        spin_unlock_irq(&priv->lock);
 258
 259        netif_wake_queue(ndev);
 260}
 261
 262static int
 263netx_eth_phy_read(struct net_device *ndev, int phy_id, int reg)
 264{
 265        unsigned int val;
 266
 267        val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) |
 268              MIIMU_REGADDR(reg) | MIIMU_PHY_NRES;
 269
 270        writel(val, NETX_MIIMU);
 271        while (readl(NETX_MIIMU) & MIIMU_SNRDY);
 272
 273        return readl(NETX_MIIMU) >> 16;
 274
 275}
 276
 277static void
 278netx_eth_phy_write(struct net_device *ndev, int phy_id, int reg, int value)
 279{
 280        unsigned int val;
 281
 282        val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) |
 283              MIIMU_REGADDR(reg) | MIIMU_PHY_NRES | MIIMU_OPMODE_WRITE |
 284              MIIMU_DATA(value);
 285
 286        writel(val, NETX_MIIMU);
 287        while (readl(NETX_MIIMU) & MIIMU_SNRDY);
 288}
 289
 290static const struct net_device_ops netx_eth_netdev_ops = {
 291        .ndo_open               = netx_eth_open,
 292        .ndo_stop               = netx_eth_close,
 293        .ndo_start_xmit         = netx_eth_hard_start_xmit,
 294        .ndo_tx_timeout         = netx_eth_timeout,
 295        .ndo_set_rx_mode        = netx_eth_set_multicast_list,
 296        .ndo_validate_addr      = eth_validate_addr,
 297        .ndo_set_mac_address    = eth_mac_addr,
 298};
 299
 300static int netx_eth_enable(struct net_device *ndev)
 301{
 302        struct netx_eth_priv *priv = netdev_priv(ndev);
 303        unsigned int mac4321, mac65;
 304        int running, i, ret;
 305        bool inv_mac_addr = false;
 306
 307        ndev->netdev_ops = &netx_eth_netdev_ops;
 308        ndev->watchdog_timeo = msecs_to_jiffies(5000);
 309
 310        priv->msg_enable       = NETIF_MSG_LINK;
 311        priv->mii.phy_id_mask  = 0x1f;
 312        priv->mii.reg_num_mask = 0x1f;
 313        priv->mii.force_media  = 0;
 314        priv->mii.full_duplex  = 0;
 315        priv->mii.dev        = ndev;
 316        priv->mii.mdio_read    = netx_eth_phy_read;
 317        priv->mii.mdio_write   = netx_eth_phy_write;
 318        priv->mii.phy_id = INTERNAL_PHY_ADR + priv->id;
 319
 320        running = xc_running(priv->xc);
 321        xc_stop(priv->xc);
 322
 323        /* if the xc engine is already running, assume the bootloader has
 324         * loaded the firmware for us
 325         */
 326        if (running) {
 327                /* get Node Address from hardware */
 328                mac4321 = readl(priv->xpec_base +
 329                        NETX_XPEC_RAM_START_OFS + ETH_MAC_4321);
 330                mac65 = readl(priv->xpec_base +
 331                        NETX_XPEC_RAM_START_OFS + ETH_MAC_65);
 332
 333                ndev->dev_addr[0] = mac4321 & 0xff;
 334                ndev->dev_addr[1] = (mac4321 >> 8) & 0xff;
 335                ndev->dev_addr[2] = (mac4321 >> 16) & 0xff;
 336                ndev->dev_addr[3] = (mac4321 >> 24) & 0xff;
 337                ndev->dev_addr[4] = mac65 & 0xff;
 338                ndev->dev_addr[5] = (mac65 >> 8) & 0xff;
 339        } else {
 340                if (xc_request_firmware(priv->xc)) {
 341                        printk(CARDNAME ": requesting firmware failed\n");
 342                        return -ENODEV;
 343                }
 344        }
 345
 346        xc_reset(priv->xc);
 347        xc_start(priv->xc);
 348
 349        if (!is_valid_ether_addr(ndev->dev_addr))
 350                inv_mac_addr = true;
 351
 352        for (i=2; i<=18; i++)
 353                pfifo_push(EMPTY_PTR_FIFO(priv->id),
 354                        FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id));
 355
 356        ret = register_netdev(ndev);
 357        if (inv_mac_addr)
 358                printk("%s: Invalid ethernet MAC address. Please set using ip\n",
 359                       ndev->name);
 360
 361        return ret;
 362}
 363
 364static int netx_eth_drv_probe(struct platform_device *pdev)
 365{
 366        struct netx_eth_priv *priv;
 367        struct net_device *ndev;
 368        struct netxeth_platform_data *pdata;
 369        int ret;
 370
 371        ndev = alloc_etherdev(sizeof (struct netx_eth_priv));
 372        if (!ndev) {
 373                ret = -ENOMEM;
 374                goto exit;
 375        }
 376        SET_NETDEV_DEV(ndev, &pdev->dev);
 377
 378        platform_set_drvdata(pdev, ndev);
 379
 380        priv = netdev_priv(ndev);
 381
 382        pdata = dev_get_platdata(&pdev->dev);
 383        priv->xc = request_xc(pdata->xcno, &pdev->dev);
 384        if (!priv->xc) {
 385                dev_err(&pdev->dev, "unable to request xc engine\n");
 386                ret = -ENODEV;
 387                goto exit_free_netdev;
 388        }
 389
 390        ndev->irq = priv->xc->irq;
 391        priv->id = pdev->id;
 392        priv->xpec_base = priv->xc->xpec_base;
 393        priv->xmac_base = priv->xc->xmac_base;
 394        priv->sram_base = priv->xc->sram_base;
 395
 396        spin_lock_init(&priv->lock);
 397
 398        ret = pfifo_request(PFIFO_MASK(priv->id));
 399        if (ret) {
 400                printk("unable to request PFIFO\n");
 401                goto exit_free_xc;
 402        }
 403
 404        ret = netx_eth_enable(ndev);
 405        if (ret)
 406                goto exit_free_pfifo;
 407
 408        return 0;
 409exit_free_pfifo:
 410        pfifo_free(PFIFO_MASK(priv->id));
 411exit_free_xc:
 412        free_xc(priv->xc);
 413exit_free_netdev:
 414        free_netdev(ndev);
 415exit:
 416        return ret;
 417}
 418
 419static int netx_eth_drv_remove(struct platform_device *pdev)
 420{
 421        struct net_device *ndev = platform_get_drvdata(pdev);
 422        struct netx_eth_priv *priv = netdev_priv(ndev);
 423
 424        unregister_netdev(ndev);
 425        xc_stop(priv->xc);
 426        free_xc(priv->xc);
 427        free_netdev(ndev);
 428        pfifo_free(PFIFO_MASK(priv->id));
 429
 430        return 0;
 431}
 432
 433static int netx_eth_drv_suspend(struct platform_device *pdev, pm_message_t state)
 434{
 435        dev_err(&pdev->dev, "suspend not implemented\n");
 436        return 0;
 437}
 438
 439static int netx_eth_drv_resume(struct platform_device *pdev)
 440{
 441        dev_err(&pdev->dev, "resume not implemented\n");
 442        return 0;
 443}
 444
 445static struct platform_driver netx_eth_driver = {
 446        .probe          = netx_eth_drv_probe,
 447        .remove         = netx_eth_drv_remove,
 448        .suspend        = netx_eth_drv_suspend,
 449        .resume         = netx_eth_drv_resume,
 450        .driver         = {
 451                .name   = CARDNAME,
 452        },
 453};
 454
 455static int __init netx_eth_init(void)
 456{
 457        unsigned int phy_control, val;
 458
 459        printk("NetX Ethernet driver\n");
 460
 461        phy_control = PHY_CONTROL_PHY_ADDRESS(INTERNAL_PHY_ADR>>1) |
 462                      PHY_CONTROL_PHY1_MODE(PHY_MODE_ALL) |
 463                      PHY_CONTROL_PHY1_AUTOMDIX |
 464                      PHY_CONTROL_PHY1_EN |
 465                      PHY_CONTROL_PHY0_MODE(PHY_MODE_ALL) |
 466                      PHY_CONTROL_PHY0_AUTOMDIX |
 467                      PHY_CONTROL_PHY0_EN |
 468                      PHY_CONTROL_CLK_XLATIN;
 469
 470        val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
 471        writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
 472
 473        writel(phy_control | PHY_CONTROL_RESET, NETX_SYSTEM_PHY_CONTROL);
 474        udelay(100);
 475
 476        val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
 477        writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
 478
 479        writel(phy_control, NETX_SYSTEM_PHY_CONTROL);
 480
 481        return platform_driver_register(&netx_eth_driver);
 482}
 483
 484static void __exit netx_eth_cleanup(void)
 485{
 486        platform_driver_unregister(&netx_eth_driver);
 487}
 488
 489module_init(netx_eth_init);
 490module_exit(netx_eth_cleanup);
 491
 492MODULE_AUTHOR("Sascha Hauer, Pengutronix");
 493MODULE_LICENSE("GPL");
 494MODULE_ALIAS("platform:" CARDNAME);
 495MODULE_FIRMWARE("xc0.bin");
 496MODULE_FIRMWARE("xc1.bin");
 497MODULE_FIRMWARE("xc2.bin");
 498