From: Felix Fietkau Date: Wed, 20 Jul 2011 14:46:36 +0000 (+0000) Subject: ar71xx: merge ar7240 fixes from trunk X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=commitdiff_plain;hb=aa11e6122a71bdbbb351427e7e657a302d01f1a8 ar71xx: merge ar7240 fixes from trunk SVN-Revision: 27706 --- diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c b/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c index f809deae55..43226c1da6 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c @@ -442,6 +442,8 @@ void __init ar71xx_add_device_eth(unsigned int id) ar71xx_eth1_data.reset_bit |= AR724X_RESET_GE1_MDIO; /* fall through */ case AR71XX_SOC_AR7240: + ar71xx_eth0_data.reset_bit |= RESET_MODULE_GE0_PHY; + ar71xx_eth1_data.reset_bit |= RESET_MODULE_GE1_PHY; pdata->ddr_flush = id ? ar724x_ddr_flush_ge1 : ar724x_ddr_flush_ge0; pdata->set_pll = id ? ar724x_set_pll_ge1 diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c index d84cc81aec..534af4b9f9 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c @@ -57,7 +57,13 @@ #define AR7240_VTUDATA_MEMBER BITS(0, 10) #define AR7240_VTUDATA_VALID BIT(11) +#define AR7240_REG_ATU 0x50 +#define AR7240_ATU_FLUSH_ALL 0x1 + #define AR7240_REG_AT_CTRL 0x5c +#define AR7240_AT_CTRL_AGE_TIME BITS(0, 15) +#define AR7240_AT_CTRL_AGE_EN BIT(17) +#define AR7240_AT_CTRL_LEARN_CHANGE BIT(18) #define AR7240_AT_CTRL_ARP_EN BIT(20) #define AR7240_REG_TAG_PRIORITY 0x70 @@ -412,28 +418,6 @@ static void ar7240sw_disable_port(struct ar7240sw *as, unsigned port) AR7240_PORT_CTRL_STATE_DISABLED); } -static int ar7240sw_reset(struct ar7240sw *as) -{ - struct mii_bus *mii = as->mii_bus; - int ret; - int i; - - /* Set all ports to disabled state. */ - for (i = 0; i < AR7240_NUM_PORTS; i++) - ar7240sw_disable_port(as, i); - - /* Wait for transmit queues to drain. */ - msleep(2); - - /* Reset the switch. */ - ar7240sw_reg_write(mii, AR7240_REG_MASK_CTRL, - AR7240_MASK_CTRL_SOFT_RESET); - - ret = ar7240sw_reg_wait(mii, AR7240_REG_MASK_CTRL, - AR7240_MASK_CTRL_SOFT_RESET, 0, 1000); - return ret; -} - static void ar7240sw_setup(struct ar7240sw *as) { struct mii_bus *mii = as->mii_bus; @@ -446,8 +430,12 @@ static void ar7240sw_setup(struct ar7240sw *as) /* Setup TAG priority mapping */ ar7240sw_reg_write(mii, AR7240_REG_TAG_PRIORITY, 0xfa50); - /* Enable ARP frame acknowledge */ - ar7240sw_reg_set(mii, AR7240_REG_AT_CTRL, AR7240_AT_CTRL_ARP_EN); + /* Enable ARP frame acknowledge, aging, MAC replacing */ + ar7240sw_reg_write(mii, AR7240_REG_AT_CTRL, + 0x2b /* 5 min age time */ | + AR7240_AT_CTRL_AGE_EN | + AR7240_AT_CTRL_ARP_EN | + AR7240_AT_CTRL_LEARN_CHANGE); /* Enable Broadcast frames transmitted to the CPU */ ar7240sw_reg_set(mii, AR7240_REG_FLOOD_MASK, @@ -461,6 +449,30 @@ static void ar7240sw_setup(struct ar7240sw *as) ar7240sw_reg_rmw(mii, AR7240_REG_SERVICE_TAG, AR7240_SERVICE_TAG_M, 0); } +static int ar7240sw_reset(struct ar7240sw *as) +{ + struct mii_bus *mii = as->mii_bus; + int ret; + int i; + + /* Set all ports to disabled state. */ + for (i = 0; i < AR7240_NUM_PORTS; i++) + ar7240sw_disable_port(as, i); + + /* Wait for transmit queues to drain. */ + msleep(2); + + /* Reset the switch. */ + ar7240sw_reg_write(mii, AR7240_REG_MASK_CTRL, + AR7240_MASK_CTRL_SOFT_RESET); + + ret = ar7240sw_reg_wait(mii, AR7240_REG_MASK_CTRL, + AR7240_MASK_CTRL_SOFT_RESET, 0, 1000); + + ar7240sw_setup(as); + return ret; +} + static void ar7240sw_setup_port(struct ar7240sw *as, unsigned port, u8 portmask) { struct mii_bus *mii = as->mii_bus; @@ -857,7 +869,6 @@ void ag71xx_ar7240_start(struct ag71xx *ag) struct ar7240sw *as = ag->phy_priv; ar7240sw_reset(as); - ar7240sw_setup(as); ag->speed = SPEED_1000; ag->duplex = 1; 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 0eb5ce15bd..2a7ba3336c 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c @@ -344,93 +344,6 @@ static unsigned char *ag71xx_speed_str(struct ag71xx *ag) return "?"; } -void ag71xx_link_adjust(struct ag71xx *ag) -{ - struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); - u32 cfg2; - u32 ifctl; - u32 fifo5; - u32 mii_speed; - - if (!ag->link) { - netif_carrier_off(ag->dev); - if (netif_msg_link(ag)) - printk(KERN_INFO "%s: link down\n", ag->dev->name); - return; - } - - 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; - - ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL); - ifctl &= ~(MAC_IFCTL_SPEED); - - fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5); - fifo5 &= ~FIFO_CFG5_BM; - - switch (ag->speed) { - case SPEED_1000: - mii_speed = MII_CTRL_SPEED_1000; - cfg2 |= MAC_CFG2_IF_1000; - fifo5 |= FIFO_CFG5_BM; - break; - case SPEED_100: - mii_speed = MII_CTRL_SPEED_100; - cfg2 |= MAC_CFG2_IF_10_100; - ifctl |= MAC_IFCTL_SPEED; - break; - case SPEED_10: - mii_speed = MII_CTRL_SPEED_10; - cfg2 |= MAC_CFG2_IF_10_100; - break; - default: - BUG(); - return; - } - - if (pdata->is_ar91xx) - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x00780fff); - else if (pdata->is_ar724x) - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, pdata->fifo_cfg3); - else - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x008001ff); - - if (pdata->set_pll) - pdata->set_pll(ag->speed); - - ag71xx_mii_ctrl_set_speed(ag, mii_speed); - - ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2); - ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5); - ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl); - - netif_carrier_on(ag->dev); - if (netif_msg_link(ag)) - printk(KERN_INFO "%s: link up (%sMbps/%s duplex)\n", - ag->dev->name, - ag71xx_speed_str(ag), - (DUPLEX_FULL == ag->duplex) ? "Full" : "Half"); - - DBG("%s: fifo_cfg0=%#x, fifo_cfg1=%#x, fifo_cfg2=%#x\n", - ag->dev->name, - ag71xx_rr(ag, AG71XX_REG_FIFO_CFG0), - ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1), - ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2)); - - DBG("%s: fifo_cfg3=%#x, fifo_cfg4=%#x, fifo_cfg5=%#x\n", - ag->dev->name, - ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3), - ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4), - ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5)); - - DBG("%s: mac_cfg2=%#x, mac_ifctl=%#x, mii_ctrl=%#x\n", - ag->dev->name, - ag71xx_rr(ag, AG71XX_REG_MAC_CFG2), - ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL), - ag71xx_mii_ctrl_rr(ag)); -} - static void ag71xx_hw_set_macaddr(struct ag71xx *ag, unsigned char *mac) { u32 t; @@ -511,9 +424,31 @@ static void ag71xx_dma_reset(struct ag71xx *ag) FIFO_CFG5_LE | FIFO_CFG5_FT | FIFO_CFG5_16 | \ FIFO_CFG5_17 | FIFO_CFG5_SF) +static void ag71xx_hw_stop(struct ag71xx *ag) +{ + /* disable all interrupts and stop the rx engine */ + ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, 0); + ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0); +} + static void ag71xx_hw_init(struct ag71xx *ag) { struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); + u32 reset_mask = pdata->reset_bit; + + ag71xx_hw_stop(ag); + + if (pdata->is_ar724x) { + u32 reset_phy = reset_mask; + + reset_phy &= RESET_MODULE_GE0_PHY | RESET_MODULE_GE1_PHY; + reset_mask &= ~(RESET_MODULE_GE0_PHY | RESET_MODULE_GE1_PHY); + + ar71xx_device_stop(reset_phy); + mdelay(50); + ar71xx_device_start(reset_phy); + mdelay(200); + } ag71xx_sb(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_SR); udelay(20); @@ -521,14 +456,10 @@ static void ag71xx_hw_init(struct ag71xx *ag) ar71xx_device_stop(pdata->reset_bit); mdelay(100); ar71xx_device_start(pdata->reset_bit); - mdelay(100); + mdelay(200); /* setup MAC configuration registers */ - if (pdata->is_ar724x) - ag71xx_wr(ag, AG71XX_REG_MAC_CFG1, - MAC_CFG1_INIT | MAC_CFG1_TFC | MAC_CFG1_RFC); - else - ag71xx_wr(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_INIT); + 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); @@ -563,12 +494,93 @@ static void ag71xx_hw_start(struct ag71xx *ag) ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, AG71XX_INT_INIT); } -static void ag71xx_hw_stop(struct ag71xx *ag) +void ag71xx_link_adjust(struct ag71xx *ag) { - /* disable all interrupts */ - ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, 0); + struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); + u32 cfg2; + u32 ifctl; + u32 fifo5; + u32 mii_speed; - ag71xx_dma_reset(ag); + if (!ag->link) { + ag71xx_hw_stop(ag); + netif_carrier_off(ag->dev); + if (netif_msg_link(ag)) + printk(KERN_INFO "%s: link down\n", ag->dev->name); + return; + } + + 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; + + ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL); + ifctl &= ~(MAC_IFCTL_SPEED); + + fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5); + fifo5 &= ~FIFO_CFG5_BM; + + switch (ag->speed) { + case SPEED_1000: + mii_speed = MII_CTRL_SPEED_1000; + cfg2 |= MAC_CFG2_IF_1000; + fifo5 |= FIFO_CFG5_BM; + break; + case SPEED_100: + mii_speed = MII_CTRL_SPEED_100; + cfg2 |= MAC_CFG2_IF_10_100; + ifctl |= MAC_IFCTL_SPEED; + break; + case SPEED_10: + mii_speed = MII_CTRL_SPEED_10; + cfg2 |= MAC_CFG2_IF_10_100; + break; + default: + BUG(); + return; + } + + if (pdata->is_ar91xx) + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x00780fff); + else if (pdata->is_ar724x) + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, pdata->fifo_cfg3); + else + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x008001ff); + + if (pdata->set_pll) + pdata->set_pll(ag->speed); + + ag71xx_mii_ctrl_set_speed(ag, mii_speed); + + ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2); + ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5); + ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl); + ag71xx_hw_start(ag); + + netif_carrier_on(ag->dev); + if (netif_msg_link(ag)) + printk(KERN_INFO "%s: link up (%sMbps/%s duplex)\n", + ag->dev->name, + ag71xx_speed_str(ag), + (DUPLEX_FULL == ag->duplex) ? "Full" : "Half"); + + DBG("%s: fifo_cfg0=%#x, fifo_cfg1=%#x, fifo_cfg2=%#x\n", + ag->dev->name, + ag71xx_rr(ag, AG71XX_REG_FIFO_CFG0), + ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1), + ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2)); + + DBG("%s: fifo_cfg3=%#x, fifo_cfg4=%#x, fifo_cfg5=%#x\n", + ag->dev->name, + ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3), + ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4), + ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5)); + + DBG("%s: mac_cfg2=%#x, mac_ifctl=%#x, mii_ctrl=%#x\n", + ag->dev->name, + ag71xx_rr(ag, AG71XX_REG_MAC_CFG2), + ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL), + ag71xx_mii_ctrl_rr(ag)); } static int ag71xx_open(struct net_device *dev) @@ -590,8 +602,6 @@ static int ag71xx_open(struct net_device *dev) ag71xx_hw_set_macaddr(ag, dev->dev_addr); - ag71xx_hw_start(ag); - netif_start_queue(dev); return 0; @@ -614,6 +624,7 @@ static int ag71xx_stop(struct net_device *dev) netif_stop_queue(dev); ag71xx_hw_stop(ag); + ag71xx_dma_reset(ag); napi_disable(&ag->napi); del_timer_sync(&ag->oom_timer); @@ -744,13 +755,8 @@ static void ag71xx_tx_timeout(struct net_device *dev) static void ag71xx_restart_work_func(struct work_struct *work) { struct ag71xx *ag = container_of(work, struct ag71xx, restart_work); - struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ag71xx_stop(ag->dev); - - if (pdata->is_ar724x) - ag71xx_hw_init(ag); - ag71xx_open(ag->dev); }