blob: b5dfa8bd914196a222af9f9ef43e2926797e9c57 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Sergey Kubushyne8f39122007-08-10 20:26:18 +02002/*
3 * Ethernet driver for TI TMS320DM644x (DaVinci) chips.
4 *
5 * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
6 *
7 * Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright
8 * follows:
9 *
10 * ----------------------------------------------------------------------------
11 *
12 * dm644x_emac.c
13 *
14 * TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM
15 *
16 * Copyright (C) 2005 Texas Instruments.
17 *
18 * ----------------------------------------------------------------------------
19 *
Sergey Kubushyne8f39122007-08-10 20:26:18 +020020 * Modifications:
21 * ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot.
22 * ver 1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors
Sergey Kubushyne8f39122007-08-10 20:26:18 +020023 */
24#include <common.h>
25#include <command.h>
Simon Glass63334482019-11-14 12:57:39 -070026#include <cpu_func.h>
Sergey Kubushyne8f39122007-08-10 20:26:18 +020027#include <net.h>
28#include <miiphy.h>
Ben Warren5301bbf2009-05-26 00:34:07 -070029#include <malloc.h>
Simon Glass274e0b02020-05-10 11:39:56 -060030#include <asm/cache.h>
Ilya Yanokff672762011-11-28 06:37:33 +000031#include <linux/compiler.h>
Sergey Kubushyne8f39122007-08-10 20:26:18 +020032#include <asm/arch/emac_defs.h>
Nick Thompsond5ee6f62009-12-18 13:33:07 +000033#include <asm/io.h>
Ilya Yanok5f732f72011-11-28 06:37:29 +000034#include "davinci_emac.h"
Sergey Kubushyne8f39122007-08-10 20:26:18 +020035
Sergey Kubushyne8f39122007-08-10 20:26:18 +020036unsigned int emac_dbg = 0;
37#define debug_emac(fmt,args...) if (emac_dbg) printf(fmt,##args)
38
Ilya Yanok518036e2011-11-28 06:37:30 +000039#ifdef EMAC_HW_RAM_ADDR
40static inline unsigned long BD_TO_HW(unsigned long x)
41{
42 if (x == 0)
43 return 0;
44
45 return x - EMAC_WRAPPER_RAM_ADDR + EMAC_HW_RAM_ADDR;
46}
47
48static inline unsigned long HW_TO_BD(unsigned long x)
49{
50 if (x == 0)
51 return 0;
52
53 return x - EMAC_HW_RAM_ADDR + EMAC_WRAPPER_RAM_ADDR;
54}
55#else
56#define BD_TO_HW(x) (x)
57#define HW_TO_BD(x) (x)
58#endif
59
Nick Thompsond5ee6f62009-12-18 13:33:07 +000060#ifdef DAVINCI_EMAC_GIG_ENABLE
Manjunath Hadli5b5260e2011-10-13 03:40:55 +000061#define emac_gigabit_enable(phy_addr) davinci_eth_gigabit_enable(phy_addr)
Nick Thompsond5ee6f62009-12-18 13:33:07 +000062#else
Manjunath Hadli5b5260e2011-10-13 03:40:55 +000063#define emac_gigabit_enable(phy_addr) /* no gigabit to enable */
Nick Thompsond5ee6f62009-12-18 13:33:07 +000064#endif
65
Heiko Schocher3e806132011-11-01 20:00:27 +000066#if !defined(CONFIG_SYS_EMAC_TI_CLKDIV)
67#define CONFIG_SYS_EMAC_TI_CLKDIV ((EMAC_MDIO_BUS_FREQ / \
68 EMAC_MDIO_CLOCK_FREQ) - 1)
69#endif
70
Sandeep Paulraj4b26f052008-08-31 00:39:46 +020071static void davinci_eth_mdio_enable(void);
Sergey Kubushyne8f39122007-08-10 20:26:18 +020072
73static int gen_init_phy(int phy_addr);
74static int gen_is_phy_connected(int phy_addr);
75static int gen_get_link_speed(int phy_addr);
76static int gen_auto_negotiate(int phy_addr);
77
Sergey Kubushyne8f39122007-08-10 20:26:18 +020078void eth_mdio_enable(void)
79{
Sandeep Paulraj4b26f052008-08-31 00:39:46 +020080 davinci_eth_mdio_enable();
Sergey Kubushyne8f39122007-08-10 20:26:18 +020081}
Sergey Kubushyne8f39122007-08-10 20:26:18 +020082
Sergey Kubushyne8f39122007-08-10 20:26:18 +020083/* EMAC Addresses */
84static volatile emac_regs *adap_emac = (emac_regs *)EMAC_BASE_ADDR;
85static volatile ewrap_regs *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR;
86static volatile mdio_regs *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR;
87
88/* EMAC descriptors */
89static volatile emac_desc *emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE);
90static volatile emac_desc *emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE);
91static volatile emac_desc *emac_rx_active_head = 0;
92static volatile emac_desc *emac_rx_active_tail = 0;
93static int emac_rx_queue_active = 0;
94
95/* Receive packet buffers */
Ilya Yanokff672762011-11-28 06:37:33 +000096static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * EMAC_RXBUF_SIZE]
97 __aligned(ARCH_DMA_MINALIGN);
Sergey Kubushyne8f39122007-08-10 20:26:18 +020098
Heiko Schocher7d037f72011-11-15 10:00:04 -050099#ifndef CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT
100#define CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT 3
101#endif
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000102
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200103/* PHY address for a discovered PHY (0xff - not found) */
Heiko Schocher7d037f72011-11-15 10:00:04 -0500104static u_int8_t active_phy_addr[CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT];
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200105
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000106/* number of PHY found active */
107static u_int8_t num_phy;
108
Heiko Schocher7d037f72011-11-15 10:00:04 -0500109phy_t phy[CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT];
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200110
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200111static int davinci_emac_write_hwaddr(struct udevice *dev)
Ben Gardiner1fb49e32010-09-23 09:58:43 -0400112{
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200113 struct eth_pdata *pdata = dev_get_platdata(dev);
Ben Gardiner1fb49e32010-09-23 09:58:43 -0400114 unsigned long mac_hi;
115 unsigned long mac_lo;
116
117 /*
118 * Set MAC Addresses & Init multicast Hash to 0 (disable any multicast
119 * receive)
120 * Using channel 0 only - other channels are disabled
121 * */
122 writel(0, &adap_emac->MACINDEX);
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200123 mac_hi = (pdata->enetaddr[3] << 24) |
124 (pdata->enetaddr[2] << 16) |
125 (pdata->enetaddr[1] << 8) |
126 (pdata->enetaddr[0]);
127 mac_lo = (pdata->enetaddr[5] << 8) |
128 (pdata->enetaddr[4]);
Ben Gardiner1fb49e32010-09-23 09:58:43 -0400129
130 writel(mac_hi, &adap_emac->MACADDRHI);
131#if defined(DAVINCI_EMAC_VERSION2)
132 writel(mac_lo | EMAC_MAC_ADDR_IS_VALID | EMAC_MAC_ADDR_MATCH,
133 &adap_emac->MACADDRLO);
134#else
135 writel(mac_lo, &adap_emac->MACADDRLO);
136#endif
137
138 writel(0, &adap_emac->MACHASH1);
139 writel(0, &adap_emac->MACHASH2);
140
141 /* Set source MAC address - REQUIRED */
142 writel(mac_hi, &adap_emac->MACSRCADDRHI);
143 writel(mac_lo, &adap_emac->MACSRCADDRLO);
144
145
146 return 0;
147}
148
Sandeep Paulraj4b26f052008-08-31 00:39:46 +0200149static void davinci_eth_mdio_enable(void)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200150{
151 u_int32_t clkdiv;
152
Heiko Schocher3e806132011-11-01 20:00:27 +0000153 clkdiv = CONFIG_SYS_EMAC_TI_CLKDIV;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200154
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000155 writel((clkdiv & 0xff) |
156 MDIO_CONTROL_ENABLE |
157 MDIO_CONTROL_FAULT |
158 MDIO_CONTROL_FAULT_ENABLE,
159 &adap_mdio->CONTROL);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200160
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000161 while (readl(&adap_mdio->CONTROL) & MDIO_CONTROL_IDLE)
162 ;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200163}
164
165/*
166 * Tries to find an active connected PHY. Returns 1 if address if found.
167 * If no active PHY (or more than one PHY) found returns 0.
168 * Sets active_phy_addr variable.
169 */
Sandeep Paulraj4b26f052008-08-31 00:39:46 +0200170static int davinci_eth_phy_detect(void)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200171{
172 u_int32_t phy_act_state;
173 int i;
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000174 int j;
175 unsigned int count = 0;
176
Heiko Schocher7d037f72011-11-15 10:00:04 -0500177 for (i = 0; i < CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT; i++)
178 active_phy_addr[i] = 0xff;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200179
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000180 udelay(1000);
181 phy_act_state = readl(&adap_mdio->ALIVE);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200182
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000183 if (phy_act_state == 0)
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000184 return 0; /* No active PHYs */
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200185
Sandeep Paulraj4b26f052008-08-31 00:39:46 +0200186 debug_emac("davinci_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200187
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000188 for (i = 0, j = 0; i < 32; i++)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200189 if (phy_act_state & (1 << i)) {
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000190 count++;
Prabhakar Lad60289fe2011-11-17 02:53:23 +0000191 if (count <= CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT) {
Heiko Schocher7d037f72011-11-15 10:00:04 -0500192 active_phy_addr[j++] = i;
193 } else {
194 printf("%s: to many PHYs detected.\n",
195 __func__);
196 count = 0;
197 break;
198 }
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200199 }
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200200
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000201 num_phy = count;
202
203 return count;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200204}
205
206
207/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
Sandeep Paulraj4b26f052008-08-31 00:39:46 +0200208int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200209{
210 int tmp;
211
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000212 while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
213 ;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200214
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000215 writel(MDIO_USERACCESS0_GO |
216 MDIO_USERACCESS0_WRITE_READ |
217 ((reg_num & 0x1f) << 21) |
218 ((phy_addr & 0x1f) << 16),
219 &adap_mdio->USERACCESS0);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200220
221 /* Wait for command to complete */
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000222 while ((tmp = readl(&adap_mdio->USERACCESS0)) & MDIO_USERACCESS0_GO)
223 ;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200224
225 if (tmp & MDIO_USERACCESS0_ACK) {
226 *data = tmp & 0xffff;
karl beldan05d06982016-08-20 08:56:53 +0000227 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200228 }
229
karl beldan05d06982016-08-20 08:56:53 +0000230 return 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200231}
232
233/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
Sandeep Paulraj4b26f052008-08-31 00:39:46 +0200234int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200235{
236
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000237 while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
238 ;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200239
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000240 writel(MDIO_USERACCESS0_GO |
241 MDIO_USERACCESS0_WRITE_WRITE |
242 ((reg_num & 0x1f) << 21) |
243 ((phy_addr & 0x1f) << 16) |
244 (data & 0xffff),
245 &adap_mdio->USERACCESS0);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200246
247 /* Wait for command to complete */
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000248 while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
249 ;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200250
karl beldan05d06982016-08-20 08:56:53 +0000251 return 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200252}
253
254/* PHY functions for a generic PHY */
255static int gen_init_phy(int phy_addr)
256{
257 int ret = 1;
258
259 if (gen_get_link_speed(phy_addr)) {
260 /* Try another time */
261 ret = gen_get_link_speed(phy_addr);
262 }
263
264 return(ret);
265}
266
267static int gen_is_phy_connected(int phy_addr)
268{
269 u_int16_t dummy;
270
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000271 return davinci_eth_phy_read(phy_addr, MII_PHYSID1, &dummy);
272}
273
274static int get_active_phy(void)
275{
276 int i;
277
278 for (i = 0; i < num_phy; i++)
279 if (phy[i].get_link_speed(active_phy_addr[i]))
280 return i;
281
282 return -1; /* Return error if no link */
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200283}
284
285static int gen_get_link_speed(int phy_addr)
286{
287 u_int16_t tmp;
288
Sudhakar Rajashekhara5851e122010-11-18 09:59:37 -0500289 if (davinci_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) &&
290 (tmp & 0x04)) {
291#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
292 defined(CONFIG_MACH_DAVINCI_DA850_EVM)
Ben Gardinerb936eaa2011-01-11 14:48:17 -0500293 davinci_eth_phy_read(phy_addr, MII_LPA, &tmp);
Sudhakar Rajashekhara5851e122010-11-18 09:59:37 -0500294
295 /* Speed doesn't matter, there is no setting for it in EMAC. */
Ben Gardinerb936eaa2011-01-11 14:48:17 -0500296 if (tmp & (LPA_100FULL | LPA_10FULL)) {
Sudhakar Rajashekhara5851e122010-11-18 09:59:37 -0500297 /* set EMAC for Full Duplex */
298 writel(EMAC_MACCONTROL_MIIEN_ENABLE |
299 EMAC_MACCONTROL_FULLDUPLEX_ENABLE,
300 &adap_emac->MACCONTROL);
301 } else {
302 /*set EMAC for Half Duplex */
303 writel(EMAC_MACCONTROL_MIIEN_ENABLE,
304 &adap_emac->MACCONTROL);
305 }
306
Ben Gardinerb936eaa2011-01-11 14:48:17 -0500307 if (tmp & (LPA_100FULL | LPA_100HALF))
Sudhakar Rajashekhara5851e122010-11-18 09:59:37 -0500308 writel(readl(&adap_emac->MACCONTROL) |
309 EMAC_MACCONTROL_RMIISPEED_100,
310 &adap_emac->MACCONTROL);
311 else
312 writel(readl(&adap_emac->MACCONTROL) &
313 ~EMAC_MACCONTROL_RMIISPEED_100,
314 &adap_emac->MACCONTROL);
315#endif
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200316 return(1);
Sudhakar Rajashekhara5851e122010-11-18 09:59:37 -0500317 }
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200318
319 return(0);
320}
321
322static int gen_auto_negotiate(int phy_addr)
323{
324 u_int16_t tmp;
Manjunath Hadli4141ad42011-10-13 03:40:53 +0000325 u_int16_t val;
326 unsigned long cntr = 0;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200327
Mike Frysingerd63ee712010-12-23 15:40:12 -0500328 if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &tmp))
Manjunath Hadli4141ad42011-10-13 03:40:53 +0000329 return 0;
330
331 val = tmp | BMCR_FULLDPLX | BMCR_ANENABLE |
332 BMCR_SPEED100;
333 davinci_eth_phy_write(phy_addr, MII_BMCR, val);
334
335 if (!davinci_eth_phy_read(phy_addr, MII_ADVERTISE, &val))
336 return 0;
337
338 val |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10FULL |
339 ADVERTISE_10HALF);
340 davinci_eth_phy_write(phy_addr, MII_ADVERTISE, val);
341
342 if (!davinci_eth_phy_read(phy_addr, MII_BMCR, &tmp))
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200343 return(0);
344
Tom Rinic3cf8992017-05-10 12:01:02 -0400345#ifdef DAVINCI_EMAC_GIG_ENABLE
346 davinci_eth_phy_read(phy_addr, MII_CTRL1000, &val);
347 val |= PHY_1000BTCR_1000FD;
348 val &= ~PHY_1000BTCR_1000HD;
349 davinci_eth_phy_write(phy_addr, MII_CTRL1000, val);
350 davinci_eth_phy_read(phy_addr, MII_CTRL1000, &val);
351#endif
352
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200353 /* Restart Auto_negotiation */
Manjunath Hadli4141ad42011-10-13 03:40:53 +0000354 tmp |= BMCR_ANRESTART;
Mike Frysingerd63ee712010-12-23 15:40:12 -0500355 davinci_eth_phy_write(phy_addr, MII_BMCR, tmp);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200356
357 /*check AutoNegotiate complete */
Manjunath Hadli4141ad42011-10-13 03:40:53 +0000358 do {
359 udelay(40000);
360 if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &tmp))
361 return 0;
362
363 if (tmp & BMSR_ANEGCOMPLETE)
364 break;
365
366 cntr++;
367 } while (cntr < 200);
368
Mike Frysingerd63ee712010-12-23 15:40:12 -0500369 if (!davinci_eth_phy_read(phy_addr, MII_BMSR, &tmp))
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200370 return(0);
371
Mike Frysingerd63ee712010-12-23 15:40:12 -0500372 if (!(tmp & BMSR_ANEGCOMPLETE))
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200373 return(0);
374
375 return(gen_get_link_speed(phy_addr));
376}
377/* End of generic PHY functions */
378
379
Wolfgang Denk56cbd022007-08-12 14:27:39 +0200380#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500381static int davinci_mii_phy_read(struct mii_dev *bus, int addr, int devad,
382 int reg)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200383{
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500384 unsigned short value = 0;
Joe Hershbergerece1aa62016-08-08 11:28:40 -0500385 int retval = davinci_eth_phy_read(addr, reg, &value);
karl beldan05d06982016-08-20 08:56:53 +0000386
387 return retval ? value : -EIO;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200388}
389
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500390static int davinci_mii_phy_write(struct mii_dev *bus, int addr, int devad,
391 int reg, u16 value)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200392{
karl beldan05d06982016-08-20 08:56:53 +0000393 return davinci_eth_phy_write(addr, reg, value) ? 0 : 1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200394}
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200395#endif
396
Manjunath Hadli5b5260e2011-10-13 03:40:55 +0000397static void __attribute__((unused)) davinci_eth_gigabit_enable(int phy_addr)
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000398{
399 u_int16_t data;
400
Manjunath Hadli5b5260e2011-10-13 03:40:55 +0000401 if (davinci_eth_phy_read(phy_addr, 0, &data)) {
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000402 if (data & (1 << 6)) { /* speed selection MSB */
403 /*
404 * Check if link detected is giga-bit
405 * If Gigabit mode detected, enable gigbit in MAC
406 */
Sandeep Paulraj9da994b2010-12-28 14:37:33 -0500407 writel(readl(&adap_emac->MACCONTROL) |
408 EMAC_MACCONTROL_GIGFORCE |
409 EMAC_MACCONTROL_GIGABIT_ENABLE,
410 &adap_emac->MACCONTROL);
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000411 }
412 }
413}
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200414
415/* Eth device open */
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200416static int davinci_emac_start(struct udevice *dev)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200417{
418 dv_reg_p addr;
Tom Rinic3cf8992017-05-10 12:01:02 -0400419 u_int32_t clkdiv, cnt, mac_control;
420 uint16_t __maybe_unused lpa_val;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200421 volatile emac_desc *rx_desc;
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000422 int index;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200423
424 debug_emac("+ emac_open\n");
425
426 /* Reset EMAC module and disable interrupts in wrapper */
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000427 writel(1, &adap_emac->SOFTRESET);
428 while (readl(&adap_emac->SOFTRESET) != 0)
429 ;
430#if defined(DAVINCI_EMAC_VERSION2)
431 writel(1, &adap_ewrap->softrst);
432 while (readl(&adap_ewrap->softrst) != 0)
433 ;
434#else
435 writel(0, &adap_ewrap->EWCTL);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200436 for (cnt = 0; cnt < 5; cnt++) {
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000437 clkdiv = readl(&adap_ewrap->EWCTL);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200438 }
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000439#endif
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200440
Sudhakar Rajashekhara5851e122010-11-18 09:59:37 -0500441#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
442 defined(CONFIG_MACH_DAVINCI_DA850_EVM)
443 adap_ewrap->c0rxen = adap_ewrap->c1rxen = adap_ewrap->c2rxen = 0;
444 adap_ewrap->c0txen = adap_ewrap->c1txen = adap_ewrap->c2txen = 0;
445 adap_ewrap->c0miscen = adap_ewrap->c1miscen = adap_ewrap->c2miscen = 0;
446#endif
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200447 rx_desc = emac_rx_desc;
448
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000449 writel(1, &adap_emac->TXCONTROL);
450 writel(1, &adap_emac->RXCONTROL);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200451
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200452 davinci_emac_write_hwaddr(dev);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200453
454 /* Set DMA 8 TX / 8 RX Head pointers to 0 */
455 addr = &adap_emac->TX0HDP;
Vishwas Srivastava8aaeb1f2016-01-25 21:28:17 +0530456 for (cnt = 0; cnt < 8; cnt++)
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000457 writel(0, addr++);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200458
459 addr = &adap_emac->RX0HDP;
Vishwas Srivastava8aaeb1f2016-01-25 21:28:17 +0530460 for (cnt = 0; cnt < 8; cnt++)
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000461 writel(0, addr++);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200462
463 /* Clear Statistics (do this before setting MacControl register) */
464 addr = &adap_emac->RXGOODFRAMES;
465 for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++)
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000466 writel(0, addr++);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200467
468 /* No multicast addressing */
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000469 writel(0, &adap_emac->MACHASH1);
470 writel(0, &adap_emac->MACHASH2);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200471
472 /* Create RX queue and set receive process in place */
473 emac_rx_active_head = emac_rx_desc;
474 for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) {
Ilya Yanok518036e2011-11-28 06:37:30 +0000475 rx_desc->next = BD_TO_HW((u_int32_t)(rx_desc + 1));
Ilya Yanokff672762011-11-28 06:37:33 +0000476 rx_desc->buffer = &emac_rx_buffers[cnt * EMAC_RXBUF_SIZE];
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200477 rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
478 rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
479 rx_desc++;
480 }
481
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000482 /* Finalize the rx desc list */
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200483 rx_desc--;
484 rx_desc->next = 0;
485 emac_rx_active_tail = rx_desc;
486 emac_rx_queue_active = 1;
487
488 /* Enable TX/RX */
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000489 writel(EMAC_MAX_ETHERNET_PKT_SIZE, &adap_emac->RXMAXLEN);
490 writel(0, &adap_emac->RXBUFFEROFFSET);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200491
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000492 /*
493 * No fancy configs - Use this for promiscous debug
494 * - EMAC_RXMBPENABLE_RXCAFEN_ENABLE
495 */
496 writel(EMAC_RXMBPENABLE_RXBROADEN, &adap_emac->RXMBPENABLE);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200497
498 /* Enable ch 0 only */
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000499 writel(1, &adap_emac->RXUNICASTSET);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200500
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200501 /* Init MDIO & get link state */
Heiko Schocher3e806132011-11-01 20:00:27 +0000502 clkdiv = CONFIG_SYS_EMAC_TI_CLKDIV;
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000503 writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT,
504 &adap_mdio->CONTROL);
505
506 /* We need to wait for MDIO to start */
507 udelay(1000);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200508
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000509 index = get_active_phy();
510 if (index == -1)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200511 return(0);
512
Tom Rinic3cf8992017-05-10 12:01:02 -0400513 /* Enable MII interface */
514 mac_control = EMAC_MACCONTROL_MIIEN_ENABLE;
515#ifdef DAVINCI_EMAC_GIG_ENABLE
516 davinci_eth_phy_read(active_phy_addr[index], MII_STAT1000, &lpa_val);
517 if (lpa_val & PHY_1000BTSR_1000FD) {
518 debug_emac("eth_open : gigabit negotiated\n");
519 mac_control |= EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
520 mac_control |= EMAC_MACCONTROL_GIGABIT_ENABLE;
521 }
522#endif
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000523
Tom Rinic3cf8992017-05-10 12:01:02 -0400524 davinci_eth_phy_read(active_phy_addr[index], MII_LPA, &lpa_val);
525 if (lpa_val & (LPA_100FULL | LPA_10FULL))
526 /* set EMAC for Full Duplex */
527 mac_control |= EMAC_MACCONTROL_FULLDUPLEX_ENABLE;
528#if defined(CONFIG_SOC_DA8XX) || \
529 (defined(CONFIG_OMAP34XX) && defined(CONFIG_DRIVER_TI_EMAC_USE_RMII))
530 mac_control |= EMAC_MACCONTROL_RMIISPEED_100;
531#endif
532 writel(mac_control, &adap_emac->MACCONTROL);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200533 /* Start receive process */
Ilya Yanok518036e2011-11-28 06:37:30 +0000534 writel(BD_TO_HW((u_int32_t)emac_rx_desc), &adap_emac->RX0HDP);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200535
536 debug_emac("- emac_open\n");
537
538 return(1);
539}
540
541/* EMAC Channel Teardown */
Sandeep Paulraj4b26f052008-08-31 00:39:46 +0200542static void davinci_eth_ch_teardown(int ch)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200543{
544 dv_reg dly = 0xff;
545 dv_reg cnt;
546
547 debug_emac("+ emac_ch_teardown\n");
548
549 if (ch == EMAC_CH_TX) {
550 /* Init TX channel teardown */
Nagabhushana Netaguntea33bc4b2011-09-03 22:20:33 -0400551 writel(0, &adap_emac->TXTEARDOWN);
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000552 do {
553 /*
554 * Wait here for Tx teardown completion interrupt to
555 * occur. Note: A task delay can be called here to pend
556 * rather than occupying CPU cycles - anyway it has
557 * been found that teardown takes very few cpu cycles
558 * and does not affect functionality
559 */
560 dly--;
561 udelay(1);
562 if (dly == 0)
Wolfgang Denka1be4762008-05-20 16:00:29 +0200563 break;
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000564 cnt = readl(&adap_emac->TX0CP);
565 } while (cnt != 0xfffffffc);
566 writel(cnt, &adap_emac->TX0CP);
567 writel(0, &adap_emac->TX0HDP);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200568 } else {
569 /* Init RX channel teardown */
Nagabhushana Netaguntea33bc4b2011-09-03 22:20:33 -0400570 writel(0, &adap_emac->RXTEARDOWN);
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000571 do {
572 /*
573 * Wait here for Rx teardown completion interrupt to
574 * occur. Note: A task delay can be called here to pend
575 * rather than occupying CPU cycles - anyway it has
576 * been found that teardown takes very few cpu cycles
577 * and does not affect functionality
578 */
579 dly--;
580 udelay(1);
581 if (dly == 0)
Wolfgang Denka1be4762008-05-20 16:00:29 +0200582 break;
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000583 cnt = readl(&adap_emac->RX0CP);
584 } while (cnt != 0xfffffffc);
585 writel(cnt, &adap_emac->RX0CP);
586 writel(0, &adap_emac->RX0HDP);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200587 }
588
589 debug_emac("- emac_ch_teardown\n");
590}
591
592/* Eth device close */
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200593static void davinci_emac_stop(struct udevice *dev)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200594{
595 debug_emac("+ emac_close\n");
596
Sandeep Paulraj4b26f052008-08-31 00:39:46 +0200597 davinci_eth_ch_teardown(EMAC_CH_TX); /* TX Channel teardown */
Jeroen Hofstee8938b5b2015-06-07 17:30:38 +0200598 if (readl(&adap_emac->RXCONTROL) & 1)
599 davinci_eth_ch_teardown(EMAC_CH_RX); /* RX Channel teardown */
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200600
601 /* Reset EMAC module and disable interrupts in wrapper */
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000602 writel(1, &adap_emac->SOFTRESET);
603#if defined(DAVINCI_EMAC_VERSION2)
604 writel(1, &adap_ewrap->softrst);
605#else
606 writel(0, &adap_ewrap->EWCTL);
607#endif
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200608
Sudhakar Rajashekhara5851e122010-11-18 09:59:37 -0500609#if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
610 defined(CONFIG_MACH_DAVINCI_DA850_EVM)
611 adap_ewrap->c0rxen = adap_ewrap->c1rxen = adap_ewrap->c2rxen = 0;
612 adap_ewrap->c0txen = adap_ewrap->c1txen = adap_ewrap->c2txen = 0;
613 adap_ewrap->c0miscen = adap_ewrap->c1miscen = adap_ewrap->c2miscen = 0;
614#endif
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200615 debug_emac("- emac_close\n");
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200616}
617
618static int tx_send_loop = 0;
619
620/*
621 * This function sends a single packet on the network and returns
622 * positive number (number of bytes transmitted) or negative for error
623 */
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200624static int davinci_emac_send(struct udevice *dev,
625 void *packet, int length)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200626{
627 int ret_status = -1;
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000628 int index;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200629 tx_send_loop = 0;
630
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000631 index = get_active_phy();
632 if (index == -1) {
633 printf(" WARN: emac_send_packet: No link\n");
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200634 return (ret_status);
635 }
636
637 /* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200638 if (length < EMAC_MIN_ETHERNET_PKT_SIZE) {
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200639 length = EMAC_MIN_ETHERNET_PKT_SIZE;
640 }
641
642 /* Populate the TX descriptor */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200643 emac_tx_desc->next = 0;
644 emac_tx_desc->buffer = (u_int8_t *) packet;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200645 emac_tx_desc->buff_off_len = (length & 0xffff);
646 emac_tx_desc->pkt_flag_len = ((length & 0xffff) |
Wolfgang Denka1be4762008-05-20 16:00:29 +0200647 EMAC_CPPI_SOP_BIT |
648 EMAC_CPPI_OWNERSHIP_BIT |
649 EMAC_CPPI_EOP_BIT);
Ilya Yanokff672762011-11-28 06:37:33 +0000650
651 flush_dcache_range((unsigned long)packet,
karl beldane24ce8b2016-08-15 17:23:00 +0000652 (unsigned long)packet + ALIGN(length, PKTALIGN));
Ilya Yanokff672762011-11-28 06:37:33 +0000653
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200654 /* Send the packet */
Ilya Yanok518036e2011-11-28 06:37:30 +0000655 writel(BD_TO_HW((unsigned long)emac_tx_desc), &adap_emac->TX0HDP);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200656
657 /* Wait for packet to complete or link down */
658 while (1) {
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000659 if (!phy[index].get_link_speed(active_phy_addr[index])) {
Sandeep Paulraj4b26f052008-08-31 00:39:46 +0200660 davinci_eth_ch_teardown (EMAC_CH_TX);
Wolfgang Denka1be4762008-05-20 16:00:29 +0200661 return (ret_status);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200662 }
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000663
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000664 if (readl(&adap_emac->TXINTSTATRAW) & 0x01) {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200665 ret_status = length;
666 break;
667 }
668 tx_send_loop++;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200669 }
670
Wolfgang Denka1be4762008-05-20 16:00:29 +0200671 return (ret_status);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200672}
673
674/*
675 * This function handles receipt of a packet from the network
676 */
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200677static int davinci_emac_recv(struct udevice *dev, int flags, uchar **packetp)
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200678{
Wolfgang Denka1be4762008-05-20 16:00:29 +0200679 volatile emac_desc *rx_curr_desc;
680 volatile emac_desc *curr_desc;
681 volatile emac_desc *tail_desc;
682 int status, ret = -1;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200683
684 rx_curr_desc = emac_rx_active_head;
Vishwas Srivastavac994c9c2016-01-26 12:46:42 +0530685 if (!rx_curr_desc)
686 return 0;
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200687 *packetp = rx_curr_desc->buffer;
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200688 status = rx_curr_desc->pkt_flag_len;
Vishwas Srivastavac994c9c2016-01-26 12:46:42 +0530689 if ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0) {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200690 if (status & EMAC_CPPI_RX_ERROR_FRAME) {
691 /* Error in packet - discard it and requeue desc */
692 printf ("WARN: emac_rcv_pkt: Error in packet\n");
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200693 } else {
Ilya Yanokff672762011-11-28 06:37:33 +0000694 unsigned long tmp = (unsigned long)rx_curr_desc->buffer;
karl beldan12e49872016-08-15 17:23:01 +0000695 unsigned short len =
696 rx_curr_desc->buff_off_len & 0xffff;
Ilya Yanokff672762011-11-28 06:37:33 +0000697
karl beldan12e49872016-08-15 17:23:01 +0000698 invalidate_dcache_range(tmp, tmp + ALIGN(len, PKTALIGN));
karl beldan12e49872016-08-15 17:23:01 +0000699 ret = len;
Wolfgang Denka1be4762008-05-20 16:00:29 +0200700 }
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200701
Wolfgang Denka1be4762008-05-20 16:00:29 +0200702 /* Ack received packet descriptor */
Ilya Yanok518036e2011-11-28 06:37:30 +0000703 writel(BD_TO_HW((ulong)rx_curr_desc), &adap_emac->RX0CP);
Wolfgang Denka1be4762008-05-20 16:00:29 +0200704 curr_desc = rx_curr_desc;
705 emac_rx_active_head =
Ilya Yanok518036e2011-11-28 06:37:30 +0000706 (volatile emac_desc *) (HW_TO_BD(rx_curr_desc->next));
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200707
Wolfgang Denka1be4762008-05-20 16:00:29 +0200708 if (status & EMAC_CPPI_EOQ_BIT) {
709 if (emac_rx_active_head) {
Ilya Yanok518036e2011-11-28 06:37:30 +0000710 writel(BD_TO_HW((ulong)emac_rx_active_head),
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000711 &adap_emac->RX0HDP);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200712 } else {
713 emac_rx_queue_active = 0;
Wolfgang Denka1be4762008-05-20 16:00:29 +0200714 printf ("INFO:emac_rcv_packet: RX Queue not active\n");
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200715 }
716 }
717
718 /* Recycle RX descriptor */
719 rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
720 rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
721 rx_curr_desc->next = 0;
722
723 if (emac_rx_active_head == 0) {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200724 printf ("INFO: emac_rcv_pkt: active queue head = 0\n");
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200725 emac_rx_active_head = curr_desc;
726 emac_rx_active_tail = curr_desc;
727 if (emac_rx_queue_active != 0) {
Ilya Yanok518036e2011-11-28 06:37:30 +0000728 writel(BD_TO_HW((ulong)emac_rx_active_head),
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000729 &adap_emac->RX0HDP);
Wolfgang Denka1be4762008-05-20 16:00:29 +0200730 printf ("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n");
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200731 emac_rx_queue_active = 1;
732 }
733 } else {
734 tail_desc = emac_rx_active_tail;
735 emac_rx_active_tail = curr_desc;
Ilya Yanok518036e2011-11-28 06:37:30 +0000736 tail_desc->next = BD_TO_HW((ulong) curr_desc);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200737 status = tail_desc->pkt_flag_len;
738 if (status & EMAC_CPPI_EOQ_BIT) {
Ilya Yanok518036e2011-11-28 06:37:30 +0000739 writel(BD_TO_HW((ulong)curr_desc),
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000740 &adap_emac->RX0HDP);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200741 status &= ~EMAC_CPPI_EOQ_BIT;
742 tail_desc->pkt_flag_len = status;
743 }
744 }
Wolfgang Denka1be4762008-05-20 16:00:29 +0200745 return (ret);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200746 }
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200747
Wolfgang Denka1be4762008-05-20 16:00:29 +0200748 return (0);
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200749}
750
Ben Warren4c28e272009-04-27 23:19:10 -0700751/*
752 * This function initializes the emac hardware. It does NOT initialize
753 * EMAC modules power or pin multiplexors, that is done by board_init()
754 * much earlier in bootup process. Returns 1 on success, 0 otherwise.
755 */
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200756static int davinci_emac_probe(struct udevice *dev)
Ben Warren4c28e272009-04-27 23:19:10 -0700757{
758 u_int32_t phy_id;
759 u_int16_t tmp;
760 int i;
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000761 int ret;
Ben Warren4c28e272009-04-27 23:19:10 -0700762
763 davinci_eth_mdio_enable();
764
Heiko Schocher70fa9662011-09-14 19:37:42 +0000765 /* let the EMAC detect the PHYs */
766 udelay(5000);
767
Ben Warren4c28e272009-04-27 23:19:10 -0700768 for (i = 0; i < 256; i++) {
Nick Thompsond5ee6f62009-12-18 13:33:07 +0000769 if (readl(&adap_mdio->ALIVE))
Ben Warren4c28e272009-04-27 23:19:10 -0700770 break;
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000771 udelay(1000);
Ben Warren4c28e272009-04-27 23:19:10 -0700772 }
773
774 if (i >= 256) {
775 printf("No ETH PHY detected!!!\n");
776 return(0);
777 }
778
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000779 /* Find if PHY(s) is/are connected */
780 ret = davinci_eth_phy_detect();
781 if (!ret)
Ben Warren4c28e272009-04-27 23:19:10 -0700782 return(0);
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000783 else
Heiko Schocher7d037f72011-11-15 10:00:04 -0500784 debug_emac(" %d ETH PHY detected\n", ret);
Ben Warren4c28e272009-04-27 23:19:10 -0700785
786 /* Get PHY ID and initialize phy_ops for a detected PHY */
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000787 for (i = 0; i < num_phy; i++) {
788 if (!davinci_eth_phy_read(active_phy_addr[i], MII_PHYSID1,
789 &tmp)) {
790 active_phy_addr[i] = 0xff;
791 continue;
792 }
Sergey Kubushyne8f39122007-08-10 20:26:18 +0200793
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000794 phy_id = (tmp << 16) & 0xffff0000;
Ben Warren4c28e272009-04-27 23:19:10 -0700795
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000796 if (!davinci_eth_phy_read(active_phy_addr[i], MII_PHYSID2,
797 &tmp)) {
798 active_phy_addr[i] = 0xff;
799 continue;
800 }
Ben Warren4c28e272009-04-27 23:19:10 -0700801
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000802 phy_id |= tmp & 0x0000ffff;
Ben Warren4c28e272009-04-27 23:19:10 -0700803
Bartosz Golaszewski101c5ba2019-04-29 18:37:08 +0200804 sprintf(phy[i].name, "GENERIC @ 0x%02x",
805 active_phy_addr[i]);
806 phy[i].init = gen_init_phy;
807 phy[i].is_phy_connected = gen_is_phy_connected;
808 phy[i].get_link_speed = gen_get_link_speed;
809 phy[i].auto_negotiate = gen_auto_negotiate;
Ben Warren4c28e272009-04-27 23:19:10 -0700810
Ilya Yanok57c449d2011-11-01 13:15:55 +0000811 debug("Ethernet PHY: %s\n", phy[i].name);
Ben Warren4c28e272009-04-27 23:19:10 -0700812
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500813 int retval;
814 struct mii_dev *mdiodev = mdio_alloc();
815 if (!mdiodev)
816 return -ENOMEM;
817 strncpy(mdiodev->name, phy[i].name, MDIO_NAME_LEN);
818 mdiodev->read = davinci_mii_phy_read;
819 mdiodev->write = davinci_mii_phy_write;
820
821 retval = mdio_register(mdiodev);
822 if (retval < 0)
823 return retval;
Tom Rinic3cf8992017-05-10 12:01:02 -0400824#ifdef DAVINCI_EMAC_GIG_ENABLE
825#define PHY_CONF_REG 22
826 /* Enable PHY to clock out TX_CLK */
827 davinci_eth_phy_read(active_phy_addr[i], PHY_CONF_REG, &tmp);
828 tmp |= PHY_CONF_TXCLKEN;
829 davinci_eth_phy_write(active_phy_addr[i], PHY_CONF_REG, tmp);
830 davinci_eth_phy_read(active_phy_addr[i], PHY_CONF_REG, &tmp);
831#endif
Manjunath Hadli444d8c12011-10-13 03:40:54 +0000832 }
Rajashekhara, Sudhakarfe3a0d62012-06-07 00:27:44 +0000833
Tom Rinic3cf8992017-05-10 12:01:02 -0400834#if defined(CONFIG_TI816X) || (defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
Bastian Ruppertef2746a2012-09-13 22:29:03 +0000835 defined(CONFIG_MACH_DAVINCI_DA850_EVM) && \
Tom Rinic3cf8992017-05-10 12:01:02 -0400836 !defined(CONFIG_DRIVER_TI_EMAC_RMII_NO_NEGOTIATE))
Rajashekhara, Sudhakarfe3a0d62012-06-07 00:27:44 +0000837 for (i = 0; i < num_phy; i++) {
838 if (phy[i].is_phy_connected(i))
839 phy[i].auto_negotiate(i);
840 }
841#endif
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200842 return 0;
Ben Warren4c28e272009-04-27 23:19:10 -0700843}
Bartosz Golaszewski2cedf752019-07-24 10:12:07 +0200844
845static const struct eth_ops davinci_emac_ops = {
846 .start = davinci_emac_start,
847 .send = davinci_emac_send,
848 .recv = davinci_emac_recv,
849 .stop = davinci_emac_stop,
850 .write_hwaddr = davinci_emac_write_hwaddr,
851};
852
853static const struct udevice_id davinci_emac_ids[] = {
854 { .compatible = "ti,davinci-dm6467-emac" },
855 { .compatible = "ti,am3517-emac", },
856 { .compatible = "ti,dm816-emac", },
857 { }
858};
859
860U_BOOT_DRIVER(davinci_emac) = {
861 .name = "davinci_emac",
862 .id = UCLASS_ETH,
863 .of_match = davinci_emac_ids,
864 .probe = davinci_emac_probe,
865 .ops = &davinci_emac_ops,
866 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
867};