[qca-ssdk]: Add ess reset to ssdk
Add ess reset to ssdk.
Change-Id: I777ce470b10f0094e9abb1d640b8519768b049ac
Signed-off-by: xiaofeis <xiaofeis@codeaurora.org>
diff --git a/include/init/ssdk_plat.h b/include/init/ssdk_plat.h
index 825d032..a3c25b7 100755
--- a/include/init/ssdk_plat.h
+++ b/include/init/ssdk_plat.h
@@ -231,4 +231,12 @@
qca_ar8327_phy_dbg_read(a_uint32_t dev_id, a_uint32_t phy_addr,
a_uint16_t dbg_addr, a_uint16_t *dbg_data);
+void
+qca_phy_mmd_write(u32 dev_id, u32 phy_id,
+ u16 mmd_num, u16 reg_id, u16 reg_val);
+
+u16
+qca_phy_mmd_read(u32 dev_id, u32 phy_id,
+ u16 mmd_num, u16 reg_id);
+
#endif
diff --git a/src/init/ssdk_init.c b/src/init/ssdk_init.c
index 211d097..551e836 100755
--- a/src/init/ssdk_init.c
+++ b/src/init/ssdk_init.c
@@ -84,6 +84,9 @@
#ifdef IN_RFS
struct rfs_device rfs_dev;
struct notifier_block ssdk_inet_notifier;
+#if defined(CONFIG_RFS_ACCEL)
+struct notifier_block ssdk_dev_notifier;
+#endif
#endif
/*
@@ -1543,6 +1546,216 @@
return SW_FAIL;
}
+#if defined(CONFIG_OF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
+struct reset_control *ess_rst;
+void ssdk_ess_reset()
+{
+ reset_control_assert(ess_rst);
+ mdelay(10);
+ reset_control_deassert(ess_rst);
+ mdelay(100);
+}
+#endif
+
+
+void ssdk_psgmii_self_test()
+{
+ int i = 0, phy = 0,j=0;
+ int reset = 0;
+ u32 value = 0;
+ u32 phy_t_status = 0;
+
+ qca_ar8327_phy_write(0, 4, 0x1f, 0x8500);/*switch to access MII reg for copper*/
+ for(phy = 0; phy < 5; phy++) {
+ /*enable phy mdio broadcast write*/
+ qca_phy_mmd_write(0, phy, 7, 0x8028, 0x801f);
+ }
+
+ /* force no link by power down */
+ qca_ar8327_phy_write(0, 0x1f, 0x0, 0x1840);
+
+ /*packet number*/
+ qca_phy_mmd_write(0, 0x1f, 7, 0x8021, 0x3000);
+ qca_phy_mmd_write(0, 0x1f, 7, 0x8062, 0x05e0);
+
+ /*fix mdi status */
+ qca_ar8327_phy_write(0, 0x1f, 0x10, 0x6800);
+
+ for(i = 0; i < 100; i++)
+ {
+ phy_t_status = 0;
+
+ for(phy = 0; phy < 5; phy++) {
+ value = readl(hw_addr+0x66c+phy*0xc);
+ writel((value|(1<<21)), (hw_addr+0x66c+phy*0xc));
+ }
+
+ for (phy = 0;phy < 5; phy++)
+ {
+ u32 tx_counter_ok, tx_counter_error;
+ u32 rx_counter_ok, rx_counter_error;
+ u32 tx_counter_ok_high16;
+ u32 rx_counter_ok_high16;
+ u32 tx_ok,rx_ok;
+ qca_ar8327_phy_write(0, phy, 0x0, 0x9000);
+ qca_ar8327_phy_write(0, phy, 0x0, 0x4140);
+ j=0;
+ while (j<100)
+ {
+ u16 status;
+ qca_ar8327_phy_read(0, phy, 0x11, &status);
+ if(status & (1 << 10))
+ break;
+ mdelay(10);
+ j++;
+ }
+
+ /*enable check*/
+ qca_phy_mmd_write(0, phy, 7, 0x8029, 0x0000);
+ qca_phy_mmd_write(0, phy, 7, 0x8029, 0x0003);
+
+ /*start traffic*/
+ qca_phy_mmd_write(0, phy, 7, 0x8020, 0xa000);
+ mdelay(200);
+
+ /*check counter*/
+ tx_counter_ok = qca_phy_mmd_read(0, phy, 7, 0x802e);
+ tx_counter_ok_high16 = qca_phy_mmd_read(0, phy, 7, 0x802d);
+ tx_counter_error = qca_phy_mmd_read(0, phy, 7, 0x802f);
+ rx_counter_ok = qca_phy_mmd_read(0, phy, 7, 0x802b);
+ rx_counter_ok_high16 = qca_phy_mmd_read(0, phy, 7, 0x802a);
+ rx_counter_error = qca_phy_mmd_read(0, phy, 7, 0x802c);
+ tx_ok = tx_counter_ok + (tx_counter_ok_high16<<16);
+ rx_ok = rx_counter_ok + (rx_counter_ok_high16<<16);
+ if( tx_ok== 0x3000 && tx_counter_error == 0)/*success*/
+ {
+ phy_t_status &= (~(1<<phy));
+ }
+ else
+ {
+ printk("tx_ok = 0x%x, rx_ok = 0x%x, tx_counter_error = 0x%x, rx_counter_error = 0x%x\n",
+ tx_ok, rx_ok, tx_counter_error, rx_counter_error);
+ printk("PHY %d single test PSGMII issue happen \n", phy);
+ phy_t_status |= (1<<phy);
+ }
+
+ qca_ar8327_phy_write(0, phy, 0x0, 0x1840);
+ }
+
+ qca_ar8327_phy_write(0, 0x1f, 0x0, 0x9000);
+
+ qca_ar8327_phy_write(0, 0x1f, 0x0, 0x4140);
+
+ j=0;
+ while(j < 100)
+ {
+ for(phy = 0; phy < 5; phy++)
+ {
+ u16 status;
+ qca_ar8327_phy_read(0, phy, 0x11, &status);
+ if(!(status & (1 << 10)))
+ break;
+ }
+
+ if(phy >= 5)
+ break;
+ mdelay(10);
+ j++;
+ }
+ /*enable check*/
+ qca_phy_mmd_write(0, 0x1f, 7, 0x8029, 0x0000);
+ qca_phy_mmd_write(0, 0x1f, 7, 0x8029, 0x0003);
+
+ /*start traffic*/
+ qca_phy_mmd_write(0, 0x1f, 7, 0x8020, 0xa000);
+ mdelay(200);
+ for(phy = 0; phy < 5; phy++)
+ {
+ u32 tx_counter_ok, tx_counter_error;
+ u32 rx_counter_ok, rx_counter_error;
+ u32 tx_counter_ok_high16;
+ u32 rx_counter_ok_high16;
+ u32 tx_ok,rx_ok;
+ /*check counter*/
+ tx_counter_ok = qca_phy_mmd_read(0, phy, 7, 0x802e);
+ tx_counter_ok_high16 = qca_phy_mmd_read(0, phy, 7, 0x802d);
+ tx_counter_error = qca_phy_mmd_read(0, phy, 7, 0x802f);
+ rx_counter_ok = qca_phy_mmd_read(0, phy, 7, 0x802b);
+ rx_counter_ok_high16 = qca_phy_mmd_read(0, phy, 7, 0x802a);
+ rx_counter_error = qca_phy_mmd_read(0, phy, 7, 0x802c);
+ tx_ok = tx_counter_ok + (tx_counter_ok_high16<<16);
+ rx_ok = rx_counter_ok + (rx_counter_ok_high16<<16);
+ if( tx_ok== 0x3000 && tx_counter_error == 0)/*success*/
+ {
+ phy_t_status &= (~(1<<(phy+8)));
+ }
+ else
+ {
+ printk("tx_ok = 0x%x, rx_ok = 0x%x, tx_counter_error = 0x%x, rx_counter_error = 0x%x\n",
+ tx_ok, rx_ok, tx_counter_error, rx_counter_error);
+ printk("PHY %d PSGMII issue happen,Reset PSGMII!!!!!!\n", phy);
+ phy_t_status |= (1<<(phy+8));
+ }
+ }
+ printk("PHY all test 0x%x \r\n",phy_t_status);
+ if (phy_t_status)
+ {
+ qca_ar8327_phy_write(0, 5, 0x0, 0x005b);/*fix phy psgmii RX 20bit*/
+ qca_ar8327_phy_write(0, 5, 0x0, 0x001b);/*reset phy psgmii*/
+ qca_ar8327_phy_write(0, 5, 0x0, 0x005b);/*release reset phy psgmii*/
+ mdelay(100);
+ qca_ar8327_phy_write(0, 5, 0x1a, 0x2230);/*freeze phy psgmii RX CDR*/
+
+ #if defined(CONFIG_OF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
+ ssdk_ess_reset();
+ #endif
+
+ qca_ar8327_phy_write(0, 5, 0x1a, 0x3230);/*relesae phy psgmii RX CDR*/
+ qca_ar8327_phy_write(0, 5, 0x0, 0x005f);/*release phy psgmii RX 20bit*/
+ mdelay(200);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+#if 1
+ if (i>=100)
+ printk("PSGMII cannot recover\n");
+ else
+ printk("PSGMII recovered after %d times reset\n",i);
+#endif
+ /*configuration recover*/
+ /*packet number*/
+ qca_phy_mmd_write(0, 0x1f, 7, 0x8021, 0x0);
+ /*disable check*/
+ qca_phy_mmd_write(0, 0x1f, 7, 0x8029, 0x0);
+ /*disable traffic*/
+ qca_phy_mmd_write(0, 0x1f, 7, 0x8020, 0x0);
+}
+
+
+void clear_self_test_config()
+{
+ int i = 0, phy = 0;
+ u32 value = 0;
+ /* disable EEE */
+ qca_phy_mmd_write(0, 0x1f, 0x7, 0x3c, 0x0);
+
+ /*disable phy internal loopback*/
+ qca_ar8327_phy_write(0, 0x1f, 0x10, 0x6860);
+ qca_ar8327_phy_write(0, 0x1f, 0x0, 0x9040);
+
+ for(phy = 0; phy < 5; phy++)
+ {
+ /*disable mac loop back*/
+ value = readl(hw_addr+0x66c+phy*0xc);
+ writel((value&(~(1<<21))), (hw_addr+0x66c+phy*0xc));
+ /*diable phy mdio broadcast write*/
+ qca_phy_mmd_write(0, phy, 7, 0x8028, 0x001f);
+ }
+}
sw_error_t
ssdk_init(a_uint32_t dev_id, ssdk_init_cfg * cfg)
@@ -1564,10 +1777,20 @@
rv = hsl_dev_init(dev_id, cfg);
#else
rv = fal_init(dev_id, cfg);
+ if (rv != SW_OK)
+ printk("ssdk fal init failed \r\n");
#endif
#endif
+
+ ssdk_phy_init(cfg);
+
+ if (cfg->chip_type == CHIP_DESS)
+ ssdk_psgmii_self_test();
rv = ssdk_switch_init(dev_id);
- ssdk_phy_init(cfg);
+ if (rv != SW_OK)
+ printk("ssdk switch init failed \r\n");
+ if (cfg->chip_type == CHIP_DESS)
+ clear_self_test_config();
return rv;
}
@@ -1647,6 +1870,35 @@
mdiobus_write(bus, phy_addr, QCA_MII_MMD_DATA, data);
}
+void qca_phy_mmd_write(u32 dev_id, u32 phy_id,
+ u16 mmd_num, u16 reg_id, u16 reg_val)
+{
+ qca_ar8327_phy_write(dev_id, phy_id,
+ QCA_MII_MMD_ADDR, mmd_num);
+ qca_ar8327_phy_write(dev_id, phy_id,
+ QCA_MII_MMD_DATA, reg_id);
+ qca_ar8327_phy_write(dev_id, phy_id,
+ QCA_MII_MMD_ADDR,
+ 0x4000 | mmd_num);
+ qca_ar8327_phy_write(dev_id, phy_id,
+ QCA_MII_MMD_DATA, reg_val);
+}
+
+u16 qca_phy_mmd_read(u32 dev_id, u32 phy_id,
+ u16 mmd_num, u16 reg_id)
+{
+ u16 value = 0;
+ qca_ar8327_phy_write(dev_id, phy_id,
+ QCA_MII_MMD_ADDR, mmd_num);
+ qca_ar8327_phy_write(dev_id, phy_id,
+ QCA_MII_MMD_DATA, reg_id);
+ qca_ar8327_phy_write(dev_id, phy_id,
+ QCA_MII_MMD_ADDR,
+ 0x4000 | mmd_num);
+ qca_ar8327_phy_read(dev_id, phy_id,
+ QCA_MII_MMD_DATA, &value);
+ return value;
+}
uint32_t
qca_switch_reg_read(a_uint32_t dev_id, a_uint32_t reg_addr, a_uint8_t * reg_data, a_uint32_t len)
@@ -1719,20 +1971,9 @@
}
-void switch_port_enable()
+void switch_cpuport_enable()
{
- a_uint32_t value = 0x4e;
- a_uint8_t reg_value[] = {0};
-
- aos_mem_copy(reg_value, &value, sizeof(a_uint32_t));
- qca_switch_reg_write(0, 0x7c, ®_value, 4 );
-/*
- qca_switch_reg_write(0, 0x80, ®_value, 4 );
- qca_switch_reg_write(0, 0x84, ®_value, 4 );
- qca_switch_reg_write(0, 0x88, ®_value, 4 );
- qca_switch_reg_write(0, 0x8c, (a_uint8_t *)®_value, 4 );
- qca_switch_reg_write(0, 0x90, (a_uint8_t *)®_value, 4 );
-*/
+ writel(0x7e, hw_addr + 0x7c);
}
#if defined(CONFIG_OF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
@@ -1888,17 +2129,7 @@
reg_value = 0x2200;
qca_psgmii_reg_write(0, DESS_PSGMII_MODE_CONTROL,
(a_uint8_t *)®_value, 4);
- reg_value = 0x2803;
- qca_psgmii_reg_write(0, DESS_PSGMII_PLL_VCO_RELATED_CONTROL_1,
- (a_uint8_t *)®_value, 4);
- reg_value = 0x4ADA;
- qca_psgmii_reg_write(0, DESS_PSGMII_VCO_CALIBRATION_CONTROL_1,
- (a_uint8_t *)®_value, 4);
- udelay(1000);
- reg_value = 0xADA;
- qca_psgmii_reg_write(0, DESS_PSGMII_VCO_CALIBRATION_CONTROL_1,
- (a_uint8_t *)®_value, 4);
- udelay(1000);
+
return 0;
}
@@ -1928,6 +2159,23 @@
return ssdk_rfs_ipct_rule_set(src, dst, sport, dport,
proto, rxq_index, action);
}
+
+static int ssdk_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+
+ switch (event) {
+ case NETDEV_UP:
+ if (strstr(dev->name, "eth")) {
+ if (dev->netdev_ops && dev->netdev_ops->ndo_register_rfs_filter) {
+ dev->netdev_ops->ndo_register_rfs_filter(dev,
+ ssdk_netdev_rfs_cb);
+ }
+ }
+ break;
+ }
+ return NOTIFY_DONE;
+}
#endif
int ssdk_intf_search(
fal_intf_mac_entry_t *exist_entry, int num,
@@ -2067,7 +2315,34 @@
return NOTIFY_DONE;
}
#endif
+#if defined(CONFIG_OF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
+char ssdk_driver_name[] = "ess_ssdk";
+static int ssdk_probe(struct platform_device *pdev)
+{
+ ess_rst = devm_reset_control_get(&pdev->dev, "ess_rst");
+ reset_control_assert(ess_rst);
+ mdelay(10);
+ reset_control_deassert(ess_rst);
+ mdelay(100);
+ printk("reset ok in probe!\n");
+ return 0;
+}
+
+static const struct of_device_id ssdk_of_mtable[] = {
+ {.compatible = "qcom,ess-switch" },
+ {}
+};
+
+static struct platform_driver ssdk_driver = {
+ .driver = {
+ .name = ssdk_driver_name,
+ .owner = THIS_MODULE,
+ .of_match_table = ssdk_of_mtable,
+ },
+ .probe = ssdk_probe,
+};
+#endif
static int __init
regi_init(void)
{
@@ -2077,11 +2352,11 @@
ssdk_dt_global.switch_reg_access_mode = HSL_REG_MDIO;
ssdk_dt_global.psgmii_reg_access_mode = HSL_REG_MDIO;
a_uint8_t chip_version = 0;
- #ifdef IN_RFS
- #if defined(CONFIG_RFS_ACCEL)
- struct net_device *rfs_net = NULL;
+ #if defined(CONFIG_OF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
+ struct device dev;
+ struct reset_control *ess_rst = NULL;
#endif
-
+ #ifdef IN_RFS
memset(&rfs_dev, 0, sizeof(rfs_dev));
#endif
@@ -2097,6 +2372,15 @@
memset(&chip_spec_cfg, 0, sizeof(garuda_init_spec_cfg));
+#if defined(CONFIG_OF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
+ if(ssdk_dt_global.switch_reg_access_mode == HSL_REG_LOCAL_BUS) {
+ dev.of_node=of_find_node_by_name(NULL, "ess-switch");
+
+ platform_driver_register(&ssdk_driver);
+ }
+#endif
+
+
if(ssdk_dt_global.switch_reg_access_mode == HSL_REG_MDIO)
cfg.reg_mode = HSL_MDIO;
else if(ssdk_dt_global.switch_reg_access_mode == HSL_REG_LOCAL_BUS)
@@ -2146,22 +2430,9 @@
rfs_dev.ip6_rule_cb = ssdk_rfs_ip6_rule_set;
rfs_ess_device_register(&rfs_dev);
#if defined(CONFIG_RFS_ACCEL)
- rfs_net = dev_get_by_name(&init_net, "eth0");
- if(rfs_net) {
- if(rfs_net->netdev_ops) {
- if(rfs_net->netdev_ops->ndo_register_rfs_filter)
- rfs_net->netdev_ops->ndo_register_rfs_filter(rfs_net,
- ssdk_netdev_rfs_cb);
- }
- }
- rfs_net = dev_get_by_name(&init_net, "eth1");
- if(rfs_net) {
- if(rfs_net->netdev_ops) {
- if(rfs_net->netdev_ops->ndo_register_rfs_filter)
- rfs_net->netdev_ops->ndo_register_rfs_filter(rfs_net,
- ssdk_netdev_rfs_cb);
- }
- }
+ ssdk_dev_notifier.notifier_call = ssdk_dev_event;
+ ssdk_dev_notifier.priority = 1;
+ register_netdevice_notifier(&ssdk_dev_notifier);
#endif
ssdk_inet_notifier.notifier_call = ssdk_inet_event;
ssdk_inet_notifier.priority = 1;
@@ -2169,7 +2440,7 @@
#endif
/* Enable port temprarily, will remove the code when phy board is ok. */
- switch_port_enable();
+ switch_cpuport_enable();
}
out:
@@ -2199,6 +2470,9 @@
#ifdef IN_RFS
rfs_ess_device_unregister(&rfs_dev);
unregister_inetaddr_notifier(&ssdk_inet_notifier);
+ #if defined(CONFIG_RFS_ACCEL)
+ unregister_netdevice_notifier(&ssdk_dev_notifier);
+ #endif
#endif
}
diff --git a/src/ref/ref_misc.c b/src/ref/ref_misc.c
index f0dd61a..f715742 100755
--- a/src/ref/ref_misc.c
+++ b/src/ref/ref_misc.c
@@ -114,16 +114,18 @@
memset(priv->vlan_tagged, 0, sizeof(a_uint8_t) * AR8327_MAX_VLANS);
memset(priv->pvid, 0, sizeof(a_uint16_t) * AR8327_NUM_PORTS);
- /*for (i = 0; i < AR8327_MAX_VLANS; i++)*/
- /* priv->vlan_id[i] = i;*/
-#ifndef BOARD_AR71XX
+ /*for (i = 0; i < AR8327_MAX_VLANS; i++)*/
+ /* priv->vlan_id[i] = i;*/
+ #ifndef BOARD_AR71XX
+ if (priv->version == QCA_VER_AR8327 ||
+ priv->version == QCA_VER_AR8337) {
+ qca_ar8327_phy_disable();
+ msleep(1000);
+ /* init switch, not necessary for dess??*/
+ rv += ssdk_switch_init(0);
- qca_ar8327_phy_disable();
- msleep(1000);
-
-#endif
- /* init switch */
- rv += ssdk_switch_init(0);
+ }
+ #endif
mutex_unlock(&priv->reg_mutex);
@@ -136,13 +138,19 @@
qca_ar8327_port_init(priv, i);
}
#endif
- fal_port_link_forcemode_set(0, 1, A_FALSE);
- fal_port_link_forcemode_set(0, 2, A_FALSE);
- fal_port_link_forcemode_set(0, 3, A_FALSE);
- fal_port_link_forcemode_set(0, 4, A_FALSE);
- fal_port_link_forcemode_set(0, 5, A_FALSE);
- qca_ar8327_phy_enable(priv);
+ if (priv->version == QCA_VER_AR8327 ||
+ priv->version == QCA_VER_AR8337) {
+ fal_port_link_forcemode_set(0, 1, A_FALSE);
+ fal_port_link_forcemode_set(0, 2, A_FALSE);
+ fal_port_link_forcemode_set(0, 3, A_FALSE);
+ fal_port_link_forcemode_set(0, 4, A_FALSE);
+ fal_port_link_forcemode_set(0, 5, A_FALSE);
+ qca_ar8327_phy_enable(priv);
+ }
#endif
- return rv;
+ fal_port_rxmac_status_set(0, 0, A_TRUE);
+ fal_port_txmac_status_set(0, 0, A_TRUE);
+
+ return rv;
}