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