]> git.ipfire.org Git - thirdparty/u-boot.git/blame - drivers/net/ti/am65-cpsw-nuss.c
common: Drop net.h from common header
[thirdparty/u-boot.git] / drivers / net / ti / am65-cpsw-nuss.c
CommitLineData
9d0dca11
K
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver
4 *
5 * Copyright (C) 2019, Texas Instruments, Incorporated
6 *
7 */
8
9#include <common.h>
336d4615 10#include <malloc.h>
90526e9f 11#include <asm/cache.h>
9d0dca11
K
12#include <asm/io.h>
13#include <asm/processor.h>
14#include <clk.h>
15#include <dm.h>
336d4615 16#include <dm/device_compat.h>
9d0dca11
K
17#include <dm/lists.h>
18#include <dma-uclass.h>
19#include <dm/of_access.h>
20#include <miiphy.h>
21#include <net.h>
22#include <phy.h>
23#include <power-domain.h>
24#include <linux/soc/ti/ti-udma.h>
25
26#include "cpsw_mdio.h"
27
28#define AM65_CPSW_CPSWNU_MAX_PORTS 2
29
30#define AM65_CPSW_SS_BASE 0x0
31#define AM65_CPSW_SGMII_BASE 0x100
32#define AM65_CPSW_MDIO_BASE 0xf00
33#define AM65_CPSW_XGMII_BASE 0x2100
34#define AM65_CPSW_CPSW_NU_BASE 0x20000
35#define AM65_CPSW_CPSW_NU_ALE_BASE 0x1e000
36
37#define AM65_CPSW_CPSW_NU_PORTS_OFFSET 0x1000
38#define AM65_CPSW_CPSW_NU_PORT_MACSL_OFFSET 0x330
39
40#define AM65_CPSW_MDIO_BUS_FREQ_DEF 1000000
41
42#define AM65_CPSW_CTL_REG 0x4
43#define AM65_CPSW_STAT_PORT_EN_REG 0x14
44#define AM65_CPSW_PTYPE_REG 0x18
45
46#define AM65_CPSW_CTL_REG_P0_ENABLE BIT(2)
47#define AM65_CPSW_CTL_REG_P0_TX_CRC_REMOVE BIT(13)
48#define AM65_CPSW_CTL_REG_P0_RX_PAD BIT(14)
49
50#define AM65_CPSW_P0_FLOW_ID_REG 0x8
51#define AM65_CPSW_PN_RX_MAXLEN_REG 0x24
52#define AM65_CPSW_PN_REG_SA_L 0x308
53#define AM65_CPSW_PN_REG_SA_H 0x30c
54
55#define AM65_CPSW_ALE_CTL_REG 0x8
56#define AM65_CPSW_ALE_CTL_REG_ENABLE BIT(31)
57#define AM65_CPSW_ALE_CTL_REG_RESET_TBL BIT(30)
58#define AM65_CPSW_ALE_CTL_REG_BYPASS BIT(4)
59#define AM65_CPSW_ALE_PN_CTL_REG(x) (0x40 + (x) * 4)
60#define AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD 0x3
61#define AM65_CPSW_ALE_PN_CTL_REG_MAC_ONLY BIT(11)
62
63#define AM65_CPSW_MACSL_CTL_REG 0x0
64#define AM65_CPSW_MACSL_CTL_REG_IFCTL_A BIT(15)
39821d58 65#define AM65_CPSW_MACSL_CTL_EXT_EN BIT(18)
9d0dca11
K
66#define AM65_CPSW_MACSL_CTL_REG_GIG BIT(7)
67#define AM65_CPSW_MACSL_CTL_REG_GMII_EN BIT(5)
68#define AM65_CPSW_MACSL_CTL_REG_LOOPBACK BIT(1)
69#define AM65_CPSW_MACSL_CTL_REG_FULL_DUPLEX BIT(0)
70#define AM65_CPSW_MACSL_RESET_REG 0x8
71#define AM65_CPSW_MACSL_RESET_REG_RESET BIT(0)
72#define AM65_CPSW_MACSL_STATUS_REG 0x4
73#define AM65_CPSW_MACSL_RESET_REG_PN_IDLE BIT(31)
74#define AM65_CPSW_MACSL_RESET_REG_PN_E_IDLE BIT(30)
75#define AM65_CPSW_MACSL_RESET_REG_PN_P_IDLE BIT(29)
76#define AM65_CPSW_MACSL_RESET_REG_PN_TX_IDLE BIT(28)
77#define AM65_CPSW_MACSL_RESET_REG_IDLE_MASK \
78 (AM65_CPSW_MACSL_RESET_REG_PN_IDLE | \
79 AM65_CPSW_MACSL_RESET_REG_PN_E_IDLE | \
80 AM65_CPSW_MACSL_RESET_REG_PN_P_IDLE | \
81 AM65_CPSW_MACSL_RESET_REG_PN_TX_IDLE)
82
83#define AM65_CPSW_CPPI_PKT_TYPE 0x7
84
85struct am65_cpsw_port {
86 fdt_addr_t port_base;
87 fdt_addr_t macsl_base;
88 bool disabled;
89 u32 mac_control;
90};
91
92struct am65_cpsw_common {
93 struct udevice *dev;
94 fdt_addr_t ss_base;
95 fdt_addr_t cpsw_base;
96 fdt_addr_t mdio_base;
97 fdt_addr_t ale_base;
98 fdt_addr_t gmii_sel;
99 fdt_addr_t mac_efuse;
100
101 struct clk fclk;
102 struct power_domain pwrdmn;
103
104 u32 port_num;
105 struct am65_cpsw_port ports[AM65_CPSW_CPSWNU_MAX_PORTS];
9d0dca11
K
106
107 struct mii_dev *bus;
108 u32 bus_freq;
109
110 struct dma dma_tx;
111 struct dma dma_rx;
112 u32 rx_next;
113 u32 rx_pend;
114 bool started;
115};
116
117struct am65_cpsw_priv {
118 struct udevice *dev;
119 struct am65_cpsw_common *cpsw_common;
120 u32 port_id;
121
122 struct phy_device *phydev;
123 bool has_phy;
124 ofnode phy_node;
125 u32 phy_addr;
126};
127
128#ifdef PKTSIZE_ALIGN
129#define UDMA_RX_BUF_SIZE PKTSIZE_ALIGN
130#else
131#define UDMA_RX_BUF_SIZE ALIGN(1522, ARCH_DMA_MINALIGN)
132#endif
133
134#ifdef PKTBUFSRX
135#define UDMA_RX_DESC_NUM PKTBUFSRX
136#else
137#define UDMA_RX_DESC_NUM 4
138#endif
139
140#define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \
141 ((mac)[2] << 16) | ((mac)[3] << 24))
142#define mac_lo(mac) (((mac)[4] << 0) | ((mac)[5] << 8))
143
144static void am65_cpsw_set_sl_mac(struct am65_cpsw_port *slave,
145 unsigned char *addr)
146{
147 writel(mac_hi(addr),
148 slave->port_base + AM65_CPSW_PN_REG_SA_H);
149 writel(mac_lo(addr),
150 slave->port_base + AM65_CPSW_PN_REG_SA_L);
151}
152
153int am65_cpsw_macsl_reset(struct am65_cpsw_port *slave)
154{
155 u32 i = 100;
156
157 /* Set the soft reset bit */
158 writel(AM65_CPSW_MACSL_RESET_REG_RESET,
159 slave->macsl_base + AM65_CPSW_MACSL_RESET_REG);
160
161 while ((readl(slave->macsl_base + AM65_CPSW_MACSL_RESET_REG) &
162 AM65_CPSW_MACSL_RESET_REG_RESET) && i--)
163 cpu_relax();
164
165 /* Timeout on the reset */
166 return i;
167}
168
169static int am65_cpsw_macsl_wait_for_idle(struct am65_cpsw_port *slave)
170{
171 u32 i = 100;
172
173 while ((readl(slave->macsl_base + AM65_CPSW_MACSL_STATUS_REG) &
174 AM65_CPSW_MACSL_RESET_REG_IDLE_MASK) && i--)
175 cpu_relax();
176
177 return i;
178}
179
180static int am65_cpsw_update_link(struct am65_cpsw_priv *priv)
181{
182 struct am65_cpsw_common *common = priv->cpsw_common;
183 struct am65_cpsw_port *port = &common->ports[priv->port_id];
184 struct phy_device *phy = priv->phydev;
185 u32 mac_control = 0;
186
187 if (phy->link) { /* link up */
188 mac_control = /*AM65_CPSW_MACSL_CTL_REG_LOOPBACK |*/
189 AM65_CPSW_MACSL_CTL_REG_GMII_EN;
190 if (phy->speed == 1000)
191 mac_control |= AM65_CPSW_MACSL_CTL_REG_GIG;
39821d58
MK
192 if (phy->speed == 10 && phy_interface_is_rgmii(phy))
193 /* Can be used with in band mode only */
194 mac_control |= AM65_CPSW_MACSL_CTL_EXT_EN;
9d0dca11
K
195 if (phy->duplex == DUPLEX_FULL)
196 mac_control |= AM65_CPSW_MACSL_CTL_REG_FULL_DUPLEX;
197 if (phy->speed == 100)
198 mac_control |= AM65_CPSW_MACSL_CTL_REG_IFCTL_A;
199 }
200
201 if (mac_control == port->mac_control)
202 goto out;
203
204 if (mac_control) {
205 printf("link up on port %d, speed %d, %s duplex\n",
206 priv->port_id, phy->speed,
207 (phy->duplex == DUPLEX_FULL) ? "full" : "half");
208 } else {
209 printf("link down on port %d\n", priv->port_id);
210 }
211
212 writel(mac_control, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
213 port->mac_control = mac_control;
214
215out:
216 return phy->link;
217}
218
219#define AM65_GMII_SEL_MODE_MII 0
220#define AM65_GMII_SEL_MODE_RMII 1
221#define AM65_GMII_SEL_MODE_RGMII 2
222
223#define AM65_GMII_SEL_RGMII_IDMODE BIT(4)
224
225static void am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
226 phy_interface_t phy_mode, int slave)
227{
228 struct am65_cpsw_common *common = priv->cpsw_common;
229 u32 reg;
230 u32 mode = 0;
231 bool rgmii_id = false;
232
233 reg = readl(common->gmii_sel);
234
235 dev_dbg(common->dev, "old gmii_sel: %08x\n", reg);
236
237 switch (phy_mode) {
238 case PHY_INTERFACE_MODE_RMII:
239 mode = AM65_GMII_SEL_MODE_RMII;
240 break;
241
242 case PHY_INTERFACE_MODE_RGMII:
da6a728e 243 case PHY_INTERFACE_MODE_RGMII_RXID:
9d0dca11
K
244 mode = AM65_GMII_SEL_MODE_RGMII;
245 break;
246
247 case PHY_INTERFACE_MODE_RGMII_ID:
9d0dca11
K
248 case PHY_INTERFACE_MODE_RGMII_TXID:
249 mode = AM65_GMII_SEL_MODE_RGMII;
250 rgmii_id = true;
251 break;
252
253 default:
254 dev_warn(common->dev,
255 "Unsupported PHY mode: %u. Defaulting to MII.\n",
256 phy_mode);
257 /* fallthrough */
258 case PHY_INTERFACE_MODE_MII:
259 mode = AM65_GMII_SEL_MODE_MII;
260 break;
261 };
262
263 if (rgmii_id)
264 mode |= AM65_GMII_SEL_RGMII_IDMODE;
265
266 reg = mode;
267 dev_dbg(common->dev, "gmii_sel PHY mode: %u, new gmii_sel: %08x\n",
268 phy_mode, reg);
269 writel(reg, common->gmii_sel);
270
271 reg = readl(common->gmii_sel);
272 if (reg != mode)
273 dev_err(common->dev,
274 "gmii_sel PHY mode NOT SET!: requested: %08x, gmii_sel: %08x\n",
275 mode, reg);
276}
277
278static int am65_cpsw_start(struct udevice *dev)
279{
280 struct eth_pdata *pdata = dev_get_platdata(dev);
281 struct am65_cpsw_priv *priv = dev_get_priv(dev);
282 struct am65_cpsw_common *common = priv->cpsw_common;
283 struct am65_cpsw_port *port = &common->ports[priv->port_id];
284 struct am65_cpsw_port *port0 = &common->ports[0];
461a290c 285 struct ti_udma_drv_chan_cfg_data *dma_rx_cfg_data;
9d0dca11
K
286 int ret, i;
287
288 ret = power_domain_on(&common->pwrdmn);
289 if (ret) {
290 dev_err(dev, "power_domain_on() failed %d\n", ret);
291 goto out;
292 }
293
294 ret = clk_enable(&common->fclk);
295 if (ret) {
296 dev_err(dev, "clk enabled failed %d\n", ret);
297 goto err_off_pwrdm;
298 }
299
300 common->rx_next = 0;
301 common->rx_pend = 0;
302 ret = dma_get_by_name(common->dev, "tx0", &common->dma_tx);
303 if (ret) {
304 dev_err(dev, "TX dma get failed %d\n", ret);
305 goto err_off_clk;
306 }
307 ret = dma_get_by_name(common->dev, "rx", &common->dma_rx);
308 if (ret) {
309 dev_err(dev, "RX dma get failed %d\n", ret);
310 goto err_free_tx;
311 }
312
313 for (i = 0; i < UDMA_RX_DESC_NUM; i++) {
314 ret = dma_prepare_rcv_buf(&common->dma_rx,
315 net_rx_packets[i],
316 UDMA_RX_BUF_SIZE);
317 if (ret) {
318 dev_err(dev, "RX dma add buf failed %d\n", ret);
319 goto err_free_tx;
320 }
321 }
322
323 ret = dma_enable(&common->dma_tx);
324 if (ret) {
325 dev_err(dev, "TX dma_enable failed %d\n", ret);
326 goto err_free_rx;
327 }
328 ret = dma_enable(&common->dma_rx);
329 if (ret) {
330 dev_err(dev, "RX dma_enable failed %d\n", ret);
331 goto err_dis_tx;
332 }
333
334 /* Control register */
335 writel(AM65_CPSW_CTL_REG_P0_ENABLE |
336 AM65_CPSW_CTL_REG_P0_TX_CRC_REMOVE |
337 AM65_CPSW_CTL_REG_P0_RX_PAD,
338 common->cpsw_base + AM65_CPSW_CTL_REG);
339
340 /* disable priority elevation */
341 writel(0, common->cpsw_base + AM65_CPSW_PTYPE_REG);
342
343 /* enable statistics */
344 writel(BIT(0) | BIT(priv->port_id),
345 common->cpsw_base + AM65_CPSW_STAT_PORT_EN_REG);
346
347 /* Port 0 length register */
348 writel(PKTSIZE_ALIGN, port0->port_base + AM65_CPSW_PN_RX_MAXLEN_REG);
349
350 /* set base flow_id */
461a290c
VR
351 dma_get_cfg(&common->dma_rx, 0, (void **)&dma_rx_cfg_data);
352 writel(dma_rx_cfg_data->flow_id_base,
9d0dca11 353 port0->port_base + AM65_CPSW_P0_FLOW_ID_REG);
461a290c
VR
354 dev_info(dev, "K3 CPSW: rflow_id_base: %u\n",
355 dma_rx_cfg_data->flow_id_base);
9d0dca11
K
356
357 /* Reset and enable the ALE */
358 writel(AM65_CPSW_ALE_CTL_REG_ENABLE | AM65_CPSW_ALE_CTL_REG_RESET_TBL |
359 AM65_CPSW_ALE_CTL_REG_BYPASS,
360 common->ale_base + AM65_CPSW_ALE_CTL_REG);
361
362 /* port 0 put into forward mode */
363 writel(AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD,
364 common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
365
366 /* PORT x configuration */
367
368 /* Port x Max length register */
369 writel(PKTSIZE_ALIGN, port->port_base + AM65_CPSW_PN_RX_MAXLEN_REG);
370
371 /* Port x set mac */
372 am65_cpsw_set_sl_mac(port, pdata->enetaddr);
373
374 /* Port x ALE: mac_only, Forwarding */
375 writel(AM65_CPSW_ALE_PN_CTL_REG_MAC_ONLY |
376 AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD,
377 common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
378
379 port->mac_control = 0;
380 if (!am65_cpsw_macsl_reset(port)) {
381 dev_err(dev, "mac_sl reset failed\n");
382 ret = -EFAULT;
383 goto err_dis_rx;
384 }
385
386 ret = phy_startup(priv->phydev);
387 if (ret) {
388 dev_err(dev, "phy_startup failed\n");
389 goto err_dis_rx;
390 }
391
392 ret = am65_cpsw_update_link(priv);
393 if (!ret) {
394 ret = -ENODEV;
395 goto err_phy_shutdown;
396 }
397
398 common->started = true;
399
400 return 0;
401
402err_phy_shutdown:
403 phy_shutdown(priv->phydev);
404err_dis_rx:
405 /* disable ports */
406 writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
407 writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
408 if (!am65_cpsw_macsl_wait_for_idle(port))
409 dev_err(dev, "mac_sl idle timeout\n");
410 writel(0, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
411 writel(0, common->ale_base + AM65_CPSW_ALE_CTL_REG);
412 writel(0, common->cpsw_base + AM65_CPSW_CTL_REG);
413
414 dma_disable(&common->dma_rx);
415err_dis_tx:
416 dma_disable(&common->dma_tx);
417err_free_rx:
418 dma_free(&common->dma_rx);
419err_free_tx:
420 dma_free(&common->dma_tx);
421err_off_clk:
422 clk_disable(&common->fclk);
423err_off_pwrdm:
424 power_domain_off(&common->pwrdmn);
425out:
426 dev_err(dev, "%s end error\n", __func__);
427
428 return ret;
429}
430
431static int am65_cpsw_send(struct udevice *dev, void *packet, int length)
432{
433 struct am65_cpsw_priv *priv = dev_get_priv(dev);
434 struct am65_cpsw_common *common = priv->cpsw_common;
435 struct ti_udma_drv_packet_data packet_data;
436 int ret;
437
438 packet_data.pkt_type = AM65_CPSW_CPPI_PKT_TYPE;
439 packet_data.dest_tag = priv->port_id;
440 ret = dma_send(&common->dma_tx, packet, length, &packet_data);
441 if (ret) {
442 dev_err(dev, "TX dma_send failed %d\n", ret);
443 return ret;
444 }
445
446 return 0;
447}
448
449static int am65_cpsw_recv(struct udevice *dev, int flags, uchar **packetp)
450{
451 struct am65_cpsw_priv *priv = dev_get_priv(dev);
452 struct am65_cpsw_common *common = priv->cpsw_common;
453
454 /* try to receive a new packet */
455 return dma_receive(&common->dma_rx, (void **)packetp, NULL);
456}
457
458static int am65_cpsw_free_pkt(struct udevice *dev, uchar *packet, int length)
459{
460 struct am65_cpsw_priv *priv = dev_get_priv(dev);
461 struct am65_cpsw_common *common = priv->cpsw_common;
462 int ret;
463
464 if (length > 0) {
465 u32 pkt = common->rx_next % UDMA_RX_DESC_NUM;
466
467 ret = dma_prepare_rcv_buf(&common->dma_rx,
468 net_rx_packets[pkt],
469 UDMA_RX_BUF_SIZE);
470 if (ret)
471 dev_err(dev, "RX dma free_pkt failed %d\n", ret);
472 common->rx_next++;
473 }
474
475 return 0;
476}
477
478static void am65_cpsw_stop(struct udevice *dev)
479{
480 struct am65_cpsw_priv *priv = dev_get_priv(dev);
481 struct am65_cpsw_common *common = priv->cpsw_common;
482 struct am65_cpsw_port *port = &common->ports[priv->port_id];
483
484 if (!common->started)
485 return;
486
487 phy_shutdown(priv->phydev);
488
489 writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
490 writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
491 if (!am65_cpsw_macsl_wait_for_idle(port))
492 dev_err(dev, "mac_sl idle timeout\n");
493 writel(0, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
494 writel(0, common->ale_base + AM65_CPSW_ALE_CTL_REG);
495 writel(0, common->cpsw_base + AM65_CPSW_CTL_REG);
496
497 dma_disable(&common->dma_tx);
498 dma_free(&common->dma_tx);
499
500 dma_disable(&common->dma_rx);
501 dma_free(&common->dma_rx);
502
503 common->started = false;
504}
505
506static int am65_cpsw_read_rom_hwaddr(struct udevice *dev)
507{
508 struct am65_cpsw_priv *priv = dev_get_priv(dev);
509 struct am65_cpsw_common *common = priv->cpsw_common;
510 struct eth_pdata *pdata = dev_get_platdata(dev);
511 u32 mac_hi, mac_lo;
512
513 if (common->mac_efuse == FDT_ADDR_T_NONE)
514 return -1;
515
516 mac_lo = readl(common->mac_efuse);
517 mac_hi = readl(common->mac_efuse + 4);
518 pdata->enetaddr[0] = (mac_hi >> 8) & 0xff;
519 pdata->enetaddr[1] = mac_hi & 0xff;
520 pdata->enetaddr[2] = (mac_lo >> 24) & 0xff;
521 pdata->enetaddr[3] = (mac_lo >> 16) & 0xff;
522 pdata->enetaddr[4] = (mac_lo >> 8) & 0xff;
523 pdata->enetaddr[5] = mac_lo & 0xff;
524
525 return 0;
526}
527
528static const struct eth_ops am65_cpsw_ops = {
529 .start = am65_cpsw_start,
530 .send = am65_cpsw_send,
531 .recv = am65_cpsw_recv,
532 .free_pkt = am65_cpsw_free_pkt,
533 .stop = am65_cpsw_stop,
534 .read_rom_hwaddr = am65_cpsw_read_rom_hwaddr,
535};
536
537static int am65_cpsw_mdio_init(struct udevice *dev)
538{
539 struct am65_cpsw_priv *priv = dev_get_priv(dev);
540 struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
541
542 if (!priv->has_phy || cpsw_common->bus)
543 return 0;
544
545 cpsw_common->bus = cpsw_mdio_init(dev->name,
546 cpsw_common->mdio_base,
547 cpsw_common->bus_freq,
548 clk_get_rate(&cpsw_common->fclk));
549 if (!cpsw_common->bus)
550 return -EFAULT;
551
552 return 0;
553}
554
555static int am65_cpsw_phy_init(struct udevice *dev)
556{
557 struct am65_cpsw_priv *priv = dev_get_priv(dev);
558 struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
559 struct eth_pdata *pdata = dev_get_platdata(dev);
560 struct phy_device *phydev;
561 u32 supported = PHY_GBIT_FEATURES;
562 int ret;
563
564 phydev = phy_connect(cpsw_common->bus,
565 priv->phy_addr,
566 priv->dev,
567 pdata->phy_interface);
568
569 if (!phydev) {
570 dev_err(dev, "phy_connect() failed\n");
571 return -ENODEV;
572 }
573
574 phydev->supported &= supported;
575 if (pdata->max_speed) {
576 ret = phy_set_supported(phydev, pdata->max_speed);
577 if (ret)
578 return ret;
579 }
580 phydev->advertising = phydev->supported;
581
582 if (ofnode_valid(priv->phy_node))
583 phydev->node = priv->phy_node;
584
585 priv->phydev = phydev;
586 ret = phy_config(phydev);
587 if (ret < 0)
588 pr_err("phy_config() failed: %d", ret);
589
590 return ret;
591}
592
593static int am65_cpsw_ofdata_parse_phy(struct udevice *dev, ofnode port_np)
594{
595 struct eth_pdata *pdata = dev_get_platdata(dev);
596 struct am65_cpsw_priv *priv = dev_get_priv(dev);
597 struct ofnode_phandle_args out_args;
598 const char *phy_mode;
599 int ret = 0;
600
601 phy_mode = ofnode_read_string(port_np, "phy-mode");
602 if (phy_mode) {
603 pdata->phy_interface =
604 phy_get_interface_by_name(phy_mode);
605 if (pdata->phy_interface == -1) {
606 dev_err(dev, "Invalid PHY mode '%s', port %u\n",
607 phy_mode, priv->port_id);
608 ret = -EINVAL;
609 goto out;
610 }
611 }
612
613 ofnode_read_u32(port_np, "max-speed", (u32 *)&pdata->max_speed);
614 if (pdata->max_speed)
615 dev_err(dev, "Port %u speed froced to %uMbit\n",
616 priv->port_id, pdata->max_speed);
617
618 priv->has_phy = true;
619 ret = ofnode_parse_phandle_with_args(port_np, "phy-handle",
620 NULL, 0, 0, &out_args);
621 if (ret) {
622 dev_err(dev, "can't parse phy-handle port %u (%d)\n",
623 priv->port_id, ret);
624 priv->has_phy = false;
625 ret = 0;
626 }
627
628 priv->phy_node = out_args.node;
629 if (priv->has_phy) {
630 ret = ofnode_read_u32(priv->phy_node, "reg", &priv->phy_addr);
631 if (ret) {
632 dev_err(dev, "failed to get phy_addr port %u (%d)\n",
633 priv->port_id, ret);
634 goto out;
635 }
636 }
637
638out:
639 return ret;
640}
641
642static int am65_cpsw_probe_cpsw(struct udevice *dev)
643{
644 struct am65_cpsw_priv *priv = dev_get_priv(dev);
645 struct eth_pdata *pdata = dev_get_platdata(dev);
646 struct am65_cpsw_common *cpsw_common;
647 ofnode ports_np, node;
648 int ret, i;
649
650 priv->dev = dev;
651
652 cpsw_common = calloc(1, sizeof(*priv->cpsw_common));
653 if (!cpsw_common)
654 return -ENOMEM;
655 priv->cpsw_common = cpsw_common;
656
657 cpsw_common->dev = dev;
658 cpsw_common->ss_base = dev_read_addr(dev);
659 if (cpsw_common->ss_base == FDT_ADDR_T_NONE)
660 return -EINVAL;
661 cpsw_common->mac_efuse = devfdt_get_addr_name(dev, "mac_efuse");
662 /* no err check - optional */
663
664 ret = power_domain_get_by_index(dev, &cpsw_common->pwrdmn, 0);
665 if (ret) {
666 dev_err(dev, "failed to get pwrdmn: %d\n", ret);
667 return ret;
668 }
669
670 ret = clk_get_by_name(dev, "fck", &cpsw_common->fclk);
671 if (ret) {
672 power_domain_free(&cpsw_common->pwrdmn);
673 dev_err(dev, "failed to get clock %d\n", ret);
674 return ret;
675 }
676
677 cpsw_common->cpsw_base = cpsw_common->ss_base + AM65_CPSW_CPSW_NU_BASE;
678 cpsw_common->ale_base = cpsw_common->cpsw_base +
679 AM65_CPSW_CPSW_NU_ALE_BASE;
680 cpsw_common->mdio_base = cpsw_common->ss_base + AM65_CPSW_MDIO_BASE;
681
9d0dca11
K
682 ports_np = dev_read_subnode(dev, "ports");
683 if (!ofnode_valid(ports_np)) {
684 ret = -ENOENT;
685 goto out;
686 }
687
688 ofnode_for_each_subnode(node, ports_np) {
689 const char *node_name;
690 u32 port_id;
691 bool disabled;
692
693 node_name = ofnode_get_name(node);
694
695 disabled = !ofnode_is_available(node);
696
697 ret = ofnode_read_u32(node, "reg", &port_id);
698 if (ret) {
699 dev_err(dev, "%s: failed to get port_id (%d)\n",
700 node_name, ret);
701 goto out;
702 }
703
704 if (port_id >= AM65_CPSW_CPSWNU_MAX_PORTS) {
705 dev_err(dev, "%s: invalid port_id (%d)\n",
706 node_name, port_id);
707 ret = -EINVAL;
708 goto out;
709 }
710 cpsw_common->port_num++;
711
712 if (!port_id)
713 continue;
714
715 priv->port_id = port_id;
716 cpsw_common->ports[port_id].disabled = disabled;
717 if (disabled)
718 continue;
719
720 ret = am65_cpsw_ofdata_parse_phy(dev, node);
721 if (ret)
722 goto out;
723 }
724
725 for (i = 0; i < AM65_CPSW_CPSWNU_MAX_PORTS; i++) {
726 struct am65_cpsw_port *port = &cpsw_common->ports[i];
727
728 port->port_base = cpsw_common->cpsw_base +
729 AM65_CPSW_CPSW_NU_PORTS_OFFSET +
730 (i * AM65_CPSW_CPSW_NU_PORTS_OFFSET);
731 port->macsl_base = port->port_base +
732 AM65_CPSW_CPSW_NU_PORT_MACSL_OFFSET;
733 }
734
735 node = dev_read_subnode(dev, "cpsw-phy-sel");
736 if (!ofnode_valid(node)) {
737 dev_err(dev, "can't find cpsw-phy-sel\n");
738 ret = -ENOENT;
739 goto out;
740 }
741
742 cpsw_common->gmii_sel = ofnode_get_addr(node);
743 if (cpsw_common->gmii_sel == FDT_ADDR_T_NONE) {
744 dev_err(dev, "failed to get gmii_sel base\n");
745 goto out;
746 }
747
748 node = dev_read_subnode(dev, "mdio");
749 if (!ofnode_valid(node)) {
750 dev_err(dev, "can't find mdio\n");
751 ret = -ENOENT;
752 goto out;
753 }
754
755 cpsw_common->bus_freq =
756 dev_read_u32_default(dev, "bus_freq",
757 AM65_CPSW_MDIO_BUS_FREQ_DEF);
758
759 am65_cpsw_gmii_sel_k3(priv, pdata->phy_interface, priv->port_id);
760
761 ret = am65_cpsw_mdio_init(dev);
762 if (ret)
763 goto out;
764
765 ret = am65_cpsw_phy_init(dev);
766 if (ret)
767 goto out;
768
461a290c 769 dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u mdio_freq:%u\n",
9d0dca11
K
770 readl(cpsw_common->ss_base),
771 readl(cpsw_common->cpsw_base),
772 readl(cpsw_common->ale_base),
773 cpsw_common->port_num,
9d0dca11
K
774 cpsw_common->bus_freq);
775
776out:
777 clk_free(&cpsw_common->fclk);
778 power_domain_free(&cpsw_common->pwrdmn);
779 return ret;
780}
781
782static const struct udevice_id am65_cpsw_nuss_ids[] = {
783 { .compatible = "ti,am654-cpsw-nuss" },
382c0c62 784 { .compatible = "ti,j721e-cpsw-nuss" },
9d0dca11
K
785 { }
786};
787
788U_BOOT_DRIVER(am65_cpsw_nuss_slave) = {
789 .name = "am65_cpsw_nuss_slave",
790 .id = UCLASS_ETH,
791 .of_match = am65_cpsw_nuss_ids,
792 .probe = am65_cpsw_probe_cpsw,
793 .ops = &am65_cpsw_ops,
794 .priv_auto_alloc_size = sizeof(struct am65_cpsw_priv),
795 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
796 .flags = DM_FLAG_ALLOC_PRIV_DMA,
797};