fec_mxc.c 34.0 KB
Newer Older
1 2 3 4 5 6 7
/*
 * (C) Copyright 2009 Ilya Yanok, Emcraft Systems Ltd <yanok@emcraft.com>
 * (C) Copyright 2008,2009 Eric Jarrige <eric.jarrige@armadeus.org>
 * (C) Copyright 2008 Armadeus Systems nc
 * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
 * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.de>
 *
8
 * SPDX-License-Identifier:	GPL-2.0+
9 10 11
 */

#include <common.h>
12
#include <dm.h>
13
#include <environment.h>
14
#include <malloc.h>
15
#include <memalign.h>
J
Jagan Teki 已提交
16
#include <miiphy.h>
17
#include <net.h>
18
#include <netdev.h>
19 20 21
#include "fec_mxc.h"

#include <asm/io.h>
22
#include <linux/errno.h>
23
#include <linux/compiler.h>
24

J
Jagan Teki 已提交
25 26
#include <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
27
#include <asm/mach-imx/sys_proto.h>
J
Jagan Teki 已提交
28

29 30
DECLARE_GLOBAL_DATA_PTR;

31 32 33 34 35 36
/*
 * Timeout the transfer after 5 mS. This is usually a bit more, since
 * the code in the tightloops this timeout is used in adds some overhead.
 */
#define FEC_XFER_TIMEOUT	5000

37 38 39 40 41 42 43 44
/*
 * The standard 32-byte DMA alignment does not work on mx6solox, which requires
 * 64-byte alignment in the DMA RX FEC buffer.
 * Introduce the FEC_DMA_RX_MINALIGN which can cover mx6solox needs and also
 * satisfies the alignment on other SoCs (32-bytes)
 */
#define FEC_DMA_RX_MINALIGN	64

45 46 47 48
#ifndef CONFIG_MII
#error "CONFIG_MII has to be defined!"
#endif

49 50
#ifndef CONFIG_FEC_XCV_TYPE
#define CONFIG_FEC_XCV_TYPE MII100
51 52
#endif

M
Marek Vasut 已提交
53 54 55 56
/*
 * The i.MX28 operates with packets in big endian. We need to swap them before
 * sending and after receiving.
 */
57 58 59 60 61 62 63 64 65 66 67 68 69 70
#ifdef CONFIG_MX28
#define CONFIG_FEC_MXC_SWAP_PACKET
#endif

#define RXDESC_PER_CACHELINE (ARCH_DMA_MINALIGN/sizeof(struct fec_bd))

/* Check various alignment issues at compile time */
#if ((ARCH_DMA_MINALIGN < 16) || (ARCH_DMA_MINALIGN % 16 != 0))
#error "ARCH_DMA_MINALIGN must be multiple of 16!"
#endif

#if ((PKTALIGN < ARCH_DMA_MINALIGN) || \
	(PKTALIGN % ARCH_DMA_MINALIGN != 0))
#error "PKTALIGN must be multiple of ARCH_DMA_MINALIGN!"
M
Marek Vasut 已提交
71 72
#endif

73 74
#undef DEBUG

75
#ifdef CONFIG_FEC_MXC_SWAP_PACKET
M
Marek Vasut 已提交
76 77 78 79 80 81 82 83 84
static void swap_packet(uint32_t *packet, int length)
{
	int i;

	for (i = 0; i < DIV_ROUND_UP(length, 4); i++)
		packet[i] = __swab32(packet[i]);
}
#endif

J
Jagan Teki 已提交
85 86 87
/* MII-interface related functions */
static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyaddr,
		uint8_t regaddr)
88 89 90 91
{
	uint32_t reg;		/* convenient holder for the PHY register */
	uint32_t phy;		/* convenient holder for the PHY */
	uint32_t start;
T
Troy Kisky 已提交
92
	int val;
93 94 95 96 97

	/*
	 * reading from any PHY's register is done by properly
	 * programming the FEC's MII data register.
	 */
98
	writel(FEC_IEVENT_MII, &eth->ievent);
J
Jagan Teki 已提交
99 100
	reg = regaddr << FEC_MII_DATA_RA_SHIFT;
	phy = phyaddr << FEC_MII_DATA_PA_SHIFT;
101 102

	writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA |
103
			phy | reg, &eth->mii_data);
104

J
Jagan Teki 已提交
105
	/* wait for the related interrupt */
106
	start = get_timer(0);
107
	while (!(readl(&eth->ievent) & FEC_IEVENT_MII)) {
108 109 110 111 112 113
		if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
			printf("Read MDIO failed...\n");
			return -1;
		}
	}

J
Jagan Teki 已提交
114
	/* clear mii interrupt bit */
115
	writel(FEC_IEVENT_MII, &eth->ievent);
116

J
Jagan Teki 已提交
117
	/* it's now safe to read the PHY's register */
T
Troy Kisky 已提交
118
	val = (unsigned short)readl(&eth->mii_data);
J
Jagan Teki 已提交
119 120
	debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyaddr,
	      regaddr, val);
T
Troy Kisky 已提交
121
	return val;
122 123
}

124
static void fec_mii_setspeed(struct ethernet_regs *eth)
125 126 127 128
{
	/*
	 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
	 * and do not drop the Preamble.
129 130 131 132 133 134 135 136 137 138 139
	 *
	 * The i.MX28 and i.MX6 types have another field in the MSCR (aka
	 * MII_SPEED) register that defines the MDIO output hold time. Earlier
	 * versions are RAZ there, so just ignore the difference and write the
	 * register always.
	 * The minimal hold time according to IEE802.3 (clause 22) is 10 ns.
	 * HOLDTIME + 1 is the number of clk cycles the fec is holding the
	 * output.
	 * The HOLDTIME bitfield takes values between 0 and 7 (inclusive).
	 * Given that ceil(clkrate / 5000000) <= 64, the calculation for
	 * holdtime cannot result in a value greater than 3.
140
	 */
141 142 143
	u32 pclk = imx_get_fecclk();
	u32 speed = DIV_ROUND_UP(pclk, 5000000);
	u32 hold = DIV_ROUND_UP(pclk, 100000000) - 1;
144 145 146
#ifdef FEC_QUIRK_ENET_MAC
	speed--;
#endif
147
	writel(speed << 1 | hold << 8, &eth->mii_speed);
148
	debug("%s: mii_speed %08x\n", __func__, readl(&eth->mii_speed));
149
}
150

J
Jagan Teki 已提交
151 152
static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyaddr,
		uint8_t regaddr, uint16_t data)
T
Troy Kisky 已提交
153
{
154 155 156 157
	uint32_t reg;		/* convenient holder for the PHY register */
	uint32_t phy;		/* convenient holder for the PHY */
	uint32_t start;

J
Jagan Teki 已提交
158 159
	reg = regaddr << FEC_MII_DATA_RA_SHIFT;
	phy = phyaddr << FEC_MII_DATA_PA_SHIFT;
160 161

	writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
162
		FEC_MII_DATA_TA | phy | reg | data, &eth->mii_data);
