1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2007-2015 STMicroelectronics Ltd 4 * 5 * Author: Alexandre Torgue <alexandre.torgue@st.com> 6 */ 7 8 #include <linux/io.h> 9 #include <linux/iopoll.h> 10 #include <linux/delay.h> 11 #include "common.h" 12 #include "dwmac4_dma.h" 13 #include "dwmac4.h" 14 #include "stmmac.h" 15 16 int dwmac4_dma_reset(void __iomem *ioaddr) 17 { 18 u32 value = readl(ioaddr + DMA_BUS_MODE); 19 20 /* DMA SW reset */ 21 value |= DMA_BUS_MODE_SFT_RESET; 22 writel(value, ioaddr + DMA_BUS_MODE); 23 24 return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value, 25 !(value & DMA_BUS_MODE_SFT_RESET), 26 10000, 1000000); 27 } 28 29 void dwmac4_set_rx_tail_ptr(struct stmmac_priv *priv, void __iomem *ioaddr, 30 u32 tail_ptr, u32 chan) 31 { 32 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 33 34 writel(tail_ptr, ioaddr + DMA_CHAN_RX_END_ADDR(dwmac4_addrs, chan)); 35 } 36 37 void dwmac4_set_tx_tail_ptr(struct stmmac_priv *priv, void __iomem *ioaddr, 38 u32 tail_ptr, u32 chan) 39 { 40 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 41 42 writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(dwmac4_addrs, chan)); 43 } 44 45 void dwmac4_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr, 46 u32 chan) 47 { 48 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 49 u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan)); 50 51 value |= DMA_CONTROL_ST; 52 writel(value, ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan)); 53 54 value = readl(ioaddr + GMAC_CONFIG); 55 value |= GMAC_CONFIG_TE; 56 writel(value, ioaddr + GMAC_CONFIG); 57 } 58 59 void dwmac4_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, 60 u32 chan) 61 { 62 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 63 64 u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan)); 65 66 value &= ~DMA_CONTROL_ST; 67 writel(value, ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan)); 68 } 69 70 void dwmac4_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr, 71 u32 chan) 72 { 73 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 74 75 u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan)); 76 77 value |= DMA_CONTROL_SR; 78 79 writel(value, ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan)); 80 81 value = readl(ioaddr + GMAC_CONFIG); 82 value |= GMAC_CONFIG_RE; 83 writel(value, ioaddr + GMAC_CONFIG); 84 } 85 86 void dwmac4_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, 87 u32 chan) 88 { 89 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 90 u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan)); 91 92 value &= ~DMA_CONTROL_SR; 93 writel(value, ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan)); 94 } 95 96 void dwmac4_set_tx_ring_len(struct stmmac_priv *priv, void __iomem *ioaddr, 97 u32 len, u32 chan) 98 { 99 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 100 101 writel(len, ioaddr + DMA_CHAN_TX_RING_LEN(dwmac4_addrs, chan)); 102 } 103 104 void dwmac4_set_rx_ring_len(struct stmmac_priv *priv, void __iomem *ioaddr, 105 u32 len, u32 chan) 106 { 107 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 108 109 writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(dwmac4_addrs, chan)); 110 } 111 112 void dwmac4_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, 113 u32 chan, bool rx, bool tx) 114 { 115 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 116 u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); 117 118 if (rx) 119 value |= DMA_CHAN_INTR_DEFAULT_RX; 120 if (tx) 121 value |= DMA_CHAN_INTR_DEFAULT_TX; 122 123 writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); 124 } 125 126 void dwmac410_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, 127 u32 chan, bool rx, bool tx) 128 { 129 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 130 u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); 131 132 if (rx) 133 value |= DMA_CHAN_INTR_DEFAULT_RX_4_10; 134 if (tx) 135 value |= DMA_CHAN_INTR_DEFAULT_TX_4_10; 136 137 writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); 138 } 139 140 void dwmac4_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, 141 u32 chan, bool rx, bool tx) 142 { 143 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 144 u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); 145 146 if (rx) 147 value &= ~DMA_CHAN_INTR_DEFAULT_RX; 148 if (tx) 149 value &= ~DMA_CHAN_INTR_DEFAULT_TX; 150 151 writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); 152 } 153 154 void dwmac410_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, 155 u32 chan, bool rx, bool tx) 156 { 157 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 158 u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); 159 160 if (rx) 161 value &= ~DMA_CHAN_INTR_DEFAULT_RX_4_10; 162 if (tx) 163 value &= ~DMA_CHAN_INTR_DEFAULT_TX_4_10; 164 165 writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); 166 } 167 168 int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, 169 struct stmmac_extra_stats *x, u32 chan, u32 dir) 170 { 171 const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; 172 u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan)); 173 u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); 174 struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; 175 struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; 176 int ret = 0; 177 178 if (dir == DMA_DIR_RX) 179 intr_status &= DMA_CHAN_STATUS_MSK_RX; 180 else if (dir == DMA_DIR_TX) 181 intr_status &= DMA_CHAN_STATUS_MSK_TX; 182 183 /* ABNORMAL interrupts */ 184 if (unlikely(intr_status & DMA_CHAN_STATUS_AIS)) { 185 if (unlikely(intr_status & DMA_CHAN_STATUS_RBU)) 186 x->rx_buf_unav_irq++; 187 if (unlikely(intr_status & DMA_CHAN_STATUS_RPS)) 188 x->rx_process_stopped_irq++; 189 if (unlikely(intr_status & DMA_CHAN_STATUS_RWT)) 190 x->rx_watchdog_irq++; 191 if (unlikely(intr_status & DMA_CHAN_STATUS_ETI)) 192 x->tx_early_irq++; 193 if (unlikely(intr_status & DMA_CHAN_STATUS_TPS)) { 194 x->tx_process_stopped_irq++; 195 ret = tx_hard_error; 196 } 197 if (unlikely(intr_status & DMA_CHAN_STATUS_FBE)) { 198 x->fatal_bus_error_irq++; 199 ret = tx_hard_error; 200 } 201 } 202 /* TX/RX NORMAL interrupts */ 203 if (likely(intr_status & DMA_CHAN_STATUS_RI)) { 204 u64_stats_update_begin(&rxq_stats->syncp); 205 rxq_stats->rx_normal_irq_n++; 206 u64_stats_update_end(&rxq_stats->syncp); 207 ret |= handle_rx; 208 } 209 if (likely(intr_status & DMA_CHAN_STATUS_TI)) { 210 u64_stats_update_begin(&txq_stats->syncp); 211 txq_stats->tx_normal_irq_n++; 212 u64_stats_update_end(&txq_stats->syncp); 213 ret |= handle_tx; 214 } 215 216 if (unlikely(intr_status & DMA_CHAN_STATUS_TBU)) 217 ret |= handle_tx; 218 if (unlikely(intr_status & DMA_CHAN_STATUS_ERI)) 219 x->rx_early_irq++; 220 221 writel(intr_status & intr_en, 222 ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan)); 223 return ret; 224 } 225 226 void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6], 227 unsigned int high, unsigned int low) 228 { 229 unsigned long data; 230 231 data = (addr[5] << 8) | addr[4]; 232 /* For MAC Addr registers se have to set the Address Enable (AE) 233 * bit that has no effect on the High Reg 0 where the bit 31 (MO) 234 * is RO. 235 */ 236 data |= (STMMAC_CHAN0 << GMAC_HI_DCS_SHIFT); 237 writel(data | GMAC_HI_REG_AE, ioaddr + high); 238 data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; 239 writel(data, ioaddr + low); 240 } 241 242 /* Enable disable MAC RX/TX */ 243 void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable) 244 { 245 u32 value = readl(ioaddr + GMAC_CONFIG); 246 u32 old_val = value; 247 248 if (enable) 249 value |= GMAC_CONFIG_RE | GMAC_CONFIG_TE; 250 else 251 value &= ~(GMAC_CONFIG_TE | GMAC_CONFIG_RE); 252 253 if (value != old_val) 254 writel(value, ioaddr + GMAC_CONFIG); 255 } 256 257 void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr, 258 unsigned int high, unsigned int low) 259 { 260 unsigned int hi_addr, lo_addr; 261 262 /* Read the MAC address from the hardware */ 263 hi_addr = readl(ioaddr + high); 264 lo_addr = readl(ioaddr + low); 265 266 /* Extract the MAC address from the high and low words */ 267 addr[0] = lo_addr & 0xff; 268 addr[1] = (lo_addr >> 8) & 0xff; 269 addr[2] = (lo_addr >> 16) & 0xff; 270 addr[3] = (lo_addr >> 24) & 0xff; 271 addr[4] = hi_addr & 0xff; 272 addr[5] = (hi_addr >> 8) & 0xff; 273 } 274