123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575 |
- /***************************************************************************************
- amlogic networks .....
- add by zhouzhi 2008-8-18
- ***************************************************************************************/
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/string.h>
- #include <linux/slab.h>
- #include <linux/interrupt.h>
- #include <linux/netdevice.h>
- #include <linux/etherdevice.h>
- #include <linux/io.h>
- #include <linux/mii.h>
- #include <asm/delay.h>
- #include <mach/pinmux.h>
- #include <linux/sched.h>
- #include <linux/pm.h>
- #include <linux/crc32.h>
- #include <linux/platform_device.h>
- #include <plat/eth.h>
- #include <mach/reg_addr.h>
- #include <plat/regops.h>
- #include "am_net8218.h"
- // >0 for basic init and remove debug;
- // >1 further setting debug;
- // >2 for tx
- // >3 for rx
- #ifdef CONFIG_AM_ETHERNET_DEBUG_LEVEL
- static int debug = CONFIG_AM_ETHERNET_DEBUG_LEVEL;
- #else
- static int debug = 1;
- #endif
- //#define LOOP_BACK_TEST
- //#define MAC_LOOPBACK_TEST
- //#define PHY_LOOPBACK_TEST
- void start_test(struct net_device *dev);
- static int running = 0;
- static struct net_device *my_ndev = NULL;
- static unsigned int g_mac_setup = 0;
- static char DEFMAC[] = "\x00\x01\x23\xcd\xee\xaf";
- #define MODULE_NAME "ethernet"
- #define DRIVER_NAME "ethernet"
- #define DRV_NAME DRIVER_NAME
- #define DRV_VERSION "v2.0.0"
- #define DRV_RELDATE "2008-8-28"
- MODULE_AUTHOR("rising_o<zhi_zhou@amlogic.com>");
- MODULE_DESCRIPTION("Amlogic Ethernet Driver");
- MODULE_LICENSE("Amlogic");
- MODULE_VERSION(DRV_VERSION);
- module_param_named(amlog_level, debug, int, 0664);
- MODULE_PARM_DESC(amlog_level, "ethernet debug level\n");
- #define PERIPHS_SET_BITS(reg, mask) \
- aml_set_reg32_mask(reg, mask)
- #define PERIPHS_CLEAR_BITS(reg, mask) \
- aml_clr_reg32_mask(reg, mask)
- static void write_mac_addr(struct net_device *dev, char *macaddr);
- static int ethernet_reset(struct net_device *dev);
- static int mdio_read(struct net_device *dev, int phyid, int reg)
- {
- #define WR (1<<1)
- #define MDCCLK (0x1) << 2 //our 130 MHz
- #define BUSY 0x1
- struct am_net_private *priv = netdev_priv(dev);
- unsigned long busy = 0;
- unsigned long reg4;
- unsigned long val = 0;
- reg4 = phyid << 11 | reg << 6 | MDCCLK | BUSY;
- /*
- do{ //waiting the phy is ready to write ...
- busy=IO_READ32(priv->base_addr+ETH_MAC_4_GMII_Addr);
- }while(busy&0x1);
- */
- IO_WRITE32(reg4, priv->base_addr + ETH_MAC_4_GMII_Addr);
- do { //waiting the phy is ready to write ...
- busy = IO_READ32(priv->base_addr + ETH_MAC_4_GMII_Addr);
- } while (busy & 0x1);
- val = IO_READ32(priv->base_addr + ETH_MAC_5_GMII_Data) & 0xffff;
- return val;
- }
- static void mdio_write(struct net_device *dev, int phyid, int reg, int val)
- {
- #define WR (1<<1)
- #define MDCCLK (0x1) << 2 //our 130 MHz
- #define BUSY 0x1
- struct am_net_private *priv = netdev_priv(dev);
- unsigned long busy = 0;
- unsigned long reg4;
- reg4 = phyid << 11 | reg << 6 | MDCCLK | WR | BUSY;
- IO_WRITE32(val, priv->base_addr + ETH_MAC_5_GMII_Data);
- do { //waiting the phy is ready to write ...
- busy = IO_READ32(priv->base_addr + ETH_MAC_4_GMII_Addr);
- } while (busy & 0x1);
- IO_WRITE32(reg4, priv->base_addr + ETH_MAC_4_GMII_Addr);
- do { //waiting the phy is ready to write ...
- busy = IO_READ32(priv->base_addr + ETH_MAC_4_GMII_Addr);
- } while (busy & 0x1);
- }
- static void dump(unsigned char *p, int len)
- {
- int i, j;
- char s[20];
- for (i = 0; i < len; i += 16) {
- printk("%08x:", (unsigned int)p);
- for (j = 0; j < 16 && j < len - 0 * 16; j++) {
- s[j] = (p[j] > 15 && p[j] < 128) ? p[j] : '.';
- printk(" %02x", p[j]);
- }
- s[j] = 0;
- printk(" |%s|\n", s);
- p = p + 16;
- }
- }
- static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
- {
- struct mii_ioctl_data *data = if_mii(rq);
- struct am_net_private *np = netdev_priv(dev);
- char addr[MAX_ADDR_LEN];
- if (debug > 0)
- printk("Ethernet Driver ioctl (%x) \n", cmd);
- switch (cmd) {
- case SIOCGMIIPHY: /* Get address of MII PHY in use. */
- data->phy_id =
- ((struct am_net_private *)netdev_priv(dev))->phys[0] & 0x1f;
- /* Fall Through */
- case SIOCGMIIREG: /* Read MII PHY register. */
- spin_lock_irq(&np->lock);
- data->val_out =
- mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
- spin_unlock_irq(&np->lock);
- return 0;
- case SIOCSMIIREG: /* Write MII PHY register. */
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- spin_lock_irq(&np->lock);
- mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f,
- data->val_in);
- spin_unlock_irq(&np->lock);
- return 0;
- case SIOCSIFHWADDR:
- if (copy_from_user(&addr,
- (void __user *)rq->ifr_hwaddr.sa_data,
- MAX_ADDR_LEN)) {
- return -EFAULT;
- }
- if (debug > 0)
- printk
- ("set mac addr to %02x:%02x:%02x:%02x:%02x:%02x\n",
- addr[0], addr[1], addr[2], addr[3], addr[4],
- addr[5]);
- spin_lock_irq(&np->lock);
- memcpy(dev->dev_addr, &addr, MAX_ADDR_LEN);
- write_mac_addr(dev, addr);
- spin_unlock_irq(&np->lock);
- default:
- if (debug > 0)
- printk("Ethernet Driver unknow ioctl (%x) \n", cmd);
- return -EOPNOTSUPP;
- }
- return 0;
- }
- int init_rxtx_rings(struct net_device *dev)
- {
- struct am_net_private *np = netdev_priv(dev);
- int i;
- #ifndef DMA_USE_SKB_BUF
- unsigned long tx = 0, rx = 0;
- #endif
- #ifdef DMA_USE_MALLOC_ADDR
- rx = (unsigned long)kmalloc((RX_RING_SIZE) * np->rx_buf_sz, GFP_KERNEL);
- if (rx == 0) {
- printk("error to alloc Rx ring buf\n");
- return -1;
- }
- tx = (unsigned long)kmalloc((TX_RING_SIZE) * np->rx_buf_sz, GFP_KERNEL);
- if (tx == 0) {
- kfree((void *)rx);
- printk("error to alloc Tx ring buf\n");
- return -1;
- }
- #elif defined(DMA_USE_SKB_BUF)
- //not needed
- #else
- tx = TX_BUF_ADDR;
- rx = RX_BUF_ADDR;
- #endif
- /* Fill in the Rx buffers. Handle allocation failure gracefully. */
- for (i = 0; i < RX_RING_SIZE; i++) {
- #ifdef DMA_USE_SKB_BUF
- struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);
- np->rx_ring[i].skb = skb;
- if (skb == NULL)
- break;
- skb_reserve(skb, 2); /* 16 byte alignd for ip */
- skb->dev = dev; /* Mark as being used by this device. */
- np->rx_ring[i].buf = (unsigned long)skb->data;
- #else
- np->rx_ring[i].skb = NULL;
- np->rx_ring[i].buf = (rx + i * np->rx_buf_sz); //(unsigned long )skb->data;
- #endif
- np->rx_ring[i].buf_dma =
- dma_map_single(&dev->dev, (void *)np->rx_ring[i].buf,
- np->rx_buf_sz, DMA_FROM_DEVICE);
- np->rx_ring[i].count =
- (DescChain) | (np->rx_buf_sz & DescSize1Mask);
- np->rx_ring[i].status = (DescOwnByDma);
- np->rx_ring[i].next_dma = &np->rx_ring_dma[i + 1];
- np->rx_ring[i].next = &np->rx_ring[i + 1];
- }
- np->rx_ring[RX_RING_SIZE - 1].next_dma = &np->rx_ring_dma[0];
- np->rx_ring[RX_RING_SIZE - 1].next = &np->rx_ring[0];
- /* Initialize the Tx descriptors */
- for (i = 0; i < TX_RING_SIZE; i++) {
- #ifdef DMA_USE_SKB_BUF
- np->tx_ring[i].buf = 0;
- #else
- np->tx_ring[i].buf = (tx + i * np->rx_buf_sz);
- #endif
- np->tx_ring[i].status = 0;
- np->tx_ring[i].count =
- (DescChain) | (np->rx_buf_sz & DescSize1Mask);
- np->tx_ring[i].next_dma = &np->tx_ring_dma[i + 1];
- np->tx_ring[i].next = &np->tx_ring[i + 1];
- np->tx_ring[i].skb = NULL;
- }
- np->tx_ring[TX_RING_SIZE - 1].next_dma = &np->tx_ring_dma[0];
- np->tx_ring[TX_RING_SIZE - 1].next = &np->tx_ring[0];
- np->start_tx = &np->tx_ring[0];
- np->last_tx = NULL;
- np->last_rx = &np->rx_ring[RX_RING_SIZE - 1];
- CACHE_WSYNC(np->tx_ring, sizeof(struct _tx_desc) * TX_RING_SIZE);
- CACHE_WSYNC(np->rx_ring, sizeof(struct _rx_desc) * RX_RING_SIZE);
- return 0;
- }
- EXPORT_SYMBOL(init_rxtx_rings);
- static int alloc_ringdesc(struct net_device *dev)
- {
- struct am_net_private *np = netdev_priv(dev);
- np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
- #ifdef USE_COHERENT_MEMORY
- np->rx_ring = dma_alloc_coherent(&dev->dev,
- sizeof(struct _rx_desc) * RX_RING_SIZE,
- (dma_addr_t *) & np->rx_ring_dma,
- GFP_KERNEL);
- #else
- np->rx_ring =
- kmalloc(sizeof(struct _rx_desc) * RX_RING_SIZE, GFP_KERNEL);
- np->rx_ring_dma = (void *)virt_to_phys(np->rx_ring);
- #endif
- if (!np->rx_ring)
- return -ENOMEM;
- if (!IS_CACHE_ALIGNED(np->rx_ring)) {
- printk("Error the alloc mem is not cache aligned(%p)\n",
- np->rx_ring);
- }
- printk("NET MDA descpter start addr=%p\n", np->rx_ring);
- #ifdef USE_COHERENT_MEMORY
- np->tx_ring = dma_alloc_coherent(&dev->dev,
- sizeof(struct _tx_desc) * TX_RING_SIZE,
- (dma_addr_t *) & np->tx_ring_dma,
- GFP_KERNEL);
- #else
- np->tx_ring =
- kmalloc(sizeof(struct _tx_desc) * TX_RING_SIZE, GFP_KERNEL);
- np->tx_ring_dma = (void *)virt_to_phys(np->tx_ring);
- #endif
- if (init_rxtx_rings(dev)) {
- printk("init rx tx ring failed!!\n");
- return -1;
- }
- //make sure all the data are write to memory
- return 0;
- }
- static int free_ringdesc(struct net_device *dev)
- {
- struct am_net_private *np = netdev_priv(dev);
- int i;
- for (i = 0; i < RX_RING_SIZE; i++) {
- if (np->rx_ring[i].skb) {
- dev_kfree_skb_any(np->rx_ring[i].skb);
- if (np->rx_ring[i].buf_dma != 0)
- dma_unmap_single(&dev->dev,
- np->rx_ring[i].buf_dma,
- np->rx_buf_sz,
- DMA_FROM_DEVICE);
- }
- np->rx_ring[i].skb = NULL;
- }
- for (i = 0; i < TX_RING_SIZE; i++) {
- if (np->tx_ring[i].skb != NULL) {
- dev_kfree_skb_any(np->tx_ring[i].skb);
- if (np->rx_ring[i].buf_dma != 0)
- dma_unmap_single(&dev->dev,
- np->tx_ring[i].buf_dma,
- np->rx_buf_sz, DMA_TO_DEVICE);
- }
- np->tx_ring[i].skb = NULL;
- }
- if (np->rx_ring) {
- #ifdef USE_COHERENT_MEMORY
- dma_free_coherent(&dev->dev, sizeof(struct _rx_desc) * RX_RING_SIZE, np->rx_ring, (dma_addr_t) np->rx_ring_dma); // for apollo
- #else
- kfree(np->rx_ring);
- #endif
- }
- np->rx_ring = NULL;
- if (np->tx_ring) {
- #ifdef USE_COHERENT_MEMORY
- dma_free_coherent(&dev->dev, sizeof(struct _tx_desc) * TX_RING_SIZE, np->tx_ring, (dma_addr_t) np->tx_ring_dma); // for apollo
- #else
- kfree(np->tx_ring);
- #endif
- }
- np->tx_ring = NULL;
- return 0;
- }
- static int phy_linked(struct am_net_private *np)
- {
- unsigned int val;
- switch (np->phy_Identifier) {
- case PHY_ATHEROS_8032:
- val = mdio_read(np->dev, np->phys[0], 17);
- val = (val & (1 << 10));
- break;
- case PHY_SMSC_8700:
- case PHY_SMSC_8720:
- default:
- val = mdio_read(np->dev, np->phys[0], 1);
- val = (val & (1 << 2));
- }
- return val;
- }
- static int mac_PLL_changed(struct am_net_private *np, int clk_mhz)
- {
- unsigned long tmp;
- switch (clk_mhz) {
- case 0: //disable clock
- PERIPHS_CLEAR_BITS(P_PREG_ETHERNET_ADDR0, 1); //disable clk
- PERIPHS_CLEAR_BITS(P_PREG_ETHERNET_ADDR0,
- (1 << 0 | 1 << 2 | 1 << 3));
- break;
- case 10:
- if (debug > 0)
- printk("10m\n");
- //(*ETH_MAC_0_Configuration) &= ~(1<<14); // program mac
- tmp = IO_READ32(np->base_addr + ETH_MAC_0_Configuration);
- tmp &= ~(1 << 14);
- IO_WRITE32(tmp, np->base_addr + ETH_MAC_0_Configuration);
- PERIPHS_CLEAR_BITS(P_PREG_ETHERNET_ADDR0, 1);
- PERIPHS_CLEAR_BITS(P_PREG_ETHERNET_ADDR0, (1 << 1));
- PERIPHS_SET_BITS(P_PREG_ETHERNET_ADDR0, 1);
- break;
- case 100:
- default:
- if (debug > 0)
- printk("100m\n");
- //(*ETH_MAC_0_Configuration) |= 1<<14; // program mac
- tmp = IO_READ32(np->base_addr + ETH_MAC_0_Configuration);
- tmp |= 1 << 14;
- IO_WRITE32(tmp, np->base_addr + ETH_MAC_0_Configuration);
- PERIPHS_CLEAR_BITS(P_PREG_ETHERNET_ADDR0, 1);
- PERIPHS_SET_BITS(P_PREG_ETHERNET_ADDR0, (1 << 1));
- PERIPHS_SET_BITS(P_PREG_ETHERNET_ADDR0, 1);
- }
- udelay(10);
- return 0;
- }
- static void phy_auto_negotiation_set(struct am_net_private *np)
- {
- unsigned int rint;
- int s100, full, tmp;
- switch (np->phy_Identifier) {
- case PHY_ATHEROS_8032:
- rint = mdio_read(np->dev, np->phys[0], 0x11);
- s100 = rint & (1 << 14);
- full = ((rint) & (1 << 13));
- break;
- case PHY_SMSC_8700:
- case PHY_SMSC_8720:
- default:
- rint = mdio_read(np->dev, np->phys[0], 31);
- s100 = rint & (1 << 3);
- full = ((rint >> 4) & 1);
- break;
- }
- if (full) {
- if (debug > 0)
- printk("duplex\n");
- //(*ETH_MAC_0_Configuration) |= 1<<11; // program mac
- tmp = IO_READ32(np->base_addr + ETH_MAC_0_Configuration);
- tmp |= 1 << 11;
- IO_WRITE32(tmp, np->base_addr + ETH_MAC_0_Configuration);
- } else {
- if (debug > 0)
- printk("half duplex\n");
- //(*ETH_MAC_0_Configuration) &= ~(1<<11) ; // program mac
- tmp = IO_READ32(np->base_addr + ETH_MAC_0_Configuration);
- tmp &= ~(1 << 11);
- IO_WRITE32(tmp, np->base_addr + ETH_MAC_0_Configuration);
- }
- mac_PLL_changed(np, s100 ? 100 : 10);
- return;
- }
- static void netdev_timer(unsigned long data)
- {
- struct net_device *dev = (struct net_device *)data;
- struct am_net_private *np = netdev_priv(dev);
- unsigned long ioaddr = np->base_addr;
- static int error_num = 0;
- int val;
- if (debug > 2)
- printk(KERN_DEBUG
- "%s: Media selection timer tick, mac status %8.8x \n",
- dev->name, ioread32(ioaddr + ETH_DMA_5_Status));
- if (!phy_linked(np)) { //unlink .....
- error_num++;
- if (error_num > 30) {
- error_num = 0;
- spin_lock_irq(&np->lock);
- val = (1 << 14) | (7 << 5) | np->phys[0];
- mdio_write(dev, np->phys[0], 18, val);
- // Auto negotiation restart
- val = mdio_read(dev, np->phys[0], MII_BMCR);
- #ifdef PHY_LOOPBACK_TEST
- val = 1 << 14 | 1 << 8 | 1 << 13; //100M,full,seting it as
- #else
- val |= BMCR_ANENABLE | BMCR_ANRESTART;
- #endif
- mdio_write(dev, np->phys[0], MII_BMCR, val);
- spin_unlock_irq(&np->lock);
- }
- np->timer.expires = jiffies + 1 * HZ;
- netif_stop_queue(dev);
- netif_carrier_off(dev);
- np->phy_set[0] = 0;
- } else { //linked
- val = mdio_read(dev, np->phys[0], 1);
- if (np->phy_set[0] != val) {
- np->phy_set[0] = val;
- phy_auto_negotiation_set(np);
- }
- error_num = 0;
- netif_carrier_on(dev);
- netif_start_queue(dev);
- np->timer.expires = jiffies + 1 * HZ;
- }
- add_timer(&np->timer);
- }
- static inline int update_status(struct net_device *dev, unsigned long status,
- unsigned long mask)
- {
- struct am_net_private *np = netdev_priv(dev);
- int need_reset = 0;
- int need_rx_restart = 0;
- int res = 0;
- if (status & NOR_INTR_EN) //Normal Interrupts Process
- {
- if (status & TX_INTR_EN) //Transmit Interrupt Process
- {
- IO_WRITE32((1 << 0 | 1 << 16),
- np->base_addr + ETH_DMA_5_Status);
- res |= 1;
- }
- if (status & RX_INTR_EN) //Receive Interrupt Process
- {
- IO_WRITE32((1 << 6 | 1 << 16),
- np->base_addr + ETH_DMA_5_Status);
- res |= 2;
- }
- if (status & EARLY_RX_INTR_EN) {
- IO_WRITE32((EARLY_RX_INTR_EN | NOR_INTR_EN),
- np->base_addr + ETH_DMA_5_Status);
- }
- if (status & TX_BUF_UN_EN) {
- IO_WRITE32((1 << 2 | 1 << 16),
- np->base_addr + ETH_DMA_5_Status);
- res |= 1;
- //this error will cleard in start tx...
- if (debug > 1)
- printk(KERN_WARNING "[" DRV_NAME "]"
- "Tx bufer unenable\n");
- }
- } else if (status & ANOR_INTR_EN) //Abnormal Interrupts Process
- {
- if (status & RX_BUF_UN) {
- IO_WRITE32((RX_BUF_UN | ANOR_INTR_EN),
- np->base_addr + ETH_DMA_5_Status);
- np->stats.rx_over_errors++;
- need_rx_restart++;
- res |= 2;
- //printk(KERN_WARNING DRV_NAME "Receive Buffer Unavailable\n");
- if (debug > 1)
- printk(KERN_WARNING "[" DRV_NAME "]"
- "Rx bufer unenable\n");
- }
- if (status & RX_STOP_EN) {
- IO_WRITE32((RX_STOP_EN | ANOR_INTR_EN),
- np->base_addr + ETH_DMA_5_Status);
- need_rx_restart++;
- res |= 2;
- }
- if (status & RX_WATCH_TIMEOUT) {
- IO_WRITE32((RX_WATCH_TIMEOUT | ANOR_INTR_EN),
- np->base_addr + ETH_DMA_5_Status);
- need_rx_restart++;
- }
- if (status & FATAL_BUS_ERROR) {
- IO_WRITE32((FATAL_BUS_ERROR | ANOR_INTR_EN),
- np->base_addr + ETH_DMA_5_Status);
- need_reset++;
- printk(KERN_WARNING "[" DRV_NAME "]"
- "fatal bus error\n");
- }
- if (status & EARLY_TX_INTR_EN) {
- IO_WRITE32((EARLY_TX_INTR_EN | ANOR_INTR_EN),
- np->base_addr + ETH_DMA_5_Status);
- }
- if (status & TX_STOP_EN) {
- IO_WRITE32((TX_STOP_EN | ANOR_INTR_EN),
- np->base_addr + ETH_DMA_5_Status);
- res |= 1;
- }
- if (status & TX_JABBER_TIMEOUT) {
- IO_WRITE32((TX_JABBER_TIMEOUT | ANOR_INTR_EN),
- np->base_addr + ETH_DMA_5_Status);
- printk(KERN_WARNING "[" DRV_NAME "]"
- "tx jabber timeout\n");
- np->first_tx = 1;
- }
- if (status & RX_FIFO_OVER) {
- IO_WRITE32((RX_FIFO_OVER | ANOR_INTR_EN),
- np->base_addr + ETH_DMA_5_Status);
- np->stats.rx_fifo_errors++;
- need_rx_restart++;
- res |= 2;
- printk(KERN_WARNING "[" DRV_NAME "]" "Rx fifo over\n");
- }
- if (status & TX_UNDERFLOW) {
- IO_WRITE32((TX_UNDERFLOW | ANOR_INTR_EN),
- np->base_addr + ETH_DMA_5_Status);
- printk(KERN_WARNING "[" DRV_NAME "]" "Tx underflow\n");
- np->first_tx = 1;
- res |= 1;
- }
- }
- if (need_reset) {
- printk(KERN_WARNING DRV_NAME "system reset\n");
- free_ringdesc(dev);
- ethernet_reset(dev);
- } else if (need_rx_restart) {
- IO_WRITE32(1, np->base_addr + ETH_DMA_2_Re_Poll_Demand);
- }
- return res;
- }
- static void inline print_rx_error_log(unsigned long status)
- {
- if (status & DescRxTruncated) {
- printk(KERN_WARNING "Descriptor Error desc-mask[%d]\n",
- DescRxTruncated);
- }
- if (status & DescSAFilterFail) {
- printk(KERN_WARNING
- "Source Address Filter Fail rx desc-mask[%d]\n",
- DescSAFilterFail);
- }
- if (status & DescRxLengthError) {
- printk(KERN_WARNING "Length Error rx desc-mask[%d]\n",
- DescRxLengthError);
- }
- if (status & DescRxIPChecksumErr) {
- printk(KERN_WARNING "TCP checksum Error rx desc-mask[%d]\n",
- DescRxLengthError);
- }
- if (status & DescRxTCPChecksumErr) {
- printk(KERN_WARNING "TCP checksum Error rx desc-mask[%d]\n",
- DescRxLengthError);
- }
- if (status & DescRxDamaged) {
- printk(KERN_WARNING "Overflow Error rx desc-mask[%d]\n",
- DescRxDamaged);
- }
- if (status & DescRxMiiError) {
- printk(KERN_WARNING "Receive Error rx desc-mask[%d]\n",
- DescRxMiiError);
- }
- if (status & DescRxDribbling) {
- printk(KERN_WARNING "Dribble Bit Error rx desc-mask[%d]\n",
- DescRxDribbling);
- }
- if (status & DescRxCrc) {
- printk(KERN_WARNING "CE: CRC Errorrx desc-mask[%d]\n",
- DescRxCrc);
- }
- }
- /**********************
- we do the basic rx tx operation irq;
- FIXME:on SMP system..
- ************************/
- void net_tasklet(unsigned long dev_instance)
- {
- struct net_device *dev = (struct net_device *)dev_instance;
- struct am_net_private *np = netdev_priv(dev);
- int len;
- int result;
- unsigned long flags;
- #ifndef DMA_USE_SKB_BUF
- struct sk_buff *skb = NULL;
- #endif
- spin_lock_irqsave(&np->lock, flags);
- result = np->int_rx_tx;
- np->int_rx_tx = 0;
- spin_unlock_irqrestore(&np->lock, flags);
- if (!running)
- goto release;
- if (result & 1) {
- struct _tx_desc *c_tx, *tx = NULL;
- c_tx =
- (void *)IO_READ32(np->base_addr +
- ETH_DMA_18_Curr_Host_Tr_Descriptor);
- c_tx = np->tx_ring + (c_tx - np->tx_ring_dma);
- tx = np->start_tx;
- CACHE_RSYNC(tx, sizeof(struct _tx_desc));
- while (tx != NULL && tx != c_tx && !(tx->status & DescOwnByDma)) {
- #ifdef DMA_USE_SKB_BUF
- spin_lock_irqsave(&np->lock, flags);
- if (tx->skb != NULL) {
- //clear to next send;
- if (np->tx_full) {
- netif_wake_queue(dev);
- np->tx_full = 0;
- }
- if (debug > 2)
- printk("send data ok len=%d\n",
- tx->skb->len);
- dev_kfree_skb_any(tx->skb);
- if (tx->buf_dma != 0)
- dma_unmap_single(&dev->dev, tx->buf_dma,
- np->rx_buf_sz,
- DMA_TO_DEVICE);
- tx->skb = NULL;
- tx->buf = 0;
- tx->buf_dma = 0;
- tx->status = 0;
- } else {
- spin_unlock_irqrestore(&np->lock, flags);
- break;
- }
- spin_unlock_irqrestore(&np->lock, flags);
- #else
- tx->status = 0;
- CACHE_WSYNC(tx, sizeof(struct _tx_desc));
- if (np->tx_full) {
- netif_wake_queue(dev);
- np->tx_full = 0;
- }
- #endif
- tx = tx->next;
- CACHE_RSYNC(tx, sizeof(struct _tx_desc));
- }
- np->start_tx = tx;
- //data tx end... todo
- }
- if (result & 2) {
- //data rx;
- struct _rx_desc *c_rx, *rx = NULL;
- c_rx =
- (void *)IO_READ32(np->base_addr +
- ETH_DMA_19_Curr_Host_Re_Descriptor);
- c_rx = np->rx_ring + (c_rx - np->rx_ring_dma);
- rx = np->last_rx->next;
- while (rx != NULL) {
- //if(rx->status !=IO_READ32(&rx->status))
- // printk("error of D-chche!\n");
- CACHE_RSYNC(rx, sizeof(struct _rx_desc));
- if (!(rx->status & (DescOwnByDma))) {
- int ip_summed = CHECKSUM_UNNECESSARY;
- len =
- (rx->
- status & DescFrameLengthMask) >>
- DescFrameLengthShift;
- if (unlikely(len < 18 || len > np->rx_buf_sz)) { //here is fatal error we drop it ;
- np->stats.rx_dropped++;
- np->stats.rx_errors++;
- goto to_next;
- }
- if (unlikely(rx->status & (DescError))) { //here is not often occur
- print_rx_error_log(rx->status);
- //rx->status=DescOwnByDma;
- if ((rx->status & DescRxIPChecksumErr) || (rx->status & DescRxTCPChecksumErr)) { //maybe checksum engine's problem;
- //we set the NONE for ip/tcp need check it again
- ip_summed = CHECKSUM_NONE;
- } else {
- np->stats.rx_dropped++;
- np->stats.rx_errors++;
- goto to_next;
- }
- }
- len = len - 4; //clear the crc
- #ifdef DMA_USE_SKB_BUF
- if (rx->skb == NULL) {
- printk("NET skb pointer error!!!\n");
- break;
- }
- if (rx->skb->len > 0) {
- printk
- ("skb have data before,skb=%p,len=%d\n",
- rx->skb, rx->skb->len);
- rx->skb = NULL;
- goto to_next;
- }
- skb_put(rx->skb, len);
- rx->skb->dev = dev;
- rx->skb->protocol =
- eth_type_trans(rx->skb, dev);
- /*we have checked in hardware;
- we not need check again */
- rx->skb->ip_summed = ip_summed;
- if (rx->buf_dma != 0)
- dma_unmap_single(&dev->dev, rx->buf_dma,
- np->rx_buf_sz,
- DMA_FROM_DEVICE);
- rx->buf_dma = 0;
- netif_rx(rx->skb);
- if (debug > 3)
- printk("receive skb=%p\n", rx->skb);
- rx->skb = NULL;
- #else
- skb = dev_alloc_skb(len + 4);
- if (skb == NULL) {
- np->stats.rx_dropped++;
- printk("error to alloc skb\n");
- break;
- }
- skb_reserve(skb, 2);
- skb_put(skb, len);
- if (rx->buf_dma != NULL)
- dma_unmap_single(&dev->dev,
- (void *)rx->buf_dma,
- np->rx_buf_sz,
- DMA_FROM_DEVICE);
- memcpy(skb->data, (void *)rx->buf, len);
- skb->dev = dev;
- skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = ip_summed;
- netif_rx(skb);
- #endif
- dev->last_rx = jiffies;
- np->stats.rx_packets++;
- np->stats.rx_bytes += len;
- //*/
- if (debug > 3)
- printk("receive data len=%d\n", len);
- //dump((unsigned char *)rx->buf,len);
- //reset the rx_ring to receive
- ///
- to_next:
- #ifdef DMA_USE_SKB_BUF
- if (rx->skb)
- dev_kfree_skb_any(rx->skb);
- rx->skb = dev_alloc_skb(np->rx_buf_sz + 4);
- if (rx->skb == NULL) {
- printk(KERN_ERR
- "error to alloc the skb\n");
- rx->buf = 0;
- rx->buf_dma = 0;
- rx->status = 0;
- rx->count = 0;
- np->last_rx = rx;
- CACHE_WSYNC(rx,
- sizeof(struct _rx_desc));
- break;
- }
- if (debug > 3)
- printk("new malloc skb=%p\n", rx->skb);
- skb_reserve(rx->skb, 2);
- rx->buf = (unsigned long)rx->skb->data;
- #endif
- rx->buf_dma = dma_map_single(&dev->dev, (void *)rx->buf, (unsigned long)np->rx_buf_sz, DMA_FROM_DEVICE); //invalidate for next dma in;
- rx->count =
- (DescChain) | (np->
- rx_buf_sz & DescSize1Mask);
- rx->status = DescOwnByDma;
- CACHE_WSYNC(rx, sizeof(struct _rx_desc));
- np->last_rx = rx;
- rx = rx->next;
- } else {
- break;
- }
- }
- }
- release:
- IO_WRITE32(np->irq_mask, (np->base_addr + ETH_DMA_7_Interrupt_Enable));
- }
- static irqreturn_t intr_handler(int irq, void *dev_instance)
- {
- struct net_device *dev = (struct net_device *)dev_instance;
- struct am_net_private *np = netdev_priv(dev);
- unsigned long status, mask = 0;
- IO_WRITE32(0, (np->base_addr + ETH_DMA_7_Interrupt_Enable)); //disable irq
- tasklet_schedule(&np->rx_tasklet);
- status = IO_READ32(np->base_addr + ETH_DMA_5_Status);
- mask = IO_READ32(np->base_addr + ETH_MAC_Interrupt_Mask);
- np->int_rx_tx |= update_status(dev, status, mask);
- return IRQ_HANDLED;
- }
- static int phy_reset(struct net_device *ndev)
- {
- struct am_net_private *np = netdev_priv(ndev);
- unsigned long val;
- int k;
- //mac reset ...
- IO_WRITE32(1, np->base_addr + ETH_DMA_0_Bus_Mode);
- //waiting mac reset...
- for (k = 0;
- (IO_READ32(np->base_addr + ETH_DMA_0_Bus_Mode) & 1) && k < 1000;
- k++)
- udelay(1);
- if (k >= 1000) {
- printk("error to reset mac!\n");
- goto error_reset;
- }
- //set for RMII mode;
- val = (1 << 14) | (7 << 5) | np->phys[0];
- mdio_write(ndev, np->phys[0], 18, val);
- val = BMCR_RESET;
- mdio_write(ndev, np->phys[0], MII_BMCR, val);
- //waiting to phy reset ok....
- for (k = 0; (mdio_read(ndev, np->phys[0], MII_BMCR)) & (BMCR_RESET)
- && k < 1000; k++) {
- udelay(1);
- }
- if (k >= 1000) {
- printk("error to reset phy!\n");
- goto error_reset;
- }
- // mode = 111; turn on auto-neg mode (previously was power-saving)
- val = (1 << 14) | (7 << 5) | np->phys[0];
- mdio_write(ndev, np->phys[0], 18, val);
- // Auto negotiation restart
- val = BMCR_ANENABLE | BMCR_ANRESTART;
- mdio_write(ndev, np->phys[0], MII_BMCR, val);
- if (debug > 1)
- printk("starting to auto negotiation!\n");
- //(*ETH_DMA_0_Bus_Mode) = 0x00100800;
- IO_WRITE32(0x00100800, np->base_addr + ETH_DMA_0_Bus_Mode);
- /*
- val=*((unsigned short *)&ndev->dev_addr[4]);
- IO_WRITE32(val,np->base_addr+ETH_MAC_Addr0_High);
- val=*((unsigned long *)ndev->dev_addr);
- IO_WRITE32(val,np->base_addr+ETH_MAC_Addr0_Low);
- */
- write_mac_addr(ndev, ndev->dev_addr);
- val = 0xc80c | //8<<8 | 8<<17; //tx and rx all 8bit mode;
- 1 << 10; //checksum offload enabled
- #ifdef MAC_LOOPBACK_TEST
- val |= 1 << 12; //mac loop back
- #endif
- IO_WRITE32(val, np->base_addr + ETH_MAC_0_Configuration);
- val = 1 << 4; /*receive all muticast */
- //| 1 << 31; //receive all the data
- IO_WRITE32(val, np->base_addr + ETH_MAC_1_Frame_Filter);
- #ifdef PHY_LOOPBACK_TEST
- /*phy loop back */
- val = mdio_read(ndev, np->phys[0], MII_BMCR);
- //val=1<<14 | 1<<8 | 1<<13;//100M,full,seting it as ;
- val = 1 << 14 | 1 << 8; /////10M,full,seting it as ;
- mdio_write(ndev, np->phys[0], MII_BMCR, val);
- #endif
- IO_WRITE32((unsigned long)&np->rx_ring_dma[0],
- (np->base_addr + ETH_DMA_3_Re_Descriptor_List_Addr));
- IO_WRITE32((unsigned long)&np->tx_ring_dma[0],
- (np->base_addr + ETH_DMA_4_Tr_Descriptor_List_Addr));
- IO_WRITE32(np->irq_mask, (np->base_addr + ETH_DMA_7_Interrupt_Enable));
- IO_WRITE32((0), (np->base_addr + ETH_MAC_Interrupt_Mask));
- printk("Current DMA mode=%x\n",
- IO_READ32(np->base_addr + ETH_DMA_6_Operation_Mode));
- val = (7 << 14 | 1 << 25 | 1 << 8 | 1 << 26 | 1 << 21); /*don't start receive here */
- ////1<<21 is Transmit Store and Forward used for tcp/ip checksum insert
- IO_WRITE32(val, (np->base_addr + ETH_DMA_6_Operation_Mode));
- np->phy_set[0] = 0; //make sure reset the phy speed
- return 0;
- error_reset:
- return -1;
- }
- static int ethernet_reset(struct net_device *dev)
- {
- struct am_net_private *np = netdev_priv(dev);
- int res;
- unsigned long flags;
- spin_lock_irqsave(&np->lock, flags);
- res = alloc_ringdesc(dev);
- spin_unlock_irqrestore(&np->lock, flags);
- if (res != 0) {
- printk(KERN_INFO "can't alloc ring desc!err=%d\n", res);
- goto out_err;
- }
- res = phy_reset(dev);
- if (res != 0) {
- printk(KERN_INFO "can't reset ethernet phy!err=%d\n", res);
- goto out_err;
- }
- np->first_tx = 1;
- out_err:
- return res;
- }
- static int netdev_open(struct net_device *dev)
- {
- struct am_net_private *np = netdev_priv(dev);
- unsigned long val;
- int res;
- if (running)
- return 0;
- printk(KERN_INFO "netdev_open\n");
- res = ethernet_reset(dev);
- if (res != 0) {
- printk(KERN_INFO "ethernet_reset err=%d\n", res);
- goto out_err;
- }
- //netif_device_detach(dev);
- res = request_irq(dev->irq, &intr_handler, IRQF_SHARED, dev->name, dev);
- if (res) {
- printk(KERN_ERR "%s: request_irq error %d.,err=%d\n",
- dev->name, dev->irq, res);
- goto out_err;
- }
- if (debug > 0)
- printk("%s: opened (irq %d).\n", dev->name, dev->irq);
- //enable_irq(dev->irq);
- /* Set the timer to check for link beat. */
- init_timer(&np->timer);
- np->timer.expires = jiffies + 1;
- np->timer.data = (unsigned long)dev;
- np->timer.function = &netdev_timer; /* timer handler */
- add_timer(&np->timer);
- val = IO_READ32((np->base_addr + ETH_DMA_6_Operation_Mode));
- val |= (1 << 1); /*start receive */
- IO_WRITE32(val, (np->base_addr + ETH_DMA_6_Operation_Mode));
- running = 1;
- #ifdef LOOP_BACK_TEST
- start_test(np->dev);
- #endif
- return 0;
- out_err:
- running = 0;
- return -EIO;
- }
- static int netdev_close(struct net_device *dev)
- {
- struct am_net_private *np = netdev_priv(dev);
- unsigned long val;
- if (!running)
- return 0;
- running = 0;
- IO_WRITE32(0, (np->base_addr + ETH_DMA_6_Operation_Mode));
- IO_WRITE32(0, np->base_addr + ETH_DMA_7_Interrupt_Enable);
- val = IO_READ32((np->base_addr + ETH_DMA_5_Status));
- while ((val & (7 << 17)) || (val & (5 << 20))) { /*DMA not finished? */
- printk(KERN_ERR "ERROR! MDA is not stoped,val=%lx!\n", val);
- msleep(1); //waiting all dma is finished!!
- val = IO_READ32((np->base_addr + ETH_DMA_5_Status));
- }
- if (debug > 0)
- printk(KERN_INFO "NET MDA is stoped,val=%lx!\n", val);
- disable_irq(dev->irq);
- netif_carrier_off(dev);
- netif_stop_queue(dev);
- free_ringdesc(dev);
- free_irq(dev->irq, dev);
- del_timer_sync(&np->timer);
- // free_rxtx_rings(np);
- // free_ringdesc(np);
- // PERIPHS_CLEAR_BITS(P_ETH_PLL_CNTL,1);//disable clk
- if (debug > 0)
- printk(KERN_DEBUG "%s: closed\n", dev->name);
- return 0;
- }
- static int start_tx(struct sk_buff *skb, struct net_device *dev)
- {
- struct am_net_private *np = netdev_priv(dev);
- int tmp;
- struct _tx_desc *tx;
- unsigned long flags;
- dev->trans_start = jiffies;
- if (!running)
- return -1;
- if (debug > 2) {
- printk(KERN_DEBUG "%s: Transmit frame queued\n", dev->name);
- }
- spin_lock_irqsave(&np->lock, flags);
- if (np->last_tx != NULL)
- tx = np->last_tx->next;
- else
- tx = &np->tx_ring[0];
- CACHE_RSYNC(tx, sizeof(*tx));
- if (tx->status & DescOwnByDma) {
- spin_unlock_irqrestore(&np->lock, flags);
- if (debug > 2)
- printk("tx queue is full \n");
- goto err;
- }
- #ifdef DMA_USE_SKB_BUF
- if (tx->skb != NULL) {
- dev_kfree_skb_any(tx->skb);
- if (tx->buf_dma != 0)
- dma_unmap_single(&dev->dev, tx->buf_dma, np->rx_buf_sz,
- DMA_FROM_DEVICE);
- }
- tx->skb = skb;
- tx->buf = (unsigned long)skb->data;
- #else
- memcpy((void *)tx->buf, skb->data, skb->len);
- #endif
- tx->buf_dma =
- dma_map_single(&dev->dev, (void *)tx->buf,
- (unsigned long)(skb->len), DMA_TO_DEVICE);
- tx->count = ((skb->len << DescSize1Shift) & DescSize1Mask) | DescTxFirst | DescTxLast | DescTxIntEnable | DescChain; //|2<<27; (1<<25, ring end)
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- tx->count |= 0x3 << 27; //add hw check sum;
- }
- tx->status = DescOwnByDma;
- np->last_tx = tx;
- np->stats.tx_packets++;
- np->stats.tx_bytes += skb->len;
- CACHE_WSYNC(tx, sizeof(*tx));
- #ifndef DMA_USE_SKB_BUF
- dev_kfree_skb_any(skb);
- #endif
- if (np->first_tx) {
- np->first_tx = 0;
- tmp = IO_READ32(np->base_addr + ETH_DMA_6_Operation_Mode);
- tmp |= (7 << 14) | (1 << 13);
- IO_WRITE32(tmp, np->base_addr + ETH_DMA_6_Operation_Mode);
- } else {
- //ETH_DMA_1_Tr_Poll_Demand
- IO_WRITE32(1, np->base_addr + ETH_DMA_1_Tr_Poll_Demand);
- }
- spin_unlock_irqrestore(&np->lock, flags);
- return 0;
- err:
- np->tx_full = 1;
- np->stats.tx_dropped++;
- netif_stop_queue(dev);
- return -1;
- }
- #ifdef LOOP_BACK_TEST
- void test_loop_back(struct net_device *dev)
- {
- //static int start_tx(struct sk_buff *skb, struct net_device *dev)
- //struct am_net_private *np = netdev_priv(dev);
- int i = 0;
- char header[64] = "";
- struct am_net_private *np = netdev_priv(dev);
- printk("start testing!!\n");
- memcpy(header, dev->dev_addr, 6);
- memcpy(header + 8, dev->dev_addr, 6);
- header[12] = 0x80;
- header[13] = 0;
- while (1) {
- struct sk_buff *skb = dev_alloc_skb(1600);
- while (!running) {
- i = 0;
- msleep(10);
- }
- skb_put(skb, 1400);
- memset(skb->data, 0x55, skb->len);
- memcpy(skb->data, header, 16);
- if (start_tx(skb, dev) != 0) {
- /*tx list is full */
- msleep(1);
- dev_kfree_skb(skb);
- } else
- i++;
- if (i % 2000 == 0) {
- msleep(1);
- printk("send pkts=%ld,receive pkts=%ld\n",
- np->stats.tx_packets, np->stats.rx_packets);
- }
- }
- }
- void start_test(struct net_device *dev)
- {
- static int test_running = 0;
- struct am_net_private *np = netdev_priv(dev);
- if (test_running)
- return;
- phy_auto_negotiation_set(np);
- kernel_thread((void *)test_loop_back, (void *)dev,
- CLONE_FS | CLONE_SIGHAND);
- test_running++;
- }
- #endif
- static struct net_device_stats *get_stats(struct net_device *dev)
- {
- struct am_net_private *np = netdev_priv(dev);
- return &np->stats;
- }
- static void tx_timeout(struct net_device *dev)
- {
- struct am_net_private *np = netdev_priv(dev);
- int val;
- //FIXME
- spin_lock_irq(&np->lock);
- val = mdio_read(dev, np->phys[0], MII_BMSR);
- spin_unlock_irq(&np->lock);
- if (!(val & (BMSR_LSTATUS))) { //unlink .....
- netif_stop_queue(dev);
- netif_carrier_off(dev);
- } else {
- netif_carrier_on(dev);
- netif_wake_queue(dev);
- dev->trans_start = jiffies;
- np->stats.tx_errors++;
- }
- return;
- }
- static void write_mac_addr(struct net_device *dev, char *macaddr)
- {
- struct am_net_private *np = netdev_priv(dev);
- unsigned int val;
- val = *((unsigned short *)&macaddr[4]);
- IO_WRITE32(val, np->base_addr + ETH_MAC_Addr0_High);
- val = *((unsigned long *)macaddr);
- IO_WRITE32(val, np->base_addr + ETH_MAC_Addr0_Low);
- printk("write mac add to:");
- dump(macaddr, 6);
- }
- static unsigned char inline chartonum(char c)
- {
- if (c >= '0' && c <= '9')
- return c - '0';
- if (c >= 'A' && c <= 'F')
- return (c - 'A') + 10;
- if (c >= 'a' && c <= 'f')
- return (c - 'a') + 10;
- return 0;
- }
- static void config_mac_addr(struct net_device *dev, void *mac)
- {
- if(g_mac_setup == 0) {
- printk("*****WARNING: Haven't setup MAC address! Using random MAC address.\n");
- unsigned long mac_fir = 0;
- unsigned char mac_add[6] = {};
- mac_fir = READ_MPEG_REG(RAND64_ADDR1);
- mac_add[1] = mac_fir&0xFF; mac_add[2] = (mac_fir>>16)&0xFF;
- mac_add[3] = (mac_fir>>8)&0xFF; mac_add[4] = (mac_fir>>24) &0xFF;
- mac_add[5] = (mac_add[1]<<4)|(mac_add[4]>>4);
- memcpy(mac, mac_add, 6);
- printk("mac-addr: %x:%x:%x:%x:%x:%x\n", mac_add[0],mac_add[1],mac_add[2],
- mac_add[3],mac_add[4],mac_add[5]);
- }
- memcpy(dev->dev_addr, mac, 6);
- write_mac_addr(dev, dev->dev_addr);
- }
- static int __init mac_addr_set(char *line)
- {
- unsigned char mac[6];
- int i = 0;
- for (i = 0; i < 6 && line[0] != '\0' && line[1] != '\0'; i++) {
- mac[i] = chartonum(line[0]) << 4 | chartonum(line[1]);
- line += 3;
- }
- memcpy(DEFMAC, mac, 6);
- printk("******** uboot setup mac-addr: %x:%x:%x:%x:%x:%x\n",
- DEFMAC[0], DEFMAC[1], DEFMAC[2], DEFMAC[3], DEFMAC[4], DEFMAC[5]);
- g_mac_setup++;
- return 1;
- }
- __setup("mac=", mac_addr_set);
- static inline int phy_mc_hash(__u8 * addr)
- {
- return (bitrev32(~crc32_le(~0, addr, ETH_ALEN)) >> 26);
- }
- static void set_multicast_list(struct net_device *dev)
- {
- struct am_net_private *np = netdev_priv(dev);
- u32 tmp;
- if ((dev->flags & IFF_PROMISC)) {
- tmp = IO_READ32(np->base_addr + ETH_MAC_1_Frame_Filter);
- tmp |= 1;
- IO_WRITE32(tmp, np->base_addr + ETH_MAC_1_Frame_Filter); //promisc module
- printk("ether enter promisc module\n");
- } else {
- tmp = IO_READ32(np->base_addr + ETH_MAC_1_Frame_Filter);
- tmp &= ~1;
- IO_WRITE32(tmp, np->base_addr + ETH_MAC_1_Frame_Filter); //live promisc
- //printk("ether leave promisc module\n");
- }
- if ((dev->flags & IFF_ALLMULTI)) {
- tmp = IO_READ32(np->base_addr + ETH_MAC_1_Frame_Filter);
- tmp |= (1 << 4);
- IO_WRITE32(tmp, np->base_addr + ETH_MAC_1_Frame_Filter); //all muticast
- printk("ether enter all multicast module\n");
- } else {
- tmp = IO_READ32(np->base_addr + ETH_MAC_1_Frame_Filter);
- tmp &= (1 << 4);
- IO_WRITE32(tmp, np->base_addr + ETH_MAC_1_Frame_Filter); //live all muticast
- //printk("ether leave all muticast module\n");
- }
- if (netdev_mc_count(dev) > 0) {
- u32 hash[2];
- struct netdev_hw_addr *ha;
- u32 hash_id;
- char *addr;
- hash[0] = 0;
- hash[1] = 0;
- printk("changed the Multicast,mcount=%d\n",
- netdev_mc_count(dev));
- //for (addr_list = dev->mc_list; cnt && addr_list != NULL; addr_list = addr_list->next, cnt--) {
- netdev_for_each_mc_addr(ha, dev) {
- addr = ha->addr;
- hash_id = phy_mc_hash(addr);
- ///*
- printk
- ("add mac address:%02x:%02x:%02x:%02x:%02x:%02x,bit=%d\n",
- addr[0], addr[1], addr[2], addr[3], addr[4],
- addr[5], hash_id);
- //*/
- //set_bit(hash_id,hash);
- if (hash_id > 31)
- hash[1] |= 1 << (hash_id - 32);
- else
- hash[0] |= 1 << hash_id;
- }
- printk("set hash low=%x,high=%x\n", hash[0], hash[1]);
- IO_WRITE32(hash[1], np->base_addr + ETH_MAC_2_Hash_Table_High);
- IO_WRITE32(hash[0], np->base_addr + ETH_MAC_3_Hash_Table_Low);
- tmp = IO_READ32(np->base_addr + ETH_MAC_1_Frame_Filter);
- tmp = (1 << 2) | //hash filter
- 0;
- printk("changed the filter setting to :%x\n", tmp);
- IO_WRITE32(tmp, np->base_addr + ETH_MAC_1_Frame_Filter); //hash muticast
- }
- }
- static const struct net_device_ops am_netdev_ops = {
- .ndo_open = netdev_open,
- .ndo_stop = netdev_close,
- .ndo_start_xmit = start_tx,
- .ndo_tx_timeout = tx_timeout,
- .ndo_set_multicast_list = set_multicast_list,
- .ndo_do_ioctl = netdev_ioctl,
- .ndo_get_stats = get_stats,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
- };
- static int setup_net_device(struct net_device *dev)
- {
- struct am_net_private *np = netdev_priv(dev);
- int res = 0;
- dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
- dev->features = NETIF_F_GEN_CSUM;
- dev->netdev_ops = &am_netdev_ops;
- dev->ethtool_ops = NULL; // &netdev_ethtool_ops;
- dev->watchdog_timeo = TX_TIMEOUT;
- np->irq_mask = (1 << 16) | //NIE: Normal Interrupt Summary Enable
- (1 << 15) | //abnormal int summary
- (1 << 6) | //Receive Interrupt Enable
- (1 << 2) | //Transmit Buffer Unavailable Enable
- (1 << 3) | //TJT: Transmit Jabber Timeout
- (1 << 4) | //OVF: Receive Overflow
- (1 << 5) | //UNF: Transmit Underflow
- (1 << 7) | //7 RU: Receive Buffer Unavailable
- (1 << 8) | //RPS: Receive Process Stopped
- (1 << 13) | //13 FBI: Fatal Bus Error Interrupt
- (1) | //tx interrupt
- 0;
- config_mac_addr(dev, DEFMAC);
- dev_alloc_name(dev, "eth%d");
- memset(&np->stats, 0, sizeof(np->stats));
- return res;
- }
- static int probe_init(struct net_device *ndev)
- {
- int phy = 0;
- int phy_idx = 0;
- int found = 0;
- int res = 0;
- unsigned int val;
- int k, kk;
- struct am_net_private *priv = netdev_priv(ndev);
- priv->dev = ndev;
- //ndev->base_addr = (unsigned long)ioremap(ETHBASE,0x2000);
- ndev->base_addr = (unsigned long)(ETHBASE);
- ndev->irq = ETH_INTERRUPT;
- spin_lock_init(&priv->lock);
- priv->mii_if.dev = ndev;
- priv->mii_if.mdio_read = mdio_read;
- priv->mii_if.mdio_write = mdio_write;
- priv->base_addr = ndev->base_addr;
- if (debug > 0)
- printk("addr is %x\n", (unsigned int)ndev->base_addr);
- //bank_io_init(ndev);
- for (k = 0; k < 100 && !found; k++) {
- //mac reset ...
- IO_WRITE32(1, priv->base_addr + ETH_DMA_0_Bus_Mode);
- //waiting mac reset...
- for (kk = 0;
- (IO_READ32(priv->base_addr + ETH_DMA_0_Bus_Mode) & 1)
- && kk < 1000; kk++)
- udelay(1);
- if (kk >= 1000) {
- printk("error to reset mac at probe!\n");
- goto error0;
- }
- for (phy = 0; phy < 32 && phy_idx < MII_CNT; phy++) {
- int mii_status = mdio_read(ndev, phy, MII_BMSR);
- if (mii_status != 0xffff && mii_status != 0x0000) {
- priv->phys[phy_idx++] = phy;
- priv->mii_if.advertising =
- mdio_read(ndev, phy, MII_ADVERTISE);
- priv->mii =
- (mdio_read(ndev, phy, MII_PHYSID1) << 16) +
- mdio_read(ndev, phy, MII_PHYSID2);
- if (debug > 0)
- printk(KERN_INFO
- "%s: MII PHY %8.8xh found at address %d, status "
- "0x%4.4x advertising %4.4x.\n",
- DRV_NAME, priv->mii, phy,
- mii_status,
- priv->mii_if.advertising);
- found++;
- }
- }
- }
- if (!found) {
- printk("can't find any mii phy device !\n");
- res = -EIO;
- goto error0;
- }
- mdio_write(ndev, priv->phys[0], 18, priv->phys[0] | (1 << 14 | 7 << 5));
- val = mdio_read(ndev, priv->phys[0], 2); //phy_rw(0, phyad, 2, &val);
- priv->phy_Identifier = val << 16;
- val = mdio_read(ndev, priv->phys[0], 3); //phy_rw(0, phyad, 3, &val);
- priv->phy_Identifier |= val;
- printk("find phy phy_Identifier=%x\n", priv->phy_Identifier);
- res = setup_net_device(ndev);
- if (res != 0) {
- printk("setup net device error !\n");
- res = -EIO;
- goto error0;
- }
- res = register_netdev(ndev);
- if (res != 0) {
- printk("can't register net device !\n");
- res = -EBUSY;
- goto error0;
- }
- tasklet_init(&priv->rx_tasklet, net_tasklet, (unsigned long)ndev);
- return 0;
- //error1:
- // unregister_netdev(ndev);
- error0:
- return res;
- }
- static int has_ethernet_pm = 0;
- static struct aml_eth_platdata *eth_pdata;
- static int ethernet_probe(struct platform_device *pdev)
- {
- printk("ethernet_driver probe!\n");
- eth_pdata = (struct aml_eth_platdata *)pdev->dev.platform_data;
- if (!eth_pdata) {
- printk("\nethernet pm ops resource undefined.\n");
- return -EFAULT;
- }
- if (eth_pdata->clock_enable)
- eth_pdata->clock_enable();
- if (eth_pdata->pinmux_setup)
- eth_pdata->pinmux_setup();
- return 0;
- }
- static int ethernet_remove(struct platform_device *pdev)
- {
- printk("ethernet_driver remove!\n");
- return 0;
- }
- static int ethernet_suspend(struct platform_device *dev, pm_message_t event)
- {
- netdev_close(my_ndev);
- ///unregister_netdev(my_ndev);
- eth_pdata->clock_disable();
- //eth_clk_set(ETH_CLKSRC_APLL_CLK,400*CLK_1M,0);
- printk("ethernet_suspend()\n");
- return 0;
- }
- static int ethernet_resume(struct platform_device *dev)
- {
- int res = 0;
- if (eth_pdata->clock_enable)
- eth_pdata->clock_enable();
- //eth_clk_set(ETH_CLKSRC_APLL_CLK,400*CLK_1M,50*CLK_1M);
- eth_pdata->reset();
- printk("ethernet_resume()\n");
- //res = probe_init(my_ndev);
- res = netdev_open(my_ndev);
- if (res != 0)
- printk("nono, it can not be true!\n");
- printk("ethernet_resume!\n");
- return 0;
- }
- static struct platform_driver ethernet_driver = {
- .probe = ethernet_probe,
- .remove = ethernet_remove,
- .suspend = ethernet_suspend,
- .resume = ethernet_resume,
- .driver = {
- .name = "meson-eth",
- }
- };
- static int __init am_net_init(void)
- {
- int res;
- printk(DRV_NAME "init(dbg[%p]:%d)\n", (&debug), debug);
- my_ndev = alloc_etherdev(sizeof(struct am_net_private));
- if (my_ndev == NULL) {
- printk(DRV_NAME "ndev alloc failed!!\n");
- return -ENOMEM;
- }
- res = probe_init(my_ndev);
- if (res != 0)
- free_netdev(my_ndev);
- else {
- printk("ethernet_driver init\n");
- if (platform_driver_register(ðernet_driver)) {
- printk("failed to register ethernet_pm driver\n");
- has_ethernet_pm = 0;
- } else
- has_ethernet_pm = 1;
- }
- return res;
- }
- static void am_net_free(struct net_device *ndev)
- {
- //struct am_net_private *np=netdev_priv(ndev);
- netdev_close(ndev);
- unregister_netdev(ndev);
- }
- static void __exit am_net_exit(void)
- {
- printk(DRV_NAME "exit\n");
- am_net_free(my_ndev);
- free_netdev(my_ndev);
- if (has_ethernet_pm == 1) {
- printk("ethernet_pm driver remove.\n");
- platform_driver_unregister(ðernet_driver);
- has_ethernet_pm = 0;
- }
- return;
- }
- module_init(am_net_init);
- module_exit(am_net_exit);
|