163

J
Jagan Teki 已提交
164
	/* wait for the MII interrupt */
165
	start = get_timer(0);
166
	while (!(readl(&eth->ievent) & FEC_IEVENT_MII)) {
167 168 169 170 171 172
		if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
			printf("Write MDIO failed...\n");
			return -1;
		}
	}

J
Jagan Teki 已提交
173
	/* clear MII interrupt bit */
174
	writel(FEC_IEVENT_MII, &eth->ievent);
J
Jagan Teki 已提交
175 176
	debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyaddr,
	      regaddr, data);
177 178 179 180

	return 0;
}

J
Jagan Teki 已提交
181 182
static int fec_phy_read(struct mii_dev *bus, int phyaddr, int dev_addr,
			int regaddr)
T
Troy Kisky 已提交
183
{
J
Jagan Teki 已提交
184
	return fec_mdio_read(bus->priv, phyaddr, regaddr);
T
Troy Kisky 已提交
185 186
}

J
Jagan Teki 已提交
187 188
static int fec_phy_write(struct mii_dev *bus, int phyaddr, int dev_addr,
			 int regaddr, u16 data)
T
Troy Kisky 已提交
189
{
J
Jagan Teki 已提交
190
	return fec_mdio_write(bus->priv, phyaddr, regaddr, data);
T
Troy Kisky 已提交
191 192 193
}

#ifndef CONFIG_PHYLIB
194 195
static int miiphy_restart_aneg(struct eth_device *dev)
{
196 197
	int ret = 0;
#if !defined(CONFIG_FEC_MXC_NO_ANEG)
M
Marek Vasut 已提交
198
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
T
Troy Kisky 已提交
199
	struct ethernet_regs *eth = fec->bus->priv;
M
Marek Vasut 已提交
200

201 202 203 204
	/*
	 * Wake up from sleep if necessary
	 * Reset PHY, then delay 300ns
	 */
205
#ifdef CONFIG_MX27
T
Troy Kisky 已提交
206
	fec_mdio_write(eth, fec->phy_id, MII_DCOUNTER, 0x00FF);
207
#endif
T
Troy Kisky 已提交
208
	fec_mdio_write(eth, fec->phy_id, MII_BMCR, BMCR_RESET);
209 210
	udelay(1000);

J
Jagan Teki 已提交
211
	/* Set the auto-negotiation advertisement register bits */
T
Troy Kisky 已提交
212
	fec_mdio_write(eth, fec->phy_id, MII_ADVERTISE,
J
Jagan Teki 已提交
213 214
		       LPA_100FULL | LPA_100HALF | LPA_10FULL |
		       LPA_10HALF | PHY_ANLPAR_PSB_802_3);
T
Troy Kisky 已提交
215
	fec_mdio_write(eth, fec->phy_id, MII_BMCR,
J
Jagan Teki 已提交
216
		       BMCR_ANENABLE | BMCR_ANRESTART);
217 218 219 220

	if (fec->mii_postcall)
		ret = fec->mii_postcall(fec->phy_id);

221
#endif
222
	return ret;
223 224
}

225
#ifndef CONFIG_FEC_FIXED_SPEED
226 227 228
static int miiphy_wait_aneg(struct eth_device *dev)
{
	uint32_t start;
T
Troy Kisky 已提交
229
	int status;
M
Marek Vasut 已提交
230
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
T
Troy Kisky 已提交
231
	struct ethernet_regs *eth = fec->bus->priv;
232

J
Jagan Teki 已提交
233
	/* Wait for AN completion */
234
	start = get_timer(0);
235 236 237 238 239 240
	do {
		if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
			printf("%s: Autonegotiation timeout\n", dev->name);
			return -1;
		}

T
Troy Kisky 已提交
241 242 243
		status = fec_mdio_read(eth, fec->phy_id, MII_BMSR);
		if (status < 0) {
			printf("%s: Autonegotiation failed. status: %d\n",
J
Jagan Teki 已提交
244
			       dev->name, status);
245 246
			return -1;
		}
M
Mike Frysinger 已提交
247
	} while (!(status & BMSR_LSTATUS));
248 249 250

	return 0;
}
251
#endif /* CONFIG_FEC_FIXED_SPEED */
T
Troy Kisky 已提交
252 253
#endif

254 255
static int fec_rx_task_enable(struct fec_priv *fec)
{
M
Marek Vasut 已提交
256
	writel(FEC_R_DES_ACTIVE_RDAR, &fec->eth->r_des_active);
257 258 259 260 261 262 263 264 265 266
	return 0;
}

static int fec_rx_task_disable(struct fec_priv *fec)
{
	return 0;
}

static int fec_tx_task_enable(struct fec_priv *fec)
{
M
Marek Vasut 已提交
267
	writel(FEC_X_DES_ACTIVE_TDAR, &fec->eth->x_des_active);
268 269 270 271 272 273 274 275 276 277 278 279
	return 0;
}

static int fec_tx_task_disable(struct fec_priv *fec)
{
	return 0;
}

/**
 * Initialize receive task's buffer descriptors
 * @param[in] fec all we know about the device yet
 * @param[in] count receive buffer count to be allocated
280
 * @param[in] dsize desired size of each receive buffer
281 282
 * @return 0 on success
 *
M
Marek Vasut 已提交
283
 * Init all RX descriptors to default values.
284
 */
M
Marek Vasut 已提交
285
static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
286
{
287
	uint32_t size;
288
	ulong data;
289 290
	int i;

291
	/*
M
Marek Vasut 已提交
292 293
	 * Reload the RX descriptors with default values and wipe
	 * the RX buffers.
294
	 */
295 296
	size = roundup(dsize, ARCH_DMA_MINALIGN);
	for (i = 0; i < count; i++) {
297 298 299
		data = fec->rbd_base[i].data_pointer;
		memset((void *)data, 0, dsize);
		flush_dcache_range(data, data + size);
M
Marek Vasut 已提交
300 301 302

		fec->rbd_base[i].status = FEC_RBD_EMPTY;
		fec->rbd_base[i].data_length = 0;
303 304 305
	}

	/* Mark the last RBD to close the ring. */
M
Marek Vasut 已提交
306
	fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;
307 308
	fec->rbd_index = 0;

309 310
	flush_dcache_range((ulong)fec->rbd_base,
			   (ulong)fec->rbd_base + size);
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
}

/**
 * Initialize transmit task's buffer descriptors
 * @param[in] fec all we know about the device yet
 *
 * Transmit buffers are created externally. We only have to init the BDs here.\n
 * Note: There is a race condition in the hardware. When only one BD is in
 * use it must be marked with the WRAP bit to use it for every transmitt.
 * This bit in combination with the READY bit results into double transmit
 * of each data buffer. It seems the state machine checks READY earlier then
 * resetting it after the first transfer.
 * Using two BDs solves this issue.
 */
