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