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