static void fec_tbd_init(struct fec_priv *fec)
{
327
	ulong addr = (ulong)fec->tbd_base;
328 329
	unsigned size = roundup(2 * sizeof(struct fec_bd),
				ARCH_DMA_MINALIGN);
M
Marek Vasut 已提交
330 331 332 333

	memset(fec->tbd_base, 0, size);
	fec->tbd_base[0].status = 0;
	fec->tbd_base[1].status = FEC_TBD_WRAP;
334
	fec->tbd_index = 0;
M
Marek Vasut 已提交
335
	flush_dcache_range(addr, addr + size);
336 337 338 339 340
}

/**
 * Mark the given read buffer descriptor as free
 * @param[in] last 1 if this is the last buffer descriptor in the chain, else 0
J
Jagan Teki 已提交
341
 * @param[in] prbd buffer descriptor to mark free again
342
 */
J
Jagan Teki 已提交
343
static void fec_rbd_clean(int last, struct fec_bd *prbd)
344
{
345
	unsigned short flags = FEC_RBD_EMPTY;
346
	if (last)
347
		flags |= FEC_RBD_WRAP;
J
Jagan Teki 已提交
348 349
	writew(flags, &prbd->status);
	writew(0, &prbd->data_length);
350 351
}

352
static int fec_get_hwaddr(int dev_id, unsigned char *mac)
353
{
354
	imx_get_mac_from_fuse(dev_id, mac);
355
	return !is_valid_ethaddr(mac);
356 357
}

358 359 360
#ifdef CONFIG_DM_ETH
static int fecmxc_set_hwaddr(struct udevice *dev)
#else
361
static int fec_set_hwaddr(struct eth_device *dev)
362
#endif
363
{
364 365 366 367 368
#ifdef CONFIG_DM_ETH
	struct fec_priv *fec = dev_get_priv(dev);
	struct eth_pdata *pdata = dev_get_platdata(dev);
	uchar *mac = pdata->enetaddr;
#else
369
	uchar *mac = dev->enetaddr;
370
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
371
#endif
372 373 374 375 376 377

	writel(0, &fec->eth->iaddr1);
	writel(0, &fec->eth->iaddr2);
	writel(0, &fec->eth->gaddr1);
	writel(0, &fec->eth->gaddr2);

J
Jagan Teki 已提交
378
	/* Set physical address */
379
	writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3],
J
Jagan Teki 已提交
380
	       &fec->eth->paddr1);
381 382 383 384 385
	writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, &fec->eth->paddr2);

	return 0;
}

J
Jagan Teki 已提交
386
/* Do initial configuration of the FEC registers */
M
Marek Vasut 已提交
387 388 389 390
static void fec_reg_setup(struct fec_priv *fec)
{
	uint32_t rcntrl;

J
Jagan Teki 已提交
391
	/* Set interrupt mask register */
M
Marek Vasut 已提交
392 393
	writel(0x00000000, &fec->eth->imask);

J
Jagan Teki 已提交
394
	/* Clear FEC-Lite interrupt event register(IEVENT) */
M
Marek Vasut 已提交
395 396
	writel(0xffffffff, &fec->eth->ievent);

J
Jagan Teki 已提交
397
	/* Set FEC-Lite receive control register(R_CNTRL): */
M
Marek Vasut 已提交
398 399 400

	/* Start with frame length = 1518, common for all modes. */
	rcntrl = PKTSIZE << FEC_RCNTRL_MAX_FL_SHIFT;
401 402 403
	if (fec->xcv_type != SEVENWIRE)		/* xMII modes */
		rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE;
	if (fec->xcv_type == RGMII)
M
Marek Vasut 已提交
404 405 406 407 408 409 410
		rcntrl |= FEC_RCNTRL_RGMII;
	else if (fec->xcv_type == RMII)
		rcntrl |= FEC_RCNTRL_RMII;

	writel(rcntrl, &fec->eth->r_cntrl);
}

411 412 413 414
/**
 * Start the FEC engine
 * @param[in] dev Our device to handle
 */
415 416 417
#ifdef CONFIG_DM_ETH
static int fec_open(struct udevice *dev)
#else
418
static int fec_open(struct eth_device *edev)
419
#endif
420
{
421 422 423
#ifdef CONFIG_DM_ETH
	struct fec_priv *fec = dev_get_priv(dev);
#else
424
	struct fec_priv *fec = (struct fec_priv *)edev->priv;
425
#endif
426
	int speed;
427
	ulong addr, size;
428
	int i;
429 430 431 432 433 434

	debug("fec_open: fec_open(dev)\n");
	/* full-duplex, heartbeat disabled */
	writel(1 << 2, &fec->eth->x_cntrl);
	fec->rbd_index = 0;

435 436 437 438 439 440 441 442
	/* Invalidate all descriptors */
	for (i = 0; i < FEC_RBD_NUM - 1; i++)
		fec_rbd_clean(0, &fec->rbd_base[i]);
	fec_rbd_clean(1, &fec->rbd_base[i]);

	/* Flush the descriptors into RAM */
	size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd),
			ARCH_DMA_MINALIGN);
443
	addr = (ulong)fec->rbd_base;
444 445
	flush_dcache_range(addr, addr + size);

446
#ifdef FEC_QUIRK_ENET_MAC
447 448
	/* Enable ENET HW endian SWAP */
	writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_DBSWAP,
J
Jagan Teki 已提交
449
	       &fec->eth->ecntrl);
450 451
	/* Enable ENET store and forward mode */
	writel(readl(&fec->eth->x_wmrk) | FEC_X_WMRK_STRFWD,
J
Jagan Teki 已提交
452
	       &fec->eth->x_wmrk);
453
#endif
J
Jagan Teki 已提交
454
	/* Enable FEC-Lite controller */
455
	writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN,
J
Jagan Teki 已提交
456 457
	       &fec->eth->ecntrl);

458
#if defined(CONFIG_MX25) || defined(CONFIG_MX53) || defined(CONFIG_MX6SL)
J
John Rigby 已提交
459 460
	udelay(100);

J
Jagan Teki 已提交
461
	/* setup the MII gasket for RMII mode */
J
John Rigby 已提交
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
	/* disable the gasket */
	writew(0, &fec->eth->miigsk_enr);

	/* wait for the gasket to be disabled */
	while (readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY)
		udelay(2);

	/* configure gasket for RMII, 50 MHz, no loopback, and no echo */
	writew(MIIGSK_CFGR_IF_MODE_RMII, &fec->eth->miigsk_cfgr);

	/* re-enable the gasket */
	writew(MIIGSK_ENR_EN, &fec->eth->miigsk_enr);

	/* wait until MII gasket is ready */
	int max_loops = 10;
	while ((readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) == 0) {
		if (--max_loops <= 0) {
			printf("WAIT for MII Gasket ready timed out\n");
			break;
		}
	}
