2 * Copyright (C) 2007-2015 STMicroelectronics Ltd
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * Author: Alexandre Torgue <alexandre.torgue@st.com>
12 #include <linux/delay.h>
14 #include "dwmac4_dma.h"
17 int dwmac4_dma_reset(void __iomem
*ioaddr
)
19 u32 value
= readl(ioaddr
+ DMA_BUS_MODE
);
23 value
|= DMA_BUS_MODE_SFT_RESET
;
24 writel(value
, ioaddr
+ DMA_BUS_MODE
);
27 if (!(readl(ioaddr
+ DMA_BUS_MODE
) & DMA_BUS_MODE_SFT_RESET
))
38 void dwmac4_set_rx_tail_ptr(void __iomem
*ioaddr
, u32 tail_ptr
, u32 chan
)
40 writel(tail_ptr
, ioaddr
+ DMA_CHAN_RX_END_ADDR(chan
));
43 void dwmac4_set_tx_tail_ptr(void __iomem
*ioaddr
, u32 tail_ptr
, u32 chan
)
45 writel(tail_ptr
, ioaddr
+ DMA_CHAN_TX_END_ADDR(chan
));
48 void dwmac4_dma_start_tx(void __iomem
*ioaddr
, u32 chan
)
50 u32 value
= readl(ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
52 value
|= DMA_CONTROL_ST
;
53 writel(value
, ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
55 value
= readl(ioaddr
+ GMAC_CONFIG
);
56 value
|= GMAC_CONFIG_TE
;
57 writel(value
, ioaddr
+ GMAC_CONFIG
);
60 void dwmac4_dma_stop_tx(void __iomem
*ioaddr
, u32 chan
)
62 u32 value
= readl(ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
64 value
&= ~DMA_CONTROL_ST
;
65 writel(value
, ioaddr
+ DMA_CHAN_TX_CONTROL(chan
));
67 value
= readl(ioaddr
+ GMAC_CONFIG
);
68 value
&= ~GMAC_CONFIG_TE
;
69 writel(value
, ioaddr
+ GMAC_CONFIG
);
72 void dwmac4_dma_start_rx(void __iomem
*ioaddr
, u32 chan
)
74 u32 value
= readl(ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
76 value
|= DMA_CONTROL_SR
;
78 writel(value
, ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
80 value
= readl(ioaddr
+ GMAC_CONFIG
);
81 value
|= GMAC_CONFIG_RE
;
82 writel(value
, ioaddr
+ GMAC_CONFIG
);
85 void dwmac4_dma_stop_rx(void __iomem
*ioaddr
, u32 chan
)
87 u32 value
= readl(ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
89 value
&= ~DMA_CONTROL_SR
;
90 writel(value
, ioaddr
+ DMA_CHAN_RX_CONTROL(chan
));
92 value
= readl(ioaddr
+ GMAC_CONFIG
);
93 value
&= ~GMAC_CONFIG_RE
;
94 writel(value
, ioaddr
+ GMAC_CONFIG
);
97 void dwmac4_set_tx_ring_len(void __iomem
*ioaddr
, u32 len
, u32 chan
)
99 writel(len
, ioaddr
+ DMA_CHAN_TX_RING_LEN(chan
));
102 void dwmac4_set_rx_ring_len(void __iomem
*ioaddr
, u32 len
, u32 chan
)
104 writel(len
, ioaddr
+ DMA_CHAN_RX_RING_LEN(chan
));
107 void dwmac4_enable_dma_irq(void __iomem
*ioaddr
, u32 chan
)
109 writel(DMA_CHAN_INTR_DEFAULT_MASK
, ioaddr
+
110 DMA_CHAN_INTR_ENA(chan
));
113 void dwmac410_enable_dma_irq(void __iomem
*ioaddr
, u32 chan
)
115 writel(DMA_CHAN_INTR_DEFAULT_MASK_4_10
,
116 ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
119 void dwmac4_disable_dma_irq(void __iomem
*ioaddr
, u32 chan
)
121 writel(0, ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
124 int dwmac4_dma_interrupt(void __iomem
*ioaddr
,
125 struct stmmac_extra_stats
*x
, u32 chan
)
129 u32 intr_status
= readl(ioaddr
+ DMA_CHAN_STATUS(chan
));
131 /* ABNORMAL interrupts */
132 if (unlikely(intr_status
& DMA_CHAN_STATUS_AIS
)) {
133 if (unlikely(intr_status
& DMA_CHAN_STATUS_RBU
))
134 x
->rx_buf_unav_irq
++;
135 if (unlikely(intr_status
& DMA_CHAN_STATUS_RPS
))
136 x
->rx_process_stopped_irq
++;
137 if (unlikely(intr_status
& DMA_CHAN_STATUS_RWT
))
138 x
->rx_watchdog_irq
++;
139 if (unlikely(intr_status
& DMA_CHAN_STATUS_ETI
))
141 if (unlikely(intr_status
& DMA_CHAN_STATUS_TPS
)) {
142 x
->tx_process_stopped_irq
++;
145 if (unlikely(intr_status
& DMA_CHAN_STATUS_FBE
)) {
146 x
->fatal_bus_error_irq
++;
150 /* TX/RX NORMAL interrupts */
151 if (likely(intr_status
& DMA_CHAN_STATUS_NIS
)) {
153 if (likely(intr_status
& DMA_CHAN_STATUS_RI
)) {
156 value
= readl(ioaddr
+ DMA_CHAN_INTR_ENA(chan
));
157 /* to schedule NAPI on real RIE event. */
158 if (likely(value
& DMA_CHAN_INTR_ENA_RIE
)) {
159 x
->rx_normal_irq_n
++;
163 if (likely(intr_status
& DMA_CHAN_STATUS_TI
)) {
164 x
->tx_normal_irq_n
++;
167 if (unlikely(intr_status
& DMA_CHAN_STATUS_ERI
))
171 /* Clear the interrupt by writing a logic 1 to the chanX interrupt
172 * status [21-0] expect reserved bits [5-3]
174 writel((intr_status
& 0x3fffc7),
175 ioaddr
+ DMA_CHAN_STATUS(chan
));
180 void stmmac_dwmac4_set_mac_addr(void __iomem
*ioaddr
, u8 addr
[6],
181 unsigned int high
, unsigned int low
)
185 data
= (addr
[5] << 8) | addr
[4];
186 /* For MAC Addr registers se have to set the Address Enable (AE)
187 * bit that has no effect on the High Reg 0 where the bit 31 (MO)
190 data
|= (STMMAC_CHAN0
<< GMAC_HI_DCS_SHIFT
);
191 writel(data
| GMAC_HI_REG_AE
, ioaddr
+ high
);
192 data
= (addr
[3] << 24) | (addr
[2] << 16) | (addr
[1] << 8) | addr
[0];
193 writel(data
, ioaddr
+ low
);
196 /* Enable disable MAC RX/TX */
197 void stmmac_dwmac4_set_mac(void __iomem
*ioaddr
, bool enable
)
199 u32 value
= readl(ioaddr
+ GMAC_CONFIG
);
202 value
|= GMAC_CONFIG_RE
| GMAC_CONFIG_TE
;
204 value
&= ~(GMAC_CONFIG_TE
| GMAC_CONFIG_RE
);
206 writel(value
, ioaddr
+ GMAC_CONFIG
);
209 void stmmac_dwmac4_get_mac_addr(void __iomem
*ioaddr
, unsigned char *addr
,
210 unsigned int high
, unsigned int low
)
212 unsigned int hi_addr
, lo_addr
;
214 /* Read the MAC address from the hardware */
215 hi_addr
= readl(ioaddr
+ high
);
216 lo_addr
= readl(ioaddr
+ low
);
218 /* Extract the MAC address from the high and low words */
219 addr
[0] = lo_addr
& 0xff;
220 addr
[1] = (lo_addr
>> 8) & 0xff;
221 addr
[2] = (lo_addr
>> 16) & 0xff;
222 addr
[3] = (lo_addr
>> 24) & 0xff;
223 addr
[4] = hi_addr
& 0xff;
224 addr
[5] = (hi_addr
>> 8) & 0xff;