blob: 8176f7b4bc346033dfca1f145f96f99bc548e573 [file] [log] [blame]
Stephan Linze1fd4be2012-02-25 00:48:31 +00001/*
2 * Xilinx xps_ll_temac ethernet driver for u-boot
3 *
4 * SDMA sub-controller
5 *
6 * Copyright (C) 2011 - 2012 Stephan Linz <linz@li-pro.net>
7 * Copyright (C) 2008 - 2011 Michal Simek <monstr@monstr.eu>
8 * Copyright (C) 2008 - 2011 PetaLogix
9 *
10 * Based on Yoshio Kashiwagi kashiwagi@co-nss.co.jp driver
11 * Copyright (C) 2008 Nissin Systems Co.,Ltd.
12 * March 2008 created
13 *
14 * CREDITS: tsec driver
15 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +020016 * SPDX-License-Identifier: GPL-2.0+
Stephan Linze1fd4be2012-02-25 00:48:31 +000017 *
18 * [0]: http://www.xilinx.com/support/documentation
19 *
20 * [M]: [0]/ip_documentation/mpmc.pdf
21 * [S]: [0]/ip_documentation/xps_ll_temac.pdf
22 * [A]: [0]/application_notes/xapp1041.pdf
23 */
24
25#include <config.h>
26#include <common.h>
27#include <net.h>
28
29#include <asm/types.h>
30#include <asm/io.h>
31
32#include "xilinx_ll_temac.h"
33#include "xilinx_ll_temac_sdma.h"
34
35#define TX_BUF_CNT 2
36
37static unsigned int rx_idx; /* index of the current RX buffer */
38static unsigned int tx_idx; /* index of the current TX buffer */
39
40struct rtx_cdmac_bd {
41 struct cdmac_bd rx[PKTBUFSRX];
42 struct cdmac_bd tx[TX_BUF_CNT];
43};
44
45/*
46 * DMA Buffer Descriptor alignment
47 *
48 * If the address contained in the Next Descriptor Pointer register is not
49 * 8-word aligned or reaches beyond the range of available memory, the SDMA
50 * halts processing and sets the CDMAC_BD_STCTRL_ERROR bit in the respective
51 * status register (tx_chnl_sts or rx_chnl_sts).
52 *
53 * [1]: [0]/ip_documentation/mpmc.pdf
54 * page 161, Next Descriptor Pointer
55 */
56static struct rtx_cdmac_bd cdmac_bd __aligned(32);
57
Stephan Linze1fd4be2012-02-25 00:48:31 +000058/* Xilinx Processor Local Bus (PLB) in/out accessors */
59inline unsigned ll_temac_xlplb_in32(phys_addr_t addr)
60{
61 return in_be32((void *)addr);
62}
63inline void ll_temac_xlplb_out32(phys_addr_t addr, unsigned value)
64{
65 out_be32((void *)addr, value);
66}
67
68/* collect all register addresses for Xilinx PLB in/out accessors */
69void ll_temac_collect_xlplb_sdma_reg_addr(struct eth_device *dev)
70{
71 struct ll_temac *ll_temac = dev->priv;
72 struct sdma_ctrl *sdma_ctrl = (void *)ll_temac->ctrladdr;
73 phys_addr_t *ra = ll_temac->sdma_reg_addr;
74
75 ra[TX_NXTDESC_PTR] = (phys_addr_t)&sdma_ctrl->tx_nxtdesc_ptr;
76 ra[TX_CURBUF_ADDR] = (phys_addr_t)&sdma_ctrl->tx_curbuf_addr;
77 ra[TX_CURBUF_LENGTH] = (phys_addr_t)&sdma_ctrl->tx_curbuf_length;
78 ra[TX_CURDESC_PTR] = (phys_addr_t)&sdma_ctrl->tx_curdesc_ptr;
79 ra[TX_TAILDESC_PTR] = (phys_addr_t)&sdma_ctrl->tx_taildesc_ptr;
80 ra[TX_CHNL_CTRL] = (phys_addr_t)&sdma_ctrl->tx_chnl_ctrl;
81 ra[TX_IRQ_REG] = (phys_addr_t)&sdma_ctrl->tx_irq_reg;
82 ra[TX_CHNL_STS] = (phys_addr_t)&sdma_ctrl->tx_chnl_sts;
83 ra[RX_NXTDESC_PTR] = (phys_addr_t)&sdma_ctrl->rx_nxtdesc_ptr;
84 ra[RX_CURBUF_ADDR] = (phys_addr_t)&sdma_ctrl->rx_curbuf_addr;
85 ra[RX_CURBUF_LENGTH] = (phys_addr_t)&sdma_ctrl->rx_curbuf_length;
86 ra[RX_CURDESC_PTR] = (phys_addr_t)&sdma_ctrl->rx_curdesc_ptr;
87 ra[RX_TAILDESC_PTR] = (phys_addr_t)&sdma_ctrl->rx_taildesc_ptr;
88 ra[RX_CHNL_CTRL] = (phys_addr_t)&sdma_ctrl->rx_chnl_ctrl;
89 ra[RX_IRQ_REG] = (phys_addr_t)&sdma_ctrl->rx_irq_reg;
90 ra[RX_CHNL_STS] = (phys_addr_t)&sdma_ctrl->rx_chnl_sts;
91 ra[DMA_CONTROL_REG] = (phys_addr_t)&sdma_ctrl->dma_control_reg;
92}
93
94/* Check for TX and RX channel errors. */
95static inline int ll_temac_sdma_error(struct eth_device *dev)
96{
97 int err;
98 struct ll_temac *ll_temac = dev->priv;
99 phys_addr_t *ra = ll_temac->sdma_reg_addr;
100
101 err = ll_temac->in32(ra[TX_CHNL_STS]) & CHNL_STS_ERROR;
102 err |= ll_temac->in32(ra[RX_CHNL_STS]) & CHNL_STS_ERROR;
103
104 return err;
105}
106
107int ll_temac_init_sdma(struct eth_device *dev)
108{
109 struct ll_temac *ll_temac = dev->priv;
110 struct cdmac_bd *rx_dp;
111 struct cdmac_bd *tx_dp;
112 phys_addr_t *ra = ll_temac->sdma_reg_addr;
113 int i;
114
115 printf("%s: SDMA: %d Rx buffers, %d Tx buffers\n",
116 dev->name, PKTBUFSRX, TX_BUF_CNT);
117
118 /* Initialize the Rx Buffer descriptors */
119 for (i = 0; i < PKTBUFSRX; i++) {
120 rx_dp = &cdmac_bd.rx[i];
121 memset(rx_dp, 0, sizeof(*rx_dp));
122 rx_dp->next_p = rx_dp;
123 rx_dp->buf_len = PKTSIZE_ALIGN;
Joe Hershberger9f09a362015-04-08 01:41:06 -0500124 rx_dp->phys_buf_p = (u8 *)net_rx_packets[i];
Stephan Linze1fd4be2012-02-25 00:48:31 +0000125 flush_cache((u32)rx_dp->phys_buf_p, PKTSIZE_ALIGN);
126 }
127 flush_cache((u32)cdmac_bd.rx, sizeof(cdmac_bd.rx));
128
129 /* Initialize the TX Buffer Descriptors */
130 for (i = 0; i < TX_BUF_CNT; i++) {
131 tx_dp = &cdmac_bd.tx[i];
132 memset(tx_dp, 0, sizeof(*tx_dp));
133 tx_dp->next_p = tx_dp;
134 }
135 flush_cache((u32)cdmac_bd.tx, sizeof(cdmac_bd.tx));
136
137 /* Reset index counter to the Rx and Tx Buffer descriptors */
138 rx_idx = tx_idx = 0;
139
140 /* initial Rx DMA start by writing to respective TAILDESC_PTR */
141 ll_temac->out32(ra[RX_CURDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
142 ll_temac->out32(ra[RX_TAILDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
143
144 return 0;
145}
146
147int ll_temac_halt_sdma(struct eth_device *dev)
148{
149 unsigned timeout = 50; /* 1usec * 50 = 50usec */
150 struct ll_temac *ll_temac = dev->priv;
151 phys_addr_t *ra = ll_temac->sdma_reg_addr;
152
153 /*
154 * Soft reset the DMA
155 *
156 * Quote from MPMC documentation: Writing a 1 to this field
157 * forces the DMA engine to shutdown and reset itself. After
158 * setting this bit, software must poll it until the bit is
159 * cleared by the DMA. This indicates that the reset process
160 * is done and the pipeline has been flushed.
161 */
162 ll_temac->out32(ra[DMA_CONTROL_REG], DMA_CONTROL_RESET);
163 while (timeout && (ll_temac->in32(ra[DMA_CONTROL_REG])
164 & DMA_CONTROL_RESET)) {
165 timeout--;
166 udelay(1);
167 }
168
169 if (!timeout) {
170 printf("%s: Timeout\n", __func__);
171 return -1;
172 }
173
174 return 0;
175}
176
177int ll_temac_reset_sdma(struct eth_device *dev)
178{
179 u32 r;
180 struct ll_temac *ll_temac = dev->priv;
181 phys_addr_t *ra = ll_temac->sdma_reg_addr;
182
183 /* Soft reset the DMA. */
184 if (ll_temac_halt_sdma(dev))
185 return -1;
186
187 /* Now clear the interrupts. */
188 r = ll_temac->in32(ra[TX_CHNL_CTRL]);
189 r &= ~CHNL_CTRL_IRQ_MASK;
190 ll_temac->out32(ra[TX_CHNL_CTRL], r);
191
192 r = ll_temac->in32(ra[RX_CHNL_CTRL]);
193 r &= ~CHNL_CTRL_IRQ_MASK;
194 ll_temac->out32(ra[RX_CHNL_CTRL], r);
195
196 /* Now ACK pending IRQs. */
197 ll_temac->out32(ra[TX_IRQ_REG], IRQ_REG_IRQ_MASK);
198 ll_temac->out32(ra[RX_IRQ_REG], IRQ_REG_IRQ_MASK);
199
200 /* Set tail-ptr mode, disable errors for both channels. */
201 ll_temac->out32(ra[DMA_CONTROL_REG],
202 /* Enable use of tail pointer register */
203 DMA_CONTROL_TPE |
204 /* Disable error when 2 or 4 bit coalesce cnt overfl */
205 DMA_CONTROL_RXOCEID |
206 /* Disable error when 2 or 4 bit coalesce cnt overfl */
207 DMA_CONTROL_TXOCEID);
208
209 return 0;
210}
211
212int ll_temac_recv_sdma(struct eth_device *dev)
213{
214 int length, pb_idx;
215 struct cdmac_bd *rx_dp = &cdmac_bd.rx[rx_idx];
216 struct ll_temac *ll_temac = dev->priv;
217 phys_addr_t *ra = ll_temac->sdma_reg_addr;
218
219 if (ll_temac_sdma_error(dev)) {
220
221 if (ll_temac_reset_sdma(dev))
222 return -1;
223
224 ll_temac_init_sdma(dev);
225 }
226
227 flush_cache((u32)rx_dp, sizeof(*rx_dp));
228
229 if (!(rx_dp->sca.stctrl & CDMAC_BD_STCTRL_COMPLETED))
230 return 0;
231
232 if (rx_dp->sca.stctrl & (CDMAC_BD_STCTRL_SOP | CDMAC_BD_STCTRL_EOP)) {
233 pb_idx = rx_idx;
234 length = rx_dp->sca.app[4] & CDMAC_BD_APP4_RXBYTECNT_MASK;
235 } else {
236 pb_idx = -1;
237 length = 0;
238 printf("%s: Got part of package, unsupported (%x)\n",
239 __func__, rx_dp->sca.stctrl);
240 }
241
242 /* flip the buffer */
243 flush_cache((u32)rx_dp->phys_buf_p, length);
244
245 /* reset the current descriptor */
246 rx_dp->sca.stctrl = 0;
247 rx_dp->sca.app[4] = 0;
248 flush_cache((u32)rx_dp, sizeof(*rx_dp));
249
250 /* Find next empty buffer descriptor, preparation for next iteration */
251 rx_idx = (rx_idx + 1) % PKTBUFSRX;
252 rx_dp = &cdmac_bd.rx[rx_idx];
253 flush_cache((u32)rx_dp, sizeof(*rx_dp));
254
255 /* DMA start by writing to respective TAILDESC_PTR */
256 ll_temac->out32(ra[RX_CURDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
257 ll_temac->out32(ra[RX_TAILDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
258
259 if (length > 0 && pb_idx != -1)
Joe Hershberger9f09a362015-04-08 01:41:06 -0500260 net_process_received_packet(net_rx_packets[pb_idx], length);
Stephan Linze1fd4be2012-02-25 00:48:31 +0000261
262 return 0;
263}
264
Stephan Linz458e4fe2012-05-22 12:18:09 +0000265int ll_temac_send_sdma(struct eth_device *dev, void *packet, int length)
Stephan Linze1fd4be2012-02-25 00:48:31 +0000266{
267 unsigned timeout = 50; /* 1usec * 50 = 50usec */
268 struct cdmac_bd *tx_dp = &cdmac_bd.tx[tx_idx];
269 struct ll_temac *ll_temac = dev->priv;
270 phys_addr_t *ra = ll_temac->sdma_reg_addr;
271
272 if (ll_temac_sdma_error(dev)) {
273
274 if (ll_temac_reset_sdma(dev))
275 return -1;
276
277 ll_temac_init_sdma(dev);
278 }
279
280 tx_dp->phys_buf_p = (u8 *)packet;
281 tx_dp->buf_len = length;
282 tx_dp->sca.stctrl = CDMAC_BD_STCTRL_SOP | CDMAC_BD_STCTRL_EOP |
283 CDMAC_BD_STCTRL_STOP_ON_END;
284
285 flush_cache((u32)packet, length);
286 flush_cache((u32)tx_dp, sizeof(*tx_dp));
287
288 /* DMA start by writing to respective TAILDESC_PTR */
289 ll_temac->out32(ra[TX_CURDESC_PTR], (int)tx_dp);
290 ll_temac->out32(ra[TX_TAILDESC_PTR], (int)tx_dp);
291
292 /* Find next empty buffer descriptor, preparation for next iteration */
293 tx_idx = (tx_idx + 1) % TX_BUF_CNT;
294 tx_dp = &cdmac_bd.tx[tx_idx];
295
296 do {
297 flush_cache((u32)tx_dp, sizeof(*tx_dp));
298 udelay(1);
299 } while (timeout-- && !(tx_dp->sca.stctrl & CDMAC_BD_STCTRL_COMPLETED));
300
301 if (!timeout) {
302 printf("%s: Timeout\n", __func__);
303 return -1;
304 }
305
306 return 0;
307}