#endif
484

T
Troy Kisky 已提交
485
#ifdef CONFIG_PHYLIB
486
	{
T
Troy Kisky 已提交
487
		/* Start up the PHY */
488 489 490 491 492 493 494
		int ret = phy_startup(fec->phydev);

		if (ret) {
			printf("Could not initialize PHY %s\n",
			       fec->phydev->dev->name);
			return ret;
		}
T
Troy Kisky 已提交
495 496
		speed = fec->phydev->speed;
	}
497 498
#elif CONFIG_FEC_FIXED_SPEED
	speed = CONFIG_FEC_FIXED_SPEED;
T
Troy Kisky 已提交
499
#else
500
	miiphy_wait_aneg(edev);
501
	speed = miiphy_speed(edev->name, fec->phy_id);
M
Marek Vasut 已提交
502
	miiphy_duplex(edev->name, fec->phy_id);
T
Troy Kisky 已提交
503
#endif
504

505 506 507
#ifdef FEC_QUIRK_ENET_MAC
	{
		u32 ecr = readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_SPEED;
508
		u32 rcr = readl(&fec->eth->r_cntrl) & ~FEC_RCNTRL_RMII_10T;
509 510 511 512 513 514 515 516 517 518
		if (speed == _1000BASET)
			ecr |= FEC_ECNTRL_SPEED;
		else if (speed != _100BASET)
			rcr |= FEC_RCNTRL_RMII_10T;
		writel(ecr, &fec->eth->ecntrl);
		writel(rcr, &fec->eth->r_cntrl);
	}
#endif
	debug("%s:Speed=%i\n", __func__, speed);

J
Jagan Teki 已提交
519
	/* Enable SmartDMA receive task */
520 521 522 523 524 525
	fec_rx_task_enable(fec);

	udelay(100000);
	return 0;
}

526 527 528
#ifdef CONFIG_DM_ETH
static int fecmxc_init(struct udevice *dev)
#else
J
Jagan Teki 已提交
529
static int fec_init(struct eth_device *dev, bd_t *bd)
530
#endif
531
{
532 533 534
#ifdef CONFIG_DM_ETH
	struct fec_priv *fec = dev_get_priv(dev);
#else
535
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
536
#endif
537 538 539
	u8 *mib_ptr = (uint8_t *)&fec->eth->rmon_t_drop;
	u8 *i;
	ulong addr;
540

541
	/* Initialize MAC address */
542 543 544
#ifdef CONFIG_DM_ETH
	fecmxc_set_hwaddr(dev);
#else
545
	fec_set_hwaddr(dev);
546
#endif
547

J
Jagan Teki 已提交
548
	/* Setup transmit descriptors, there are two in total. */
M
Marek Vasut 已提交
549
	fec_tbd_init(fec);
550

M
Marek Vasut 已提交
551 552
	/* Setup receive descriptors. */
	fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE);
553

M
Marek Vasut 已提交
554
	fec_reg_setup(fec);
M
Marek Vasut 已提交
555

556
	if (fec->xcv_type != SEVENWIRE)
557
		fec_mii_setspeed(fec->bus->priv);
M
Marek Vasut 已提交
558

J
Jagan Teki 已提交
559
	/* Set Opcode/Pause Duration Register */
560 561
	writel(0x00010020, &fec->eth->op_pause);	/* FIXME 0xffff0020; */
	writel(0x2, &fec->eth->x_wmrk);
J
Jagan Teki 已提交
562 563

	/* Set multicast address filter */
564 565 566
	writel(0x00000000, &fec->eth->gaddr1);
	writel(0x00000000, &fec->eth->gaddr2);

567 568
	/* Do not access reserved register */
	if (!is_mx6ul() && !is_mx6ull() && !is_mx8m()) {
569 570 571
		/* clear MIB RAM */
		for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
			writel(0, i);
572

573 574 575
		/* FIFO receive start register */
		writel(0x520, &fec->eth->r_fstart);
	}
576 577 578

	/* size and address of each buffer */
	writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
579 580 581 582 583 584

	addr = (ulong)fec->tbd_base;
	writel((uint32_t)addr, &fec->eth->etdsr);

	addr = (ulong)fec->rbd_base;
	writel((uint32_t)addr, &fec->eth->erdsr);
585

T
Troy Kisky 已提交
586
#ifndef CONFIG_PHYLIB
587 588
	if (fec->xcv_type != SEVENWIRE)
		miiphy_restart_aneg(dev);
T
Troy Kisky 已提交
589
#endif
590 591 592 593 594 595 596 597
	fec_open(dev);
	return 0;
}

/**
 * Halt the FEC engine
 * @param[in] dev Our device to handle
 */
598 599 600
#ifdef CONFIG_DM_ETH
static void fecmxc_halt(struct udevice *dev)
#else
601
static void fec_halt(struct eth_device *dev)
602
#endif
603
{
604 605 606
#ifdef CONFIG_DM_ETH
	struct fec_priv *fec = dev_get_priv(dev);
#else
M
Marek Vasut 已提交
607
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
608
#endif
609 610
	int counter = 0xffff;

J
Jagan Teki 已提交
611
	/* issue graceful stop command to the FEC transmitter if necessary */
612
	writel(FEC_TCNTRL_GTS | readl(&fec->eth->x_cntrl),
J
Jagan Teki 已提交
613
	       &fec->eth->x_cntrl);
614 615

	debug("eth_halt: wait for stop regs\n");
J
Jagan Teki 已提交
616
	/* wait for graceful stop to register */
617
	while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA)))
618
		udelay(1);
619

J
Jagan Teki 已提交
620
	/* Disable SmartDMA tasks */
621 622 623 624 625 626 627
	fec_tx_task_disable(fec);
	fec_rx_task_disable(fec);

	/*
	 * Disable the Ethernet Controller
	 * Note: this will also reset the BD index counter!
	 */
J
John Rigby 已提交
628
	writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN,
J
Jagan Teki 已提交
629
	       &fec->eth->ecntrl);
630 631 632 633 634 635 636 637 638 639 640 641
	fec->rbd_index = 0;
	fec->tbd_index = 0;
	debug("eth_halt: done\n");
}

/**
 * Transmit one frame
 * @param[in] dev Our ethernet device to handle
 * @param[in] packet Pointer to the data to be transmitted
 * @param[in] length Data count in bytes
 * @return 0 on success
 */
