Root/target/linux/ifxmips/files-2.6.33/drivers/net/ifxmips.c

1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) 2005 Wu Qi Ming <Qi-Ming.Wu@infineon.com>
17 * Copyright (C) 2008 John Crispin <blogic@openwrt.org>
18 */
19
20#include <linux/kernel.h>
21#include <linux/slab.h>
22#include <linux/errno.h>
23#include <linux/types.h>
24#include <linux/interrupt.h>
25#include <linux/uaccess.h>
26#include <linux/in.h>
27#include <linux/netdevice.h>
28#include <linux/etherdevice.h>
29#include <linux/phy.h>
30#include <linux/ip.h>
31#include <linux/tcp.h>
32#include <linux/skbuff.h>
33#include <linux/mm.h>
34#include <linux/platform_device.h>
35#include <linux/ethtool.h>
36#include <linux/init.h>
37#include <linux/delay.h>
38
39#include <asm/checksum.h>
40
41#include <ifxmips.h>
42#include <ifxmips_dma.h>
43#include <ifxmips_pmu.h>
44
45struct ifxmips_mii_priv {
46    struct net_device_stats stats;
47    struct dma_device_info *dma_device;
48    struct sk_buff *skb;
49
50    struct mii_bus *mii_bus;
51    struct phy_device *phydev;
52    int oldlink, oldspeed, oldduplex;
53};
54
55static struct net_device *ifxmips_mii0_dev;
56static unsigned char mac_addr[MAX_ADDR_LEN];
57
58static int ifxmips_mdiobus_write(struct mii_bus *bus, int phy_addr,
59                int phy_reg, u16 phy_data)
60{
61    u32 val = MDIO_ACC_REQUEST |
62        ((phy_addr & MDIO_ACC_ADDR_MASK) << MDIO_ACC_ADDR_OFFSET) |
63        ((phy_reg & MDIO_ACC_REG_MASK) << MDIO_ACC_REG_OFFSET) |
64        phy_data;
65
66    while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST)
67        ;
68    ifxmips_w32(val, IFXMIPS_PPE32_MDIO_ACC);
69
70    return 0;
71}
72
73static int ifxmips_mdiobus_read(struct mii_bus *bus, int phy_addr, int phy_reg)
74{
75    u32 val = MDIO_ACC_REQUEST | MDIO_ACC_READ |
76        ((phy_addr & MDIO_ACC_ADDR_MASK) << MDIO_ACC_ADDR_OFFSET) |
77        ((phy_reg & MDIO_ACC_REG_MASK) << MDIO_ACC_REG_OFFSET);
78
79    while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST)
80        ;
81    ifxmips_w32(val, IFXMIPS_PPE32_MDIO_ACC);
82    while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST)
83        ;
84    val = ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_VAL_MASK;
85    return val;
86}
87
88int ifxmips_ifxmips_mii_open(struct net_device *dev)
89{
90    struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
91    struct dma_device_info *dma_dev = priv->dma_device;
92    int i;
93
94    for (i = 0; i < dma_dev->max_rx_chan_num; i++) {
95        if ((dma_dev->rx_chan[i])->control == IFXMIPS_DMA_CH_ON)
96            (dma_dev->rx_chan[i])->open(dma_dev->rx_chan[i]);
97    }
98    netif_start_queue(dev);
99    return 0;
100}
101
102int ifxmips_mii_release(struct net_device *dev)
103{
104    struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
105    struct dma_device_info *dma_dev = priv->dma_device;
106    int i;
107
108    for (i = 0; i < dma_dev->max_rx_chan_num; i++)
109        dma_dev->rx_chan[i]->close(dma_dev->rx_chan[i]);
110    netif_stop_queue(dev);
111    return 0;
112}
113
114int ifxmips_mii_hw_receive(struct net_device *dev, struct dma_device_info *dma_dev)
115{
116    struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
117    unsigned char *buf = NULL;
118    struct sk_buff *skb = NULL;
119    int len = 0;
120
121    len = dma_device_read(dma_dev, &buf, (void **)&skb);
122
123    if (len >= ETHERNET_PACKET_DMA_BUFFER_SIZE) {
124        printk(KERN_INFO "ifxmips_mii0: packet too large %d\n", len);
125        goto ifxmips_mii_hw_receive_err_exit;
126    }
127
128    /* remove CRC */
129    len -= 4;
130    if (skb == NULL) {
131        printk(KERN_INFO "ifxmips_mii0: cannot restore pointer\n");
132        goto ifxmips_mii_hw_receive_err_exit;
133    }
134
135    if (len > (skb->end - skb->tail)) {
136        printk(KERN_INFO "ifxmips_mii0: BUG, len:%d end:%p tail:%p\n",
137            (len+4), skb->end, skb->tail);
138        goto ifxmips_mii_hw_receive_err_exit;
139    }
140
141    skb_put(skb, len);
142    skb->dev = dev;
143    skb->protocol = eth_type_trans(skb, dev);
144    netif_rx(skb);
145
146    priv->stats.rx_packets++;
147    priv->stats.rx_bytes += len;
148    return 0;
149
150ifxmips_mii_hw_receive_err_exit:
151    if (len == 0) {
152        if (skb)
153            dev_kfree_skb_any(skb);
154        priv->stats.rx_errors++;
155        priv->stats.rx_dropped++;
156        return -EIO;
157    } else {
158        return len;
159    }
160}
161
162int ifxmips_mii_hw_tx(char *buf, int len, struct net_device *dev)
163{
164    int ret = 0;
165    struct ifxmips_mii_priv *priv = netdev_priv(dev);
166    struct dma_device_info *dma_dev = priv->dma_device;
167    ret = dma_device_write(dma_dev, buf, len, priv->skb);
168    return ret;
169}
170
171int ifxmips_mii_tx(struct sk_buff *skb, struct net_device *dev)
172{
173    int len;
174    char *data;
175    struct ifxmips_mii_priv *priv = netdev_priv(dev);
176    struct dma_device_info *dma_dev = priv->dma_device;
177
178    len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
179    data = skb->data;
180    priv->skb = skb;
181    dev->trans_start = jiffies;
182    /* TODO: we got more than 1 dma channel,
183       so we should do something intelligent here to select one */
184    dma_dev->current_tx_chan = 0;
185
186    wmb();
187
188    if (ifxmips_mii_hw_tx(data, len, dev) != len) {
189        dev_kfree_skb_any(skb);
190        priv->stats.tx_errors++;
191        priv->stats.tx_dropped++;
192    } else {
193        priv->stats.tx_packets++;
194        priv->stats.tx_bytes += len;
195    }
196
197    return 0;
198}
199
200void ifxmips_mii_tx_timeout(struct net_device *dev)
201{
202    int i;
203    struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
204
205    priv->stats.tx_errors++;
206    for (i = 0; i < priv->dma_device->max_tx_chan_num; i++)
207        priv->dma_device->tx_chan[i]->disable_irq(priv->dma_device->tx_chan[i]);
208    netif_wake_queue(dev);
209    return;
210}
211
212int dma_intr_handler(struct dma_device_info *dma_dev, int status)
213{
214    int i;
215
216    switch (status) {
217    case RCV_INT:
218        ifxmips_mii_hw_receive(ifxmips_mii0_dev, dma_dev);
219        break;
220
221    case TX_BUF_FULL_INT:
222        printk(KERN_INFO "ifxmips_mii0: tx buffer full\n");
223        netif_stop_queue(ifxmips_mii0_dev);
224        for (i = 0; i < dma_dev->max_tx_chan_num; i++) {
225            if ((dma_dev->tx_chan[i])->control == IFXMIPS_DMA_CH_ON)
226                dma_dev->tx_chan[i]->enable_irq(dma_dev->tx_chan[i]);
227        }
228        break;
229
230    case TRANSMIT_CPT_INT:
231        for (i = 0; i < dma_dev->max_tx_chan_num; i++)
232            dma_dev->tx_chan[i]->disable_irq(dma_dev->tx_chan[i]);
233
234        netif_wake_queue(ifxmips_mii0_dev);
235        break;
236    }
237
238    return 0;
239}
240
241unsigned char *ifxmips_etop_dma_buffer_alloc(int len, int *byte_offset, void **opt)
242{
243    unsigned char *buffer = NULL;
244    struct sk_buff *skb = NULL;
245
246    skb = dev_alloc_skb(ETHERNET_PACKET_DMA_BUFFER_SIZE);
247    if (skb == NULL)
248        return NULL;
249
250    buffer = (unsigned char *)(skb->data);
251    skb_reserve(skb, 2);
252    *(int *)opt = (int)skb;
253    *byte_offset = 2;
254
255    return buffer;
256}
257
258void ifxmips_etop_dma_buffer_free(unsigned char *dataptr, void *opt)
259{
260    struct sk_buff *skb = NULL;
261
262    if (opt == NULL) {
263        kfree(dataptr);
264    } else {
265        skb = (struct sk_buff *)opt;
266        dev_kfree_skb_any(skb);
267    }
268}
269
270static struct net_device_stats *ifxmips_get_stats(struct net_device *dev)
271{
272    return &((struct ifxmips_mii_priv *)netdev_priv(dev))->stats;
273}
274
275static void
276ifxmips_adjust_link(struct net_device *dev)
277{
278    struct ifxmips_mii_priv *priv = netdev_priv(dev);
279    struct phy_device *phydev = priv->phydev;
280    int new_state = 0;
281
282    /* Did anything change? */
283    if (priv->oldlink != phydev->link ||
284        priv->oldduplex != phydev->duplex ||
285        priv->oldspeed != phydev->speed) {
286        /* Yes, so update status and mark as changed */
287        new_state = 1;
288        priv->oldduplex = phydev->duplex;
289        priv->oldspeed = phydev->speed;
290        priv->oldlink = phydev->link;
291    }
292
293    /* If link status changed, show new status */
294    if (new_state)
295        phy_print_status(phydev);
296}
297
298static int mii_probe(struct net_device *dev)
299{
300    struct ifxmips_mii_priv *priv = netdev_priv(dev);
301    struct phy_device *phydev = NULL;
302    int phy_addr;
303
304    priv->oldlink = 0;
305    priv->oldspeed = 0;
306    priv->oldduplex = -1;
307
308    /* find the first (lowest address) PHY on the current MAC's MII bus */
309    for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
310        if (priv->mii_bus->phy_map[phy_addr]) {
311            phydev = priv->mii_bus->phy_map[phy_addr];
312            break; /* break out with first one found */
313        }
314    }
315
316    if (!phydev) {
317        printk (KERN_ERR "%s: no PHY found\n", dev->name);
318        return -ENODEV;
319    }
320
321    /* now we are supposed to have a proper phydev, to attach to... */
322    BUG_ON(!phydev);
323    BUG_ON(phydev->attached_dev);
324
325    phydev = phy_connect(dev, dev_name(&phydev->dev), &ifxmips_adjust_link,
326            0, PHY_INTERFACE_MODE_MII);
327
328    if (IS_ERR(phydev)) {
329        printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
330        return PTR_ERR(phydev);
331    }
332
333    /* mask with MAC supported features */
334    phydev->supported &= (SUPPORTED_10baseT_Half
335                  | SUPPORTED_10baseT_Full
336                  | SUPPORTED_100baseT_Half
337                  | SUPPORTED_100baseT_Full
338                  | SUPPORTED_Autoneg
339                  /* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */
340                  | SUPPORTED_MII
341                  | SUPPORTED_TP);
342
343    phydev->advertising = phydev->supported;
344
345    priv->phydev = phydev;
346
347    printk(KERN_INFO "%s: attached PHY driver [%s] "
348           "(mii_bus:phy_addr=%s, irq=%d)\n",
349           dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->irq);
350
351    return 0;
352}
353
354
355static int ifxmips_mii_dev_init(struct net_device *dev)
356{
357    int i;
358    struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev);
359    ether_setup(dev);
360    dev->watchdog_timeo = 10 * HZ;
361    dev->mtu = 1500;
362    memset(priv, 0, sizeof(struct ifxmips_mii_priv));
363    priv->dma_device = dma_device_reserve("PPE");
364    if (!priv->dma_device) {
365        BUG();
366        return -ENODEV;
367    }
368    priv->dma_device->buffer_alloc = &ifxmips_etop_dma_buffer_alloc;
369    priv->dma_device->buffer_free = &ifxmips_etop_dma_buffer_free;
370    priv->dma_device->intr_handler = &dma_intr_handler;
371    priv->dma_device->max_rx_chan_num = 4;
372
373    for (i = 0; i < priv->dma_device->max_rx_chan_num; i++) {
374        priv->dma_device->rx_chan[i]->packet_size = ETHERNET_PACKET_DMA_BUFFER_SIZE;
375        priv->dma_device->rx_chan[i]->control = IFXMIPS_DMA_CH_ON;
376    }
377
378    for (i = 0; i < priv->dma_device->max_tx_chan_num; i++)
379        if (i == 0)
380            priv->dma_device->tx_chan[i]->control = IFXMIPS_DMA_CH_ON;
381        else
382            priv->dma_device->tx_chan[i]->control = IFXMIPS_DMA_CH_OFF;
383
384    dma_device_register(priv->dma_device);
385
386    printk(KERN_INFO "%s: using mac=", dev->name);
387    for (i = 0; i < 6; i++) {
388        dev->dev_addr[i] = mac_addr[i];
389        printk("%02X%c", dev->dev_addr[i], (i == 5) ? ('\n') : (':'));
390    }
391
392    priv->mii_bus = mdiobus_alloc();
393    if (priv->mii_bus == NULL)
394        return -ENOMEM;
395
396    priv->mii_bus->priv = dev;
397    priv->mii_bus->read = ifxmips_mdiobus_read;
398    priv->mii_bus->write = ifxmips_mdiobus_write;
399    priv->mii_bus->name = "ifxmips_mii";
400    snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
401    priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
402    for(i = 0; i < PHY_MAX_ADDR; ++i)
403        priv->mii_bus->irq[i] = PHY_POLL;
404
405    mdiobus_register(priv->mii_bus);
406
407    return mii_probe(dev);
408}
409
410static void ifxmips_mii_chip_init(int mode)
411{
412    ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_DMA);
413    ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_PPE);
414
415    if (mode == REV_MII_MODE)
416        ifxmips_w32_mask(PPE32_MII_MASK, PPE32_MII_REVERSE, IFXMIPS_PPE32_CFG);
417    else if (mode == MII_MODE)
418        ifxmips_w32_mask(PPE32_MII_MASK, PPE32_MII_NORMAL, IFXMIPS_PPE32_CFG);
419    ifxmips_w32(PPE32_PLEN_UNDER | PPE32_PLEN_OVER, IFXMIPS_PPE32_IG_PLEN_CTRL);
420    ifxmips_w32(PPE32_CGEN, IFXMIPS_PPE32_ENET_MAC_CFG);
421    wmb();
422}
423
424static const struct net_device_ops ifxmips_eth_netdev_ops = {
425    .ndo_init = ifxmips_mii_dev_init,
426    .ndo_open = ifxmips_ifxmips_mii_open,
427    .ndo_stop = ifxmips_mii_release,
428    .ndo_start_xmit = ifxmips_mii_tx,
429    .ndo_tx_timeout = ifxmips_mii_tx_timeout,
430    .ndo_change_mtu = eth_change_mtu,
431    .ndo_set_mac_address = eth_mac_addr,
432    .ndo_validate_addr = eth_validate_addr,
433};
434
435static int
436ifxmips_mii_probe(struct platform_device *dev)
437{
438    int result = 0;
439    unsigned char *mac = (unsigned char *)dev->dev.platform_data;
440    ifxmips_mii0_dev = alloc_etherdev(sizeof(struct ifxmips_mii_priv));
441    ifxmips_mii0_dev->netdev_ops = &ifxmips_eth_netdev_ops;
442    memcpy(mac_addr, mac, 6);
443    strcpy(ifxmips_mii0_dev->name, "eth%d");
444    ifxmips_mii_chip_init(REV_MII_MODE);
445    result = register_netdev(ifxmips_mii0_dev);
446    if (result) {
447        printk(KERN_INFO "ifxmips_mii0: error %i registering device \"%s\"\n", result, ifxmips_mii0_dev->name);
448        goto out;
449    }
450
451    printk(KERN_INFO "ifxmips_mii0: driver loaded!\n");
452
453out:
454    return result;
455}
456
457static int ifxmips_mii_remove(struct platform_device *dev)
458{
459    struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(ifxmips_mii0_dev);
460
461    printk(KERN_INFO "ifxmips_mii0: ifxmips_mii0 cleanup\n");
462
463    dma_device_unregister(priv->dma_device);
464    dma_device_release(priv->dma_device);
465    kfree(priv->dma_device);
466    unregister_netdev(ifxmips_mii0_dev);
467    return 0;
468}
469
470static struct platform_driver ifxmips_mii_driver = {
471    .probe = ifxmips_mii_probe,
472    .remove = ifxmips_mii_remove,
473    .driver = {
474        .name = "ifxmips_mii0",
475        .owner = THIS_MODULE,
476    },
477};
478
479int __init ifxmips_mii_init(void)
480{
481    int ret = platform_driver_register(&ifxmips_mii_driver);
482    if (ret)
483        printk(KERN_INFO "ifxmips_mii0: Error registering platfom driver!");
484    return ret;
485}
486
487static void __exit ifxmips_mii_cleanup(void)
488{
489    platform_driver_unregister(&ifxmips_mii_driver);
490}
491
492module_init(ifxmips_mii_init);
493module_exit(ifxmips_mii_cleanup);
494
495MODULE_LICENSE("GPL");
496MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
497MODULE_DESCRIPTION("ethernet driver for IFXMIPS boards");
498

Archive Download this file



interactive