atheros: add 3.14 configuration
[openwrt/svn-archive/archive.git] / target / linux / atheros / patches-3.10 / 110-ar2313_ethernet.patch
index 00348c3537b70a30b9166e8f7402dbb3ce50f5af..a9dcab24c941f20d27cabc3a4d23ef5f361e390b 100644 (file)
@@ -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.
 + *
 +#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");
 +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);
 +#endif
 +};
 +
-+int ar231x_probe(struct platform_device *pdev)
++static int ar231x_probe(struct platform_device *pdev)
 +{
 +      struct net_device *dev;
 +      struct ar231x_private *sp;
 +      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;
 +      /**
 +       * 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';
 +              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)
 +              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;
 +              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;
 +              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++) {
 +                      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;
 +                      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 */
 +      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);
 +              ((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 =
 +      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;
 +              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);
 +
 +              } 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);
 +              }
 +              /* 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) {
 +                              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 */
 +      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;
 +
 +      /* 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++) {
 + * 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.
 + */
 +{
 +      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)
 +{
 +      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)
 +              ;
 +      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);
 +}
 +
 --- /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.
 + *
 +#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)
 +
 +/**
 + * 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 */
 +
 +} ETHERNET_STRUCT;
 +
++typedef struct {
++      volatile unsigned int mii_addr;
++      volatile unsigned int mii_data;
++} MII;
++
 +/********************************************************************
 + * Interrupt controller
 + ********************************************************************/
 +      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 */
 +
 +
 +      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;