642 643 644
#ifdef CONFIG_DM_ETH
static int fecmxc_send(struct udevice *dev, void *packet, int length)
#else
645
static int fec_send(struct eth_device *dev, void *packet, int length)
646
#endif
647 648
{
	unsigned int status;
649 650
	u32 size;
	ulong addr, end;
651 652
	int timeout = FEC_XFER_TIMEOUT;
	int ret = 0;
653 654 655 656 657

	/*
	 * This routine transmits one frame.  This routine only accepts
	 * 6-byte Ethernet addresses.
	 */
658 659 660
#ifdef CONFIG_DM_ETH
	struct fec_priv *fec = dev_get_priv(dev);
#else
661
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
662
#endif
663 664 665 666 667

	/*
	 * Check for valid length of data.
	 */
	if ((length > 1500) || (length <= 0)) {
668
		printf("Payload (%d) too large\n", length);
669 670 671 672
		return -1;
	}

	/*
673 674 675
	 * Setup the transmit buffer. We are always using the first buffer for
	 * transmission, the second will be empty and only used to stop the DMA
	 * engine. We also flush the packet to RAM here to avoid cache trouble.
676
	 */
677
#ifdef CONFIG_FEC_MXC_SWAP_PACKET
M
Marek Vasut 已提交
678 679
	swap_packet((uint32_t *)packet, length);
#endif
680

681
	addr = (ulong)packet;
682 683 684
	end = roundup(addr + length, ARCH_DMA_MINALIGN);
	addr &= ~(ARCH_DMA_MINALIGN - 1);
	flush_dcache_range(addr, end);
685

686
	writew(length, &fec->tbd_base[fec->tbd_index].data_length);
687
	writel((uint32_t)addr, &fec->tbd_base[fec->tbd_index].data_pointer);
688

689 690 691 692 693 694 695 696 697 698 699 700
	/*
	 * update BD's status now
	 * This block:
	 * - is always the last in a chain (means no chain)
	 * - should transmitt the CRC
	 * - might be the last BD in the list, so the address counter should
	 *   wrap (-> keep the WRAP flag)
	 */
	status = readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_WRAP;
	status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
	writew(status, &fec->tbd_base[fec->tbd_index].status);

701 702 703 704 705 706
	/*
	 * Flush data cache. This code flushes both TX descriptors to RAM.
	 * After this code, the descriptors will be safely in RAM and we
	 * can start DMA.
	 */
	size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
707
	addr = (ulong)fec->tbd_base;
708 709
	flush_dcache_range(addr, addr + size);

710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
	/*
	 * Below we read the DMA descriptor's last four bytes back from the
	 * DRAM. This is important in order to make sure that all WRITE
	 * operations on the bus that were triggered by previous cache FLUSH
	 * have completed.
	 *
	 * Otherwise, on MX28, it is possible to observe a corruption of the
	 * DMA descriptors. Please refer to schematic "Figure 1-2" in MX28RM
	 * for the bus structure of MX28. The scenario is as follows:
	 *
	 * 1) ARM core triggers a series of WRITEs on the AHB_ARB2 bus going
	 *    to DRAM due to flush_dcache_range()
	 * 2) ARM core writes the FEC registers via AHB_ARB2
	 * 3) FEC DMA starts reading/writing from/to DRAM via AHB_ARB3
	 *
	 * Note that 2) does sometimes finish before 1) due to reordering of
	 * WRITE accesses on the AHB bus, therefore triggering 3) before the
	 * DMA descriptor is fully written into DRAM. This results in occasional
	 * corruption of the DMA descriptor.
	 */
	readl(addr + size - 4);

J
Jagan Teki 已提交
732
	/* Enable SmartDMA transmit task */
733 734 735
	fec_tx_task_enable(fec);

	/*
736 737 738
	 * Wait until frame is sent. On each turn of the wait cycle, we must
	 * invalidate data cache to see what's really in RAM. Also, we need
	 * barrier here.
739
	 */
M
Marek Vasut 已提交
740
	while (--timeout) {
M
Marek Vasut 已提交
741
		if (!(readl(&fec->eth->x_des_active) & FEC_X_DES_ACTIVE_TDAR))
742
			break;
743
	}
744

745
	if (!timeout) {
M
Marek Vasut 已提交
746
		ret = -EINVAL;
747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
		goto out;
	}

	/*
	 * The TDAR bit is cleared when the descriptors are all out from TX
	 * but on mx6solox we noticed that the READY bit is still not cleared
	 * right after TDAR.
	 * These are two distinct signals, and in IC simulation, we found that
	 * TDAR always gets cleared prior than the READY bit of last BD becomes
	 * cleared.
	 * In mx6solox, we use a later version of FEC IP. It looks like that
	 * this intrinsic behaviour of TDAR bit has changed in this newer FEC
	 * version.
	 *
	 * Fix this by polling the READY bit of BD after the TDAR polling,
	 * which covers the mx6solox case and does not harm the other SoCs.
	 */
	timeout = FEC_XFER_TIMEOUT;
	while (--timeout) {
		invalidate_dcache_range(addr, addr + size);
		if (!(readw(&fec->tbd_base[fec->tbd_index].status) &
		    FEC_TBD_READY))
			break;
	}
M
Marek Vasut 已提交
771

772
	if (!timeout)
M
Marek Vasut 已提交
773 774
		ret = -EINVAL;

775
out:
M
Marek Vasut 已提交
776
	debug("fec_send: status 0x%x index %d ret %i\n",
J
Jagan Teki 已提交
777 778
	      readw(&fec->tbd_base[fec->tbd_index].status),
	      fec->tbd_index, ret);
779 780 781 782 783 784
	/* for next transmission use the other buffer */
	if (fec->tbd_index)
		fec->tbd_index = 0;
	else
		fec->tbd_index = 1;

785
	return ret;
786 787 788 789 790 791 792
}

/**
 * Pull one frame from the card
 * @param[in] dev Our ethernet device to handle
 * @return Length of packet read
 */
