drivers: net: xgene: Add SGMII based 1GbE support with ring manager v2

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Iyappan Subramanian 2015-04-28 13:52:40 -07:00 committed by David S. Miller
parent bc1b7c132a
commit 561fea6dea
5 changed files with 68 additions and 29 deletions

View File

@ -104,7 +104,6 @@ enum xgene_enet_rm {
#define BLOCK_ETH_RING_IF_OFFSET 0x9000 #define BLOCK_ETH_RING_IF_OFFSET 0x9000
#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000 #define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000
#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000 #define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
#define BLOCK_ETH_MAC_OFFSET 0x0000 #define BLOCK_ETH_MAC_OFFSET 0x0000
#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800 #define BLOCK_ETH_MAC_CSR_OFFSET 0x2800

View File

@ -876,14 +876,21 @@ static int xgene_get_port_id(struct device *dev, struct xgene_enet_pdata *pdata)
int ret; int ret;
ret = device_property_read_u32(dev, "port-id", &id); ret = device_property_read_u32(dev, "port-id", &id);
if (!ret && id > 1) {
dev_err(dev, "Incorrect port-id specified\n"); switch (ret) {
return -ENODEV; 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 ret;
return 0;
} }
static int xgene_get_mac_address(struct device *dev, 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 device *dev;
struct resource *res; struct resource *res;
void __iomem *base_addr; void __iomem *base_addr;
u32 offset;
int ret; int ret;
pdev = pdata->pdev; 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 || if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) { pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
pdata->mcx_mac_addr = pdata->base_addr + BLOCK_ETH_MAC_OFFSET; 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 { } else {
pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET; pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET;
pdata->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_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,xgene-enet", .data = (void *)XGENE_ENET1},
{.compatible = "apm,xgene1-sgenet", .data = (void *)XGENE_ENET1}, {.compatible = "apm,xgene1-sgenet", .data = (void *)XGENE_ENET1},
{.compatible = "apm,xgene1-xgenet", .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}, {.compatible = "apm,xgene2-xgenet", .data = (void *)XGENE_ENET2},
{}, {},
}; };

View File

@ -56,7 +56,6 @@
#define X2_START_ETH_BUFNUM_0 0 #define X2_START_ETH_BUFNUM_0 0
#define X2_START_BP_BUFNUM_0 0x20 #define X2_START_BP_BUFNUM_0 0x20
#define X2_START_RING_NUM_0 0 #define X2_START_RING_NUM_0 0
#define X2_START_CPU_BUFNUM_1 0xc #define X2_START_CPU_BUFNUM_1 0xc
#define X2_START_ETH_BUFNUM_1 0 #define X2_START_ETH_BUFNUM_1 0
#define X2_START_BP_BUFNUM_1 0x20 #define X2_START_BP_BUFNUM_1 0x20

View File

@ -21,6 +21,7 @@
#include "xgene_enet_main.h" #include "xgene_enet_main.h"
#include "xgene_enet_hw.h" #include "xgene_enet_hw.h"
#include "xgene_enet_sgmac.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) 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); 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, static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl,
u32 wr_addr, u32 wr_data) 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) 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_CFGSSQMIWQASSOC_ADDR, val);
xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPQASSOC_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 data, loop = 10;
u32 offset = p->port_id * 4; 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); xgene_sgmac_reset(p);
@ -239,7 +251,7 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
SGMII_STATUS_ADDR >> 2); SGMII_STATUS_ADDR >> 2);
if ((data & AUTO_NEG_COMPLETE) && (data & LINK_STATUS)) if ((data & AUTO_NEG_COMPLETE) && (data & LINK_STATUS))
break; break;
usleep_range(10, 20); usleep_range(1000, 2000);
} }
if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS)) if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS))
netdev_err(p->ndev, "Auto-negotiation failed\n"); 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, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2);
xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE); 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; 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); 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 */ /* Adjust MDC clock frequency */
data = xgene_enet_rd_mac(p, MII_MGMT_CONFIG_ADDR); data = xgene_enet_rd_mac(p, MII_MGMT_CONFIG_ADDR);
MGMT_CLOCK_SEL_SET(&data, 7); MGMT_CLOCK_SEL_SET(&data, 7);
xgene_enet_wr_mac(p, MII_MGMT_CONFIG_ADDR, data); xgene_enet_wr_mac(p, MII_MGMT_CONFIG_ADDR, data);
/* Enable drop if bufpool not available */ /* 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; data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
xgene_enet_wr_csr(p, RSIF_CONFIG_REG_ADDR, data); xgene_enet_wr_csr(p, rsif_config_reg, data);
/* Rtype should be copied from FP */
xgene_enet_wr_csr(p, RSIF_RAM_DBG_REG0_ADDR, 0);
/* Bypass traffic gating */ /* Bypass traffic gating */
xgene_enet_wr_csr(p, CFG_LINK_AGGR_RESUME_0_ADDR + offset, TX_PORT0); xgene_enet_wr_csr(p, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x84);
xgene_enet_wr_csr(p, CFG_BYPASS_ADDR, RESUME_TX); xgene_enet_wr_csr(p, cfg_bypass_reg, RESUME_TX);
xgene_enet_wr_csr(p, SG_RX_DV_GATE_REG_0_ADDR + offset, RESUME_RX0); 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) 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 dst_ring_num, u16 bufpool_id)
{ {
u32 data, fpsel; u32 data, fpsel;
u32 cle_bypass_reg0, cle_bypass_reg1;
u32 offset = p->port_id * MAC_OFFSET; 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; 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; fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel); 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) static void xgene_enet_shutdown(struct xgene_enet_pdata *p)

View File

@ -21,11 +21,13 @@
#ifndef __XGENE_ENET_XGMAC_H__ #ifndef __XGENE_ENET_XGMAC_H__
#define __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_OFFSET 0x0800
#define BLOCK_AXG_MAC_CSR_OFFSET 0x2000 #define BLOCK_AXG_MAC_CSR_OFFSET 0x2000
#define XGENET_SRST_ADDR 0x0000 #define XGENET_CONFIG_REG_ADDR 0x20
#define XGENET_CLKEN_ADDR 0x0008 #define XGENET_SRST_ADDR 0x00
#define XGENET_CLKEN_ADDR 0x08
#define CSR_CLK BIT(0) #define CSR_CLK BIT(0)
#define XGENET_CLK BIT(1) #define XGENET_CLK BIT(1)
@ -55,6 +57,7 @@
#define HSTMACADR_MSW_ADDR 0x0014 #define HSTMACADR_MSW_ADDR 0x0014
#define HSTMAXFRAME_LENGTH_ADDR 0x0020 #define HSTMAXFRAME_LENGTH_ADDR 0x0020
#define XG_MCX_RX_DV_GATE_REG_0_ADDR 0x0004
#define XG_RSIF_CONFIG_REG_ADDR 0x00a0 #define XG_RSIF_CONFIG_REG_ADDR 0x00a0
#define XCLE_BYPASS_REG0_ADDR 0x0160 #define XCLE_BYPASS_REG0_ADDR 0x0160
#define XCLE_BYPASS_REG1_ADDR 0x0164 #define XCLE_BYPASS_REG1_ADDR 0x0164