generic: ar8216: add support for the AR8327 chip
authorGabor Juhos <juhosg@openwrt.org>
Sun, 18 Mar 2012 22:06:55 +0000 (22:06 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Sun, 18 Mar 2012 22:06:55 +0000 (22:06 +0000)
SVN-Revision: 31011

target/linux/generic/files/drivers/net/phy/ar8216.c
target/linux/generic/files/drivers/net/phy/ar8216.h
target/linux/generic/files/include/linux/ar8216_platform.h [new file with mode: 0644]

index b5c13b084f3ebfa60a9e1f07f2e9e0c809081667..93d30079f8af1172899813aa8956934d1841c061 100644 (file)
@@ -2,6 +2,7 @@
  * ar8216.c: AR8216 switch driver
  *
  * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -30,6 +31,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/lockdep.h>
+#include <linux/ar8216_platform.h>
 #include "ar8216.h"
 
 /* size of the vlan table */
@@ -70,6 +72,7 @@ struct ar8216_priv {
        char buf[80];
 
        bool init;
+       bool mii_lo_first;
 
        /* all fields below are cleared on reset */
        bool vlan;
@@ -137,8 +140,13 @@ ar8216_mii_write(struct ar8216_priv *priv, int reg, u32 val)
 
        bus->write(bus, 0x18, 0, r3);
        usleep_range(1000, 2000); /* wait for the page switch to propagate */
-       bus->write(bus, 0x10 | r2, r1 + 1, hi);
-       bus->write(bus, 0x10 | r2, r1, lo);
+       if (priv->mii_lo_first) {
+               bus->write(bus, 0x10 | r2, r1, lo);
+               bus->write(bus, 0x10 | r2, r1 + 1, hi);
+       } else {
+               bus->write(bus, 0x10 | r2, r1 + 1, hi);
+               bus->write(bus, 0x10 | r2, r1, lo);
+       }
 
        mutex_unlock(&bus->mdio_lock);
 }
@@ -609,6 +617,309 @@ static const struct ar8xxx_chip ar8316_chip = {
        .vtu_load_vlan = ar8216_vtu_load_vlan,
 };
 
+static u32
+ar8327_get_pad_cfg(struct ar8327_pad_cfg *cfg)
+{
+       u32 t;
+
+       if (!cfg)
+               return 0;
+
+       t = 0;
+       switch (cfg->mode) {
+       case AR8327_PAD_NC:
+               break;
+
+       case AR8327_PAD_MAC2MAC_MII:
+               t = AR8327_PAD_MAC_MII_EN;
+               if (cfg->rxclk_sel)
+                       t |= AR8327_PAD_MAC_MII_RXCLK_SEL;
+               if (cfg->txclk_sel)
+                       t |= AR8327_PAD_MAC_MII_TXCLK_SEL;
+               break;
+
+       case AR8327_PAD_MAC2MAC_GMII:
+               t = AR8327_PAD_MAC_GMII_EN;
+               if (cfg->rxclk_sel)
+                       t |= AR8327_PAD_MAC_GMII_RXCLK_SEL;
+               if (cfg->txclk_sel)
+                       t |= AR8327_PAD_MAC_GMII_TXCLK_SEL;
+               break;
+
+       case AR8327_PAD_MAC_SGMII:
+               t = AR8327_PAD_SGMII_EN;
+               break;
+
+       case AR8327_PAD_MAC2PHY_MII:
+               t = AR8327_PAD_PHY_MII_EN;
+               if (cfg->rxclk_sel)
+                       t |= AR8327_PAD_PHY_MII_RXCLK_SEL;
+               if (cfg->txclk_sel)
+                       t |= AR8327_PAD_PHY_MII_TXCLK_SEL;
+               break;
+
+       case AR8327_PAD_MAC2PHY_GMII:
+               t = AR8327_PAD_PHY_GMII_EN;
+               if (cfg->pipe_rxclk_sel)
+                       t |= AR8327_PAD_PHY_GMII_PIPE_RXCLK_SEL;
+               if (cfg->rxclk_sel)
+                       t |= AR8327_PAD_PHY_GMII_RXCLK_SEL;
+               if (cfg->txclk_sel)
+                       t |= AR8327_PAD_PHY_GMII_TXCLK_SEL;
+               break;
+
+       case AR8327_PAD_MAC_RGMII:
+               t = AR8327_PAD_RGMII_EN;
+               t |= cfg->txclk_delay_sel << AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S;
+               t |= cfg->rxclk_delay_sel << AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S;
+               if (cfg->rxclk_delay_en)
+                       t |= AR8327_PAD_RGMII_RXCLK_DELAY_EN;
+               if (cfg->txclk_delay_en)
+                       t |= AR8327_PAD_RGMII_TXCLK_DELAY_EN;
+               break;
+
+       case AR8327_PAD_PHY_GMII:
+               t = AR8327_PAD_PHYX_GMII_EN;
+               break;
+
+       case AR8327_PAD_PHY_RGMII:
+               t = AR8327_PAD_PHYX_RGMII_EN;
+               break;
+
+       case AR8327_PAD_PHY_MII:
+               t = AR8327_PAD_PHYX_MII_EN;
+               break;
+       }
+
+       return t;
+}
+
+static int
+ar8327_hw_init(struct ar8216_priv *priv)
+{
+       struct ar8327_platform_data *pdata;
+       u32 t;
+       int i;
+
+       pdata = priv->phy->dev.platform_data;
+       if (!pdata)
+               return -EINVAL;
+
+       t = ar8327_get_pad_cfg(pdata->pad0_cfg);
+       priv->write(priv, AR8327_REG_PAD0_MODE, t);
+       t = ar8327_get_pad_cfg(pdata->pad5_cfg);
+       priv->write(priv, AR8327_REG_PAD5_MODE, t);
+       t = ar8327_get_pad_cfg(pdata->pad6_cfg);
+       priv->write(priv, AR8327_REG_PAD6_MODE, t);
+
+       priv->write(priv, AR8327_REG_POWER_ON_STRIP, 0x40000000);
+
+       /* fixup PHYs */
+       for (i = 0; i < AR8327_NUM_PHYS; i++) {
+               /* For 100M waveform */
+               ar8216_phy_dbg_write(priv, i, 0, 0x02ea);
+
+               /* Turn on Gigabit clock */
+               ar8216_phy_dbg_write(priv, i, 0x3d, 0x68a0);
+       }
+
+       return 0;
+}
+
+static void
+ar8327_init_globals(struct ar8216_priv *priv)
+{
+       u32 t;
+
+       /* enable CPU port and disable mirror port */
+       t = AR8327_FWD_CTRL0_CPU_PORT_EN |
+           AR8327_FWD_CTRL0_MIRROR_PORT;
+       priv->write(priv, AR8327_REG_FWD_CTRL0, t);
+
+       /* forward multicast and broadcast frames to CPU */
+       t = (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_UC_FLOOD_S) |
+           (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_BC_FLOOD_S);
+       priv->write(priv, AR8327_REG_FWD_CTRL1, t);
+
+       /* setup MTU */
+       ar8216_rmw(priv, AR8327_REG_MAX_FRAME_SIZE,
+                  AR8327_MAX_FRAME_SIZE_MTU, 1518 + 8 + 2);
+}
+
+static void
+ar8327_init_cpuport(struct ar8216_priv *priv)
+{
+       struct ar8327_platform_data *pdata;
+       struct ar8327_port_cfg *cfg;
+       u32 t;
+
+       pdata = priv->phy->dev.platform_data;
+       if (!pdata)
+               return;
+
+       cfg = &pdata->cpuport_cfg;
+       if (!cfg->force_link) {
+               priv->write(priv, AR8327_REG_PORT_STATUS(AR8216_PORT_CPU),
+                           AR8216_PORT_STATUS_LINK_AUTO);
+               return;
+       }
+
+       t = AR8216_PORT_STATUS_TXMAC | AR8216_PORT_STATUS_RXMAC;
+       t |= cfg->duplex ? AR8216_PORT_STATUS_DUPLEX : 0;
+       t |= cfg->rxpause ? AR8216_PORT_STATUS_RXFLOW : 0;
+       t |= cfg->txpause ? AR8216_PORT_STATUS_TXFLOW : 0;
+       switch (cfg->speed) {
+       case AR8327_PORT_SPEED_10:
+               t |= AR8216_PORT_SPEED_10M;
+               break;
+       case AR8327_PORT_SPEED_100:
+               t |= AR8216_PORT_SPEED_100M;
+               break;
+       case AR8327_PORT_SPEED_1000:
+               t |= AR8216_PORT_SPEED_1000M;
+               break;
+       }
+
+       priv->write(priv, AR8327_REG_PORT_STATUS(AR8216_PORT_CPU), t);
+}
+
+static void
+ar8327_init_port(struct ar8216_priv *priv, int port)
+{
+       u32 t;
+
+       if (port == AR8216_PORT_CPU) {
+               ar8327_init_cpuport(priv);
+       } else {
+               t = AR8216_PORT_STATUS_LINK_AUTO;
+               priv->write(priv, AR8327_REG_PORT_STATUS(port), t);
+       }
+
+       priv->write(priv, AR8327_REG_PORT_HEADER(port), 0);
+
+       priv->write(priv, AR8327_REG_PORT_VLAN0(port), 0);
+
+       t = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH << AR8327_PORT_VLAN1_OUT_MODE_S;
+       priv->write(priv, AR8327_REG_PORT_VLAN1(port), t);
+
+       t = AR8327_PORT_LOOKUP_LEARN;
+       t |= AR8216_PORT_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
+       priv->write(priv, AR8327_REG_PORT_LOOKUP(port), t);
+}
+
+static u32
+ar8327_read_port_status(struct ar8216_priv *priv, int port)
+{
+       return priv->read(priv, AR8327_REG_PORT_STATUS(port));
+}
+
+static int
+ar8327_atu_flush(struct ar8216_priv *priv)
+{
+       int ret;
+
+       ret = ar8216_wait_bit(priv, AR8327_REG_ATU_FUNC,
+                             AR8327_ATU_FUNC_BUSY, 0);
+       if (!ret)
+               priv->write(priv, AR8327_REG_ATU_FUNC,
+                           AR8327_ATU_FUNC_OP_FLUSH);
+
+       return ret;
+}
+
+static void
+ar8327_vtu_op(struct ar8216_priv *priv, u32 op, u32 val)
+{
+       if (ar8216_wait_bit(priv, AR8327_REG_VTU_FUNC1,
+                           AR8327_VTU_FUNC1_BUSY, 0))
+               return;
+
+       if ((op & AR8327_VTU_FUNC1_OP) == AR8327_VTU_FUNC1_OP_LOAD)
+               priv->write(priv, AR8327_REG_VTU_FUNC0, val);
+
+       op |= AR8327_VTU_FUNC1_BUSY;
+       priv->write(priv, AR8327_REG_VTU_FUNC1, op);
+}
+
+static void
+ar8327_vtu_flush(struct ar8216_priv *priv)
+{
+       ar8327_vtu_op(priv, AR8327_VTU_FUNC1_OP_FLUSH, 0);
+}
+
+static void
+ar8327_vtu_load_vlan(struct ar8216_priv *priv, u32 vid, u32 port_mask)
+{
+       u32 op;
+       u32 val;
+       int i;
+
+       op = AR8327_VTU_FUNC1_OP_LOAD | (vid << AR8327_VTU_FUNC1_VID_S);
+       val = AR8327_VTU_FUNC0_VALID | AR8327_VTU_FUNC0_IVL;
+       for (i = 0; i < AR8327_NUM_PORTS; i++) {
+               u32 mode;
+
+               if ((port_mask & BIT(i)) == 0)
+                       mode = AR8327_VTU_FUNC0_EG_MODE_NOT;
+               else if (priv->vlan == 0)
+                       mode = AR8327_VTU_FUNC0_EG_MODE_KEEP;
+               else if (priv->vlan_tagged & BIT(i))
+                       mode = AR8327_VTU_FUNC0_EG_MODE_TAG;
+               else
+                       mode = AR8327_VTU_FUNC0_EG_MODE_UNTAG;
+
+               val |= mode << AR8327_VTU_FUNC0_EG_MODE_S(i);
+       }
+       ar8327_vtu_op(priv, op, val);
+}
+
+static void
+ar8327_setup_port(struct ar8216_priv *priv, int port, u32 egress, u32 ingress,
+                 u32 members, u32 pvid)
+{
+       u32 t;
+       u32 mode;
+
+       t = pvid << AR8327_PORT_VLAN0_DEF_SVID_S;
+       t |= pvid << AR8327_PORT_VLAN0_DEF_CVID_S;
+       priv->write(priv, AR8327_REG_PORT_VLAN0(port), t);
+
+       mode = AR8327_PORT_VLAN1_OUT_MODE_UNMOD;
+       switch (egress) {
+       case AR8216_OUT_KEEP:
+               mode = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH;
+               break;
+       case AR8216_OUT_STRIP_VLAN:
+               mode = AR8327_PORT_VLAN1_OUT_MODE_UNTAG;
+               break;
+       case AR8216_OUT_ADD_VLAN:
+               mode = AR8327_PORT_VLAN1_OUT_MODE_TAG;
+               break;
+       }
+
+       t = AR8327_PORT_VLAN1_PORT_VLAN_PROP;
+       t |= mode << AR8327_PORT_VLAN1_OUT_MODE_S;
+       priv->write(priv, AR8327_REG_PORT_VLAN1(port), t);
+
+       t = members;
+       t |= AR8327_PORT_LOOKUP_LEARN;
+       t |= ingress << AR8327_PORT_LOOKUP_IN_MODE_S;
+       t |= AR8216_PORT_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
+       priv->write(priv, AR8327_REG_PORT_LOOKUP(port), t);
+}
+
+static const struct ar8xxx_chip ar8327_chip = {
+       .caps = AR8XXX_CAP_GIGE,
+       .hw_init = ar8327_hw_init,
+       .init_globals = ar8327_init_globals,
+       .init_port = ar8327_init_port,
+       .setup_port = ar8327_setup_port,
+       .read_port_status = ar8327_read_port_status,
+       .atu_flush = ar8327_atu_flush,
+       .vtu_flush = ar8327_vtu_flush,
+       .vtu_load_vlan = ar8327_vtu_load_vlan,
+};
+
 static int
 ar8216_sw_set_vlan(struct switch_dev *dev, const struct switch_attr *attr,
                   struct switch_val *val)
@@ -910,6 +1221,11 @@ ar8216_id_chip(struct ar8216_priv *priv)
                priv->chip_type = AR8316;
                priv->chip = &ar8316_chip;
                break;
+       case 0x1202:
+               priv->chip_type = AR8327;
+               priv->mii_lo_first = true;
+               priv->chip = &ar8327_chip;
+               break;
        default:
                printk(KERN_DEBUG
                        "ar8216: Unknown Atheros device [ver=%d, rev=%d, phy_id=%04x%04x]\n",
@@ -1012,6 +1328,10 @@ ar8216_config_init(struct phy_device *pdev)
                swdev->name = "Atheros AR8236";
                swdev->vlans = AR8216_NUM_VLANS;
                swdev->ports = AR8216_NUM_PORTS;
+       } else if (priv->chip_type == AR8327) {
+               swdev->name = "Atheros AR8327";
+               swdev->vlans = AR8X16_MAX_VLANS;
+               swdev->ports = AR8327_NUM_PORTS;
        } else {
                swdev->name = "Atheros AR8216";
                swdev->vlans = AR8216_NUM_VLANS;
index 886730c619c0a11e626953f0d23c15bd835cc682..49a6296651de8bc546aec7e961d7055a6221a3c6 100644 (file)
 #define   AR8236_PORT_VLAN2_VLAN_MODE  BITS(30, 2)
 #define   AR8236_PORT_VLAN2_VLAN_MODE_S        30
 
+#define AR8327_NUM_PORTS       7
+#define AR8327_NUM_PHYS                5
+#define AR8327_PORTS_ALL       0x7f
+
+#define AR8327_REG_MASK                                0x000
+
+#define AR8327_REG_PAD0_MODE                   0x004
+#define AR8327_REG_PAD5_MODE                   0x008
+#define AR8327_REG_PAD6_MODE                   0x00c
+#define   AR8327_PAD_MAC_MII_RXCLK_SEL         BIT(0)
+#define   AR8327_PAD_MAC_MII_TXCLK_SEL         BIT(1)
+#define   AR8327_PAD_MAC_MII_EN                        BIT(2)
+#define   AR8327_PAD_MAC_GMII_RXCLK_SEL                BIT(4)
+#define   AR8327_PAD_MAC_GMII_TXCLK_SEL                BIT(5)
+#define   AR8327_PAD_MAC_GMII_EN               BIT(6)
+#define   AR8327_PAD_SGMII_EN                  BIT(7)
+#define   AR8327_PAD_PHY_MII_RXCLK_SEL         BIT(8)
+#define   AR8327_PAD_PHY_MII_TXCLK_SEL         BIT(9)
+#define   AR8327_PAD_PHY_MII_EN                        BIT(10)
+#define   AR8327_PAD_PHY_GMII_PIPE_RXCLK_SEL   BIT(11)
+#define   AR8327_PAD_PHY_GMII_RXCLK_SEL                BIT(12)
+#define   AR8327_PAD_PHY_GMII_TXCLK_SEL                BIT(13)
+#define   AR8327_PAD_PHY_GMII_EN               BIT(14)
+#define   AR8327_PAD_PHYX_GMII_EN              BIT(16)
+#define   AR8327_PAD_PHYX_RGMII_EN             BIT(17)
+#define   AR8327_PAD_PHYX_MII_EN               BIT(18)
+#define   AR8327_PAD_RGMII_RXCLK_DELAY_SEL     BITS(20, 2)
+#define   AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S   20
+#define   AR8327_PAD_RGMII_TXCLK_DELAY_SEL     BITS(22, 2)
+#define   AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S   22
+#define   AR8327_PAD_RGMII_RXCLK_DELAY_EN      BIT(24)
+#define   AR8327_PAD_RGMII_TXCLK_DELAY_EN      BIT(25)
+#define   AR8327_PAD_RGMII_EN                  BIT(26)
+
+#define AR8327_REG_POWER_ON_STRIP              0x010
+
+#define AR8327_REG_INT_STATUS0                 0x020
+#define   AR8327_INT0_VT_DONE                  BIT(20)
+
+#define AR8327_REG_INT_STATUS1                 0x024
+#define AR8327_REG_INT_MASK0                   0x028
+#define AR8327_REG_INT_MASK1                   0x02c
+#define AR8327_REG_SERVICE_TAG                 0x048
+#define AR8327_REG_LED_CTRL0                   0x050
+#define AR8327_REG_LED_CTRL1                   0x054
+#define AR8327_REG_LED_CTRL2                   0x058
+#define AR8327_REG_LED_CTRL3                   0x05c
+#define AR8327_REG_MAC_ADDR0                   0x060
+#define AR8327_REG_MAC_ADDR1                   0x064
+
+#define AR8327_REG_MAX_FRAME_SIZE              0x078
+#define   AR8327_MAX_FRAME_SIZE_MTU            BITS(0, 14)
+
+#define AR8327_REG_PORT_STATUS(_i)             (0x07c + (_i) * 4)
+
+#define AR8327_REG_HEADER_CTRL                 0x098
+#define AR8327_REG_PORT_HEADER(_i)             (0x09c + (_i) * 4)
+
+#define AR8327_REG_PORT_VLAN0(_i)              (0x420 + (_i) * 0x8)
+#define   AR8327_PORT_VLAN0_DEF_SVID           BITS(0, 12)
+#define   AR8327_PORT_VLAN0_DEF_SVID_S         0
+#define   AR8327_PORT_VLAN0_DEF_CVID           BITS(16, 12)
+#define   AR8327_PORT_VLAN0_DEF_CVID_S         16
+
+#define AR8327_REG_PORT_VLAN1(_i)              (0x424 + (_i) * 0x8)
+#define   AR8327_PORT_VLAN1_PORT_VLAN_PROP     BIT(6)
+#define   AR8327_PORT_VLAN1_OUT_MODE           BITS(12, 2)
+#define   AR8327_PORT_VLAN1_OUT_MODE_S         12
+#define   AR8327_PORT_VLAN1_OUT_MODE_UNMOD     0
+#define   AR8327_PORT_VLAN1_OUT_MODE_UNTAG     1
+#define   AR8327_PORT_VLAN1_OUT_MODE_TAG       2
+#define   AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH   3
+
+#define AR8327_REG_ATU_DATA0                   0x600
+#define AR8327_REG_ATU_DATA1                   0x604
+#define AR8327_REG_ATU_DATA2                   0x608
+
+#define AR8327_REG_ATU_FUNC                    0x60c
+#define   AR8327_ATU_FUNC_OP                   BITS(0, 4)
+#define   AR8327_ATU_FUNC_OP_NOOP              0x0
+#define   AR8327_ATU_FUNC_OP_FLUSH             0x1
+#define   AR8327_ATU_FUNC_OP_LOAD              0x2
+#define   AR8327_ATU_FUNC_OP_PURGE             0x3
+#define   AR8327_ATU_FUNC_OP_FLUSH_LOCKED      0x4
+#define   AR8327_ATU_FUNC_OP_FLUSH_UNICAST     0x5
+#define   AR8327_ATU_FUNC_OP_GET_NEXT          0x6
+#define   AR8327_ATU_FUNC_OP_SEARCH_MAC                0x7
+#define   AR8327_ATU_FUNC_OP_CHANGE_TRUNK      0x8
+#define   AR8327_ATU_FUNC_BUSY                 BIT(31)
+
+#define AR8327_REG_VTU_FUNC0                   0x0610
+#define   AR8327_VTU_FUNC0_EG_MODE             BITS(4, 14)
+#define   AR8327_VTU_FUNC0_EG_MODE_S(_i)       (4 + (_i) * 2)
+#define   AR8327_VTU_FUNC0_EG_MODE_KEEP                0
+#define   AR8327_VTU_FUNC0_EG_MODE_UNTAG       1
+#define   AR8327_VTU_FUNC0_EG_MODE_TAG         2
+#define   AR8327_VTU_FUNC0_EG_MODE_NOT         3
+#define   AR8327_VTU_FUNC0_IVL                 BIT(19)
+#define   AR8327_VTU_FUNC0_VALID               BIT(20)
+
+#define AR8327_REG_VTU_FUNC1                   0x0614
+#define   AR8327_VTU_FUNC1_OP                  BITS(0, 3)
+#define   AR8327_VTU_FUNC1_OP_NOOP             0
+#define   AR8327_VTU_FUNC1_OP_FLUSH            1
+#define   AR8327_VTU_FUNC1_OP_LOAD             2
+#define   AR8327_VTU_FUNC1_OP_PURGE            3
+#define   AR8327_VTU_FUNC1_OP_REMOVE_PORT      4
+#define   AR8327_VTU_FUNC1_OP_GET_NEXT         5
+#define   AR8327_VTU_FUNC1_OP_GET_ONE          6
+#define   AR8327_VTU_FUNC1_FULL                        BIT(4)
+#define   AR8327_VTU_FUNC1_PORT                        BIT(8, 4)
+#define   AR8327_VTU_FUNC1_PORT_S              8
+#define   AR8327_VTU_FUNC1_VID                 BIT(16, 12)
+#define   AR8327_VTU_FUNC1_VID_S               16
+#define   AR8327_VTU_FUNC1_BUSY                        BIT(31)
+
+#define AR8327_REG_FWD_CTRL0                   0x620
+#define   AR8327_FWD_CTRL0_CPU_PORT_EN         BIT(10)
+#define   AR8327_FWD_CTRL0_MIRROR_PORT         BITS(4, 4)
+#define   AR8327_FWD_CTRL0_MIRROR_PORT_S       4
+
+#define AR8327_REG_FWD_CTRL1                   0x624
+#define   AR8327_FWD_CTRL1_UC_FLOOD            BITS(0, 7)
+#define   AR8327_FWD_CTRL1_UC_FLOOD_S          0
+#define   AR8327_FWD_CTRL1_MC_FLOOD            BITS(8, 7)
+#define   AR8327_FWD_CTRL1_MC_FLOOD_S          8
+#define   AR8327_FWD_CTRL1_BC_FLOOD            BITS(16, 7)
+#define   AR8327_FWD_CTRL1_BC_FLOOD_S          16
+#define   AR8327_FWD_CTRL1_IGMP                        BITS(24, 7)
+#define   AR8327_FWD_CTRL1_IGMP_S              24
+
+#define AR8327_REG_PORT_LOOKUP(_i)             (0x660 + (_i) * 0xc)
+#define   AR8327_PORT_LOOKUP_MEMBER            BITS(0, 7)
+#define   AR8327_PORT_LOOKUP_IN_MODE           BITS(8, 2)
+#define   AR8327_PORT_LOOKUP_IN_MODE_S         8
+#define   AR8327_PORT_LOOKUP_STATE             BITS(16, 3)
+#define   AR8327_PORT_LOOKUP_STATE_S           16
+#define   AR8327_PORT_LOOKUP_LEARN             BIT(20)
+
+#define AR8327_REG_PORT_PRIO(_i)               (0x664 + (_i) * 0xc)
+
 /* port speed */
 enum {
         AR8216_PORT_SPEED_10M = 0,
@@ -199,6 +340,7 @@ enum {
   AR8216 = 8216,
   AR8236 = 8236,
   AR8316 = 8316,
+  AR8327 = 8327,
 };
 
 #endif
diff --git a/target/linux/generic/files/include/linux/ar8216_platform.h b/target/linux/generic/files/include/linux/ar8216_platform.h
new file mode 100644 (file)
index 0000000..1ecb6e5
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * AR8216 switch driver platform data
+ *
+ * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef AR8216_PLATFORM_H
+#define AR8216_PLATFORM_H
+
+enum ar8327_pad_mode {
+       AR8327_PAD_NC = 0,
+       AR8327_PAD_MAC2MAC_MII,
+       AR8327_PAD_MAC2MAC_GMII,
+       AR8327_PAD_MAC_SGMII,
+       AR8327_PAD_MAC2PHY_MII,
+       AR8327_PAD_MAC2PHY_GMII,
+       AR8327_PAD_MAC_RGMII,
+       AR8327_PAD_PHY_GMII,
+       AR8327_PAD_PHY_RGMII,
+       AR8327_PAD_PHY_MII,
+};
+
+enum ar8327_clk_delay_sel {
+       AR8327_CLK_DELAY_SEL0 = 0,
+       AR8327_CLK_DELAY_SEL1,
+       AR8327_CLK_DELAY_SEL2,
+       AR8327_CLK_DELAY_SEL3,
+};
+
+struct ar8327_pad_cfg {
+       enum ar8327_pad_mode mode;
+       bool rxclk_sel;
+       bool txclk_sel;
+       bool pipe_rxclk_sel;
+       bool txclk_delay_en;
+       bool rxclk_delay_en;
+       enum ar8327_clk_delay_sel txclk_delay_sel;
+       enum ar8327_clk_delay_sel rxclk_delay_sel;
+};
+
+enum ar8327_port_speed {
+       AR8327_PORT_SPEED_10 = 0,
+       AR8327_PORT_SPEED_100,
+       AR8327_PORT_SPEED_1000,
+};
+
+struct ar8327_port_cfg {
+       int force_link:1;
+       enum ar8327_port_speed speed;
+       int txpause:1;
+       int rxpause:1;
+       int duplex:1;
+};
+
+struct ar8327_platform_data {
+       struct ar8327_pad_cfg *pad0_cfg;
+       struct ar8327_pad_cfg *pad5_cfg;
+       struct ar8327_pad_cfg *pad6_cfg;
+       struct ar8327_port_cfg cpuport_cfg;
+};
+
+#endif /* AR8216_PLATFORM_H */
\ No newline at end of file