793 794 795
#ifdef CONFIG_DM_ETH
static int fecmxc_recv(struct udevice *dev, int flags, uchar **packetp)
#else
796
static int fec_recv(struct eth_device *dev)
797
#endif
798
{
799 800 801
#ifdef CONFIG_DM_ETH
	struct fec_priv *fec = dev_get_priv(dev);
#else
802
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
803
#endif
804 805 806 807
	struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
	unsigned long ievent;
	int frame_length, len = 0;
	uint16_t bd_status;
808
	ulong addr, size, end;
809
	int i;
810 811 812 813 814 815 816 817

#ifdef CONFIG_DM_ETH
	*packetp = memalign(ARCH_DMA_MINALIGN, FEC_MAX_PKT_SIZE);
	if (*packetp == 0) {
		printf("%s: error allocating packetp\n", __func__);
		return -ENOMEM;
	}
#else
818
	ALLOC_CACHE_ALIGN_BUFFER(uchar, buff, FEC_MAX_PKT_SIZE);
819
#endif
820

J
Jagan Teki 已提交
821
	/* Check if any critical events have happened */
822 823
	ievent = readl(&fec->eth->ievent);
	writel(ievent, &fec->eth->ievent);
M
Marek Vasut 已提交
824
	debug("fec_recv: ievent 0x%lx\n", ievent);
825
	if (ievent & FEC_IEVENT_BABR) {
826 827 828 829
#ifdef CONFIG_DM_ETH
		fecmxc_halt(dev);
		fecmxc_init(dev);
#else
830 831
		fec_halt(dev);
		fec_init(dev, fec->bd);
832
#endif
833 834 835 836 837 838
		printf("some error: 0x%08lx\n", ievent);
		return 0;
	}
	if (ievent & FEC_IEVENT_HBERR) {
		/* Heartbeat error */
		writel(0x00000001 | readl(&fec->eth->x_cntrl),
J
Jagan Teki 已提交
839
		       &fec->eth->x_cntrl);
840 841 842 843
	}
	if (ievent & FEC_IEVENT_GRA) {
		/* Graceful stop complete */
		if (readl(&fec->eth->x_cntrl) & 0x00000001) {
844 845 846
#ifdef CONFIG_DM_ETH
			fecmxc_halt(dev);
#else
847
			fec_halt(dev);
848
#endif
849
			writel(~0x00000001 & readl(&fec->eth->x_cntrl),
J
Jagan Teki 已提交
850
			       &fec->eth->x_cntrl);
851 852 853
#ifdef CONFIG_DM_ETH
			fecmxc_init(dev);
#else
854
			fec_init(dev, fec->bd);
855
#endif
856 857 858 859
		}
	}

	/*
860 861 862 863 864 865 866 867 868 869 870
	 * Read the buffer status. Before the status can be read, the data cache
	 * must be invalidated, because the data in RAM might have been changed
	 * by DMA. The descriptors are properly aligned to cachelines so there's
	 * no need to worry they'd overlap.
	 *
	 * WARNING: By invalidating the descriptor here, we also invalidate
	 * the descriptors surrounding this one. Therefore we can NOT change the
	 * contents of this descriptor nor the surrounding ones. The problem is
	 * that in order to mark the descriptor as processed, we need to change
	 * the descriptor. The solution is to mark the whole cache line when all
	 * descriptors in the cache line are processed.
871
	 */
872
	addr = (ulong)rbd;
873 874 875 876
	addr &= ~(ARCH_DMA_MINALIGN - 1);
	size = roundup(sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
	invalidate_dcache_range(addr, addr + size);

877 878 879 880 881
	bd_status = readw(&rbd->status);
	debug("fec_recv: status 0x%x\n", bd_status);

	if (!(bd_status & FEC_RBD_EMPTY)) {
		if ((bd_status & FEC_RBD_LAST) && !(bd_status & FEC_RBD_ERR) &&
J
Jagan Teki 已提交
882 883
		    ((readw(&rbd->data_length) - 4) > 14)) {
			/* Get buffer address and size */
884
			addr = readl(&rbd->data_pointer);
885
			frame_length = readw(&rbd->data_length) - 4;
J
Jagan Teki 已提交
886
			/* Invalidate data cache over the buffer */
887 888 889
			end = roundup(addr + frame_length, ARCH_DMA_MINALIGN);
			addr &= ~(ARCH_DMA_MINALIGN - 1);
			invalidate_dcache_range(addr, end);
890

J
Jagan Teki 已提交
891
			/* Fill the buffer and pass it to upper layers */
892
#ifdef CONFIG_FEC_MXC_SWAP_PACKET
893
			swap_packet((uint32_t *)addr, frame_length);
M
Marek Vasut 已提交
894
#endif
895 896 897 898

#ifdef CONFIG_DM_ETH
			memcpy(*packetp, (char *)addr, frame_length);
#else
899
			memcpy(buff, (char *)addr, frame_length);
900
			net_process_received_packet(buff, frame_length);
901
#endif
902 903 904
			len = frame_length;
		} else {
			if (bd_status & FEC_RBD_ERR)
905 906
				debug("error frame: 0x%08lx 0x%08x\n",
				      addr, bd_status);
907
		}
908

909
		/*
910 911 912 913
		 * Free the current buffer, restart the engine and move forward
		 * to the next buffer. Here we check if the whole cacheline of
		 * descriptors was already processed and if so, we mark it free
		 * as whole.
914
		 */
915 916 917
		size = RXDESC_PER_CACHELINE - 1;
		if ((fec->rbd_index & size) == size) {
			i = fec->rbd_index - size;
918
			addr = (ulong)&fec->rbd_base[i];
919 920 921 922 923
			for (; i <= fec->rbd_index ; i++) {
				fec_rbd_clean(i == (FEC_RBD_NUM - 1),
					      &fec->rbd_base[i]);
			}
			flush_dcache_range(addr,
J
Jagan Teki 已提交
924
					   addr + ARCH_DMA_MINALIGN);
925 926
		}

927 928 929 930 931 932 933 934
		fec_rx_task_enable(fec);
		fec->rbd_index = (fec->rbd_index + 1) % FEC_RBD_NUM;
	}
	debug("fec_recv: stop\n");

	return len;
}

935 936 937 938 939
static void fec_set_dev_name(char *dest, int dev_id)
{
	sprintf(dest, (dev_id == -1) ? "FEC" : "FEC%i", dev_id);
}

M
Marek Vasut 已提交
940 941 942 943 944
static int fec_alloc_descs(struct fec_priv *fec)
{
	unsigned int size;
	int i;
	uint8_t *data;
945
	ulong addr;
M
Marek Vasut 已提交
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963

	/* Allocate TX descriptors. */
	size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
	fec->tbd_base = memalign(ARCH_DMA_MINALIGN, size);
	if (!fec->tbd_base)
		goto err_tx;

	/* Allocate RX descriptors. */
	size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
	fec->rbd_base = memalign(ARCH_DMA_MINALIGN, size);
	if (!fec->rbd_base)
		goto err_rx;

	memset(fec->rbd_base, 0, size);

	/* Allocate RX buffers. */

	/* Maximum RX buffer size. */
964
	size = roundup(FEC_MAX_PKT_SIZE, FEC_DMA_RX_MINALIGN);
M
Marek Vasut 已提交
965
	for (i = 0; i < FEC_RBD_NUM; i++) {
966
		data = memalign(FEC_DMA_RX_MINALIGN, size);
M
Marek Vasut 已提交
967 968 969 970 971 972 973
		if (!data) {
			printf("%s: error allocating rxbuf %d\n", __func__, i);
			goto err_ring;
		}

		memset(data, 0, size);

974 975
		addr = (ulong)data;
		fec->rbd_base[i].data_pointer = (uint32_t)addr;
M
Marek Vasut 已提交
976 977 978
		fec->rbd_base[i].status = FEC_RBD_EMPTY;
		fec->rbd_base[i].data_length = 0;
		/* Flush the buffer to memory. */
979
		flush_dcache_range(addr, addr + size);
M
Marek Vasut 已提交
980 981 982 983 984 985 986 987 988 989 990
	}

	/* Mark the last RBD to close the ring. */
	fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;

	fec->rbd_index = 0;
	fec->tbd_index = 0;

	return 0;

err_ring:
991 992 993 994
	for (; i >= 0; i--) {
		addr = fec->rbd_base[i].data_pointer;
		free((void *)addr);
	}
M
Marek Vasut 已提交
995 996 997 998 999 1000 1001 1002 1003 1004
	free(fec->rbd_base);
err_rx:
	free(fec->tbd_base);
err_tx:
	return -ENOMEM;
}

static void fec_free_descs(struct fec_priv *fec)
{
	int i;
1005
	ulong addr;
M
Marek Vasut 已提交
1006

1007 1008 1009 1010
	for (i = 0; i < FEC_RBD_NUM; i++) {
		addr = fec->rbd_base[i].data_pointer;
		free((void *)addr);
	}
M
Marek Vasut 已提交
1011 1012 1013 1014
	free(fec->rbd_base);
	free(fec->tbd_base);
}

P
Peng Fan 已提交
1015
struct mii_dev *fec_get_miibus(ulong base_addr, int dev_id)
1016
{
P
Peng Fan 已提交
1017
	struct ethernet_regs *eth = (struct ethernet_regs *)base_addr;
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
	struct mii_dev *bus;
	int ret;

	bus = mdio_alloc();
	if (!bus) {
		printf("mdio_alloc failed\n");
		return NULL;
	}
	bus->read = fec_phy_read;
	bus->write = fec_phy_write;
	bus->priv = eth;
	fec_set_dev_name(bus->name, dev_id);

	ret = mdio_register(bus);
	if (ret) {
		printf("mdio_register failed\n");
		free(bus);
		return NULL;
	}
	fec_mii_setspeed(eth);
	return bus;
}

#ifndef CONFIG_DM_ETH
1042 1043 1044 1045 1046 1047 1048
#ifdef CONFIG_PHYLIB
int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
		struct mii_dev *bus, struct phy_device *phydev)
