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_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); 175 int ret = 0; 176 177 if (dir == DMA_DIR_RX) 178 intr_status &= DMA_CHAN_STATUS_MSK_RX; 179 else if (dir == DMA_DIR_TX) 180 intr_status &= DMA_CHAN_STATUS_MSK_TX; 181 182 /* ABNORMAL interrupts */ 183 if (unlikely(intr_status & DMA_CHAN_STATUS_AIS)) { 184 if (unlikely(intr_status & DMA_CHAN_STATUS_RBU)) 185 x->rx_buf_unav_irq++; 186 if (unlikely(intr_status & DMA_CHAN_STATUS_RPS)) 187 x->rx_process_stopped_irq++; 188 if (unlikely(intr_status & DMA_CHAN_STATUS_ETI)) 189 x->tx_early_irq++; 190 if (unlikely(intr_status & DMA_CHAN_STATUS_TPS)) { 191 x->tx_process_stopped_irq++; 192 ret = tx_hard_error; 193 } 194 if (unlikely(intr_status & DMA_CHAN_STATUS_FBE)) { 195 x->fatal_bus_error_irq++; 196 ret = tx_hard_error; 197 } 198 } 199 200 if (unlikely(intr_status & DMA_CHAN_STATUS_RWT)) 201 x->rx_watchdog_irq++; 202 203 /* TX/RX NORMAL interrupts */ 204 if (likely(intr_status & DMA_CHAN_STATUS_RI)) { 205 u64_stats_update_begin(&stats->syncp); 206 u64_stats_inc(&stats->rx_normal_irq_n[chan]); 207 u64_stats_update_end(&stats->syncp); 208 ret |= handle_rx; 209 } 210 if (likely(intr_status & DMA_CHAN_STATUS_TI)) { 211 u64_stats_update_begin(&stats->syncp); 212 u64_stats_inc(&stats->tx_normal_irq_n[chan]); 213 u64_stats_update_end(&stats->syncp); 214 ret |= handle_tx; 215 } 216 217 if (unlikely(intr_status & DMA_CHAN_STATUS_TBU)) 218 ret |= handle_tx; 219 if (unlikely(intr_status & DMA_CHAN_STATUS_ERI)) 220 x->rx_early_irq++; 221 222 writel(intr_status & intr_en, 223 ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan)); 224 return ret; 225 } 226 227 void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6], 228 unsigned int high, unsigned int low) 229 { 230 unsigned long data; 231 232 data = (addr[5] << 8) | addr[4]; 233 /* For MAC Addr registers se have to set the Address Enable (AE) 234 * bit that has no effect on the High Reg 0 where the bit 31 (MO) 235 * is RO. 236 */ 237 data |= (STMMAC_CHAN0 << GMAC_HI_DCS_SHIFT); 238 writel(data | GMAC_HI_REG_AE, ioaddr + high); 239 data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; 240 writel(data, ioaddr + low); 241 } 242 243 /* Enable disable MAC RX/TX */ 244 void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable) 245 { 246 u32 value = readl(ioaddr + GMAC_CONFIG); 247 u32 old_val = value; 248 249 if (enable) 250 value |= GMAC_CONFIG_RE | GMAC_CONFIG_TE; 251 else 252 value &= ~(GMAC_CONFIG_TE | GMAC_CONFIG_RE); 253 254 if (value != old_val) 255 writel(value, ioaddr + GMAC_CONFIG); 256 } 257 258 void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr, 259 unsigned int high, unsigned int low) 260 { 261 unsigned int hi_addr, lo_addr; 262 263 /* Read the MAC address from the hardware */ 264 hi_addr = readl(ioaddr + high); 265 lo_addr = readl(ioaddr + low); 266 267 /* Extract the MAC address from the high and low words */ 268 addr[0] = lo_addr & 0xff; 269 addr[1] = (lo_addr >> 8) & 0xff; 270 addr[2] = (lo_addr >> 16) & 0xff; 271 addr[3] = (lo_addr >> 24) & 0xff; 272 addr[4] = hi_addr & 0xff; 273 addr[5] = (hi_addr >> 8) & 0xff; 274 } 275