Root/target/linux/amazon/files/drivers/net/ethernet/amazon_sw.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//-----------------------------------------------------------------------
17/*
18 * Description:
19 * Driver for Infineon Amazon 3 port switch
20 */
21//-----------------------------------------------------------------------
22/* Author: Wu Qi Ming[Qi-Ming.Wu@infineon.com]
23 * Created: 7-April-2004
24 */
25//-----------------------------------------------------------------------
26/* History
27 * Changed on: Jun 28, 2004
28 * Changed by: peng.liu@infineon.com
29 * Reason: add hardware flow control (HFC) (CONFIG_NET_HW_FLOWCONTROL)
30 *
31 * Changed on: Apr 6, 2005
32 * Changed by: mars.lin@infineon.com
33 * Reason : supoort port identification
34 */
35
36
37// copyright 2004-2005 infineon.com
38
39// copyright 2007 john crispin <blogic@openwrt.org>
40// copyright 2007 felix fietkau <nbd@openwrt.org>
41// copyright 2009 hauke mehrtens <hauke@hauke-m.de>
42
43
44// TODO
45// port vlan code from bcrm target... the tawainese code was scrapped due to crappyness
46// check all the mmi reg settings and possibly document them better
47// verify the ethtool code
48// remove the while(1) stuff
49// further clean up and rework ... but it works for now
50// check the mode[]=bridge stuff
51// verify that the ethaddr can be set from u-boot
52
53
54#ifndef __KERNEL__
55#define __KERNEL__
56#endif
57
58
59#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
60#define MODVERSIONS
61#endif
62
63#if defined(MODVERSIONS) && !defined(__GENKSYMS__)
64#include <linux/modversions.h>
65#endif
66
67#include <linux/module.h>
68#include <linux/string.h>
69#include <linux/sched.h>
70#include <linux/kernel.h>
71#include <linux/slab.h>
72#include <linux/errno.h>
73#include <linux/types.h>
74#include <linux/interrupt.h>
75#include <linux/mii.h>
76#include <asm/uaccess.h>
77#include <linux/in.h>
78#include <linux/netdevice.h>
79#include <linux/etherdevice.h>
80#include <linux/ip.h>
81#include <linux/tcp.h>
82#include <linux/skbuff.h>
83#include <linux/in6.h>
84#include <linux/proc_fs.h>
85#include <linux/mm.h>
86#include <linux/ethtool.h>
87#include <asm/checksum.h>
88#include <linux/init.h>
89#include <linux/platform_device.h>
90
91#include <asm/amazon/amazon.h>
92#include <asm/amazon/amazon_dma.h>
93#include <asm/amazon/amazon_sw.h>
94
95// how many mii ports are there ?
96#define AMAZON_SW_INT_NO 2
97
98#define ETHERNET_PACKET_DMA_BUFFER_SIZE 1536
99
100/***************************************** Module Parameters *************************************/
101static char mode[] = "bridge";
102module_param_array(mode, charp, NULL, 0);
103
104static int timeout = 1 * HZ;
105module_param(timeout, int, 0);
106
107int switch_init(struct net_device *dev);
108void switch_tx_timeout(struct net_device *dev);
109
110static struct net_device *switch_devs[2];
111
112int add_mac_table_entry(u64 entry_value)
113{
114    int i;
115    u32 data1, data2;
116
117    AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) = ~7;
118
119    for (i = 0; i < 32; i++) {
120        AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0x80000000 | 0x20 | i;
121        while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
122        data1 = AMAZON_SW_REG32(AMAZON_SW_DATA1);
123        data2 = AMAZON_SW_REG32(AMAZON_SW_DATA2);
124        if ((data1 & (0x00700000)) != 0x00700000)
125            continue;
126        AMAZON_SW_REG32(AMAZON_SW_DATA1) = (u32) (entry_value >> 32);
127        AMAZON_SW_REG32(AMAZON_SW_DATA2) = (u32) entry_value & 0xffffffff;
128        AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0xc0000020 | i;
129        while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
130        break;
131    }
132    AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) |= 7;
133    if (i >= 32)
134        return -1;
135    return OK;
136}
137
138u64 read_mac_table_entry(int index)
139{
140    u32 data1, data2;
141    u64 value;
142    AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0x80000000 | 0x20 | index;
143    while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
144    data1 = AMAZON_SW_REG32(AMAZON_SW_DATA1) & 0xffffff;
145    data2 = AMAZON_SW_REG32(AMAZON_SW_DATA2);
146    value = (u64) data1 << 32 | (u64) data2;
147    return value;
148}
149
150int write_mac_table_entry(int index, u64 value)
151{
152    u32 data1, data2;
153    data1 = (u32) (value >> 32);
154    data2 = (u32) value & 0xffffffff;
155    AMAZON_SW_REG32(AMAZON_SW_DATA1) = data1;
156    AMAZON_SW_REG32(AMAZON_SW_DATA2) = data2;
157    AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0xc0000020 | index;
158    while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
159    return OK;
160}
161
162u32 get_mdio_reg(int phy_addr, int reg_num)
163{
164    u32 value;
165    AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) = (3 << 30) | ((phy_addr & 0x1f) << 21) | ((reg_num & 0x1f) << 16);
166    while (AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) & (1 << 31)) {};
167    value = AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) & 0xffff;
168    return value;
169}
170
171int set_mdio_reg(int phy_addr, int reg_num, u32 value)
172{
173    AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) = (2 << 30) | ((phy_addr & 0x1f) << 21) | ((reg_num & 0x1f) << 16) | (value & 0xffff);
174    while (AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) & (1 << 31)) {};
175    return OK;
176}
177
178int auto_negotiate(int phy_addr)
179{
180    u32 value = 0;
181    value = get_mdio_reg(phy_addr, MDIO_BASE_CONTROL_REG);
182    set_mdio_reg(phy_addr, MDIO_BASE_CONTROL_REG, (value | RESTART_AUTO_NEGOTIATION | AUTO_NEGOTIATION_ENABLE | PHY_RESET));
183    return OK;
184}
185
186/*
187     In this version of switch driver, we split the dma channels for the switch.
188     2 for port0 and 2 for port1. So that we can do internal bridging if necessary.
189     In switch mode, packets coming in from port0 or port1 is able to do Destination
190     address lookup. Packets coming from port0 with destination address of port1 should
191     not go to pmac again. The switch hardware should be able to do the switch in the hard
192     ware level. Packets coming from the pmac should not do the DA look up in that the
193     desination is already known for the kernel. It only needs to go to the correct NIC to
194     find its way out.
195  */
196int amazon_sw_chip_init(void)
197{
198    u32 tmp1;
199    int i = 0;
200
201    /* Aging tick select: 5mins */
202    tmp1 = 0xa0;
203    if (strcmp(mode, "bridge") == 0) {
204        // bridge mode, set militarised mode to 1, no learning!
205        tmp1 |= 0xC00;
206    } else {
207        // enable learning for P0 and P1,
208        tmp1 |= 3;
209    }
210
211    /* unknown broadcast/multicast/unicast to all ports */
212    AMAZON_SW_REG32(AMAZON_SW_UN_DEST) = 0x1ff;
213
214    AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) = tmp1;
215
216    /* OCS:1 set OCS bit, split the two NIC in rx direction EDL:1 (enable DA lookup) */
217#if defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT) || defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT_MODULE)
218    AMAZON_SW_REG32(AMAZON_SW_P2_PCTL) = 0x700;
219#else
220    AMAZON_SW_REG32(AMAZON_SW_P2_PCTL) = 0x401;
221#endif
222
223    /* EPC: 1 split the two NIC in tx direction CRC is generated */
224    AMAZON_SW_REG32(AMAZON_SW_P2_CTL) = 0x6;
225
226    // for bi-directional
227    AMAZON_SW_REG32(AMAZON_SW_P0_WM) = 0x14141412;
228    AMAZON_SW_REG32(AMAZON_SW_P1_WM) = 0x14141412;
229    AMAZON_SW_REG32(AMAZON_SW_P2_WM) = 0x28282826;
230    AMAZON_SW_REG32(AMAZON_SW_GBL_WM) = 0x0;
231
232    AMAZON_SW_REG32(AMAZON_CGU_PLL0SR) = (AMAZON_SW_REG32(AMAZON_CGU_PLL0SR)) | 0x58000000;
233    // clock for PHY
234    AMAZON_SW_REG32(AMAZON_CGU_IFCCR) = (AMAZON_SW_REG32(AMAZON_CGU_IFCCR)) | 0x80000004;
235    // enable power for PHY
236    AMAZON_SW_REG32(AMAZON_PMU_PWDCR) = (AMAZON_SW_REG32(AMAZON_PMU_PWDCR)) | AMAZON_PMU_PWDCR_EPHY;
237    // set reverse MII, enable MDIO statemachine
238    AMAZON_SW_REG32(AMAZON_SW_MDIO_CFG) = 0x800027bf;
239    while (1)
240        if (((AMAZON_SW_REG32(AMAZON_SW_MDIO_CFG)) & 0x80000000) == 0)
241            break;
242    AMAZON_SW_REG32(AMAZON_SW_EPHY) = 0xff;
243
244    // auto negotiation
245    AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) = 0x83e08000;
246    auto_negotiate(0x1f);
247
248    /* enable all ports */
249    AMAZON_SW_REG32(AMAZON_SW_PS_CTL) = 0x7;
250    for (i = 0; i < 32; i++)
251        write_mac_table_entry(i, 1 << 50);
252    return 0;
253}
254
255static unsigned char my_ethaddr[MAX_ADDR_LEN];
256/* need to get the ether addr from u-boot */
257static int __init ethaddr_setup(char *line)
258{
259    char *ep;
260    int i;
261
262    memset(my_ethaddr, 0, MAX_ADDR_LEN);
263    for (i = 0; i < 6; i++) {
264        my_ethaddr[i] = line ? simple_strtoul(line, &ep, 16) : 0;
265        if (line)
266            line = (*ep) ? ep + 1 : ep;
267    }
268    printk(KERN_INFO "amazon_mii0: mac address %2x-%2x-%2x-%2x-%2x-%2x \n", my_ethaddr[0], my_ethaddr[1], my_ethaddr[2], my_ethaddr[3], my_ethaddr[4], my_ethaddr[5]);
269    return 0;
270}
271
272__setup("ethaddr=", ethaddr_setup);
273
274static void open_rx_dma(struct net_device *dev)
275{
276    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
277    struct dma_device_info *dma_dev = priv->dma_device;
278    int i;
279
280    for (i = 0; i < dma_dev->num_rx_chan; i++)
281        dma_dev->rx_chan[i].control = 1;
282    dma_device_update_rx(dma_dev);
283}
284
285#ifdef CONFIG_NET_HW_FLOWCONTROL
286static void close_rx_dma(struct net_device *dev)
287{
288    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
289    struct dma_device_info *dma_dev = priv->dma_device;
290    int i;
291
292    for (i = 0; i < dma_dev->num_rx_chan; i++)
293        dma_dev->rx_chan[i].control = 0;
294    dma_device_update_rx(dma_dev);
295}
296
297void amazon_xon(struct net_device *dev)
298{
299    unsigned long flag;
300    local_irq_save(flag);
301    open_rx_dma(dev);
302    local_irq_restore(flag);
303}
304#endif
305
306int switch_open(struct net_device *dev)
307{
308    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
309    if (!strcmp(dev->name, "eth1")) {
310        priv->mdio_phy_addr = PHY0_ADDR;
311    }
312    open_rx_dma(dev);
313
314#ifdef CONFIG_NET_HW_FLOWCONTROL
315    if ((priv->fc_bit = netdev_register_fc(dev, amazon_xon)) == 0) {
316        printk(KERN_WARNING "amazon_mii0: Hardware Flow Control register fails\n");
317    }
318#endif
319
320    netif_start_queue(dev);
321    return OK;
322}
323
324int switch_release(struct net_device *dev)
325{
326    int i;
327    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
328    struct dma_device_info *dma_dev = priv->dma_device;
329
330    for (i = 0; i < dma_dev->num_tx_chan; i++)
331        dma_dev->tx_chan[i].control = 0;
332    for (i = 0; i < dma_dev->num_rx_chan; i++)
333        dma_dev->rx_chan[i].control = 0;
334
335    dma_device_update(dma_dev);
336
337#ifdef CONFIG_NET_HW_FLOWCONTROL
338    if (priv->fc_bit) {
339        netdev_unregister_fc(priv->fc_bit);
340    }
341#endif
342    netif_stop_queue(dev);
343
344    return OK;
345}
346
347
348void switch_rx(struct net_device *dev, int len, struct sk_buff *skb)
349{
350    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
351#ifdef CONFIG_NET_HW_FLOWCONTROL
352    int mit_sel = 0;
353#endif
354    skb->dev = dev;
355    skb->protocol = eth_type_trans(skb, dev);
356
357#ifdef CONFIG_NET_HW_FLOWCONTROL
358    mit_sel = netif_rx(skb);
359    switch (mit_sel) {
360    case NET_RX_SUCCESS:
361    case NET_RX_CN_LOW:
362    case NET_RX_CN_MOD:
363        break;
364    case NET_RX_CN_HIGH:
365        break;
366    case NET_RX_DROP:
367        if ((priv->fc_bit)
368            && (!test_and_set_bit(priv->fc_bit, &netdev_fc_xoff))) {
369            close_rx_dma(dev);
370        }
371        break;
372    }
373#else
374    netif_rx(skb);
375#endif
376    priv->stats.rx_packets++;
377    priv->stats.rx_bytes += len;
378    return;
379}
380
381int asmlinkage switch_hw_tx(char *buf, int len, struct net_device *dev)
382{
383    struct switch_priv *priv = netdev_priv(dev);
384    struct dma_device_info *dma_dev = priv->dma_device;
385
386    dma_dev->current_tx_chan = 0;
387    return dma_device_write(dma_dev, buf, len, priv->skb);
388}
389
390int asmlinkage switch_tx(struct sk_buff *skb, struct net_device *dev)
391{
392    int len;
393    char *data;
394    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
395
396    len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
397    data = skb->data;
398    priv->skb = skb;
399    dev->trans_start = jiffies;
400
401    if (switch_hw_tx(data, len, dev) != len) {
402        dev_kfree_skb_any(skb);
403        return OK;
404    }
405
406    priv->stats.tx_packets++;
407    priv->stats.tx_bytes += len;
408    return OK;
409}
410
411void switch_tx_timeout(struct net_device *dev)
412{
413    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
414    priv->stats.tx_errors++;
415    netif_wake_queue(dev);
416    return;
417}
418
419void negotiate(struct net_device *dev)
420{
421    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
422    unsigned short data = get_mdio_reg(priv->mdio_phy_addr, MDIO_ADVERTISMENT_REG);
423
424    data &= ~(MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD);
425
426    switch (priv->current_speed_selection) {
427    case 10:
428        if (priv->current_duplex == full)
429            data |= MDIO_ADVERT_10_FD;
430        else if (priv->current_duplex == half)
431            data |= MDIO_ADVERT_10_HD;
432        else
433            data |= MDIO_ADVERT_10_HD | MDIO_ADVERT_10_FD;
434        break;
435
436    case 100:
437        if (priv->current_duplex == full)
438            data |= MDIO_ADVERT_100_FD;
439        else if (priv->current_duplex == half)
440            data |= MDIO_ADVERT_100_HD;
441        else
442            data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD;
443        break;
444
445    case 0: /* Auto */
446        if (priv->current_duplex == full)
447            data |= MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD;
448        else if (priv->current_duplex == half)
449            data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_10_HD;
450        else
451            data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD;
452        break;
453
454    default: /* assume autoneg speed and duplex */
455        data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD;
456    }
457
458    set_mdio_reg(priv->mdio_phy_addr, MDIO_ADVERTISMENT_REG, data);
459
460    /* Renegotiate with link partner */
461
462    data = get_mdio_reg(priv->mdio_phy_addr, MDIO_BASE_CONTROL_REG);
463    data |= MDIO_BC_NEGOTIATE;
464
465    set_mdio_reg(priv->mdio_phy_addr, MDIO_BASE_CONTROL_REG, data);
466
467}
468
469
470void set_duplex(struct net_device *dev, enum duplex new_duplex)
471{
472    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
473    if (new_duplex != priv->current_duplex) {
474        priv->current_duplex = new_duplex;
475        negotiate(dev);
476    }
477}
478
479void set_speed(struct net_device *dev, unsigned long speed)
480{
481    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
482    priv->current_speed_selection = speed;
483    negotiate(dev);
484}
485
486static int switch_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
487{
488    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
489    struct ethtool_cmd ecmd;
490
491    if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd)))
492        return -EFAULT;
493
494    switch (ecmd.cmd) {
495    case ETHTOOL_GSET:
496        memset((void *) &ecmd, 0, sizeof(ecmd));
497        ecmd.supported = SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
498                        SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
499        ecmd.port = PORT_TP;
500        ecmd.transceiver = XCVR_EXTERNAL;
501        ecmd.phy_address = priv->mdio_phy_addr;
502
503        ecmd.speed = priv->current_speed;
504
505        ecmd.duplex = priv->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
506
507        ecmd.advertising = ADVERTISED_TP;
508        if (priv->current_duplex == autoneg && priv->current_speed_selection == 0)
509            ecmd.advertising |= ADVERTISED_Autoneg;
510        else {
511            ecmd.advertising |= ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
512                ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
513            if (priv->current_speed_selection == 10)
514                ecmd.advertising &= ~(ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full);
515            else if (priv->current_speed_selection == 100)
516                ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full);
517            if (priv->current_duplex == half)
518                ecmd.advertising &= ~(ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Full);
519            else if (priv->current_duplex == full)
520                ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_100baseT_Half);
521        }
522        ecmd.autoneg = AUTONEG_ENABLE;
523        if (copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd)))
524            return -EFAULT;
525        break;
526
527    case ETHTOOL_SSET:
528        if (!capable(CAP_NET_ADMIN)) {
529            return -EPERM;
530        }
531        if (ecmd.autoneg == AUTONEG_ENABLE) {
532            set_duplex(dev, autoneg);
533            set_speed(dev, 0);
534        } else {
535            set_duplex(dev, ecmd.duplex == DUPLEX_HALF ? half : full);
536            set_speed(dev, ecmd.speed == SPEED_10 ? 10 : 100);
537        }
538        break;
539
540    case ETHTOOL_GDRVINFO:
541        {
542            struct ethtool_drvinfo info;
543            memset((void *) &info, 0, sizeof(info));
544            strncpy(info.driver, "AMAZONE", sizeof(info.driver) - 1);
545            strncpy(info.fw_version, "N/A", sizeof(info.fw_version) - 1);
546            strncpy(info.bus_info, "N/A", sizeof(info.bus_info) - 1);
547            info.regdump_len = 0;
548            info.eedump_len = 0;
549            info.testinfo_len = 0;
550            if (copy_to_user(ifr->ifr_data, &info, sizeof(info)))
551                return -EFAULT;
552        }
553        break;
554    case ETHTOOL_NWAY_RST:
555        if (priv->current_duplex == autoneg && priv->current_speed_selection == 0)
556            negotiate(dev);
557        break;
558    default:
559        return -EOPNOTSUPP;
560        break;
561    }
562    return 0;
563}
564
565
566
567int mac_table_tools_ioctl(struct net_device *dev, struct mac_table_req *req)
568{
569    int cmd;
570    int i;
571    cmd = req->cmd;
572    switch (cmd) {
573    case RESET_MAC_TABLE:
574        for (i = 0; i < 32; i++) {
575            write_mac_table_entry(i, 0);
576        }
577        break;
578    case READ_MAC_ENTRY:
579        req->entry_value = read_mac_table_entry(req->index);
580        break;
581    case WRITE_MAC_ENTRY:
582        write_mac_table_entry(req->index, req->entry_value);
583        break;
584    case ADD_MAC_ENTRY:
585        add_mac_table_entry(req->entry_value);
586        break;
587    default:
588        return -EINVAL;
589    }
590
591    return 0;
592}
593
594
595/*
596    the ioctl for the switch driver is developed in the conventional way
597    the control type falls into some basic categories, among them, the
598    SIOCETHTOOL is the traditional eth interface. VLAN_TOOLS and
599    MAC_TABLE_TOOLS are designed specifically for amazon chip. User
600    should be aware of the data structures used in these interfaces.
601*/
602int switch_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
603{
604    struct data_req *switch_data_req = (struct data_req *) ifr->ifr_data;
605    struct mac_table_req *switch_mac_table_req;
606    switch (cmd) {
607    case SIOCETHTOOL:
608        switch_ethtool_ioctl(dev, ifr);
609        break;
610    case SIOCGMIIPHY: /* Get PHY address */
611        break;
612    case SIOCGMIIREG: /* Read MII register */
613        break;
614    case SIOCSMIIREG: /* Write MII register */
615        break;
616    case SET_ETH_SPEED_10: /* 10 Mbps */
617        break;
618    case SET_ETH_SPEED_100: /* 100 Mbps */
619        break;
620    case SET_ETH_SPEED_AUTO: /* Auto negotiate speed */
621        break;
622    case SET_ETH_DUPLEX_HALF: /* Half duplex. */
623        break;
624    case SET_ETH_DUPLEX_FULL: /* Full duplex. */
625        break;
626    case SET_ETH_DUPLEX_AUTO: /* Autonegotiate duplex */
627        break;
628    case SET_ETH_REG:
629        AMAZON_SW_REG32(switch_data_req->index) = switch_data_req->value;
630        break;
631    case MAC_TABLE_TOOLS:
632        switch_mac_table_req = (struct mac_table_req *) ifr->ifr_data;
633        mac_table_tools_ioctl(dev, switch_mac_table_req);
634        break;
635    default:
636        return -EINVAL;
637    }
638
639    return 0;
640}
641
642struct net_device_stats *switch_stats(struct net_device *dev)
643{
644    struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
645    return &priv->stats;
646}
647
648int switch_change_mtu(struct net_device *dev, int new_mtu)
649{
650    if (new_mtu >= 1516)
651        new_mtu = 1516;
652    dev->mtu = new_mtu;
653    return 0;
654}
655
656int switch_hw_receive(struct net_device *dev, struct dma_device_info *dma_dev)
657{
658    u8 *buf = NULL;
659    int len = 0;
660    struct sk_buff *skb = NULL;
661
662    len = dma_device_read(dma_dev, &buf, (void **) &skb);
663
664    if (len >= 0x600) {
665        printk(KERN_WARNING "amazon_mii0: packet too large %d\n", len);
666        goto switch_hw_receive_err_exit;
667    }
668
669    /* remove CRC */
670    len -= 4;
671    if (skb == NULL) {
672        printk(KERN_WARNING "amazon_mii0: cannot restore pointer\n");
673        goto switch_hw_receive_err_exit;
674    }
675    if (len > (skb->end - skb->tail)) {
676        printk(KERN_WARNING "amazon_mii0: BUG, len:%d end:%p tail:%p\n", (len + 4), skb->end, skb->tail);
677        goto switch_hw_receive_err_exit;
678    }
679    skb_put(skb, len);
680    skb->dev = dev;
681    switch_rx(dev, len, skb);
682    return OK;
683  
684  switch_hw_receive_err_exit:
685    if (skb)
686        dev_kfree_skb_any(skb);
687    return -EIO;
688}
689
690int dma_intr_handler(struct dma_device_info *dma_dev, int status)
691{
692    struct net_device *dev;
693
694    dev = dma_dev->priv;
695    switch (status) {
696    case RCV_INT:
697        switch_hw_receive(dev, dma_dev);
698        break;
699    case TX_BUF_FULL_INT:
700        netif_stop_queue(dev);
701        break;
702    case TRANSMIT_CPT_INT:
703        netif_wake_queue(dev);
704        break;
705    }
706    return OK;
707}
708
709/* reserve 2 bytes in front of data pointer*/
710u8 *dma_buffer_alloc(int len, int *byte_offset, void **opt)
711{
712    u8 *buffer = NULL;
713    struct sk_buff *skb = NULL;
714    skb = dev_alloc_skb(ETHERNET_PACKET_DMA_BUFFER_SIZE);
715    if (skb == NULL) {
716        return NULL;
717    }
718    buffer = (u8 *) (skb->data);
719    skb_reserve(skb, 2);
720    *(int *) opt = (int) skb;
721    *byte_offset = 2;
722    return buffer;
723}
724
725int dma_buffer_free(u8 * dataptr, void *opt)
726{
727    struct sk_buff *skb = NULL;
728    if (opt == NULL) {
729        kfree(dataptr);
730    } else {
731        skb = (struct sk_buff *) opt;
732        dev_kfree_skb_any(skb);
733    }
734    return OK;
735}
736
737int init_dma_device(_dma_device_info * dma_dev, struct net_device *dev)
738{
739    int i;
740    int num_tx_chan, num_rx_chan;
741    if (strcmp(dma_dev->device_name, "switch1") == 0) {
742        num_tx_chan = 1;
743        num_rx_chan = 2;
744    } else {
745        num_tx_chan = 1;
746        num_rx_chan = 2;
747    }
748    dma_dev->priv = dev;
749
750    dma_dev->weight = 1;
751    dma_dev->num_tx_chan = num_tx_chan;
752    dma_dev->num_rx_chan = num_rx_chan;
753    dma_dev->ack = 1;
754    dma_dev->tx_burst_len = 4;
755    dma_dev->rx_burst_len = 4;
756    for (i = 0; i < dma_dev->num_tx_chan; i++) {
757        dma_dev->tx_chan[i].weight = QOS_DEFAULT_WGT;
758        dma_dev->tx_chan[i].desc_num = 10;
759        dma_dev->tx_chan[i].packet_size = 0;
760        dma_dev->tx_chan[i].control = 0;
761    }
762    for (i = 0; i < num_rx_chan; i++) {
763        dma_dev->rx_chan[i].weight = QOS_DEFAULT_WGT;
764        dma_dev->rx_chan[i].desc_num = 10;
765        dma_dev->rx_chan[i].packet_size = ETHERNET_PACKET_DMA_BUFFER_SIZE;
766        dma_dev->rx_chan[i].control = 0;
767    }
768    dma_dev->intr_handler = dma_intr_handler;
769    dma_dev->buffer_alloc = dma_buffer_alloc;
770    dma_dev->buffer_free = dma_buffer_free;
771    return 0;
772}
773
774int switch_set_mac_address(struct net_device *dev, void *p)
775{
776    struct sockaddr *addr = p;
777    memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
778    return OK;
779}
780
781static const struct net_device_ops amazon_mii_ops = {
782    .ndo_init = switch_init,
783    .ndo_open = switch_open,
784    .ndo_stop = switch_release,
785    .ndo_start_xmit = switch_tx,
786    .ndo_do_ioctl = switch_ioctl,
787    .ndo_get_stats = switch_stats,
788    .ndo_change_mtu = switch_change_mtu,
789    .ndo_set_mac_address = switch_set_mac_address,
790    .ndo_tx_timeout = switch_tx_timeout,
791};
792
793int switch_init(struct net_device *dev)
794{
795    u64 retval = 0;
796    int i;
797    int result;
798    struct switch_priv *priv;
799    ether_setup(dev); /* assign some of the fields */
800    printk(KERN_INFO "amazon_mii0: %s up using ", dev->name);
801    dev->watchdog_timeo = timeout;
802
803    priv = netdev_priv(dev);
804    priv->dma_device = (struct dma_device_info *) kmalloc(sizeof(struct dma_device_info), GFP_KERNEL);
805    if (priv->num == 0) {
806        sprintf(priv->dma_device->device_name, "switch1");
807    } else if (priv->num == 1) {
808        sprintf(priv->dma_device->device_name, "switch2");
809    }
810    printk("\"%s\"\n", priv->dma_device->device_name);
811    init_dma_device(priv->dma_device, dev);
812    result = dma_device_register(priv->dma_device);
813
814    /* read the mac address from the mac table and put them into the mac table. */
815    for (i = 0; i < 6; i++) {
816        retval += my_ethaddr[i];
817    }
818    /* ethaddr not set in u-boot ? */
819    if (retval == 0) {
820        dev->dev_addr[0] = 0x00;
821        dev->dev_addr[1] = 0x20;
822        dev->dev_addr[2] = 0xda;
823        dev->dev_addr[3] = 0x86;
824        dev->dev_addr[4] = 0x23;
825        dev->dev_addr[5] = 0x74 + (unsigned char) priv->num;
826    } else {
827        for (i = 0; i < 6; i++) {
828            dev->dev_addr[i] = my_ethaddr[i];
829        }
830        dev->dev_addr[5] += +(unsigned char) priv->num;
831    }
832    return OK;
833}
834
835static int amazon_mii_probe(struct platform_device *dev)
836{
837    int i = 0, result, device_present = 0;
838    struct switch_priv *priv;
839
840    for (i = 0; i < AMAZON_SW_INT_NO; i++) {
841        switch_devs[i] = alloc_etherdev(sizeof(struct switch_priv));
842        switch_devs[i]->netdev_ops = &amazon_mii_ops;
843        strcpy(switch_devs[i]->name, "eth%d");
844        priv = (struct switch_priv *) netdev_priv(switch_devs[i]);
845        priv->num = i;
846        if ((result = register_netdev(switch_devs[i])))
847            printk(KERN_WARNING "amazon_mii0: error %i registering device \"%s\"\n", result, switch_devs[i]->name);
848        else
849            device_present++;
850    }
851    amazon_sw_chip_init();
852    return device_present ? 0 : -ENODEV;
853}
854
855static int amazon_mii_remove(struct platform_device *dev)
856{
857    int i;
858    struct switch_priv *priv;
859    for (i = 0; i < AMAZON_SW_INT_NO; i++) {
860        priv = netdev_priv(switch_devs[i]);
861        if (priv->dma_device) {
862            dma_device_unregister(priv->dma_device);
863            kfree(priv->dma_device);
864        }
865        kfree(netdev_priv(switch_devs[i]));
866        unregister_netdev(switch_devs[i]);
867    }
868    return 0;
869}
870
871static struct platform_driver amazon_mii_driver = {
872    .probe = amazon_mii_probe,
873    .remove = amazon_mii_remove,
874    .driver = {
875        .name = "amazon_mii0",
876        .owner = THIS_MODULE,
877    },
878};
879
880static int __init amazon_mii_init(void)
881{
882    int ret = platform_driver_register(&amazon_mii_driver);
883    if (ret)
884        printk(KERN_WARNING "amazon_mii0: Error registering platfom driver!\n");
885    return ret;
886}
887
888static void __exit amazon_mii_cleanup(void)
889{
890    platform_driver_unregister(&amazon_mii_driver);
891}
892
893module_init(amazon_mii_init);
894module_exit(amazon_mii_cleanup);
895
896MODULE_LICENSE("GPL");
897MODULE_AUTHOR("Wu Qi Ming");
898MODULE_DESCRIPTION("ethernet driver for AMAZON boards");
899
900

Archive Download this file



interactive