#else
static int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
		struct mii_dev *bus, int phy_id)
#endif
1049 1050
{
	struct eth_device *edev;
M
Marek Vasut 已提交
1051
	struct fec_priv *fec;
1052
	unsigned char ethaddr[6];
1053
	char mac[16];
M
Marek Vasut 已提交
1054 1055
	uint32_t start;
	int ret = 0;
1056 1057 1058 1059

	/* create and fill edev struct */
	edev = (struct eth_device *)malloc(sizeof(struct eth_device));
	if (!edev) {
M
Marek Vasut 已提交
1060
		puts("fec_mxc: not enough malloc memory for eth_device\n");
M
Marek Vasut 已提交
1061 1062
		ret = -ENOMEM;
		goto err1;
M
Marek Vasut 已提交
1063 1064 1065 1066 1067
	}

	fec = (struct fec_priv *)malloc(sizeof(struct fec_priv));
	if (!fec) {
		puts("fec_mxc: not enough malloc memory for fec_priv\n");
M
Marek Vasut 已提交
1068 1069
		ret = -ENOMEM;
		goto err2;
1070
	}
M
Marek Vasut 已提交
1071

1072
	memset(edev, 0, sizeof(*edev));
M
Marek Vasut 已提交
1073 1074
	memset(fec, 0, sizeof(*fec));

M
Marek Vasut 已提交
1075 1076 1077 1078
	ret = fec_alloc_descs(fec);
	if (ret)
		goto err3;

1079 1080 1081 1082 1083
	edev->priv = fec;
	edev->init = fec_init;
	edev->send = fec_send;
	edev->recv = fec_recv;
	edev->halt = fec_halt;
1084
	edev->write_hwaddr = fec_set_hwaddr;
1085

1086
	fec->eth = (struct ethernet_regs *)(ulong)base_addr;
1087 1088
	fec->bd = bd;

1089
	fec->xcv_type = CONFIG_FEC_XCV_TYPE;
1090 1091

	/* Reset chip. */
1092
	writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl);
M
Marek Vasut 已提交
1093 1094 1095
	start = get_timer(0);
	while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET) {
		if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
V
Vagrant Cascadian 已提交
1096
			printf("FEC MXC: Timeout resetting chip\n");
M
Marek Vasut 已提交
1097
			goto err4;
M
Marek Vasut 已提交
1098
		}
1099
		udelay(10);
M
Marek Vasut 已提交
1100
	}
1101

M
Marek Vasut 已提交
1102
	fec_reg_setup(fec);
1103 1104
	fec_set_dev_name(edev->name, dev_id);
	fec->dev_id = (dev_id == -1) ? 0 : dev_id;
1105 1106 1107 1108 1109 1110 1111 1112
	fec->bus = bus;
	fec_mii_setspeed(bus->priv);
#ifdef CONFIG_PHYLIB
	fec->phydev = phydev;
	phy_connect_dev(phydev, edev);
	/* Configure phy */
	phy_config(phydev);
#else
M
Marek Vasut 已提交
1113
	fec->phy_id = phy_id;
1114 1115
#endif
	eth_register(edev);
1116 1117
	/* only support one eth device, the index number pointed by dev_id */
	edev->index = fec->dev_id;
1118

1119 1120
	if (fec_get_hwaddr(fec->dev_id, ethaddr) == 0) {
		debug("got MAC%d address from fuse: %pM\n", fec->dev_id, ethaddr);
1121
		memcpy(edev->enetaddr, ethaddr, 6);
1122 1123 1124 1125
		if (fec->dev_id)
			sprintf(mac, "eth%daddr", fec->dev_id);
		else
			strcpy(mac, "ethaddr");
1126
		if (!env_get(mac))
1127
			eth_env_set_enetaddr(mac, ethaddr);
1128 1129
	}
	return ret;
M
Marek Vasut 已提交
1130 1131
err4:
	fec_free_descs(fec);
1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
err3:
	free(fec);
err2:
	free(edev);
err1:
	return ret;
}

