blob: e02a57b4114c312b3abc805d17839af4a8ec73b7 [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{
Anup Patel88799a62019-07-24 04:09:32 +0000577 void *gemgxl_regs;
578
Bin Meng81ce6372021-09-12 11:15:14 +0800579 gemgxl_regs = dev_read_addr_index_ptr(dev, 1);
Anup Patel88799a62019-07-24 04:09:32 +0000580 if (!gemgxl_regs)
581 return -ENODEV;
582
583 /*
584 * SiFive GEMGXL TX clock operation mode:
585 *
586 * 0 = GMII mode. Use 125 MHz gemgxlclk from PRCI in TX logic
587 * and output clock on GMII output signal GTX_CLK
588 * 1 = MII mode. Use MII input signal TX_CLK in TX logic
589 */
590 writel(rate != 125000000, gemgxl_regs);
591 return 0;
592}
593
Claudiu Beznea01ca4eb2021-01-19 13:26:46 +0200594static int macb_sama7g5_clk_init(struct udevice *dev, ulong rate)
595{
596 struct clk clk;
597 int ret;
598
599 ret = clk_get_by_name(dev, "tx_clk", &clk);
600 if (ret)
601 return ret;
602
603 /*
604 * This is for using GCK. Clock rate is addressed via assigned-clock
605 * property, so only clock enable is needed here. The switching to
606 * proper clock rate depending on link speed is managed by IP logic.
607 */
608 return clk_enable(&clk);
609}
610
Bin Mengcf821322019-05-22 00:09:45 -0700611int __weak macb_linkspd_cb(struct udevice *dev, unsigned int speed)
612{
Bin Meng12766ca2019-05-22 00:09:46 -0700613#ifdef CONFIG_CLK
Anup Patel88799a62019-07-24 04:09:32 +0000614 struct macb_device *macb = dev_get_priv(dev);
Bin Meng12766ca2019-05-22 00:09:46 -0700615 struct clk tx_clk;
616 ulong rate;
617 int ret;
618
Bin Meng12766ca2019-05-22 00:09:46 -0700619 switch (speed) {
620 case _10BASET:
621 rate = 2500000; /* 2.5 MHz */
622 break;
623 case _100BASET:
624 rate = 25000000; /* 25 MHz */
625 break;
626 case _1000BASET:
627 rate = 125000000; /* 125 MHz */
628 break;
629 default:
630 /* does not change anything */
631 return 0;
632 }
633
Anup Patel88799a62019-07-24 04:09:32 +0000634 if (macb->config->clk_init)
635 return macb->config->clk_init(dev, rate);
636
637 /*
638 * "tx_clk" is an optional clock source for MACB.
639 * Ignore if it does not exist in DT.
640 */
641 ret = clk_get_by_name(dev, "tx_clk", &tx_clk);
642 if (ret)
643 return 0;
644
Bin Meng12766ca2019-05-22 00:09:46 -0700645 if (tx_clk.dev) {
646 ret = clk_set_rate(&tx_clk, rate);
Claudiu Bezneae2888dc2021-01-19 13:26:45 +0200647 if (ret < 0)
Bin Meng12766ca2019-05-22 00:09:46 -0700648 return ret;
649 }
650#endif
651
Bin Mengcf821322019-05-22 00:09:45 -0700652 return 0;
653}
654#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700655int __weak macb_linkspd_cb(void *regs, unsigned int speed)
656{
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100657 return 0;
658}
Bin Mengcf821322019-05-22 00:09:45 -0700659#endif
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100660
Wenyou Yang7b811852016-05-17 13:11:35 +0800661#ifdef CONFIG_DM_ETH
662static int macb_phy_init(struct udevice *dev, const char *name)
663#else
Simon Glass5ad27512016-05-05 07:28:09 -0600664static int macb_phy_init(struct macb_device *macb, const char *name)
Wenyou Yang7b811852016-05-17 13:11:35 +0800665#endif
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200666{
Wenyou Yang7b811852016-05-17 13:11:35 +0800667#ifdef CONFIG_DM_ETH
668 struct macb_device *macb = dev_get_priv(dev);
669#endif
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200670 u32 ncfgr;
671 u16 phy_id, status, adv, lpa;
672 int media, speed, duplex;
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700673 int ret;
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200674 int i;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100675
Simon Glass5ad27512016-05-05 07:28:09 -0600676 arch_get_mdio_control(name);
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100677 /* Auto-detect phy_addr */
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700678 ret = macb_phy_find(macb, name);
679 if (ret)
680 return ret;
Gunnar Rangoy6dd74f32009-01-23 12:56:31 +0100681
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200682 /* Check if the PHY is up to snuff... */
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200683 phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200684 if (phy_id == 0xffff) {
Simon Glass5ad27512016-05-05 07:28:09 -0600685 printf("%s: No PHY present\n", name);
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700686 return -ENODEV;
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200687 }
688
Bo Shen7d91deb2013-04-24 15:59:27 +0800689#ifdef CONFIG_PHYLIB
Wenyou Yang7b811852016-05-17 13:11:35 +0800690#ifdef CONFIG_DM_ETH
Wenyou Yang44835ea2017-04-14 14:36:04 +0800691 macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev,
Wenyou Yang7b811852016-05-17 13:11:35 +0800692 macb->phy_interface);
693#else
Bo Shene04fe552013-08-19 10:35:47 +0800694 /* need to consider other phy interface mode */
Wenyou Yang44835ea2017-04-14 14:36:04 +0800695 macb->phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev,
Bo Shene04fe552013-08-19 10:35:47 +0800696 PHY_INTERFACE_MODE_RGMII);
Wenyou Yang7b811852016-05-17 13:11:35 +0800697#endif
Wenyou Yang44835ea2017-04-14 14:36:04 +0800698 if (!macb->phydev) {
Bo Shene04fe552013-08-19 10:35:47 +0800699 printf("phy_connect failed\n");
700 return -ENODEV;
701 }
702
Wenyou Yang44835ea2017-04-14 14:36:04 +0800703 phy_config(macb->phydev);
Bo Shen7d91deb2013-04-24 15:59:27 +0800704#endif
705
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200706 status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100707 if (!(status & BMSR_LSTATUS)) {
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200708 /* Try to re-negotiate if we don't have link already. */
Simon Glass5ad27512016-05-05 07:28:09 -0600709 macb_phy_reset(macb, name);
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200710
Andreas Bießmann1e868122014-05-26 22:55:18 +0200711 for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200712 status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
Stefan Roese40291802019-03-27 11:20:19 +0100713 if (status & BMSR_LSTATUS) {
714 /*
715 * Delay a bit after the link is established,
716 * so that the next xfer does not fail
717 */
718 mdelay(10);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100719 break;
Stefan Roese40291802019-03-27 11:20:19 +0100720 }
Haavard Skinnemoenb3ad7722007-05-02 13:31:53 +0200721 udelay(100);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100722 }
723 }
724
725 if (!(status & BMSR_LSTATUS)) {
726 printf("%s: link down (status: 0x%04x)\n",
Simon Glass5ad27512016-05-05 07:28:09 -0600727 name, status);
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700728 return -ENETDOWN;
Bo Shen6f7d7d92013-04-24 15:59:28 +0800729 }
730
Gregory CLEMENTf1a1e582015-12-16 14:50:34 +0100731 /* First check for GMAC and that it is GiB capable */
732 if (gem_is_gigabit_capable(macb)) {
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200733 lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100734
Radu Pirea1676dfb2019-06-07 14:18:36 +0300735 if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
736 LPA_1000XHALF)) {
737 duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ?
738 1 : 0);
Andreas Bießmannd43a89a2014-09-18 23:46:48 +0200739
740 printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
Simon Glass5ad27512016-05-05 07:28:09 -0600741 name,
Bo Shen6f7d7d92013-04-24 15:59:28 +0800742 duplex ? "full" : "half",
743 lpa);
744
745 ncfgr = macb_readl(macb, NCFGR);
Andreas Bießmannd43a89a2014-09-18 23:46:48 +0200746 ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
747 ncfgr |= GEM_BIT(GBE);
748
Bo Shen6f7d7d92013-04-24 15:59:28 +0800749 if (duplex)
750 ncfgr |= MACB_BIT(FD);
Andreas Bießmannd43a89a2014-09-18 23:46:48 +0200751
Bo Shen6f7d7d92013-04-24 15:59:28 +0800752 macb_writel(macb, NCFGR, ncfgr);
753
Bin Mengcf821322019-05-22 00:09:45 -0700754#ifdef CONFIG_DM_ETH
755 ret = macb_linkspd_cb(dev, _1000BASET);
756#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700757 ret = macb_linkspd_cb(macb->regs, _1000BASET);
Bin Mengcf821322019-05-22 00:09:45 -0700758#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700759 if (ret)
760 return ret;
761
762 return 0;
Bo Shen6f7d7d92013-04-24 15:59:28 +0800763 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100764 }
Bo Shen6f7d7d92013-04-24 15:59:28 +0800765
766 /* fall back for EMAC checking */
Josef Holzmayr9fe18782019-10-02 21:22:51 +0200767 adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE);
768 lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA);
Bo Shen6f7d7d92013-04-24 15:59:28 +0800769 media = mii_nway_result(lpa & adv);
770 speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
771 ? 1 : 0);
772 duplex = (media & ADVERTISE_FULL) ? 1 : 0;
773 printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
Simon Glass5ad27512016-05-05 07:28:09 -0600774 name,
Bo Shen6f7d7d92013-04-24 15:59:28 +0800775 speed ? "100" : "10",
776 duplex ? "full" : "half",
777 lpa);
778
779 ncfgr = macb_readl(macb, NCFGR);
Bo Shenfe19ef32015-03-04 13:35:16 +0800780 ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE));
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700781 if (speed) {
Bo Shen6f7d7d92013-04-24 15:59:28 +0800782 ncfgr |= MACB_BIT(SPD);
Bin Mengcf821322019-05-22 00:09:45 -0700783#ifdef CONFIG_DM_ETH
784 ret = macb_linkspd_cb(dev, _100BASET);
785#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700786 ret = macb_linkspd_cb(macb->regs, _100BASET);
Bin Mengcf821322019-05-22 00:09:45 -0700787#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700788 } else {
Bin Mengcf821322019-05-22 00:09:45 -0700789#ifdef CONFIG_DM_ETH
790 ret = macb_linkspd_cb(dev, _10BASET);
791#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700792 ret = macb_linkspd_cb(macb->regs, _10BASET);
Bin Mengcf821322019-05-22 00:09:45 -0700793#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700794 }
795
796 if (ret)
797 return ret;
798
Bo Shen6f7d7d92013-04-24 15:59:28 +0800799 if (duplex)
800 ncfgr |= MACB_BIT(FD);
801 macb_writel(macb, NCFGR, ncfgr);
802
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700803 return 0;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100804}
805
Wu, Josh012d68d2015-06-03 16:45:44 +0800806static int gmac_init_multi_queues(struct macb_device *macb)
807{
808 int i, num_queues = 1;
809 u32 queue_mask;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530810 unsigned long paddr;
Wu, Josh012d68d2015-06-03 16:45:44 +0800811
812 /* bit 0 is never set but queue 0 always exists */
813 queue_mask = gem_readl(macb, DCFG6) & 0xff;
814 queue_mask |= 0x1;
815
816 for (i = 1; i < MACB_MAX_QUEUES; i++)
817 if (queue_mask & (1 << i))
818 num_queues++;
819
Ramon Fried6402fb192019-07-16 22:04:33 +0300820 macb->dummy_desc->ctrl = MACB_BIT(TX_USED);
Wu, Josh012d68d2015-06-03 16:45:44 +0800821 macb->dummy_desc->addr = 0;
822 flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma +
Heiko Schocher8353f9d2016-08-29 07:46:11 +0200823 ALIGN(MACB_TX_DUMMY_DMA_DESC_SIZE, PKTALIGN));
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530824 paddr = macb->dummy_desc_dma;
Wu, Josh012d68d2015-06-03 16:45:44 +0800825
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530826 for (i = 1; i < num_queues; i++) {
827 gem_writel_queue_TBQP(macb, lower_32_bits(paddr), i - 1);
828 gem_writel_queue_RBQP(macb, lower_32_bits(paddr), i - 1);
829 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
830 gem_writel_queue_TBQPH(macb, upper_32_bits(paddr),
831 i - 1);
832 gem_writel_queue_RBQPH(macb, upper_32_bits(paddr),
833 i - 1);
834 }
835 }
Wu, Josh012d68d2015-06-03 16:45:44 +0800836 return 0;
837}
838
Ramon Friedb40501f2019-07-16 22:04:36 +0300839static void gmac_configure_dma(struct macb_device *macb)
840{
841 u32 buffer_size;
842 u32 dmacfg;
843
Ramon Fried377d19d2019-07-14 18:25:14 +0300844 buffer_size = macb->rx_buffer_size / RX_BUFFER_MULTIPLE;
Ramon Friedb40501f2019-07-16 22:04:36 +0300845 dmacfg = gem_readl(macb, DMACFG) & ~GEM_BF(RXBS, -1L);
846 dmacfg |= GEM_BF(RXBS, buffer_size);
847
Anup Patel88799a62019-07-24 04:09:32 +0000848 if (macb->config->dma_burst_length)
849 dmacfg = GEM_BFINS(FBLDO,
850 macb->config->dma_burst_length, dmacfg);
Ramon Friedb40501f2019-07-16 22:04:36 +0300851
852 dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
853 dmacfg &= ~GEM_BIT(ENDIA_PKT);
854
Anup Patela1818b12019-07-24 04:09:37 +0000855 if (macb->is_big_endian)
Ramon Friedb40501f2019-07-16 22:04:36 +0300856 dmacfg |= GEM_BIT(ENDIA_DESC); /* CPU in big endian */
Anup Patela1818b12019-07-24 04:09:37 +0000857 else
858 dmacfg &= ~GEM_BIT(ENDIA_DESC);
Ramon Friedb40501f2019-07-16 22:04:36 +0300859
860 dmacfg &= ~GEM_BIT(ADDR64);
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530861 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
862 dmacfg |= GEM_BIT(ADDR64);
863
Ramon Friedb40501f2019-07-16 22:04:36 +0300864 gem_writel(macb, DMACFG, dmacfg);
865}
866
Wenyou Yang7b811852016-05-17 13:11:35 +0800867#ifdef CONFIG_DM_ETH
868static int _macb_init(struct udevice *dev, const char *name)
869#else
Simon Glass5ad27512016-05-05 07:28:09 -0600870static int _macb_init(struct macb_device *macb, const char *name)
Wenyou Yang7b811852016-05-17 13:11:35 +0800871#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100872{
Wenyou Yang7b811852016-05-17 13:11:35 +0800873#ifdef CONFIG_DM_ETH
874 struct macb_device *macb = dev_get_priv(dev);
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200875 unsigned int val = 0;
Wenyou Yang7b811852016-05-17 13:11:35 +0800876#endif
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100877 unsigned long paddr;
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700878 int ret;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100879 int i;
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530880 int count;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100881
882 /*
883 * macb_halt should have been called at some point before now,
884 * so we'll assume the controller is idle.
885 */
886
887 /* initialize DMA descriptors */
888 paddr = macb->rx_buffer_dma;
Andreas Bießmann1e868122014-05-26 22:55:18 +0200889 for (i = 0; i < MACB_RX_RING_SIZE; i++) {
890 if (i == (MACB_RX_RING_SIZE - 1))
Ramon Fried6402fb192019-07-16 22:04:33 +0300891 paddr |= MACB_BIT(RX_WRAP);
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530892 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
893 count = i * 2;
894 else
895 count = i;
896 macb->rx_ring[count].ctrl = 0;
897 macb_set_addr(macb, &macb->rx_ring[count], paddr);
Ramon Fried377d19d2019-07-14 18:25:14 +0300898 paddr += macb->rx_buffer_size;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100899 }
Wu, Josh18052402014-05-27 16:31:05 +0800900 macb_flush_ring_desc(macb, RX);
901 macb_flush_rx_buffer(macb);
902
Andreas Bießmann1e868122014-05-26 22:55:18 +0200903 for (i = 0; i < MACB_TX_RING_SIZE; i++) {
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530904 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
905 count = i * 2;
906 else
907 count = i;
908 macb_set_addr(macb, &macb->tx_ring[count], 0);
Andreas Bießmann1e868122014-05-26 22:55:18 +0200909 if (i == (MACB_TX_RING_SIZE - 1))
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530910 macb->tx_ring[count].ctrl = MACB_BIT(TX_USED) |
Ramon Fried6402fb192019-07-16 22:04:33 +0300911 MACB_BIT(TX_WRAP);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100912 else
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530913 macb->tx_ring[count].ctrl = MACB_BIT(TX_USED);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100914 }
Wu, Josh18052402014-05-27 16:31:05 +0800915 macb_flush_ring_desc(macb, TX);
916
Andreas Bießmann1e868122014-05-26 22:55:18 +0200917 macb->rx_tail = 0;
918 macb->tx_head = 0;
919 macb->tx_tail = 0;
Simon Glass5ad27512016-05-05 07:28:09 -0600920 macb->next_rx_tail = 0;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100921
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700922#ifdef CONFIG_MACB_ZYNQ
Michal Simekfc91bdb2020-03-26 15:01:29 +0100923 gem_writel(macb, DMACFG, MACB_ZYNQ_GEM_DMACR_INIT);
Wilson Lee41d6d1e2017-08-22 20:25:07 -0700924#endif
925
Padmarao Begari7a2c4962021-01-15 08:20:36 +0530926 macb_writel(macb, RBQP, lower_32_bits(macb->rx_ring_dma));
927 macb_writel(macb, TBQP, lower_32_bits(macb->tx_ring_dma));
928 if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
929 macb_writel(macb, RBQPH, upper_32_bits(macb->rx_ring_dma));
930 macb_writel(macb, TBQPH, upper_32_bits(macb->tx_ring_dma));
931 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100932
Bo Shen6f7d7d92013-04-24 15:59:28 +0800933 if (macb_is_gem(macb)) {
Ramon Friedb40501f2019-07-16 22:04:36 +0300934 /* Initialize DMA properties */
935 gmac_configure_dma(macb);
Wu, Josh012d68d2015-06-03 16:45:44 +0800936 /* Check the multi queue and initialize the queue for tx */
937 gmac_init_multi_queues(macb);
938
Bo Shen4660b332014-11-10 15:24:01 +0800939 /*
940 * When the GMAC IP with GE feature, this bit is used to
941 * select interface between RGMII and GMII.
942 * When the GMAC IP without GE feature, this bit is used
943 * to select interface between RMII and MII.
944 */
Wenyou Yang7b811852016-05-17 13:11:35 +0800945#ifdef CONFIG_DM_ETH
Claudiu Bezneaa81146b2021-01-19 13:26:48 +0200946 if (macb->phy_interface == PHY_INTERFACE_MODE_RGMII ||
947 macb->phy_interface == PHY_INTERFACE_MODE_RGMII_ID ||
948 macb->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID ||
949 macb->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID)
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200950 val = macb->config->usrio->rgmii;
951 else if (macb->phy_interface == PHY_INTERFACE_MODE_RMII)
952 val = macb->config->usrio->rmii;
953 else if (macb->phy_interface == PHY_INTERFACE_MODE_MII)
954 val = macb->config->usrio->mii;
955
956 if (macb->config->caps & MACB_CAPS_USRIO_HAS_CLKEN)
957 val |= macb->config->usrio->clken;
958
959 gem_writel(macb, USRIO, val);
Ramon Fried588a5b72019-07-16 22:04:34 +0300960
961 if (macb->phy_interface == PHY_INTERFACE_MODE_SGMII) {
962 unsigned int ncfgr = macb_readl(macb, NCFGR);
963
964 ncfgr |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
965 macb_writel(macb, NCFGR, ncfgr);
966 }
Wenyou Yang7b811852016-05-17 13:11:35 +0800967#else
Bo Shen4660b332014-11-10 15:24:01 +0800968#if defined(CONFIG_RGMII) || defined(CONFIG_RMII)
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200969 gem_writel(macb, USRIO, macb->config->usrio->rgmii);
Bo Shen6f7d7d92013-04-24 15:59:28 +0800970#else
Ramon Fried94e6bd82019-07-16 22:03:00 +0300971 gem_writel(macb, USRIO, 0);
Bo Shen6f7d7d92013-04-24 15:59:28 +0800972#endif
Wenyou Yang7b811852016-05-17 13:11:35 +0800973#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +0800974 } else {
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100975 /* choose RMII or MII mode. This depends on the board */
Wenyou Yang7b811852016-05-17 13:11:35 +0800976#ifdef CONFIG_DM_ETH
977#ifdef CONFIG_AT91FAMILY
978 if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) {
979 macb_writel(macb, USRIO,
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200980 macb->config->usrio->rmii |
981 macb->config->usrio->clken);
Wenyou Yang7b811852016-05-17 13:11:35 +0800982 } else {
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200983 macb_writel(macb, USRIO, macb->config->usrio->clken);
Wenyou Yang7b811852016-05-17 13:11:35 +0800984 }
985#else
986 if (macb->phy_interface == PHY_INTERFACE_MODE_RMII)
987 macb_writel(macb, USRIO, 0);
988 else
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200989 macb_writel(macb, USRIO, macb->config->usrio->mii);
Wenyou Yang7b811852016-05-17 13:11:35 +0800990#endif
991#else
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100992#ifdef CONFIG_RMII
Bo Shencc29ce52013-04-24 15:59:26 +0800993#ifdef CONFIG_AT91FAMILY
Claudiu Bezneadc17aec2021-01-19 13:26:44 +0200994 macb_writel(macb, USRIO, macb->config->usrio->rmii |
995 macb->config->usrio->clken);
Stelian Pop87a82542008-01-03 21:15:56 +0000996#else
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +0100997 macb_writel(macb, USRIO, 0);
Stelian Pop87a82542008-01-03 21:15:56 +0000998#endif
999#else
Bo Shencc29ce52013-04-24 15:59:26 +08001000#ifdef CONFIG_AT91FAMILY
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001001 macb_writel(macb, USRIO, macb->config->usrio->clken);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001002#else
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001003 macb_writel(macb, USRIO, macb->config->usrio->mii);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001004#endif
Stelian Pop87a82542008-01-03 21:15:56 +00001005#endif /* CONFIG_RMII */
Wenyou Yang7b811852016-05-17 13:11:35 +08001006#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +08001007 }
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001008
Wenyou Yang7b811852016-05-17 13:11:35 +08001009#ifdef CONFIG_DM_ETH
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001010 ret = macb_phy_init(dev, name);
Wenyou Yang7b811852016-05-17 13:11:35 +08001011#else
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001012 ret = macb_phy_init(macb, name);
Wenyou Yang7b811852016-05-17 13:11:35 +08001013#endif
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001014 if (ret)
1015 return ret;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001016
1017 /* Enable TX and RX */
1018 macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE));
1019
Ben Warrende9fcb52008-01-09 18:15:53 -05001020 return 0;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001021}
1022
Simon Glass5ad27512016-05-05 07:28:09 -06001023static void _macb_halt(struct macb_device *macb)
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001024{
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001025 u32 ncr, tsr;
1026
1027 /* Halt the controller and wait for any ongoing transmission to end. */
1028 ncr = macb_readl(macb, NCR);
1029 ncr |= MACB_BIT(THALT);
1030 macb_writel(macb, NCR, ncr);
1031
1032 do {
1033 tsr = macb_readl(macb, TSR);
1034 } while (tsr & MACB_BIT(TGO));
1035
1036 /* Disable TX and RX, and clear statistics */
1037 macb_writel(macb, NCR, MACB_BIT(CLRSTAT));
1038}
1039
Simon Glass5ad27512016-05-05 07:28:09 -06001040static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr)
Ben Warren33f84312010-06-01 11:55:42 -07001041{
Ben Warren33f84312010-06-01 11:55:42 -07001042 u32 hwaddr_bottom;
1043 u16 hwaddr_top;
1044
1045 /* set hardware address */
Simon Glass5ad27512016-05-05 07:28:09 -06001046 hwaddr_bottom = enetaddr[0] | enetaddr[1] << 8 |
1047 enetaddr[2] << 16 | enetaddr[3] << 24;
Ben Warren33f84312010-06-01 11:55:42 -07001048 macb_writel(macb, SA1B, hwaddr_bottom);
Simon Glass5ad27512016-05-05 07:28:09 -06001049 hwaddr_top = enetaddr[4] | enetaddr[5] << 8;
Ben Warren33f84312010-06-01 11:55:42 -07001050 macb_writel(macb, SA1T, hwaddr_top);
1051 return 0;
1052}
1053
Bo Shen6f7d7d92013-04-24 15:59:28 +08001054static u32 macb_mdc_clk_div(int id, struct macb_device *macb)
1055{
1056 u32 config;
Wenyou Yang19449362017-02-14 16:24:40 +08001057#if defined(CONFIG_DM_ETH) && defined(CONFIG_CLK)
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001058 unsigned long macb_hz = macb->pclk_rate;
1059#else
Bo Shen6f7d7d92013-04-24 15:59:28 +08001060 unsigned long macb_hz = get_macb_pclk_rate(id);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001061#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +08001062
1063 if (macb_hz < 20000000)
1064 config = MACB_BF(CLK, MACB_CLK_DIV8);
1065 else if (macb_hz < 40000000)
1066 config = MACB_BF(CLK, MACB_CLK_DIV16);
1067 else if (macb_hz < 80000000)
1068 config = MACB_BF(CLK, MACB_CLK_DIV32);
1069 else
1070 config = MACB_BF(CLK, MACB_CLK_DIV64);
1071
1072 return config;
1073}
1074
1075static u32 gem_mdc_clk_div(int id, struct macb_device *macb)
1076{
1077 u32 config;
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001078
Wenyou Yang19449362017-02-14 16:24:40 +08001079#if defined(CONFIG_DM_ETH) && defined(CONFIG_CLK)
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001080 unsigned long macb_hz = macb->pclk_rate;
1081#else
Bo Shen6f7d7d92013-04-24 15:59:28 +08001082 unsigned long macb_hz = get_macb_pclk_rate(id);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001083#endif
Bo Shen6f7d7d92013-04-24 15:59:28 +08001084
1085 if (macb_hz < 20000000)
1086 config = GEM_BF(CLK, GEM_CLK_DIV8);
1087 else if (macb_hz < 40000000)
1088 config = GEM_BF(CLK, GEM_CLK_DIV16);
1089 else if (macb_hz < 80000000)
1090 config = GEM_BF(CLK, GEM_CLK_DIV32);
1091 else if (macb_hz < 120000000)
1092 config = GEM_BF(CLK, GEM_CLK_DIV48);
1093 else if (macb_hz < 160000000)
1094 config = GEM_BF(CLK, GEM_CLK_DIV64);
Ramon Friedb1b9b4f2019-07-16 22:04:32 +03001095 else if (macb_hz < 240000000)
Bo Shen6f7d7d92013-04-24 15:59:28 +08001096 config = GEM_BF(CLK, GEM_CLK_DIV96);
Ramon Friedb1b9b4f2019-07-16 22:04:32 +03001097 else if (macb_hz < 320000000)
1098 config = GEM_BF(CLK, GEM_CLK_DIV128);
1099 else
1100 config = GEM_BF(CLK, GEM_CLK_DIV224);
Bo Shen6f7d7d92013-04-24 15:59:28 +08001101
1102 return config;
1103}
1104
Bo Shen0e6624a2013-09-18 15:07:44 +08001105/*
1106 * Get the DMA bus width field of the network configuration register that we
1107 * should program. We find the width from decoding the design configuration
1108 * register to find the maximum supported data bus width.
1109 */
1110static u32 macb_dbw(struct macb_device *macb)
1111{
1112 switch (GEM_BFEXT(DBWDEF, gem_readl(macb, DCFG1))) {
1113 case 4:
1114 return GEM_BF(DBW, GEM_DBW128);
1115 case 2:
1116 return GEM_BF(DBW, GEM_DBW64);
1117 case 1:
1118 default:
1119 return GEM_BF(DBW, GEM_DBW32);
1120 }
Simon Glass5ad27512016-05-05 07:28:09 -06001121}
1122
1123static void _macb_eth_initialize(struct macb_device *macb)
1124{
1125 int id = 0; /* This is not used by functions we call */
1126 u32 ncfgr;
1127
Ramon Fried377d19d2019-07-14 18:25:14 +03001128 if (macb_is_gem(macb))
1129 macb->rx_buffer_size = GEM_RX_BUFFER_SIZE;
1130 else
1131 macb->rx_buffer_size = MACB_RX_BUFFER_SIZE;
1132
Simon Glass5ad27512016-05-05 07:28:09 -06001133 /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */
Ramon Fried377d19d2019-07-14 18:25:14 +03001134 macb->rx_buffer = dma_alloc_coherent(macb->rx_buffer_size *
1135 MACB_RX_RING_SIZE,
Simon Glass5ad27512016-05-05 07:28:09 -06001136 &macb->rx_buffer_dma);
1137 macb->rx_ring = dma_alloc_coherent(MACB_RX_DMA_DESC_SIZE,
1138 &macb->rx_ring_dma);
1139 macb->tx_ring = dma_alloc_coherent(MACB_TX_DMA_DESC_SIZE,
1140 &macb->tx_ring_dma);
1141 macb->dummy_desc = dma_alloc_coherent(MACB_TX_DUMMY_DMA_DESC_SIZE,
1142 &macb->dummy_desc_dma);
1143
1144 /*
1145 * Do some basic initialization so that we at least can talk
1146 * to the PHY
1147 */
1148 if (macb_is_gem(macb)) {
1149 ncfgr = gem_mdc_clk_div(id, macb);
1150 ncfgr |= macb_dbw(macb);
1151 } else {
1152 ncfgr = macb_mdc_clk_div(id, macb);
1153 }
1154
1155 macb_writel(macb, NCFGR, ncfgr);
1156}
1157
Simon Glass75c5d182016-05-05 07:28:11 -06001158#ifndef CONFIG_DM_ETH
Simon Glass5ad27512016-05-05 07:28:09 -06001159static int macb_send(struct eth_device *netdev, void *packet, int length)
1160{
1161 struct macb_device *macb = to_macb(netdev);
1162
1163 return _macb_send(macb, netdev->name, packet, length);
Bo Shen0e6624a2013-09-18 15:07:44 +08001164}
1165
Simon Glass5ad27512016-05-05 07:28:09 -06001166static int macb_recv(struct eth_device *netdev)
1167{
1168 struct macb_device *macb = to_macb(netdev);
1169 uchar *packet;
1170 int length;
1171
1172 macb->wrapped = false;
1173 for (;;) {
1174 macb->next_rx_tail = macb->rx_tail;
1175 length = _macb_recv(macb, &packet);
1176 if (length >= 0) {
1177 net_process_received_packet(packet, length);
1178 reclaim_rx_buffers(macb, macb->next_rx_tail);
Heinrich Schuchardt6c4aae92018-03-18 11:32:53 +01001179 } else {
Simon Glass5ad27512016-05-05 07:28:09 -06001180 return length;
1181 }
1182 }
1183}
1184
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001185static int macb_init(struct eth_device *netdev, struct bd_info *bd)
Simon Glass5ad27512016-05-05 07:28:09 -06001186{
1187 struct macb_device *macb = to_macb(netdev);
1188
1189 return _macb_init(macb, netdev->name);
1190}
1191
1192static void macb_halt(struct eth_device *netdev)
1193{
1194 struct macb_device *macb = to_macb(netdev);
1195
1196 return _macb_halt(macb);
1197}
1198
1199static int macb_write_hwaddr(struct eth_device *netdev)
1200{
1201 struct macb_device *macb = to_macb(netdev);
1202
1203 return _macb_write_hwaddr(macb, netdev->enetaddr);
1204}
1205
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001206int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
1207{
1208 struct macb_device *macb;
1209 struct eth_device *netdev;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001210
1211 macb = malloc(sizeof(struct macb_device));
1212 if (!macb) {
1213 printf("Error: Failed to allocate memory for MACB%d\n", id);
1214 return -1;
1215 }
1216 memset(macb, 0, sizeof(struct macb_device));
1217
1218 netdev = &macb->netdev;
1219
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001220 macb->regs = regs;
1221 macb->phy_addr = phy_addr;
1222
Bo Shen6f7d7d92013-04-24 15:59:28 +08001223 if (macb_is_gem(macb))
1224 sprintf(netdev->name, "gmac%d", id);
1225 else
1226 sprintf(netdev->name, "macb%d", id);
1227
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001228 netdev->init = macb_init;
1229 netdev->halt = macb_halt;
1230 netdev->send = macb_send;
1231 netdev->recv = macb_recv;
Ben Warren33f84312010-06-01 11:55:42 -07001232 netdev->write_hwaddr = macb_write_hwaddr;
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001233
Simon Glass5ad27512016-05-05 07:28:09 -06001234 _macb_eth_initialize(macb);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001235
1236 eth_register(netdev);
1237
Bo Shen7d91deb2013-04-24 15:59:27 +08001238#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
Joe Hershberger1fbcbed2016-08-08 11:28:38 -05001239 int retval;
1240 struct mii_dev *mdiodev = mdio_alloc();
1241 if (!mdiodev)
1242 return -ENOMEM;
Vladimir Oltean7947ab42021-09-27 14:21:52 +03001243 strlcpy(mdiodev->name, netdev->name, MDIO_NAME_LEN);
Joe Hershberger1fbcbed2016-08-08 11:28:38 -05001244 mdiodev->read = macb_miiphy_read;
1245 mdiodev->write = macb_miiphy_write;
1246
1247 retval = mdio_register(mdiodev);
1248 if (retval < 0)
1249 return retval;
Bo Shen7d91deb2013-04-24 15:59:27 +08001250 macb->bus = miiphy_get_dev_by_name(netdev->name);
Semih Hazar790088e2009-12-17 15:07:15 +02001251#endif
Simon Glass75c5d182016-05-05 07:28:11 -06001252 return 0;
1253}
1254#endif /* !CONFIG_DM_ETH */
1255
1256#ifdef CONFIG_DM_ETH
1257
1258static int macb_start(struct udevice *dev)
1259{
Wenyou Yang7b811852016-05-17 13:11:35 +08001260 return _macb_init(dev, dev->name);
Simon Glass75c5d182016-05-05 07:28:11 -06001261}
1262
1263static int macb_send(struct udevice *dev, void *packet, int length)
1264{
1265 struct macb_device *macb = dev_get_priv(dev);
1266
1267 return _macb_send(macb, dev->name, packet, length);
1268}
1269
1270static int macb_recv(struct udevice *dev, int flags, uchar **packetp)
1271{
1272 struct macb_device *macb = dev_get_priv(dev);
1273
1274 macb->next_rx_tail = macb->rx_tail;
1275 macb->wrapped = false;
1276
1277 return _macb_recv(macb, packetp);
1278}
1279
1280static int macb_free_pkt(struct udevice *dev, uchar *packet, int length)
1281{
1282 struct macb_device *macb = dev_get_priv(dev);
1283
1284 reclaim_rx_buffers(macb, macb->next_rx_tail);
1285
1286 return 0;
1287}
1288
1289static void macb_stop(struct udevice *dev)
1290{
1291 struct macb_device *macb = dev_get_priv(dev);
1292
1293 _macb_halt(macb);
1294}
1295
1296static int macb_write_hwaddr(struct udevice *dev)
1297{
Simon Glassfa20e932020-12-03 16:55:20 -07001298 struct eth_pdata *plat = dev_get_plat(dev);
Simon Glass75c5d182016-05-05 07:28:11 -06001299 struct macb_device *macb = dev_get_priv(dev);
1300
1301 return _macb_write_hwaddr(macb, plat->enetaddr);
1302}
1303
1304static const struct eth_ops macb_eth_ops = {
1305 .start = macb_start,
1306 .send = macb_send,
1307 .recv = macb_recv,
1308 .stop = macb_stop,
1309 .free_pkt = macb_free_pkt,
1310 .write_hwaddr = macb_write_hwaddr,
1311};
1312
Wenyou Yang19449362017-02-14 16:24:40 +08001313#ifdef CONFIG_CLK
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001314static int macb_enable_clk(struct udevice *dev)
1315{
1316 struct macb_device *macb = dev_get_priv(dev);
1317 struct clk clk;
1318 ulong clk_rate;
1319 int ret;
1320
1321 ret = clk_get_by_index(dev, 0, &clk);
1322 if (ret)
1323 return -EINVAL;
1324
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001325 /*
Anup Patel51b51f82019-02-25 08:14:36 +00001326 * If clock driver didn't support enable or disable then
1327 * we get -ENOSYS from clk_enable(). To handle this, we
1328 * don't fail for ret == -ENOSYS.
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001329 */
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001330 ret = clk_enable(&clk);
Anup Patel51b51f82019-02-25 08:14:36 +00001331 if (ret && ret != -ENOSYS)
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001332 return ret;
1333
1334 clk_rate = clk_get_rate(&clk);
1335 if (!clk_rate)
1336 return -EINVAL;
1337
1338 macb->pclk_rate = clk_rate;
1339
1340 return 0;
1341}
Wenyou Yang19449362017-02-14 16:24:40 +08001342#endif
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001343
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001344static const struct macb_usrio_cfg macb_default_usrio = {
1345 .mii = MACB_BIT(MII),
1346 .rmii = MACB_BIT(RMII),
1347 .rgmii = GEM_BIT(RGMII),
1348 .clken = MACB_BIT(CLKEN),
1349};
1350
Padmarao Begari63459cd2021-11-17 18:21:15 +05301351static struct macb_config default_gem_config = {
Ramon Fried834040c2019-07-16 22:04:35 +03001352 .dma_burst_length = 16,
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301353 .hw_dma_cap = HW_DMA_CAP_32B,
Anup Patel88799a62019-07-24 04:09:32 +00001354 .clk_init = NULL,
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001355 .usrio = &macb_default_usrio,
Ramon Fried834040c2019-07-16 22:04:35 +03001356};
1357
Simon Glass75c5d182016-05-05 07:28:11 -06001358static int macb_eth_probe(struct udevice *dev)
1359{
Simon Glassfa20e932020-12-03 16:55:20 -07001360 struct eth_pdata *pdata = dev_get_plat(dev);
Simon Glass75c5d182016-05-05 07:28:11 -06001361 struct macb_device *macb = dev_get_priv(dev);
Padmarao Begari34394ba2021-01-15 08:20:37 +05301362 struct ofnode_phandle_args phandle_args;
Anup Patel88799a62019-07-24 04:09:32 +00001363 int ret;
Wenyou Yang7b811852016-05-17 13:11:35 +08001364
Marek Behúnbc194772022-04-07 00:33:01 +02001365 macb->phy_interface = dev_read_phy_mode(dev);
Marek Behún48631e42022-04-07 00:33:03 +02001366 if (macb->phy_interface == PHY_INTERFACE_MODE_NA)
Wenyou Yang7b811852016-05-17 13:11:35 +08001367 return -EINVAL;
Wenyou Yang7b811852016-05-17 13:11:35 +08001368
Padmarao Begari34394ba2021-01-15 08:20:37 +05301369 /* Read phyaddr from DT */
1370 if (!dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
1371 &phandle_args))
1372 macb->phy_addr = ofnode_read_u32_default(phandle_args.node,
1373 "reg", -1);
1374
Bin Meng81ce6372021-09-12 11:15:14 +08001375 macb->regs = (void *)(uintptr_t)pdata->iobase;
Simon Glass75c5d182016-05-05 07:28:11 -06001376
Anup Patela1818b12019-07-24 04:09:37 +00001377 macb->is_big_endian = (cpu_to_be32(0x12345678) == 0x12345678);
1378
Anup Patel88799a62019-07-24 04:09:32 +00001379 macb->config = (struct macb_config *)dev_get_driver_data(dev);
Padmarao Begari63459cd2021-11-17 18:21:15 +05301380 if (!macb->config) {
1381 if (IS_ENABLED(CONFIG_DMA_ADDR_T_64BIT)) {
1382 if (GEM_BFEXT(DAW64, gem_readl(macb, DCFG6)))
1383 default_gem_config.hw_dma_cap = HW_DMA_CAP_64B;
1384 }
Anup Patel88799a62019-07-24 04:09:32 +00001385 macb->config = &default_gem_config;
Padmarao Begari63459cd2021-11-17 18:21:15 +05301386 }
Ramon Fried834040c2019-07-16 22:04:35 +03001387
Wenyou Yang19449362017-02-14 16:24:40 +08001388#ifdef CONFIG_CLK
Wenyou Yang44835ea2017-04-14 14:36:04 +08001389 ret = macb_enable_clk(dev);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001390 if (ret)
1391 return ret;
Wenyou Yang19449362017-02-14 16:24:40 +08001392#endif
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001393
Simon Glass75c5d182016-05-05 07:28:11 -06001394 _macb_eth_initialize(macb);
Wenyou Yang3d8d3482016-11-02 10:06:56 +08001395
Simon Glass75c5d182016-05-05 07:28:11 -06001396#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
Wenyou Yang44835ea2017-04-14 14:36:04 +08001397 macb->bus = mdio_alloc();
1398 if (!macb->bus)
Joe Hershberger1fbcbed2016-08-08 11:28:38 -05001399 return -ENOMEM;
Vladimir Oltean7947ab42021-09-27 14:21:52 +03001400 strlcpy(macb->bus->name, dev->name, MDIO_NAME_LEN);
Wenyou Yang44835ea2017-04-14 14:36:04 +08001401 macb->bus->read = macb_miiphy_read;
1402 macb->bus->write = macb_miiphy_write;
Joe Hershberger1fbcbed2016-08-08 11:28:38 -05001403
Wenyou Yang44835ea2017-04-14 14:36:04 +08001404 ret = mdio_register(macb->bus);
1405 if (ret < 0)
1406 return ret;
Simon Glass75c5d182016-05-05 07:28:11 -06001407 macb->bus = miiphy_get_dev_by_name(dev->name);
1408#endif
Wenyou Yang44835ea2017-04-14 14:36:04 +08001409
1410 return 0;
1411}
1412
1413static int macb_eth_remove(struct udevice *dev)
1414{
1415 struct macb_device *macb = dev_get_priv(dev);
1416
1417#ifdef CONFIG_PHYLIB
1418 free(macb->phydev);
1419#endif
1420 mdio_unregister(macb->bus);
1421 mdio_free(macb->bus);
Simon Glass75c5d182016-05-05 07:28:11 -06001422
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001423 return 0;
1424}
1425
1426/**
Simon Glassaad29ae2020-12-03 16:55:21 -07001427 * macb_late_eth_of_to_plat
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001428 * @dev: udevice struct
1429 * Returns 0 when operation success and negative errno number
1430 * when operation failed.
1431 */
Simon Glassaad29ae2020-12-03 16:55:21 -07001432int __weak macb_late_eth_of_to_plat(struct udevice *dev)
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001433{
Simon Glass75c5d182016-05-05 07:28:11 -06001434 return 0;
1435}
1436
Simon Glassaad29ae2020-12-03 16:55:21 -07001437static int macb_eth_of_to_plat(struct udevice *dev)
Simon Glass75c5d182016-05-05 07:28:11 -06001438{
Simon Glassfa20e932020-12-03 16:55:20 -07001439 struct eth_pdata *pdata = dev_get_plat(dev);
Simon Glass75c5d182016-05-05 07:28:11 -06001440
Bin Meng81ce6372021-09-12 11:15:14 +08001441 pdata->iobase = (uintptr_t)dev_remap_addr(dev);
Ramon Friedbf15d2f2018-12-27 19:58:42 +02001442 if (!pdata->iobase)
1443 return -EINVAL;
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001444
Simon Glassaad29ae2020-12-03 16:55:21 -07001445 return macb_late_eth_of_to_plat(dev);
Haavard Skinnemoen51c8f242006-01-20 10:03:34 +01001446}
1447
Claudiu Beznea01ca4eb2021-01-19 13:26:46 +02001448static const struct macb_usrio_cfg sama7g5_usrio = {
1449 .mii = 0,
1450 .rmii = 1,
1451 .rgmii = 2,
1452 .clken = BIT(2),
1453};
1454
Ramon Fried834040c2019-07-16 22:04:35 +03001455static const struct macb_config sama5d4_config = {
1456 .dma_burst_length = 4,
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301457 .hw_dma_cap = HW_DMA_CAP_32B,
Anup Patel88799a62019-07-24 04:09:32 +00001458 .clk_init = NULL,
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001459 .usrio = &macb_default_usrio,
Anup Patel88799a62019-07-24 04:09:32 +00001460};
1461
1462static const struct macb_config sifive_config = {
1463 .dma_burst_length = 16,
Padmarao Begari7a2c4962021-01-15 08:20:36 +05301464 .hw_dma_cap = HW_DMA_CAP_32B,
Anup Patel88799a62019-07-24 04:09:32 +00001465 .clk_init = macb_sifive_clk_init,
Claudiu Bezneadc17aec2021-01-19 13:26:44 +02001466 .usrio = &macb_default_usrio,
Ramon Fried834040c2019-07-16 22:04:35 +03001467};
1468
Claudiu Beznea01ca4eb2021-01-19 13:26:46 +02001469static const struct macb_config sama7g5_gmac_config = {
1470 .dma_burst_length = 16,
1471 .hw_dma_cap = HW_DMA_CAP_32B,
1472 .clk_init = macb_sama7g5_clk_init,
1473 .usrio = &sama7g5_usrio,
1474};
1475
Claudiu Beznea2acf5f82021-01-19 13:26:47 +02001476static const struct macb_config sama7g5_emac_config = {
1477 .caps = MACB_CAPS_USRIO_HAS_CLKEN,
1478 .dma_burst_length = 16,
1479 .hw_dma_cap = HW_DMA_CAP_32B,
1480 .usrio = &sama7g5_usrio,
1481};
1482
Simon Glass75c5d182016-05-05 07:28:11 -06001483static const struct udevice_id macb_eth_ids[] = {
1484 { .compatible = "cdns,macb" },
Wenyou Yang8f155402017-04-14 14:36:05 +08001485 { .compatible = "cdns,at91sam9260-macb" },
Nicolas Ferre9115f572019-09-27 13:08:32 +00001486 { .compatible = "cdns,sam9x60-macb" },
Claudiu Beznea01ca4eb2021-01-19 13:26:46 +02001487 { .compatible = "cdns,sama7g5-gem",
1488 .data = (ulong)&sama7g5_gmac_config },
Claudiu Beznea2acf5f82021-01-19 13:26:47 +02001489 { .compatible = "cdns,sama7g5-emac",
1490 .data = (ulong)&sama7g5_emac_config },
Wenyou Yang8f155402017-04-14 14:36:05 +08001491 { .compatible = "atmel,sama5d2-gem" },
1492 { .compatible = "atmel,sama5d3-gem" },
Ramon Fried834040c2019-07-16 22:04:35 +03001493 { .compatible = "atmel,sama5d4-gem", .data = (ulong)&sama5d4_config },
Wilson Lee41d6d1e2017-08-22 20:25:07 -07001494 { .compatible = "cdns,zynq-gem" },
Anup Patel88799a62019-07-24 04:09:32 +00001495 { .compatible = "sifive,fu540-c000-gem",
1496 .data = (ulong)&sifive_config },
Simon Glass75c5d182016-05-05 07:28:11 -06001497 { }
1498};
1499
1500U_BOOT_DRIVER(eth_macb) = {
1501 .name = "eth_macb",
1502 .id = UCLASS_ETH,
1503 .of_match = macb_eth_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001504 .of_to_plat = macb_eth_of_to_plat,
Simon Glass75c5d182016-05-05 07:28:11 -06001505 .probe = macb_eth_probe,
Wenyou Yang44835ea2017-04-14 14:36:04 +08001506 .remove = macb_eth_remove,
Simon Glass75c5d182016-05-05 07:28:11 -06001507 .ops = &macb_eth_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001508 .priv_auto = sizeof(struct macb_device),
Simon Glass71fa5b42020-12-03 16:55:18 -07001509 .plat_auto = sizeof(struct eth_pdata),
Simon Glass75c5d182016-05-05 07:28:11 -06001510};
1511#endif
1512
Jon Loeligerb1d408a2007-07-09 17:30:01 -05001513#endif