554 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*******************************************************************************3 This is the driver for the GMAC on-chip Ethernet controller for ST SoCs.4 DWC Ether MAC 10/100/1000 Universal version 3.41a has been used for5 developing this code.6 7 This only implements the mac core functions for this chip.8 9 Copyright (C) 2007-2009 STMicroelectronics Ltd10 11 12 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>13*******************************************************************************/14 15#include <linux/crc32.h>16#include <linux/slab.h>17#include <linux/ethtool.h>18#include <linux/io.h>19#include "stmmac.h"20#include "stmmac_pcs.h"21#include "dwmac1000.h"22 23static void dwmac1000_core_init(struct mac_device_info *hw,24 struct net_device *dev)25{26 void __iomem *ioaddr = hw->pcsr;27 u32 value = readl(ioaddr + GMAC_CONTROL);28 int mtu = dev->mtu;29 30 /* Configure GMAC core */31 value |= GMAC_CORE_INIT;32 33 if (mtu > 1500)34 value |= GMAC_CONTROL_2K;35 if (mtu > 2000)36 value |= GMAC_CONTROL_JE;37 38 if (hw->ps) {39 value |= GMAC_CONTROL_TE;40 41 value &= ~hw->link.speed_mask;42 switch (hw->ps) {43 case SPEED_1000:44 value |= hw->link.speed1000;45 break;46 case SPEED_100:47 value |= hw->link.speed100;48 break;49 case SPEED_10:50 value |= hw->link.speed10;51 break;52 }53 }54 55 writel(value, ioaddr + GMAC_CONTROL);56 57 /* Mask GMAC interrupts */58 value = GMAC_INT_DEFAULT_MASK;59 60 if (hw->pcs)61 value &= ~GMAC_INT_DISABLE_PCS;62 63 writel(value, ioaddr + GMAC_INT_MASK);64 65#ifdef STMMAC_VLAN_TAG_USED66 /* Tag detection without filtering */67 writel(0x0, ioaddr + GMAC_VLAN_TAG);68#endif69}70 71static int dwmac1000_rx_ipc_enable(struct mac_device_info *hw)72{73 void __iomem *ioaddr = hw->pcsr;74 u32 value = readl(ioaddr + GMAC_CONTROL);75 76 if (hw->rx_csum)77 value |= GMAC_CONTROL_IPC;78 else79 value &= ~GMAC_CONTROL_IPC;80 81 writel(value, ioaddr + GMAC_CONTROL);82 83 value = readl(ioaddr + GMAC_CONTROL);84 85 return !!(value & GMAC_CONTROL_IPC);86}87 88static void dwmac1000_dump_regs(struct mac_device_info *hw, u32 *reg_space)89{90 void __iomem *ioaddr = hw->pcsr;91 int i;92 93 for (i = 0; i < 55; i++)94 reg_space[i] = readl(ioaddr + i * 4);95}96 97static void dwmac1000_set_umac_addr(struct mac_device_info *hw,98 const unsigned char *addr,99 unsigned int reg_n)100{101 void __iomem *ioaddr = hw->pcsr;102 stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),103 GMAC_ADDR_LOW(reg_n));104}105 106static void dwmac1000_get_umac_addr(struct mac_device_info *hw,107 unsigned char *addr,108 unsigned int reg_n)109{110 void __iomem *ioaddr = hw->pcsr;111 stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),112 GMAC_ADDR_LOW(reg_n));113}114 115static void dwmac1000_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,116 int mcbitslog2)117{118 int numhashregs, regs;119 120 switch (mcbitslog2) {121 case 6:122 writel(mcfilterbits[0], ioaddr + GMAC_HASH_LOW);123 writel(mcfilterbits[1], ioaddr + GMAC_HASH_HIGH);124 return;125 case 7:126 numhashregs = 4;127 break;128 case 8:129 numhashregs = 8;130 break;131 default:132 pr_debug("STMMAC: err in setting multicast filter\n");133 return;134 }135 for (regs = 0; regs < numhashregs; regs++)136 writel(mcfilterbits[regs],137 ioaddr + GMAC_EXTHASH_BASE + regs * 4);138}139 140static void dwmac1000_set_filter(struct mac_device_info *hw,141 struct net_device *dev)142{143 void __iomem *ioaddr = (void __iomem *)dev->base_addr;144 unsigned int value = 0;145 unsigned int perfect_addr_number = hw->unicast_filter_entries;146 u32 mc_filter[8];147 int mcbitslog2 = hw->mcast_bits_log2;148 149 pr_debug("%s: # mcasts %d, # unicast %d\n", __func__,150 netdev_mc_count(dev), netdev_uc_count(dev));151 152 memset(mc_filter, 0, sizeof(mc_filter));153 154 if (dev->flags & IFF_PROMISC) {155 value = GMAC_FRAME_FILTER_PR | GMAC_FRAME_FILTER_PCF;156 } else if (dev->flags & IFF_ALLMULTI) {157 value = GMAC_FRAME_FILTER_PM; /* pass all multi */158 } else if (!netdev_mc_empty(dev) && (mcbitslog2 == 0)) {159 /* Fall back to all multicast if we've no filter */160 value = GMAC_FRAME_FILTER_PM;161 } else if (!netdev_mc_empty(dev)) {162 struct netdev_hw_addr *ha;163 164 /* Hash filter for multicast */165 value = GMAC_FRAME_FILTER_HMC;166 167 netdev_for_each_mc_addr(ha, dev) {168 /* The upper n bits of the calculated CRC are used to169 * index the contents of the hash table. The number of170 * bits used depends on the hardware configuration171 * selected at core configuration time.172 */173 int bit_nr = bitrev32(~crc32_le(~0, ha->addr,174 ETH_ALEN)) >>175 (32 - mcbitslog2);176 /* The most significant bit determines the register to177 * use (H/L) while the other 5 bits determine the bit178 * within the register.179 */180 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);181 }182 }183 184 value |= GMAC_FRAME_FILTER_HPF;185 dwmac1000_set_mchash(ioaddr, mc_filter, mcbitslog2);186 187 /* Handle multiple unicast addresses (perfect filtering) */188 if (netdev_uc_count(dev) > perfect_addr_number)189 /* Switch to promiscuous mode if more than unicast190 * addresses are requested than supported by hardware.191 */192 value |= GMAC_FRAME_FILTER_PR;193 else {194 int reg = 1;195 struct netdev_hw_addr *ha;196 197 netdev_for_each_uc_addr(ha, dev) {198 stmmac_set_mac_addr(ioaddr, ha->addr,199 GMAC_ADDR_HIGH(reg),200 GMAC_ADDR_LOW(reg));201 reg++;202 }203 204 while (reg < perfect_addr_number) {205 writel(0, ioaddr + GMAC_ADDR_HIGH(reg));206 writel(0, ioaddr + GMAC_ADDR_LOW(reg));207 reg++;208 }209 }210 211#ifdef FRAME_FILTER_DEBUG212 /* Enable Receive all mode (to debug filtering_fail errors) */213 value |= GMAC_FRAME_FILTER_RA;214#endif215 writel(value, ioaddr + GMAC_FRAME_FILTER);216}217 218 219static void dwmac1000_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,220 unsigned int fc, unsigned int pause_time,221 u32 tx_cnt)222{223 void __iomem *ioaddr = hw->pcsr;224 /* Set flow such that DZPQ in Mac Register 6 is 0,225 * and unicast pause detect is enabled.226 */227 unsigned int flow = GMAC_FLOW_CTRL_UP;228 229 pr_debug("GMAC Flow-Control:\n");230 if (fc & FLOW_RX) {231 pr_debug("\tReceive Flow-Control ON\n");232 flow |= GMAC_FLOW_CTRL_RFE;233 }234 if (fc & FLOW_TX) {235 pr_debug("\tTransmit Flow-Control ON\n");236 flow |= GMAC_FLOW_CTRL_TFE;237 }238 239 if (duplex) {240 pr_debug("\tduplex mode: PAUSE %d\n", pause_time);241 flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT);242 }243 244 writel(flow, ioaddr + GMAC_FLOW_CTRL);245}246 247static void dwmac1000_pmt(struct mac_device_info *hw, unsigned long mode)248{249 void __iomem *ioaddr = hw->pcsr;250 unsigned int pmt = 0;251 252 if (mode & WAKE_MAGIC) {253 pr_debug("GMAC: WOL Magic frame\n");254 pmt |= power_down | magic_pkt_en;255 }256 if (mode & WAKE_UCAST) {257 pr_debug("GMAC: WOL on global unicast\n");258 pmt |= power_down | global_unicast | wake_up_frame_en;259 }260 261 writel(pmt, ioaddr + GMAC_PMT);262}263 264/* RGMII or SMII interface */265static void dwmac1000_rgsmii(void __iomem *ioaddr, struct stmmac_extra_stats *x)266{267 u32 status;268 269 status = readl(ioaddr + GMAC_RGSMIIIS);270 x->irq_rgmii_n++;271 272 /* Check the link status */273 if (status & GMAC_RGSMIIIS_LNKSTS) {274 int speed_value;275 276 x->pcs_link = 1;277 278 speed_value = ((status & GMAC_RGSMIIIS_SPEED) >>279 GMAC_RGSMIIIS_SPEED_SHIFT);280 if (speed_value == GMAC_RGSMIIIS_SPEED_125)281 x->pcs_speed = SPEED_1000;282 else if (speed_value == GMAC_RGSMIIIS_SPEED_25)283 x->pcs_speed = SPEED_100;284 else285 x->pcs_speed = SPEED_10;286 287 x->pcs_duplex = (status & GMAC_RGSMIIIS_LNKMOD_MASK);288 289 pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed,290 x->pcs_duplex ? "Full" : "Half");291 } else {292 x->pcs_link = 0;293 pr_info("Link is Down\n");294 }295}296 297static int dwmac1000_irq_status(struct mac_device_info *hw,298 struct stmmac_extra_stats *x)299{300 void __iomem *ioaddr = hw->pcsr;301 u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);302 u32 intr_mask = readl(ioaddr + GMAC_INT_MASK);303 int ret = 0;304 305 /* Discard masked bits */306 intr_status &= ~intr_mask;307 308 /* Not used events (e.g. MMC interrupts) are not handled. */309 if ((intr_status & GMAC_INT_STATUS_MMCTIS))310 x->mmc_tx_irq_n++;311 if (unlikely(intr_status & GMAC_INT_STATUS_MMCRIS))312 x->mmc_rx_irq_n++;313 if (unlikely(intr_status & GMAC_INT_STATUS_MMCCSUM))314 x->mmc_rx_csum_offload_irq_n++;315 if (unlikely(intr_status & GMAC_INT_DISABLE_PMT)) {316 /* clear the PMT bits 5 and 6 by reading the PMT status reg */317 readl(ioaddr + GMAC_PMT);318 x->irq_receive_pmt_irq_n++;319 }320 321 /* MAC tx/rx EEE LPI entry/exit interrupts */322 if (intr_status & GMAC_INT_STATUS_LPIIS) {323 /* Clean LPI interrupt by reading the Reg 12 */324 ret = readl(ioaddr + LPI_CTRL_STATUS);325 326 if (ret & LPI_CTRL_STATUS_TLPIEN)327 x->irq_tx_path_in_lpi_mode_n++;328 if (ret & LPI_CTRL_STATUS_TLPIEX)329 x->irq_tx_path_exit_lpi_mode_n++;330 if (ret & LPI_CTRL_STATUS_RLPIEN)331 x->irq_rx_path_in_lpi_mode_n++;332 if (ret & LPI_CTRL_STATUS_RLPIEX)333 x->irq_rx_path_exit_lpi_mode_n++;334 }335 336 dwmac_pcs_isr(ioaddr, GMAC_PCS_BASE, intr_status, x);337 338 if (intr_status & PCS_RGSMIIIS_IRQ)339 dwmac1000_rgsmii(ioaddr, x);340 341 return ret;342}343 344static void dwmac1000_set_eee_mode(struct mac_device_info *hw,345 bool en_tx_lpi_clockgating)346{347 void __iomem *ioaddr = hw->pcsr;348 u32 value;349 350 /*TODO - en_tx_lpi_clockgating treatment */351 352 /* Enable the link status receive on RGMII, SGMII ore SMII353 * receive path and instruct the transmit to enter in LPI354 * state.355 */356 value = readl(ioaddr + LPI_CTRL_STATUS);357 value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;358 writel(value, ioaddr + LPI_CTRL_STATUS);359}360 361static void dwmac1000_reset_eee_mode(struct mac_device_info *hw)362{363 void __iomem *ioaddr = hw->pcsr;364 u32 value;365 366 value = readl(ioaddr + LPI_CTRL_STATUS);367 value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);368 writel(value, ioaddr + LPI_CTRL_STATUS);369}370 371static void dwmac1000_set_eee_pls(struct mac_device_info *hw, int link)372{373 void __iomem *ioaddr = hw->pcsr;374 u32 value;375 376 value = readl(ioaddr + LPI_CTRL_STATUS);377 378 if (link)379 value |= LPI_CTRL_STATUS_PLS;380 else381 value &= ~LPI_CTRL_STATUS_PLS;382 383 writel(value, ioaddr + LPI_CTRL_STATUS);384}385 386static void dwmac1000_set_eee_timer(struct mac_device_info *hw, int ls, int tw)387{388 void __iomem *ioaddr = hw->pcsr;389 int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);390 391 /* Program the timers in the LPI timer control register:392 * LS: minimum time (ms) for which the link393 * status from PHY should be ok before transmitting394 * the LPI pattern.395 * TW: minimum time (us) for which the core waits396 * after it has stopped transmitting the LPI pattern.397 */398 writel(value, ioaddr + LPI_TIMER_CTRL);399}400 401static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool ane, bool srgmi_ral,402 bool loopback)403{404 dwmac_ctrl_ane(ioaddr, GMAC_PCS_BASE, ane, srgmi_ral, loopback);405}406 407static void dwmac1000_get_adv_lp(void __iomem *ioaddr, struct rgmii_adv *adv)408{409 dwmac_get_adv_lp(ioaddr, GMAC_PCS_BASE, adv);410}411 412static void dwmac1000_debug(struct stmmac_priv *priv, void __iomem *ioaddr,413 struct stmmac_extra_stats *x,414 u32 rx_queues, u32 tx_queues)415{416 u32 value = readl(ioaddr + GMAC_DEBUG);417 418 if (value & GMAC_DEBUG_TXSTSFSTS)419 x->mtl_tx_status_fifo_full++;420 if (value & GMAC_DEBUG_TXFSTS)421 x->mtl_tx_fifo_not_empty++;422 if (value & GMAC_DEBUG_TWCSTS)423 x->mmtl_fifo_ctrl++;424 if (value & GMAC_DEBUG_TRCSTS_MASK) {425 u32 trcsts = (value & GMAC_DEBUG_TRCSTS_MASK)426 >> GMAC_DEBUG_TRCSTS_SHIFT;427 if (trcsts == GMAC_DEBUG_TRCSTS_WRITE)428 x->mtl_tx_fifo_read_ctrl_write++;429 else if (trcsts == GMAC_DEBUG_TRCSTS_TXW)430 x->mtl_tx_fifo_read_ctrl_wait++;431 else if (trcsts == GMAC_DEBUG_TRCSTS_READ)432 x->mtl_tx_fifo_read_ctrl_read++;433 else434 x->mtl_tx_fifo_read_ctrl_idle++;435 }436 if (value & GMAC_DEBUG_TXPAUSED)437 x->mac_tx_in_pause++;438 if (value & GMAC_DEBUG_TFCSTS_MASK) {439 u32 tfcsts = (value & GMAC_DEBUG_TFCSTS_MASK)440 >> GMAC_DEBUG_TFCSTS_SHIFT;441 442 if (tfcsts == GMAC_DEBUG_TFCSTS_XFER)443 x->mac_tx_frame_ctrl_xfer++;444 else if (tfcsts == GMAC_DEBUG_TFCSTS_GEN_PAUSE)445 x->mac_tx_frame_ctrl_pause++;446 else if (tfcsts == GMAC_DEBUG_TFCSTS_WAIT)447 x->mac_tx_frame_ctrl_wait++;448 else449 x->mac_tx_frame_ctrl_idle++;450 }451 if (value & GMAC_DEBUG_TPESTS)452 x->mac_gmii_tx_proto_engine++;453 if (value & GMAC_DEBUG_RXFSTS_MASK) {454 u32 rxfsts = (value & GMAC_DEBUG_RXFSTS_MASK)455 >> GMAC_DEBUG_RRCSTS_SHIFT;456 457 if (rxfsts == GMAC_DEBUG_RXFSTS_FULL)458 x->mtl_rx_fifo_fill_level_full++;459 else if (rxfsts == GMAC_DEBUG_RXFSTS_AT)460 x->mtl_rx_fifo_fill_above_thresh++;461 else if (rxfsts == GMAC_DEBUG_RXFSTS_BT)462 x->mtl_rx_fifo_fill_below_thresh++;463 else464 x->mtl_rx_fifo_fill_level_empty++;465 }466 if (value & GMAC_DEBUG_RRCSTS_MASK) {467 u32 rrcsts = (value & GMAC_DEBUG_RRCSTS_MASK) >>468 GMAC_DEBUG_RRCSTS_SHIFT;469 470 if (rrcsts == GMAC_DEBUG_RRCSTS_FLUSH)471 x->mtl_rx_fifo_read_ctrl_flush++;472 else if (rrcsts == GMAC_DEBUG_RRCSTS_RSTAT)473 x->mtl_rx_fifo_read_ctrl_read_data++;474 else if (rrcsts == GMAC_DEBUG_RRCSTS_RDATA)475 x->mtl_rx_fifo_read_ctrl_status++;476 else477 x->mtl_rx_fifo_read_ctrl_idle++;478 }479 if (value & GMAC_DEBUG_RWCSTS)480 x->mtl_rx_fifo_ctrl_active++;481 if (value & GMAC_DEBUG_RFCFCSTS_MASK)482 x->mac_rx_frame_ctrl_fifo = (value & GMAC_DEBUG_RFCFCSTS_MASK)483 >> GMAC_DEBUG_RFCFCSTS_SHIFT;484 if (value & GMAC_DEBUG_RPESTS)485 x->mac_gmii_rx_proto_engine++;486}487 488static void dwmac1000_set_mac_loopback(void __iomem *ioaddr, bool enable)489{490 u32 value = readl(ioaddr + GMAC_CONTROL);491 492 if (enable)493 value |= GMAC_CONTROL_LM;494 else495 value &= ~GMAC_CONTROL_LM;496 497 writel(value, ioaddr + GMAC_CONTROL);498}499 500const struct stmmac_ops dwmac1000_ops = {501 .core_init = dwmac1000_core_init,502 .set_mac = stmmac_set_mac,503 .rx_ipc = dwmac1000_rx_ipc_enable,504 .dump_regs = dwmac1000_dump_regs,505 .host_irq_status = dwmac1000_irq_status,506 .set_filter = dwmac1000_set_filter,507 .flow_ctrl = dwmac1000_flow_ctrl,508 .pmt = dwmac1000_pmt,509 .set_umac_addr = dwmac1000_set_umac_addr,510 .get_umac_addr = dwmac1000_get_umac_addr,511 .set_eee_mode = dwmac1000_set_eee_mode,512 .reset_eee_mode = dwmac1000_reset_eee_mode,513 .set_eee_timer = dwmac1000_set_eee_timer,514 .set_eee_pls = dwmac1000_set_eee_pls,515 .debug = dwmac1000_debug,516 .pcs_ctrl_ane = dwmac1000_ctrl_ane,517 .pcs_get_adv_lp = dwmac1000_get_adv_lp,518 .set_mac_loopback = dwmac1000_set_mac_loopback,519};520 521int dwmac1000_setup(struct stmmac_priv *priv)522{523 struct mac_device_info *mac = priv->hw;524 525 dev_info(priv->device, "\tDWMAC1000\n");526 527 priv->dev->priv_flags |= IFF_UNICAST_FLT;528 mac->pcsr = priv->ioaddr;529 mac->multicast_filter_bins = priv->plat->multicast_filter_bins;530 mac->unicast_filter_entries = priv->plat->unicast_filter_entries;531 mac->mcast_bits_log2 = 0;532 533 if (mac->multicast_filter_bins)534 mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);535 536 mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |537 MAC_10 | MAC_100 | MAC_1000;538 mac->link.duplex = GMAC_CONTROL_DM;539 mac->link.speed10 = GMAC_CONTROL_PS;540 mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;541 mac->link.speed1000 = 0;542 mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;543 mac->mii.addr = GMAC_MII_ADDR;544 mac->mii.data = GMAC_MII_DATA;545 mac->mii.addr_shift = 11;546 mac->mii.addr_mask = 0x0000F800;547 mac->mii.reg_shift = 6;548 mac->mii.reg_mask = 0x000007C0;549 mac->mii.clk_csr_shift = 2;550 mac->mii.clk_csr_mask = GENMASK(5, 2);551 552 return 0;553}554