1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2007-2015 STMicroelectronics Ltd
5 * Author: Alexandre Torgue <alexandre.torgue@st.com>
9 #include <linux/iopoll.h>
10 #include <linux/delay.h>
12 #include "dwmac4_dma.h"
15 int dwmac4_dma_reset(void __iomem
*ioaddr
)
17 u32 value
= readl(ioaddr
+ DMA_BUS_MODE
);
20 value
|= DMA_BUS_MODE_SFT_RESET
;
21 writel(value
, ioaddr
+ DMA_BUS_MODE
);
23 return readl_poll_timeout(ioaddr
+ DMA_BUS_MODE
, value
,
24 !(value
& DMA_BUS_MODE_SFT_RESET
),
28 void dwmac4_set_rx_tail_ptr(void __iomem
*ioaddr
, u32 tail_ptr
, u32 chan
)
30 writel(tail_ptr
, ioaddr
+ DMA_CHAN_RX_END_ADDR(chan
));
33 void dwmac4_set_tx_tail_ptr(void __iomem
*ioaddr
, u32 tail_ptr
, u32 chan
)
35 writel(tail_ptr
, ioaddr
+ DMA_CHAN_TX_END_ADDR(chan
));
38 void dwmac4_dma_start_tx(void __iomem
*ioaddr
, u32 chan
)
40 u32 value
= readl(ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
42 value
|= DMA_CONTROL_ST
;
43 writel(value
, ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
45 value
= readl(ioaddr
+ GMAC_CONFIG
);
46 value
|= GMAC_CONFIG_TE
;
47 writel(value
, ioaddr
+ GMAC_CONFIG
);
50 void dwmac4_dma_stop_tx(void __iomem
*ioaddr
, u32 chan
)
52 u32 value
= readl(ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
54 value
&= ~DMA_CONTROL_ST
;
55 writel(value
, ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
57 value
= readl(ioaddr
+ GMAC_CONFIG
);
58 value
&= ~GMAC_CONFIG_TE
;
59 writel(value
, ioaddr
+ GMAC_CONFIG
);
62 void dwmac4_dma_start_rx(void __iomem
*ioaddr
, u32 chan
)
64 u32 value
= readl(ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
66 value
|= DMA_CONTROL_SR
;
68 writel(value
, ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
70 value
= readl(ioaddr
+ GMAC_CONFIG
);
71 value
|= GMAC_CONFIG_RE
;
72 writel(value
, ioaddr
+ GMAC_CONFIG
);
75 void dwmac4_dma_stop_rx(void __iomem
*ioaddr
, u32 chan
)
77 u32 value
= readl(ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
79 value
&= ~DMA_CONTROL_SR
;
80 writel(value
, ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
83 void dwmac4_set_tx_ring_len(void __iomem
*ioaddr
, u32 len
, u32 chan
)
85 writel(len
, ioaddr
+ DMA_CHAN_TX_RING_LEN(chan
));
88 void dwmac4_set_rx_ring_len(void __iomem
*ioaddr
, u32 len
, u32 chan
)
90 writel(len
, ioaddr
+ DMA_CHAN_RX_RING_LEN(chan
));
93 void dwmac4_enable_dma_irq(void __iomem
*ioaddr
, u32 chan
, bool rx
, bool tx
)
95 u32 value
= readl(ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
98 value
|= DMA_CHAN_INTR_DEFAULT_RX
;
100 value
|= DMA_CHAN_INTR_DEFAULT_TX
;
102 writel(value
, ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
105 void dwmac410_enable_dma_irq(void __iomem
*ioaddr
, u32 chan
, bool rx
, bool tx
)
107 u32 value
= readl(ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
110 value
|= DMA_CHAN_INTR_DEFAULT_RX_4_10
;
112 value
|= DMA_CHAN_INTR_DEFAULT_TX_4_10
;
114 writel(value
, ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
117 void dwmac4_disable_dma_irq(void __iomem
*ioaddr
, u32 chan
, bool rx
, bool tx
)
119 u32 value
= readl(ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
122 value
&= ~DMA_CHAN_INTR_DEFAULT_RX
;
124 value
&= ~DMA_CHAN_INTR_DEFAULT_TX
;
126 writel(value
, ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
129 void dwmac410_disable_dma_irq(void __iomem
*ioaddr
, u32 chan
, bool rx
, bool tx
)
131 u32 value
= readl(ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
134 value
&= ~DMA_CHAN_INTR_DEFAULT_RX_4_10
;
136 value
&= ~DMA_CHAN_INTR_DEFAULT_TX_4_10
;
138 writel(value
, ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
141 int dwmac4_dma_interrupt(void __iomem
*ioaddr
,
142 struct stmmac_extra_stats
*x
, u32 chan
)
144 u32 intr_status
= readl(ioaddr
+ DMA_CHAN_STATUS(chan
));
145 u32 intr_en
= readl(ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
148 /* ABNORMAL interrupts */
149 if (unlikely(intr_status
& DMA_CHAN_STATUS_AIS
)) {
150 if (unlikely(intr_status
& DMA_CHAN_STATUS_RBU
))
151 x
->rx_buf_unav_irq
++;
152 if (unlikely(intr_status
& DMA_CHAN_STATUS_RPS
))
153 x
->rx_process_stopped_irq
++;
154 if (unlikely(intr_status
& DMA_CHAN_STATUS_RWT
))
155 x
->rx_watchdog_irq
++;
156 if (unlikely(intr_status
& DMA_CHAN_STATUS_ETI
))
158 if (unlikely(intr_status
& DMA_CHAN_STATUS_TPS
)) {
159 x
->tx_process_stopped_irq
++;
162 if (unlikely(intr_status
& DMA_CHAN_STATUS_FBE
)) {
163 x
->fatal_bus_error_irq
++;
167 /* TX/RX NORMAL interrupts */
168 if (likely(intr_status
& DMA_CHAN_STATUS_NIS
)) {
170 if (likely(intr_status
& DMA_CHAN_STATUS_RI
)) {
171 x
->rx_normal_irq_n
++;
174 if (likely(intr_status
& (DMA_CHAN_STATUS_TI
|
175 DMA_CHAN_STATUS_TBU
))) {
176 x
->tx_normal_irq_n
++;
179 if (unlikely(intr_status
& DMA_CHAN_STATUS_ERI
))
183 writel(intr_status
& intr_en
, ioaddr
+ DMA_CHAN_STATUS(chan
));
187 void stmmac_dwmac4_set_mac_addr(void __iomem
*ioaddr
, u8 addr
[6],
188 unsigned int high
, unsigned int low
)
192 data
= (addr
[5] << 8) | addr
[4];
193 /* For MAC Addr registers se have to set the Address Enable (AE)
194 * bit that has no effect on the High Reg 0 where the bit 31 (MO)
197 data
|= (STMMAC_CHAN0
<< GMAC_HI_DCS_SHIFT
);
198 writel(data
| GMAC_HI_REG_AE
, ioaddr
+ high
);
199 data
= (addr
[3] << 24) | (addr
[2] << 16) | (addr
[1] << 8) | addr
[0];
200 writel(data
, ioaddr
+ low
);
203 /* Enable disable MAC RX/TX */
204 void stmmac_dwmac4_set_mac(void __iomem
*ioaddr
, bool enable
)
206 u32 value
= readl(ioaddr
+ GMAC_CONFIG
);
209 value
|= GMAC_CONFIG_RE
| GMAC_CONFIG_TE
;
211 value
&= ~(GMAC_CONFIG_TE
| GMAC_CONFIG_RE
);
213 writel(value
, ioaddr
+ GMAC_CONFIG
);
216 void stmmac_dwmac4_get_mac_addr(void __iomem
*ioaddr
, unsigned char *addr
,
217 unsigned int high
, unsigned int low
)
219 unsigned int hi_addr
, lo_addr
;
221 /* Read the MAC address from the hardware */
222 hi_addr
= readl(ioaddr
+ high
);
223 lo_addr
= readl(ioaddr
+ low
);
225 /* Extract the MAC address from the high and low words */
226 addr
[0] = lo_addr
& 0xff;
227 addr
[1] = (lo_addr
>> 8) & 0xff;
228 addr
[2] = (lo_addr
>> 16) & 0xff;
229 addr
[3] = (lo_addr
>> 24) & 0xff;
230 addr
[4] = hi_addr
& 0xff;
231 addr
[5] = (hi_addr
>> 8) & 0xff;