blob: 2225b33ff65173f6d3d49103c0753d2919627c15 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01002/*
3 * Copyright (C) 2005-2006 Atmel Corporation
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01004 */
5#include <common.h>
Wenyou Yang3d8d3482016-11-02 10:06:56 +08006#include <clk.h>
Simon Glass63334482019-11-14 12:57:39 -07007#include <cpu_func.h>
Simon Glass75c5d182016-05-05 07:28:11 -06008#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Simon Glassdbd79542020-05-10 11:40:11 -060010#include <linux/delay.h>
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010011
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010012/*
13 * The u-boot networking stack is a little weird. It seems like the
14 * networking core allocates receive buffers up front without any
15 * regard to the hardware that's supposed to actually receive those
16 * packets.
17 *
18 * The MACB receives packets into 128-byte receive buffers, so the
19 * buffers allocated by the core isn't very practical to use. We'll
20 * allocate our own, but we need one such buffer in case a packet
21 * wraps around the DMA ring so that we have to copy it.
22 *
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020023 * Therefore, define CONFIG_SYS_RX_ETH_BUFFER to 1 in the board-specific
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010024 * configuration header. This way, the core allocates one RX buffer
25 * and one TX buffer, each of which can hold a ethernet packet of
26 * maximum size.
27 *
28 * For some reason, the networking core unconditionally specifies a
29 * 32-byte packet "alignment" (which really should be called
30 * "padding"). MACB shouldn't need that, but we'll refrain from any
31 * core modifications here...
32 */
33
34#include <net.h>
Simon Glass75c5d182016-05-05 07:28:11 -060035#ifndef CONFIG_DM_ETH
Ben Warren2f2b6b62008-08-31 22:22:04 -070036#include <netdev.h>
Simon Glass75c5d182016-05-05 07:28:11 -060037#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010038#include <malloc.h>
Semih Hazar790088e2009-12-17 15:07:15 +020039#include <miiphy.h>
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010040
41#include <linux/mii.h>
42#include <asm/io.h>
Masahiro Yamada6373a172020-02-14 16:40:19 +090043#include <linux/dma-mapping.h>
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010044#include <asm/arch/clk.h>
Masahiro Yamada64e4f7f2016-09-21 11:28:57 +090045#include <linux/errno.h>
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010046
47#include "macb.h"
48
Wenyou Yang7b811852016-05-17 13:11:35 +080049DECLARE_GLOBAL_DATA_PTR;
50
Ramon Fried377d19d2019-07-14 18:25:14 +030051/*
52 * These buffer sizes must be power of 2 and divisible
53 * by RX_BUFFER_MULTIPLE
54 */
55#define MACB_RX_BUFFER_SIZE 128
56#define GEM_RX_BUFFER_SIZE 2048
Ramon Friedb40501f2019-07-16 22:04:36 +030057#define RX_BUFFER_MULTIPLE 64
Ramon Fried377d19d2019-07-14 18:25:14 +030058
59#define MACB_RX_RING_SIZE 32
Andreas Bießmann1e868122014-05-26 22:55:18 +020060#define MACB_TX_RING_SIZE 16
Ramon Fried377d19d2019-07-14 18:25:14 +030061
Andreas Bießmann1e868122014-05-26 22:55:18 +020062#define MACB_TX_TIMEOUT 1000
63#define MACB_AUTONEG_TIMEOUT 5000000
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010064
Wilson Lee41d6d1e2017-08-22 20:25:07 -070065#ifdef CONFIG_MACB_ZYNQ
66/* INCR4 AHB bursts */
67#define MACB_ZYNQ_GEM_DMACR_BLENGTH 0x00000004
68/* Use full configured addressable space (8 Kb) */
69#define MACB_ZYNQ_GEM_DMACR_RXSIZE 0x00000300
70/* Use full configured addressable space (4 Kb) */
71#define MACB_ZYNQ_GEM_DMACR_TXSIZE 0x00000400
72/* Set RXBUF with use of 128 byte */
73#define MACB_ZYNQ_GEM_DMACR_RXBUF 0x00020000
74#define MACB_ZYNQ_GEM_DMACR_INIT \
75 (MACB_ZYNQ_GEM_DMACR_BLENGTH | \
76 MACB_ZYNQ_GEM_DMACR_RXSIZE | \
77 MACB_ZYNQ_GEM_DMACR_TXSIZE | \
78 MACB_ZYNQ_GEM_DMACR_RXBUF)
79#endif
80
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010081struct macb_dma_desc {
82 u32 addr;
83 u32 ctrl;
84};
85
Padmarao Begari7a2c4962021-01-15 08:20:36 +053086struct macb_dma_desc_64 {
87 u32 addrh;
88 u32 unused;
89};
90
91#define HW_DMA_CAP_32B 0
92#define HW_DMA_CAP_64B 1
93
94#define DMA_DESC_SIZE 16
95#define DMA_DESC_BYTES(n) ((n) * DMA_DESC_SIZE)
Wu, Josh18052402014-05-27 16:31:05 +080096#define MACB_TX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_TX_RING_SIZE))
97#define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE))
Wu, Josh012d68d2015-06-03 16:45:44 +080098#define MACB_TX_DUMMY_DMA_DESC_SIZE (DMA_DESC_BYTES(1))
Wu, Josh18052402014-05-27 16:31:05 +080099
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100100#define RXBUF_FRMLEN_MASK 0x00000fff
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100101#define TXBUF_FRMLEN_MASK 0x000007ff
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100102
103struct macb_device {
104 void *regs;
Anup Patel88799a62019-07-24 04:09:32 +0000105
Anup Patela1818b12019-07-24 04:09:37 +0000106 bool is_big_endian;
107
Anup Patel88799a62019-07-24 04:09:32 +0000108 const struct macb_config *config;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100109
110 unsigned int rx_tail;
111 unsigned int tx_head;
112 unsigned int tx_tail;
Simon Glass5ad27512016-05-05 07:28:09 -0600113 unsigned int next_rx_tail;
114 bool wrapped;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100115
116 void *rx_buffer;
117 void *tx_buffer;
118 struct macb_dma_desc *rx_ring;
119 struct macb_dma_desc *tx_ring;
Ramon Fried377d19d2019-07-14 18:25:14 +0300120 size_t rx_buffer_size;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100121
122 unsigned long rx_buffer_dma;
123 unsigned long rx_ring_dma;
124 unsigned long tx_ring_dma;
125
Wu, Josh012d68d2015-06-03 16:45:44 +0800126 struct macb_dma_desc *dummy_desc;
127 unsigned long dummy_desc_dma;
128
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100129 const struct device *dev;
Simon Glass75c5d182016-05-05 07:28:11 -0600130#ifndef CONFIG_DM_ETH
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100131 struct eth_device netdev;
Simon Glass75c5d182016-05-05 07:28:11 -0600132#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100133 unsigned short phy_addr;
Bo Shen7d91deb2013-04-24 15:59:27 +0800134 struct mii_dev *bus;
Wenyou Yang44835ea2017-04-14 14:36:04 +0800135#ifdef CONFIG_PHYLIB
136 struct phy_device *phydev;
137#endif
Wenyou Yang7b811852016-05-17 13:11:35 +0800138
139#ifdef CONFIG_DM_ETH
Wenyou Yang19449362017-02-14 16:24:40 +0800140#ifdef CONFIG_CLK
Wenyou Yang3d8d3482016-11-02 10:06:56 +0800141 unsigned long pclk_rate;
Wenyou Yang19449362017-02-14 16:24:40 +0800142#endif
Wenyou Yang7b811852016-05-17 13:11:35 +0800143 phy_interface_t phy_interface;
144#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100145};
Ramon Fried834040c2019-07-16 22:04:35 +0300146
147struct macb_config {
148 unsigned int dma_burst_length;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530149 unsigned int hw_dma_cap;
Anup Patel88799a62019-07-24 04:09:32 +0000150
151 int (*clk_init)(struct udevice *dev, ulong rate);
Ramon Fried834040c2019-07-16 22:04:35 +0300152};
153
Simon Glass75c5d182016-05-05 07:28:11 -0600154#ifndef CONFIG_DM_ETH
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100155#define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
Simon Glass75c5d182016-05-05 07:28:11 -0600156#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100157
Bo Shen6f7d7d92013-04-24 15:59:28 +0800158static int macb_is_gem(struct macb_device *macb)
159{
Atish Patrae1a85182019-02-25 08:14:42 +0000160 return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) >= 0x2;
Bo Shen6f7d7d92013-04-24 15:59:28 +0800161}
162
Gregory CLEMENTf1a1e582015-12-16 14:50:34 +0100163#ifndef cpu_is_sama5d2
164#define cpu_is_sama5d2() 0
165#endif
166
167#ifndef cpu_is_sama5d4
168#define cpu_is_sama5d4() 0
169#endif
170
171static int gem_is_gigabit_capable(struct macb_device *macb)
172{
173 /*
Robert P. J. Day8c60f922016-05-04 04:47:31 -0400174 * The GEM controllers embedded in SAMA5D2 and SAMA5D4 are
Gregory CLEMENTf1a1e582015-12-16 14:50:34 +0100175 * configured to support only 10/100.
176 */
177 return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4();
178}
179
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200180static void macb_mdio_write(struct macb_device *macb, u8 phy_adr, u8 reg,
181 u16 value)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100182{
183 unsigned long netctl;
184 unsigned long netstat;
185 unsigned long frame;
186
187 netctl = macb_readl(macb, NCR);
188 netctl |= MACB_BIT(MPE);
189 macb_writel(macb, NCR, netctl);
190
191 frame = (MACB_BF(SOF, 1)
192 | MACB_BF(RW, 1)
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200193 | MACB_BF(PHYA, phy_adr)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100194 | MACB_BF(REGA, reg)
195 | MACB_BF(CODE, 2)
196 | MACB_BF(DATA, value));
197 macb_writel(macb, MAN, frame);
198
199 do {
200 netstat = macb_readl(macb, NSR);
201 } while (!(netstat & MACB_BIT(IDLE)));
202
203 netctl = macb_readl(macb, NCR);
204 netctl &= ~MACB_BIT(MPE);
205 macb_writel(macb, NCR, netctl);
206}
207
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200208static u16 macb_mdio_read(struct macb_device *macb, u8 phy_adr, u8 reg)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100209{
210 unsigned long netctl;
211 unsigned long netstat;
212 unsigned long frame;
213
214 netctl = macb_readl(macb, NCR);
215 netctl |= MACB_BIT(MPE);
216 macb_writel(macb, NCR, netctl);
217
218 frame = (MACB_BF(SOF, 1)
219 | MACB_BF(RW, 2)
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200220 | MACB_BF(PHYA, phy_adr)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100221 | MACB_BF(REGA, reg)
222 | MACB_BF(CODE, 2));
223 macb_writel(macb, MAN, frame);
224
225 do {
226 netstat = macb_readl(macb, NSR);
227 } while (!(netstat & MACB_BIT(IDLE)));
228
229 frame = macb_readl(macb, MAN);
230
231 netctl = macb_readl(macb, NCR);
232 netctl &= ~MACB_BIT(MPE);
233 macb_writel(macb, NCR, netctl);
234
235 return MACB_BFEXT(DATA, frame);
236}
237
Joe Hershberger9e5742b2013-06-24 19:06:38 -0500238void __weak arch_get_mdio_control(const char *name)
Shiraz Hashim77cdf0f2012-12-13 17:22:52 +0530239{
240 return;
241}
242
Bo Shen7d91deb2013-04-24 15:59:27 +0800243#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
Semih Hazar790088e2009-12-17 15:07:15 +0200244
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500245int macb_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg)
Semih Hazar790088e2009-12-17 15:07:15 +0200246{
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500247 u16 value = 0;
Simon Glass75c5d182016-05-05 07:28:11 -0600248#ifdef CONFIG_DM_ETH
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500249 struct udevice *dev = eth_get_dev_by_name(bus->name);
Simon Glass75c5d182016-05-05 07:28:11 -0600250 struct macb_device *macb = dev_get_priv(dev);
251#else
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500252 struct eth_device *dev = eth_get_dev_by_name(bus->name);
Semih Hazar790088e2009-12-17 15:07:15 +0200253 struct macb_device *macb = to_macb(dev);
Simon Glass75c5d182016-05-05 07:28:11 -0600254#endif
Semih Hazar790088e2009-12-17 15:07:15 +0200255
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500256 arch_get_mdio_control(bus->name);
Josef Holzmayr017feb52019-10-02 21:22:52 +0200257 value = macb_mdio_read(macb, phy_adr, reg);
Semih Hazar790088e2009-12-17 15:07:15 +0200258
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500259 return value;
Semih Hazar790088e2009-12-17 15:07:15 +0200260}
261
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500262int macb_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg,
263 u16 value)
Semih Hazar790088e2009-12-17 15:07:15 +0200264{
Simon Glass75c5d182016-05-05 07:28:11 -0600265#ifdef CONFIG_DM_ETH
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500266 struct udevice *dev = eth_get_dev_by_name(bus->name);
Simon Glass75c5d182016-05-05 07:28:11 -0600267 struct macb_device *macb = dev_get_priv(dev);
268#else
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500269 struct eth_device *dev = eth_get_dev_by_name(bus->name);
Semih Hazar790088e2009-12-17 15:07:15 +0200270 struct macb_device *macb = to_macb(dev);
Simon Glass75c5d182016-05-05 07:28:11 -0600271#endif
Semih Hazar790088e2009-12-17 15:07:15 +0200272
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500273 arch_get_mdio_control(bus->name);
Josef Holzmayr017feb52019-10-02 21:22:52 +0200274 macb_mdio_write(macb, phy_adr, reg, value);
Semih Hazar790088e2009-12-17 15:07:15 +0200275
276 return 0;
277}
278#endif
279
Wu, Josh18052402014-05-27 16:31:05 +0800280#define RX 1
281#define TX 0
282static inline void macb_invalidate_ring_desc(struct macb_device *macb, bool rx)
283{
284 if (rx)
Heiko Schocher8353f9d2016-08-29 07:46:11 +0200285 invalidate_dcache_range(macb->rx_ring_dma,
286 ALIGN(macb->rx_ring_dma + MACB_RX_DMA_DESC_SIZE,
287 PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800288 else
Heiko Schocher8353f9d2016-08-29 07:46:11 +0200289 invalidate_dcache_range(macb->tx_ring_dma,
290 ALIGN(macb->tx_ring_dma + MACB_TX_DMA_DESC_SIZE,
291 PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800292}
293
294static inline void macb_flush_ring_desc(struct macb_device *macb, bool rx)
295{
296 if (rx)
297 flush_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma +
Heiko Schocher8353f9d2016-08-29 07:46:11 +0200298 ALIGN(MACB_RX_DMA_DESC_SIZE, PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800299 else
300 flush_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma +
Heiko Schocher8353f9d2016-08-29 07:46:11 +0200301 ALIGN(MACB_TX_DMA_DESC_SIZE, PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800302}
303
304static inline void macb_flush_rx_buffer(struct macb_device *macb)
305{
306 flush_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma +
Stefan Roese7df65a52019-08-26 09:18:11 +0200307 ALIGN(macb->rx_buffer_size * MACB_RX_RING_SIZE,
308 PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800309}
310
311static inline void macb_invalidate_rx_buffer(struct macb_device *macb)
312{
313 invalidate_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma +
Stefan Roese7df65a52019-08-26 09:18:11 +0200314 ALIGN(macb->rx_buffer_size * MACB_RX_RING_SIZE,
315 PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800316}
Semih Hazar790088e2009-12-17 15:07:15 +0200317
Jon Loeligerb1d408a2007-07-09 17:30:01 -0500318#if defined(CONFIG_CMD_NET)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100319
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530320static struct macb_dma_desc_64 *macb_64b_desc(struct macb_dma_desc *desc)
321{
322 return (struct macb_dma_desc_64 *)((void *)desc
323 + sizeof(struct macb_dma_desc));
324}
325
326static void macb_set_addr(struct macb_device *macb, struct macb_dma_desc *desc,
327 ulong addr)
328{
329 struct macb_dma_desc_64 *desc_64;
330
331 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
332 desc_64 = macb_64b_desc(desc);
333 desc_64->addrh = upper_32_bits(addr);
334 }
335 desc->addr = lower_32_bits(addr);
336}
337
Simon Glass5ad27512016-05-05 07:28:09 -0600338static int _macb_send(struct macb_device *macb, const char *name, void *packet,
339 int length)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100340{
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100341 unsigned long paddr, ctrl;
342 unsigned int tx_head = macb->tx_head;
343 int i;
344
345 paddr = dma_map_single(packet, length, DMA_TO_DEVICE);
346
347 ctrl = length & TXBUF_FRMLEN_MASK;
Ramon Fried6402fb192019-07-16 22:04:33 +0300348 ctrl |= MACB_BIT(TX_LAST);
Andreas Bießmann1e868122014-05-26 22:55:18 +0200349 if (tx_head == (MACB_TX_RING_SIZE - 1)) {
Ramon Fried6402fb192019-07-16 22:04:33 +0300350 ctrl |= MACB_BIT(TX_WRAP);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100351 macb->tx_head = 0;
Andreas Bießmann1e868122014-05-26 22:55:18 +0200352 } else {
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100353 macb->tx_head++;
Andreas Bießmann1e868122014-05-26 22:55:18 +0200354 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100355
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530356 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
357 tx_head = tx_head * 2;
358
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100359 macb->tx_ring[tx_head].ctrl = ctrl;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530360 macb_set_addr(macb, &macb->tx_ring[tx_head], paddr);
361
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200362 barrier();
Wu, Josh18052402014-05-27 16:31:05 +0800363 macb_flush_ring_desc(macb, TX);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100364 macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
365
366 /*
367 * I guess this is necessary because the networking core may
368 * re-use the transmit buffer as soon as we return...
369 */
Andreas Bießmann1e868122014-05-26 22:55:18 +0200370 for (i = 0; i <= MACB_TX_TIMEOUT; i++) {
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200371 barrier();
Wu, Josh18052402014-05-27 16:31:05 +0800372 macb_invalidate_ring_desc(macb, TX);
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200373 ctrl = macb->tx_ring[tx_head].ctrl;
Ramon Fried6402fb192019-07-16 22:04:33 +0300374 if (ctrl & MACB_BIT(TX_USED))
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100375 break;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100376 udelay(1);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100377 }
378
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900379 dma_unmap_single(paddr, length, DMA_TO_DEVICE);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100380
Andreas Bießmann1e868122014-05-26 22:55:18 +0200381 if (i <= MACB_TX_TIMEOUT) {
Ramon Fried6402fb192019-07-16 22:04:33 +0300382 if (ctrl & MACB_BIT(TX_UNDERRUN))
Simon Glass5ad27512016-05-05 07:28:09 -0600383 printf("%s: TX underrun\n", name);
Ramon Fried6402fb192019-07-16 22:04:33 +0300384 if (ctrl & MACB_BIT(TX_BUF_EXHAUSTED))
Simon Glass5ad27512016-05-05 07:28:09 -0600385 printf("%s: TX buffers exhausted in mid frame\n", name);
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200386 } else {
Simon Glass5ad27512016-05-05 07:28:09 -0600387 printf("%s: TX timeout\n", name);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100388 }
389
390 /* No one cares anyway */
391 return 0;
392}
393
394static void reclaim_rx_buffers(struct macb_device *macb,
395 unsigned int new_tail)
396{
397 unsigned int i;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530398 unsigned int count;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100399
400 i = macb->rx_tail;
Wu, Josh18052402014-05-27 16:31:05 +0800401
402 macb_invalidate_ring_desc(macb, RX);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100403 while (i > new_tail) {
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530404 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
405 count = i * 2;
406 else
407 count = i;
408 macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100409 i++;
Andreas Bießmann1e868122014-05-26 22:55:18 +0200410 if (i > MACB_RX_RING_SIZE)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100411 i = 0;
412 }
413
414 while (i < new_tail) {
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530415 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
416 count = i * 2;
417 else
418 count = i;
419 macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100420 i++;
421 }
422
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200423 barrier();
Wu, Josh18052402014-05-27 16:31:05 +0800424 macb_flush_ring_desc(macb, RX);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100425 macb->rx_tail = new_tail;
426}
427
Simon Glass5ad27512016-05-05 07:28:09 -0600428static int _macb_recv(struct macb_device *macb, uchar **packetp)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100429{
Simon Glass5ad27512016-05-05 07:28:09 -0600430 unsigned int next_rx_tail = macb->next_rx_tail;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100431 void *buffer;
432 int length;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100433 u32 status;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530434 u8 flag = false;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100435
Simon Glass5ad27512016-05-05 07:28:09 -0600436 macb->wrapped = false;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100437 for (;;) {
Wu, Josh18052402014-05-27 16:31:05 +0800438 macb_invalidate_ring_desc(macb, RX);
439
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530440 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
441 next_rx_tail = next_rx_tail * 2;
442
Ramon Fried6402fb192019-07-16 22:04:33 +0300443 if (!(macb->rx_ring[next_rx_tail].addr & MACB_BIT(RX_USED)))
Simon Glass5ad27512016-05-05 07:28:09 -0600444 return -EAGAIN;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100445
Simon Glass5ad27512016-05-05 07:28:09 -0600446 status = macb->rx_ring[next_rx_tail].ctrl;
Ramon Fried6402fb192019-07-16 22:04:33 +0300447 if (status & MACB_BIT(RX_SOF)) {
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530448 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
449 next_rx_tail = next_rx_tail / 2;
450 flag = true;
451 }
452
Simon Glass5ad27512016-05-05 07:28:09 -0600453 if (next_rx_tail != macb->rx_tail)
454 reclaim_rx_buffers(macb, next_rx_tail);
455 macb->wrapped = false;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100456 }
457
Ramon Fried6402fb192019-07-16 22:04:33 +0300458 if (status & MACB_BIT(RX_EOF)) {
Ramon Fried377d19d2019-07-14 18:25:14 +0300459 buffer = macb->rx_buffer +
460 macb->rx_buffer_size * macb->rx_tail;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100461 length = status & RXBUF_FRMLEN_MASK;
Wu, Josh18052402014-05-27 16:31:05 +0800462
463 macb_invalidate_rx_buffer(macb);
Simon Glass5ad27512016-05-05 07:28:09 -0600464 if (macb->wrapped) {
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100465 unsigned int headlen, taillen;
466
Ramon Fried377d19d2019-07-14 18:25:14 +0300467 headlen = macb->rx_buffer_size *
468 (MACB_RX_RING_SIZE - macb->rx_tail);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100469 taillen = length - headlen;
Joe Hershberger9f09a362015-04-08 01:41:06 -0500470 memcpy((void *)net_rx_packets[0],
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100471 buffer, headlen);
Joe Hershberger9f09a362015-04-08 01:41:06 -0500472 memcpy((void *)net_rx_packets[0] + headlen,
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100473 macb->rx_buffer, taillen);
Simon Glass5ad27512016-05-05 07:28:09 -0600474 *packetp = (void *)net_rx_packets[0];
475 } else {
476 *packetp = buffer;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100477 }
478
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530479 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
480 if (!flag)
481 next_rx_tail = next_rx_tail / 2;
482 }
483
Simon Glass5ad27512016-05-05 07:28:09 -0600484 if (++next_rx_tail >= MACB_RX_RING_SIZE)
485 next_rx_tail = 0;
486 macb->next_rx_tail = next_rx_tail;
487 return length;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100488 } else {
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530489 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
490 if (!flag)
491 next_rx_tail = next_rx_tail / 2;
492 flag = false;
493 }
494
Simon Glass5ad27512016-05-05 07:28:09 -0600495 if (++next_rx_tail >= MACB_RX_RING_SIZE) {
496 macb->wrapped = true;
497 next_rx_tail = 0;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100498 }
499 }
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200500 barrier();
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100501 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100502}
503
Simon Glass5ad27512016-05-05 07:28:09 -0600504static void macb_phy_reset(struct macb_device *macb, const char *name)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100505{
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100506 int i;
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200507 u16 status, adv;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100508
509 adv = ADVERTISE_CSMA | ADVERTISE_ALL;
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200510 macb_mdio_write(macb, macb->phy_addr, MII_ADVERTISE, adv);
Simon Glass5ad27512016-05-05 07:28:09 -0600511 printf("%s: Starting autonegotiation...\n", name);
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200512 macb_mdio_write(macb, macb->phy_addr, MII_BMCR, (BMCR_ANENABLE
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100513 | BMCR_ANRESTART));
514
Andreas Bießmann1e868122014-05-26 22:55:18 +0200515 for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200516 status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100517 if (status & BMSR_ANEGCOMPLETE)
518 break;
519 udelay(100);
520 }
521
522 if (status & BMSR_ANEGCOMPLETE)
Simon Glass5ad27512016-05-05 07:28:09 -0600523 printf("%s: Autonegotiation complete\n", name);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100524 else
525 printf("%s: Autonegotiation timed out (status=0x%04x)\n",
Simon Glass5ad27512016-05-05 07:28:09 -0600526 name, status);
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200527}
528
Wenyou Yang7b811852016-05-17 13:11:35 +0800529static int macb_phy_find(struct macb_device *macb, const char *name)
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100530{
531 int i;
532 u16 phy_id;
533
Padmarao Begari34394ba2021-01-15 08:20:37 +0530534 phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
535 if (phy_id != 0xffff) {
536 printf("%s: PHY present at %d\n", name, macb->phy_addr);
537 return 0;
538 }
539
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100540 /* Search for PHY... */
541 for (i = 0; i < 32; i++) {
542 macb->phy_addr = i;
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200543 phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100544 if (phy_id != 0xffff) {
Wenyou Yang7b811852016-05-17 13:11:35 +0800545 printf("%s: PHY present at %d\n", name, i);
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700546 return 0;
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100547 }
548 }
549
550 /* PHY isn't up to snuff */
Wenyou Yang7b811852016-05-17 13:11:35 +0800551 printf("%s: PHY not found\n", name);
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100552
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700553 return -ENODEV;
554}
555
556/**
557 * macb_linkspd_cb - Linkspeed change callback function
Bin Mengcf821322019-05-22 00:09:45 -0700558 * @dev/@regs: MACB udevice (DM version) or
559 * Base Register of MACB devices (non-DM version)
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700560 * @speed: Linkspeed
561 * Returns 0 when operation success and negative errno number
562 * when operation failed.
563 */
Bin Mengcf821322019-05-22 00:09:45 -0700564#ifdef CONFIG_DM_ETH
Anup Patel88799a62019-07-24 04:09:32 +0000565static int macb_sifive_clk_init(struct udevice *dev, ulong rate)
566{
567 fdt_addr_t addr;
568 void *gemgxl_regs;
569
570 addr = dev_read_addr_index(dev, 1);
571 if (addr == FDT_ADDR_T_NONE)
572 return -ENODEV;
573
574 gemgxl_regs = (void __iomem *)addr;
575 if (!gemgxl_regs)
576 return -ENODEV;
577
578 /*
579 * SiFive GEMGXL TX clock operation mode:
580 *
581 * 0 = GMII mode. Use 125 MHz gemgxlclk from PRCI in TX logic
582 * and output clock on GMII output signal GTX_CLK
583 * 1 = MII mode. Use MII input signal TX_CLK in TX logic
584 */
585 writel(rate != 125000000, gemgxl_regs);
586 return 0;
587}
588
Bin Mengcf821322019-05-22 00:09:45 -0700589int __weak macb_linkspd_cb(struct udevice *dev, unsigned int speed)
590{
Bin Meng12766ca2019-05-22 00:09:46 -0700591#ifdef CONFIG_CLK
Anup Patel88799a62019-07-24 04:09:32 +0000592 struct macb_device *macb = dev_get_priv(dev);
Bin Meng12766ca2019-05-22 00:09:46 -0700593 struct clk tx_clk;
594 ulong rate;
595 int ret;
596
Bin Meng12766ca2019-05-22 00:09:46 -0700597 switch (speed) {
598 case _10BASET:
599 rate = 2500000; /* 2.5 MHz */
600 break;
601 case _100BASET:
602 rate = 25000000; /* 25 MHz */
603 break;
604 case _1000BASET:
605 rate = 125000000; /* 125 MHz */
606 break;
607 default:
608 /* does not change anything */
609 return 0;
610 }
611
Anup Patel88799a62019-07-24 04:09:32 +0000612 if (macb->config->clk_init)
613 return macb->config->clk_init(dev, rate);
614
615 /*
616 * "tx_clk" is an optional clock source for MACB.
617 * Ignore if it does not exist in DT.
618 */
619 ret = clk_get_by_name(dev, "tx_clk", &tx_clk);
620 if (ret)
621 return 0;
622
Bin Meng12766ca2019-05-22 00:09:46 -0700623 if (tx_clk.dev) {
624 ret = clk_set_rate(&tx_clk, rate);
625 if (ret)
626 return ret;
627 }
628#endif
629
Bin Mengcf821322019-05-22 00:09:45 -0700630 return 0;
631}
632#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700633int __weak macb_linkspd_cb(void *regs, unsigned int speed)
634{
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100635 return 0;
636}
Bin Mengcf821322019-05-22 00:09:45 -0700637#endif
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100638
Wenyou Yang7b811852016-05-17 13:11:35 +0800639#ifdef CONFIG_DM_ETH
640static int macb_phy_init(struct udevice *dev, const char *name)
641#else
Simon Glass5ad27512016-05-05 07:28:09 -0600642static int macb_phy_init(struct macb_device *macb, const char *name)
Wenyou Yang7b811852016-05-17 13:11:35 +0800643#endif
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200644{
Wenyou Yang7b811852016-05-17 13:11:35 +0800645#ifdef CONFIG_DM_ETH
646 struct macb_device *macb = dev_get_priv(dev);
647#endif
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200648 u32 ncfgr;
649 u16 phy_id, status, adv, lpa;
650 int media, speed, duplex;
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700651 int ret;
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200652 int i;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100653
Simon Glass5ad27512016-05-05 07:28:09 -0600654 arch_get_mdio_control(name);
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100655 /* Auto-detect phy_addr */
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700656 ret = macb_phy_find(macb, name);
657 if (ret)
658 return ret;
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100659
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200660 /* Check if the PHY is up to snuff... */
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200661 phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200662 if (phy_id == 0xffff) {
Simon Glass5ad27512016-05-05 07:28:09 -0600663 printf("%s: No PHY present\n", name);
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700664 return -ENODEV;
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200665 }
666
Bo Shen7d91deb2013-04-24 15:59:27 +0800667#ifdef CONFIG_PHYLIB
Wenyou Yang7b811852016-05-17 13:11:35 +0800668#ifdef CONFIG_DM_ETH
Wenyou Yang44835ea2017-04-14 14:36:04 +0800669 macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev,
Wenyou Yang7b811852016-05-17 13:11:35 +0800670 macb->phy_interface);
671#else
Bo Shene04fe552013-08-19 10:35:47 +0800672 /* need to consider other phy interface mode */
Wenyou Yang44835ea2017-04-14 14:36:04 +0800673 macb->phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev,
Bo Shene04fe552013-08-19 10:35:47 +0800674 PHY_INTERFACE_MODE_RGMII);
Wenyou Yang7b811852016-05-17 13:11:35 +0800675#endif
Wenyou Yang44835ea2017-04-14 14:36:04 +0800676 if (!macb->phydev) {
Bo Shene04fe552013-08-19 10:35:47 +0800677 printf("phy_connect failed\n");
678 return -ENODEV;
679 }
680
Wenyou Yang44835ea2017-04-14 14:36:04 +0800681 phy_config(macb->phydev);
Bo Shen7d91deb2013-04-24 15:59:27 +0800682#endif
683
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200684 status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100685 if (!(status & BMSR_LSTATUS)) {
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200686 /* Try to re-negotiate if we don't have link already. */
Simon Glass5ad27512016-05-05 07:28:09 -0600687 macb_phy_reset(macb, name);
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200688
Andreas Bießmann1e868122014-05-26 22:55:18 +0200689 for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200690 status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
Stefan Roese40291802019-03-27 11:20:19 +0100691 if (status & BMSR_LSTATUS) {
692 /*
693 * Delay a bit after the link is established,
694 * so that the next xfer does not fail
695 */
696 mdelay(10);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100697 break;
Stefan Roese40291802019-03-27 11:20:19 +0100698 }
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200699 udelay(100);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100700 }
701 }
702
703 if (!(status & BMSR_LSTATUS)) {
704 printf("%s: link down (status: 0x%04x)\n",
Simon Glass5ad27512016-05-05 07:28:09 -0600705 name, status);
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700706 return -ENETDOWN;
Bo Shen6f7d7d92013-04-24 15:59:28 +0800707 }
708
Gregory CLEMENTf1a1e582015-12-16 14:50:34 +0100709 /* First check for GMAC and that it is GiB capable */
710 if (gem_is_gigabit_capable(macb)) {
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200711 lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100712
Radu Pirea1676dfb2019-06-07 14:18:36 +0300713 if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
714 LPA_1000XHALF)) {
715 duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ?
716 1 : 0);
Andreas Bießmannd43a89a2014-09-18 23:46:48 +0200717
718 printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
Simon Glass5ad27512016-05-05 07:28:09 -0600719 name,
Bo Shen6f7d7d92013-04-24 15:59:28 +0800720 duplex ? "full" : "half",
721 lpa);
722
723 ncfgr = macb_readl(macb, NCFGR);
Andreas Bießmannd43a89a2014-09-18 23:46:48 +0200724 ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
725 ncfgr |= GEM_BIT(GBE);
726
Bo Shen6f7d7d92013-04-24 15:59:28 +0800727 if (duplex)
728 ncfgr |= MACB_BIT(FD);
Andreas Bießmannd43a89a2014-09-18 23:46:48 +0200729
Bo Shen6f7d7d92013-04-24 15:59:28 +0800730 macb_writel(macb, NCFGR, ncfgr);
731
Bin Mengcf821322019-05-22 00:09:45 -0700732#ifdef CONFIG_DM_ETH
733 ret = macb_linkspd_cb(dev, _1000BASET);
734#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700735 ret = macb_linkspd_cb(macb->regs, _1000BASET);
Bin Mengcf821322019-05-22 00:09:45 -0700736#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700737 if (ret)
738 return ret;
739
740 return 0;
Bo Shen6f7d7d92013-04-24 15:59:28 +0800741 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100742 }
Bo Shen6f7d7d92013-04-24 15:59:28 +0800743
744 /* fall back for EMAC checking */
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200745 adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE);
746 lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA);
Bo Shen6f7d7d92013-04-24 15:59:28 +0800747 media = mii_nway_result(lpa & adv);
748 speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
749 ? 1 : 0);
750 duplex = (media & ADVERTISE_FULL) ? 1 : 0;
751 printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
Simon Glass5ad27512016-05-05 07:28:09 -0600752 name,
Bo Shen6f7d7d92013-04-24 15:59:28 +0800753 speed ? "100" : "10",
754 duplex ? "full" : "half",
755 lpa);
756
757 ncfgr = macb_readl(macb, NCFGR);
Bo Shenfe19ef32015-03-04 13:35:16 +0800758 ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE));
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700759 if (speed) {
Bo Shen6f7d7d92013-04-24 15:59:28 +0800760 ncfgr |= MACB_BIT(SPD);
Bin Mengcf821322019-05-22 00:09:45 -0700761#ifdef CONFIG_DM_ETH
762 ret = macb_linkspd_cb(dev, _100BASET);
763#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700764 ret = macb_linkspd_cb(macb->regs, _100BASET);
Bin Mengcf821322019-05-22 00:09:45 -0700765#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700766 } else {
Bin Mengcf821322019-05-22 00:09:45 -0700767#ifdef CONFIG_DM_ETH
768 ret = macb_linkspd_cb(dev, _10BASET);
769#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700770 ret = macb_linkspd_cb(macb->regs, _10BASET);
Bin Mengcf821322019-05-22 00:09:45 -0700771#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700772 }
773
774 if (ret)
775 return ret;
776
Bo Shen6f7d7d92013-04-24 15:59:28 +0800777 if (duplex)
778 ncfgr |= MACB_BIT(FD);
779 macb_writel(macb, NCFGR, ncfgr);
780
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700781 return 0;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100782}
783
Wu, Josh012d68d2015-06-03 16:45:44 +0800784static int gmac_init_multi_queues(struct macb_device *macb)
785{
786 int i, num_queues = 1;
787 u32 queue_mask;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530788 unsigned long paddr;
Wu, Josh012d68d2015-06-03 16:45:44 +0800789
790 /* bit 0 is never set but queue 0 always exists */
791 queue_mask = gem_readl(macb, DCFG6) & 0xff;
792 queue_mask |= 0x1;
793
794 for (i = 1; i < MACB_MAX_QUEUES; i++)
795 if (queue_mask & (1 << i))
796 num_queues++;
797
Ramon Fried6402fb192019-07-16 22:04:33 +0300798 macb->dummy_desc->ctrl = MACB_BIT(TX_USED);
Wu, Josh012d68d2015-06-03 16:45:44 +0800799 macb->dummy_desc->addr = 0;
800 flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma +
Heiko Schocher8353f9d2016-08-29 07:46:11 +0200801 ALIGN(MACB_TX_DUMMY_DMA_DESC_SIZE, PKTALIGN));
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530802 paddr = macb->dummy_desc_dma;
Wu, Josh012d68d2015-06-03 16:45:44 +0800803
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530804 for (i = 1; i < num_queues; i++) {
805 gem_writel_queue_TBQP(macb, lower_32_bits(paddr), i - 1);
806 gem_writel_queue_RBQP(macb, lower_32_bits(paddr), i - 1);
807 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
808 gem_writel_queue_TBQPH(macb, upper_32_bits(paddr),
809 i - 1);
810 gem_writel_queue_RBQPH(macb, upper_32_bits(paddr),
811 i - 1);
812 }
813 }
Wu, Josh012d68d2015-06-03 16:45:44 +0800814 return 0;
815}
816
Ramon Friedb40501f2019-07-16 22:04:36 +0300817static void gmac_configure_dma(struct macb_device *macb)
818{
819 u32 buffer_size;
820 u32 dmacfg;
821
Ramon Fried377d19d2019-07-14 18:25:14 +0300822 buffer_size = macb->rx_buffer_size / RX_BUFFER_MULTIPLE;
Ramon Friedb40501f2019-07-16 22:04:36 +0300823 dmacfg = gem_readl(macb, DMACFG) & ~GEM_BF(RXBS, -1L);
824 dmacfg |= GEM_BF(RXBS, buffer_size);
825
Anup Patel88799a62019-07-24 04:09:32 +0000826 if (macb->config->dma_burst_length)
827 dmacfg = GEM_BFINS(FBLDO,
828 macb->config->dma_burst_length, dmacfg);
Ramon Friedb40501f2019-07-16 22:04:36 +0300829
830 dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
831 dmacfg &= ~GEM_BIT(ENDIA_PKT);
832
Anup Patela1818b12019-07-24 04:09:37 +0000833 if (macb->is_big_endian)
Ramon Friedb40501f2019-07-16 22:04:36 +0300834 dmacfg |= GEM_BIT(ENDIA_DESC); /* CPU in big endian */
Anup Patela1818b12019-07-24 04:09:37 +0000835 else
836 dmacfg &= ~GEM_BIT(ENDIA_DESC);
Ramon Friedb40501f2019-07-16 22:04:36 +0300837
838 dmacfg &= ~GEM_BIT(ADDR64);
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530839 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
840 dmacfg |= GEM_BIT(ADDR64);
841
Ramon Friedb40501f2019-07-16 22:04:36 +0300842 gem_writel(macb, DMACFG, dmacfg);
843}
844
Wenyou Yang7b811852016-05-17 13:11:35 +0800845#ifdef CONFIG_DM_ETH
846static int _macb_init(struct udevice *dev, const char *name)
847#else
Simon Glass5ad27512016-05-05 07:28:09 -0600848static int _macb_init(struct macb_device *macb, const char *name)
Wenyou Yang7b811852016-05-17 13:11:35 +0800849#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100850{
Wenyou Yang7b811852016-05-17 13:11:35 +0800851#ifdef CONFIG_DM_ETH
852 struct macb_device *macb = dev_get_priv(dev);
853#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100854 unsigned long paddr;
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700855 int ret;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100856 int i;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530857 int count;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100858
859 /*
860 * macb_halt should have been called at some point before now,
861 * so we'll assume the controller is idle.
862 */
863
864 /* initialize DMA descriptors */
865 paddr = macb->rx_buffer_dma;
Andreas Bießmann1e868122014-05-26 22:55:18 +0200866 for (i = 0; i < MACB_RX_RING_SIZE; i++) {
867 if (i == (MACB_RX_RING_SIZE - 1))
Ramon Fried6402fb192019-07-16 22:04:33 +0300868 paddr |= MACB_BIT(RX_WRAP);
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530869 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
870 count = i * 2;
871 else
872 count = i;
873 macb->rx_ring[count].ctrl = 0;
874 macb_set_addr(macb, &macb->rx_ring[count], paddr);
Ramon Fried377d19d2019-07-14 18:25:14 +0300875 paddr += macb->rx_buffer_size;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100876 }
Wu, Josh18052402014-05-27 16:31:05 +0800877 macb_flush_ring_desc(macb, RX);
878 macb_flush_rx_buffer(macb);
879
Andreas Bießmann1e868122014-05-26 22:55:18 +0200880 for (i = 0; i < MACB_TX_RING_SIZE; i++) {
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530881 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
882 count = i * 2;
883 else
884 count = i;
885 macb_set_addr(macb, &macb->tx_ring[count], 0);
Andreas Bießmann1e868122014-05-26 22:55:18 +0200886 if (i == (MACB_TX_RING_SIZE - 1))
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530887 macb->tx_ring[count].ctrl = MACB_BIT(TX_USED) |
Ramon Fried6402fb192019-07-16 22:04:33 +0300888 MACB_BIT(TX_WRAP);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100889 else
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530890 macb->tx_ring[count].ctrl = MACB_BIT(TX_USED);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100891 }
Wu, Josh18052402014-05-27 16:31:05 +0800892 macb_flush_ring_desc(macb, TX);
893
Andreas Bießmann1e868122014-05-26 22:55:18 +0200894 macb->rx_tail = 0;
895 macb->tx_head = 0;
896 macb->tx_tail = 0;
Simon Glass5ad27512016-05-05 07:28:09 -0600897 macb->next_rx_tail = 0;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100898
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700899#ifdef CONFIG_MACB_ZYNQ
Michal Simekfc91bdb2020-03-26 15:01:29 +0100900 gem_writel(macb, DMACFG, MACB_ZYNQ_GEM_DMACR_INIT);
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700901#endif
902
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530903 macb_writel(macb, RBQP, lower_32_bits(macb->rx_ring_dma));
904 macb_writel(macb, TBQP, lower_32_bits(macb->tx_ring_dma));
905 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
906 macb_writel(macb, RBQPH, upper_32_bits(macb->rx_ring_dma));
907 macb_writel(macb, TBQPH, upper_32_bits(macb->tx_ring_dma));
908 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100909
Bo Shen6f7d7d92013-04-24 15:59:28 +0800910 if (macb_is_gem(macb)) {
Ramon Friedb40501f2019-07-16 22:04:36 +0300911 /* Initialize DMA properties */
912 gmac_configure_dma(macb);
Wu, Josh012d68d2015-06-03 16:45:44 +0800913 /* Check the multi queue and initialize the queue for tx */
914 gmac_init_multi_queues(macb);
915
Bo Shen4660b332014-11-10 15:24:01 +0800916 /*
917 * When the GMAC IP with GE feature, this bit is used to
918 * select interface between RGMII and GMII.
919 * When the GMAC IP without GE feature, this bit is used
920 * to select interface between RMII and MII.
921 */
Wenyou Yang7b811852016-05-17 13:11:35 +0800922#ifdef CONFIG_DM_ETH
Wenyou Yang5653dbc2017-04-20 11:13:13 +0800923 if ((macb->phy_interface == PHY_INTERFACE_MODE_RMII) ||
924 (macb->phy_interface == PHY_INTERFACE_MODE_RGMII))
Ramon Fried94e6bd82019-07-16 22:03:00 +0300925 gem_writel(macb, USRIO, GEM_BIT(RGMII));
Wenyou Yang7b811852016-05-17 13:11:35 +0800926 else
Ramon Fried94e6bd82019-07-16 22:03:00 +0300927 gem_writel(macb, USRIO, 0);
Ramon Fried588a5b72019-07-16 22:04:34 +0300928
929 if (macb->phy_interface == PHY_INTERFACE_MODE_SGMII) {
930 unsigned int ncfgr = macb_readl(macb, NCFGR);
931
932 ncfgr |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
933 macb_writel(macb, NCFGR, ncfgr);
934 }
Wenyou Yang7b811852016-05-17 13:11:35 +0800935#else
Bo Shen4660b332014-11-10 15:24:01 +0800936#if defined(CONFIG_RGMII) || defined(CONFIG_RMII)
Ramon Fried94e6bd82019-07-16 22:03:00 +0300937 gem_writel(macb, USRIO, GEM_BIT(RGMII));
Bo Shen6f7d7d92013-04-24 15:59:28 +0800938#else
Ramon Fried94e6bd82019-07-16 22:03:00 +0300939 gem_writel(macb, USRIO, 0);
Bo Shen6f7d7d92013-04-24 15:59:28 +0800940#endif
Wenyou Yang7b811852016-05-17 13:11:35 +0800941#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +0800942 } else {
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100943 /* choose RMII or MII mode. This depends on the board */
Wenyou Yang7b811852016-05-17 13:11:35 +0800944#ifdef CONFIG_DM_ETH
945#ifdef CONFIG_AT91FAMILY
946 if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) {
947 macb_writel(macb, USRIO,
948 MACB_BIT(RMII) | MACB_BIT(CLKEN));
949 } else {
950 macb_writel(macb, USRIO, MACB_BIT(CLKEN));
951 }
952#else
953 if (macb->phy_interface == PHY_INTERFACE_MODE_RMII)
954 macb_writel(macb, USRIO, 0);
955 else
956 macb_writel(macb, USRIO, MACB_BIT(MII));
957#endif
958#else
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100959#ifdef CONFIG_RMII
Bo Shencc29ce52013-04-24 15:59:26 +0800960#ifdef CONFIG_AT91FAMILY
Stelian Pop87a82542008-01-03 21:15:56 +0000961 macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN));
962#else
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100963 macb_writel(macb, USRIO, 0);
Stelian Pop87a82542008-01-03 21:15:56 +0000964#endif
965#else
Bo Shencc29ce52013-04-24 15:59:26 +0800966#ifdef CONFIG_AT91FAMILY
Stelian Pop87a82542008-01-03 21:15:56 +0000967 macb_writel(macb, USRIO, MACB_BIT(CLKEN));
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100968#else
969 macb_writel(macb, USRIO, MACB_BIT(MII));
970#endif
Stelian Pop87a82542008-01-03 21:15:56 +0000971#endif /* CONFIG_RMII */
Wenyou Yang7b811852016-05-17 13:11:35 +0800972#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +0800973 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100974
Wenyou Yang7b811852016-05-17 13:11:35 +0800975#ifdef CONFIG_DM_ETH
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700976 ret = macb_phy_init(dev, name);
Wenyou Yang7b811852016-05-17 13:11:35 +0800977#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700978 ret = macb_phy_init(macb, name);
Wenyou Yang7b811852016-05-17 13:11:35 +0800979#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700980 if (ret)
981 return ret;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100982
983 /* Enable TX and RX */
984 macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE));
985
Ben Warrende9fcb52008-01-09 18:15:53 -0500986 return 0;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100987}
988
Simon Glass5ad27512016-05-05 07:28:09 -0600989static void _macb_halt(struct macb_device *macb)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100990{
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100991 u32 ncr, tsr;
992
993 /* Halt the controller and wait for any ongoing transmission to end. */
994 ncr = macb_readl(macb, NCR);
995 ncr |= MACB_BIT(THALT);
996 macb_writel(macb, NCR, ncr);
997
998 do {
999 tsr = macb_readl(macb, TSR);
1000 } while (tsr & MACB_BIT(TGO));
1001
1002 /* Disable TX and RX, and clear statistics */
1003 macb_writel(macb, NCR, MACB_BIT(CLRSTAT));
1004}
1005
Simon Glass5ad27512016-05-05 07:28:09 -06001006static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr)
Ben Warren33f84312010-06-01 11:55:42 -07001007{
Ben Warren33f84312010-06-01 11:55:42 -07001008 u32 hwaddr_bottom;
1009 u16 hwaddr_top;
1010
1011 /* set hardware address */
Simon Glass5ad27512016-05-05 07:28:09 -06001012 hwaddr_bottom = enetaddr[0] | enetaddr[1] << 8 |
1013 enetaddr[2] << 16 | enetaddr[3] << 24;
Ben Warren33f84312010-06-01 11:55:42 -07001014 macb_writel(macb, SA1B, hwaddr_bottom);
Simon Glass5ad27512016-05-05 07:28:09 -06001015 hwaddr_top = enetaddr[4] | enetaddr[5] << 8;
Ben Warren33f84312010-06-01 11:55:42 -07001016 macb_writel(macb, SA1T, hwaddr_top);
1017 return 0;
1018}
1019
Bo Shen6f7d7d92013-04-24 15:59:28 +08001020static u32 macb_mdc_clk_div(int id, struct macb_device *macb)
1021{
1022 u32 config;
Wenyou Yang19449362017-02-14 16:24:40 +08001023#if defined(CONFIG_DM_ETH) && defined(CONFIG_CLK)
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001024 unsigned long macb_hz = macb->pclk_rate;
1025#else
Bo Shen6f7d7d92013-04-24 15:59:28 +08001026 unsigned long macb_hz = get_macb_pclk_rate(id);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001027#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +08001028
1029 if (macb_hz < 20000000)
1030 config = MACB_BF(CLK, MACB_CLK_DIV8);
1031 else if (macb_hz < 40000000)
1032 config = MACB_BF(CLK, MACB_CLK_DIV16);
1033 else if (macb_hz < 80000000)
1034 config = MACB_BF(CLK, MACB_CLK_DIV32);
1035 else
1036 config = MACB_BF(CLK, MACB_CLK_DIV64);
1037
1038 return config;
1039}
1040
1041static u32 gem_mdc_clk_div(int id, struct macb_device *macb)
1042{
1043 u32 config;
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001044
Wenyou Yang19449362017-02-14 16:24:40 +08001045#if defined(CONFIG_DM_ETH) && defined(CONFIG_CLK)
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001046 unsigned long macb_hz = macb->pclk_rate;
1047#else
Bo Shen6f7d7d92013-04-24 15:59:28 +08001048 unsigned long macb_hz = get_macb_pclk_rate(id);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001049#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +08001050
1051 if (macb_hz < 20000000)
1052 config = GEM_BF(CLK, GEM_CLK_DIV8);
1053 else if (macb_hz < 40000000)
1054 config = GEM_BF(CLK, GEM_CLK_DIV16);
1055 else if (macb_hz < 80000000)
1056 config = GEM_BF(CLK, GEM_CLK_DIV32);
1057 else if (macb_hz < 120000000)
1058 config = GEM_BF(CLK, GEM_CLK_DIV48);
1059 else if (macb_hz < 160000000)
1060 config = GEM_BF(CLK, GEM_CLK_DIV64);
Ramon Friedb1b9b4f2019-07-16 22:04:32 +03001061 else if (macb_hz < 240000000)
Bo Shen6f7d7d92013-04-24 15:59:28 +08001062 config = GEM_BF(CLK, GEM_CLK_DIV96);
Ramon Friedb1b9b4f2019-07-16 22:04:32 +03001063 else if (macb_hz < 320000000)
1064 config = GEM_BF(CLK, GEM_CLK_DIV128);
1065 else
1066 config = GEM_BF(CLK, GEM_CLK_DIV224);
Bo Shen6f7d7d92013-04-24 15:59:28 +08001067
1068 return config;
1069}
1070
Bo Shen0e6624a2013-09-18 15:07:44 +08001071/*
1072 * Get the DMA bus width field of the network configuration register that we
1073 * should program. We find the width from decoding the design configuration
1074 * register to find the maximum supported data bus width.
1075 */
1076static u32 macb_dbw(struct macb_device *macb)
1077{
1078 switch (GEM_BFEXT(DBWDEF, gem_readl(macb, DCFG1))) {
1079 case 4:
1080 return GEM_BF(DBW, GEM_DBW128);
1081 case 2:
1082 return GEM_BF(DBW, GEM_DBW64);
1083 case 1:
1084 default:
1085 return GEM_BF(DBW, GEM_DBW32);
1086 }
Simon Glass5ad27512016-05-05 07:28:09 -06001087}
1088
1089static void _macb_eth_initialize(struct macb_device *macb)
1090{
1091 int id = 0; /* This is not used by functions we call */
1092 u32 ncfgr;
1093
Ramon Fried377d19d2019-07-14 18:25:14 +03001094 if (macb_is_gem(macb))
1095 macb->rx_buffer_size = GEM_RX_BUFFER_SIZE;
1096 else
1097 macb->rx_buffer_size = MACB_RX_BUFFER_SIZE;
1098
Simon Glass5ad27512016-05-05 07:28:09 -06001099 /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */
Ramon Fried377d19d2019-07-14 18:25:14 +03001100 macb->rx_buffer = dma_alloc_coherent(macb->rx_buffer_size *
1101 MACB_RX_RING_SIZE,
Simon Glass5ad27512016-05-05 07:28:09 -06001102 &macb->rx_buffer_dma);
1103 macb->rx_ring = dma_alloc_coherent(MACB_RX_DMA_DESC_SIZE,
1104 &macb->rx_ring_dma);
1105 macb->tx_ring = dma_alloc_coherent(MACB_TX_DMA_DESC_SIZE,
1106 &macb->tx_ring_dma);
1107 macb->dummy_desc = dma_alloc_coherent(MACB_TX_DUMMY_DMA_DESC_SIZE,
1108 &macb->dummy_desc_dma);
1109
1110 /*
1111 * Do some basic initialization so that we at least can talk
1112 * to the PHY
1113 */
1114 if (macb_is_gem(macb)) {
1115 ncfgr = gem_mdc_clk_div(id, macb);
1116 ncfgr |= macb_dbw(macb);
1117 } else {
1118 ncfgr = macb_mdc_clk_div(id, macb);
1119 }
1120
1121 macb_writel(macb, NCFGR, ncfgr);
1122}
1123
Simon Glass75c5d182016-05-05 07:28:11 -06001124#ifndef CONFIG_DM_ETH
Simon Glass5ad27512016-05-05 07:28:09 -06001125static int macb_send(struct eth_device *netdev, void *packet, int length)
1126{
1127 struct macb_device *macb = to_macb(netdev);
1128
1129 return _macb_send(macb, netdev->name, packet, length);
Bo Shen0e6624a2013-09-18 15:07:44 +08001130}
1131
Simon Glass5ad27512016-05-05 07:28:09 -06001132static int macb_recv(struct eth_device *netdev)
1133{
1134 struct macb_device *macb = to_macb(netdev);
1135 uchar *packet;
1136 int length;
1137
1138 macb->wrapped = false;
1139 for (;;) {
1140 macb->next_rx_tail = macb->rx_tail;
1141 length = _macb_recv(macb, &packet);
1142 if (length >= 0) {
1143 net_process_received_packet(packet, length);
1144 reclaim_rx_buffers(macb, macb->next_rx_tail);
Heinrich Schuchardt6c4aae92018-03-18 11:32:53 +01001145 } else {
Simon Glass5ad27512016-05-05 07:28:09 -06001146 return length;
1147 }
1148 }
1149}
1150
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001151static int macb_init(struct eth_device *netdev, struct bd_info *bd)
Simon Glass5ad27512016-05-05 07:28:09 -06001152{
1153 struct macb_device *macb = to_macb(netdev);
1154
1155 return _macb_init(macb, netdev->name);
1156}
1157
1158static void macb_halt(struct eth_device *netdev)
1159{
1160 struct macb_device *macb = to_macb(netdev);
1161
1162 return _macb_halt(macb);
1163}
1164
1165static int macb_write_hwaddr(struct eth_device *netdev)
1166{
1167 struct macb_device *macb = to_macb(netdev);
1168
1169 return _macb_write_hwaddr(macb, netdev->enetaddr);
1170}
1171
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001172int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
1173{
1174 struct macb_device *macb;
1175 struct eth_device *netdev;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001176
1177 macb = malloc(sizeof(struct macb_device));
1178 if (!macb) {
1179 printf("Error: Failed to allocate memory for MACB%d\n", id);
1180 return -1;
1181 }
1182 memset(macb, 0, sizeof(struct macb_device));
1183
1184 netdev = &macb->netdev;
1185
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001186 macb->regs = regs;
1187 macb->phy_addr = phy_addr;
1188
Bo Shen6f7d7d92013-04-24 15:59:28 +08001189 if (macb_is_gem(macb))
1190 sprintf(netdev->name, "gmac%d", id);
1191 else
1192 sprintf(netdev->name, "macb%d", id);
1193
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001194 netdev->init = macb_init;
1195 netdev->halt = macb_halt;
1196 netdev->send = macb_send;
1197 netdev->recv = macb_recv;
Ben Warren33f84312010-06-01 11:55:42 -07001198 netdev->write_hwaddr = macb_write_hwaddr;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001199
Simon Glass5ad27512016-05-05 07:28:09 -06001200 _macb_eth_initialize(macb);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001201
1202 eth_register(netdev);
1203
Bo Shen7d91deb2013-04-24 15:59:27 +08001204#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
Joe Hershberger1fbcbed2016-08-08 11:28:38 -05001205 int retval;
1206 struct mii_dev *mdiodev = mdio_alloc();
1207 if (!mdiodev)
1208 return -ENOMEM;
1209 strncpy(mdiodev->name, netdev->name, MDIO_NAME_LEN);
1210 mdiodev->read = macb_miiphy_read;
1211 mdiodev->write = macb_miiphy_write;
1212
1213 retval = mdio_register(mdiodev);
1214 if (retval < 0)
1215 return retval;
Bo Shen7d91deb2013-04-24 15:59:27 +08001216 macb->bus = miiphy_get_dev_by_name(netdev->name);
Semih Hazar790088e2009-12-17 15:07:15 +02001217#endif
Simon Glass75c5d182016-05-05 07:28:11 -06001218 return 0;
1219}
1220#endif /* !CONFIG_DM_ETH */
1221
1222#ifdef CONFIG_DM_ETH
1223
1224static int macb_start(struct udevice *dev)
1225{
Wenyou Yang7b811852016-05-17 13:11:35 +08001226 return _macb_init(dev, dev->name);
Simon Glass75c5d182016-05-05 07:28:11 -06001227}
1228
1229static int macb_send(struct udevice *dev, void *packet, int length)
1230{
1231 struct macb_device *macb = dev_get_priv(dev);
1232
1233 return _macb_send(macb, dev->name, packet, length);
1234}
1235
1236static int macb_recv(struct udevice *dev, int flags, uchar **packetp)
1237{
1238 struct macb_device *macb = dev_get_priv(dev);
1239
1240 macb->next_rx_tail = macb->rx_tail;
1241 macb->wrapped = false;
1242
1243 return _macb_recv(macb, packetp);
1244}
1245
1246static int macb_free_pkt(struct udevice *dev, uchar *packet, int length)
1247{
1248 struct macb_device *macb = dev_get_priv(dev);
1249
1250 reclaim_rx_buffers(macb, macb->next_rx_tail);
1251
1252 return 0;
1253}
1254
1255static void macb_stop(struct udevice *dev)
1256{
1257 struct macb_device *macb = dev_get_priv(dev);
1258
1259 _macb_halt(macb);
1260}
1261
1262static int macb_write_hwaddr(struct udevice *dev)
1263{
Simon Glassfa20e932020-12-03 16:55:20 -07001264 struct eth_pdata *plat = dev_get_plat(dev);
Simon Glass75c5d182016-05-05 07:28:11 -06001265 struct macb_device *macb = dev_get_priv(dev);
1266
1267 return _macb_write_hwaddr(macb, plat->enetaddr);
1268}
1269
1270static const struct eth_ops macb_eth_ops = {
1271 .start = macb_start,
1272 .send = macb_send,
1273 .recv = macb_recv,
1274 .stop = macb_stop,
1275 .free_pkt = macb_free_pkt,
1276 .write_hwaddr = macb_write_hwaddr,
1277};
1278
Wenyou Yang19449362017-02-14 16:24:40 +08001279#ifdef CONFIG_CLK
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001280static int macb_enable_clk(struct udevice *dev)
1281{
1282 struct macb_device *macb = dev_get_priv(dev);
1283 struct clk clk;
1284 ulong clk_rate;
1285 int ret;
1286
1287 ret = clk_get_by_index(dev, 0, &clk);
1288 if (ret)
1289 return -EINVAL;
1290
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001291 /*
Anup Patel51b51f82019-02-25 08:14:36 +00001292 * If clock driver didn't support enable or disable then
1293 * we get -ENOSYS from clk_enable(). To handle this, we
1294 * don't fail for ret == -ENOSYS.
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001295 */
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001296 ret = clk_enable(&clk);
Anup Patel51b51f82019-02-25 08:14:36 +00001297 if (ret && ret != -ENOSYS)
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001298 return ret;
1299
1300 clk_rate = clk_get_rate(&clk);
1301 if (!clk_rate)
1302 return -EINVAL;
1303
1304 macb->pclk_rate = clk_rate;
1305
1306 return 0;
1307}
Wenyou Yang19449362017-02-14 16:24:40 +08001308#endif
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001309
Ramon Fried834040c2019-07-16 22:04:35 +03001310static const struct macb_config default_gem_config = {
1311 .dma_burst_length = 16,
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301312 .hw_dma_cap = HW_DMA_CAP_32B,
Anup Patel88799a62019-07-24 04:09:32 +00001313 .clk_init = NULL,
Ramon Fried834040c2019-07-16 22:04:35 +03001314};
1315
Simon Glass75c5d182016-05-05 07:28:11 -06001316static int macb_eth_probe(struct udevice *dev)
1317{
Simon Glassfa20e932020-12-03 16:55:20 -07001318 struct eth_pdata *pdata = dev_get_plat(dev);
Simon Glass75c5d182016-05-05 07:28:11 -06001319 struct macb_device *macb = dev_get_priv(dev);
Padmarao Begari34394ba2021-01-15 08:20:37 +05301320 struct ofnode_phandle_args phandle_args;
Wenyou Yang7b811852016-05-17 13:11:35 +08001321 const char *phy_mode;
Anup Patel88799a62019-07-24 04:09:32 +00001322 int ret;
Wenyou Yang7b811852016-05-17 13:11:35 +08001323
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301324 phy_mode = dev_read_prop(dev, "phy-mode", NULL);
1325
Wenyou Yang7b811852016-05-17 13:11:35 +08001326 if (phy_mode)
1327 macb->phy_interface = phy_get_interface_by_name(phy_mode);
1328 if (macb->phy_interface == -1) {
1329 debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
1330 return -EINVAL;
1331 }
Wenyou Yang7b811852016-05-17 13:11:35 +08001332
Padmarao Begari34394ba2021-01-15 08:20:37 +05301333 /* Read phyaddr from DT */
1334 if (!dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
1335 &phandle_args))
1336 macb->phy_addr = ofnode_read_u32_default(phandle_args.node,
1337 "reg", -1);
1338
Simon Glass75c5d182016-05-05 07:28:11 -06001339 macb->regs = (void *)pdata->iobase;
1340
Anup Patela1818b12019-07-24 04:09:37 +00001341 macb->is_big_endian = (cpu_to_be32(0x12345678) == 0x12345678);
1342
Anup Patel88799a62019-07-24 04:09:32 +00001343 macb->config = (struct macb_config *)dev_get_driver_data(dev);
1344 if (!macb->config)
1345 macb->config = &default_gem_config;
Ramon Fried834040c2019-07-16 22:04:35 +03001346
Wenyou Yang19449362017-02-14 16:24:40 +08001347#ifdef CONFIG_CLK
Wenyou Yang44835ea2017-04-14 14:36:04 +08001348 ret = macb_enable_clk(dev);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001349 if (ret)
1350 return ret;
Wenyou Yang19449362017-02-14 16:24:40 +08001351#endif
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001352
Simon Glass75c5d182016-05-05 07:28:11 -06001353 _macb_eth_initialize(macb);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001354
Simon Glass75c5d182016-05-05 07:28:11 -06001355#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
Wenyou Yang44835ea2017-04-14 14:36:04 +08001356 macb->bus = mdio_alloc();
1357 if (!macb->bus)
Joe Hershberger1fbcbed2016-08-08 11:28:38 -05001358 return -ENOMEM;
Wenyou Yang44835ea2017-04-14 14:36:04 +08001359 strncpy(macb->bus->name, dev->name, MDIO_NAME_LEN);
1360 macb->bus->read = macb_miiphy_read;
1361 macb->bus->write = macb_miiphy_write;
Joe Hershberger1fbcbed2016-08-08 11:28:38 -05001362
Wenyou Yang44835ea2017-04-14 14:36:04 +08001363 ret = mdio_register(macb->bus);
1364 if (ret < 0)
1365 return ret;
Simon Glass75c5d182016-05-05 07:28:11 -06001366 macb->bus = miiphy_get_dev_by_name(dev->name);
1367#endif
Wenyou Yang44835ea2017-04-14 14:36:04 +08001368
1369 return 0;
1370}
1371
1372static int macb_eth_remove(struct udevice *dev)
1373{
1374 struct macb_device *macb = dev_get_priv(dev);
1375
1376#ifdef CONFIG_PHYLIB
1377 free(macb->phydev);
1378#endif
1379 mdio_unregister(macb->bus);
1380 mdio_free(macb->bus);
Simon Glass75c5d182016-05-05 07:28:11 -06001381
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001382 return 0;
1383}
1384
1385/**
Simon Glassaad29ae2020-12-03 16:55:21 -07001386 * macb_late_eth_of_to_plat
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001387 * @dev: udevice struct
1388 * Returns 0 when operation success and negative errno number
1389 * when operation failed.
1390 */
Simon Glassaad29ae2020-12-03 16:55:21 -07001391int __weak macb_late_eth_of_to_plat(struct udevice *dev)
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001392{
Simon Glass75c5d182016-05-05 07:28:11 -06001393 return 0;
1394}
1395
Simon Glassaad29ae2020-12-03 16:55:21 -07001396static int macb_eth_of_to_plat(struct udevice *dev)
Simon Glass75c5d182016-05-05 07:28:11 -06001397{
Simon Glassfa20e932020-12-03 16:55:20 -07001398 struct eth_pdata *pdata = dev_get_plat(dev);
Simon Glass75c5d182016-05-05 07:28:11 -06001399
Ramon Friedbf15d2f2018-12-27 19:58:42 +02001400 pdata->iobase = (phys_addr_t)dev_remap_addr(dev);
1401 if (!pdata->iobase)
1402 return -EINVAL;
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001403
Simon Glassaad29ae2020-12-03 16:55:21 -07001404 return macb_late_eth_of_to_plat(dev);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001405}
1406
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301407static const struct macb_config microchip_config = {
1408 .dma_burst_length = 16,
1409 .hw_dma_cap = HW_DMA_CAP_64B,
1410 .clk_init = NULL,
1411};
1412
Ramon Fried834040c2019-07-16 22:04:35 +03001413static const struct macb_config sama5d4_config = {
1414 .dma_burst_length = 4,
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301415 .hw_dma_cap = HW_DMA_CAP_32B,
Anup Patel88799a62019-07-24 04:09:32 +00001416 .clk_init = NULL,
1417};
1418
1419static const struct macb_config sifive_config = {
1420 .dma_burst_length = 16,
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301421 .hw_dma_cap = HW_DMA_CAP_32B,
Anup Patel88799a62019-07-24 04:09:32 +00001422 .clk_init = macb_sifive_clk_init,
Ramon Fried834040c2019-07-16 22:04:35 +03001423};
1424
Simon Glass75c5d182016-05-05 07:28:11 -06001425static const struct udevice_id macb_eth_ids[] = {
1426 { .compatible = "cdns,macb" },
Wenyou Yang8f155402017-04-14 14:36:05 +08001427 { .compatible = "cdns,at91sam9260-macb" },
Nicolas Ferre9115f572019-09-27 13:08:32 +00001428 { .compatible = "cdns,sam9x60-macb" },
Wenyou Yang8f155402017-04-14 14:36:05 +08001429 { .compatible = "atmel,sama5d2-gem" },
1430 { .compatible = "atmel,sama5d3-gem" },
Ramon Fried834040c2019-07-16 22:04:35 +03001431 { .compatible = "atmel,sama5d4-gem", .data = (ulong)&sama5d4_config },
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001432 { .compatible = "cdns,zynq-gem" },
Anup Patel88799a62019-07-24 04:09:32 +00001433 { .compatible = "sifive,fu540-c000-gem",
1434 .data = (ulong)&sifive_config },
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301435 { .compatible = "microchip,mpfs-mss-gem",
1436 .data = (ulong)&microchip_config },
Simon Glass75c5d182016-05-05 07:28:11 -06001437 { }
1438};
1439
1440U_BOOT_DRIVER(eth_macb) = {
1441 .name = "eth_macb",
1442 .id = UCLASS_ETH,
1443 .of_match = macb_eth_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001444 .of_to_plat = macb_eth_of_to_plat,
Simon Glass75c5d182016-05-05 07:28:11 -06001445 .probe = macb_eth_probe,
Wenyou Yang44835ea2017-04-14 14:36:04 +08001446 .remove = macb_eth_remove,
Simon Glass75c5d182016-05-05 07:28:11 -06001447 .ops = &macb_eth_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001448 .priv_auto = sizeof(struct macb_device),
Simon Glass71fa5b42020-12-03 16:55:18 -07001449 .plat_auto = sizeof(struct eth_pdata),
Simon Glass75c5d182016-05-05 07:28:11 -06001450};
1451#endif
1452
Jon Loeligerb1d408a2007-07-09 17:30:01 -05001453#endif