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