X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=blobdiff_plain;f=target%2Flinux%2Fatheros%2Fpatches-3.10%2F110-ar2313_ethernet.patch;h=a9dcab24c941f20d27cabc3a4d23ef5f361e390b;hp=00348c3537b70a30b9166e8f7402dbb3ce50f5af;hb=c7629cdb4844f8db31bf0ef9d63889011c02e14c;hpb=03d67b0fdb6ebf68a5d9801fb3a78cdc1b284dfd diff --git a/target/linux/atheros/patches-3.10/110-ar2313_ethernet.patch b/target/linux/atheros/patches-3.10/110-ar2313_ethernet.patch index 00348c3537..a9dcab24c9 100644 --- a/target/linux/atheros/patches-3.10/110-ar2313_ethernet.patch +++ b/target/linux/atheros/patches-3.10/110-ar2313_ethernet.patch @@ -1,38 +1,39 @@ ---- a/drivers/net/ethernet/Kconfig -+++ b/drivers/net/ethernet/Kconfig -@@ -22,6 +22,7 @@ source "drivers/net/ethernet/adaptec/Kco - source "drivers/net/ethernet/aeroflex/Kconfig" - source "drivers/net/ethernet/alteon/Kconfig" - source "drivers/net/ethernet/amd/Kconfig" -+source "drivers/net/ethernet/ar231x/Kconfig" - source "drivers/net/ethernet/apple/Kconfig" - source "drivers/net/ethernet/atheros/Kconfig" - source "drivers/net/ethernet/cadence/Kconfig" ---- a/drivers/net/ethernet/Makefile -+++ b/drivers/net/ethernet/Makefile -@@ -9,6 +9,7 @@ obj-$(CONFIG_GRETH) += aeroflex/ - obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/ - obj-$(CONFIG_NET_VENDOR_AMD) += amd/ - obj-$(CONFIG_NET_VENDOR_APPLE) += apple/ -+obj-$(CONFIG_NET_VENDOR_AR231X) += ar231x/ - obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/ - obj-$(CONFIG_NET_CADENCE) += cadence/ - obj-$(CONFIG_NET_BFIN) += adi/ ---- /dev/null -+++ b/drivers/net/ethernet/ar231x/Kconfig -@@ -0,0 +1,5 @@ -+config NET_VENDOR_AR231X -+ tristate "AR231X Ethernet support" +--- a/drivers/net/ethernet/atheros/Makefile ++++ b/drivers/net/ethernet/atheros/Makefile +@@ -7,3 +7,4 @@ obj-$(CONFIG_ATL2) += atlx/ + obj-$(CONFIG_ATL1E) += atl1e/ + obj-$(CONFIG_ATL1C) += atl1c/ + obj-$(CONFIG_ALX) += alx/ ++obj-$(CONFIG_NET_AR231X) += ar231x/ +--- a/drivers/net/ethernet/atheros/Kconfig ++++ b/drivers/net/ethernet/atheros/Kconfig +@@ -5,7 +5,7 @@ + config NET_VENDOR_ATHEROS + bool "Atheros devices" + default y +- depends on PCI ++ depends on (PCI || ATHEROS_AR231X) + ---help--- + If you have a network (Ethernet) card belonging to this class, say Y + and read the Ethernet-HOWTO, available from +@@ -85,4 +85,10 @@ config ALX + To compile this driver as a module, choose M here. The module + will be called alx. + ++config NET_AR231X ++ tristate "Atheros AR231X built-in Ethernet support" + depends on ATHEROS_AR231X + help + Support for the AR231x/531x ethernet controller ++ + endif # NET_VENDOR_ATHEROS --- /dev/null -+++ b/drivers/net/ethernet/ar231x/Makefile ++++ b/drivers/net/ethernet/atheros/ar231x/Makefile @@ -0,0 +1 @@ -+obj-$(CONFIG_NET_VENDOR_AR231X) += ar231x.o ++obj-$(CONFIG_NET_AR231X) += ar231x.o --- /dev/null -+++ b/drivers/net/ethernet/ar231x/ar231x.c -@@ -0,0 +1,1257 @@ ++++ b/drivers/net/ethernet/atheros/ar231x/ar231x.c +@@ -0,0 +1,1250 @@ +/* + * ar231x.c: Linux driver for the Atheros AR231x Ethernet device. + * @@ -159,7 +160,8 @@ +#define VLAN_HDR 0 +#endif + -+#define AR2313_BUFSIZE (AR2313_MTU + VLAN_HDR + ETH_HLEN + CRC_LEN + RX_OFFSET) ++#define AR2313_BUFSIZE (AR2313_MTU + VLAN_HDR + ETH_HLEN + CRC_LEN + \ ++ RX_OFFSET) + +#ifdef MODULE +MODULE_LICENSE("GPL"); @@ -177,7 +179,8 @@ +static void ar231x_tx_timeout(struct net_device *dev); + +static int ar231x_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum); -+static int ar231x_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, u16 value); ++static int ar231x_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, ++ u16 value); +static int ar231x_mdiobus_reset(struct mii_bus *bus); +static int ar231x_mdiobus_probe(struct net_device *dev); +static void ar231x_adjust_link(struct net_device *dev); @@ -213,7 +216,7 @@ +#endif +}; + -+int ar231x_probe(struct platform_device *pdev) ++static int ar231x_probe(struct platform_device *pdev) +{ + struct net_device *dev; + struct ar231x_private *sp; @@ -254,8 +257,7 @@ + tasklet_init(&sp->rx_tasklet, rx_tasklet_func, (unsigned long) dev); + tasklet_disable(&sp->rx_tasklet); + -+ sp->eth_regs = -+ ioremap_nocache(virt_to_phys(ar_eth_base), sizeof(*sp->eth_regs)); ++ sp->eth_regs = ioremap_nocache(ar_eth_base, sizeof(*sp->eth_regs)); + if (!sp->eth_regs) { + printk("Can't remap eth registers\n"); + return -ENXIO; @@ -264,34 +266,28 @@ + /** + * When there's only one MAC, PHY regs are typically on ENET0, + * even though the MAC might be on ENET1. -+ * Needto remap PHY regs separately in this case ++ * So remap PHY regs separately. + */ -+ if (virt_to_phys(ar_eth_base) == virt_to_phys(sp->phy_regs)) -+ sp->phy_regs = sp->eth_regs; -+ else { -+ sp->phy_regs = -+ ioremap_nocache(virt_to_phys(sp->cfg->phy_base), -+ sizeof(*sp->phy_regs)); -+ if (!sp->phy_regs) { -+ printk("Can't remap phy registers\n"); -+ return -ENXIO; -+ } ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eth0_mii"); ++ if (!res) { ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, ++ "eth1_mii"); ++ if (!res) ++ return -ENODEV; + } -+ -+ sp->dma_regs = -+ ioremap_nocache(virt_to_phys(ar_eth_base + 0x1000), -+ sizeof(*sp->dma_regs)); -+ dev->base_addr = (unsigned int) sp->dma_regs; -+ if (!sp->dma_regs) { -+ printk("Can't remap DMA registers\n"); ++ sp->phy_regs = ioremap_nocache(res->start, resource_size(res)); ++ if (!sp->phy_regs) { ++ printk("Can't remap phy registers\n"); + return -ENXIO; + } + -+ sp->int_regs = ioremap_nocache(virt_to_phys(sp->cfg->reset_base), 4); -+ if (!sp->int_regs) { -+ printk("Can't remap INTERRUPT registers\n"); ++ sp->dma_regs = ioremap_nocache(ar_eth_base + 0x1000, ++ sizeof(*sp->dma_regs)); ++ if (!sp->dma_regs) { ++ printk("Can't remap DMA registers\n"); + return -ENXIO; + } ++ dev->base_addr = ar_eth_base + 0x1000; + + strncpy(sp->name, "Atheros AR231x", sizeof(sp->name) - 1); + sp->name[sizeof(sp->name) - 1] = '\0'; @@ -308,10 +304,8 @@ + return -1; + } + -+ printk("%s: %s: %02x:%02x:%02x:%02x:%02x:%02x, irq %d\n", -+ dev->name, sp->name, -+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], -+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], dev->irq); ++ printk("%s: %s: %pM, irq %d\n", dev->name, sp->name, dev->dev_addr, ++ dev->irq); + + sp->mii_bus = mdiobus_alloc(); + if (sp->mii_bus == NULL) @@ -442,8 +436,7 @@ + return 0; + } + -+ size = -+ (sizeof(ar231x_descr_t) * (AR2313_DESCR_ENTRIES * AR2313_QUEUES)); ++ size = sizeof(ar231x_descr_t) * (AR2313_DESCR_ENTRIES * AR2313_QUEUES); + space = kmalloc(size, GFP_KERNEL); + if (space == NULL) + return 1; @@ -468,9 +461,7 @@ + td->status = 0; + td->devcs = DMA_TX1_CHAINED; + td->addr = 0; -+ td->descr = -+ virt_to_phys(&sp-> -+ tx_ring[(j + 1) & (AR2313_DESCR_ENTRIES - 1)]); ++ td->descr = virt_to_phys(&sp->tx_ring[DSC_NEXT(j)]); + } + + return 0; @@ -493,6 +484,8 @@ + iounmap((void *)sp->eth_regs); + if (sp->dma_regs) + iounmap((void *)sp->dma_regs); ++ if (sp->phy_regs) ++ iounmap((void *)sp->phy_regs); + + if (sp->rx_skb) { + for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { @@ -571,11 +564,14 @@ + u16 reg; + + sp->link = 1; -+ reg = ar231x_mdiobus_read(sp->mii_bus, sp->phy, MII_BMCR); ++ reg = ar231x_mdiobus_read(sp->mii_bus, sp->phy, ++ MII_BMCR); + if (reg & BMCR_ANENABLE) { + /* auto neg enabled */ -+ reg = ar231x_mdiobus_read(sp->mii_bus, sp->phy, MII_LPA); -+ duplex = (reg & (LPA_100FULL | LPA_10FULL)) ? 1 : 0; ++ reg = ar231x_mdiobus_read(sp->mii_bus, sp->phy, ++ MII_LPA); ++ duplex = reg & (LPA_100FULL | LPA_10FULL) ? ++ 1 : 0; + } else { + /* no auto neg, just read duplex config */ + duplex = (reg & BMCR_FULLDPLX) ? 1 : 0; @@ -587,13 +583,13 @@ + if (duplex) { + /* full duplex */ + sp->eth_regs->mac_control = -+ ((sp->eth_regs-> -+ mac_control | MAC_CONTROL_F) & ~MAC_CONTROL_DRO); ++ (sp->eth_regs->mac_control | ++ MAC_CONTROL_F) & ~MAC_CONTROL_DRO; + } else { + /* half duplex */ + sp->eth_regs->mac_control = -+ ((sp->eth_regs-> -+ mac_control | MAC_CONTROL_DRO) & ~MAC_CONTROL_F); ++ (sp->eth_regs->mac_control | ++ MAC_CONTROL_DRO) & ~MAC_CONTROL_F; + } + } else { + /* no link */ @@ -609,13 +605,13 @@ + unsigned int ethsal, ethsah; + unsigned int flags; + -+ *sp->int_regs |= sp->cfg->reset_mac; ++ sp->cfg->reset_set(sp->cfg->reset_mac); + mdelay(10); -+ *sp->int_regs &= ~sp->cfg->reset_mac; ++ sp->cfg->reset_clear(sp->cfg->reset_mac); + mdelay(10); -+ *sp->int_regs |= sp->cfg->reset_phy; ++ sp->cfg->reset_set(sp->cfg->reset_phy); + mdelay(10); -+ *sp->int_regs &= ~sp->cfg->reset_phy; ++ sp->cfg->reset_clear(sp->cfg->reset_phy); + mdelay(10); + + sp->dma_regs->bus_mode = (DMA_BUS_MODE_SWR); @@ -624,10 +620,9 @@ + ((32 << DMA_BUS_MODE_PBL_SHIFT) | DMA_BUS_MODE_BLE); + + /* enable interrupts */ -+ sp->dma_regs->intr_ena = (DMA_STATUS_AIS | -+ DMA_STATUS_NIS | -+ DMA_STATUS_RI | -+ DMA_STATUS_TI | DMA_STATUS_FBE); ++ sp->dma_regs->intr_ena = DMA_STATUS_AIS | DMA_STATUS_NIS | ++ DMA_STATUS_RI | DMA_STATUS_TI | ++ DMA_STATUS_FBE; + sp->dma_regs->xmt_base = virt_to_phys(sp->tx_ring); + sp->dma_regs->rcv_base = virt_to_phys(sp->rx_ring); + sp->dma_regs->control = @@ -648,13 +643,13 @@ + sp->eth_regs->mac_control = flags; + + /* Set all Ethernet station address registers to their initial values */ -+ ethsah = ((((u_int) (dev->dev_addr[5]) << 8) & (u_int) 0x0000FF00) | -+ (((u_int) (dev->dev_addr[4]) << 0) & (u_int) 0x000000FF)); ++ ethsah = (((u_int) (dev->dev_addr[5]) << 8) & (u_int) 0x0000FF00) | ++ (((u_int) (dev->dev_addr[4]) << 0) & (u_int) 0x000000FF); + -+ ethsal = ((((u_int) (dev->dev_addr[3]) << 24) & (u_int) 0xFF000000) | -+ (((u_int) (dev->dev_addr[2]) << 16) & (u_int) 0x00FF0000) | -+ (((u_int) (dev->dev_addr[1]) << 8) & (u_int) 0x0000FF00) | -+ (((u_int) (dev->dev_addr[0]) << 0) & (u_int) 0x000000FF)); ++ ethsal = (((u_int) (dev->dev_addr[3]) << 24) & (u_int) 0xFF000000) | ++ (((u_int) (dev->dev_addr[2]) << 16) & (u_int) 0x00FF0000) | ++ (((u_int) (dev->dev_addr[1]) << 8) & (u_int) 0x0000FF00) | ++ (((u_int) (dev->dev_addr[0]) << 0) & (u_int) 0x000000FF); + + sp->eth_regs->mac_addr[0] = ethsah; + sp->eth_regs->mac_addr[1] = ethsal; @@ -787,9 +782,7 @@ + rd->devcs = ((AR2313_BUFSIZE << DMA_RX1_BSIZE_SHIFT) | + DMA_RX1_CHAINED); + rd->addr = virt_to_phys(skb->data); -+ rd->descr = -+ virt_to_phys(&sp-> -+ rx_ring[(idx + 1) & (AR2313_DESCR_ENTRIES - 1)]); ++ rd->descr = virt_to_phys(&sp->rx_ring[DSC_NEXT(idx)]); + rd->status = DMA_RX_OWN; + + idx = DSC_NEXT(idx); @@ -849,12 +842,13 @@ + + } else { + /* alloc new buffer. */ -+ skb_new = netdev_alloc_skb_ip_align(dev, AR2313_BUFSIZE); ++ skb_new = netdev_alloc_skb_ip_align(dev, ++ AR2313_BUFSIZE); + if (skb_new != NULL) { + skb = sp->rx_skb[idx]; + /* set skb */ -+ skb_put(skb, -+ ((status >> DMA_RX_LEN_SHIFT) & 0x3fff) - CRC_LEN); ++ skb_put(skb, ((status >> DMA_RX_LEN_SHIFT) & ++ 0x3fff) - CRC_LEN); + + dev->stats.rx_bytes += skb->len; + skb->protocol = eth_type_trans(skb, dev); @@ -905,8 +899,8 @@ + } + /* done with this descriptor */ + dma_unmap_single(NULL, txdesc->addr, -+ txdesc->devcs & DMA_TX1_BSIZE_MASK, -+ DMA_TO_DEVICE); ++ txdesc->devcs & DMA_TX1_BSIZE_MASK, ++ DMA_TO_DEVICE); + txdesc->status = 0; + + if (status & DMA_TX_ERROR) { @@ -918,9 +912,8 @@ + dev->stats.tx_heartbeat_errors++; + if (status & (DMA_TX_ERR_LOSS | DMA_TX_ERR_LINK)) + dev->stats.tx_carrier_errors++; -+ if (status & (DMA_TX_ERR_LATE | -+ DMA_TX_ERR_COL | -+ DMA_TX_ERR_JABBER | DMA_TX_ERR_DEFER)) ++ if (status & (DMA_TX_ERR_LATE | DMA_TX_ERR_COL | ++ DMA_TX_ERR_JABBER | DMA_TX_ERR_DEFER)) + dev->stats.tx_aborted_errors++; + } else { + /* transmit OK */ @@ -1009,13 +1002,13 @@ + unsigned int ethsal, ethsah; + + /* reset the hardware, in case the MAC address changed */ -+ ethsah = ((((u_int) (dev->dev_addr[5]) << 8) & (u_int) 0x0000FF00) | -+ (((u_int) (dev->dev_addr[4]) << 0) & (u_int) 0x000000FF)); ++ ethsah = (((u_int) (dev->dev_addr[5]) << 8) & (u_int) 0x0000FF00) | ++ (((u_int) (dev->dev_addr[4]) << 0) & (u_int) 0x000000FF); + -+ ethsal = ((((u_int) (dev->dev_addr[3]) << 24) & (u_int) 0xFF000000) | -+ (((u_int) (dev->dev_addr[2]) << 16) & (u_int) 0x00FF0000) | -+ (((u_int) (dev->dev_addr[1]) << 8) & (u_int) 0x0000FF00) | -+ (((u_int) (dev->dev_addr[0]) << 0) & (u_int) 0x000000FF)); ++ ethsal = (((u_int) (dev->dev_addr[3]) << 24) & (u_int) 0xFF000000) | ++ (((u_int) (dev->dev_addr[2]) << 16) & (u_int) 0x00FF0000) | ++ (((u_int) (dev->dev_addr[1]) << 8) & (u_int) 0x0000FF00) | ++ (((u_int) (dev->dev_addr[0]) << 0) & (u_int) 0x000000FF); + + sp->eth_regs->mac_addr[0] = ethsah; + sp->eth_regs->mac_addr[1] = ethsal; @@ -1049,13 +1042,14 @@ + + /* kill the MAC */ + sp->eth_regs->mac_control &= ~(MAC_CONTROL_RE | /* disable Receives */ -+ MAC_CONTROL_TE); /* disable Transmits */ ++ MAC_CONTROL_TE); /* disable Transmits */ + /* stop dma */ + sp->dma_regs->control = 0; + sp->dma_regs->bus_mode = DMA_BUS_MODE_SWR; + + /* place phy and MAC in reset */ -+ *sp->int_regs |= (sp->cfg->reset_mac | sp->cfg->reset_phy); ++ sp->cfg->reset_set(sp->cfg->reset_mac); ++ sp->cfg->reset_set(sp->cfg->reset_phy); + + /* free buffers on tx ring */ + for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { @@ -1079,7 +1073,7 @@ + * the irq is gone forever ! When bond0 is made 'up' again, + * the ar231x_open () does not call request_irq (). Worse, + * the call to ar231x_halt() generates a WDOG reset due to -+ * the write to 'sp->int_regs' and the box reboots. ++ * the write to reset register and the box reboots. + * Commenting this out is good since it allows the + * system to resume when bond0 is made up again. + */ @@ -1205,7 +1199,7 @@ +{ + struct net_device *const dev = bus->priv; + struct ar231x_private *sp = netdev_priv(dev); -+ volatile ETHERNET_STRUCT *ethernet = sp->phy_regs; ++ volatile MII *ethernet = sp->phy_regs; + + ethernet->mii_addr = MII_ADDR(phy_addr, regnum); + while (ethernet->mii_addr & MII_ADDR_BUSY) @@ -1218,7 +1212,7 @@ +{ + struct net_device *const dev = bus->priv; + struct ar231x_private *sp = netdev_priv(dev); -+ volatile ETHERNET_STRUCT *ethernet = sp->phy_regs; ++ volatile MII *ethernet = sp->phy_regs; + + while (ethernet->mii_addr & MII_ADDR_BUSY) + ; @@ -1260,8 +1254,8 @@ + BUG_ON(!phydev); + BUG_ON(phydev->attached_dev); + -+ phydev = phy_connect(dev, dev_name(&phydev->dev), &ar231x_adjust_link, 0, -+ PHY_INTERFACE_MODE_MII); ++ phydev = phy_connect(dev, dev_name(&phydev->dev), &ar231x_adjust_link, ++ PHY_INTERFACE_MODE_MII); + + if (IS_ERR(phydev)) { + printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); @@ -1291,8 +1285,8 @@ +} + --- /dev/null -+++ b/drivers/net/ethernet/ar231x/ar231x.h -@@ -0,0 +1,288 @@ ++++ b/drivers/net/ethernet/atheros/ar231x/ar231x.h +@@ -0,0 +1,295 @@ +/* + * ar231x.h: Linux driver for the Atheros AR231x Ethernet device. + * @@ -1400,13 +1394,13 @@ +#define MAC_CONTROL_HO BIT(15) /* Hash only filtering */ +#define MAC_CONTROL_PB BIT(16) /* Pass Bad frames */ +#define MAC_CONTROL_IF BIT(17) /* Inverse filtering */ -+#define MAC_CONTROL_PR BIT(18) /* promiscuous mode (valid frames only) */ ++#define MAC_CONTROL_PR BIT(18) /* promis mode (valid frames only) */ +#define MAC_CONTROL_PM BIT(19) /* pass multicast */ +#define MAC_CONTROL_F BIT(20) /* full-duplex */ +#define MAC_CONTROL_DRO BIT(23) /* Disable Receive Own */ +#define MAC_CONTROL_HBD BIT(28) /* heart-beat disabled (MUST BE SET) */ +#define MAC_CONTROL_BLE BIT(30) /* big endian mode */ -+#define MAC_CONTROL_RA BIT(31) /* receive all (valid and invalid frames) */ ++#define MAC_CONTROL_RA BIT(31) /* rcv all (valid and invalid frames) */ + +#define MII_ADDR_BUSY BIT(0) +#define MII_ADDR_WRITE BIT(1) @@ -1454,13 +1448,16 @@ + +/** + * New Combo structure for Both Eth0 AND eth1 ++ * ++ * Don't directly access MII related regs since phy chip could be actually ++ * connected to another ethernet block. + */ +typedef struct { + volatile unsigned int mac_control; /* 0x00 */ + volatile unsigned int mac_addr[2]; /* 0x04 - 0x08 */ + volatile unsigned int mcast_table[2]; /* 0x0c - 0x10 */ -+ volatile unsigned int mii_addr; /* 0x14 */ -+ volatile unsigned int mii_data; /* 0x18 */ ++ volatile unsigned int __mii_addr; /* 0x14 */ ++ volatile unsigned int __mii_data; /* 0x18 */ + volatile unsigned int flow_control; /* 0x1c */ + volatile unsigned int vlan_tag; /* 0x20 */ + volatile unsigned int pad[7]; /* 0x24 - 0x3c */ @@ -1468,6 +1465,11 @@ + +} ETHERNET_STRUCT; + ++typedef struct { ++ volatile unsigned int mii_addr; ++ volatile unsigned int mii_data; ++} MII; ++ +/******************************************************************** + * Interrupt controller + ********************************************************************/ @@ -1515,10 +1517,9 @@ + int version; + u32 mb[2]; + -+ volatile ETHERNET_STRUCT *phy_regs; ++ volatile MII *phy_regs; + volatile ETHERNET_STRUCT *eth_regs; + volatile DMA *dma_regs; -+ volatile u32 *int_regs; + struct ar231x_eth *cfg; + + spinlock_t lock; /* Serialise access to device */ @@ -1549,7 +1550,7 @@ + + + struct timer_list link_timer; -+ unsigned short phy; /* merlot phy = 1, samsung phy = 0x1f */ ++ unsigned short phy; /* merlot phy = 1, samsung phy = 0x1f */ + unsigned short mac; + unsigned short link; /* 0 - link down, 1 - link up */ + u16 phy_data;