generic: ar8216: add support for ar724x/ar933x builtin switch
authorChuanhong Guo <gch981213@gmail.com>
Thu, 10 Jan 2019 15:53:23 +0000 (23:53 +0800)
committerPetr Štetiar <ynezz@true.cz>
Sun, 24 Mar 2019 00:44:26 +0000 (01:44 +0100)
This builtin switch is a bugless ar8216 with different mib counters
and gigabit cpu port.
Atheros uses the same device ID and it's impossible to distinguish
the standalone one and the builtin one. So we add support to mdio
device probe only.

This switch doesn't have buggy vlan tag so it's not needed to enable
atheros header. This commit changed ar8216_setup_port so that it can
be reused for this switch.

Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
target/linux/generic/files/drivers/net/phy/ar8216.c
target/linux/generic/files/drivers/net/phy/ar8216.h

index f3cafc79a572ffd9b88c2724c7547221b35ace7a..3cee84f0df26ee8cf510ec690792cdf12f9889ed 100644 (file)
@@ -653,7 +653,8 @@ ar8216_read_port_status(struct ar8xxx_priv *priv, int port)
 }
 
 static void
-ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 members)
+__ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 members,
+                   bool ath_hdr_en)
 {
        u32 header;
        u32 egress, ingress;
@@ -672,10 +673,7 @@ ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 members)
                ingress = AR8216_IN_PORT_ONLY;
        }
 
-       if (chip_is_ar8216(priv) && priv->vlan && port == AR8216_PORT_CPU)
-               header = AR8216_PORT_CTRL_HEADER;
-       else
-               header = 0;
+       header = ath_hdr_en ? AR8216_PORT_CTRL_HEADER : 0;
 
        ar8xxx_rmw(priv, AR8216_REG_PORT_CTRL(port),
                   AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE |
@@ -693,6 +691,14 @@ ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 members)
                   (pvid << AR8216_PORT_VLAN_DEFAULT_ID_S));
 }
 
+static void
+ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 members)
+{
+       return __ar8216_setup_port(priv, port, members,
+                                  chip_is_ar8216(priv) && priv->vlan &&
+                                  port == AR8216_PORT_CPU);
+}
+
 static int
 ar8216_hw_init(struct ar8xxx_priv *priv)
 {
@@ -885,9 +891,12 @@ ar8229_hw_init(struct ar8xxx_priv *priv)
                return -EINVAL;
        }
 
-       if (priv->port4_phy)
+       if (priv->port4_phy) {
                ar8xxx_write(priv, AR8229_REG_OPER_MODE1,
                             AR8229_REG_OPER_MODE1_PHY4_MII_EN);
+               /* disable port5 to prevent mii conflict */
+               ar8xxx_write(priv, AR8216_REG_PORT_STATUS(5), 0);
+       }
 
        ar8xxx_phy_init(priv);
 
@@ -940,6 +949,65 @@ ar8229_init_port(struct ar8xxx_priv *priv, int port)
        __ar8216_init_port(priv, port, true, true);
 }
 
