return t;
}
+static void
+ar8327_phy_rgmii_set(struct ar8xxx_priv *priv, struct phy_device *phydev)
+{
+ u16 phy_val = 0;
+ int phyaddr = phydev->mdio.addr;
+ struct device_node *np = phydev->mdio.dev.of_node;
+
+ if (!np)
+ return;
+
+ if (!of_property_read_bool(np, "qca,phy-rgmii-en")) {
+ pr_err("ar8327: qca,phy-rgmii-en is not specified\n");
+ return;
+ }
+ ar8xxx_phy_dbg_read(priv, phyaddr,
+ AR8327_PHY_MODE_SEL, &phy_val);
+ phy_val |= AR8327_PHY_MODE_SEL_RGMII;
+ ar8xxx_phy_dbg_write(priv, phyaddr,
+ AR8327_PHY_MODE_SEL, phy_val);
+
+ /* set rgmii tx clock delay if needed */
+ if (!of_property_read_bool(np, "qca,txclk-delay-en")) {
+ pr_err("ar8327: qca,txclk-delay-en is not specified\n");
+ return;
+ }
+ ar8xxx_phy_dbg_read(priv, phyaddr,
+ AR8327_PHY_SYS_CTRL, &phy_val);
+ phy_val |= AR8327_PHY_SYS_CTRL_RGMII_TX_DELAY;
+ ar8xxx_phy_dbg_write(priv, phyaddr,
+ AR8327_PHY_SYS_CTRL, phy_val);
+
+ /* set rgmii rx clock delay if needed */
+ if (!of_property_read_bool(np, "qca,rxclk-delay-en")) {
+ pr_err("ar8327: qca,rxclk-delay-en is not specified\n");
+ return;
+ }
+ ar8xxx_phy_dbg_read(priv, phyaddr,
+ AR8327_PHY_TEST_CTRL, &phy_val);
+ phy_val |= AR8327_PHY_TEST_CTRL_RGMII_RX_DELAY;
+ ar8xxx_phy_dbg_write(priv, phyaddr,
+ AR8327_PHY_TEST_CTRL, phy_val);
+}
+
static void
ar8327_phy_fixup(struct ar8xxx_priv *priv, int phy)
{
ar8xxx_write(priv, AR8327_REG_PAD0_MODE, t);
t = ar8327_get_pad_cfg(pdata->pad5_cfg);
- if (chip_is_ar8337(priv)) {
- /*
- * Workaround: RGMII RX delay setting needs to be
- * always specified for AR8337 to avoid port 5
- * RX hang on high traffic / flood conditions
- */
- t |= AR8327_PAD_RGMII_RXCLK_DELAY_EN;
- }
ar8xxx_write(priv, AR8327_REG_PAD5_MODE, t);
t = ar8327_get_pad_cfg(pdata->pad6_cfg);
ar8xxx_write(priv, AR8327_REG_PAD6_MODE, t);
if (!priv->chip_data)
return -ENOMEM;
- if (priv->phy->mdio.dev.of_node)
- ret = ar8327_hw_config_of(priv, priv->phy->mdio.dev.of_node);
+ if (priv->pdev->of_node)
+ ret = ar8327_hw_config_of(priv, priv->pdev->of_node);
else
ret = ar8327_hw_config_pdata(priv,
priv->phy->mdio.dev.platform_data);
/* Disable EEE on all phy's due to stability issues */
for (i = 0; i < AR8XXX_NUM_PHYS; i++)
data->eee[i] = false;
-
- if (chip_is_ar8337(priv)) {
- /* Update HOL registers with values suggested by QCA switch team */
- for (i = 0; i < AR8327_NUM_PORTS; i++) {
- if (i == AR8216_PORT_CPU || i == 5 || i == 6) {
- t = 0x3 << AR8327_PORT_HOL_CTRL0_EG_PRI0_BUF_S;
- t |= 0x4 << AR8327_PORT_HOL_CTRL0_EG_PRI1_BUF_S;
- t |= 0x4 << AR8327_PORT_HOL_CTRL0_EG_PRI2_BUF_S;
- t |= 0x4 << AR8327_PORT_HOL_CTRL0_EG_PRI3_BUF_S;
- t |= 0x6 << AR8327_PORT_HOL_CTRL0_EG_PRI4_BUF_S;
- t |= 0x8 << AR8327_PORT_HOL_CTRL0_EG_PRI5_BUF_S;
- t |= 0x1e << AR8327_PORT_HOL_CTRL0_EG_PORT_BUF_S;
- } else {
- t = 0x3 << AR8327_PORT_HOL_CTRL0_EG_PRI0_BUF_S;
- t |= 0x4 << AR8327_PORT_HOL_CTRL0_EG_PRI1_BUF_S;
- t |= 0x6 << AR8327_PORT_HOL_CTRL0_EG_PRI2_BUF_S;
- t |= 0x8 << AR8327_PORT_HOL_CTRL0_EG_PRI3_BUF_S;
- t |= 0x19 << AR8327_PORT_HOL_CTRL0_EG_PORT_BUF_S;
- }
- ar8xxx_write(priv, AR8327_REG_PORT_HOL_CTRL0(i), t);
-
- t = 0x6 << AR8327_PORT_HOL_CTRL1_ING_BUF_S;
- t |= AR8327_PORT_HOL_CTRL1_EG_PRI_BUF_EN;
- t |= AR8327_PORT_HOL_CTRL1_EG_PORT_BUF_EN;
- t |= AR8327_PORT_HOL_CTRL1_WRED_EN;
- ar8xxx_rmw(priv, AR8327_REG_PORT_HOL_CTRL1(i),
- AR8327_PORT_HOL_CTRL1_ING_BUF |
- AR8327_PORT_HOL_CTRL1_EG_PRI_BUF_EN |
- AR8327_PORT_HOL_CTRL1_EG_PORT_BUF_EN |
- AR8327_PORT_HOL_CTRL1_WRED_EN,
- t);
- }
- }
}
static void
t = pvid << AR8327_PORT_VLAN0_DEF_SVID_S;
t |= pvid << AR8327_PORT_VLAN0_DEF_CVID_S;
+ if (priv->vlan && priv->port_vlan_prio[port]) {
+ u32 prio = priv->port_vlan_prio[port];
+
+ t |= prio << AR8327_PORT_VLAN0_DEF_SPRI_S;
+ t |= prio << AR8327_PORT_VLAN0_DEF_CPRI_S;
+ }
ar8xxx_write(priv, AR8327_REG_PORT_VLAN0(port), t);
t = AR8327_PORT_VLAN1_PORT_VLAN_PROP;
t |= egress << AR8327_PORT_VLAN1_OUT_MODE_S;
+ if (priv->vlan && priv->port_vlan_prio[port])
+ t |= AR8327_PORT_VLAN1_VLAN_PRI_PROP;
+
ar8xxx_write(priv, AR8327_REG_PORT_VLAN1(port), t);
t = members;
{
int timeout = 20;
- while (ar8xxx_mii_read32(priv, r2, r1) & AR8327_ATU_FUNC_BUSY && --timeout)
- udelay(10);
+ while (ar8xxx_mii_read32(priv, r2, r1) & AR8327_ATU_FUNC_BUSY && --timeout) {
+ udelay(10);
+ cond_resched();
+ }
if (!timeout)
pr_err("ar8327: timeout waiting for atu to become ready\n");
struct mii_bus *bus = priv->mii_bus;
u16 r2, page;
u16 r1_data0, r1_data1, r1_data2, r1_func;
- u32 t, val0, val1, val2;
- int i;
+ u32 val0, val1, val2;
split_addr(AR8327_REG_ATU_DATA0, &r1_data0, &r2, &page);
r2 |= 0x10;
if (!*status)
break;
- i = 0;
- t = AR8327_ATU_PORT0;
- while (!(val1 & t) && ++i < AR8327_NUM_PORTS)
- t <<= 1;
-
- a->port = i;
+ a->portmap = (val1 & AR8327_ATU_PORTS) >> AR8327_ATU_PORTS_S;
a->mac[0] = (val0 & AR8327_ATU_ADDR0) >> AR8327_ATU_ADDR0_S;
a->mac[1] = (val0 & AR8327_ATU_ADDR1) >> AR8327_ATU_ADDR1_S;
a->mac[2] = (val0 & AR8327_ATU_ADDR2) >> AR8327_ATU_ADDR2_S;
return 0;
}
+static int
+ar8327_sw_set_port_vlan_prio(struct switch_dev *dev, const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev);
+ int port = val->port_vlan;
+
+ if (port >= dev->ports)
+ return -EINVAL;
+ if (port == 0 || port == 6)
+ return -EOPNOTSUPP;
+ if (val->value.i < 0 || val->value.i > 7)
+ return -EINVAL;
+
+ priv->port_vlan_prio[port] = val->value.i;
+
+ return 0;
+}
+
+static int
+ar8327_sw_get_port_vlan_prio(struct switch_dev *dev, const struct switch_attr *attr,
+ struct switch_val *val)
+{
+ struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev);
+ int port = val->port_vlan;
+
+ val->value.i = priv->port_vlan_prio[port];
+
+ return 0;
+}
+
static const struct switch_attr ar8327_sw_attr_globals[] = {
{
.type = SWITCH_TYPE_INT,
.set = ar8xxx_sw_set_mirror_source_port,
.get = ar8xxx_sw_get_mirror_source_port,
.max = AR8327_NUM_PORTS - 1
- },
+ },
{
.type = SWITCH_TYPE_INT,
.name = "arl_age_time",
.get = ar8327_sw_get_port_igmp_snooping,
.max = 1
},
+ {
+ .type = SWITCH_TYPE_INT,
+ .name = "vlan_prio",
+ .description = "Port VLAN default priority (VLAN PCP) (0-7)",
+ .set = ar8327_sw_set_port_vlan_prio,
+ .get = ar8327_sw_get_port_vlan_prio,
+ .max = 7,
+ },
};
static const struct switch_dev_ops ar8327_sw_ops = {
.atu_flush_port = ar8327_atu_flush_port,
.vtu_flush = ar8327_vtu_flush,
.vtu_load_vlan = ar8327_vtu_load_vlan,
+ .phy_fixup = ar8327_phy_fixup,
.set_mirror_regs = ar8327_set_mirror_regs,
.get_arl_entry = ar8327_get_arl_entry,
.sw_hw_apply = ar8327_sw_hw_apply,
.set_mirror_regs = ar8327_set_mirror_regs,
.get_arl_entry = ar8327_get_arl_entry,
.sw_hw_apply = ar8327_sw_hw_apply,
+ .phy_rgmii_set = ar8327_phy_rgmii_set,
.num_mibs = ARRAY_SIZE(ar8236_mibs),
.mib_decs = ar8236_mibs,