diff options
Diffstat (limited to 'drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c')
| -rw-r--r-- | drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 73 |
1 files changed, 51 insertions, 22 deletions
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c index f27fb6f2a93b..05b817e56fde 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 @@ | |||
| 21 | #include "xgene_enet_main.h" | 21 | #include "xgene_enet_main.h" |
| 22 | #include "xgene_enet_hw.h" | 22 | #include "xgene_enet_hw.h" |
| 23 | #include "xgene_enet_sgmac.h" | 23 | #include "xgene_enet_sgmac.h" |
| 24 | #include "xgene_enet_xgmac.h" | ||
| 24 | 25 | ||
| 25 | static void xgene_enet_wr_csr(struct xgene_enet_pdata *p, u32 offset, u32 val) | 26 | static void xgene_enet_wr_csr(struct xgene_enet_pdata *p, u32 offset, u32 val) |
| 26 | { | 27 | { |
| @@ -39,6 +40,14 @@ static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *p, | |||
| 39 | iowrite32(val, p->eth_diag_csr_addr + offset); | 40 | iowrite32(val, p->eth_diag_csr_addr + offset); |
| 40 | } | 41 | } |
| 41 | 42 | ||
| 43 | static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata, | ||
| 44 | u32 offset, u32 val) | ||
| 45 | { | ||
| 46 | void __iomem *addr = pdata->mcx_mac_csr_addr + offset; | ||
| 47 | |||
| 48 | iowrite32(val, addr); | ||
| 49 | } | ||
| 50 | |||
| 42 | static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl, | 51 | static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl, |
| 43 | u32 wr_addr, u32 wr_data) | 52 | u32 wr_addr, u32 wr_data) |
| 44 | { | 53 | { |
| @@ -140,8 +149,9 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *p) | |||
| 140 | 149 | ||
| 141 | static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p) | 150 | static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p) |
| 142 | { | 151 | { |
| 143 | u32 val = 0xffffffff; | 152 | u32 val; |
| 144 | 153 | ||
| 154 | val = (p->enet_id == XGENE_ENET1) ? 0xffffffff : 0; | ||
| 145 | xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQASSOC_ADDR, val); | 155 | xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQASSOC_ADDR, val); |
| 146 | xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPQASSOC_ADDR, val); | 156 | xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPQASSOC_ADDR, val); |
| 147 | } | 157 | } |
| @@ -227,6 +237,8 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p) | |||
| 227 | { | 237 | { |
| 228 | u32 data, loop = 10; | 238 | u32 data, loop = 10; |
| 229 | u32 offset = p->port_id * 4; | 239 | u32 offset = p->port_id * 4; |
| 240 | u32 enet_spare_cfg_reg, rsif_config_reg; | ||
| 241 | u32 cfg_bypass_reg, rx_dv_gate_reg; | ||
| 230 | 242 | ||
| 231 | xgene_sgmac_reset(p); | 243 | xgene_sgmac_reset(p); |
| 232 | 244 | ||
| @@ -239,7 +251,7 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p) | |||
| 239 | SGMII_STATUS_ADDR >> 2); | 251 | SGMII_STATUS_ADDR >> 2); |
| 240 | if ((data & AUTO_NEG_COMPLETE) && (data & LINK_STATUS)) | 252 | if ((data & AUTO_NEG_COMPLETE) && (data & LINK_STATUS)) |
| 241 | break; | 253 | break; |
| 242 | usleep_range(10, 20); | 254 | usleep_range(1000, 2000); |
| 243 | } | 255 | } |
| 244 | if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS)) | 256 | if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS)) |
| 245 | netdev_err(p->ndev, "Auto-negotiation failed\n"); | 257 | netdev_err(p->ndev, "Auto-negotiation failed\n"); |
| @@ -249,33 +261,38 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p) | |||
| 249 | xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2); | 261 | xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2); |
| 250 | xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE); | 262 | xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE); |
| 251 | 263 | ||
| 252 | data = xgene_enet_rd_csr(p, ENET_SPARE_CFG_REG_ADDR); | 264 | if (p->enet_id == XGENE_ENET1) { |
| 265 | enet_spare_cfg_reg = ENET_SPARE_CFG_REG_ADDR; | ||
| 266 | rsif_config_reg = RSIF_CONFIG_REG_ADDR; | ||
| 267 | cfg_bypass_reg = CFG_BYPASS_ADDR; | ||
| 268 | rx_dv_gate_reg = SG_RX_DV_GATE_REG_0_ADDR; | ||
| 269 | } else { | ||
| 270 | enet_spare_cfg_reg = XG_ENET_SPARE_CFG_REG_ADDR; | ||
| 271 | rsif_config_reg = XG_RSIF_CONFIG_REG_ADDR; | ||
| 272 | cfg_bypass_reg = XG_CFG_BYPASS_ADDR; | ||
| 273 | rx_dv_gate_reg = XG_MCX_RX_DV_GATE_REG_0_ADDR; | ||
| 274 | } | ||
| 275 | |||
| 276 | data = xgene_enet_rd_csr(p, enet_spare_cfg_reg); | ||
| 253 | data |= MPA_IDLE_WITH_QMI_EMPTY; | 277 | data |= MPA_IDLE_WITH_QMI_EMPTY; |
| 254 | xgene_enet_wr_csr(p, ENET_SPARE_CFG_REG_ADDR, data); | 278 | xgene_enet_wr_csr(p, enet_spare_cfg_reg, data); |
| 255 | 279 | ||
| 256 | xgene_sgmac_set_mac_addr(p); | 280 | xgene_sgmac_set_mac_addr(p); |
| 257 | 281 | ||
| 258 | data = xgene_enet_rd_csr(p, DEBUG_REG_ADDR); | ||
| 259 | data |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX; | ||
| 260 | xgene_enet_wr_csr(p, DEBUG_REG_ADDR, data); | ||
| 261 | |||
| 262 | /* Adjust MDC clock frequency */ | 282 | /* Adjust MDC clock frequency */ |
| 263 | data = xgene_enet_rd_mac(p, MII_MGMT_CONFIG_ADDR); | 283 | data = xgene_enet_rd_mac(p, MII_MGMT_CONFIG_ADDR); |
| 264 | MGMT_CLOCK_SEL_SET(&data, 7); | 284 | MGMT_CLOCK_SEL_SET(&data, 7); |
| 265 | xgene_enet_wr_mac(p, MII_MGMT_CONFIG_ADDR, data); | 285 | xgene_enet_wr_mac(p, MII_MGMT_CONFIG_ADDR, data); |
| 266 | 286 | ||
| 267 | /* Enable drop if bufpool not available */ | 287 | /* Enable drop if bufpool not available */ |
| 268 | data = xgene_enet_rd_csr(p, RSIF_CONFIG_REG_ADDR); | 288 | data = xgene_enet_rd_csr(p, rsif_config_reg); |
| 269 | data |= CFG_RSIF_FPBUFF_TIMEOUT_EN; | 289 | data |= CFG_RSIF_FPBUFF_TIMEOUT_EN; |
| 270 | xgene_enet_wr_csr(p, RSIF_CONFIG_REG_ADDR, data); | 290 | xgene_enet_wr_csr(p, rsif_config_reg, data); |
| 271 | |||
| 272 | /* Rtype should be copied from FP */ | ||
| 273 | xgene_enet_wr_csr(p, RSIF_RAM_DBG_REG0_ADDR, 0); | ||
| 274 | 291 | ||
| 275 | /* Bypass traffic gating */ | 292 | /* Bypass traffic gating */ |
| 276 | xgene_enet_wr_csr(p, CFG_LINK_AGGR_RESUME_0_ADDR + offset, TX_PORT0); | 293 | xgene_enet_wr_csr(p, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x84); |
| 277 | xgene_enet_wr_csr(p, CFG_BYPASS_ADDR, RESUME_TX); | 294 | xgene_enet_wr_csr(p, cfg_bypass_reg, RESUME_TX); |
| 278 | xgene_enet_wr_csr(p, SG_RX_DV_GATE_REG_0_ADDR + offset, RESUME_RX0); | 295 | xgene_enet_wr_mcx_csr(p, rx_dv_gate_reg + offset, RESUME_RX0); |
| 279 | } | 296 | } |
| 280 | 297 | ||
| 281 | static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set) | 298 | static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set) |
| @@ -317,9 +334,11 @@ static int xgene_enet_reset(struct xgene_enet_pdata *p) | |||
| 317 | if (!xgene_ring_mgr_init(p)) | 334 | if (!xgene_ring_mgr_init(p)) |
| 318 | return -ENODEV; | 335 | return -ENODEV; |
| 319 | 336 | ||
| 320 | clk_prepare_enable(p->clk); | 337 | if (!IS_ERR(p->clk)) { |
| 321 | clk_disable_unprepare(p->clk); | 338 | clk_prepare_enable(p->clk); |
| 322 | clk_prepare_enable(p->clk); | 339 | clk_disable_unprepare(p->clk); |
| 340 | clk_prepare_enable(p->clk); | ||
| 341 | } | ||
| 323 | 342 | ||
| 324 | xgene_enet_ecc_init(p); | 343 | xgene_enet_ecc_init(p); |
| 325 | xgene_enet_config_ring_if_assoc(p); | 344 | xgene_enet_config_ring_if_assoc(p); |
| @@ -331,19 +350,29 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p, | |||
| 331 | u32 dst_ring_num, u16 bufpool_id) | 350 | u32 dst_ring_num, u16 bufpool_id) |
| 332 | { | 351 | { |
| 333 | u32 data, fpsel; | 352 | u32 data, fpsel; |
| 353 | u32 cle_bypass_reg0, cle_bypass_reg1; | ||
| 334 | u32 offset = p->port_id * MAC_OFFSET; | 354 | u32 offset = p->port_id * MAC_OFFSET; |
| 335 | 355 | ||
| 356 | if (p->enet_id == XGENE_ENET1) { | ||
| 357 | cle_bypass_reg0 = CLE_BYPASS_REG0_0_ADDR; | ||
| 358 | cle_bypass_reg1 = CLE_BYPASS_REG1_0_ADDR; | ||
| 359 | } else { | ||
| 360 | cle_bypass_reg0 = XCLE_BYPASS_REG0_ADDR; | ||
| 361 | cle_bypass_reg1 = XCLE_BYPASS_REG1_ADDR; | ||
| 362 | } | ||
| 363 | |||
| 336 | data = CFG_CLE_BYPASS_EN0; | 364 | data = CFG_CLE_BYPASS_EN0; |
| 337 | xgene_enet_wr_csr(p, CLE_BYPASS_REG0_0_ADDR + offset, data); | 365 | xgene_enet_wr_csr(p, cle_bypass_reg0 + offset, data); |
| 338 | 366 | ||
| 339 | fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20; | 367 | fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20; |
| 340 | data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel); | 368 | data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel); |
| 341 | xgene_enet_wr_csr(p, CLE_BYPASS_REG1_0_ADDR + offset, data); | 369 | xgene_enet_wr_csr(p, cle_bypass_reg1 + offset, data); |
| 342 | } | 370 | } |
| 343 | 371 | ||
| 344 | static void xgene_enet_shutdown(struct xgene_enet_pdata *p) | 372 | static void xgene_enet_shutdown(struct xgene_enet_pdata *p) |
| 345 | { | 373 | { |
| 346 | clk_disable_unprepare(p->clk); | 374 | if (!IS_ERR(p->clk)) |
| 375 | clk_disable_unprepare(p->clk); | ||
| 347 | } | 376 | } |
| 348 | 377 | ||
| 349 | static void xgene_enet_link_state(struct work_struct *work) | 378 | static void xgene_enet_link_state(struct work_struct *work) |
