1// SPDX-License-Identifier: GPL-2.0-only
2/* 10G controller driver for Samsung SoCs
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 *
7 * Author: Siva Reddy Kallam <siva.kallam@samsung.com>
8 */
9#include <linux/delay.h>
10#include <linux/export.h>
11#include <linux/io.h>
12#include <linux/netdevice.h>
13#include <linux/phy.h>
14
15#include "sxgbe_common.h"
16#include "sxgbe_dma.h"
17#include "sxgbe_reg.h"
18#include "sxgbe_desc.h"
19
20/* DMA core initialization */
21static int sxgbe_dma_init(void __iomem *ioaddr, int fix_burst, int burst_map)
22{
23 u32 reg_val;
24
25 reg_val = readl(addr: ioaddr + SXGBE_DMA_SYSBUS_MODE_REG);
26
27 /* if fix_burst = 0, Set UNDEF = 1 of DMA_Sys_Mode Register.
28 * if fix_burst = 1, Set UNDEF = 0 of DMA_Sys_Mode Register.
29 * burst_map is bitmap for BLEN[4, 8, 16, 32, 64, 128 and 256].
30 * Set burst_map irrespective of fix_burst value.
31 */
32 if (!fix_burst)
33 reg_val |= SXGBE_DMA_AXI_UNDEF_BURST;
34
35 /* write burst len map */
36 reg_val |= (burst_map << SXGBE_DMA_BLENMAP_LSHIFT);
37
38 writel(val: reg_val, addr: ioaddr + SXGBE_DMA_SYSBUS_MODE_REG);
39
40 return 0;
41}
42
43static void sxgbe_dma_channel_init(void __iomem *ioaddr, int cha_num,
44 int fix_burst, int pbl, dma_addr_t dma_tx,
45 dma_addr_t dma_rx, int t_rsize, int r_rsize)
46{
47 u32 reg_val;
48 dma_addr_t dma_addr;
49
50 reg_val = readl(addr: ioaddr + SXGBE_DMA_CHA_CTL_REG(cha_num));
51 /* set the pbl */
52 if (fix_burst) {
53 reg_val |= SXGBE_DMA_PBL_X8MODE;
54 writel(val: reg_val, addr: ioaddr + SXGBE_DMA_CHA_CTL_REG(cha_num));
55 /* program the TX pbl */
56 reg_val = readl(addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num));
57 reg_val |= (pbl << SXGBE_DMA_TXPBL_LSHIFT);
58 writel(val: reg_val, addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num));
59 /* program the RX pbl */
60 reg_val = readl(addr: ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cha_num));
61 reg_val |= (pbl << SXGBE_DMA_RXPBL_LSHIFT);
62 writel(val: reg_val, addr: ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cha_num));
63 }
64
65 /* program desc registers */
66 writel(upper_32_bits(dma_tx),
67 addr: ioaddr + SXGBE_DMA_CHA_TXDESC_HADD_REG(cha_num));
68 writel(lower_32_bits(dma_tx),
69 addr: ioaddr + SXGBE_DMA_CHA_TXDESC_LADD_REG(cha_num));
70
71 writel(upper_32_bits(dma_rx),
72 addr: ioaddr + SXGBE_DMA_CHA_RXDESC_HADD_REG(cha_num));
73 writel(lower_32_bits(dma_rx),
74 addr: ioaddr + SXGBE_DMA_CHA_RXDESC_LADD_REG(cha_num));
75
76 /* program tail pointers */
77 /* assumption: upper 32 bits are constant and
78 * same as TX/RX desc list
79 */
80 dma_addr = dma_tx + ((t_rsize - 1) * SXGBE_DESC_SIZE_BYTES);
81 writel(lower_32_bits(dma_addr),
82 addr: ioaddr + SXGBE_DMA_CHA_TXDESC_TAILPTR_REG(cha_num));
83
84 dma_addr = dma_rx + ((r_rsize - 1) * SXGBE_DESC_SIZE_BYTES);
85 writel(lower_32_bits(dma_addr),
86 addr: ioaddr + SXGBE_DMA_CHA_RXDESC_LADD_REG(cha_num));
87 /* program the ring sizes */
88 writel(val: t_rsize - 1, addr: ioaddr + SXGBE_DMA_CHA_TXDESC_RINGLEN_REG(cha_num));
89 writel(val: r_rsize - 1, addr: ioaddr + SXGBE_DMA_CHA_RXDESC_RINGLEN_REG(cha_num));
90
91 /* Enable TX/RX interrupts */
92 writel(SXGBE_DMA_ENA_INT,
93 addr: ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(cha_num));
94}
95
96static void sxgbe_enable_dma_transmission(void __iomem *ioaddr, int cha_num)
97{
98 u32 tx_config;
99
100 tx_config = readl(addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num));
101 tx_config |= SXGBE_TX_START_DMA;
102 writel(val: tx_config, addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num));
103}
104
105static void sxgbe_enable_dma_irq(void __iomem *ioaddr, int dma_cnum)
106{
107 /* Enable TX/RX interrupts */
108 writel(SXGBE_DMA_ENA_INT,
109 addr: ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(dma_cnum));
110}
111
112static void sxgbe_disable_dma_irq(void __iomem *ioaddr, int dma_cnum)
113{
114 /* Disable TX/RX interrupts */
115 writel(val: 0, addr: ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(dma_cnum));
116}
117
118static void sxgbe_dma_start_tx(void __iomem *ioaddr, int tchannels)
119{
120 int cnum;
121 u32 tx_ctl_reg;
122
123 for (cnum = 0; cnum < tchannels; cnum++) {
124 tx_ctl_reg = readl(addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum));
125 tx_ctl_reg |= SXGBE_TX_ENABLE;
126 writel(val: tx_ctl_reg,
127 addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum));
128 }
129}
130
131static void sxgbe_dma_start_tx_queue(void __iomem *ioaddr, int dma_cnum)
132{
133 u32 tx_ctl_reg;
134
135 tx_ctl_reg = readl(addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum));
136 tx_ctl_reg |= SXGBE_TX_ENABLE;
137 writel(val: tx_ctl_reg, addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum));
138}
139
140static void sxgbe_dma_stop_tx_queue(void __iomem *ioaddr, int dma_cnum)
141{
142 u32 tx_ctl_reg;
143
144 tx_ctl_reg = readl(addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum));
145 tx_ctl_reg &= ~(SXGBE_TX_ENABLE);
146 writel(val: tx_ctl_reg, addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum));
147}
148
149static void sxgbe_dma_stop_tx(void __iomem *ioaddr, int tchannels)
150{
151 int cnum;
152 u32 tx_ctl_reg;
153
154 for (cnum = 0; cnum < tchannels; cnum++) {
155 tx_ctl_reg = readl(addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum));
156 tx_ctl_reg &= ~(SXGBE_TX_ENABLE);
157 writel(val: tx_ctl_reg, addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum));
158 }
159}
160
161static void sxgbe_dma_start_rx(void __iomem *ioaddr, int rchannels)
162{
163 int cnum;
164 u32 rx_ctl_reg;
165
166 for (cnum = 0; cnum < rchannels; cnum++) {
167 rx_ctl_reg = readl(addr: ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum));
168 rx_ctl_reg |= SXGBE_RX_ENABLE;
169 writel(val: rx_ctl_reg,
170 addr: ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum));
171 }
172}
173
174static void sxgbe_dma_stop_rx(void __iomem *ioaddr, int rchannels)
175{
176 int cnum;
177 u32 rx_ctl_reg;
178
179 for (cnum = 0; cnum < rchannels; cnum++) {
180 rx_ctl_reg = readl(addr: ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum));
181 rx_ctl_reg &= ~(SXGBE_RX_ENABLE);
182 writel(val: rx_ctl_reg, addr: ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum));
183 }
184}
185
186static int sxgbe_tx_dma_int_status(void __iomem *ioaddr, int channel_no,
187 struct sxgbe_extra_stats *x)
188{
189 u32 int_status = readl(addr: ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no));
190 u32 clear_val = 0;
191 u32 ret_val = 0;
192
193 /* TX Normal Interrupt Summary */
194 if (likely(int_status & SXGBE_DMA_INT_STATUS_NIS)) {
195 x->normal_irq_n++;
196 if (int_status & SXGBE_DMA_INT_STATUS_TI) {
197 ret_val |= handle_tx;
198 x->tx_normal_irq_n++;
199 clear_val |= SXGBE_DMA_INT_STATUS_TI;
200 }
201
202 if (int_status & SXGBE_DMA_INT_STATUS_TBU) {
203 x->tx_underflow_irq++;
204 ret_val |= tx_bump_tc;
205 clear_val |= SXGBE_DMA_INT_STATUS_TBU;
206 }
207 } else if (unlikely(int_status & SXGBE_DMA_INT_STATUS_AIS)) {
208 /* TX Abnormal Interrupt Summary */
209 if (int_status & SXGBE_DMA_INT_STATUS_TPS) {
210 ret_val |= tx_hard_error;
211 clear_val |= SXGBE_DMA_INT_STATUS_TPS;
212 x->tx_process_stopped_irq++;
213 }
214
215 if (int_status & SXGBE_DMA_INT_STATUS_FBE) {
216 ret_val |= tx_hard_error;
217 x->fatal_bus_error_irq++;
218
219 /* Assumption: FBE bit is the combination of
220 * all the bus access erros and cleared when
221 * the respective error bits cleared
222 */
223
224 /* check for actual cause */
225 if (int_status & SXGBE_DMA_INT_STATUS_TEB0) {
226 x->tx_read_transfer_err++;
227 clear_val |= SXGBE_DMA_INT_STATUS_TEB0;
228 } else {
229 x->tx_write_transfer_err++;
230 }
231
232 if (int_status & SXGBE_DMA_INT_STATUS_TEB1) {
233 x->tx_desc_access_err++;
234 clear_val |= SXGBE_DMA_INT_STATUS_TEB1;
235 } else {
236 x->tx_buffer_access_err++;
237 }
238
239 if (int_status & SXGBE_DMA_INT_STATUS_TEB2) {
240 x->tx_data_transfer_err++;
241 clear_val |= SXGBE_DMA_INT_STATUS_TEB2;
242 }
243 }
244
245 /* context descriptor error */
246 if (int_status & SXGBE_DMA_INT_STATUS_CTXTERR) {
247 x->tx_ctxt_desc_err++;
248 clear_val |= SXGBE_DMA_INT_STATUS_CTXTERR;
249 }
250 }
251
252 /* clear the served bits */
253 writel(val: clear_val, addr: ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no));
254
255 return ret_val;
256}
257
258static int sxgbe_rx_dma_int_status(void __iomem *ioaddr, int channel_no,
259 struct sxgbe_extra_stats *x)
260{
261 u32 int_status = readl(addr: ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no));
262 u32 clear_val = 0;
263 u32 ret_val = 0;
264
265 /* RX Normal Interrupt Summary */
266 if (likely(int_status & SXGBE_DMA_INT_STATUS_NIS)) {
267 x->normal_irq_n++;
268 if (int_status & SXGBE_DMA_INT_STATUS_RI) {
269 ret_val |= handle_rx;
270 x->rx_normal_irq_n++;
271 clear_val |= SXGBE_DMA_INT_STATUS_RI;
272 }
273 } else if (unlikely(int_status & SXGBE_DMA_INT_STATUS_AIS)) {
274 /* RX Abnormal Interrupt Summary */
275 if (int_status & SXGBE_DMA_INT_STATUS_RBU) {
276 ret_val |= rx_bump_tc;
277 clear_val |= SXGBE_DMA_INT_STATUS_RBU;
278 x->rx_underflow_irq++;
279 }
280
281 if (int_status & SXGBE_DMA_INT_STATUS_RPS) {
282 ret_val |= rx_hard_error;
283 clear_val |= SXGBE_DMA_INT_STATUS_RPS;
284 x->rx_process_stopped_irq++;
285 }
286
287 if (int_status & SXGBE_DMA_INT_STATUS_FBE) {
288 ret_val |= rx_hard_error;
289 x->fatal_bus_error_irq++;
290
291 /* Assumption: FBE bit is the combination of
292 * all the bus access erros and cleared when
293 * the respective error bits cleared
294 */
295
296 /* check for actual cause */
297 if (int_status & SXGBE_DMA_INT_STATUS_REB0) {
298 x->rx_read_transfer_err++;
299 clear_val |= SXGBE_DMA_INT_STATUS_REB0;
300 } else {
301 x->rx_write_transfer_err++;
302 }
303
304 if (int_status & SXGBE_DMA_INT_STATUS_REB1) {
305 x->rx_desc_access_err++;
306 clear_val |= SXGBE_DMA_INT_STATUS_REB1;
307 } else {
308 x->rx_buffer_access_err++;
309 }
310
311 if (int_status & SXGBE_DMA_INT_STATUS_REB2) {
312 x->rx_data_transfer_err++;
313 clear_val |= SXGBE_DMA_INT_STATUS_REB2;
314 }
315 }
316 }
317
318 /* clear the served bits */
319 writel(val: clear_val, addr: ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no));
320
321 return ret_val;
322}
323
324/* Program the HW RX Watchdog */
325static void sxgbe_dma_rx_watchdog(void __iomem *ioaddr, u32 riwt)
326{
327 u32 que_num;
328
329 SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, que_num) {
330 writel(val: riwt,
331 addr: ioaddr + SXGBE_DMA_CHA_INT_RXWATCHTMR_REG(que_num));
332 }
333}
334
335static void sxgbe_enable_tso(void __iomem *ioaddr, u8 chan_num)
336{
337 u32 ctrl;
338
339 ctrl = readl(addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(chan_num));
340 ctrl |= SXGBE_DMA_CHA_TXCTL_TSE_ENABLE;
341 writel(val: ctrl, addr: ioaddr + SXGBE_DMA_CHA_TXCTL_REG(chan_num));
342}
343
344static const struct sxgbe_dma_ops sxgbe_dma_ops = {
345 .init = sxgbe_dma_init,
346 .cha_init = sxgbe_dma_channel_init,
347 .enable_dma_transmission = sxgbe_enable_dma_transmission,
348 .enable_dma_irq = sxgbe_enable_dma_irq,
349 .disable_dma_irq = sxgbe_disable_dma_irq,
350 .start_tx = sxgbe_dma_start_tx,
351 .start_tx_queue = sxgbe_dma_start_tx_queue,
352 .stop_tx = sxgbe_dma_stop_tx,
353 .stop_tx_queue = sxgbe_dma_stop_tx_queue,
354 .start_rx = sxgbe_dma_start_rx,
355 .stop_rx = sxgbe_dma_stop_rx,
356 .tx_dma_int_status = sxgbe_tx_dma_int_status,
357 .rx_dma_int_status = sxgbe_rx_dma_int_status,
358 .rx_watchdog = sxgbe_dma_rx_watchdog,
359 .enable_tso = sxgbe_enable_tso,
360};
361
362const struct sxgbe_dma_ops *sxgbe_get_dma_ops(void)
363{
364 return &sxgbe_dma_ops;
365}
366

source code of linux/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c