dm: net: Tidy up designware driver ready for driver model
[oweals/u-boot.git] / drivers / net / designware.c
1 /*
2  * (C) Copyright 2010
3  * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 /*
9  * Designware ethernet IP driver for U-Boot
10  */
11
12 #include <common.h>
13 #include <errno.h>
14 #include <miiphy.h>
15 #include <malloc.h>
16 #include <linux/compiler.h>
17 #include <linux/err.h>
18 #include <asm/io.h>
19 #include "designware.h"
20
21 #if !defined(CONFIG_PHYLIB)
22 # error "DesignWare Ether MAC requires PHYLIB - missing CONFIG_PHYLIB"
23 #endif
24
25 static int dw_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
26 {
27         struct eth_mac_regs *mac_p = bus->priv;
28         ulong start;
29         u16 miiaddr;
30         int timeout = CONFIG_MDIO_TIMEOUT;
31
32         miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) |
33                   ((reg << MIIREGSHIFT) & MII_REGMSK);
34
35         writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
36
37         start = get_timer(0);
38         while (get_timer(start) < timeout) {
39                 if (!(readl(&mac_p->miiaddr) & MII_BUSY))
40                         return readl(&mac_p->miidata);
41                 udelay(10);
42         };
43
44         return -ETIMEDOUT;
45 }
46
47 static int dw_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
48                         u16 val)
49 {
50         struct eth_mac_regs *mac_p = bus->priv;
51         ulong start;
52         u16 miiaddr;
53         int ret = -ETIMEDOUT, timeout = CONFIG_MDIO_TIMEOUT;
54
55         writel(val, &mac_p->miidata);
56         miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) |
57                   ((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE;
58
59         writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
60
61         start = get_timer(0);
62         while (get_timer(start) < timeout) {
63                 if (!(readl(&mac_p->miiaddr) & MII_BUSY)) {
64                         ret = 0;
65                         break;
66                 }
67                 udelay(10);
68         };
69
70         return ret;
71 }
72
73 static int dw_mdio_init(const char *name, struct eth_mac_regs *mac_regs_p)
74 {
75         struct mii_dev *bus = mdio_alloc();
76
77         if (!bus) {
78                 printf("Failed to allocate MDIO bus\n");
79                 return -ENOMEM;
80         }
81
82         bus->read = dw_mdio_read;
83         bus->write = dw_mdio_write;
84         snprintf(bus->name, sizeof(bus->name), name);
85
86         bus->priv = (void *)mac_regs_p;
87
88         return mdio_register(bus);
89 }
90
91 static void tx_descs_init(struct dw_eth_dev *priv)
92 {
93         struct eth_dma_regs *dma_p = priv->dma_regs_p;
94         struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0];
95         char *txbuffs = &priv->txbuffs[0];
96         struct dmamacdescr *desc_p;
97         u32 idx;
98
99         for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
100                 desc_p = &desc_table_p[idx];
101                 desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE];
102                 desc_p->dmamac_next = &desc_table_p[idx + 1];
103
104 #if defined(CONFIG_DW_ALTDESCRIPTOR)
105                 desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST |
106                                 DESC_TXSTS_TXFIRST | DESC_TXSTS_TXCRCDIS | \
107                                 DESC_TXSTS_TXCHECKINSCTRL | \
108                                 DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS);
109
110                 desc_p->txrx_status |= DESC_TXSTS_TXCHAIN;
111                 desc_p->dmamac_cntl = 0;
112                 desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA);
113 #else
114                 desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN;
115                 desc_p->txrx_status = 0;
116 #endif
117         }
118
119         /* Correcting the last pointer of the chain */
120         desc_p->dmamac_next = &desc_table_p[0];
121
122         /* Flush all Tx buffer descriptors at once */
123         flush_dcache_range((unsigned int)priv->tx_mac_descrtable,
124                            (unsigned int)priv->tx_mac_descrtable +
125                            sizeof(priv->tx_mac_descrtable));
126
127         writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr);
128         priv->tx_currdescnum = 0;
129 }
130
131 static void rx_descs_init(struct dw_eth_dev *priv)
132 {
133         struct eth_dma_regs *dma_p = priv->dma_regs_p;
134         struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0];
135         char *rxbuffs = &priv->rxbuffs[0];
136         struct dmamacdescr *desc_p;
137         u32 idx;
138
139         /* Before passing buffers to GMAC we need to make sure zeros
140          * written there right after "priv" structure allocation were
141          * flushed into RAM.
142          * Otherwise there's a chance to get some of them flushed in RAM when
143          * GMAC is already pushing data to RAM via DMA. This way incoming from
144          * GMAC data will be corrupted. */
145         flush_dcache_range((unsigned int)rxbuffs, (unsigned int)rxbuffs +
146                            RX_TOTAL_BUFSIZE);
147
148         for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
149                 desc_p = &desc_table_p[idx];
150                 desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE];
151                 desc_p->dmamac_next = &desc_table_p[idx + 1];
152
153                 desc_p->dmamac_cntl =
154                         (MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) | \
155                                       DESC_RXCTRL_RXCHAIN;
156
157                 desc_p->txrx_status = DESC_RXSTS_OWNBYDMA;
158         }
159
160         /* Correcting the last pointer of the chain */
161         desc_p->dmamac_next = &desc_table_p[0];
162
163         /* Flush all Rx buffer descriptors at once */
164         flush_dcache_range((unsigned int)priv->rx_mac_descrtable,
165                            (unsigned int)priv->rx_mac_descrtable +
166                            sizeof(priv->rx_mac_descrtable));
167
168         writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr);
169         priv->rx_currdescnum = 0;
170 }
171
172 static int _dw_write_hwaddr(struct dw_eth_dev *priv, u8 *mac_id)
173 {
174         struct eth_mac_regs *mac_p = priv->mac_regs_p;
175         u32 macid_lo, macid_hi;
176
177         macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) +
178                    (mac_id[3] << 24);
179         macid_hi = mac_id[4] + (mac_id[5] << 8);
180
181         writel(macid_hi, &mac_p->macaddr0hi);
182         writel(macid_lo, &mac_p->macaddr0lo);
183
184         return 0;
185 }
186
187 static void dw_adjust_link(struct eth_mac_regs *mac_p,
188                            struct phy_device *phydev)
189 {
190         u32 conf = readl(&mac_p->conf) | FRAMEBURSTENABLE | DISABLERXOWN;
191
192         if (!phydev->link) {
193                 printf("%s: No link.\n", phydev->dev->name);
194                 return;
195         }
196
197         if (phydev->speed != 1000)
198                 conf |= MII_PORTSELECT;
199
200         if (phydev->speed == 100)
201                 conf |= FES_100;
202
203         if (phydev->duplex)
204                 conf |= FULLDPLXMODE;
205
206         writel(conf, &mac_p->conf);
207
208         printf("Speed: %d, %s duplex%s\n", phydev->speed,
209                (phydev->duplex) ? "full" : "half",
210                (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
211 }
212
213 static void _dw_eth_halt(struct dw_eth_dev *priv)
214 {
215         struct eth_mac_regs *mac_p = priv->mac_regs_p;
216         struct eth_dma_regs *dma_p = priv->dma_regs_p;
217
218         writel(readl(&mac_p->conf) & ~(RXENABLE | TXENABLE), &mac_p->conf);
219         writel(readl(&dma_p->opmode) & ~(RXSTART | TXSTART), &dma_p->opmode);
220
221         phy_shutdown(priv->phydev);
222 }
223
224 static int _dw_eth_init(struct dw_eth_dev *priv, u8 *enetaddr)
225 {
226         struct eth_mac_regs *mac_p = priv->mac_regs_p;
227         struct eth_dma_regs *dma_p = priv->dma_regs_p;
228         unsigned int start;
229         int ret;
230
231         writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode);
232
233         start = get_timer(0);
234         while (readl(&dma_p->busmode) & DMAMAC_SRST) {
235                 if (get_timer(start) >= CONFIG_MACRESET_TIMEOUT) {
236                         printf("DMA reset timeout\n");
237                         return -ETIMEDOUT;
238                 }
239
240                 mdelay(100);
241         };
242
243         /* Soft reset above clears HW address registers.
244          * So we have to set it here once again */
245         _dw_write_hwaddr(priv, enetaddr);
246
247         rx_descs_init(priv);
248         tx_descs_init(priv);
249
250         writel(FIXEDBURST | PRIORXTX_41 | DMA_PBL, &dma_p->busmode);
251
252 #ifndef CONFIG_DW_MAC_FORCE_THRESHOLD_MODE
253         writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD,
254                &dma_p->opmode);
255 #else
256         writel(readl(&dma_p->opmode) | FLUSHTXFIFO,
257                &dma_p->opmode);
258 #endif
259
260         writel(readl(&dma_p->opmode) | RXSTART | TXSTART, &dma_p->opmode);
261
262 #ifdef CONFIG_DW_AXI_BURST_LEN
263         writel((CONFIG_DW_AXI_BURST_LEN & 0x1FF >> 1), &dma_p->axibus);
264 #endif
265
266         /* Start up the PHY */
267         ret = phy_startup(priv->phydev);
268         if (ret) {
269                 printf("Could not initialize PHY %s\n",
270                        priv->phydev->dev->name);
271                 return ret;
272         }
273
274         dw_adjust_link(mac_p, priv->phydev);
275
276         if (!priv->phydev->link)
277                 return -EIO;
278
279         writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf);
280
281         return 0;
282 }
283
284 static int _dw_eth_send(struct dw_eth_dev *priv, void *packet, int length)
285 {
286         struct eth_dma_regs *dma_p = priv->dma_regs_p;
287         u32 desc_num = priv->tx_currdescnum;
288         struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
289         uint32_t desc_start = (uint32_t)desc_p;
290         uint32_t desc_end = desc_start +
291                 roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
292         uint32_t data_start = (uint32_t)desc_p->dmamac_addr;
293         uint32_t data_end = data_start +
294                 roundup(length, ARCH_DMA_MINALIGN);
295         /*
296          * Strictly we only need to invalidate the "txrx_status" field
297          * for the following check, but on some platforms we cannot
298          * invalidate only 4 bytes, so we flush the entire descriptor,
299          * which is 16 bytes in total. This is safe because the
300          * individual descriptors in the array are each aligned to
301          * ARCH_DMA_MINALIGN and padded appropriately.
302          */
303         invalidate_dcache_range(desc_start, desc_end);
304
305         /* Check if the descriptor is owned by CPU */
306         if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) {
307                 printf("CPU not owner of tx frame\n");
308                 return -EPERM;
309         }
310
311         memcpy(desc_p->dmamac_addr, packet, length);
312
313         /* Flush data to be sent */
314         flush_dcache_range(data_start, data_end);
315
316 #if defined(CONFIG_DW_ALTDESCRIPTOR)
317         desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST;
318         desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \
319                                DESC_TXCTRL_SIZE1MASK;
320
321         desc_p->txrx_status &= ~(DESC_TXSTS_MSK);
322         desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA;
323 #else
324         desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) & \
325                                DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST | \
326                                DESC_TXCTRL_TXFIRST;
327
328         desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
329 #endif
330
331         /* Flush modified buffer descriptor */
332         flush_dcache_range(desc_start, desc_end);
333
334         /* Test the wrap-around condition. */
335         if (++desc_num >= CONFIG_TX_DESCR_NUM)
336                 desc_num = 0;
337
338         priv->tx_currdescnum = desc_num;
339
340         /* Start the transmission */
341         writel(POLL_DATA, &dma_p->txpolldemand);
342
343         return 0;
344 }
345
346 static int _dw_eth_recv(struct dw_eth_dev *priv)
347 {
348         u32 status, desc_num = priv->rx_currdescnum;
349         struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num];
350         int length = 0;
351         uint32_t desc_start = (uint32_t)desc_p;
352         uint32_t desc_end = desc_start +
353                 roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN);
354         uint32_t data_start = (uint32_t)desc_p->dmamac_addr;
355         uint32_t data_end;
356
357         /* Invalidate entire buffer descriptor */
358         invalidate_dcache_range(desc_start, desc_end);
359
360         status = desc_p->txrx_status;
361
362         /* Check  if the owner is the CPU */
363         if (!(status & DESC_RXSTS_OWNBYDMA)) {
364
365                 length = (status & DESC_RXSTS_FRMLENMSK) >> \
366                          DESC_RXSTS_FRMLENSHFT;
367
368                 /* Invalidate received data */
369                 data_end = data_start + roundup(length, ARCH_DMA_MINALIGN);
370                 invalidate_dcache_range(data_start, data_end);
371
372                 net_process_received_packet(desc_p->dmamac_addr, length);
373
374                 /*
375                  * Make the current descriptor valid again and go to
376                  * the next one
377                  */
378                 desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
379
380                 /* Flush only status field - others weren't changed */
381                 flush_dcache_range(desc_start, desc_end);
382
383                 /* Test the wrap-around condition. */
384                 if (++desc_num >= CONFIG_RX_DESCR_NUM)
385                         desc_num = 0;
386         }
387
388         priv->rx_currdescnum = desc_num;
389
390         return length;
391 }
392
393 static int dw_phy_init(struct dw_eth_dev *priv, void *dev)
394 {
395         struct phy_device *phydev;
396         int mask = 0xffffffff;
397
398 #ifdef CONFIG_PHY_ADDR
399         mask = 1 << CONFIG_PHY_ADDR;
400 #endif
401
402         phydev = phy_find_by_mask(priv->bus, mask, priv->interface);
403         if (!phydev)
404                 return -ENODEV;
405
406         phy_connect_dev(phydev, dev);
407
408         phydev->supported &= PHY_GBIT_FEATURES;
409         phydev->advertising = phydev->supported;
410
411         priv->phydev = phydev;
412         phy_config(phydev);
413
414         return 0;
415 }
416
417 static int dw_eth_init(struct eth_device *dev, bd_t *bis)
418 {
419         return _dw_eth_init(dev->priv, dev->enetaddr);
420 }
421
422 static int dw_eth_send(struct eth_device *dev, void *packet, int length)
423 {
424         return _dw_eth_send(dev->priv, packet, length);
425 }
426
427 static int dw_eth_recv(struct eth_device *dev)
428 {
429         return _dw_eth_recv(dev->priv);
430 }
431
432 static void dw_eth_halt(struct eth_device *dev)
433 {
434         return _dw_eth_halt(dev->priv);
435 }
436
437 static int dw_write_hwaddr(struct eth_device *dev)
438 {
439         return _dw_write_hwaddr(dev->priv, dev->enetaddr);
440 }
441
442 int designware_initialize(ulong base_addr, u32 interface)
443 {
444         struct eth_device *dev;
445         struct dw_eth_dev *priv;
446
447         dev = (struct eth_device *) malloc(sizeof(struct eth_device));
448         if (!dev)
449                 return -ENOMEM;
450
451         /*
452          * Since the priv structure contains the descriptors which need a strict
453          * buswidth alignment, memalign is used to allocate memory
454          */
455         priv = (struct dw_eth_dev *) memalign(ARCH_DMA_MINALIGN,
456                                               sizeof(struct dw_eth_dev));
457         if (!priv) {
458                 free(dev);
459                 return -ENOMEM;
460         }
461
462         memset(dev, 0, sizeof(struct eth_device));
463         memset(priv, 0, sizeof(struct dw_eth_dev));
464
465         sprintf(dev->name, "dwmac.%lx", base_addr);
466         dev->iobase = (int)base_addr;
467         dev->priv = priv;
468
469         priv->dev = dev;
470         priv->mac_regs_p = (struct eth_mac_regs *)base_addr;
471         priv->dma_regs_p = (struct eth_dma_regs *)(base_addr +
472                         DW_DMA_BASE_OFFSET);
473
474         dev->init = dw_eth_init;
475         dev->send = dw_eth_send;
476         dev->recv = dw_eth_recv;
477         dev->halt = dw_eth_halt;
478         dev->write_hwaddr = dw_write_hwaddr;
479
480         eth_register(dev);
481
482         priv->interface = interface;
483
484         dw_mdio_init(dev->name, priv->mac_regs_p);
485         priv->bus = miiphy_get_dev_by_name(dev->name);
486
487         return dw_phy_init(priv, dev);
488 }