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/delay.h>
11 #include "dwmac4_dma.h"
14 int dwmac4_dma_reset(void __iomem
*ioaddr
)
16 u32 value
= readl(ioaddr
+ DMA_BUS_MODE
);
20 value
|= DMA_BUS_MODE_SFT_RESET
;
21 writel(value
, ioaddr
+ DMA_BUS_MODE
);
24 if (!(readl(ioaddr
+ DMA_BUS_MODE
) & DMA_BUS_MODE_SFT_RESET
))
35 void dwmac4_set_rx_tail_ptr(void __iomem
*ioaddr
, u32 tail_ptr
, u32 chan
)
37 writel(tail_ptr
, ioaddr
+ DMA_CHAN_RX_END_ADDR(chan
));
40 void dwmac4_set_tx_tail_ptr(void __iomem
*ioaddr
, u32 tail_ptr
, u32 chan
)
42 writel(tail_ptr
, ioaddr
+ DMA_CHAN_TX_END_ADDR(chan
));
45 void dwmac4_dma_start_tx(void __iomem
*ioaddr
, u32 chan
)
47 u32 value
= readl(ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
49 value
|= DMA_CONTROL_ST
;
50 writel(value
, ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
52 value
= readl(ioaddr
+ GMAC_CONFIG
);
53 value
|= GMAC_CONFIG_TE
;
54 writel(value
, ioaddr
+ GMAC_CONFIG
);
57 void dwmac4_dma_stop_tx(void __iomem
*ioaddr
, u32 chan
)
59 u32 value
= readl(ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
61 value
&= ~DMA_CONTROL_ST
;
62 writel(value
, ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
64 value
= readl(ioaddr
+ GMAC_CONFIG
);
65 value
&= ~GMAC_CONFIG_TE
;
66 writel(value
, ioaddr
+ GMAC_CONFIG
);
69 void dwmac4_dma_start_rx(void __iomem
*ioaddr
, u32 chan
)
71 u32 value
= readl(ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
73 value
|= DMA_CONTROL_SR
;
75 writel(value
, ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
77 value
= readl(ioaddr
+ GMAC_CONFIG
);
78 value
|= GMAC_CONFIG_RE
;
79 writel(value
, ioaddr
+ GMAC_CONFIG
);
82 void dwmac4_dma_stop_rx(void __iomem
*ioaddr
, u32 chan
)
84 u32 value
= readl(ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
86 value
&= ~DMA_CONTROL_SR
;
87 writel(value
, ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
90 void dwmac4_set_tx_ring_len(void __iomem
*ioaddr
, u32 len
, u32 chan
)
92 writel(len
, ioaddr
+ DMA_CHAN_TX_RING_LEN(chan
));
95 void dwmac4_set_rx_ring_len(void __iomem
*ioaddr
, u32 len
, u32 chan
)
97 writel(len
, ioaddr
+ DMA_CHAN_RX_RING_LEN(chan
));
100 void dwmac4_enable_dma_irq(void __iomem
*ioaddr
, u32 chan
, bool rx
, bool tx
)
102 u32 value
= readl(ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
105 value
|= DMA_CHAN_INTR_DEFAULT_RX
;
107 value
|= DMA_CHAN_INTR_DEFAULT_TX
;
109 writel(value
, ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
112 void dwmac410_enable_dma_irq(void __iomem
*ioaddr
, u32 chan
, bool rx
, bool tx
)
114 u32 value
= readl(ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
117 value
|= DMA_CHAN_INTR_DEFAULT_RX_4_10
;
119 value
|= DMA_CHAN_INTR_DEFAULT_TX_4_10
;
121 writel(value
, ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
124 void dwmac4_disable_dma_irq(void __iomem
*ioaddr
, u32 chan
, bool rx
, bool tx
)
126 u32 value
= readl(ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
129 value
&= ~DMA_CHAN_INTR_DEFAULT_RX
;
131 value
&= ~DMA_CHAN_INTR_DEFAULT_TX
;
133 writel(value
, ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
136 void dwmac410_disable_dma_irq(void __iomem
*ioaddr
, u32 chan
, bool rx
, bool tx
)
138 u32 value
= readl(ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
141 value
&= ~DMA_CHAN_INTR_DEFAULT_RX_4_10
;
143 value
&= ~DMA_CHAN_INTR_DEFAULT_TX_4_10
;
145 writel(value
, ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
148 int dwmac4_dma_interrupt(void __iomem
*ioaddr
,
149 struct stmmac_extra_stats
*x
, u32 chan
)
151 u32 intr_status
= readl(ioaddr
+ DMA_CHAN_STATUS(chan
));
152 u32 intr_en
= readl(ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
155 /* ABNORMAL interrupts */
156 if (unlikely(intr_status
& DMA_CHAN_STATUS_AIS
)) {
157 if (unlikely(intr_status
& DMA_CHAN_STATUS_RBU
))
158 x
->rx_buf_unav_irq
++;
159 if (unlikely(intr_status
& DMA_CHAN_STATUS_RPS
))
160 x
->rx_process_stopped_irq
++;
161 if (unlikely(intr_status
& DMA_CHAN_STATUS_RWT
))
162 x
->rx_watchdog_irq
++;
163 if (unlikely(intr_status
& DMA_CHAN_STATUS_ETI
))
165 if (unlikely(intr_status
& DMA_CHAN_STATUS_TPS
)) {
166 x
->tx_process_stopped_irq
++;
169 if (unlikely(intr_status
& DMA_CHAN_STATUS_FBE
)) {
170 x
->fatal_bus_error_irq
++;
174 /* TX/RX NORMAL interrupts */
175 if (likely(intr_status
& DMA_CHAN_STATUS_NIS
)) {
177 if (likely(intr_status
& DMA_CHAN_STATUS_RI
)) {
178 x
->rx_normal_irq_n
++;
181 if (likely(intr_status
& (DMA_CHAN_STATUS_TI
|
182 DMA_CHAN_STATUS_TBU
))) {
183 x
->tx_normal_irq_n
++;
186 if (unlikely(intr_status
& DMA_CHAN_STATUS_ERI
))
190 writel(intr_status
& intr_en
, ioaddr
+ DMA_CHAN_STATUS(chan
));
194 void stmmac_dwmac4_set_mac_addr(void __iomem
*ioaddr
, u8 addr
[6],
195 unsigned int high
, unsigned int low
)
199 data
= (addr
[5] << 8) | addr
[4];
200 /* For MAC Addr registers se have to set the Address Enable (AE)
201 * bit that has no effect on the High Reg 0 where the bit 31 (MO)
204 data
|= (STMMAC_CHAN0
<< GMAC_HI_DCS_SHIFT
);
205 writel(data
| GMAC_HI_REG_AE
, ioaddr
+ high
);
206 data
= (addr
[3] << 24) | (addr
[2] << 16) | (addr
[1] << 8) | addr
[0];
207 writel(data
, ioaddr
+ low
);
210 /* Enable disable MAC RX/TX */
211 void stmmac_dwmac4_set_mac(void __iomem
*ioaddr
, bool enable
)
213 u32 value
= readl(ioaddr
+ GMAC_CONFIG
);
216 value
|= GMAC_CONFIG_RE
| GMAC_CONFIG_TE
;
218 value
&= ~(GMAC_CONFIG_TE
| GMAC_CONFIG_RE
);
220 writel(value
, ioaddr
+ GMAC_CONFIG
);
223 void stmmac_dwmac4_get_mac_addr(void __iomem
*ioaddr
, unsigned char *addr
,
224 unsigned int high
, unsigned int low
)
226 unsigned int hi_addr
, lo_addr
;
228 /* Read the MAC address from the hardware */
229 hi_addr
= readl(ioaddr
+ high
);
230 lo_addr
= readl(ioaddr
+ low
);
232 /* Extract the MAC address from the high and low words */
233 addr
[0] = lo_addr
& 0xff;
234 addr
[1] = (lo_addr
>> 8) & 0xff;
235 addr
[2] = (lo_addr
>> 16) & 0xff;
236 addr
[3] = (lo_addr
>> 24) & 0xff;
237 addr
[4] = hi_addr
& 0xff;
238 addr
[5] = (hi_addr
>> 8) & 0xff;