summaryrefslogtreecommitdiff
path: root/target/linux/generic/files/drivers
diff options
context:
space:
mode:
authorjuhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73>2011-11-12 14:09:52 +0000
committerjuhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73>2011-11-12 14:09:52 +0000
commit9394e4a065ca6036acc0ec73edf88226c3efe135 (patch)
treeca1ddb47632d4dbed2adab06e3db07a80ef1f8fa /target/linux/generic/files/drivers
parent63898b07ccfad95327a69f244aced0b6940c3831 (diff)
kernel: ar8216: add support for the AR8236 switch
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@28993 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/generic/files/drivers')
-rw-r--r--target/linux/generic/files/drivers/net/phy/ar8216.c72
-rw-r--r--target/linux/generic/files/drivers/net/phy/ar8216.h19
2 files changed, 87 insertions, 4 deletions
diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c
index cdbf1668b6..c79a92a0a1 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.c
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.c
@@ -144,6 +144,8 @@ ar8216_id_chip(struct ar8216_priv *priv)
switch (id) {
case 0x0101:
return AR8216;
+ case 0x0301:
+ return AR8236;
case 0x1000:
case 0x1001:
return AR8316;
@@ -513,6 +515,29 @@ ar8216_setup_port(struct ar8216_priv *priv, int port, u32 egress, u32 ingress,
(pvid << AR8216_PORT_VLAN_DEFAULT_ID_S));
}
+static void
+ar8236_setup_port(struct ar8216_priv *priv, int port, u32 egress, u32 ingress,
+ u32 members, u32 pvid)
+{
+ ar8216_rmw(priv, AR8216_REG_PORT_CTRL(port),
+ AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE |
+ AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE |
+ AR8216_PORT_CTRL_HEADER | AR8216_PORT_CTRL_LEARN_LOCK,
+ AR8216_PORT_CTRL_LEARN |
+ (egress << AR8216_PORT_CTRL_VLAN_MODE_S) |
+ (AR8216_PORT_STATE_FORWARD << AR8216_PORT_CTRL_STATE_S));
+
+ ar8216_rmw(priv, AR8236_REG_PORT_VLAN(port),
+ AR8236_PORT_VLAN_DEFAULT_ID,
+ (pvid << AR8236_PORT_VLAN_DEFAULT_ID_S));
+
+ ar8216_rmw(priv, AR8236_REG_PORT_VLAN2(port),
+ AR8236_PORT_VLAN2_VLAN_MODE |
+ AR8236_PORT_VLAN2_MEMBER,
+ (ingress << AR8236_PORT_VLAN2_VLAN_MODE_S) |
+ (members << AR8236_PORT_VLAN2_MEMBER_S));
+}
+
static int
ar8216_hw_apply(struct switch_dev *dev)
{
@@ -579,13 +604,41 @@ ar8216_hw_apply(struct switch_dev *dev)
ingress = AR8216_IN_PORT_ONLY;
}
- ar8216_setup_port(priv, i, egress, ingress, portmask[i], pvid);
+ if (priv->chip == AR8236)
+ ar8236_setup_port(priv, i, egress, ingress, portmask[i],
+ pvid);
+ else
+ ar8216_setup_port(priv, i, egress, ingress, portmask[i],
+ pvid);
}
mutex_unlock(&priv->reg_mutex);
return 0;
}
static int
+ar8236_hw_init(struct ar8216_priv *priv) {
+ static int initialized;
+ int i;
+ struct mii_bus *bus;
+
+ if (initialized)
+ return 0;
+
+ /* Initialize the PHYs */
+ bus = priv->phy->bus;
+ for (i = 0; i < 5; i++) {
+ bus->write(bus, i, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+ bus->write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
+ }
+ msleep(1000);
+
+ initialized = true;
+ return 0;
+}
+
+static int
ar8316_hw_init(struct ar8216_priv *priv) {
int i;
u32 val, newval;
@@ -692,7 +745,8 @@ ar8216_reset_switch(struct switch_dev *dev)
if (priv->chip == AR8216) {
ar8216_rmw(priv, AR8216_REG_GLOBAL_CTRL,
AR8216_GCTRL_MTU, 1518 + 8 + 2);
- } else if (priv->chip == AR8316) {
+ } else if (priv->chip == AR8316 ||
+ priv->chip == AR8236) {
/* enable jumbo frames */
ar8216_rmw(priv, AR8216_REG_GLOBAL_CTRL,
AR8316_GCTRL_MTU, 9018 + 8 + 2);
@@ -806,6 +860,10 @@ ar8216_config_init(struct phy_device *pdev)
/* port 5 connected to the other mac, therefore unusable */
swdev->ports = (AR8216_NUM_PORTS - 1);
}
+ } else if (priv->chip == AR8236) {
+ swdev->name = "Atheros AR8236";
+ swdev->vlans = AR8216_NUM_VLANS;
+ swdev->ports = AR8216_NUM_PORTS;
} else {
swdev->name = "Atheros AR8216";
swdev->vlans = AR8216_NUM_VLANS;
@@ -824,6 +882,14 @@ ar8216_config_init(struct phy_device *pdev)
}
}
+ if (priv->chip == AR8236) {
+ ret = ar8236_hw_init(priv);
+ if (ret) {
+ kfree(priv);
+ goto done;
+ }
+ }
+
ret = ar8216_reset_switch(&priv->dev);
if (ret) {
kfree(priv);
@@ -918,7 +984,7 @@ ar8216_remove(struct phy_device *pdev)
static struct phy_driver ar8216_driver = {
.phy_id = 0x004d0000,
- .name = "Atheros AR8216/AR8316",
+ .name = "Atheros AR8216/AR8316/AR8326",
.phy_id_mask = 0xffff0000,
.features = PHY_BASIC_FEATURES,
.probe = ar8216_probe,
diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.h b/target/linux/generic/files/drivers/net/phy/ar8216.h
index 5a8fa3c003..886730c619 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.h
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.h
@@ -41,6 +41,7 @@
#define AR8216_REG_GLOBAL_CTRL 0x0030
#define AR8216_GCTRL_MTU BITS(0, 11)
+#define AR8236_GCTRL_MTU BITS(0, 14)
#define AR8316_GCTRL_MTU BITS(0, 14)
#define AR8216_REG_VTU 0x0040
@@ -62,6 +63,7 @@
#define AR8216_REG_VTU_DATA 0x0044
#define AR8216_VTUDATA_MEMBER BITS(0, 10)
+#define AR8236_VTUDATA_MEMBER BITS(0, 7)
#define AR8216_VTUDATA_VALID BIT(11)
#define AR8216_REG_ATU 0x0050
@@ -145,6 +147,20 @@
#define AR8216_REG_PORT_RATE(_i) (AR8216_PORT_OFFSET(_i) + 0x000c)
#define AR8216_REG_PORT_PRIO(_i) (AR8216_PORT_OFFSET(_i) + 0x0010)
+
+#define AR8236_REG_PORT_VLAN(_i) (AR8216_PORT_OFFSET((_i)) + 0x0008)
+#define AR8236_PORT_VLAN_DEFAULT_ID BITS(16, 12)
+#define AR8236_PORT_VLAN_DEFAULT_ID_S 16
+#define AR8236_PORT_VLAN_PRIORITY BITS(29, 3)
+#define AR8236_PORT_VLAN_PRIORITY_S 28
+
+#define AR8236_REG_PORT_VLAN2(_i) (AR8216_PORT_OFFSET((_i)) + 0x000c)
+#define AR8236_PORT_VLAN2_MEMBER BITS(16, 7)
+#define AR8236_PORT_VLAN2_MEMBER_S 16
+#define AR8236_PORT_VLAN2_TX_PRIO BIT(23)
+#define AR8236_PORT_VLAN2_VLAN_MODE BITS(30, 2)
+#define AR8236_PORT_VLAN2_VLAN_MODE_S 30
+
/* port speed */
enum {
AR8216_PORT_SPEED_10M = 0,
@@ -181,7 +197,8 @@ enum {
enum {
UNKNOWN = 0,
AR8216 = 8216,
- AR8316 = 8316
+ AR8236 = 8236,
+ AR8316 = 8316,
};
#endif