From 561fea6deacf72b2d42a777c07bcb930ebdebb3c Mon Sep 17 00:00:00 2001 From: Iyappan Subramanian Date: Tue, 28 Apr 2015 13:52:40 -0700 Subject: [PATCH] drivers: net: xgene: Add SGMII based 1GbE support with ring manager v2 Signed-off-by: Iyappan Subramanian Signed-off-by: David S. Miller --- .../net/ethernet/apm/xgene/xgene_enet_hw.h | 1 - .../net/ethernet/apm/xgene/xgene_enet_main.c | 26 +++++--- .../net/ethernet/apm/xgene/xgene_enet_main.h | 1 - .../net/ethernet/apm/xgene/xgene_enet_sgmac.c | 62 +++++++++++++------ .../net/ethernet/apm/xgene/xgene_enet_xgmac.h | 7 ++- 5 files changed, 68 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h index 5176fcb9f413..541bed056012 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h @@ -104,7 +104,6 @@ enum xgene_enet_rm { #define BLOCK_ETH_RING_IF_OFFSET 0x9000 #define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000 #define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000 - #define BLOCK_ETH_MAC_OFFSET 0x0000 #define BLOCK_ETH_MAC_CSR_OFFSET 0x2800 diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 513bfa4fb790..735d7c6e5686 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -876,14 +876,21 @@ static int xgene_get_port_id(struct device *dev, struct xgene_enet_pdata *pdata) int ret; ret = device_property_read_u32(dev, "port-id", &id); - if (!ret && id > 1) { - dev_err(dev, "Incorrect port-id specified\n"); - return -ENODEV; + + switch (ret) { + case -EINVAL: + pdata->port_id = 0; + ret = 0; + break; + case 0: + pdata->port_id = id & BIT(0); + break; + default: + dev_err(dev, "Incorrect port-id specified: errno: %d\n", ret); + break; } - pdata->port_id = id; - - return 0; + return ret; } static int xgene_get_mac_address(struct device *dev, @@ -928,6 +935,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) struct device *dev; struct resource *res; void __iomem *base_addr; + u32 offset; int ret; pdev = pdata->pdev; @@ -1024,7 +1032,10 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII || pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) { pdata->mcx_mac_addr = pdata->base_addr + BLOCK_ETH_MAC_OFFSET; - pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET; + offset = (pdata->enet_id == XGENE_ENET1) ? + BLOCK_ETH_MAC_CSR_OFFSET : + X2_BLOCK_ETH_MAC_CSR_OFFSET; + pdata->mcx_mac_csr_addr = base_addr + offset; } else { pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET; pdata->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_OFFSET; @@ -1266,6 +1277,7 @@ static const struct of_device_id xgene_enet_of_match[] = { {.compatible = "apm,xgene-enet", .data = (void *)XGENE_ENET1}, {.compatible = "apm,xgene1-sgenet", .data = (void *)XGENE_ENET1}, {.compatible = "apm,xgene1-xgenet", .data = (void *)XGENE_ENET1}, + {.compatible = "apm,xgene2-sgenet", .data = (void *)XGENE_ENET2}, {.compatible = "apm,xgene2-xgenet", .data = (void *)XGENE_ENET2}, {}, }; diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h index ef1887be9428..19a042728f28 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h @@ -56,7 +56,6 @@ #define X2_START_ETH_BUFNUM_0 0 #define X2_START_BP_BUFNUM_0 0x20 #define X2_START_RING_NUM_0 0 - #define X2_START_CPU_BUFNUM_1 0xc #define X2_START_ETH_BUFNUM_1 0 #define X2_START_BP_BUFNUM_1 0x20 diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c index f27fb6f2a93b..ff240b3cb2b8 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c @@ -21,6 +21,7 @@ #include "xgene_enet_main.h" #include "xgene_enet_hw.h" #include "xgene_enet_sgmac.h" +#include "xgene_enet_xgmac.h" static void xgene_enet_wr_csr(struct xgene_enet_pdata *p, u32 offset, u32 val) { @@ -39,6 +40,14 @@ static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *p, iowrite32(val, p->eth_diag_csr_addr + offset); } +static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata, + u32 offset, u32 val) +{ + void __iomem *addr = pdata->mcx_mac_csr_addr + offset; + + iowrite32(val, addr); +} + static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl, u32 wr_addr, u32 wr_data) { @@ -140,8 +149,9 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *p) static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p) { - u32 val = 0xffffffff; + u32 val; + val = (p->enet_id == XGENE_ENET1) ? 0xffffffff : 0; xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQASSOC_ADDR, val); xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPQASSOC_ADDR, val); } @@ -227,6 +237,8 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p) { u32 data, loop = 10; u32 offset = p->port_id * 4; + u32 enet_spare_cfg_reg, rsif_config_reg; + u32 cfg_bypass_reg, rx_dv_gate_reg; xgene_sgmac_reset(p); @@ -239,7 +251,7 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p) SGMII_STATUS_ADDR >> 2); if ((data & AUTO_NEG_COMPLETE) && (data & LINK_STATUS)) break; - usleep_range(10, 20); + usleep_range(1000, 2000); } if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS)) netdev_err(p->ndev, "Auto-negotiation failed\n"); @@ -249,33 +261,38 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p) xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2); xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE); - data = xgene_enet_rd_csr(p, ENET_SPARE_CFG_REG_ADDR); + if (p->enet_id == XGENE_ENET1) { + enet_spare_cfg_reg = ENET_SPARE_CFG_REG_ADDR; + rsif_config_reg = RSIF_CONFIG_REG_ADDR; + cfg_bypass_reg = CFG_BYPASS_ADDR; + rx_dv_gate_reg = SG_RX_DV_GATE_REG_0_ADDR; + } else { + enet_spare_cfg_reg = XG_ENET_SPARE_CFG_REG_ADDR; + rsif_config_reg = XG_RSIF_CONFIG_REG_ADDR; + cfg_bypass_reg = XG_CFG_BYPASS_ADDR; + rx_dv_gate_reg = XG_MCX_RX_DV_GATE_REG_0_ADDR; + } + + data = xgene_enet_rd_csr(p, enet_spare_cfg_reg); data |= MPA_IDLE_WITH_QMI_EMPTY; - xgene_enet_wr_csr(p, ENET_SPARE_CFG_REG_ADDR, data); + xgene_enet_wr_csr(p, enet_spare_cfg_reg, data); xgene_sgmac_set_mac_addr(p); - data = xgene_enet_rd_csr(p, DEBUG_REG_ADDR); - data |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX; - xgene_enet_wr_csr(p, DEBUG_REG_ADDR, data); - /* Adjust MDC clock frequency */ data = xgene_enet_rd_mac(p, MII_MGMT_CONFIG_ADDR); MGMT_CLOCK_SEL_SET(&data, 7); xgene_enet_wr_mac(p, MII_MGMT_CONFIG_ADDR, data); /* Enable drop if bufpool not available */ - data = xgene_enet_rd_csr(p, RSIF_CONFIG_REG_ADDR); + data = xgene_enet_rd_csr(p, rsif_config_reg); data |= CFG_RSIF_FPBUFF_TIMEOUT_EN; - xgene_enet_wr_csr(p, RSIF_CONFIG_REG_ADDR, data); - - /* Rtype should be copied from FP */ - xgene_enet_wr_csr(p, RSIF_RAM_DBG_REG0_ADDR, 0); + xgene_enet_wr_csr(p, rsif_config_reg, data); /* Bypass traffic gating */ - xgene_enet_wr_csr(p, CFG_LINK_AGGR_RESUME_0_ADDR + offset, TX_PORT0); - xgene_enet_wr_csr(p, CFG_BYPASS_ADDR, RESUME_TX); - xgene_enet_wr_csr(p, SG_RX_DV_GATE_REG_0_ADDR + offset, RESUME_RX0); + xgene_enet_wr_csr(p, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x84); + xgene_enet_wr_csr(p, cfg_bypass_reg, RESUME_TX); + xgene_enet_wr_mcx_csr(p, rx_dv_gate_reg + offset, RESUME_RX0); } static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set) @@ -331,14 +348,23 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p, u32 dst_ring_num, u16 bufpool_id) { u32 data, fpsel; + u32 cle_bypass_reg0, cle_bypass_reg1; u32 offset = p->port_id * MAC_OFFSET; + if (p->enet_id == XGENE_ENET1) { + cle_bypass_reg0 = CLE_BYPASS_REG0_0_ADDR; + cle_bypass_reg1 = CLE_BYPASS_REG1_0_ADDR; + } else { + cle_bypass_reg0 = XCLE_BYPASS_REG0_ADDR; + cle_bypass_reg1 = XCLE_BYPASS_REG1_ADDR; + } + data = CFG_CLE_BYPASS_EN0; - xgene_enet_wr_csr(p, CLE_BYPASS_REG0_0_ADDR + offset, data); + xgene_enet_wr_csr(p, cle_bypass_reg0 + offset, data); fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20; data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel); - xgene_enet_wr_csr(p, CLE_BYPASS_REG1_0_ADDR + offset, data); + xgene_enet_wr_csr(p, cle_bypass_reg1 + offset, data); } static void xgene_enet_shutdown(struct xgene_enet_pdata *p) diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h index d07ee5ea3046..bf0a99435737 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h @@ -21,11 +21,13 @@ #ifndef __XGENE_ENET_XGMAC_H__ #define __XGENE_ENET_XGMAC_H__ +#define X2_BLOCK_ETH_MAC_CSR_OFFSET 0x3000 #define BLOCK_AXG_MAC_OFFSET 0x0800 #define BLOCK_AXG_MAC_CSR_OFFSET 0x2000 -#define XGENET_SRST_ADDR 0x0000 -#define XGENET_CLKEN_ADDR 0x0008 +#define XGENET_CONFIG_REG_ADDR 0x20 +#define XGENET_SRST_ADDR 0x00 +#define XGENET_CLKEN_ADDR 0x08 #define CSR_CLK BIT(0) #define XGENET_CLK BIT(1) @@ -55,6 +57,7 @@ #define HSTMACADR_MSW_ADDR 0x0014 #define HSTMAXFRAME_LENGTH_ADDR 0x0020 +#define XG_MCX_RX_DV_GATE_REG_0_ADDR 0x0004 #define XG_RSIF_CONFIG_REG_ADDR 0x00a0 #define XCLE_BYPASS_REG0_ADDR 0x0160 #define XCLE_BYPASS_REG1_ADDR 0x0164