Created
October 10, 2017 15:22
-
-
Save riptidewave93/0261107c353a710c34063e9fa63a4f29 to your computer and use it in GitHub Desktop.
Meraki MR33 GPL Source eth driver diff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -Nurp a/drivers/net/ethernet/qualcomm/essedma/edma_axi.c b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c | |
--- a/drivers/net/ethernet/qualcomm/essedma/edma_axi.c 2017-09-19 21:59:00.852206367 +0200 | |
+++ b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c 2017-09-24 20:00:30.181877681 +0200 | |
@@ -13,15 +13,36 @@ | |
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
*/ | |
#include <linux/cpu_rmap.h> | |
#include <linux/of.h> | |
#include <linux/of_net.h> | |
#include <linux/timer.h> | |
+#include <linux/of_platform.h> | |
+#include <linux/clk.h> | |
+#include <linux/string.h> | |
+#include <linux/reset.h> | |
#include "edma.h" | |
#include "ess_edma.h" | |
+ | |
+typedef struct | |
+{ | |
+ u32 switchreg_base_addr; | |
+ u32 switchreg_size; | |
+ u32 psgmiireg_base_addr; | |
+ u32 psgmiireg_size; | |
+ char *reg_access_mode; | |
+ char *psgmii_reg_access_str; | |
+ struct clk *ess_clk; | |
+ u32 mac_mode; | |
+} ssdk_dt_cfg; | |
+ | |
+ssdk_dt_cfg ssdk_dt_global = {0}; | |
+u8 __iomem *ess_hw_addr = NULL; | |
+u8 __iomem *psgmii_hw_addr = NULL; | |
+struct mii_bus *miibus = NULL; | |
/* Weight round robin and virtual QID mask */ | |
#define EDMA_WRR_VID_SCTL_MASK 0xffff | |
/* Weight round robin and virtual QID shift */ | |
#define EDMA_WRR_VID_SCTL_SHIFT 16 | |
@@ -83,7 +103,18 @@ void edma_read_reg(u16 reg_addr, volatil | |
*reg_value = readl((void __iomem *)(edma_hw_addr + reg_addr)); | |
} | |
-/* edma_change_tx_coalesce() | |
+void ess_write_reg(u16 reg_addr, u32 reg_value) | |
+{ | |
+ writel(reg_value, ((void __iomem *)(ess_hw_addr + reg_addr))); | |
+} | |
+ | |
+void ess_read_reg(u16 reg_addr, volatile u32 *reg_value) | |
+{ | |
+ *reg_value = readl((void __iomem *)(ess_hw_addr + reg_addr)); | |
+} | |
+ | |
+/* | |
+ * edma_change_tx_coalesce() | |
* change tx interrupt moderation timer | |
*/ | |
void edma_change_tx_coalesce(int usecs) | |
@@ -535,7 +556,79 @@ static struct ctl_table edma_table[] = { | |
{} | |
}; | |
-/* edma_axi_netdev_ops | |
+static int __init ssdk_dt_parse(void) | |
+{ | |
+ struct device_node *switch_node = NULL; | |
+ struct device_node *psgmii_node = NULL; | |
+ u32 len = 0; | |
+ const __be32 *reg_cfg, *mac_mode; | |
+ | |
+ switch_node = of_find_node_by_name(NULL, "ess-switch"); | |
+ if (!switch_node) { | |
+ printk("cannot find ess-switch node\n"); | |
+ return -1; | |
+ } | |
+ | |
+ reg_cfg = of_get_property(switch_node, "reg", &len); | |
+ if(!reg_cfg) { | |
+ printk("%s: error reading device node properties for reg\n", switch_node->name); | |
+ return -1; | |
+ } | |
+ | |
+ ssdk_dt_global.switchreg_base_addr = be32_to_cpup(reg_cfg); | |
+ ssdk_dt_global.switchreg_size = be32_to_cpup(reg_cfg + 1); | |
+ | |
+ if (!request_mem_region(ssdk_dt_global.switchreg_base_addr, | |
+ ssdk_dt_global.switchreg_size, "switch_mem")) { | |
+ printk("%s Unable to request resource.", __func__); | |
+ return -1; | |
+ } | |
+ | |
+ ess_hw_addr = ioremap_nocache(ssdk_dt_global.switchreg_base_addr, | |
+ ssdk_dt_global.switchreg_size); | |
+ if (!ess_hw_addr) { | |
+ printk("%s ioremap fail.", __func__); | |
+ return -1; | |
+ } | |
+ | |
+ psgmii_node = of_find_node_by_name(NULL, "ess-psgmii"); | |
+ if (!psgmii_node) { | |
+ return -1; | |
+ } | |
+ reg_cfg = of_get_property(psgmii_node, "reg", &len); | |
+ if(!reg_cfg) { | |
+ printk("%s: error reading device node properties for reg\n", psgmii_node->name); | |
+ return -1; | |
+ } | |
+ | |
+ ssdk_dt_global.psgmiireg_base_addr = be32_to_cpup(reg_cfg); | |
+ ssdk_dt_global.psgmiireg_size = be32_to_cpup(reg_cfg + 1); | |
+ | |
+ if (!request_mem_region(ssdk_dt_global.psgmiireg_base_addr, | |
+ ssdk_dt_global.psgmiireg_size, "psgmii_mem")) { | |
+ printk("%s Unable to request psgmii resource.", __func__); | |
+ return -1; | |
+ } | |
+ | |
+ psgmii_hw_addr = ioremap_nocache(ssdk_dt_global.psgmiireg_base_addr, | |
+ ssdk_dt_global.psgmiireg_size); | |
+ if (!psgmii_hw_addr) { | |
+ printk("%s ioremap fail.", __func__); | |
+ return -1; | |
+ } | |
+ | |
+ ssdk_dt_global.ess_clk = of_clk_get_by_name(switch_node, "ess_clk"); | |
+ clk_prepare_enable(ssdk_dt_global.ess_clk); | |
+ | |
+ mac_mode = of_get_property(switch_node, "switch_mac_mode", &len); | |
+ if (mac_mode) { | |
+ ssdk_dt_global.mac_mode = be32_to_cpup(mac_mode); | |
+ } | |
+ | |
+ return 0; | |
+} | |
+ | |
+/* edma_axi_netdev_ops | |
* Describe the operations supported by registered netdevices | |
* | |
* static const struct net_device_ops edma_axi_netdev_ops = { | |
@@ -787,6 +893,8 @@ static int edma_axi_probe(struct platfor | |
miibus = mdio_data->mii_bus; | |
} | |
+ ess_reset(pdev); | |
+ | |
for_each_available_child_of_node(np, pnp) { | |
const char *mac_addr; | |
@@ -1207,7 +1277,27 @@ MODULE_DEVICE_TABLE(of, edma_of_mtable); | |
.remove = edma_axi_remove, | |
}; | |
-module_platform_driver(edma_axi_driver); | |
+static int __init edma_axi_init_module(void) | |
+{ | |
+ int ret; | |
+ pr_info("edma module_init\n"); | |
+ ret = ssdk_dt_parse(); | |
+ if (ret < 0) { | |
+ pr_err("ESS Failed to parse Device Tree\n"); | |
+ } | |
+ ret = platform_driver_register(&edma_axi_driver); | |
+ | |
+ return ret; | |
+} | |
+module_init(edma_axi_init_module); | |
+ | |
+static void __exit edma_axi_exit_module(void) | |
+{ | |
+ platform_driver_unregister(&edma_axi_driver); | |
+ iounmap(ess_hw_addr); | |
+ pr_info("edma module_exit\n"); | |
+} | |
+module_exit(edma_axi_exit_module); | |
MODULE_AUTHOR("Qualcomm Atheros Inc"); | |
MODULE_DESCRIPTION("QCA ESS EDMA driver"); | |
diff -Nurp a/drivers/net/ethernet/qualcomm/essedma/edma.c b/drivers/net/ethernet/qualcomm/essedma/edma.c | |
--- a/drivers/net/ethernet/qualcomm/essedma/edma.c 2017-09-19 21:59:00.855539705 +0200 | |
+++ b/drivers/net/ethernet/qualcomm/essedma/edma.c 2017-09-24 20:00:30.551878637 +0200 | |
@@ -161,9 +165,11 @@ static void edma_configure_rx(struct edm | |
/* Set Rx FIFO threshold to start to DMA data to host */ | |
rxq_ctrl_data = EDMA_FIFO_THRESH_128_BYTE; | |
+#ifdef MERAKI_REMOVED | |
/* Set RX remove vlan bit */ | |
rxq_ctrl_data |= EDMA_RXQ_CTRL_RMV_VLAN; | |
+#endif | |
edma_write_reg(EDMA_REG_RXQ_CTRL, rxq_ctrl_data); | |
} | |
@@ -1276,6 +1209,34 @@ static int edma_check_link(struct edma_a | |
return __EDMA_LINKDOWN; | |
} | |
+void ess_set_port_status_speed(struct phy_device *phydev, uint8_t port_id) | |
+{ | |
+ uint16_t reg_off = ESS_PORT0_STATUS + (4 * port_id); | |
+ uint32_t reg_val = 0; | |
+ | |
+ ess_read_reg(reg_off, ®_val); | |
+ | |
+ /* reset the speed bits [0:1] */ | |
+ reg_val &= ~ESS_PORT_STATUS_SPEED_INV; | |
+ | |
+ /* set the new speed */ | |
+ switch(phydev->speed) { | |
+ case SPEED_1000: reg_val |= ESS_PORT_STATUS_SPEED_1000; break; | |
+ case SPEED_100: reg_val |= ESS_PORT_STATUS_SPEED_100; break; | |
+ case SPEED_10: reg_val |= ESS_PORT_STATUS_SPEED_10; break; | |
+ default: reg_val |= ESS_PORT_STATUS_SPEED_INV; break; | |
+ } | |
+ | |
+ /* check full/half duplex */ | |
+ if (phydev->duplex) { | |
+ reg_val |= ESS_PORT_STATUS_DUPLEX_MODE; | |
+ } else { | |
+ reg_val &= ~ESS_PORT_STATUS_DUPLEX_MODE; | |
+ } | |
+ | |
+ ess_write_reg(reg_off, reg_val); | |
+} | |
+ | |
/* edma_adjust_link() | |
* check for edma link status | |
*/ | |
@@ -1293,6 +1255,7 @@ void edma_adjust_link(struct net_device | |
if (status == __EDMA_LINKUP && adapter->link_state == __EDMA_LINKDOWN) { | |
dev_info(&adapter->pdev->dev, "%s: GMAC Link is up with phy_speed=%d\n", netdev->name, phydev->speed); | |
adapter->link_state = __EDMA_LINKUP; | |
+ ess_set_port_status_speed(phydev, ffs(adapter->dp_bitmap) - 1); | |
netif_carrier_on(netdev); | |
if (netif_running(netdev)) | |
netif_tx_wake_all_queues(netdev); | |
@@ -1386,8 +1354,12 @@ netdev_tx_t edma_xmit(struct sk_buff *sk | |
} | |
/* Check and mark VLAN tag offload */ | |
- if (skb_vlan_tag_present(skb)) | |
+#ifdef MERAKI_REMOVED | |
+ if (unlikely(vlan_tx_tag_present(skb))) | |
flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_FLAG; | |
+ else if (adapter->default_vlan_tag) | |
+ flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG; | |
+#endif | |
/* Check and mark checksum offload */ | |
if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) | |
diff -Nurp a/drivers/net/ethernet/qualcomm/essedma/edma_reset.c b/drivers/net/ethernet/qualcomm/essedma/edma_reset.c | |
--- a/drivers/net/ethernet/qualcomm/essedma/edma_reset.c 1970-01-01 01:00:00.000000000 +0100 | |
+++ b/drivers/net/ethernet/qualcomm/essedma/edma_reset.c 2017-09-24 20:00:29.815210068 +0200 | |
@@ -0,0 +1,330 @@ | |
+/* | |
+ * ESS reset | |
+ * | |
+ * extracted from qca-ssdk/src/init/ssdk_init.c, which is | |
+ * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. | |
+ */ | |
+ | |
+#include <linux/delay.h> | |
+#include <linux/io.h> | |
+#include <linux/platform_device.h> | |
+#include <linux/phy.h> | |
+#include <linux/timer.h> | |
+#include <linux/of.h> | |
+#include <linux/of_platform.h> | |
+#include <linux/string.h> | |
+#include <linux/reset.h> | |
+#include "edma.h" | |
+ | |
+extern u8 __iomem *ess_hw_addr; | |
+extern u8 __iomem *psgmii_hw_addr; | |
+extern struct mii_bus *miibus; | |
+ | |
+static void ssdk_ess_reset(struct platform_device *pdev) | |
+{ | |
+ u32 regval; | |
+ | |
+ struct reset_control *ess_rst = devm_reset_control_get(&pdev->dev, "ess_rst"); | |
+ if (IS_ERR(ess_rst)) { | |
+ printk("ess rst fail!\n"); | |
+ return; | |
+ } | |
+ | |
+ reset_control_assert(ess_rst); | |
+ mdelay(10); | |
+ reset_control_deassert(ess_rst); | |
+ mdelay(100); | |
+ printk("reset ok in probe!\n"); | |
+ | |
+ /* Enable only port 5 <--> port 0 | |
+ bits 0:6 bitmap of ports it can fwd to | |
+ */ | |
+#define SET_PORT_BMP(r,v) \ | |
+ ess_read_reg(r, ®val); \ | |
+ ess_write_reg(r, ((regval & ~0x3F) | v)); | |
+ | |
+ SET_PORT_BMP(ESS_PORT0_LOOKUP_CTRL,0x20); | |
+ SET_PORT_BMP(ESS_PORT1_LOOKUP_CTRL,0x00); | |
+ SET_PORT_BMP(ESS_PORT2_LOOKUP_CTRL,0x00); | |
+ SET_PORT_BMP(ESS_PORT3_LOOKUP_CTRL,0x00); | |
+ SET_PORT_BMP(ESS_PORT4_LOOKUP_CTRL,0x00); | |
+ SET_PORT_BMP(ESS_PORT5_LOOKUP_CTRL,0x01); | |
+ ess_write_reg(ESS_RGMII_CTRL, 0x400); | |
+ ess_write_reg(ESS_PORT0_STATUS, ESS_PORT_1G_FDX); | |
+ ess_write_reg(ESS_PORT5_STATUS, ESS_PORT_1G_FDX); | |
+ ess_write_reg(ESS_PORT0_HEADER_CTRL, 0); | |
+ | |
+#undef SET_PORT_BMP | |
+} | |
+ | |
+static void | |
+qca_ar8327_phy_read(u32 phy_addr, u32 reg, u16* data) | |
+{ | |
+ *data = mdiobus_read(miibus, phy_addr, reg); | |
+} | |
+ | |
+static void | |
+qca_ar8327_phy_write(u32 phy_addr, u32 reg, u16 data) | |
+{ | |
+ mdiobus_write(miibus, phy_addr, reg, data); | |
+} | |
+ | |
+static u16 | |
+qca_phy_mmd_read(u32 phy_id, u16 mmd_num, u16 reg_id) | |
+{ | |
+ u16 value = 0; | |
+ qca_ar8327_phy_write(phy_id, MII_MMD_CTRL, mmd_num); | |
+ qca_ar8327_phy_write(phy_id, MII_MMD_DATA, reg_id); | |
+ qca_ar8327_phy_write(phy_id, MII_MMD_CTRL, 0x4000 | mmd_num); | |
+ qca_ar8327_phy_read(phy_id, MII_MMD_DATA, &value); | |
+ return value; | |
+} | |
+ | |
+static void | |
+qca_phy_mmd_write(u32 phy_id, u16 mmd_num, u16 reg_id, u16 reg_val) | |
+{ | |
+ qca_ar8327_phy_write(phy_id, MII_MMD_CTRL, mmd_num); | |
+ qca_ar8327_phy_write(phy_id, MII_MMD_DATA, reg_id); | |
+ qca_ar8327_phy_write(phy_id, MII_MMD_CTRL, 0x4000 | mmd_num); | |
+ qca_ar8327_phy_write(phy_id, MII_MMD_DATA, reg_val); | |
+} | |
+ | |
+static void ssdk_malibu_psgmii_and_dakota_dess_reset(struct platform_device *pdev) | |
+{ | |
+ int m = 0, n = 0; | |
+ | |
+ /*reset Malibu PSGMII and Dakota ESS start*/ | |
+ qca_ar8327_phy_write(5, 0x0, 0x005b);/*fix phy psgmii RX 20bit*/ | |
+ qca_ar8327_phy_write(5, 0x0, 0x001b);/*reset phy psgmii*/ | |
+ qca_ar8327_phy_write(5, 0x0, 0x005b);/*release reset phy psgmii*/ | |
+ /* mdelay(100); this 100ms be replaced with below malibu psgmii calibration process*/ | |
+ /*check malibu psgmii calibration done start*/ | |
+ n = 0; | |
+ while (n < 100) { | |
+ u16 status; | |
+ status = qca_phy_mmd_read(5, 1, 0x28); | |
+ if (status & BIT(0)) | |
+ break; | |
+ mdelay(10); | |
+ n++; | |
+ } | |
+ | |
+ if (n >= 100) | |
+ printk("MALIBU PSGMII PLL_VCO_CALIB NOT READY\n"); | |
+ | |
+ mdelay(50); | |
+ /*check malibu psgmii calibration done end..*/ | |
+ qca_ar8327_phy_write(5, 0x1a, 0x2230);/*freeze phy psgmii RX CDR*/ | |
+ | |
+ ssdk_ess_reset(pdev); | |
+ /*check dakota psgmii calibration done start*/ | |
+ m = 0; | |
+ while (m < 100) { | |
+ u32 status = readl(psgmii_hw_addr + 0xa0); | |
+ if (status & BIT(0)) | |
+ break; | |
+ mdelay(10); | |
+ m++; | |
+ } | |
+ | |
+ if (m >= 100) | |
+ printk("DAKOTA PSGMII PLL_VCO_CALIB NOT READY\n"); | |
+ | |
+ mdelay(50); | |
+ /*check dakota psgmii calibration done end..*/ | |
+ qca_ar8327_phy_write(5, 0x1a, 0x3230); /*release phy psgmii RX CDR*/ | |
+ qca_ar8327_phy_write(5, 0x0, 0x005f); /*release phy psgmii RX 20bit*/ | |
+ mdelay(200); | |
+ | |
+ /*reset Malibu PSGMII and Dakota ESS end*/ | |
+ return; | |
+} | |
+ | |
+static u32 phy_t_status = 0; | |
+void ssdk_psgmii_single_phy_testing(int phy) | |
+{ | |
+ int j = 0; | |
+ | |
+ 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(phy, 0x0, 0x9000); | |
+ qca_ar8327_phy_write(phy, 0x0, 0x4140); | |
+ for (j = 0; j < 100; j++) { | |
+ u16 status; | |
+ qca_ar8327_phy_read(phy, 0x11, &status); | |
+ if (status & (1 << 10)) | |
+ break; | |
+ mdelay(10); | |
+ } | |
+ | |
+ /*enable check*/ | |
+ qca_phy_mmd_write(phy, 7, 0x8029, 0x0000); | |
+ qca_phy_mmd_write(phy, 7, 0x8029, 0x0003); | |
+ | |
+ /*start traffic*/ | |
+ qca_phy_mmd_write(phy, 7, 0x8020, 0xa000); | |
+ mdelay(200); | |
+ | |
+ /*check counter*/ | |
+ tx_counter_ok = qca_phy_mmd_read(phy, 7, 0x802e); | |
+ tx_counter_ok_high16 = qca_phy_mmd_read(phy, 7, 0x802d); | |
+ tx_counter_error = qca_phy_mmd_read(phy, 7, 0x802f); | |
+ rx_counter_ok = qca_phy_mmd_read(phy, 7, 0x802b); | |
+ rx_counter_ok_high16 = qca_phy_mmd_read(phy, 7, 0x802a); | |
+ rx_counter_error = qca_phy_mmd_read(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 { | |
+ phy_t_status |= (1<<phy); | |
+ } | |
+ | |
+ qca_ar8327_phy_write(phy, 0x0, 0x1840); | |
+} | |
+ | |
+static void ssdk_psgmii_all_phy_testing(void) | |
+{ | |
+ int phy = 0, j = 0; | |
+ | |
+ qca_ar8327_phy_write(0x1f, 0x0, 0x9000); | |
+ qca_ar8327_phy_write(0x1f, 0x0, 0x4140); | |
+ j = 0; | |
+ for (j = 0; j < 100; j++) { | |
+ for (phy = 0; phy < 5; phy++) { | |
+ u16 status; | |
+ qca_ar8327_phy_read(phy, 0x11, &status); | |
+ if (!(status & (1 << 10))) | |
+ break; | |
+ } | |
+ | |
+ if (phy >= 5) | |
+ break; | |
+ mdelay(10); | |
+ } | |
+ | |
+ /*enable check*/ | |
+ qca_phy_mmd_write(0x1f, 7, 0x8029, 0x0000); | |
+ qca_phy_mmd_write(0x1f, 7, 0x8029, 0x0003); | |
+ | |
+ /*start traffic*/ | |
+ qca_phy_mmd_write(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(phy, 7, 0x802e); | |
+ tx_counter_ok_high16 = qca_phy_mmd_read(phy, 7, 0x802d); | |
+ tx_counter_error = qca_phy_mmd_read(phy, 7, 0x802f); | |
+ rx_counter_ok = qca_phy_mmd_read(phy, 7, 0x802b); | |
+ rx_counter_ok_high16 = qca_phy_mmd_read(phy, 7, 0x802a); | |
+ rx_counter_error = qca_phy_mmd_read(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 { | |
+ phy_t_status |= (1<<(phy+8)); | |
+ } | |
+ } | |
+} | |
+ | |
+static void ssdk_psgmii_self_test(struct platform_device *pdev) | |
+{ | |
+ int i = 0, phy = 0, times = 100; | |
+ u32 value = 0; | |
+ | |
+ ssdk_malibu_psgmii_and_dakota_dess_reset(pdev); | |
+ | |
+ qca_ar8327_phy_write(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(phy, 7, 0x8028, 0x801f); | |
+ } | |
+ | |
+ /* force no link by power down */ | |
+ qca_ar8327_phy_write(0x1f, 0x0, 0x1840); | |
+ | |
+ /*packet number*/ | |
+ qca_phy_mmd_write(0x1f, 7, 0x8021, 0x3000); | |
+ qca_phy_mmd_write(0x1f, 7, 0x8062, 0x05e0); | |
+ | |
+ /*fix mdi status */ | |
+ qca_ar8327_phy_write(0x1f, 0x10, 0x6800); | |
+ | |
+ for(i = 0; i < times; i++) { | |
+ phy_t_status = 0; | |
+ | |
+ for(phy = 0; phy < 5; phy++) { | |
+ value = readl(ess_hw_addr + 0x66c + phy * 0xc); | |
+ writel((value|(1<<21)), (ess_hw_addr + 0x66c + phy * 0xc)); | |
+ } | |
+ | |
+ for (phy = 0; phy < 5; phy++) | |
+ ssdk_psgmii_single_phy_testing(phy); | |
+ | |
+ ssdk_psgmii_all_phy_testing(); | |
+ if (!phy_t_status) | |
+ break; | |
+ | |
+ ssdk_malibu_psgmii_and_dakota_dess_reset(pdev); | |
+ } | |
+ | |
+ if (i>=100) | |
+ printk("PSGMII cannot recover\n"); | |
+ else | |
+ printk("PSGMII recovered after %d times reset\n", i); | |
+ | |
+ /*configuration recover*/ | |
+ /*packet number*/ | |
+ qca_phy_mmd_write(0x1f, 7, 0x8021, 0x0); | |
+ /*disable check*/ | |
+ qca_phy_mmd_write(0x1f, 7, 0x8029, 0x0); | |
+ /*disable traffic*/ | |
+ qca_phy_mmd_write(0x1f, 7, 0x8020, 0x0); | |
+} | |
+ | |
+static void clear_self_test_config(void) | |
+{ | |
+ int phy = 0; | |
+ u32 value = 0; | |
+ /* disable EEE */ | |
+/* qca_phy_mmd_write(0, 0x1f, 0x7, 0x3c, 0x0); */ | |
+ | |
+ /*disable phy internal loopback*/ | |
+ qca_ar8327_phy_write(0x1f, 0x10, 0x6860); | |
+ qca_ar8327_phy_write(0x1f, 0x0, 0x9040); | |
+ | |
+ for (phy = 0; phy < 5; phy++) { | |
+ /*disable mac loop back*/ | |
+ value = readl(ess_hw_addr+0x66c+phy*0xc); | |
+ writel((value&(~(1<<21))), (ess_hw_addr+0x66c+phy*0xc)); | |
+ /*disable phy mdio broadcast write*/ | |
+ qca_phy_mmd_write(phy, 7, 0x8028, 0x001f); | |
+ } | |
+ | |
+ /* clear fdb entry */ | |
+ /* fal_fdb_del_all(0,1); */ | |
+} | |
+ | |
+void ess_reset(struct platform_device *pdev) | |
+{ | |
+ struct device_node* np = pdev->dev.of_node; | |
+ | |
+ if (of_property_read_bool(np, "qcom,self_test")) { | |
+ ssdk_psgmii_self_test(pdev); | |
+ clear_self_test_config(); | |
+ } else { | |
+ ssdk_ess_reset(pdev); | |
+ } | |
+} | |
diff -Nurp a/drivers/net/ethernet/qualcomm/essedma/ess_edma.h b/drivers/net/ethernet/qualcomm/essedma/ess_edma.h | |
--- a/drivers/net/ethernet/qualcomm/essedma/ess_edma.h 2017-09-19 21:59:00.852206367 +0200 | |
+++ b/drivers/net/ethernet/qualcomm/essedma/ess_edma.h 2017-09-24 20:00:30.798545941 +0200 | |
@@ -329,4 +329,53 @@ struct edma_hw; | |
#define EDMA_RRD_PRIORITY_MASK 0x7 | |
#define EDMA_RRD_PORT_TYPE_SHIFT 7 | |
#define EDMA_RRD_PORT_TYPE_MASK 0x1F | |
+ | |
+#define ESS_RGMII_CTRL 0x0004 | |
+ | |
+/* Port status registers */ | |
+#define ESS_PORT0_STATUS 0x007C | |
+#define ESS_PORT1_STATUS 0x0080 | |
+#define ESS_PORT2_STATUS 0x0084 | |
+#define ESS_PORT3_STATUS 0x0088 | |
+#define ESS_PORT4_STATUS 0x008C | |
+#define ESS_PORT5_STATUS 0x0090 | |
+ | |
+#define ESS_PORT_STATUS_HDX_FLOW_CTL 0x80 | |
+#define ESS_PORT_STATUS_DUPLEX_MODE 0x40 | |
+#define ESS_PORT_STATUS_RX_FLOW_EN 0x20 | |
+#define ESS_PORT_STATUS_TX_FLOW_EN 0x10 | |
+#define ESS_PORT_STATUS_RX_MAC_EN 0x08 | |
+#define ESS_PORT_STATUS_TX_MAC_EN 0x04 | |
+#define ESS_PORT_STATUS_SPEED_INV 0x03 | |
+#define ESS_PORT_STATUS_SPEED_1000 0x02 | |
+#define ESS_PORT_STATUS_SPEED_100 0x01 | |
+#define ESS_PORT_STATUS_SPEED_10 0x00 | |
+ | |
+#define ESS_PORT_1G_FDX (ESS_PORT_STATUS_DUPLEX_MODE | ESS_PORT_STATUS_RX_FLOW_EN | \ | |
+ ESS_PORT_STATUS_TX_FLOW_EN | ESS_PORT_STATUS_RX_MAC_EN | \ | |
+ ESS_PORT_STATUS_TX_MAC_EN | ESS_PORT_STATUS_SPEED_1000) | |
+ | |
+#define PHY_STATUS_REG 0x11 | |
+#define PHY_STATUS_SPEED 0xC000 | |
+#define PHY_STATUS_SPEED_SHIFT 14 | |
+#define PHY_STATUS_DUPLEX 0x2000 | |
+#define PHY_STATUS_DUPLEX_SHIFT 13 | |
+#define PHY_STATUS_SPEED_DUPLEX_RESOLVED 0x0800 | |
+#define PHY_STATUS_CARRIER 0x0400 | |
+#define PHY_STATUS_CARRIER_SHIFT 10 | |
+ | |
+/* Port lookup control registers */ | |
+#define ESS_PORT0_LOOKUP_CTRL 0x0660 | |
+#define ESS_PORT1_LOOKUP_CTRL 0x066C | |
+#define ESS_PORT2_LOOKUP_CTRL 0x0678 | |
+#define ESS_PORT3_LOOKUP_CTRL 0x0684 | |
+#define ESS_PORT4_LOOKUP_CTRL 0x0690 | |
+#define ESS_PORT5_LOOKUP_CTRL 0x069C | |
+ | |
+#define ESS_PORT0_HEADER_CTRL 0x009C | |
+ | |
+void ess_reset(struct platform_device *pdev); | |
+void ess_write_reg(u16 reg_addr, u32 reg_value); | |
+void ess_read_reg(u16 reg_addr, volatile u32 *reg_value); | |
+ | |
#endif /* _ESS_EDMA_H_ */ | |
diff -Nurp a/drivers/net/ethernet/qualcomm/essedma/Makefile b/drivers/net/ethernet/qualcomm/essedma/Makefile | |
--- a/drivers/net/ethernet/qualcomm/essedma/Makefile 2017-09-19 21:59:00.845539688 +0200 | |
+++ b/drivers/net/ethernet/qualcomm/essedma/Makefile 2017-09-24 20:00:29.568542764 +0200 | |
@@ -5,5 +5,5 @@ | |
obj-$(CONFIG_ESSEDMA) += essedma.o | |
-essedma-objs := edma_axi.o edma.o edma_ethtool.o | |
+essedma-objs := edma_axi.o edma.o edma_ethtool.o edma_reset.o | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment