X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;f=target%2Flinux%2Far71xx%2Ffiles%2Fdrivers%2Fnet%2Fag71xx%2Fag71xx_main.c;h=ed9e7b9ea06a82520d926b93c2a3ed5e915e692f;hb=571d12ab3ac4287d58a3abc791befa4e0ab3d907;hp=ce2af538cbd2d13e40c7eb198fc7d7fb75766125;hpb=8ea4f149b06fd5292d40d19d7c48b4f1d5592f5c;p=openwrt.git diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c index ce2af538cb..ed9e7b9ea0 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c @@ -374,8 +374,8 @@ static void ag71xx_dma_reset(struct ag71xx *ag) mdelay(1); /* clear descriptor addresses */ - ag71xx_wr(ag, AG71XX_REG_TX_DESC, 0); - ag71xx_wr(ag, AG71XX_REG_RX_DESC, 0); + ag71xx_wr(ag, AG71XX_REG_TX_DESC, ag->stop_desc_dma); + ag71xx_wr(ag, AG71XX_REG_RX_DESC, ag->stop_desc_dma); /* clear pending RX/TX interrupts */ for (i = 0; i < 256; i++) { @@ -425,9 +425,39 @@ static void ag71xx_dma_reset(struct ag71xx *ag) static void ag71xx_hw_stop(struct ag71xx *ag) { - /* disable all interrupts and stop the rx engine */ + /* disable all interrupts and stop the rx/tx engine */ ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, 0); ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0); + ag71xx_wr(ag, AG71XX_REG_TX_CTRL, 0); +} + +static void ag71xx_hw_setup(struct ag71xx *ag) +{ + struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); + + /* setup MAC configuration registers */ + ag71xx_wr(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_INIT); + + ag71xx_sb(ag, AG71XX_REG_MAC_CFG2, + MAC_CFG2_PAD_CRC_EN | MAC_CFG2_LEN_CHECK); + + /* setup max frame length */ + ag71xx_wr(ag, AG71XX_REG_MAC_MFL, AG71XX_TX_MTU_LEN); + + /* setup MII interface type */ + ag71xx_mii_ctrl_set_if(ag, pdata->mii_if); + + /* setup FIFO configuration registers */ + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG0, FIFO_CFG0_INIT); + if (pdata->is_ar724x) { + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, pdata->fifo_cfg1); + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, pdata->fifo_cfg2); + } else { + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, 0x0fff0000); + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, 0x00001fff); + } + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG4, FIFO_CFG4_INIT); + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, FIFO_CFG5_INIT); } static void ag71xx_hw_init(struct ag71xx *ag) @@ -452,36 +482,43 @@ static void ag71xx_hw_init(struct ag71xx *ag) ag71xx_sb(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_SR); udelay(20); - ar71xx_device_stop(pdata->reset_bit); + ar71xx_device_stop(reset_mask); mdelay(100); - ar71xx_device_start(pdata->reset_bit); + ar71xx_device_start(reset_mask); mdelay(200); - /* setup MAC configuration registers */ - ag71xx_wr(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_INIT); + ag71xx_hw_setup(ag); - ag71xx_sb(ag, AG71XX_REG_MAC_CFG2, - MAC_CFG2_PAD_CRC_EN | MAC_CFG2_LEN_CHECK); + ag71xx_dma_reset(ag); +} - /* setup max frame length */ - ag71xx_wr(ag, AG71XX_REG_MAC_MFL, AG71XX_TX_MTU_LEN); +static void ag71xx_fast_reset(struct ag71xx *ag) +{ + struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); + struct net_device *dev = ag->dev; + u32 reset_mask = pdata->reset_bit; + u32 rx_ds, tx_ds; + u32 mii_reg; - /* setup MII interface type */ - ag71xx_mii_ctrl_set_if(ag, pdata->mii_if); + reset_mask &= RESET_MODULE_GE0_MAC | RESET_MODULE_GE1_MAC; - /* setup FIFO configuration registers */ - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG0, FIFO_CFG0_INIT); - if (pdata->is_ar724x) { - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, pdata->fifo_cfg1); - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, pdata->fifo_cfg2); - } else { - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, 0x0fff0000); - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, 0x00001fff); - } - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG4, FIFO_CFG4_INIT); - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, FIFO_CFG5_INIT); + mii_reg = ag71xx_rr(ag, AG71XX_REG_MII_CFG); + rx_ds = ag71xx_rr(ag, AG71XX_REG_RX_DESC); + tx_ds = ag71xx_rr(ag, AG71XX_REG_TX_DESC); + + ar71xx_device_stop(reset_mask); + udelay(10); + ar71xx_device_start(reset_mask); + udelay(10); ag71xx_dma_reset(ag); + ag71xx_hw_setup(ag); + + ag71xx_wr(ag, AG71XX_REG_RX_DESC, rx_ds); + ag71xx_wr(ag, AG71XX_REG_TX_DESC, tx_ds); + ag71xx_wr(ag, AG71XX_REG_MII_CFG, mii_reg); + + ag71xx_hw_set_macaddr(ag, dev->dev_addr); } static void ag71xx_hw_start(struct ag71xx *ag) @@ -509,6 +546,9 @@ void ag71xx_link_adjust(struct ag71xx *ag) return; } + if (pdata->is_ar724x) + ag71xx_fast_reset(ag); + cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2); cfg2 &= ~(MAC_CFG2_IF_1000 | MAC_CFG2_IF_10_100 | MAC_CFG2_FDX); cfg2 |= (ag->duplex) ? MAC_CFG2_FDX : 0; @@ -1085,6 +1125,16 @@ static int __devinit ag71xx_probe(struct platform_device *pdev) ag->tx_ring.size = AG71XX_TX_RING_SIZE_DEFAULT; ag->rx_ring.size = AG71XX_RX_RING_SIZE_DEFAULT; + ag->stop_desc = dma_alloc_coherent(NULL, + sizeof(struct ag71xx_desc), &ag->stop_desc_dma, GFP_KERNEL); + + if (!ag->stop_desc) + goto err_free_irq; + + ag->stop_desc->data = 0; + ag->stop_desc->ctrl = 0; + ag->stop_desc->next = (u32) ag->stop_desc_dma; + memcpy(dev->dev_addr, pdata->mac_addr, ETH_ALEN); netif_napi_add(dev, &ag->napi, ag71xx_poll, AG71XX_NAPI_WEIGHT); @@ -1092,7 +1142,7 @@ static int __devinit ag71xx_probe(struct platform_device *pdev) err = register_netdev(dev); if (err) { dev_err(&pdev->dev, "unable to register net device\n"); - goto err_free_irq; + goto err_free_desc; } printk(KERN_INFO "%s: Atheros AG71xx at 0x%08lx, irq %d\n", @@ -1120,6 +1170,9 @@ err_phy_disconnect: ag71xx_phy_disconnect(ag); err_unregister_netdev: unregister_netdev(dev); +err_free_desc: + dma_free_coherent(NULL, sizeof(struct ag71xx_desc), ag->stop_desc, + ag->stop_desc_dma); err_free_irq: free_irq(dev->irq, dev); err_unmap_mii_ctrl: