blob: 57ea45e2dc7fc253d53b51f3f69403b53452bf19 [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 Glass3ba929a2020-10-30 21:38:53 -060010#include <asm/global_data.h>
Simon Glassdbd79542020-05-10 11:40:11 -060011#include <linux/delay.h>
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010012
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010013/*
14 * The u-boot networking stack is a little weird. It seems like the
15 * networking core allocates receive buffers up front without any
16 * regard to the hardware that's supposed to actually receive those
17 * packets.
18 *
19 * The MACB receives packets into 128-byte receive buffers, so the
20 * buffers allocated by the core isn't very practical to use. We'll
21 * allocate our own, but we need one such buffer in case a packet
22 * wraps around the DMA ring so that we have to copy it.
23 *
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020024 * Therefore, define CONFIG_SYS_RX_ETH_BUFFER to 1 in the board-specific
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010025 * configuration header. This way, the core allocates one RX buffer
26 * and one TX buffer, each of which can hold a ethernet packet of
27 * maximum size.
28 *
29 * For some reason, the networking core unconditionally specifies a
30 * 32-byte packet "alignment" (which really should be called
31 * "padding"). MACB shouldn't need that, but we'll refrain from any
32 * core modifications here...
33 */
34
35#include <net.h>
Simon Glass75c5d182016-05-05 07:28:11 -060036#ifndef CONFIG_DM_ETH
Ben Warren2f2b6b62008-08-31 22:22:04 -070037#include <netdev.h>
Simon Glass75c5d182016-05-05 07:28:11 -060038#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010039#include <malloc.h>
Semih Hazar790088e2009-12-17 15:07:15 +020040#include <miiphy.h>
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010041
42#include <linux/mii.h>
43#include <asm/io.h>
Masahiro Yamada6373a172020-02-14 16:40:19 +090044#include <linux/dma-mapping.h>
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010045#include <asm/arch/clk.h>
Masahiro Yamada64e4f7f2016-09-21 11:28:57 +090046#include <linux/errno.h>
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010047
48#include "macb.h"
49
Wenyou Yang7b811852016-05-17 13:11:35 +080050DECLARE_GLOBAL_DATA_PTR;
51
Ramon Fried377d19d2019-07-14 18:25:14 +030052/*
53 * These buffer sizes must be power of 2 and divisible
54 * by RX_BUFFER_MULTIPLE
55 */
56#define MACB_RX_BUFFER_SIZE 128
57#define GEM_RX_BUFFER_SIZE 2048
Ramon Friedb40501f2019-07-16 22:04:36 +030058#define RX_BUFFER_MULTIPLE 64
Ramon Fried377d19d2019-07-14 18:25:14 +030059
60#define MACB_RX_RING_SIZE 32
Andreas Bießmann1e868122014-05-26 22:55:18 +020061#define MACB_TX_RING_SIZE 16
Ramon Fried377d19d2019-07-14 18:25:14 +030062
Andreas Bießmann1e868122014-05-26 22:55:18 +020063#define MACB_TX_TIMEOUT 1000
64#define MACB_AUTONEG_TIMEOUT 5000000
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010065
Wilson Lee41d6d1e2017-08-22 20:25:07 -070066#ifdef CONFIG_MACB_ZYNQ
67/* INCR4 AHB bursts */
68#define MACB_ZYNQ_GEM_DMACR_BLENGTH 0x00000004
69/* Use full configured addressable space (8 Kb) */
70#define MACB_ZYNQ_GEM_DMACR_RXSIZE 0x00000300
71/* Use full configured addressable space (4 Kb) */
72#define MACB_ZYNQ_GEM_DMACR_TXSIZE 0x00000400
73/* Set RXBUF with use of 128 byte */
74#define MACB_ZYNQ_GEM_DMACR_RXBUF 0x00020000
75#define MACB_ZYNQ_GEM_DMACR_INIT \
76 (MACB_ZYNQ_GEM_DMACR_BLENGTH | \
77 MACB_ZYNQ_GEM_DMACR_RXSIZE | \
78 MACB_ZYNQ_GEM_DMACR_TXSIZE | \
79 MACB_ZYNQ_GEM_DMACR_RXBUF)
80#endif
81
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +010082struct macb_dma_desc {
83 u32 addr;
84 u32 ctrl;
85};
86
Padmarao Begari7a2c4962021-01-15 08:20:36 +053087struct macb_dma_desc_64 {
88 u32 addrh;
89 u32 unused;
90};
91
92#define HW_DMA_CAP_32B 0
93#define HW_DMA_CAP_64B 1
94
95#define DMA_DESC_SIZE 16
96#define DMA_DESC_BYTES(n) ((n) * DMA_DESC_SIZE)
Wu, Josh18052402014-05-27 16:31:05 +080097#define MACB_TX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_TX_RING_SIZE))
98#define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE))
Wu, Josh012d68d2015-06-03 16:45:44 +080099#define MACB_TX_DUMMY_DMA_DESC_SIZE (DMA_DESC_BYTES(1))
Wu, Josh18052402014-05-27 16:31:05 +0800100
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100101#define RXBUF_FRMLEN_MASK 0x00000fff
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100102#define TXBUF_FRMLEN_MASK 0x000007ff
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100103
104struct macb_device {
105 void *regs;
Anup Patel88799a62019-07-24 04:09:32 +0000106
Anup Patela1818b12019-07-24 04:09:37 +0000107 bool is_big_endian;
108
Anup Patel88799a62019-07-24 04:09:32 +0000109 const struct macb_config *config;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100110
111 unsigned int rx_tail;
112 unsigned int tx_head;
113 unsigned int tx_tail;
Simon Glass5ad27512016-05-05 07:28:09 -0600114 unsigned int next_rx_tail;
115 bool wrapped;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100116
117 void *rx_buffer;
118 void *tx_buffer;
119 struct macb_dma_desc *rx_ring;
120 struct macb_dma_desc *tx_ring;
Ramon Fried377d19d2019-07-14 18:25:14 +0300121 size_t rx_buffer_size;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100122
123 unsigned long rx_buffer_dma;
124 unsigned long rx_ring_dma;
125 unsigned long tx_ring_dma;
126
Wu, Josh012d68d2015-06-03 16:45:44 +0800127 struct macb_dma_desc *dummy_desc;
128 unsigned long dummy_desc_dma;
129
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100130 const struct device *dev;
Simon Glass75c5d182016-05-05 07:28:11 -0600131#ifndef CONFIG_DM_ETH
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100132 struct eth_device netdev;
Simon Glass75c5d182016-05-05 07:28:11 -0600133#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100134 unsigned short phy_addr;
Bo Shen7d91deb2013-04-24 15:59:27 +0800135 struct mii_dev *bus;
Wenyou Yang44835ea2017-04-14 14:36:04 +0800136#ifdef CONFIG_PHYLIB
137 struct phy_device *phydev;
138#endif
Wenyou Yang7b811852016-05-17 13:11:35 +0800139
140#ifdef CONFIG_DM_ETH
Wenyou Yang19449362017-02-14 16:24:40 +0800141#ifdef CONFIG_CLK
Wenyou Yang3d8d3482016-11-02 10:06:56 +0800142 unsigned long pclk_rate;
Wenyou Yang19449362017-02-14 16:24:40 +0800143#endif
Wenyou Yang7b811852016-05-17 13:11:35 +0800144 phy_interface_t phy_interface;
145#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100146};
Ramon Fried834040c2019-07-16 22:04:35 +0300147
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200148struct macb_usrio_cfg {
149 unsigned int mii;
150 unsigned int rmii;
151 unsigned int rgmii;
152 unsigned int clken;
153};
154
Ramon Fried834040c2019-07-16 22:04:35 +0300155struct macb_config {
156 unsigned int dma_burst_length;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530157 unsigned int hw_dma_cap;
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200158 unsigned int caps;
Anup Patel88799a62019-07-24 04:09:32 +0000159
160 int (*clk_init)(struct udevice *dev, ulong rate);
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200161 const struct macb_usrio_cfg *usrio;
Ramon Fried834040c2019-07-16 22:04:35 +0300162};
163
Simon Glass75c5d182016-05-05 07:28:11 -0600164#ifndef CONFIG_DM_ETH
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100165#define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
Simon Glass75c5d182016-05-05 07:28:11 -0600166#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100167
Bo Shen6f7d7d92013-04-24 15:59:28 +0800168static int macb_is_gem(struct macb_device *macb)
169{
Atish Patrae1a85182019-02-25 08:14:42 +0000170 return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) >= 0x2;
Bo Shen6f7d7d92013-04-24 15:59:28 +0800171}
172
Gregory CLEMENTf1a1e582015-12-16 14:50:34 +0100173#ifndef cpu_is_sama5d2
174#define cpu_is_sama5d2() 0
175#endif
176
177#ifndef cpu_is_sama5d4
178#define cpu_is_sama5d4() 0
179#endif
180
181static int gem_is_gigabit_capable(struct macb_device *macb)
182{
183 /*
Robert P. J. Day8c60f922016-05-04 04:47:31 -0400184 * The GEM controllers embedded in SAMA5D2 and SAMA5D4 are
Gregory CLEMENTf1a1e582015-12-16 14:50:34 +0100185 * configured to support only 10/100.
186 */
187 return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4();
188}
189
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200190static void macb_mdio_write(struct macb_device *macb, u8 phy_adr, u8 reg,
191 u16 value)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100192{
193 unsigned long netctl;
194 unsigned long netstat;
195 unsigned long frame;
196
197 netctl = macb_readl(macb, NCR);
198 netctl |= MACB_BIT(MPE);
199 macb_writel(macb, NCR, netctl);
200
201 frame = (MACB_BF(SOF, 1)
202 | MACB_BF(RW, 1)
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200203 | MACB_BF(PHYA, phy_adr)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100204 | MACB_BF(REGA, reg)
205 | MACB_BF(CODE, 2)
206 | MACB_BF(DATA, value));
207 macb_writel(macb, MAN, frame);
208
209 do {
210 netstat = macb_readl(macb, NSR);
211 } while (!(netstat & MACB_BIT(IDLE)));
212
213 netctl = macb_readl(macb, NCR);
214 netctl &= ~MACB_BIT(MPE);
215 macb_writel(macb, NCR, netctl);
216}
217
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200218static u16 macb_mdio_read(struct macb_device *macb, u8 phy_adr, u8 reg)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100219{
220 unsigned long netctl;
221 unsigned long netstat;
222 unsigned long frame;
223
224 netctl = macb_readl(macb, NCR);
225 netctl |= MACB_BIT(MPE);
226 macb_writel(macb, NCR, netctl);
227
228 frame = (MACB_BF(SOF, 1)
229 | MACB_BF(RW, 2)
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200230 | MACB_BF(PHYA, phy_adr)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100231 | MACB_BF(REGA, reg)
232 | MACB_BF(CODE, 2));
233 macb_writel(macb, MAN, frame);
234
235 do {
236 netstat = macb_readl(macb, NSR);
237 } while (!(netstat & MACB_BIT(IDLE)));
238
239 frame = macb_readl(macb, MAN);
240
241 netctl = macb_readl(macb, NCR);
242 netctl &= ~MACB_BIT(MPE);
243 macb_writel(macb, NCR, netctl);
244
245 return MACB_BFEXT(DATA, frame);
246}
247
Joe Hershberger9e5742b2013-06-24 19:06:38 -0500248void __weak arch_get_mdio_control(const char *name)
Shiraz Hashim77cdf0f2012-12-13 17:22:52 +0530249{
250 return;
251}
252
Bo Shen7d91deb2013-04-24 15:59:27 +0800253#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
Semih Hazar790088e2009-12-17 15:07:15 +0200254
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500255int macb_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg)
Semih Hazar790088e2009-12-17 15:07:15 +0200256{
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500257 u16 value = 0;
Simon Glass75c5d182016-05-05 07:28:11 -0600258#ifdef CONFIG_DM_ETH
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500259 struct udevice *dev = eth_get_dev_by_name(bus->name);
Simon Glass75c5d182016-05-05 07:28:11 -0600260 struct macb_device *macb = dev_get_priv(dev);
261#else
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500262 struct eth_device *dev = eth_get_dev_by_name(bus->name);
Semih Hazar790088e2009-12-17 15:07:15 +0200263 struct macb_device *macb = to_macb(dev);
Simon Glass75c5d182016-05-05 07:28:11 -0600264#endif
Semih Hazar790088e2009-12-17 15:07:15 +0200265
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500266 arch_get_mdio_control(bus->name);
Josef Holzmayr017feb52019-10-02 21:22:52 +0200267 value = macb_mdio_read(macb, phy_adr, reg);
Semih Hazar790088e2009-12-17 15:07:15 +0200268
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500269 return value;
Semih Hazar790088e2009-12-17 15:07:15 +0200270}
271
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500272int macb_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg,
273 u16 value)
Semih Hazar790088e2009-12-17 15:07:15 +0200274{
Simon Glass75c5d182016-05-05 07:28:11 -0600275#ifdef CONFIG_DM_ETH
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500276 struct udevice *dev = eth_get_dev_by_name(bus->name);
Simon Glass75c5d182016-05-05 07:28:11 -0600277 struct macb_device *macb = dev_get_priv(dev);
278#else
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500279 struct eth_device *dev = eth_get_dev_by_name(bus->name);
Semih Hazar790088e2009-12-17 15:07:15 +0200280 struct macb_device *macb = to_macb(dev);
Simon Glass75c5d182016-05-05 07:28:11 -0600281#endif
Semih Hazar790088e2009-12-17 15:07:15 +0200282
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500283 arch_get_mdio_control(bus->name);
Josef Holzmayr017feb52019-10-02 21:22:52 +0200284 macb_mdio_write(macb, phy_adr, reg, value);
Semih Hazar790088e2009-12-17 15:07:15 +0200285
286 return 0;
287}
288#endif
289
Wu, Josh18052402014-05-27 16:31:05 +0800290#define RX 1
291#define TX 0
292static inline void macb_invalidate_ring_desc(struct macb_device *macb, bool rx)
293{
294 if (rx)
Heiko Schocher8353f9d2016-08-29 07:46:11 +0200295 invalidate_dcache_range(macb->rx_ring_dma,
296 ALIGN(macb->rx_ring_dma + MACB_RX_DMA_DESC_SIZE,
297 PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800298 else
Heiko Schocher8353f9d2016-08-29 07:46:11 +0200299 invalidate_dcache_range(macb->tx_ring_dma,
300 ALIGN(macb->tx_ring_dma + MACB_TX_DMA_DESC_SIZE,
301 PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800302}
303
304static inline void macb_flush_ring_desc(struct macb_device *macb, bool rx)
305{
306 if (rx)
307 flush_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma +
Heiko Schocher8353f9d2016-08-29 07:46:11 +0200308 ALIGN(MACB_RX_DMA_DESC_SIZE, PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800309 else
310 flush_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma +
Heiko Schocher8353f9d2016-08-29 07:46:11 +0200311 ALIGN(MACB_TX_DMA_DESC_SIZE, PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800312}
313
314static inline void macb_flush_rx_buffer(struct macb_device *macb)
315{
316 flush_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma +
Stefan Roese7df65a52019-08-26 09:18:11 +0200317 ALIGN(macb->rx_buffer_size * MACB_RX_RING_SIZE,
318 PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800319}
320
321static inline void macb_invalidate_rx_buffer(struct macb_device *macb)
322{
323 invalidate_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma +
Stefan Roese7df65a52019-08-26 09:18:11 +0200324 ALIGN(macb->rx_buffer_size * MACB_RX_RING_SIZE,
325 PKTALIGN));
Wu, Josh18052402014-05-27 16:31:05 +0800326}
Semih Hazar790088e2009-12-17 15:07:15 +0200327
Jon Loeligerb1d408a2007-07-09 17:30:01 -0500328#if defined(CONFIG_CMD_NET)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100329
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530330static struct macb_dma_desc_64 *macb_64b_desc(struct macb_dma_desc *desc)
331{
332 return (struct macb_dma_desc_64 *)((void *)desc
333 + sizeof(struct macb_dma_desc));
334}
335
336static void macb_set_addr(struct macb_device *macb, struct macb_dma_desc *desc,
337 ulong addr)
338{
339 struct macb_dma_desc_64 *desc_64;
340
341 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
342 desc_64 = macb_64b_desc(desc);
343 desc_64->addrh = upper_32_bits(addr);
344 }
345 desc->addr = lower_32_bits(addr);
346}
347
Simon Glass5ad27512016-05-05 07:28:09 -0600348static int _macb_send(struct macb_device *macb, const char *name, void *packet,
349 int length)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100350{
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100351 unsigned long paddr, ctrl;
352 unsigned int tx_head = macb->tx_head;
353 int i;
354
355 paddr = dma_map_single(packet, length, DMA_TO_DEVICE);
356
357 ctrl = length & TXBUF_FRMLEN_MASK;
Ramon Fried6402fb192019-07-16 22:04:33 +0300358 ctrl |= MACB_BIT(TX_LAST);
Andreas Bießmann1e868122014-05-26 22:55:18 +0200359 if (tx_head == (MACB_TX_RING_SIZE - 1)) {
Ramon Fried6402fb192019-07-16 22:04:33 +0300360 ctrl |= MACB_BIT(TX_WRAP);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100361 macb->tx_head = 0;
Andreas Bießmann1e868122014-05-26 22:55:18 +0200362 } else {
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100363 macb->tx_head++;
Andreas Bießmann1e868122014-05-26 22:55:18 +0200364 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100365
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530366 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
367 tx_head = tx_head * 2;
368
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100369 macb->tx_ring[tx_head].ctrl = ctrl;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530370 macb_set_addr(macb, &macb->tx_ring[tx_head], paddr);
371
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200372 barrier();
Wu, Josh18052402014-05-27 16:31:05 +0800373 macb_flush_ring_desc(macb, TX);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100374 macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
375
376 /*
377 * I guess this is necessary because the networking core may
378 * re-use the transmit buffer as soon as we return...
379 */
Andreas Bießmann1e868122014-05-26 22:55:18 +0200380 for (i = 0; i <= MACB_TX_TIMEOUT; i++) {
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200381 barrier();
Wu, Josh18052402014-05-27 16:31:05 +0800382 macb_invalidate_ring_desc(macb, TX);
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200383 ctrl = macb->tx_ring[tx_head].ctrl;
Ramon Fried6402fb192019-07-16 22:04:33 +0300384 if (ctrl & MACB_BIT(TX_USED))
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100385 break;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100386 udelay(1);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100387 }
388
Masahiro Yamada05a5dba2020-02-14 16:40:18 +0900389 dma_unmap_single(paddr, length, DMA_TO_DEVICE);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100390
Andreas Bießmann1e868122014-05-26 22:55:18 +0200391 if (i <= MACB_TX_TIMEOUT) {
Ramon Fried6402fb192019-07-16 22:04:33 +0300392 if (ctrl & MACB_BIT(TX_UNDERRUN))
Simon Glass5ad27512016-05-05 07:28:09 -0600393 printf("%s: TX underrun\n", name);
Ramon Fried6402fb192019-07-16 22:04:33 +0300394 if (ctrl & MACB_BIT(TX_BUF_EXHAUSTED))
Simon Glass5ad27512016-05-05 07:28:09 -0600395 printf("%s: TX buffers exhausted in mid frame\n", name);
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200396 } else {
Simon Glass5ad27512016-05-05 07:28:09 -0600397 printf("%s: TX timeout\n", name);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100398 }
399
400 /* No one cares anyway */
401 return 0;
402}
403
404static void reclaim_rx_buffers(struct macb_device *macb,
405 unsigned int new_tail)
406{
407 unsigned int i;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530408 unsigned int count;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100409
410 i = macb->rx_tail;
Wu, Josh18052402014-05-27 16:31:05 +0800411
412 macb_invalidate_ring_desc(macb, RX);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100413 while (i > new_tail) {
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530414 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
415 count = i * 2;
416 else
417 count = i;
418 macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100419 i++;
Andreas Bießmann1e868122014-05-26 22:55:18 +0200420 if (i > MACB_RX_RING_SIZE)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100421 i = 0;
422 }
423
424 while (i < new_tail) {
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530425 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
426 count = i * 2;
427 else
428 count = i;
429 macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100430 i++;
431 }
432
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200433 barrier();
Wu, Josh18052402014-05-27 16:31:05 +0800434 macb_flush_ring_desc(macb, RX);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100435 macb->rx_tail = new_tail;
436}
437
Simon Glass5ad27512016-05-05 07:28:09 -0600438static int _macb_recv(struct macb_device *macb, uchar **packetp)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100439{
Simon Glass5ad27512016-05-05 07:28:09 -0600440 unsigned int next_rx_tail = macb->next_rx_tail;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100441 void *buffer;
442 int length;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100443 u32 status;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530444 u8 flag = false;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100445
Simon Glass5ad27512016-05-05 07:28:09 -0600446 macb->wrapped = false;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100447 for (;;) {
Wu, Josh18052402014-05-27 16:31:05 +0800448 macb_invalidate_ring_desc(macb, RX);
449
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530450 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
451 next_rx_tail = next_rx_tail * 2;
452
Ramon Fried6402fb192019-07-16 22:04:33 +0300453 if (!(macb->rx_ring[next_rx_tail].addr & MACB_BIT(RX_USED)))
Simon Glass5ad27512016-05-05 07:28:09 -0600454 return -EAGAIN;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100455
Simon Glass5ad27512016-05-05 07:28:09 -0600456 status = macb->rx_ring[next_rx_tail].ctrl;
Ramon Fried6402fb192019-07-16 22:04:33 +0300457 if (status & MACB_BIT(RX_SOF)) {
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530458 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
459 next_rx_tail = next_rx_tail / 2;
460 flag = true;
461 }
462
Simon Glass5ad27512016-05-05 07:28:09 -0600463 if (next_rx_tail != macb->rx_tail)
464 reclaim_rx_buffers(macb, next_rx_tail);
465 macb->wrapped = false;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100466 }
467
Ramon Fried6402fb192019-07-16 22:04:33 +0300468 if (status & MACB_BIT(RX_EOF)) {
Ramon Fried377d19d2019-07-14 18:25:14 +0300469 buffer = macb->rx_buffer +
470 macb->rx_buffer_size * macb->rx_tail;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100471 length = status & RXBUF_FRMLEN_MASK;
Wu, Josh18052402014-05-27 16:31:05 +0800472
473 macb_invalidate_rx_buffer(macb);
Simon Glass5ad27512016-05-05 07:28:09 -0600474 if (macb->wrapped) {
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100475 unsigned int headlen, taillen;
476
Ramon Fried377d19d2019-07-14 18:25:14 +0300477 headlen = macb->rx_buffer_size *
478 (MACB_RX_RING_SIZE - macb->rx_tail);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100479 taillen = length - headlen;
Joe Hershberger9f09a362015-04-08 01:41:06 -0500480 memcpy((void *)net_rx_packets[0],
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100481 buffer, headlen);
Joe Hershberger9f09a362015-04-08 01:41:06 -0500482 memcpy((void *)net_rx_packets[0] + headlen,
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100483 macb->rx_buffer, taillen);
Simon Glass5ad27512016-05-05 07:28:09 -0600484 *packetp = (void *)net_rx_packets[0];
485 } else {
486 *packetp = buffer;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100487 }
488
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 }
493
Simon Glass5ad27512016-05-05 07:28:09 -0600494 if (++next_rx_tail >= MACB_RX_RING_SIZE)
495 next_rx_tail = 0;
496 macb->next_rx_tail = next_rx_tail;
497 return length;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100498 } else {
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530499 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
500 if (!flag)
501 next_rx_tail = next_rx_tail / 2;
502 flag = false;
503 }
504
Simon Glass5ad27512016-05-05 07:28:09 -0600505 if (++next_rx_tail >= MACB_RX_RING_SIZE) {
506 macb->wrapped = true;
507 next_rx_tail = 0;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100508 }
509 }
Haavard Skinnemoen996e1472007-05-02 13:22:38 +0200510 barrier();
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100511 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100512}
513
Simon Glass5ad27512016-05-05 07:28:09 -0600514static void macb_phy_reset(struct macb_device *macb, const char *name)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100515{
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100516 int i;
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200517 u16 status, adv;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100518
519 adv = ADVERTISE_CSMA | ADVERTISE_ALL;
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200520 macb_mdio_write(macb, macb->phy_addr, MII_ADVERTISE, adv);
Simon Glass5ad27512016-05-05 07:28:09 -0600521 printf("%s: Starting autonegotiation...\n", name);
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200522 macb_mdio_write(macb, macb->phy_addr, MII_BMCR, (BMCR_ANENABLE
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100523 | BMCR_ANRESTART));
524
Andreas Bießmann1e868122014-05-26 22:55:18 +0200525 for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200526 status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100527 if (status & BMSR_ANEGCOMPLETE)
528 break;
529 udelay(100);
530 }
531
532 if (status & BMSR_ANEGCOMPLETE)
Simon Glass5ad27512016-05-05 07:28:09 -0600533 printf("%s: Autonegotiation complete\n", name);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100534 else
535 printf("%s: Autonegotiation timed out (status=0x%04x)\n",
Simon Glass5ad27512016-05-05 07:28:09 -0600536 name, status);
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200537}
538
Wenyou Yang7b811852016-05-17 13:11:35 +0800539static int macb_phy_find(struct macb_device *macb, const char *name)
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100540{
541 int i;
542 u16 phy_id;
543
Padmarao Begari34394ba2021-01-15 08:20:37 +0530544 phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
545 if (phy_id != 0xffff) {
546 printf("%s: PHY present at %d\n", name, macb->phy_addr);
547 return 0;
548 }
549
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100550 /* Search for PHY... */
551 for (i = 0; i < 32; i++) {
552 macb->phy_addr = i;
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200553 phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100554 if (phy_id != 0xffff) {
Wenyou Yang7b811852016-05-17 13:11:35 +0800555 printf("%s: PHY present at %d\n", name, i);
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700556 return 0;
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100557 }
558 }
559
560 /* PHY isn't up to snuff */
Wenyou Yang7b811852016-05-17 13:11:35 +0800561 printf("%s: PHY not found\n", name);
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100562
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700563 return -ENODEV;
564}
565
566/**
567 * macb_linkspd_cb - Linkspeed change callback function
Bin Mengcf821322019-05-22 00:09:45 -0700568 * @dev/@regs: MACB udevice (DM version) or
569 * Base Register of MACB devices (non-DM version)
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700570 * @speed: Linkspeed
571 * Returns 0 when operation success and negative errno number
572 * when operation failed.
573 */
Bin Mengcf821322019-05-22 00:09:45 -0700574#ifdef CONFIG_DM_ETH
Anup Patel88799a62019-07-24 04:09:32 +0000575static int macb_sifive_clk_init(struct udevice *dev, ulong rate)
576{
577 fdt_addr_t addr;
578 void *gemgxl_regs;
579
580 addr = dev_read_addr_index(dev, 1);
581 if (addr == FDT_ADDR_T_NONE)
582 return -ENODEV;
583
584 gemgxl_regs = (void __iomem *)addr;
585 if (!gemgxl_regs)
586 return -ENODEV;
587
588 /*
589 * SiFive GEMGXL TX clock operation mode:
590 *
591 * 0 = GMII mode. Use 125 MHz gemgxlclk from PRCI in TX logic
592 * and output clock on GMII output signal GTX_CLK
593 * 1 = MII mode. Use MII input signal TX_CLK in TX logic
594 */
595 writel(rate != 125000000, gemgxl_regs);
596 return 0;
597}
598
Claudiu Beznea01ca4eb2021-01-19 13:26:46 +0200599static int macb_sama7g5_clk_init(struct udevice *dev, ulong rate)
600{
601 struct clk clk;
602 int ret;
603
604 ret = clk_get_by_name(dev, "tx_clk", &clk);
605 if (ret)
606 return ret;
607
608 /*
609 * This is for using GCK. Clock rate is addressed via assigned-clock
610 * property, so only clock enable is needed here. The switching to
611 * proper clock rate depending on link speed is managed by IP logic.
612 */
613 return clk_enable(&clk);
614}
615
Bin Mengcf821322019-05-22 00:09:45 -0700616int __weak macb_linkspd_cb(struct udevice *dev, unsigned int speed)
617{
Bin Meng12766ca2019-05-22 00:09:46 -0700618#ifdef CONFIG_CLK
Anup Patel88799a62019-07-24 04:09:32 +0000619 struct macb_device *macb = dev_get_priv(dev);
Bin Meng12766ca2019-05-22 00:09:46 -0700620 struct clk tx_clk;
621 ulong rate;
622 int ret;
623
Bin Meng12766ca2019-05-22 00:09:46 -0700624 switch (speed) {
625 case _10BASET:
626 rate = 2500000; /* 2.5 MHz */
627 break;
628 case _100BASET:
629 rate = 25000000; /* 25 MHz */
630 break;
631 case _1000BASET:
632 rate = 125000000; /* 125 MHz */
633 break;
634 default:
635 /* does not change anything */
636 return 0;
637 }
638
Anup Patel88799a62019-07-24 04:09:32 +0000639 if (macb->config->clk_init)
640 return macb->config->clk_init(dev, rate);
641
642 /*
643 * "tx_clk" is an optional clock source for MACB.
644 * Ignore if it does not exist in DT.
645 */
646 ret = clk_get_by_name(dev, "tx_clk", &tx_clk);
647 if (ret)
648 return 0;
649
Bin Meng12766ca2019-05-22 00:09:46 -0700650 if (tx_clk.dev) {
651 ret = clk_set_rate(&tx_clk, rate);
Claudiu Bezneae2888dc2021-01-19 13:26:45 +0200652 if (ret < 0)
Bin Meng12766ca2019-05-22 00:09:46 -0700653 return ret;
654 }
655#endif
656
Bin Mengcf821322019-05-22 00:09:45 -0700657 return 0;
658}
659#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700660int __weak macb_linkspd_cb(void *regs, unsigned int speed)
661{
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100662 return 0;
663}
Bin Mengcf821322019-05-22 00:09:45 -0700664#endif
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100665
Wenyou Yang7b811852016-05-17 13:11:35 +0800666#ifdef CONFIG_DM_ETH
667static int macb_phy_init(struct udevice *dev, const char *name)
668#else
Simon Glass5ad27512016-05-05 07:28:09 -0600669static int macb_phy_init(struct macb_device *macb, const char *name)
Wenyou Yang7b811852016-05-17 13:11:35 +0800670#endif
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200671{
Wenyou Yang7b811852016-05-17 13:11:35 +0800672#ifdef CONFIG_DM_ETH
673 struct macb_device *macb = dev_get_priv(dev);
674#endif
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200675 u32 ncfgr;
676 u16 phy_id, status, adv, lpa;
677 int media, speed, duplex;
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700678 int ret;
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200679 int i;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100680
Simon Glass5ad27512016-05-05 07:28:09 -0600681 arch_get_mdio_control(name);
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100682 /* Auto-detect phy_addr */
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700683 ret = macb_phy_find(macb, name);
684 if (ret)
685 return ret;
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100686
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200687 /* Check if the PHY is up to snuff... */
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200688 phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200689 if (phy_id == 0xffff) {
Simon Glass5ad27512016-05-05 07:28:09 -0600690 printf("%s: No PHY present\n", name);
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700691 return -ENODEV;
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200692 }
693
Bo Shen7d91deb2013-04-24 15:59:27 +0800694#ifdef CONFIG_PHYLIB
Wenyou Yang7b811852016-05-17 13:11:35 +0800695#ifdef CONFIG_DM_ETH
Wenyou Yang44835ea2017-04-14 14:36:04 +0800696 macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev,
Wenyou Yang7b811852016-05-17 13:11:35 +0800697 macb->phy_interface);
698#else
Bo Shene04fe552013-08-19 10:35:47 +0800699 /* need to consider other phy interface mode */
Wenyou Yang44835ea2017-04-14 14:36:04 +0800700 macb->phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev,
Bo Shene04fe552013-08-19 10:35:47 +0800701 PHY_INTERFACE_MODE_RGMII);
Wenyou Yang7b811852016-05-17 13:11:35 +0800702#endif
Wenyou Yang44835ea2017-04-14 14:36:04 +0800703 if (!macb->phydev) {
Bo Shene04fe552013-08-19 10:35:47 +0800704 printf("phy_connect failed\n");
705 return -ENODEV;
706 }
707
Wenyou Yang44835ea2017-04-14 14:36:04 +0800708 phy_config(macb->phydev);
Bo Shen7d91deb2013-04-24 15:59:27 +0800709#endif
710
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200711 status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100712 if (!(status & BMSR_LSTATUS)) {
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200713 /* Try to re-negotiate if we don't have link already. */
Simon Glass5ad27512016-05-05 07:28:09 -0600714 macb_phy_reset(macb, name);
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200715
Andreas Bießmann1e868122014-05-26 22:55:18 +0200716 for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200717 status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
Stefan Roese40291802019-03-27 11:20:19 +0100718 if (status & BMSR_LSTATUS) {
719 /*
720 * Delay a bit after the link is established,
721 * so that the next xfer does not fail
722 */
723 mdelay(10);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100724 break;
Stefan Roese40291802019-03-27 11:20:19 +0100725 }
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200726 udelay(100);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100727 }
728 }
729
730 if (!(status & BMSR_LSTATUS)) {
731 printf("%s: link down (status: 0x%04x)\n",
Simon Glass5ad27512016-05-05 07:28:09 -0600732 name, status);
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700733 return -ENETDOWN;
Bo Shen6f7d7d92013-04-24 15:59:28 +0800734 }
735
Gregory CLEMENTf1a1e582015-12-16 14:50:34 +0100736 /* First check for GMAC and that it is GiB capable */
737 if (gem_is_gigabit_capable(macb)) {
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200738 lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100739
Radu Pirea1676dfb2019-06-07 14:18:36 +0300740 if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
741 LPA_1000XHALF)) {
742 duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ?
743 1 : 0);
Andreas Bießmannd43a89a2014-09-18 23:46:48 +0200744
745 printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
Simon Glass5ad27512016-05-05 07:28:09 -0600746 name,
Bo Shen6f7d7d92013-04-24 15:59:28 +0800747 duplex ? "full" : "half",
748 lpa);
749
750 ncfgr = macb_readl(macb, NCFGR);
Andreas Bießmannd43a89a2014-09-18 23:46:48 +0200751 ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
752 ncfgr |= GEM_BIT(GBE);
753
Bo Shen6f7d7d92013-04-24 15:59:28 +0800754 if (duplex)
755 ncfgr |= MACB_BIT(FD);
Andreas Bießmannd43a89a2014-09-18 23:46:48 +0200756
Bo Shen6f7d7d92013-04-24 15:59:28 +0800757 macb_writel(macb, NCFGR, ncfgr);
758
Bin Mengcf821322019-05-22 00:09:45 -0700759#ifdef CONFIG_DM_ETH
760 ret = macb_linkspd_cb(dev, _1000BASET);
761#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700762 ret = macb_linkspd_cb(macb->regs, _1000BASET);
Bin Mengcf821322019-05-22 00:09:45 -0700763#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700764 if (ret)
765 return ret;
766
767 return 0;
Bo Shen6f7d7d92013-04-24 15:59:28 +0800768 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100769 }
Bo Shen6f7d7d92013-04-24 15:59:28 +0800770
771 /* fall back for EMAC checking */
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200772 adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE);
773 lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA);
Bo Shen6f7d7d92013-04-24 15:59:28 +0800774 media = mii_nway_result(lpa & adv);
775 speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
776 ? 1 : 0);
777 duplex = (media & ADVERTISE_FULL) ? 1 : 0;
778 printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
Simon Glass5ad27512016-05-05 07:28:09 -0600779 name,
Bo Shen6f7d7d92013-04-24 15:59:28 +0800780 speed ? "100" : "10",
781 duplex ? "full" : "half",
782 lpa);
783
784 ncfgr = macb_readl(macb, NCFGR);
Bo Shenfe19ef32015-03-04 13:35:16 +0800785 ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE));
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700786 if (speed) {
Bo Shen6f7d7d92013-04-24 15:59:28 +0800787 ncfgr |= MACB_BIT(SPD);
Bin Mengcf821322019-05-22 00:09:45 -0700788#ifdef CONFIG_DM_ETH
789 ret = macb_linkspd_cb(dev, _100BASET);
790#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700791 ret = macb_linkspd_cb(macb->regs, _100BASET);
Bin Mengcf821322019-05-22 00:09:45 -0700792#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700793 } else {
Bin Mengcf821322019-05-22 00:09:45 -0700794#ifdef CONFIG_DM_ETH
795 ret = macb_linkspd_cb(dev, _10BASET);
796#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700797 ret = macb_linkspd_cb(macb->regs, _10BASET);
Bin Mengcf821322019-05-22 00:09:45 -0700798#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700799 }
800
801 if (ret)
802 return ret;
803
Bo Shen6f7d7d92013-04-24 15:59:28 +0800804 if (duplex)
805 ncfgr |= MACB_BIT(FD);
806 macb_writel(macb, NCFGR, ncfgr);
807
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700808 return 0;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100809}
810
Wu, Josh012d68d2015-06-03 16:45:44 +0800811static int gmac_init_multi_queues(struct macb_device *macb)
812{
813 int i, num_queues = 1;
814 u32 queue_mask;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530815 unsigned long paddr;
Wu, Josh012d68d2015-06-03 16:45:44 +0800816
817 /* bit 0 is never set but queue 0 always exists */
818 queue_mask = gem_readl(macb, DCFG6) & 0xff;
819 queue_mask |= 0x1;
820
821 for (i = 1; i < MACB_MAX_QUEUES; i++)
822 if (queue_mask & (1 << i))
823 num_queues++;
824
Ramon Fried6402fb192019-07-16 22:04:33 +0300825 macb->dummy_desc->ctrl = MACB_BIT(TX_USED);
Wu, Josh012d68d2015-06-03 16:45:44 +0800826 macb->dummy_desc->addr = 0;
827 flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma +
Heiko Schocher8353f9d2016-08-29 07:46:11 +0200828 ALIGN(MACB_TX_DUMMY_DMA_DESC_SIZE, PKTALIGN));
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530829 paddr = macb->dummy_desc_dma;
Wu, Josh012d68d2015-06-03 16:45:44 +0800830
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530831 for (i = 1; i < num_queues; i++) {
832 gem_writel_queue_TBQP(macb, lower_32_bits(paddr), i - 1);
833 gem_writel_queue_RBQP(macb, lower_32_bits(paddr), i - 1);
834 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
835 gem_writel_queue_TBQPH(macb, upper_32_bits(paddr),
836 i - 1);
837 gem_writel_queue_RBQPH(macb, upper_32_bits(paddr),
838 i - 1);
839 }
840 }
Wu, Josh012d68d2015-06-03 16:45:44 +0800841 return 0;
842}
843
Ramon Friedb40501f2019-07-16 22:04:36 +0300844static void gmac_configure_dma(struct macb_device *macb)
845{
846 u32 buffer_size;
847 u32 dmacfg;
848
Ramon Fried377d19d2019-07-14 18:25:14 +0300849 buffer_size = macb->rx_buffer_size / RX_BUFFER_MULTIPLE;
Ramon Friedb40501f2019-07-16 22:04:36 +0300850 dmacfg = gem_readl(macb, DMACFG) & ~GEM_BF(RXBS, -1L);
851 dmacfg |= GEM_BF(RXBS, buffer_size);
852
Anup Patel88799a62019-07-24 04:09:32 +0000853 if (macb->config->dma_burst_length)
854 dmacfg = GEM_BFINS(FBLDO,
855 macb->config->dma_burst_length, dmacfg);
Ramon Friedb40501f2019-07-16 22:04:36 +0300856
857 dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
858 dmacfg &= ~GEM_BIT(ENDIA_PKT);
859
Anup Patela1818b12019-07-24 04:09:37 +0000860 if (macb->is_big_endian)
Ramon Friedb40501f2019-07-16 22:04:36 +0300861 dmacfg |= GEM_BIT(ENDIA_DESC); /* CPU in big endian */
Anup Patela1818b12019-07-24 04:09:37 +0000862 else
863 dmacfg &= ~GEM_BIT(ENDIA_DESC);
Ramon Friedb40501f2019-07-16 22:04:36 +0300864
865 dmacfg &= ~GEM_BIT(ADDR64);
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530866 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
867 dmacfg |= GEM_BIT(ADDR64);
868
Ramon Friedb40501f2019-07-16 22:04:36 +0300869 gem_writel(macb, DMACFG, dmacfg);
870}
871
Wenyou Yang7b811852016-05-17 13:11:35 +0800872#ifdef CONFIG_DM_ETH
873static int _macb_init(struct udevice *dev, const char *name)
874#else
Simon Glass5ad27512016-05-05 07:28:09 -0600875static int _macb_init(struct macb_device *macb, const char *name)
Wenyou Yang7b811852016-05-17 13:11:35 +0800876#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100877{
Wenyou Yang7b811852016-05-17 13:11:35 +0800878#ifdef CONFIG_DM_ETH
879 struct macb_device *macb = dev_get_priv(dev);
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200880 unsigned int val = 0;
Wenyou Yang7b811852016-05-17 13:11:35 +0800881#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100882 unsigned long paddr;
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700883 int ret;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100884 int i;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530885 int count;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100886
887 /*
888 * macb_halt should have been called at some point before now,
889 * so we'll assume the controller is idle.
890 */
891
892 /* initialize DMA descriptors */
893 paddr = macb->rx_buffer_dma;
Andreas Bießmann1e868122014-05-26 22:55:18 +0200894 for (i = 0; i < MACB_RX_RING_SIZE; i++) {
895 if (i == (MACB_RX_RING_SIZE - 1))
Ramon Fried6402fb192019-07-16 22:04:33 +0300896 paddr |= MACB_BIT(RX_WRAP);
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530897 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
898 count = i * 2;
899 else
900 count = i;
901 macb->rx_ring[count].ctrl = 0;
902 macb_set_addr(macb, &macb->rx_ring[count], paddr);
Ramon Fried377d19d2019-07-14 18:25:14 +0300903 paddr += macb->rx_buffer_size;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100904 }
Wu, Josh18052402014-05-27 16:31:05 +0800905 macb_flush_ring_desc(macb, RX);
906 macb_flush_rx_buffer(macb);
907
Andreas Bießmann1e868122014-05-26 22:55:18 +0200908 for (i = 0; i < MACB_TX_RING_SIZE; i++) {
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530909 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
910 count = i * 2;
911 else
912 count = i;
913 macb_set_addr(macb, &macb->tx_ring[count], 0);
Andreas Bießmann1e868122014-05-26 22:55:18 +0200914 if (i == (MACB_TX_RING_SIZE - 1))
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530915 macb->tx_ring[count].ctrl = MACB_BIT(TX_USED) |
Ramon Fried6402fb192019-07-16 22:04:33 +0300916 MACB_BIT(TX_WRAP);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100917 else
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530918 macb->tx_ring[count].ctrl = MACB_BIT(TX_USED);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100919 }
Wu, Josh18052402014-05-27 16:31:05 +0800920 macb_flush_ring_desc(macb, TX);
921
Andreas Bießmann1e868122014-05-26 22:55:18 +0200922 macb->rx_tail = 0;
923 macb->tx_head = 0;
924 macb->tx_tail = 0;
Simon Glass5ad27512016-05-05 07:28:09 -0600925 macb->next_rx_tail = 0;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100926
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700927#ifdef CONFIG_MACB_ZYNQ
Michal Simekfc91bdb2020-03-26 15:01:29 +0100928 gem_writel(macb, DMACFG, MACB_ZYNQ_GEM_DMACR_INIT);
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700929#endif
930
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530931 macb_writel(macb, RBQP, lower_32_bits(macb->rx_ring_dma));
932 macb_writel(macb, TBQP, lower_32_bits(macb->tx_ring_dma));
933 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
934 macb_writel(macb, RBQPH, upper_32_bits(macb->rx_ring_dma));
935 macb_writel(macb, TBQPH, upper_32_bits(macb->tx_ring_dma));
936 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100937
Bo Shen6f7d7d92013-04-24 15:59:28 +0800938 if (macb_is_gem(macb)) {
Ramon Friedb40501f2019-07-16 22:04:36 +0300939 /* Initialize DMA properties */
940 gmac_configure_dma(macb);
Wu, Josh012d68d2015-06-03 16:45:44 +0800941 /* Check the multi queue and initialize the queue for tx */
942 gmac_init_multi_queues(macb);
943
Bo Shen4660b332014-11-10 15:24:01 +0800944 /*
945 * When the GMAC IP with GE feature, this bit is used to
946 * select interface between RGMII and GMII.
947 * When the GMAC IP without GE feature, this bit is used
948 * to select interface between RMII and MII.
949 */
Wenyou Yang7b811852016-05-17 13:11:35 +0800950#ifdef CONFIG_DM_ETH
Claudiu Bezneaa81146b2021-01-19 13:26:48 +0200951 if (macb->phy_interface == PHY_INTERFACE_MODE_RGMII ||
952 macb->phy_interface == PHY_INTERFACE_MODE_RGMII_ID ||
953 macb->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID ||
954 macb->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID)
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200955 val = macb->config->usrio->rgmii;
956 else if (macb->phy_interface == PHY_INTERFACE_MODE_RMII)
957 val = macb->config->usrio->rmii;
958 else if (macb->phy_interface == PHY_INTERFACE_MODE_MII)
959 val = macb->config->usrio->mii;
960
961 if (macb->config->caps & MACB_CAPS_USRIO_HAS_CLKEN)
962 val |= macb->config->usrio->clken;
963
964 gem_writel(macb, USRIO, val);
Ramon Fried588a5b72019-07-16 22:04:34 +0300965
966 if (macb->phy_interface == PHY_INTERFACE_MODE_SGMII) {
967 unsigned int ncfgr = macb_readl(macb, NCFGR);
968
969 ncfgr |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
970 macb_writel(macb, NCFGR, ncfgr);
971 }
Wenyou Yang7b811852016-05-17 13:11:35 +0800972#else
Bo Shen4660b332014-11-10 15:24:01 +0800973#if defined(CONFIG_RGMII) || defined(CONFIG_RMII)
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200974 gem_writel(macb, USRIO, macb->config->usrio->rgmii);
Bo Shen6f7d7d92013-04-24 15:59:28 +0800975#else
Ramon Fried94e6bd82019-07-16 22:03:00 +0300976 gem_writel(macb, USRIO, 0);
Bo Shen6f7d7d92013-04-24 15:59:28 +0800977#endif
Wenyou Yang7b811852016-05-17 13:11:35 +0800978#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +0800979 } else {
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100980 /* choose RMII or MII mode. This depends on the board */
Wenyou Yang7b811852016-05-17 13:11:35 +0800981#ifdef CONFIG_DM_ETH
982#ifdef CONFIG_AT91FAMILY
983 if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) {
984 macb_writel(macb, USRIO,
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200985 macb->config->usrio->rmii |
986 macb->config->usrio->clken);
Wenyou Yang7b811852016-05-17 13:11:35 +0800987 } else {
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200988 macb_writel(macb, USRIO, macb->config->usrio->clken);
Wenyou Yang7b811852016-05-17 13:11:35 +0800989 }
990#else
991 if (macb->phy_interface == PHY_INTERFACE_MODE_RMII)
992 macb_writel(macb, USRIO, 0);
993 else
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200994 macb_writel(macb, USRIO, macb->config->usrio->mii);
Wenyou Yang7b811852016-05-17 13:11:35 +0800995#endif
996#else
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100997#ifdef CONFIG_RMII
Bo Shencc29ce52013-04-24 15:59:26 +0800998#ifdef CONFIG_AT91FAMILY
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200999 macb_writel(macb, USRIO, macb->config->usrio->rmii |
1000 macb->config->usrio->clken);
Stelian Pop87a82542008-01-03 21:15:56 +00001001#else
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001002 macb_writel(macb, USRIO, 0);
Stelian Pop87a82542008-01-03 21:15:56 +00001003#endif
1004#else
Bo Shencc29ce52013-04-24 15:59:26 +08001005#ifdef CONFIG_AT91FAMILY
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001006 macb_writel(macb, USRIO, macb->config->usrio->clken);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001007#else
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001008 macb_writel(macb, USRIO, macb->config->usrio->mii);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001009#endif
Stelian Pop87a82542008-01-03 21:15:56 +00001010#endif /* CONFIG_RMII */
Wenyou Yang7b811852016-05-17 13:11:35 +08001011#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +08001012 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001013
Wenyou Yang7b811852016-05-17 13:11:35 +08001014#ifdef CONFIG_DM_ETH
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001015 ret = macb_phy_init(dev, name);
Wenyou Yang7b811852016-05-17 13:11:35 +08001016#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001017 ret = macb_phy_init(macb, name);
Wenyou Yang7b811852016-05-17 13:11:35 +08001018#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001019 if (ret)
1020 return ret;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001021
1022 /* Enable TX and RX */
1023 macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE));
1024
Ben Warrende9fcb52008-01-09 18:15:53 -05001025 return 0;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001026}
1027
Simon Glass5ad27512016-05-05 07:28:09 -06001028static void _macb_halt(struct macb_device *macb)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001029{
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001030 u32 ncr, tsr;
1031
1032 /* Halt the controller and wait for any ongoing transmission to end. */
1033 ncr = macb_readl(macb, NCR);
1034 ncr |= MACB_BIT(THALT);
1035 macb_writel(macb, NCR, ncr);
1036
1037 do {
1038 tsr = macb_readl(macb, TSR);
1039 } while (tsr & MACB_BIT(TGO));
1040
1041 /* Disable TX and RX, and clear statistics */
1042 macb_writel(macb, NCR, MACB_BIT(CLRSTAT));
1043}
1044
Simon Glass5ad27512016-05-05 07:28:09 -06001045static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr)
Ben Warren33f84312010-06-01 11:55:42 -07001046{
Ben Warren33f84312010-06-01 11:55:42 -07001047 u32 hwaddr_bottom;
1048 u16 hwaddr_top;
1049
1050 /* set hardware address */
Simon Glass5ad27512016-05-05 07:28:09 -06001051 hwaddr_bottom = enetaddr[0] | enetaddr[1] << 8 |
1052 enetaddr[2] << 16 | enetaddr[3] << 24;
Ben Warren33f84312010-06-01 11:55:42 -07001053 macb_writel(macb, SA1B, hwaddr_bottom);
Simon Glass5ad27512016-05-05 07:28:09 -06001054 hwaddr_top = enetaddr[4] | enetaddr[5] << 8;
Ben Warren33f84312010-06-01 11:55:42 -07001055 macb_writel(macb, SA1T, hwaddr_top);
1056 return 0;
1057}
1058
Bo Shen6f7d7d92013-04-24 15:59:28 +08001059static u32 macb_mdc_clk_div(int id, struct macb_device *macb)
1060{
1061 u32 config;
Wenyou Yang19449362017-02-14 16:24:40 +08001062#if defined(CONFIG_DM_ETH) && defined(CONFIG_CLK)
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001063 unsigned long macb_hz = macb->pclk_rate;
1064#else
Bo Shen6f7d7d92013-04-24 15:59:28 +08001065 unsigned long macb_hz = get_macb_pclk_rate(id);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001066#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +08001067
1068 if (macb_hz < 20000000)
1069 config = MACB_BF(CLK, MACB_CLK_DIV8);
1070 else if (macb_hz < 40000000)
1071 config = MACB_BF(CLK, MACB_CLK_DIV16);
1072 else if (macb_hz < 80000000)
1073 config = MACB_BF(CLK, MACB_CLK_DIV32);
1074 else
1075 config = MACB_BF(CLK, MACB_CLK_DIV64);
1076
1077 return config;
1078}
1079
1080static u32 gem_mdc_clk_div(int id, struct macb_device *macb)
1081{
1082 u32 config;
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001083
Wenyou Yang19449362017-02-14 16:24:40 +08001084#if defined(CONFIG_DM_ETH) && defined(CONFIG_CLK)
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001085 unsigned long macb_hz = macb->pclk_rate;
1086#else
Bo Shen6f7d7d92013-04-24 15:59:28 +08001087 unsigned long macb_hz = get_macb_pclk_rate(id);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001088#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +08001089
1090 if (macb_hz < 20000000)
1091 config = GEM_BF(CLK, GEM_CLK_DIV8);
1092 else if (macb_hz < 40000000)
1093 config = GEM_BF(CLK, GEM_CLK_DIV16);
1094 else if (macb_hz < 80000000)
1095 config = GEM_BF(CLK, GEM_CLK_DIV32);
1096 else if (macb_hz < 120000000)
1097 config = GEM_BF(CLK, GEM_CLK_DIV48);
1098 else if (macb_hz < 160000000)
1099 config = GEM_BF(CLK, GEM_CLK_DIV64);
Ramon Friedb1b9b4f2019-07-16 22:04:32 +03001100 else if (macb_hz < 240000000)
Bo Shen6f7d7d92013-04-24 15:59:28 +08001101 config = GEM_BF(CLK, GEM_CLK_DIV96);
Ramon Friedb1b9b4f2019-07-16 22:04:32 +03001102 else if (macb_hz < 320000000)
1103 config = GEM_BF(CLK, GEM_CLK_DIV128);
1104 else
1105 config = GEM_BF(CLK, GEM_CLK_DIV224);
Bo Shen6f7d7d92013-04-24 15:59:28 +08001106
1107 return config;
1108}
1109
Bo Shen0e6624a2013-09-18 15:07:44 +08001110/*
1111 * Get the DMA bus width field of the network configuration register that we
1112 * should program. We find the width from decoding the design configuration
1113 * register to find the maximum supported data bus width.
1114 */
1115static u32 macb_dbw(struct macb_device *macb)
1116{
1117 switch (GEM_BFEXT(DBWDEF, gem_readl(macb, DCFG1))) {
1118 case 4:
1119 return GEM_BF(DBW, GEM_DBW128);
1120 case 2:
1121 return GEM_BF(DBW, GEM_DBW64);
1122 case 1:
1123 default:
1124 return GEM_BF(DBW, GEM_DBW32);
1125 }
Simon Glass5ad27512016-05-05 07:28:09 -06001126}
1127
1128static void _macb_eth_initialize(struct macb_device *macb)
1129{
1130 int id = 0; /* This is not used by functions we call */
1131 u32 ncfgr;
1132
Ramon Fried377d19d2019-07-14 18:25:14 +03001133 if (macb_is_gem(macb))
1134 macb->rx_buffer_size = GEM_RX_BUFFER_SIZE;
1135 else
1136 macb->rx_buffer_size = MACB_RX_BUFFER_SIZE;
1137
Simon Glass5ad27512016-05-05 07:28:09 -06001138 /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */
Ramon Fried377d19d2019-07-14 18:25:14 +03001139 macb->rx_buffer = dma_alloc_coherent(macb->rx_buffer_size *
1140 MACB_RX_RING_SIZE,
Simon Glass5ad27512016-05-05 07:28:09 -06001141 &macb->rx_buffer_dma);
1142 macb->rx_ring = dma_alloc_coherent(MACB_RX_DMA_DESC_SIZE,
1143 &macb->rx_ring_dma);
1144 macb->tx_ring = dma_alloc_coherent(MACB_TX_DMA_DESC_SIZE,
1145 &macb->tx_ring_dma);
1146 macb->dummy_desc = dma_alloc_coherent(MACB_TX_DUMMY_DMA_DESC_SIZE,
1147 &macb->dummy_desc_dma);
1148
1149 /*
1150 * Do some basic initialization so that we at least can talk
1151 * to the PHY
1152 */
1153 if (macb_is_gem(macb)) {
1154 ncfgr = gem_mdc_clk_div(id, macb);
1155 ncfgr |= macb_dbw(macb);
1156 } else {
1157 ncfgr = macb_mdc_clk_div(id, macb);
1158 }
1159
1160 macb_writel(macb, NCFGR, ncfgr);
1161}
1162
Simon Glass75c5d182016-05-05 07:28:11 -06001163#ifndef CONFIG_DM_ETH
Simon Glass5ad27512016-05-05 07:28:09 -06001164static int macb_send(struct eth_device *netdev, void *packet, int length)
1165{
1166 struct macb_device *macb = to_macb(netdev);
1167
1168 return _macb_send(macb, netdev->name, packet, length);
Bo Shen0e6624a2013-09-18 15:07:44 +08001169}
1170
Simon Glass5ad27512016-05-05 07:28:09 -06001171static int macb_recv(struct eth_device *netdev)
1172{
1173 struct macb_device *macb = to_macb(netdev);
1174 uchar *packet;
1175 int length;
1176
1177 macb->wrapped = false;
1178 for (;;) {
1179 macb->next_rx_tail = macb->rx_tail;
1180 length = _macb_recv(macb, &packet);
1181 if (length >= 0) {
1182 net_process_received_packet(packet, length);
1183 reclaim_rx_buffers(macb, macb->next_rx_tail);
Heinrich Schuchardt6c4aae92018-03-18 11:32:53 +01001184 } else {
Simon Glass5ad27512016-05-05 07:28:09 -06001185 return length;
1186 }
1187 }
1188}
1189
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001190static int macb_init(struct eth_device *netdev, struct bd_info *bd)
Simon Glass5ad27512016-05-05 07:28:09 -06001191{
1192 struct macb_device *macb = to_macb(netdev);
1193
1194 return _macb_init(macb, netdev->name);
1195}
1196
1197static void macb_halt(struct eth_device *netdev)
1198{
1199 struct macb_device *macb = to_macb(netdev);
1200
1201 return _macb_halt(macb);
1202}
1203
1204static int macb_write_hwaddr(struct eth_device *netdev)
1205{
1206 struct macb_device *macb = to_macb(netdev);
1207
1208 return _macb_write_hwaddr(macb, netdev->enetaddr);
1209}
1210
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001211int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
1212{
1213 struct macb_device *macb;
1214 struct eth_device *netdev;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001215
1216 macb = malloc(sizeof(struct macb_device));
1217 if (!macb) {
1218 printf("Error: Failed to allocate memory for MACB%d\n", id);
1219 return -1;
1220 }
1221 memset(macb, 0, sizeof(struct macb_device));
1222
1223 netdev = &macb->netdev;
1224
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001225 macb->regs = regs;
1226 macb->phy_addr = phy_addr;
1227
Bo Shen6f7d7d92013-04-24 15:59:28 +08001228 if (macb_is_gem(macb))
1229 sprintf(netdev->name, "gmac%d", id);
1230 else
1231 sprintf(netdev->name, "macb%d", id);
1232
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001233 netdev->init = macb_init;
1234 netdev->halt = macb_halt;
1235 netdev->send = macb_send;
1236 netdev->recv = macb_recv;
Ben Warren33f84312010-06-01 11:55:42 -07001237 netdev->write_hwaddr = macb_write_hwaddr;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001238
Simon Glass5ad27512016-05-05 07:28:09 -06001239 _macb_eth_initialize(macb);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001240
1241 eth_register(netdev);
1242
Bo Shen7d91deb2013-04-24 15:59:27 +08001243#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
Joe Hershberger1fbcbed2016-08-08 11:28:38 -05001244 int retval;
1245 struct mii_dev *mdiodev = mdio_alloc();
1246 if (!mdiodev)
1247 return -ENOMEM;
1248 strncpy(mdiodev->name, netdev->name, MDIO_NAME_LEN);
1249 mdiodev->read = macb_miiphy_read;
1250 mdiodev->write = macb_miiphy_write;
1251
1252 retval = mdio_register(mdiodev);
1253 if (retval < 0)
1254 return retval;
Bo Shen7d91deb2013-04-24 15:59:27 +08001255 macb->bus = miiphy_get_dev_by_name(netdev->name);
Semih Hazar790088e2009-12-17 15:07:15 +02001256#endif
Simon Glass75c5d182016-05-05 07:28:11 -06001257 return 0;
1258}
1259#endif /* !CONFIG_DM_ETH */
1260
1261#ifdef CONFIG_DM_ETH
1262
1263static int macb_start(struct udevice *dev)
1264{
Wenyou Yang7b811852016-05-17 13:11:35 +08001265 return _macb_init(dev, dev->name);
Simon Glass75c5d182016-05-05 07:28:11 -06001266}
1267
1268static int macb_send(struct udevice *dev, void *packet, int length)
1269{
1270 struct macb_device *macb = dev_get_priv(dev);
1271
1272 return _macb_send(macb, dev->name, packet, length);
1273}
1274
1275static int macb_recv(struct udevice *dev, int flags, uchar **packetp)
1276{
1277 struct macb_device *macb = dev_get_priv(dev);
1278
1279 macb->next_rx_tail = macb->rx_tail;
1280 macb->wrapped = false;
1281
1282 return _macb_recv(macb, packetp);
1283}
1284
1285static int macb_free_pkt(struct udevice *dev, uchar *packet, int length)
1286{
1287 struct macb_device *macb = dev_get_priv(dev);
1288
1289 reclaim_rx_buffers(macb, macb->next_rx_tail);
1290
1291 return 0;
1292}
1293
1294static void macb_stop(struct udevice *dev)
1295{
1296 struct macb_device *macb = dev_get_priv(dev);
1297
1298 _macb_halt(macb);
1299}
1300
1301static int macb_write_hwaddr(struct udevice *dev)
1302{
Simon Glassfa20e932020-12-03 16:55:20 -07001303 struct eth_pdata *plat = dev_get_plat(dev);
Simon Glass75c5d182016-05-05 07:28:11 -06001304 struct macb_device *macb = dev_get_priv(dev);
1305
1306 return _macb_write_hwaddr(macb, plat->enetaddr);
1307}
1308
1309static const struct eth_ops macb_eth_ops = {
1310 .start = macb_start,
1311 .send = macb_send,
1312 .recv = macb_recv,
1313 .stop = macb_stop,
1314 .free_pkt = macb_free_pkt,
1315 .write_hwaddr = macb_write_hwaddr,
1316};
1317
Wenyou Yang19449362017-02-14 16:24:40 +08001318#ifdef CONFIG_CLK
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001319static int macb_enable_clk(struct udevice *dev)
1320{
1321 struct macb_device *macb = dev_get_priv(dev);
1322 struct clk clk;
1323 ulong clk_rate;
1324 int ret;
1325
1326 ret = clk_get_by_index(dev, 0, &clk);
1327 if (ret)
1328 return -EINVAL;
1329
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001330 /*
Anup Patel51b51f82019-02-25 08:14:36 +00001331 * If clock driver didn't support enable or disable then
1332 * we get -ENOSYS from clk_enable(). To handle this, we
1333 * don't fail for ret == -ENOSYS.
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001334 */
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001335 ret = clk_enable(&clk);
Anup Patel51b51f82019-02-25 08:14:36 +00001336 if (ret && ret != -ENOSYS)
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001337 return ret;
1338
1339 clk_rate = clk_get_rate(&clk);
1340 if (!clk_rate)
1341 return -EINVAL;
1342
1343 macb->pclk_rate = clk_rate;
1344
1345 return 0;
1346}
Wenyou Yang19449362017-02-14 16:24:40 +08001347#endif
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001348
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001349static const struct macb_usrio_cfg macb_default_usrio = {
1350 .mii = MACB_BIT(MII),
1351 .rmii = MACB_BIT(RMII),
1352 .rgmii = GEM_BIT(RGMII),
1353 .clken = MACB_BIT(CLKEN),
1354};
1355
Ramon Fried834040c2019-07-16 22:04:35 +03001356static const struct macb_config default_gem_config = {
1357 .dma_burst_length = 16,
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301358 .hw_dma_cap = HW_DMA_CAP_32B,
Anup Patel88799a62019-07-24 04:09:32 +00001359 .clk_init = NULL,
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001360 .usrio = &macb_default_usrio,
Ramon Fried834040c2019-07-16 22:04:35 +03001361};
1362
Simon Glass75c5d182016-05-05 07:28:11 -06001363static int macb_eth_probe(struct udevice *dev)
1364{
Simon Glassfa20e932020-12-03 16:55:20 -07001365 struct eth_pdata *pdata = dev_get_plat(dev);
Simon Glass75c5d182016-05-05 07:28:11 -06001366 struct macb_device *macb = dev_get_priv(dev);
Padmarao Begari34394ba2021-01-15 08:20:37 +05301367 struct ofnode_phandle_args phandle_args;
Wenyou Yang7b811852016-05-17 13:11:35 +08001368 const char *phy_mode;
Anup Patel88799a62019-07-24 04:09:32 +00001369 int ret;
Wenyou Yang7b811852016-05-17 13:11:35 +08001370
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301371 phy_mode = dev_read_prop(dev, "phy-mode", NULL);
1372
Wenyou Yang7b811852016-05-17 13:11:35 +08001373 if (phy_mode)
1374 macb->phy_interface = phy_get_interface_by_name(phy_mode);
1375 if (macb->phy_interface == -1) {
1376 debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
1377 return -EINVAL;
1378 }
Wenyou Yang7b811852016-05-17 13:11:35 +08001379
Padmarao Begari34394ba2021-01-15 08:20:37 +05301380 /* Read phyaddr from DT */
1381 if (!dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
1382 &phandle_args))
1383 macb->phy_addr = ofnode_read_u32_default(phandle_args.node,
1384 "reg", -1);
1385
Simon Glass75c5d182016-05-05 07:28:11 -06001386 macb->regs = (void *)pdata->iobase;
1387
Anup Patela1818b12019-07-24 04:09:37 +00001388 macb->is_big_endian = (cpu_to_be32(0x12345678) == 0x12345678);
1389
Anup Patel88799a62019-07-24 04:09:32 +00001390 macb->config = (struct macb_config *)dev_get_driver_data(dev);
1391 if (!macb->config)
1392 macb->config = &default_gem_config;
Ramon Fried834040c2019-07-16 22:04:35 +03001393
Wenyou Yang19449362017-02-14 16:24:40 +08001394#ifdef CONFIG_CLK
Wenyou Yang44835ea2017-04-14 14:36:04 +08001395 ret = macb_enable_clk(dev);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001396 if (ret)
1397 return ret;
Wenyou Yang19449362017-02-14 16:24:40 +08001398#endif
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001399
Simon Glass75c5d182016-05-05 07:28:11 -06001400 _macb_eth_initialize(macb);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001401
Simon Glass75c5d182016-05-05 07:28:11 -06001402#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
Wenyou Yang44835ea2017-04-14 14:36:04 +08001403 macb->bus = mdio_alloc();
1404 if (!macb->bus)
Joe Hershberger1fbcbed2016-08-08 11:28:38 -05001405 return -ENOMEM;
Wenyou Yang44835ea2017-04-14 14:36:04 +08001406 strncpy(macb->bus->name, dev->name, MDIO_NAME_LEN);
1407 macb->bus->read = macb_miiphy_read;
1408 macb->bus->write = macb_miiphy_write;
Joe Hershberger1fbcbed2016-08-08 11:28:38 -05001409
Wenyou Yang44835ea2017-04-14 14:36:04 +08001410 ret = mdio_register(macb->bus);
1411 if (ret < 0)
1412 return ret;
Simon Glass75c5d182016-05-05 07:28:11 -06001413 macb->bus = miiphy_get_dev_by_name(dev->name);
1414#endif
Wenyou Yang44835ea2017-04-14 14:36:04 +08001415
1416 return 0;
1417}
1418
1419static int macb_eth_remove(struct udevice *dev)
1420{
1421 struct macb_device *macb = dev_get_priv(dev);
1422
1423#ifdef CONFIG_PHYLIB
1424 free(macb->phydev);
1425#endif
1426 mdio_unregister(macb->bus);
1427 mdio_free(macb->bus);
Simon Glass75c5d182016-05-05 07:28:11 -06001428
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001429 return 0;
1430}
1431
1432/**
Simon Glassaad29ae2020-12-03 16:55:21 -07001433 * macb_late_eth_of_to_plat
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001434 * @dev: udevice struct
1435 * Returns 0 when operation success and negative errno number
1436 * when operation failed.
1437 */
Simon Glassaad29ae2020-12-03 16:55:21 -07001438int __weak macb_late_eth_of_to_plat(struct udevice *dev)
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001439{
Simon Glass75c5d182016-05-05 07:28:11 -06001440 return 0;
1441}
1442
Simon Glassaad29ae2020-12-03 16:55:21 -07001443static int macb_eth_of_to_plat(struct udevice *dev)
Simon Glass75c5d182016-05-05 07:28:11 -06001444{
Simon Glassfa20e932020-12-03 16:55:20 -07001445 struct eth_pdata *pdata = dev_get_plat(dev);
Simon Glass75c5d182016-05-05 07:28:11 -06001446
Ramon Friedbf15d2f2018-12-27 19:58:42 +02001447 pdata->iobase = (phys_addr_t)dev_remap_addr(dev);
1448 if (!pdata->iobase)
1449 return -EINVAL;
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001450
Simon Glassaad29ae2020-12-03 16:55:21 -07001451 return macb_late_eth_of_to_plat(dev);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001452}
1453
Claudiu Beznea01ca4eb2021-01-19 13:26:46 +02001454static const struct macb_usrio_cfg sama7g5_usrio = {
1455 .mii = 0,
1456 .rmii = 1,
1457 .rgmii = 2,
1458 .clken = BIT(2),
1459};
1460
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301461static const struct macb_config microchip_config = {
1462 .dma_burst_length = 16,
1463 .hw_dma_cap = HW_DMA_CAP_64B,
1464 .clk_init = NULL,
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001465 .usrio = &macb_default_usrio,
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301466};
1467
Ramon Fried834040c2019-07-16 22:04:35 +03001468static const struct macb_config sama5d4_config = {
1469 .dma_burst_length = 4,
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301470 .hw_dma_cap = HW_DMA_CAP_32B,
Anup Patel88799a62019-07-24 04:09:32 +00001471 .clk_init = NULL,
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001472 .usrio = &macb_default_usrio,
Anup Patel88799a62019-07-24 04:09:32 +00001473};
1474
1475static const struct macb_config sifive_config = {
1476 .dma_burst_length = 16,
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301477 .hw_dma_cap = HW_DMA_CAP_32B,
Anup Patel88799a62019-07-24 04:09:32 +00001478 .clk_init = macb_sifive_clk_init,
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001479 .usrio = &macb_default_usrio,
Ramon Fried834040c2019-07-16 22:04:35 +03001480};
1481
Claudiu Beznea01ca4eb2021-01-19 13:26:46 +02001482static const struct macb_config sama7g5_gmac_config = {
1483 .dma_burst_length = 16,
1484 .hw_dma_cap = HW_DMA_CAP_32B,
1485 .clk_init = macb_sama7g5_clk_init,
1486 .usrio = &sama7g5_usrio,
1487};
1488
Claudiu Beznea2acf5f82021-01-19 13:26:47 +02001489static const struct macb_config sama7g5_emac_config = {
1490 .caps = MACB_CAPS_USRIO_HAS_CLKEN,
1491 .dma_burst_length = 16,
1492 .hw_dma_cap = HW_DMA_CAP_32B,
1493 .usrio = &sama7g5_usrio,
1494};
1495
Simon Glass75c5d182016-05-05 07:28:11 -06001496static const struct udevice_id macb_eth_ids[] = {
1497 { .compatible = "cdns,macb" },
Wenyou Yang8f155402017-04-14 14:36:05 +08001498 { .compatible = "cdns,at91sam9260-macb" },
Nicolas Ferre9115f572019-09-27 13:08:32 +00001499 { .compatible = "cdns,sam9x60-macb" },
Claudiu Beznea01ca4eb2021-01-19 13:26:46 +02001500 { .compatible = "cdns,sama7g5-gem",
1501 .data = (ulong)&sama7g5_gmac_config },
Claudiu Beznea2acf5f82021-01-19 13:26:47 +02001502 { .compatible = "cdns,sama7g5-emac",
1503 .data = (ulong)&sama7g5_emac_config },
Wenyou Yang8f155402017-04-14 14:36:05 +08001504 { .compatible = "atmel,sama5d2-gem" },
1505 { .compatible = "atmel,sama5d3-gem" },
Ramon Fried834040c2019-07-16 22:04:35 +03001506 { .compatible = "atmel,sama5d4-gem", .data = (ulong)&sama5d4_config },
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001507 { .compatible = "cdns,zynq-gem" },
Anup Patel88799a62019-07-24 04:09:32 +00001508 { .compatible = "sifive,fu540-c000-gem",
1509 .data = (ulong)&sifive_config },
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301510 { .compatible = "microchip,mpfs-mss-gem",
1511 .data = (ulong)&microchip_config },
Simon Glass75c5d182016-05-05 07:28:11 -06001512 { }
1513};
1514
1515U_BOOT_DRIVER(eth_macb) = {
1516 .name = "eth_macb",
1517 .id = UCLASS_ETH,
1518 .of_match = macb_eth_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001519 .of_to_plat = macb_eth_of_to_plat,
Simon Glass75c5d182016-05-05 07:28:11 -06001520 .probe = macb_eth_probe,
Wenyou Yang44835ea2017-04-14 14:36:04 +08001521 .remove = macb_eth_remove,
Simon Glass75c5d182016-05-05 07:28:11 -06001522 .ops = &macb_eth_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001523 .priv_auto = sizeof(struct macb_device),
Simon Glass71fa5b42020-12-03 16:55:18 -07001524 .plat_auto = sizeof(struct eth_pdata),
Simon Glass75c5d182016-05-05 07:28:11 -06001525};
1526#endif
1527
Jon Loeligerb1d408a2007-07-09 17:30:01 -05001528#endif