blob: 63fe4b2d33c46020c3aa34b0ac0bd79d0629e783 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Kumar Gala2683c532011-04-13 08:37:44 -05002/*
Roy Zangbafd8032012-10-08 07:44:21 +00003 * Copyright 2009-2012 Freescale Semiconductor, Inc.
Madalin Bucurb76b0a62020-04-23 16:25:19 +03004 * Copyright 2020 NXP
Kumar Gala2683c532011-04-13 08:37:44 -05005 * Dave Liu <daveliu@freescale.com>
Kumar Gala2683c532011-04-13 08:37:44 -05006 */
Tom Rinidec7ea02024-05-20 13:35:03 -06007#include <config.h>
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
Simon Glass655306c2020-05-10 11:39:58 -06009#include <part.h>
Kumar Gala2683c532011-04-13 08:37:44 -050010#include <asm/io.h>
Madalin Bucurb76b0a62020-04-23 16:25:19 +030011#include <dm.h>
12#include <dm/ofnode.h>
13#include <linux/compat.h>
14#include <phy_interface.h>
Kumar Gala2683c532011-04-13 08:37:44 -050015#include <malloc.h>
16#include <net.h>
17#include <hwconfig.h>
18#include <fm_eth.h>
19#include <fsl_mdio.h>
20#include <miiphy.h>
21#include <phy.h>
Shaohui Xie513eaf22015-10-26 19:47:47 +080022#include <fsl_dtsec.h>
23#include <fsl_tgec.h>
Shaohui Xie835c72b2015-03-20 19:28:19 -070024#include <fsl_memac.h>
Simon Glassdbd79542020-05-10 11:40:11 -060025#include <linux/delay.h>
Kumar Gala2683c532011-04-13 08:37:44 -050026
27#include "fm.h"
28
Jerome Forissieredb410b2024-09-11 11:58:18 +020029#if ((defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
30 !defined(CONFIG_BITBANGMII))
Kumar Gala2683c532011-04-13 08:37:44 -050031
32#define TBIANA_SETTINGS (TBIANA_ASYMMETRIC_PAUSE | TBIANA_SYMMETRIC_PAUSE | \
33 TBIANA_FULL_DUPLEX)
34
35#define TBIANA_SGMII_ACK 0x4001
36
37#define TBICR_SETTINGS (TBICR_ANEG_ENABLE | TBICR_RESTART_ANEG | \
38 TBICR_FULL_DUPLEX | TBICR_SPEED1_SET)
39
40/* Configure the TBI for SGMII operation */
Kim Phillips914b0782012-10-29 13:34:34 +000041static void dtsec_configure_serdes(struct fm_eth *priv)
Kumar Gala2683c532011-04-13 08:37:44 -050042{
Roy Zangbafd8032012-10-08 07:44:21 +000043#ifdef CONFIG_SYS_FMAN_V3
44 u32 value;
45 struct mii_dev bus;
Shengzhou Liu95403682014-10-23 17:20:57 +080046 bool sgmii_2500 = (priv->enet_if ==
Vladimir Oltean6caef972021-09-18 15:32:35 +030047 PHY_INTERFACE_MODE_2500BASEX) ? true : false;
Madalin Bucurb76b0a62020-04-23 16:25:19 +030048 int i = 0, j;
49
Madalin Bucurb76b0a62020-04-23 16:25:19 +030050 bus.priv = priv->pcs_mdio;
Madalin Bucurb76b0a62020-04-23 16:25:19 +030051 bus.read = memac_mdio_read;
52 bus.write = memac_mdio_write;
53 bus.reset = memac_mdio_reset;
Roy Zangbafd8032012-10-08 07:44:21 +000054
Shaohui Xie1b295122015-10-26 19:47:48 +080055qsgmii_loop:
Shengzhou Liu95403682014-10-23 17:20:57 +080056 /* SGMII IF mode + AN enable only for 1G SGMII, not for 2.5G */
shaohui xiea3384a12016-11-15 14:36:47 +080057 if (sgmii_2500)
58 value = PHY_SGMII_CR_PHY_RESET |
59 PHY_SGMII_IF_SPEED_GIGABIT |
60 PHY_SGMII_IF_MODE_SGMII;
61 else
62 value = PHY_SGMII_IF_MODE_SGMII | PHY_SGMII_IF_MODE_AN;
Shengzhou Liu95403682014-10-23 17:20:57 +080063
Madalin Bucurb76b0a62020-04-23 16:25:19 +030064 for (j = 0; j <= 3; j++)
65 debug("dump PCS reg %#x: %#x\n", j,
66 memac_mdio_read(&bus, i, MDIO_DEVAD_NONE, j));
67
Shaohui Xie1b295122015-10-26 19:47:48 +080068 memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0x14, value);
Roy Zangbafd8032012-10-08 07:44:21 +000069
70 /* Dev ability according to SGMII specification */
71 value = PHY_SGMII_DEV_ABILITY_SGMII;
Shaohui Xie1b295122015-10-26 19:47:48 +080072 memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0x4, value);
Roy Zangbafd8032012-10-08 07:44:21 +000073
shaohui xiea3384a12016-11-15 14:36:47 +080074 if (sgmii_2500) {
75 /* Adjust link timer for 2.5G SGMII,
76 * 1.6 ms in units of 3.2 ns:
77 * 1.6ms / 3.2ns = 5 * 10^5 = 0x7a120.
78 */
79 memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0x13, 0x0007);
80 memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0x12, 0xa120);
81 } else {
82 /* Adjust link timer for SGMII,
83 * 1.6 ms in units of 8 ns:
84 * 1.6ms / 8ns = 2 * 10^5 = 0x30d40.
85 */
86 memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0x13, 0x0003);
87 memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0x12, 0x0d40);
88 }
Roy Zangbafd8032012-10-08 07:44:21 +000089
90 /* Restart AN */
shaohui xiea3384a12016-11-15 14:36:47 +080091 value = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
Shaohui Xie1b295122015-10-26 19:47:48 +080092 memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0, value);
93
94 if ((priv->enet_if == PHY_INTERFACE_MODE_QSGMII) && (i < 3)) {
95 i++;
96 goto qsgmii_loop;
97 }
Roy Zangbafd8032012-10-08 07:44:21 +000098#else
Kumar Gala2683c532011-04-13 08:37:44 -050099 struct dtsec *regs = priv->mac->base;
100 struct tsec_mii_mng *phyregs = priv->mac->phyregs;
101
102 /*
103 * Access TBI PHY registers at given TSEC register offset as
104 * opposed to the register offset used for external PHY accesses
105 */
106 tsec_local_mdio_write(phyregs, in_be32(&regs->tbipa), 0, TBI_TBICON,
107 TBICON_CLK_SELECT);
108 tsec_local_mdio_write(phyregs, in_be32(&regs->tbipa), 0, TBI_ANA,
109 TBIANA_SGMII_ACK);
110 tsec_local_mdio_write(phyregs, in_be32(&regs->tbipa), 0,
111 TBI_CR, TBICR_SETTINGS);
Roy Zangbafd8032012-10-08 07:44:21 +0000112#endif
Kumar Gala2683c532011-04-13 08:37:44 -0500113}
114
Madalin Bucur11fa7a32020-04-23 16:25:16 +0300115static void dtsec_init_phy(struct fm_eth *fm_eth)
Kumar Gala2683c532011-04-13 08:37:44 -0500116{
Roy Zangbafd8032012-10-08 07:44:21 +0000117#ifndef CONFIG_SYS_FMAN_V3
Tom Rini376b88a2022-10-28 20:27:13 -0400118 struct dtsec *regs = (struct dtsec *)CFG_SYS_FSL_FM1_DTSEC1_ADDR;
shaohui xie842e59e2012-10-11 20:25:36 +0000119
Kumar Gala2683c532011-04-13 08:37:44 -0500120 /* Assign a Physical address to the TBI */
Tom Rini6a5dccc2022-11-16 13:10:41 -0500121 out_be32(&regs->tbipa, CFG_SYS_TBIPA_VALUE);
Roy Zangbafd8032012-10-08 07:44:21 +0000122#endif
Kumar Gala2683c532011-04-13 08:37:44 -0500123
Shengzhou Liu95403682014-10-23 17:20:57 +0800124 if (fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII ||
Shaohui Xie1b295122015-10-26 19:47:48 +0800125 fm_eth->enet_if == PHY_INTERFACE_MODE_QSGMII ||
Vladimir Oltean6caef972021-09-18 15:32:35 +0300126 fm_eth->enet_if == PHY_INTERFACE_MODE_2500BASEX)
Kumar Gala2683c532011-04-13 08:37:44 -0500127 dtsec_configure_serdes(fm_eth);
128}
Kumar Gala2683c532011-04-13 08:37:44 -0500129#endif
130
131static u16 muram_readw(u16 *addr)
132{
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800133 ulong base = (ulong)addr & ~0x3UL;
134 u32 val32 = in_be32((void *)base);
Kumar Gala2683c532011-04-13 08:37:44 -0500135 int byte_pos;
136 u16 ret;
137
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800138 byte_pos = (ulong)addr & 0x3UL;
Kumar Gala2683c532011-04-13 08:37:44 -0500139 if (byte_pos)
140 ret = (u16)(val32 & 0x0000ffff);
141 else
142 ret = (u16)((val32 & 0xffff0000) >> 16);
143
144 return ret;
145}
146
147static void muram_writew(u16 *addr, u16 val)
148{
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800149 ulong base = (ulong)addr & ~0x3UL;
150 u32 org32 = in_be32((void *)base);
Kumar Gala2683c532011-04-13 08:37:44 -0500151 u32 val32;
152 int byte_pos;
153
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800154 byte_pos = (ulong)addr & 0x3UL;
Kumar Gala2683c532011-04-13 08:37:44 -0500155 if (byte_pos)
156 val32 = (org32 & 0xffff0000) | val;
157 else
158 val32 = (org32 & 0x0000ffff) | ((u32)val << 16);
159
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800160 out_be32((void *)base, val32);
Kumar Gala2683c532011-04-13 08:37:44 -0500161}
162
163static void bmi_rx_port_disable(struct fm_bmi_rx_port *rx_port)
164{
165 int timeout = 1000000;
166
167 clrbits_be32(&rx_port->fmbm_rcfg, FMBM_RCFG_EN);
168
169 /* wait until the rx port is not busy */
170 while ((in_be32(&rx_port->fmbm_rst) & FMBM_RST_BSY) && timeout--)
171 ;
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300172 if (!timeout)
173 printf("%s - timeout\n", __func__);
Kumar Gala2683c532011-04-13 08:37:44 -0500174}
175
176static void bmi_rx_port_init(struct fm_bmi_rx_port *rx_port)
177{
178 /* set BMI to independent mode, Rx port disable */
179 out_be32(&rx_port->fmbm_rcfg, FMBM_RCFG_IM);
180 /* clear FOF in IM case */
181 out_be32(&rx_port->fmbm_rim, 0);
182 /* Rx frame next engine -RISC */
183 out_be32(&rx_port->fmbm_rfne, NIA_ENG_RISC | NIA_RISC_AC_IM_RX);
184 /* Rx command attribute - no order, MR[3] = 1 */
185 clrbits_be32(&rx_port->fmbm_rfca, FMBM_RFCA_ORDER | FMBM_RFCA_MR_MASK);
186 setbits_be32(&rx_port->fmbm_rfca, FMBM_RFCA_MR(4));
187 /* enable Rx statistic counters */
188 out_be32(&rx_port->fmbm_rstc, FMBM_RSTC_EN);
189 /* disable Rx performance counters */
190 out_be32(&rx_port->fmbm_rpc, 0);
191}
192
193static void bmi_tx_port_disable(struct fm_bmi_tx_port *tx_port)
194{
195 int timeout = 1000000;
196
197 clrbits_be32(&tx_port->fmbm_tcfg, FMBM_TCFG_EN);
198
199 /* wait until the tx port is not busy */
200 while ((in_be32(&tx_port->fmbm_tst) & FMBM_TST_BSY) && timeout--)
201 ;
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300202 if (!timeout)
203 printf("%s - timeout\n", __func__);
Kumar Gala2683c532011-04-13 08:37:44 -0500204}
205
206static void bmi_tx_port_init(struct fm_bmi_tx_port *tx_port)
207{
208 /* set BMI to independent mode, Tx port disable */
209 out_be32(&tx_port->fmbm_tcfg, FMBM_TCFG_IM);
210 /* Tx frame next engine -RISC */
211 out_be32(&tx_port->fmbm_tfne, NIA_ENG_RISC | NIA_RISC_AC_IM_TX);
212 out_be32(&tx_port->fmbm_tfene, NIA_ENG_RISC | NIA_RISC_AC_IM_TX);
213 /* Tx command attribute - no order, MR[3] = 1 */
214 clrbits_be32(&tx_port->fmbm_tfca, FMBM_TFCA_ORDER | FMBM_TFCA_MR_MASK);
215 setbits_be32(&tx_port->fmbm_tfca, FMBM_TFCA_MR(4));
216 /* enable Tx statistic counters */
217 out_be32(&tx_port->fmbm_tstc, FMBM_TSTC_EN);
218 /* disable Tx performance counters */
219 out_be32(&tx_port->fmbm_tpc, 0);
220}
221
222static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth)
223{
224 struct fm_port_global_pram *pram;
225 u32 pram_page_offset;
226 void *rx_bd_ring_base;
227 void *rx_buf_pool;
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800228 u32 bd_ring_base_lo, bd_ring_base_hi;
229 u32 buf_lo, buf_hi;
Kumar Gala2683c532011-04-13 08:37:44 -0500230 struct fm_port_bd *rxbd;
231 struct fm_port_qd *rxqd;
232 struct fm_bmi_rx_port *bmi_rx_port = fm_eth->rx_port;
233 int i;
234
235 /* alloc global parameter ram at MURAM */
236 pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index,
237 FM_PRAM_SIZE, FM_PRAM_ALIGN);
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800238 if (!pram) {
239 printf("%s: No muram for Rx global parameter\n", __func__);
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800240 return -ENOMEM;
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800241 }
242
Kumar Gala2683c532011-04-13 08:37:44 -0500243 fm_eth->rx_pram = pram;
244
245 /* parameter page offset to MURAM */
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800246 pram_page_offset = (void *)pram - fm_muram_base(fm_eth->fm_index);
Kumar Gala2683c532011-04-13 08:37:44 -0500247
248 /* enable global mode- snooping data buffers and BDs */
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800249 out_be32(&pram->mode, PRAM_MODE_GLOBAL);
Kumar Gala2683c532011-04-13 08:37:44 -0500250
251 /* init the Rx queue descriptor pionter */
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800252 out_be32(&pram->rxqd_ptr, pram_page_offset + 0x20);
Kumar Gala2683c532011-04-13 08:37:44 -0500253
254 /* set the max receive buffer length, power of 2 */
255 muram_writew(&pram->mrblr, MAX_RXBUF_LOG2);
256
257 /* alloc Rx buffer descriptors from main memory */
258 rx_bd_ring_base = malloc(sizeof(struct fm_port_bd)
259 * RX_BD_RING_SIZE);
260 if (!rx_bd_ring_base)
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800261 return -ENOMEM;
262
Kumar Gala2683c532011-04-13 08:37:44 -0500263 memset(rx_bd_ring_base, 0, sizeof(struct fm_port_bd)
264 * RX_BD_RING_SIZE);
265
266 /* alloc Rx buffer from main memory */
267 rx_buf_pool = malloc(MAX_RXBUF_LEN * RX_BD_RING_SIZE);
Hou Zhiqiang46bcbeb2021-06-12 21:15:41 +0300268 if (!rx_buf_pool) {
269 free(rx_bd_ring_base);
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800270 return -ENOMEM;
Hou Zhiqiang46bcbeb2021-06-12 21:15:41 +0300271 }
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800272
Kumar Gala2683c532011-04-13 08:37:44 -0500273 memset(rx_buf_pool, 0, MAX_RXBUF_LEN * RX_BD_RING_SIZE);
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800274 debug("%s: rx_buf_pool = %p\n", __func__, rx_buf_pool);
Kumar Gala2683c532011-04-13 08:37:44 -0500275
276 /* save them to fm_eth */
277 fm_eth->rx_bd_ring = rx_bd_ring_base;
278 fm_eth->cur_rxbd = rx_bd_ring_base;
279 fm_eth->rx_buf = rx_buf_pool;
280
281 /* init Rx BDs ring */
282 rxbd = (struct fm_port_bd *)rx_bd_ring_base;
283 for (i = 0; i < RX_BD_RING_SIZE; i++) {
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800284 muram_writew(&rxbd->status, RxBD_EMPTY);
285 muram_writew(&rxbd->len, 0);
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800286 buf_hi = upper_32_bits(virt_to_phys(rx_buf_pool +
287 i * MAX_RXBUF_LEN));
288 buf_lo = lower_32_bits(virt_to_phys(rx_buf_pool +
289 i * MAX_RXBUF_LEN));
290 muram_writew(&rxbd->buf_ptr_hi, (u16)buf_hi);
291 out_be32(&rxbd->buf_ptr_lo, buf_lo);
Kumar Gala2683c532011-04-13 08:37:44 -0500292 rxbd++;
293 }
294
295 /* set the Rx queue descriptor */
296 rxqd = &pram->rxqd;
297 muram_writew(&rxqd->gen, 0);
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800298 bd_ring_base_hi = upper_32_bits(virt_to_phys(rx_bd_ring_base));
299 bd_ring_base_lo = lower_32_bits(virt_to_phys(rx_bd_ring_base));
300 muram_writew(&rxqd->bd_ring_base_hi, (u16)bd_ring_base_hi);
301 out_be32(&rxqd->bd_ring_base_lo, bd_ring_base_lo);
Kumar Gala2683c532011-04-13 08:37:44 -0500302 muram_writew(&rxqd->bd_ring_size, sizeof(struct fm_port_bd)
303 * RX_BD_RING_SIZE);
304 muram_writew(&rxqd->offset_in, 0);
305 muram_writew(&rxqd->offset_out, 0);
306
307 /* set IM parameter ram pointer to Rx Frame Queue ID */
308 out_be32(&bmi_rx_port->fmbm_rfqid, pram_page_offset);
309
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800310 return 0;
Kumar Gala2683c532011-04-13 08:37:44 -0500311}
312
313static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth)
314{
315 struct fm_port_global_pram *pram;
316 u32 pram_page_offset;
317 void *tx_bd_ring_base;
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800318 u32 bd_ring_base_lo, bd_ring_base_hi;
Kumar Gala2683c532011-04-13 08:37:44 -0500319 struct fm_port_bd *txbd;
320 struct fm_port_qd *txqd;
321 struct fm_bmi_tx_port *bmi_tx_port = fm_eth->tx_port;
322 int i;
323
324 /* alloc global parameter ram at MURAM */
325 pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index,
326 FM_PRAM_SIZE, FM_PRAM_ALIGN);
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800327 if (!pram) {
328 printf("%s: No muram for Tx global parameter\n", __func__);
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800329 return -ENOMEM;
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800330 }
Kumar Gala2683c532011-04-13 08:37:44 -0500331 fm_eth->tx_pram = pram;
332
333 /* parameter page offset to MURAM */
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800334 pram_page_offset = (void *)pram - fm_muram_base(fm_eth->fm_index);
Kumar Gala2683c532011-04-13 08:37:44 -0500335
336 /* enable global mode- snooping data buffers and BDs */
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800337 out_be32(&pram->mode, PRAM_MODE_GLOBAL);
Kumar Gala2683c532011-04-13 08:37:44 -0500338
339 /* init the Tx queue descriptor pionter */
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800340 out_be32(&pram->txqd_ptr, pram_page_offset + 0x40);
Kumar Gala2683c532011-04-13 08:37:44 -0500341
342 /* alloc Tx buffer descriptors from main memory */
343 tx_bd_ring_base = malloc(sizeof(struct fm_port_bd)
344 * TX_BD_RING_SIZE);
345 if (!tx_bd_ring_base)
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800346 return -ENOMEM;
347
Kumar Gala2683c532011-04-13 08:37:44 -0500348 memset(tx_bd_ring_base, 0, sizeof(struct fm_port_bd)
349 * TX_BD_RING_SIZE);
350 /* save it to fm_eth */
351 fm_eth->tx_bd_ring = tx_bd_ring_base;
352 fm_eth->cur_txbd = tx_bd_ring_base;
353
354 /* init Tx BDs ring */
355 txbd = (struct fm_port_bd *)tx_bd_ring_base;
356 for (i = 0; i < TX_BD_RING_SIZE; i++) {
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800357 muram_writew(&txbd->status, TxBD_LAST);
358 muram_writew(&txbd->len, 0);
359 muram_writew(&txbd->buf_ptr_hi, 0);
360 out_be32(&txbd->buf_ptr_lo, 0);
361 txbd++;
Kumar Gala2683c532011-04-13 08:37:44 -0500362 }
363
364 /* set the Tx queue decriptor */
365 txqd = &pram->txqd;
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800366 bd_ring_base_hi = upper_32_bits(virt_to_phys(tx_bd_ring_base));
367 bd_ring_base_lo = lower_32_bits(virt_to_phys(tx_bd_ring_base));
368 muram_writew(&txqd->bd_ring_base_hi, (u16)bd_ring_base_hi);
369 out_be32(&txqd->bd_ring_base_lo, bd_ring_base_lo);
Kumar Gala2683c532011-04-13 08:37:44 -0500370 muram_writew(&txqd->bd_ring_size, sizeof(struct fm_port_bd)
371 * TX_BD_RING_SIZE);
372 muram_writew(&txqd->offset_in, 0);
373 muram_writew(&txqd->offset_out, 0);
374
375 /* set IM parameter ram pointer to Tx Confirmation Frame Queue ID */
376 out_be32(&bmi_tx_port->fmbm_tcfqid, pram_page_offset);
377
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800378 return 0;
Kumar Gala2683c532011-04-13 08:37:44 -0500379}
380
381static int fm_eth_init(struct fm_eth *fm_eth)
382{
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800383 int ret;
Kumar Gala2683c532011-04-13 08:37:44 -0500384
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800385 ret = fm_eth_rx_port_parameter_init(fm_eth);
386 if (ret)
387 return ret;
Kumar Gala2683c532011-04-13 08:37:44 -0500388
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800389 ret = fm_eth_tx_port_parameter_init(fm_eth);
390 if (ret)
391 return ret;
Kumar Gala2683c532011-04-13 08:37:44 -0500392
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800393 return 0;
Kumar Gala2683c532011-04-13 08:37:44 -0500394}
395
396static int fm_eth_startup(struct fm_eth *fm_eth)
397{
398 struct fsl_enet_mac *mac;
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800399 int ret;
400
Kumar Gala2683c532011-04-13 08:37:44 -0500401 mac = fm_eth->mac;
402
403 /* Rx/TxBDs, Rx/TxQDs, Rx buff and parameter ram init */
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800404 ret = fm_eth_init(fm_eth);
405 if (ret)
406 return ret;
Kumar Gala2683c532011-04-13 08:37:44 -0500407 /* setup the MAC controller */
408 mac->init_mac(mac);
409
410 /* For some reason we need to set SPEED_100 */
Shaohui Xiec218d292013-08-19 18:58:52 +0800411 if (((fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII) ||
Vladimir Oltean6caef972021-09-18 15:32:35 +0300412 (fm_eth->enet_if == PHY_INTERFACE_MODE_2500BASEX) ||
Shaohui Xiec218d292013-08-19 18:58:52 +0800413 (fm_eth->enet_if == PHY_INTERFACE_MODE_QSGMII)) &&
414 mac->set_if_mode)
Kumar Gala2683c532011-04-13 08:37:44 -0500415 mac->set_if_mode(mac, fm_eth->enet_if, SPEED_100);
416
417 /* init bmi rx port, IM mode and disable */
418 bmi_rx_port_init(fm_eth->rx_port);
419 /* init bmi tx port, IM mode and disable */
420 bmi_tx_port_init(fm_eth->tx_port);
421
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800422 return 0;
Kumar Gala2683c532011-04-13 08:37:44 -0500423}
424
425static void fmc_tx_port_graceful_stop_enable(struct fm_eth *fm_eth)
426{
427 struct fm_port_global_pram *pram;
428
429 pram = fm_eth->tx_pram;
430 /* graceful stop transmission of frames */
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800431 setbits_be32(&pram->mode, PRAM_MODE_GRACEFUL_STOP);
Kumar Gala2683c532011-04-13 08:37:44 -0500432 sync();
433}
434
435static void fmc_tx_port_graceful_stop_disable(struct fm_eth *fm_eth)
436{
437 struct fm_port_global_pram *pram;
438
439 pram = fm_eth->tx_pram;
440 /* re-enable transmission of frames */
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800441 clrbits_be32(&pram->mode, PRAM_MODE_GRACEFUL_STOP);
Kumar Gala2683c532011-04-13 08:37:44 -0500442 sync();
443}
444
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300445static int fm_eth_open(struct udevice *dev)
Kumar Gala2683c532011-04-13 08:37:44 -0500446{
Simon Glassfa20e932020-12-03 16:55:20 -0700447 struct eth_pdata *pdata = dev_get_plat(dev);
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300448 struct fm_eth *fm_eth = dev_get_priv(dev);
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300449 unsigned char *enetaddr;
Kumar Gala2683c532011-04-13 08:37:44 -0500450 struct fsl_enet_mac *mac;
Timur Tabi42387462012-07-09 08:52:43 +0000451#ifdef CONFIG_PHYLIB
452 int ret;
453#endif
Kumar Gala2683c532011-04-13 08:37:44 -0500454
Kumar Gala2683c532011-04-13 08:37:44 -0500455 mac = fm_eth->mac;
456
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300457 enetaddr = pdata->enetaddr;
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300458
Kumar Gala2683c532011-04-13 08:37:44 -0500459 /* setup the MAC address */
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300460 if (enetaddr[0] & 0x01) {
461 printf("%s: MacAddress is multicast address\n", __func__);
462 enetaddr[0] = 0;
463 enetaddr[5] = fm_eth->num;
Kumar Gala2683c532011-04-13 08:37:44 -0500464 }
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300465 mac->set_mac_addr(mac, enetaddr);
Kumar Gala2683c532011-04-13 08:37:44 -0500466
467 /* enable bmi Rx port */
468 setbits_be32(&fm_eth->rx_port->fmbm_rcfg, FMBM_RCFG_EN);
469 /* enable MAC rx/tx port */
470 mac->enable_mac(mac);
471 /* enable bmi Tx port */
472 setbits_be32(&fm_eth->tx_port->fmbm_tcfg, FMBM_TCFG_EN);
473 /* re-enable transmission of frame */
474 fmc_tx_port_graceful_stop_disable(fm_eth);
475
476#ifdef CONFIG_PHYLIB
Codrin Ciubotariu1ee90f92015-01-12 14:08:29 +0200477 if (fm_eth->phydev) {
478 ret = phy_startup(fm_eth->phydev);
479 if (ret) {
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300480 printf("%s: Could not initialize\n", dev->name);
Codrin Ciubotariu1ee90f92015-01-12 14:08:29 +0200481 return ret;
482 }
483 } else {
484 return 0;
Timur Tabi42387462012-07-09 08:52:43 +0000485 }
Kumar Gala2683c532011-04-13 08:37:44 -0500486#else
487 fm_eth->phydev->speed = SPEED_1000;
488 fm_eth->phydev->link = 1;
489 fm_eth->phydev->duplex = DUPLEX_FULL;
490#endif
491
492 /* set the MAC-PHY mode */
493 mac->set_if_mode(mac, fm_eth->enet_if, fm_eth->phydev->speed);
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300494 debug("MAC IF mode %d, speed %d, link %d\n", fm_eth->enet_if,
495 fm_eth->phydev->speed, fm_eth->phydev->link);
Kumar Gala2683c532011-04-13 08:37:44 -0500496
497 if (!fm_eth->phydev->link)
498 printf("%s: No link.\n", fm_eth->phydev->dev->name);
499
500 return fm_eth->phydev->link ? 0 : -1;
501}
502
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300503static void fm_eth_halt(struct udevice *dev)
Kumar Gala2683c532011-04-13 08:37:44 -0500504{
505 struct fm_eth *fm_eth;
506 struct fsl_enet_mac *mac;
507
Simon Glass95588622020-12-22 19:30:28 -0700508 fm_eth = dev_get_priv(dev);
Kumar Gala2683c532011-04-13 08:37:44 -0500509 mac = fm_eth->mac;
510
511 /* graceful stop the transmission of frames */
512 fmc_tx_port_graceful_stop_enable(fm_eth);
513 /* disable bmi Tx port */
514 bmi_tx_port_disable(fm_eth->tx_port);
515 /* disable MAC rx/tx port */
516 mac->disable_mac(mac);
517 /* disable bmi Rx port */
518 bmi_rx_port_disable(fm_eth->rx_port);
519
Shaohui Xieab687cc2015-10-26 19:47:46 +0800520#ifdef CONFIG_PHYLIB
Codrin Ciubotariu1ee90f92015-01-12 14:08:29 +0200521 if (fm_eth->phydev)
522 phy_shutdown(fm_eth->phydev);
Shaohui Xieab687cc2015-10-26 19:47:46 +0800523#endif
Kumar Gala2683c532011-04-13 08:37:44 -0500524}
525
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300526static int fm_eth_send(struct udevice *dev, void *buf, int len)
Kumar Gala2683c532011-04-13 08:37:44 -0500527{
528 struct fm_eth *fm_eth;
529 struct fm_port_global_pram *pram;
530 struct fm_port_bd *txbd, *txbd_base;
531 u16 offset_in;
532 int i;
533
Simon Glass95588622020-12-22 19:30:28 -0700534 fm_eth = dev_get_priv(dev);
Kumar Gala2683c532011-04-13 08:37:44 -0500535 pram = fm_eth->tx_pram;
536 txbd = fm_eth->cur_txbd;
537
538 /* find one empty TxBD */
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800539 for (i = 0; muram_readw(&txbd->status) & TxBD_READY; i++) {
Kumar Gala2683c532011-04-13 08:37:44 -0500540 udelay(100);
541 if (i > 0x1000) {
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800542 printf("%s: Tx buffer not ready, txbd->status = 0x%x\n",
543 dev->name, muram_readw(&txbd->status));
Kumar Gala2683c532011-04-13 08:37:44 -0500544 return 0;
545 }
546 }
547 /* setup TxBD */
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800548 muram_writew(&txbd->buf_ptr_hi, (u16)upper_32_bits(virt_to_phys(buf)));
549 out_be32(&txbd->buf_ptr_lo, lower_32_bits(virt_to_phys(buf)));
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800550 muram_writew(&txbd->len, len);
Kumar Gala2683c532011-04-13 08:37:44 -0500551 sync();
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800552 muram_writew(&txbd->status, TxBD_READY | TxBD_LAST);
Kumar Gala2683c532011-04-13 08:37:44 -0500553 sync();
554
555 /* update TxQD, let RISC to send the packet */
556 offset_in = muram_readw(&pram->txqd.offset_in);
557 offset_in += sizeof(struct fm_port_bd);
558 if (offset_in >= muram_readw(&pram->txqd.bd_ring_size))
559 offset_in = 0;
560 muram_writew(&pram->txqd.offset_in, offset_in);
561 sync();
562
563 /* wait for buffer to be transmitted */
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800564 for (i = 0; muram_readw(&txbd->status) & TxBD_READY; i++) {
Kumar Gala2683c532011-04-13 08:37:44 -0500565 udelay(100);
566 if (i > 0x10000) {
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800567 printf("%s: Tx error, txbd->status = 0x%x\n",
568 dev->name, muram_readw(&txbd->status));
Kumar Gala2683c532011-04-13 08:37:44 -0500569 return 0;
570 }
571 }
572
573 /* advance the TxBD */
574 txbd++;
575 txbd_base = (struct fm_port_bd *)fm_eth->tx_bd_ring;
576 if (txbd >= (txbd_base + TX_BD_RING_SIZE))
577 txbd = txbd_base;
578 /* update current txbd */
579 fm_eth->cur_txbd = (void *)txbd;
580
581 return 1;
582}
583
Madalin Bucur248f9202020-04-23 16:25:17 +0300584static struct fm_port_bd *fm_eth_free_one(struct fm_eth *fm_eth,
585 struct fm_port_bd *rxbd)
Kumar Gala2683c532011-04-13 08:37:44 -0500586{
Kumar Gala2683c532011-04-13 08:37:44 -0500587 struct fm_port_global_pram *pram;
Madalin Bucur248f9202020-04-23 16:25:17 +0300588 struct fm_port_bd *rxbd_base;
Kumar Gala2683c532011-04-13 08:37:44 -0500589 u16 offset_out;
590
Kumar Gala2683c532011-04-13 08:37:44 -0500591 pram = fm_eth->rx_pram;
Madalin Bucur248f9202020-04-23 16:25:17 +0300592
593 /* clear the RxBDs */
594 muram_writew(&rxbd->status, RxBD_EMPTY);
595 muram_writew(&rxbd->len, 0);
596 sync();
597
598 /* advance RxBD */
599 rxbd++;
600 rxbd_base = (struct fm_port_bd *)fm_eth->rx_bd_ring;
601 if (rxbd >= (rxbd_base + RX_BD_RING_SIZE))
602 rxbd = rxbd_base;
603
604 /* update RxQD */
605 offset_out = muram_readw(&pram->rxqd.offset_out);
606 offset_out += sizeof(struct fm_port_bd);
607 if (offset_out >= muram_readw(&pram->rxqd.bd_ring_size))
608 offset_out = 0;
609 muram_writew(&pram->rxqd.offset_out, offset_out);
610 sync();
611
612 return rxbd;
613}
614
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300615static int fm_eth_recv(struct udevice *dev, int flags, uchar **packetp)
Madalin Bucur248f9202020-04-23 16:25:17 +0300616{
Simon Glass95588622020-12-22 19:30:28 -0700617 struct fm_eth *fm_eth;
618 struct fm_port_bd *rxbd;
Madalin Bucur248f9202020-04-23 16:25:17 +0300619 u32 buf_lo, buf_hi;
620 u16 status, len;
621 int ret = -1;
622 u8 *data;
623
Simon Glass95588622020-12-22 19:30:28 -0700624 fm_eth = dev_get_priv(dev);
Simon Glass95588622020-12-22 19:30:28 -0700625 rxbd = fm_eth->cur_rxbd;
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800626 status = muram_readw(&rxbd->status);
Kumar Gala2683c532011-04-13 08:37:44 -0500627
628 while (!(status & RxBD_EMPTY)) {
629 if (!(status & RxBD_ERROR)) {
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800630 buf_hi = muram_readw(&rxbd->buf_ptr_hi);
631 buf_lo = in_be32(&rxbd->buf_ptr_lo);
632 data = (u8 *)((ulong)(buf_hi << 16) << 16 | buf_lo);
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800633 len = muram_readw(&rxbd->len);
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300634 *packetp = data;
635 return len;
Kumar Gala2683c532011-04-13 08:37:44 -0500636 } else {
637 printf("%s: Rx error\n", dev->name);
Daniel Inderbitzinfdbc5c72015-07-10 14:06:02 +0200638 ret = 0;
Kumar Gala2683c532011-04-13 08:37:44 -0500639 }
640
Madalin Bucur248f9202020-04-23 16:25:17 +0300641 /* free current bd, advance to next one */
642 rxbd = fm_eth_free_one(fm_eth, rxbd);
Kumar Gala2683c532011-04-13 08:37:44 -0500643
Kumar Gala2683c532011-04-13 08:37:44 -0500644 /* read next status */
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800645 status = muram_readw(&rxbd->status);
Kumar Gala2683c532011-04-13 08:37:44 -0500646 }
647 fm_eth->cur_rxbd = (void *)rxbd;
648
Daniel Inderbitzinfdbc5c72015-07-10 14:06:02 +0200649 return ret;
Kumar Gala2683c532011-04-13 08:37:44 -0500650}
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300651
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300652static int fm_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
653{
Simon Glass95588622020-12-22 19:30:28 -0700654 struct fm_eth *fm_eth = (struct fm_eth *)dev_get_priv(dev);
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300655
656 fm_eth->cur_rxbd = fm_eth_free_one(fm_eth, fm_eth->cur_rxbd);
657
658 return 0;
659}
Kumar Gala2683c532011-04-13 08:37:44 -0500660
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300661static int fm_eth_init_mac(struct fm_eth *fm_eth, void *reg)
662{
663#ifndef CONFIG_SYS_FMAN_V3
664 void *mdio;
665#endif
666
667 fm_eth->mac = kzalloc(sizeof(*fm_eth->mac), GFP_KERNEL);
668 if (!fm_eth->mac)
669 return -ENOMEM;
670
671#ifndef CONFIG_SYS_FMAN_V3
672 mdio = fman_mdio(fm_eth->dev->parent, fm_eth->mac_type, fm_eth->num);
673 debug("MDIO %d @ %p\n", fm_eth->num, mdio);
674#endif
675
676 switch (fm_eth->mac_type) {
677#ifdef CONFIG_SYS_FMAN_V3
678 case FM_MEMAC:
679 init_memac(fm_eth->mac, reg, NULL, MAX_RXBUF_LEN);
680 break;
681#else
682 case FM_DTSEC:
683 init_dtsec(fm_eth->mac, reg, mdio, MAX_RXBUF_LEN);
684 break;
685 case FM_TGEC:
686 init_tgec(fm_eth->mac, reg, mdio, MAX_RXBUF_LEN);
687 break;
688#endif
689 }
690
691 return 0;
692}
Kumar Gala2683c532011-04-13 08:37:44 -0500693
Madalin Bucur11fa7a32020-04-23 16:25:16 +0300694static int init_phy(struct fm_eth *fm_eth)
Kumar Gala2683c532011-04-13 08:37:44 -0500695{
Shaohui Xieab687cc2015-10-26 19:47:46 +0800696#ifdef CONFIG_PHYLIB
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300697 u32 supported = PHY_GBIT_FEATURES;
Kumar Gala2683c532011-04-13 08:37:44 -0500698
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300699 if (fm_eth->type == FM_ETH_10G_E)
700 supported = PHY_10G_FEATURES;
Vladimir Oltean6caef972021-09-18 15:32:35 +0300701 if (fm_eth->enet_if == PHY_INTERFACE_MODE_2500BASEX)
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300702 supported |= SUPPORTED_2500baseX_Full;
703#endif
704
Jerome Forissieredb410b2024-09-11 11:58:18 +0200705#if (CONFIG_IS_ENABLED(MII) || CONFIG_IS_ENABLED(CMD_MII)) && \
706 !CONFIG_IS_ENABLED(BITBANGMII)
Kumar Gala2683c532011-04-13 08:37:44 -0500707 if (fm_eth->type == FM_ETH_1G_E)
Madalin Bucur11fa7a32020-04-23 16:25:16 +0300708 dtsec_init_phy(fm_eth);
Jerome Forissieredb410b2024-09-11 11:58:18 +0200709#endif
Kumar Gala2683c532011-04-13 08:37:44 -0500710
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300711#ifdef CONFIG_PHYLIB
712#ifdef CONFIG_DM_MDIO
713 fm_eth->phydev = dm_eth_phy_connect(fm_eth->dev);
714 if (!fm_eth->phydev)
715 return -ENODEV;
716#endif
717 fm_eth->phydev->advertising &= supported;
718 fm_eth->phydev->supported &= supported;
719
720 phy_config(fm_eth->phydev);
721#endif
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300722 return 0;
723}
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300724
725static int fm_eth_bind(struct udevice *dev)
726{
727 char mac_name[11];
728 u32 fm, num;
729
Simon Glassa7ece582020-12-19 10:40:14 -0700730 if (ofnode_read_u32(ofnode_get_parent(dev_ofnode(dev)), "cell-index", &fm)) {
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300731 printf("FMan node property cell-index missing\n");
732 return -EINVAL;
733 }
734
735 if (dev && dev_read_u32(dev, "cell-index", &num)) {
736 printf("FMan MAC node property cell-index missing\n");
737 return -EINVAL;
738 }
739
740 sprintf(mac_name, "fm%d-mac%d", fm + 1, num + 1);
741 device_set_name(dev, mac_name);
742
743 debug("%s - binding %s\n", __func__, mac_name);
744
745 return 0;
746}
747
748static struct udevice *fm_get_internal_mdio(struct udevice *dev)
749{
750 struct ofnode_phandle_args phandle = {.node = ofnode_null()};
751 struct udevice *mdiodev;
752
753 if (dev_read_phandle_with_args(dev, "pcsphy-handle", NULL,
754 0, 0, &phandle) ||
755 !ofnode_valid(phandle.node)) {
756 if (dev_read_phandle_with_args(dev, "tbi-handle", NULL,
757 0, 0, &phandle) ||
758 !ofnode_valid(phandle.node)) {
759 printf("Issue reading pcsphy-handle/tbi-handle for MAC %s\n",
760 dev->name);
761 return NULL;
762 }
763 }
764
765 if (uclass_get_device_by_ofnode(UCLASS_MDIO,
766 ofnode_get_parent(phandle.node),
767 &mdiodev)) {
768 printf("can't find MDIO bus for node %s\n",
769 ofnode_get_name(ofnode_get_parent(phandle.node)));
770 return NULL;
771 }
772 debug("Found internal MDIO bus %p\n", mdiodev);
773
774 return mdiodev;
775}
776
777static int fm_eth_probe(struct udevice *dev)
778{
Simon Glass95588622020-12-22 19:30:28 -0700779 struct fm_eth *fm_eth = (struct fm_eth *)dev_get_priv(dev);
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300780 struct ofnode_phandle_args args;
781 void *reg;
782 int ret, index;
783
784 debug("%s enter for dev %p fm_eth %p - %s\n", __func__, dev, fm_eth,
785 (dev) ? dev->name : "-");
786
787 if (fm_eth->dev) {
788 printf("%s already probed, exit\n", (dev) ? dev->name : "-");
789 return 0;
790 }
791
792 fm_eth->dev = dev;
793 fm_eth->fm_index = fman_id(dev->parent);
794 reg = (void *)(uintptr_t)dev_read_addr(dev);
795 fm_eth->mac_type = dev_get_driver_data(dev);
796#ifdef CONFIG_PHYLIB
Marek BehĂșnbc194772022-04-07 00:33:01 +0200797 fm_eth->enet_if = dev_read_phy_mode(dev);
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300798#else
799 fm_eth->enet_if = PHY_INTERFACE_MODE_SGMII;
800 printf("%s: warning - unable to determine interface type\n", __func__);
801#endif
802 switch (fm_eth->mac_type) {
803#ifndef CONFIG_SYS_FMAN_V3
804 case FM_TGEC:
805 fm_eth->type = FM_ETH_10G_E;
806 break;
807 case FM_DTSEC:
808#else
809 case FM_MEMAC:
810 /* default to 1G, 10G is indicated by port property in dts */
811#endif
812 fm_eth->type = FM_ETH_1G_E;
813 break;
814 }
815
816 if (dev_read_u32(dev, "cell-index", &fm_eth->num)) {
817 printf("FMan MAC node property cell-index missing\n");
818 return -EINVAL;
819 }
820
821 if (dev_read_phandle_with_args(dev, "fsl,fman-ports", NULL,
822 0, 0, &args))
823 goto ports_ref_failure;
824 index = ofnode_read_u32_default(args.node, "cell-index", 0);
825 if (index <= 0)
826 goto ports_ref_failure;
827 fm_eth->rx_port = fman_port(dev->parent, index);
828
829 if (ofnode_read_bool(args.node, "fsl,fman-10g-port"))
830 fm_eth->type = FM_ETH_10G_E;
831
832 if (dev_read_phandle_with_args(dev, "fsl,fman-ports", NULL,
833 0, 1, &args))
834 goto ports_ref_failure;
835 index = ofnode_read_u32_default(args.node, "cell-index", 0);
836 if (index <= 0)
837 goto ports_ref_failure;
838 fm_eth->tx_port = fman_port(dev->parent, index);
839
840 /* set the ethernet max receive length */
841 fm_eth->max_rx_len = MAX_RXBUF_LEN;
842
843 switch (fm_eth->enet_if) {
844 case PHY_INTERFACE_MODE_QSGMII:
845 /* all PCS blocks are accessed on one controller */
846 if (fm_eth->num != 0)
847 break;
848 case PHY_INTERFACE_MODE_SGMII:
Vladimir Oltean6caef972021-09-18 15:32:35 +0300849 case PHY_INTERFACE_MODE_2500BASEX:
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300850 fm_eth->pcs_mdio = fm_get_internal_mdio(dev);
851 break;
852 default:
853 break;
854 }
855
856 /* init global mac structure */
857 ret = fm_eth_init_mac(fm_eth, reg);
858 if (ret)
859 return ret;
860
861 /* startup the FM im */
862 ret = fm_eth_startup(fm_eth);
863
864 if (!ret)
865 ret = init_phy(fm_eth);
866
867 return ret;
868
869ports_ref_failure:
870 printf("Issue reading fsl,fman-ports for MAC %s\n", dev->name);
871 return -ENOENT;
872}
873
874static int fm_eth_remove(struct udevice *dev)
875{
Hou Zhiqianga02fc982015-10-26 19:47:45 +0800876 return 0;
Kumar Gala2683c532011-04-13 08:37:44 -0500877}
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300878
879static const struct eth_ops fm_eth_ops = {
880 .start = fm_eth_open,
881 .send = fm_eth_send,
882 .recv = fm_eth_recv,
883 .free_pkt = fm_eth_free_pkt,
884 .stop = fm_eth_halt,
885};
886
887static const struct udevice_id fm_eth_ids[] = {
888#ifdef CONFIG_SYS_FMAN_V3
889 { .compatible = "fsl,fman-memac", .data = FM_MEMAC },
890#else
891 { .compatible = "fsl,fman-dtsec", .data = FM_DTSEC },
892 { .compatible = "fsl,fman-xgec", .data = FM_TGEC },
893#endif
894 {}
895};
896
897U_BOOT_DRIVER(eth_fman) = {
898 .name = "eth_fman",
899 .id = UCLASS_ETH,
900 .of_match = fm_eth_ids,
901 .bind = fm_eth_bind,
902 .probe = fm_eth_probe,
903 .remove = fm_eth_remove,
904 .ops = &fm_eth_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700905 .priv_auto = sizeof(struct fm_eth),
Simon Glass71fa5b42020-12-03 16:55:18 -0700906 .plat_auto = sizeof(struct eth_pdata),
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300907 .flags = DM_FLAG_ALLOC_PRIV_DMA,
908};