+
+static int
+ar7240sw_hw_init(struct ar8xxx_priv *priv)
+{
+       if (priv->initialized)
+               return 0;
+
+       ar8xxx_write(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET);
+       ar8xxx_reg_wait(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET, 0, 1000);
+
+       priv->port4_phy = 1;
+       /* disable port5 to prevent mii conflict */
+       ar8xxx_write(priv, AR8216_REG_PORT_STATUS(5), 0);
+
+       ar8xxx_phy_init(priv);
+
+       priv->initialized = true;
+       return 0;
+}
+
+static void
+ar7240sw_init_globals(struct ar8xxx_priv *priv)
+{
+
+       /* Enable CPU port, and disable mirror port */
+       ar8xxx_write(priv, AR8216_REG_GLOBAL_CPUPORT,
+                    AR8216_GLOBAL_CPUPORT_EN |
+                    (15 << AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S));
+
+       /* Setup TAG priority mapping */
+       ar8xxx_write(priv, AR8216_REG_TAG_PRIORITY, 0xfa50);
+
+       /* Enable ARP frame acknowledge, aging, MAC replacing */
+       ar8xxx_write(priv, AR8216_REG_ATU_CTRL,
+               AR8216_ATU_CTRL_RESERVED |
+               0x2b /* 5 min age time */ |
+               AR8216_ATU_CTRL_AGE_EN |
+               AR8216_ATU_CTRL_ARP_EN |
+               AR8216_ATU_CTRL_LEARN_CHANGE);
+
+       /* Enable Broadcast frames transmitted to the CPU */
+       ar8xxx_reg_set(priv, AR8216_REG_FLOOD_MASK,
+                      AR8236_FM_CPU_BROADCAST_EN);
+
+       /* setup MTU */
+       ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CTRL,
+                  AR8216_GCTRL_MTU,
+                  AR8216_GCTRL_MTU);
+
+       /* setup Service TAG */
+       ar8xxx_rmw(priv, AR8216_REG_SERVICE_TAG, AR8216_SERVICE_TAG_M, 0);
+}
+
+static void
+ar7240sw_setup_port(struct ar8xxx_priv *priv, int port, u32 members)
+{
+       return __ar8216_setup_port(priv, port, members, false);
+}
+
 static void
 ar8236_setup_port(struct ar8xxx_priv *priv, int port, u32 members)
 {
@@ -1871,6 +1939,38 @@ static const struct switch_dev_ops ar8xxx_sw_ops = {
 #endif
 };
 
+static const struct ar8xxx_chip ar7240sw_chip = {
+       .caps = AR8XXX_CAP_MIB_COUNTERS,
+
+       .reg_port_stats_start = 0x20000,
+       .reg_port_stats_length = 0x100,
+       .reg_arl_ctrl = AR8216_REG_ATU_CTRL,
+
+       .name = "Atheros AR724X/AR933X built-in",
+       .ports = AR7240SW_NUM_PORTS,
+       .vlans = AR8216_NUM_VLANS,
+       .swops = &ar8xxx_sw_ops,
+
+       .hw_init = ar7240sw_hw_init,
+       .init_globals = ar7240sw_init_globals,
+       .init_port = ar8229_init_port,
+       .phy_read = ar8216_phy_read,
+       .phy_write = ar8216_phy_write,
+       .setup_port = ar7240sw_setup_port,
+       .read_port_status = ar8216_read_port_status,
+       .atu_flush = ar8216_atu_flush,
+       .atu_flush_port = ar8216_atu_flush_port,
+       .vtu_flush = ar8216_vtu_flush,
+       .vtu_load_vlan = ar8216_vtu_load_vlan,
+       .set_mirror_regs = ar8216_set_mirror_regs,
+       .get_arl_entry = ar8216_get_arl_entry,
+       .sw_hw_apply = ar8xxx_sw_hw_apply,
+
+       .num_mibs = ARRAY_SIZE(ar8236_mibs),
+       .mib_decs = ar8236_mibs,
+       .mib_func = AR8216_REG_MIB_FUNC
+};
+
 static const struct ar8xxx_chip ar8216_chip = {
        .caps = AR8XXX_CAP_MIB_COUNTERS,
 
@@ -2516,6 +2616,9 @@ static struct phy_driver ar8xxx_phy_driver[] = {
 
 static const struct of_device_id ar8xxx_mdiodev_of_match[] = {
        {
+               .compatible = "qca,ar7240sw",
+               .data = &ar7240sw_chip,
+       }, {
                .compatible = "qca,ar8229",
                .data = &ar8229_chip,
        }, {
index 975ba23517b2ba6494afeeceb82a373632a1c961..0bdd3e9dd8225f3be10d82121cc4424b53e979a7 100644 (file)
@@ -26,6 +26,7 @@
 #define AR8216_PORT_CPU        0
 #define AR8216_NUM_PORTS       6
 #define AR8216_NUM_VLANS       16
+#define AR7240SW_NUM_PORTS     5
 #define AR8316_NUM_VLANS       4096
 
 /* size of the vlan table */
 #define   AR8216_ATU_CTRL_AGE_TIME_S   0
 #define   AR8236_ATU_CTRL_RES          BIT(20)
 #define   AR8216_ATU_CTRL_LEARN_CHANGE BIT(18)
+#define   AR8216_ATU_CTRL_RESERVED     BIT(19)
+#define   AR8216_ATU_CTRL_ARP_EN       BIT(20)
 
 #define AR8216_REG_TAG_PRIORITY        0x0070