int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
{
	uint32_t base_mii;
	struct mii_dev *bus = NULL;
#ifdef CONFIG_PHYLIB
	struct phy_device *phydev = NULL;
#endif
	int ret;

1149
#ifdef CONFIG_FEC_MXC_MDIO_BASE
T
Troy Kisky 已提交
1150 1151 1152 1153
	/*
	 * The i.MX28 has two ethernet interfaces, but they are not equal.
	 * Only the first one can access the MDIO bus.
	 */
1154
	base_mii = CONFIG_FEC_MXC_MDIO_BASE;
T
Troy Kisky 已提交
1155
#else
1156
	base_mii = addr;
T
Troy Kisky 已提交
1157
#endif
1158 1159 1160 1161
	debug("eth_init: fec_probe(bd, %i, %i) @ %08x\n", dev_id, phy_id, addr);
	bus = fec_get_miibus(base_mii, dev_id);
	if (!bus)
		return -ENOMEM;
1162
#ifdef CONFIG_PHYLIB
1163
	phydev = phy_find_by_mask(bus, 1 << phy_id, PHY_INTERFACE_MODE_RGMII);
1164
	if (!phydev) {
1165
		mdio_unregister(bus);
1166
		free(bus);
1167
		return -ENOMEM;
1168
	}
1169 1170 1171
	ret = fec_probe(bd, dev_id, addr, bus, phydev);
#else
	ret = fec_probe(bd, dev_id, addr, bus, phy_id);
1172
#endif
1173 1174 1175 1176
	if (ret) {
#ifdef CONFIG_PHYLIB
		free(phydev);
#endif
1177
		mdio_unregister(bus);
1178 1179
		free(bus);
	}
M
Marek Vasut 已提交
1180
	return ret;
1181
}
1182

1183 1184 1185 1186 1187
#ifdef CONFIG_FEC_MXC_PHYADDR
int fecmxc_initialize(bd_t *bd)
{
	return fecmxc_initialize_multi(bd, -1, CONFIG_FEC_MXC_PHYADDR,
			IMX_FEC_BASE);
1188
}
1189
#endif
1190

T
Troy Kisky 已提交
1191
#ifndef CONFIG_PHYLIB
1192 1193 1194 1195 1196 1197
int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))
{
	struct fec_priv *fec = (struct fec_priv *)dev->priv;
	fec->mii_postcall = cb;
	return 0;
}
T
Troy Kisky 已提交
1198
#endif
1199 1200 1201

#else

J
Jagan Teki 已提交
1202 1203 1204 1205 1206 1207 1208 1209
static int fecmxc_read_rom_hwaddr(struct udevice *dev)
{
	struct fec_priv *priv = dev_get_priv(dev);
	struct eth_pdata *pdata = dev_get_platdata(dev);

	return fec_get_hwaddr(priv->dev_id, pdata->enetaddr);
}

1210 1211 1212 1213 1214 1215 1216 1217
static int fecmxc_free_pkt(struct udevice *dev, uchar *packet, int length)
{
	if (packet)
		free(packet);

	return 0;
}

1218 1219 1220 1221
static const struct eth_ops fecmxc_ops = {
	.start			= fecmxc_init,
	.send			= fecmxc_send,
	.recv			= fecmxc_recv,
1222
	.free_pkt		= fecmxc_free_pkt,
1223 1224
	.stop			= fecmxc_halt,
	.write_hwaddr		= fecmxc_set_hwaddr,
J
Jagan Teki 已提交
1225
	.read_rom_hwaddr	= fecmxc_read_rom_hwaddr,
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
};

static int fec_phy_init(struct fec_priv *priv, struct udevice *dev)
{
	struct phy_device *phydev;
	int mask = 0xffffffff;

#ifdef CONFIG_PHYLIB
	mask = 1 << CONFIG_FEC_MXC_PHYADDR;
#endif

	phydev = phy_find_by_mask(priv->bus, mask, priv->interface);
	if (!phydev)
		return -ENODEV;

	phy_connect_dev(phydev, dev);

	priv->phydev = phydev;
	phy_config(phydev);

	return 0;
}

static int fecmxc_probe(struct udevice *dev)
{
	struct eth_pdata *pdata = dev_get_platdata(dev);
	struct fec_priv *priv = dev_get_priv(dev);
	struct mii_dev *bus = NULL;
	uint32_t start;
	int ret;

	ret = fec_alloc_descs(priv);
	if (ret)
		return ret;

	/* Reset chip. */
J
Jagan Teki 已提交
1262 1263
	writel(readl(&priv->eth->ecntrl) | FEC_ECNTRL_RESET,
	       &priv->eth->ecntrl);
1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
	start = get_timer(0);
	while (readl(&priv->eth->ecntrl) & FEC_ECNTRL_RESET) {
		if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
			printf("FEC MXC: Timeout reseting chip\n");
			goto err_timeout;
		}
		udelay(10);
	}

	fec_reg_setup(priv);

1275
	priv->dev_id = dev->seq;
1276 1277 1278
#ifdef CONFIG_FEC_MXC_MDIO_BASE
	bus = fec_get_miibus((ulong)CONFIG_FEC_MXC_MDIO_BASE, dev->seq);
#else
1279
	bus = fec_get_miibus((ulong)priv->eth, dev->seq);
1280
#endif
1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292
	if (!bus) {
		ret = -ENOMEM;
		goto err_mii;
	}

	priv->bus = bus;
	priv->xcv_type = CONFIG_FEC_XCV_TYPE;
	priv->interface = pdata->phy_interface;
	ret = fec_phy_init(priv, dev);
	if (ret)
		goto err_phy;

1293 1294 1295 1296 1297 1298
	return 0;

err_phy:
	mdio_unregister(bus);
	free(bus);
err_mii:
Y
Ye Li 已提交
1299
err_timeout:
1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
	fec_free_descs(priv);
	return ret;
}

static int fecmxc_remove(struct udevice *dev)
{
	struct fec_priv *priv = dev_get_priv(dev);

	free(priv->phydev);
	fec_free_descs(priv);
	mdio_unregister(priv->bus);
	mdio_free(priv->bus);

	return 0;
}

static int fecmxc_ofdata_to_platdata(struct udevice *dev)
{
	struct eth_pdata *pdata = dev_get_platdata(dev);
	struct fec_priv *priv = dev_get_priv(dev);
	const char *phy_mode;

S
Simon Glass 已提交
1322
	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
1323 1324 1325
	priv->eth = (struct ethernet_regs *)pdata->iobase;

	pdata->phy_interface = -1;
1326 1327
	phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
			       NULL);
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344
	if (phy_mode)
		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
	if (pdata->phy_interface == -1) {
		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
		return -EINVAL;
	}

	/* TODO
	 * Need to get the reset-gpio and related properties from DT
	 * and implemet the enet reset code on .probe call
	 */

	return 0;
}

static const struct udevice_id fecmxc_ids[] = {
	{ .compatible = "fsl,imx6q-fec" },
1345 1346 1347
	{ .compatible = "fsl,imx6sl-fec" },
	{ .compatible = "fsl,imx6sx-fec" },
	{ .compatible = "fsl,imx6ul-fec" },
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
	{ }
};

U_BOOT_DRIVER(fecmxc_gem) = {
	.name	= "fecmxc",
	.id	= UCLASS_ETH,
	.of_match = fecmxc_ids,
	.ofdata_to_platdata = fecmxc_ofdata_to_platdata,
	.probe	= fecmxc_probe,
	.remove	= fecmxc_remove,
	.ops	= &fecmxc_ops,
	.priv_auto_alloc_size = sizeof(struct fec_priv),
	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
};
#endif