blob: d3a926dc73731269e14915b8477527cad5b10111 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Ilya Yanoke93a4a52009-07-21 19:32:21 +04002/*
3 * (C) Copyright 2009 Ilya Yanok, Emcraft Systems Ltd <yanok@emcraft.com>
4 * (C) Copyright 2008,2009 Eric Jarrige <eric.jarrige@armadeus.org>
5 * (C) Copyright 2008 Armadeus Systems nc
6 * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
7 * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.de>
Ilya Yanoke93a4a52009-07-21 19:32:21 +04008 */
9
10#include <common.h>
Jagan Teki484f0212016-12-06 00:00:49 +010011#include <dm.h>
Alex Kiernan9c215492018-04-01 09:22:38 +000012#include <environment.h>
Ilya Yanoke93a4a52009-07-21 19:32:21 +040013#include <malloc.h>
Simon Glass2dd337a2015-09-02 17:24:58 -060014#include <memalign.h>
Jagan Tekic6cd8d52016-12-06 00:00:50 +010015#include <miiphy.h>
Ilya Yanoke93a4a52009-07-21 19:32:21 +040016#include <net.h>
Jeroen Hofstee120f43f2014-10-08 22:57:40 +020017#include <netdev.h>
Martin Fuzzey9a6a2c92018-10-04 19:59:20 +020018#include <power/regulator.h>
Ilya Yanoke93a4a52009-07-21 19:32:21 +040019
Ilya Yanoke93a4a52009-07-21 19:32:21 +040020#include <asm/io.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090021#include <linux/errno.h>
Marek Vasut4d85b032012-08-26 10:19:20 +000022#include <linux/compiler.h>
Ilya Yanoke93a4a52009-07-21 19:32:21 +040023
Jagan Tekic6cd8d52016-12-06 00:00:50 +010024#include <asm/arch/clock.h>
25#include <asm/arch/imx-regs.h>
Stefano Babic33731bc2017-06-29 10:16:06 +020026#include <asm/mach-imx/sys_proto.h>
Michael Trimarchi0e5cccf2018-06-17 15:22:39 +020027#include <asm-generic/gpio.h>
28
29#include "fec_mxc.h"
Jagan Tekic6cd8d52016-12-06 00:00:50 +010030
Ilya Yanoke93a4a52009-07-21 19:32:21 +040031DECLARE_GLOBAL_DATA_PTR;
32
Marek Vasut5f1631d2012-08-29 03:49:49 +000033/*
34 * Timeout the transfer after 5 mS. This is usually a bit more, since
35 * the code in the tightloops this timeout is used in adds some overhead.
36 */
37#define FEC_XFER_TIMEOUT 5000
38
Fabio Estevam8b798b22014-08-25 13:34:16 -030039/*
40 * The standard 32-byte DMA alignment does not work on mx6solox, which requires
41 * 64-byte alignment in the DMA RX FEC buffer.
42 * Introduce the FEC_DMA_RX_MINALIGN which can cover mx6solox needs and also
43 * satisfies the alignment on other SoCs (32-bytes)
44 */
45#define FEC_DMA_RX_MINALIGN 64
46
Ilya Yanoke93a4a52009-07-21 19:32:21 +040047#ifndef CONFIG_MII
48#error "CONFIG_MII has to be defined!"
49#endif
50
Eric Nelson3d2f7272012-03-15 18:33:25 +000051#ifndef CONFIG_FEC_XCV_TYPE
52#define CONFIG_FEC_XCV_TYPE MII100
Marek Vasutdbb4fce2011-09-11 18:05:33 +000053#endif
54
Marek Vasut6a5fd4c2011-11-08 23:18:10 +000055/*
56 * The i.MX28 operates with packets in big endian. We need to swap them before
57 * sending and after receiving.
58 */
Eric Nelson3d2f7272012-03-15 18:33:25 +000059#ifdef CONFIG_MX28
60#define CONFIG_FEC_MXC_SWAP_PACKET
Marek Vasut6a5fd4c2011-11-08 23:18:10 +000061#endif
62
Eric Nelson3d2f7272012-03-15 18:33:25 +000063#define RXDESC_PER_CACHELINE (ARCH_DMA_MINALIGN/sizeof(struct fec_bd))
64
65/* Check various alignment issues at compile time */
66#if ((ARCH_DMA_MINALIGN < 16) || (ARCH_DMA_MINALIGN % 16 != 0))
67#error "ARCH_DMA_MINALIGN must be multiple of 16!"
68#endif
69
70#if ((PKTALIGN < ARCH_DMA_MINALIGN) || \
71 (PKTALIGN % ARCH_DMA_MINALIGN != 0))
72#error "PKTALIGN must be multiple of ARCH_DMA_MINALIGN!"
73#endif
74
Ilya Yanoke93a4a52009-07-21 19:32:21 +040075#undef DEBUG
76
Eric Nelson3d2f7272012-03-15 18:33:25 +000077#ifdef CONFIG_FEC_MXC_SWAP_PACKET
Marek Vasut6a5fd4c2011-11-08 23:18:10 +000078static void swap_packet(uint32_t *packet, int length)
79{
80 int i;
81
82 for (i = 0; i < DIV_ROUND_UP(length, 4); i++)
83 packet[i] = __swab32(packet[i]);
84}
85#endif
86
Jagan Tekic6cd8d52016-12-06 00:00:50 +010087/* MII-interface related functions */
88static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyaddr,
89 uint8_t regaddr)
Ilya Yanoke93a4a52009-07-21 19:32:21 +040090{
Ilya Yanoke93a4a52009-07-21 19:32:21 +040091 uint32_t reg; /* convenient holder for the PHY register */
92 uint32_t phy; /* convenient holder for the PHY */
93 uint32_t start;
Troy Kisky2000c662012-02-07 14:08:47 +000094 int val;
Ilya Yanoke93a4a52009-07-21 19:32:21 +040095
96 /*
97 * reading from any PHY's register is done by properly
98 * programming the FEC's MII data register.
99 */
Marek Vasutbf2386b2011-09-11 18:05:34 +0000100 writel(FEC_IEVENT_MII, &eth->ievent);
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100101 reg = regaddr << FEC_MII_DATA_RA_SHIFT;
102 phy = phyaddr << FEC_MII_DATA_PA_SHIFT;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400103
104 writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA |
Marek Vasutbf2386b2011-09-11 18:05:34 +0000105 phy | reg, &eth->mii_data);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400106
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100107 /* wait for the related interrupt */
Graeme Russf8b82ee2011-07-15 23:31:37 +0000108 start = get_timer(0);
Marek Vasutbf2386b2011-09-11 18:05:34 +0000109 while (!(readl(&eth->ievent) & FEC_IEVENT_MII)) {
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400110 if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
111 printf("Read MDIO failed...\n");
112 return -1;
113 }
114 }
115
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100116 /* clear mii interrupt bit */
Marek Vasutbf2386b2011-09-11 18:05:34 +0000117 writel(FEC_IEVENT_MII, &eth->ievent);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400118
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100119 /* it's now safe to read the PHY's register */
Troy Kisky2000c662012-02-07 14:08:47 +0000120 val = (unsigned short)readl(&eth->mii_data);
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100121 debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyaddr,
122 regaddr, val);
Troy Kisky2000c662012-02-07 14:08:47 +0000123 return val;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400124}
125
Troy Kisky5e762652012-10-22 16:40:41 +0000126static void fec_mii_setspeed(struct ethernet_regs *eth)
Stefano Babic889f2e22010-02-01 14:51:30 +0100127{
128 /*
129 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
130 * and do not drop the Preamble.
Måns Rullgård4aeddb72015-12-08 15:38:45 +0000131 *
132 * The i.MX28 and i.MX6 types have another field in the MSCR (aka
133 * MII_SPEED) register that defines the MDIO output hold time. Earlier
134 * versions are RAZ there, so just ignore the difference and write the
135 * register always.
136 * The minimal hold time according to IEE802.3 (clause 22) is 10 ns.
137 * HOLDTIME + 1 is the number of clk cycles the fec is holding the
138 * output.
139 * The HOLDTIME bitfield takes values between 0 and 7 (inclusive).
140 * Given that ceil(clkrate / 5000000) <= 64, the calculation for
141 * holdtime cannot result in a value greater than 3.
Stefano Babic889f2e22010-02-01 14:51:30 +0100142 */
Måns Rullgård4aeddb72015-12-08 15:38:45 +0000143 u32 pclk = imx_get_fecclk();
144 u32 speed = DIV_ROUND_UP(pclk, 5000000);
145 u32 hold = DIV_ROUND_UP(pclk, 100000000) - 1;
Markus Niebel1af82742014-02-05 10:54:11 +0100146#ifdef FEC_QUIRK_ENET_MAC
147 speed--;
148#endif
Måns Rullgård4aeddb72015-12-08 15:38:45 +0000149 writel(speed << 1 | hold << 8, &eth->mii_speed);
Troy Kisky5e762652012-10-22 16:40:41 +0000150 debug("%s: mii_speed %08x\n", __func__, readl(&eth->mii_speed));
Stefano Babic889f2e22010-02-01 14:51:30 +0100151}
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400152
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100153static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyaddr,
154 uint8_t regaddr, uint16_t data)
Troy Kisky2000c662012-02-07 14:08:47 +0000155{
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400156 uint32_t reg; /* convenient holder for the PHY register */
157 uint32_t phy; /* convenient holder for the PHY */
158 uint32_t start;
159
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100160 reg = regaddr << FEC_MII_DATA_RA_SHIFT;
161 phy = phyaddr << FEC_MII_DATA_PA_SHIFT;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400162
163 writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
Marek Vasutbf2386b2011-09-11 18:05:34 +0000164 FEC_MII_DATA_TA | phy | reg | data, &eth->mii_data);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400165
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100166 /* wait for the MII interrupt */
Graeme Russf8b82ee2011-07-15 23:31:37 +0000167 start = get_timer(0);
Marek Vasutbf2386b2011-09-11 18:05:34 +0000168 while (!(readl(&eth->ievent) & FEC_IEVENT_MII)) {
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400169 if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
170 printf("Write MDIO failed...\n");
171 return -1;
172 }
173 }
174
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100175 /* clear MII interrupt bit */
Marek Vasutbf2386b2011-09-11 18:05:34 +0000176 writel(FEC_IEVENT_MII, &eth->ievent);
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100177 debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyaddr,
178 regaddr, data);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400179
180 return 0;
181}
182
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100183static int fec_phy_read(struct mii_dev *bus, int phyaddr, int dev_addr,
184 int regaddr)
Troy Kisky2000c662012-02-07 14:08:47 +0000185{
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100186 return fec_mdio_read(bus->priv, phyaddr, regaddr);
Troy Kisky2000c662012-02-07 14:08:47 +0000187}
188
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100189static int fec_phy_write(struct mii_dev *bus, int phyaddr, int dev_addr,
190 int regaddr, u16 data)
Troy Kisky2000c662012-02-07 14:08:47 +0000191{
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100192 return fec_mdio_write(bus->priv, phyaddr, regaddr, data);
Troy Kisky2000c662012-02-07 14:08:47 +0000193}
194
195#ifndef CONFIG_PHYLIB
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400196static int miiphy_restart_aneg(struct eth_device *dev)
197{
Stefano Babicd6228172012-02-22 00:24:35 +0000198 int ret = 0;
199#if !defined(CONFIG_FEC_MXC_NO_ANEG)
Marek Vasutedcd6c02011-09-16 01:13:47 +0200200 struct fec_priv *fec = (struct fec_priv *)dev->priv;
Troy Kisky2000c662012-02-07 14:08:47 +0000201 struct ethernet_regs *eth = fec->bus->priv;
Marek Vasutedcd6c02011-09-16 01:13:47 +0200202
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400203 /*
204 * Wake up from sleep if necessary
205 * Reset PHY, then delay 300ns
206 */
John Rigbye650e492010-01-25 23:12:55 -0700207#ifdef CONFIG_MX27
Troy Kisky2000c662012-02-07 14:08:47 +0000208 fec_mdio_write(eth, fec->phy_id, MII_DCOUNTER, 0x00FF);
John Rigbye650e492010-01-25 23:12:55 -0700209#endif
Troy Kisky2000c662012-02-07 14:08:47 +0000210 fec_mdio_write(eth, fec->phy_id, MII_BMCR, BMCR_RESET);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400211 udelay(1000);
212
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100213 /* Set the auto-negotiation advertisement register bits */
Troy Kisky2000c662012-02-07 14:08:47 +0000214 fec_mdio_write(eth, fec->phy_id, MII_ADVERTISE,
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100215 LPA_100FULL | LPA_100HALF | LPA_10FULL |
216 LPA_10HALF | PHY_ANLPAR_PSB_802_3);
Troy Kisky2000c662012-02-07 14:08:47 +0000217 fec_mdio_write(eth, fec->phy_id, MII_BMCR,
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100218 BMCR_ANENABLE | BMCR_ANRESTART);
Marek Vasut539ecee2011-09-11 18:05:36 +0000219
220 if (fec->mii_postcall)
221 ret = fec->mii_postcall(fec->phy_id);
222
Stefano Babicd6228172012-02-22 00:24:35 +0000223#endif
Marek Vasut539ecee2011-09-11 18:05:36 +0000224 return ret;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400225}
226
Hannes Schmelzer5a15c1a2016-06-22 12:07:14 +0200227#ifndef CONFIG_FEC_FIXED_SPEED
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400228static int miiphy_wait_aneg(struct eth_device *dev)
229{
230 uint32_t start;
Troy Kisky2000c662012-02-07 14:08:47 +0000231 int status;
Marek Vasutedcd6c02011-09-16 01:13:47 +0200232 struct fec_priv *fec = (struct fec_priv *)dev->priv;
Troy Kisky2000c662012-02-07 14:08:47 +0000233 struct ethernet_regs *eth = fec->bus->priv;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400234
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100235 /* Wait for AN completion */
Graeme Russf8b82ee2011-07-15 23:31:37 +0000236 start = get_timer(0);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400237 do {
238 if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
239 printf("%s: Autonegotiation timeout\n", dev->name);
240 return -1;
241 }
242
Troy Kisky2000c662012-02-07 14:08:47 +0000243 status = fec_mdio_read(eth, fec->phy_id, MII_BMSR);
244 if (status < 0) {
245 printf("%s: Autonegotiation failed. status: %d\n",
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100246 dev->name, status);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400247 return -1;
248 }
Mike Frysingerd63ee712010-12-23 15:40:12 -0500249 } while (!(status & BMSR_LSTATUS));
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400250
251 return 0;
252}
Hannes Schmelzer5a15c1a2016-06-22 12:07:14 +0200253#endif /* CONFIG_FEC_FIXED_SPEED */
Troy Kisky2000c662012-02-07 14:08:47 +0000254#endif
255
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400256static int fec_rx_task_enable(struct fec_priv *fec)
257{
Marek Vasutc1582c02012-08-29 03:49:51 +0000258 writel(FEC_R_DES_ACTIVE_RDAR, &fec->eth->r_des_active);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400259 return 0;
260}
261
262static int fec_rx_task_disable(struct fec_priv *fec)
263{
264 return 0;
265}
266
267static int fec_tx_task_enable(struct fec_priv *fec)
268{
Marek Vasutc1582c02012-08-29 03:49:51 +0000269 writel(FEC_X_DES_ACTIVE_TDAR, &fec->eth->x_des_active);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400270 return 0;
271}
272
273static int fec_tx_task_disable(struct fec_priv *fec)
274{
275 return 0;
276}
277
278/**
279 * Initialize receive task's buffer descriptors
280 * @param[in] fec all we know about the device yet
281 * @param[in] count receive buffer count to be allocated
Eric Nelson3d2f7272012-03-15 18:33:25 +0000282 * @param[in] dsize desired size of each receive buffer
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400283 * @return 0 on success
284 *
Marek Vasut03880452013-10-12 20:36:25 +0200285 * Init all RX descriptors to default values.
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400286 */
Marek Vasut03880452013-10-12 20:36:25 +0200287static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400288{
Eric Nelson3d2f7272012-03-15 18:33:25 +0000289 uint32_t size;
Ye Lie2670912018-01-10 13:20:44 +0800290 ulong data;
Eric Nelson3d2f7272012-03-15 18:33:25 +0000291 int i;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400292
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400293 /*
Marek Vasut03880452013-10-12 20:36:25 +0200294 * Reload the RX descriptors with default values and wipe
295 * the RX buffers.
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400296 */
Eric Nelson3d2f7272012-03-15 18:33:25 +0000297 size = roundup(dsize, ARCH_DMA_MINALIGN);
298 for (i = 0; i < count; i++) {
Ye Lie2670912018-01-10 13:20:44 +0800299 data = fec->rbd_base[i].data_pointer;
300 memset((void *)data, 0, dsize);
301 flush_dcache_range(data, data + size);
Marek Vasut03880452013-10-12 20:36:25 +0200302
303 fec->rbd_base[i].status = FEC_RBD_EMPTY;
304 fec->rbd_base[i].data_length = 0;
Eric Nelson3d2f7272012-03-15 18:33:25 +0000305 }
306
307 /* Mark the last RBD to close the ring. */
Marek Vasut03880452013-10-12 20:36:25 +0200308 fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400309 fec->rbd_index = 0;
310
Ye Lie2670912018-01-10 13:20:44 +0800311 flush_dcache_range((ulong)fec->rbd_base,
312 (ulong)fec->rbd_base + size);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400313}
314
315/**
316 * Initialize transmit task's buffer descriptors
317 * @param[in] fec all we know about the device yet
318 *
319 * Transmit buffers are created externally. We only have to init the BDs here.\n
320 * Note: There is a race condition in the hardware. When only one BD is in
321 * use it must be marked with the WRAP bit to use it for every transmitt.
322 * This bit in combination with the READY bit results into double transmit
323 * of each data buffer. It seems the state machine checks READY earlier then
324 * resetting it after the first transfer.
325 * Using two BDs solves this issue.
326 */
327static void fec_tbd_init(struct fec_priv *fec)
328{
Ye Lie2670912018-01-10 13:20:44 +0800329 ulong addr = (ulong)fec->tbd_base;
Eric Nelson3d2f7272012-03-15 18:33:25 +0000330 unsigned size = roundup(2 * sizeof(struct fec_bd),
331 ARCH_DMA_MINALIGN);
Marek Vasut03880452013-10-12 20:36:25 +0200332
333 memset(fec->tbd_base, 0, size);
334 fec->tbd_base[0].status = 0;
335 fec->tbd_base[1].status = FEC_TBD_WRAP;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400336 fec->tbd_index = 0;
Marek Vasut03880452013-10-12 20:36:25 +0200337 flush_dcache_range(addr, addr + size);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400338}
339
340/**
341 * Mark the given read buffer descriptor as free
342 * @param[in] last 1 if this is the last buffer descriptor in the chain, else 0
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100343 * @param[in] prbd buffer descriptor to mark free again
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400344 */
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100345static void fec_rbd_clean(int last, struct fec_bd *prbd)
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400346{
Eric Nelson3d2f7272012-03-15 18:33:25 +0000347 unsigned short flags = FEC_RBD_EMPTY;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400348 if (last)
Eric Nelson3d2f7272012-03-15 18:33:25 +0000349 flags |= FEC_RBD_WRAP;
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100350 writew(flags, &prbd->status);
351 writew(0, &prbd->data_length);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400352}
353
Jagan Tekibc5fb462016-12-06 00:00:48 +0100354static int fec_get_hwaddr(int dev_id, unsigned char *mac)
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400355{
Fabio Estevam04fc1282011-12-20 05:46:31 +0000356 imx_get_mac_from_fuse(dev_id, mac);
Joe Hershberger8ecdbed2015-04-08 01:41:04 -0500357 return !is_valid_ethaddr(mac);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400358}
359
Jagan Teki484f0212016-12-06 00:00:49 +0100360#ifdef CONFIG_DM_ETH
361static int fecmxc_set_hwaddr(struct udevice *dev)
362#else
Stefano Babic889f2e22010-02-01 14:51:30 +0100363static int fec_set_hwaddr(struct eth_device *dev)
Jagan Teki484f0212016-12-06 00:00:49 +0100364#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400365{
Jagan Teki484f0212016-12-06 00:00:49 +0100366#ifdef CONFIG_DM_ETH
367 struct fec_priv *fec = dev_get_priv(dev);
368 struct eth_pdata *pdata = dev_get_platdata(dev);
369 uchar *mac = pdata->enetaddr;
370#else
Stefano Babic889f2e22010-02-01 14:51:30 +0100371 uchar *mac = dev->enetaddr;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400372 struct fec_priv *fec = (struct fec_priv *)dev->priv;
Jagan Teki484f0212016-12-06 00:00:49 +0100373#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400374
375 writel(0, &fec->eth->iaddr1);
376 writel(0, &fec->eth->iaddr2);
377 writel(0, &fec->eth->gaddr1);
378 writel(0, &fec->eth->gaddr2);
379
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100380 /* Set physical address */
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400381 writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3],
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100382 &fec->eth->paddr1);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400383 writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, &fec->eth->paddr2);
384
385 return 0;
386}
387
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100388/* Do initial configuration of the FEC registers */
Marek Vasut335cbd22012-05-01 11:09:41 +0000389static void fec_reg_setup(struct fec_priv *fec)
390{
391 uint32_t rcntrl;
392
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100393 /* Set interrupt mask register */
Marek Vasut335cbd22012-05-01 11:09:41 +0000394 writel(0x00000000, &fec->eth->imask);
395
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100396 /* Clear FEC-Lite interrupt event register(IEVENT) */
Marek Vasut335cbd22012-05-01 11:09:41 +0000397 writel(0xffffffff, &fec->eth->ievent);
398
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100399 /* Set FEC-Lite receive control register(R_CNTRL): */
Marek Vasut335cbd22012-05-01 11:09:41 +0000400
401 /* Start with frame length = 1518, common for all modes. */
402 rcntrl = PKTSIZE << FEC_RCNTRL_MAX_FL_SHIFT;
benoit.thebaudeau@advansacc7a282012-07-19 02:12:46 +0000403 if (fec->xcv_type != SEVENWIRE) /* xMII modes */
404 rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE;
405 if (fec->xcv_type == RGMII)
Marek Vasut335cbd22012-05-01 11:09:41 +0000406 rcntrl |= FEC_RCNTRL_RGMII;
407 else if (fec->xcv_type == RMII)
408 rcntrl |= FEC_RCNTRL_RMII;
Marek Vasut335cbd22012-05-01 11:09:41 +0000409
410 writel(rcntrl, &fec->eth->r_cntrl);
411}
412
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400413/**
414 * Start the FEC engine
415 * @param[in] dev Our device to handle
416 */
Jagan Teki484f0212016-12-06 00:00:49 +0100417#ifdef CONFIG_DM_ETH
418static int fec_open(struct udevice *dev)
419#else
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400420static int fec_open(struct eth_device *edev)
Jagan Teki484f0212016-12-06 00:00:49 +0100421#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400422{
Jagan Teki484f0212016-12-06 00:00:49 +0100423#ifdef CONFIG_DM_ETH
424 struct fec_priv *fec = dev_get_priv(dev);
425#else
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400426 struct fec_priv *fec = (struct fec_priv *)edev->priv;
Jagan Teki484f0212016-12-06 00:00:49 +0100427#endif
Troy Kisky01112132012-02-07 14:08:46 +0000428 int speed;
Ye Lie2670912018-01-10 13:20:44 +0800429 ulong addr, size;
Eric Nelson3d2f7272012-03-15 18:33:25 +0000430 int i;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400431
432 debug("fec_open: fec_open(dev)\n");
433 /* full-duplex, heartbeat disabled */
434 writel(1 << 2, &fec->eth->x_cntrl);
435 fec->rbd_index = 0;
436
Eric Nelson3d2f7272012-03-15 18:33:25 +0000437 /* Invalidate all descriptors */
438 for (i = 0; i < FEC_RBD_NUM - 1; i++)
439 fec_rbd_clean(0, &fec->rbd_base[i]);
440 fec_rbd_clean(1, &fec->rbd_base[i]);
441
442 /* Flush the descriptors into RAM */
443 size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd),
444 ARCH_DMA_MINALIGN);
Ye Lie2670912018-01-10 13:20:44 +0800445 addr = (ulong)fec->rbd_base;
Eric Nelson3d2f7272012-03-15 18:33:25 +0000446 flush_dcache_range(addr, addr + size);
447
Troy Kisky01112132012-02-07 14:08:46 +0000448#ifdef FEC_QUIRK_ENET_MAC
Jason Liubbcef6c2011-12-16 05:17:07 +0000449 /* Enable ENET HW endian SWAP */
450 writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_DBSWAP,
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100451 &fec->eth->ecntrl);
Jason Liubbcef6c2011-12-16 05:17:07 +0000452 /* Enable ENET store and forward mode */
453 writel(readl(&fec->eth->x_wmrk) | FEC_X_WMRK_STRFWD,
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100454 &fec->eth->x_wmrk);
Jason Liubbcef6c2011-12-16 05:17:07 +0000455#endif
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100456 /* Enable FEC-Lite controller */
John Rigbye650e492010-01-25 23:12:55 -0700457 writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN,
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100458 &fec->eth->ecntrl);
459
Fabio Estevam84c1f522013-09-13 00:36:27 -0300460#if defined(CONFIG_MX25) || defined(CONFIG_MX53) || defined(CONFIG_MX6SL)
John Rigby99d5fed2010-01-25 23:12:57 -0700461 udelay(100);
John Rigby99d5fed2010-01-25 23:12:57 -0700462
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100463 /* setup the MII gasket for RMII mode */
John Rigby99d5fed2010-01-25 23:12:57 -0700464 /* disable the gasket */
465 writew(0, &fec->eth->miigsk_enr);
466
467 /* wait for the gasket to be disabled */
468 while (readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY)
469 udelay(2);
470
471 /* configure gasket for RMII, 50 MHz, no loopback, and no echo */
472 writew(MIIGSK_CFGR_IF_MODE_RMII, &fec->eth->miigsk_cfgr);
473
474 /* re-enable the gasket */
475 writew(MIIGSK_ENR_EN, &fec->eth->miigsk_enr);
476
477 /* wait until MII gasket is ready */
478 int max_loops = 10;
479 while ((readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) == 0) {
480 if (--max_loops <= 0) {
481 printf("WAIT for MII Gasket ready timed out\n");
482 break;
483 }
484 }
485#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400486
Troy Kisky2000c662012-02-07 14:08:47 +0000487#ifdef CONFIG_PHYLIB
Troy Kisky2c42b3c2012-10-22 16:40:45 +0000488 {
Troy Kisky2000c662012-02-07 14:08:47 +0000489 /* Start up the PHY */
Timur Tabi42387462012-07-09 08:52:43 +0000490 int ret = phy_startup(fec->phydev);
491
492 if (ret) {
493 printf("Could not initialize PHY %s\n",
494 fec->phydev->dev->name);
495 return ret;
496 }
Troy Kisky2000c662012-02-07 14:08:47 +0000497 speed = fec->phydev->speed;
Troy Kisky2000c662012-02-07 14:08:47 +0000498 }
Hannes Schmelzer5a15c1a2016-06-22 12:07:14 +0200499#elif CONFIG_FEC_FIXED_SPEED
500 speed = CONFIG_FEC_FIXED_SPEED;
Troy Kisky2000c662012-02-07 14:08:47 +0000501#else
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400502 miiphy_wait_aneg(edev);
Troy Kisky01112132012-02-07 14:08:46 +0000503 speed = miiphy_speed(edev->name, fec->phy_id);
Marek Vasutedcd6c02011-09-16 01:13:47 +0200504 miiphy_duplex(edev->name, fec->phy_id);
Troy Kisky2000c662012-02-07 14:08:47 +0000505#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400506
Troy Kisky01112132012-02-07 14:08:46 +0000507#ifdef FEC_QUIRK_ENET_MAC
508 {
509 u32 ecr = readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_SPEED;
Alison Wang89d932a2013-05-27 22:55:43 +0000510 u32 rcr = readl(&fec->eth->r_cntrl) & ~FEC_RCNTRL_RMII_10T;
Troy Kisky01112132012-02-07 14:08:46 +0000511 if (speed == _1000BASET)
512 ecr |= FEC_ECNTRL_SPEED;
513 else if (speed != _100BASET)
514 rcr |= FEC_RCNTRL_RMII_10T;
515 writel(ecr, &fec->eth->ecntrl);
516 writel(rcr, &fec->eth->r_cntrl);
517 }
518#endif
519 debug("%s:Speed=%i\n", __func__, speed);
520
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100521 /* Enable SmartDMA receive task */
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400522 fec_rx_task_enable(fec);
523
524 udelay(100000);
525 return 0;
526}
527
Jagan Teki484f0212016-12-06 00:00:49 +0100528#ifdef CONFIG_DM_ETH
529static int fecmxc_init(struct udevice *dev)
530#else
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100531static int fec_init(struct eth_device *dev, bd_t *bd)
Jagan Teki484f0212016-12-06 00:00:49 +0100532#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400533{
Jagan Teki484f0212016-12-06 00:00:49 +0100534#ifdef CONFIG_DM_ETH
535 struct fec_priv *fec = dev_get_priv(dev);
536#else
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400537 struct fec_priv *fec = (struct fec_priv *)dev->priv;
Jagan Teki484f0212016-12-06 00:00:49 +0100538#endif
Ye Lie2670912018-01-10 13:20:44 +0800539 u8 *mib_ptr = (uint8_t *)&fec->eth->rmon_t_drop;
540 u8 *i;
541 ulong addr;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400542
John Rigbya4a30552010-10-13 14:31:08 -0600543 /* Initialize MAC address */
Jagan Teki484f0212016-12-06 00:00:49 +0100544#ifdef CONFIG_DM_ETH
545 fecmxc_set_hwaddr(dev);
546#else
John Rigbya4a30552010-10-13 14:31:08 -0600547 fec_set_hwaddr(dev);
Jagan Teki484f0212016-12-06 00:00:49 +0100548#endif
John Rigbya4a30552010-10-13 14:31:08 -0600549
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100550 /* Setup transmit descriptors, there are two in total. */
Marek Vasut03880452013-10-12 20:36:25 +0200551 fec_tbd_init(fec);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400552
Marek Vasut03880452013-10-12 20:36:25 +0200553 /* Setup receive descriptors. */
554 fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400555
Marek Vasut335cbd22012-05-01 11:09:41 +0000556 fec_reg_setup(fec);
Marek Vasutb8f88562011-09-11 18:05:31 +0000557
benoit.thebaudeau@advans551bb362012-07-19 02:12:58 +0000558 if (fec->xcv_type != SEVENWIRE)
Troy Kisky5e762652012-10-22 16:40:41 +0000559 fec_mii_setspeed(fec->bus->priv);
Marek Vasutb8f88562011-09-11 18:05:31 +0000560
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100561 /* Set Opcode/Pause Duration Register */
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400562 writel(0x00010020, &fec->eth->op_pause); /* FIXME 0xffff0020; */
563 writel(0x2, &fec->eth->x_wmrk);
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100564
565 /* Set multicast address filter */
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400566 writel(0x00000000, &fec->eth->gaddr1);
567 writel(0x00000000, &fec->eth->gaddr2);
568
Peng Fanbf8e58b2018-01-10 13:20:43 +0800569 /* Do not access reserved register */
570 if (!is_mx6ul() && !is_mx6ull() && !is_mx8m()) {
Peng Fan13433fd2015-08-12 17:46:51 +0800571 /* clear MIB RAM */
572 for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
573 writel(0, i);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400574
Peng Fan13433fd2015-08-12 17:46:51 +0800575 /* FIFO receive start register */
576 writel(0x520, &fec->eth->r_fstart);
577 }
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400578
579 /* size and address of each buffer */
580 writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
Ye Lie2670912018-01-10 13:20:44 +0800581
582 addr = (ulong)fec->tbd_base;
583 writel((uint32_t)addr, &fec->eth->etdsr);
584
585 addr = (ulong)fec->rbd_base;
586 writel((uint32_t)addr, &fec->eth->erdsr);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400587
Troy Kisky2000c662012-02-07 14:08:47 +0000588#ifndef CONFIG_PHYLIB
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400589 if (fec->xcv_type != SEVENWIRE)
590 miiphy_restart_aneg(dev);
Troy Kisky2000c662012-02-07 14:08:47 +0000591#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400592 fec_open(dev);
593 return 0;
594}
595
596/**
597 * Halt the FEC engine
598 * @param[in] dev Our device to handle
599 */
Jagan Teki484f0212016-12-06 00:00:49 +0100600#ifdef CONFIG_DM_ETH
601static void fecmxc_halt(struct udevice *dev)
602#else
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400603static void fec_halt(struct eth_device *dev)
Jagan Teki484f0212016-12-06 00:00:49 +0100604#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400605{
Jagan Teki484f0212016-12-06 00:00:49 +0100606#ifdef CONFIG_DM_ETH
607 struct fec_priv *fec = dev_get_priv(dev);
608#else
Marek Vasutedcd6c02011-09-16 01:13:47 +0200609 struct fec_priv *fec = (struct fec_priv *)dev->priv;
Jagan Teki484f0212016-12-06 00:00:49 +0100610#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400611 int counter = 0xffff;
612
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100613 /* issue graceful stop command to the FEC transmitter if necessary */
John Rigbye650e492010-01-25 23:12:55 -0700614 writel(FEC_TCNTRL_GTS | readl(&fec->eth->x_cntrl),
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100615 &fec->eth->x_cntrl);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400616
617 debug("eth_halt: wait for stop regs\n");
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100618 /* wait for graceful stop to register */
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400619 while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA)))
John Rigbye650e492010-01-25 23:12:55 -0700620 udelay(1);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400621
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100622 /* Disable SmartDMA tasks */
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400623 fec_tx_task_disable(fec);
624 fec_rx_task_disable(fec);
625
626 /*
627 * Disable the Ethernet Controller
628 * Note: this will also reset the BD index counter!
629 */
John Rigby99d5fed2010-01-25 23:12:57 -0700630 writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN,
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100631 &fec->eth->ecntrl);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400632 fec->rbd_index = 0;
633 fec->tbd_index = 0;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400634 debug("eth_halt: done\n");
635}
636
637/**
638 * Transmit one frame
639 * @param[in] dev Our ethernet device to handle
640 * @param[in] packet Pointer to the data to be transmitted
641 * @param[in] length Data count in bytes
642 * @return 0 on success
643 */
Jagan Teki484f0212016-12-06 00:00:49 +0100644#ifdef CONFIG_DM_ETH
645static int fecmxc_send(struct udevice *dev, void *packet, int length)
646#else
Joe Hershberger7c31bd12012-05-21 14:45:27 +0000647static int fec_send(struct eth_device *dev, void *packet, int length)
Jagan Teki484f0212016-12-06 00:00:49 +0100648#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400649{
650 unsigned int status;
Ye Lie2670912018-01-10 13:20:44 +0800651 u32 size;
652 ulong addr, end;
Marek Vasut5f1631d2012-08-29 03:49:49 +0000653 int timeout = FEC_XFER_TIMEOUT;
654 int ret = 0;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400655
656 /*
657 * This routine transmits one frame. This routine only accepts
658 * 6-byte Ethernet addresses.
659 */
Jagan Teki484f0212016-12-06 00:00:49 +0100660#ifdef CONFIG_DM_ETH
661 struct fec_priv *fec = dev_get_priv(dev);
662#else
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400663 struct fec_priv *fec = (struct fec_priv *)dev->priv;
Jagan Teki484f0212016-12-06 00:00:49 +0100664#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400665
666 /*
667 * Check for valid length of data.
668 */
669 if ((length > 1500) || (length <= 0)) {
Stefano Babic889f2e22010-02-01 14:51:30 +0100670 printf("Payload (%d) too large\n", length);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400671 return -1;
672 }
673
674 /*
Eric Nelson3d2f7272012-03-15 18:33:25 +0000675 * Setup the transmit buffer. We are always using the first buffer for
676 * transmission, the second will be empty and only used to stop the DMA
677 * engine. We also flush the packet to RAM here to avoid cache trouble.
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400678 */
Eric Nelson3d2f7272012-03-15 18:33:25 +0000679#ifdef CONFIG_FEC_MXC_SWAP_PACKET
Marek Vasut6a5fd4c2011-11-08 23:18:10 +0000680 swap_packet((uint32_t *)packet, length);
681#endif
Eric Nelson3d2f7272012-03-15 18:33:25 +0000682
Ye Lie2670912018-01-10 13:20:44 +0800683 addr = (ulong)packet;
Marek Vasut4325d242012-08-26 10:19:21 +0000684 end = roundup(addr + length, ARCH_DMA_MINALIGN);
685 addr &= ~(ARCH_DMA_MINALIGN - 1);
686 flush_dcache_range(addr, end);
Eric Nelson3d2f7272012-03-15 18:33:25 +0000687
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400688 writew(length, &fec->tbd_base[fec->tbd_index].data_length);
Ye Lie2670912018-01-10 13:20:44 +0800689 writel((uint32_t)addr, &fec->tbd_base[fec->tbd_index].data_pointer);
Eric Nelson3d2f7272012-03-15 18:33:25 +0000690
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400691 /*
692 * update BD's status now
693 * This block:
694 * - is always the last in a chain (means no chain)
695 * - should transmitt the CRC
696 * - might be the last BD in the list, so the address counter should
697 * wrap (-> keep the WRAP flag)
698 */
699 status = readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_WRAP;
700 status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
701 writew(status, &fec->tbd_base[fec->tbd_index].status);
702
703 /*
Eric Nelson3d2f7272012-03-15 18:33:25 +0000704 * Flush data cache. This code flushes both TX descriptors to RAM.
705 * After this code, the descriptors will be safely in RAM and we
706 * can start DMA.
707 */
708 size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
Ye Lie2670912018-01-10 13:20:44 +0800709 addr = (ulong)fec->tbd_base;
Eric Nelson3d2f7272012-03-15 18:33:25 +0000710 flush_dcache_range(addr, addr + size);
711
712 /*
Marek Vasutd521b3c2013-07-12 01:03:04 +0200713 * Below we read the DMA descriptor's last four bytes back from the
714 * DRAM. This is important in order to make sure that all WRITE
715 * operations on the bus that were triggered by previous cache FLUSH
716 * have completed.
717 *
718 * Otherwise, on MX28, it is possible to observe a corruption of the
719 * DMA descriptors. Please refer to schematic "Figure 1-2" in MX28RM
720 * for the bus structure of MX28. The scenario is as follows:
721 *
722 * 1) ARM core triggers a series of WRITEs on the AHB_ARB2 bus going
723 * to DRAM due to flush_dcache_range()
724 * 2) ARM core writes the FEC registers via AHB_ARB2
725 * 3) FEC DMA starts reading/writing from/to DRAM via AHB_ARB3
726 *
727 * Note that 2) does sometimes finish before 1) due to reordering of
728 * WRITE accesses on the AHB bus, therefore triggering 3) before the
729 * DMA descriptor is fully written into DRAM. This results in occasional
730 * corruption of the DMA descriptor.
731 */
732 readl(addr + size - 4);
733
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100734 /* Enable SmartDMA transmit task */
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400735 fec_tx_task_enable(fec);
736
737 /*
Eric Nelson3d2f7272012-03-15 18:33:25 +0000738 * Wait until frame is sent. On each turn of the wait cycle, we must
739 * invalidate data cache to see what's really in RAM. Also, we need
740 * barrier here.
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400741 */
Marek Vasut9bf7bf02012-08-29 03:49:50 +0000742 while (--timeout) {
Marek Vasutc1582c02012-08-29 03:49:51 +0000743 if (!(readl(&fec->eth->x_des_active) & FEC_X_DES_ACTIVE_TDAR))
Marek Vasut5f1631d2012-08-29 03:49:49 +0000744 break;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400745 }
Eric Nelson3d2f7272012-03-15 18:33:25 +0000746
Fabio Estevamc34e99f2014-08-25 13:34:17 -0300747 if (!timeout) {
Marek Vasut9bf7bf02012-08-29 03:49:50 +0000748 ret = -EINVAL;
Fabio Estevamc34e99f2014-08-25 13:34:17 -0300749 goto out;
750 }
Marek Vasut9bf7bf02012-08-29 03:49:50 +0000751
Fabio Estevamc34e99f2014-08-25 13:34:17 -0300752 /*
753 * The TDAR bit is cleared when the descriptors are all out from TX
754 * but on mx6solox we noticed that the READY bit is still not cleared
755 * right after TDAR.
756 * These are two distinct signals, and in IC simulation, we found that
757 * TDAR always gets cleared prior than the READY bit of last BD becomes
758 * cleared.
759 * In mx6solox, we use a later version of FEC IP. It looks like that
760 * this intrinsic behaviour of TDAR bit has changed in this newer FEC
761 * version.
762 *
763 * Fix this by polling the READY bit of BD after the TDAR polling,
764 * which covers the mx6solox case and does not harm the other SoCs.
765 */
766 timeout = FEC_XFER_TIMEOUT;
767 while (--timeout) {
768 invalidate_dcache_range(addr, addr + size);
769 if (!(readw(&fec->tbd_base[fec->tbd_index].status) &
770 FEC_TBD_READY))
771 break;
772 }
773
774 if (!timeout)
Marek Vasut9bf7bf02012-08-29 03:49:50 +0000775 ret = -EINVAL;
776
Fabio Estevamc34e99f2014-08-25 13:34:17 -0300777out:
Marek Vasut9bf7bf02012-08-29 03:49:50 +0000778 debug("fec_send: status 0x%x index %d ret %i\n",
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100779 readw(&fec->tbd_base[fec->tbd_index].status),
780 fec->tbd_index, ret);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400781 /* for next transmission use the other buffer */
782 if (fec->tbd_index)
783 fec->tbd_index = 0;
784 else
785 fec->tbd_index = 1;
786
Marek Vasut5f1631d2012-08-29 03:49:49 +0000787 return ret;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400788}
789
790/**
791 * Pull one frame from the card
792 * @param[in] dev Our ethernet device to handle
793 * @return Length of packet read
794 */
Jagan Teki484f0212016-12-06 00:00:49 +0100795#ifdef CONFIG_DM_ETH
796static int fecmxc_recv(struct udevice *dev, int flags, uchar **packetp)
797#else
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400798static int fec_recv(struct eth_device *dev)
Jagan Teki484f0212016-12-06 00:00:49 +0100799#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400800{
Jagan Teki484f0212016-12-06 00:00:49 +0100801#ifdef CONFIG_DM_ETH
802 struct fec_priv *fec = dev_get_priv(dev);
803#else
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400804 struct fec_priv *fec = (struct fec_priv *)dev->priv;
Jagan Teki484f0212016-12-06 00:00:49 +0100805#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400806 struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
807 unsigned long ievent;
808 int frame_length, len = 0;
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400809 uint16_t bd_status;
Ye Lie2670912018-01-10 13:20:44 +0800810 ulong addr, size, end;
Eric Nelson3d2f7272012-03-15 18:33:25 +0000811 int i;
Ye Libd7e5382018-03-28 20:54:11 +0800812
813#ifdef CONFIG_DM_ETH
814 *packetp = memalign(ARCH_DMA_MINALIGN, FEC_MAX_PKT_SIZE);
815 if (*packetp == 0) {
816 printf("%s: error allocating packetp\n", __func__);
817 return -ENOMEM;
818 }
819#else
Fabio Estevamcc956082013-09-17 23:13:10 -0300820 ALLOC_CACHE_ALIGN_BUFFER(uchar, buff, FEC_MAX_PKT_SIZE);
Ye Libd7e5382018-03-28 20:54:11 +0800821#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400822
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100823 /* Check if any critical events have happened */
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400824 ievent = readl(&fec->eth->ievent);
825 writel(ievent, &fec->eth->ievent);
Marek Vasut478e2d02011-10-24 23:40:03 +0000826 debug("fec_recv: ievent 0x%lx\n", ievent);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400827 if (ievent & FEC_IEVENT_BABR) {
Jagan Teki484f0212016-12-06 00:00:49 +0100828#ifdef CONFIG_DM_ETH
829 fecmxc_halt(dev);
830 fecmxc_init(dev);
831#else
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400832 fec_halt(dev);
833 fec_init(dev, fec->bd);
Jagan Teki484f0212016-12-06 00:00:49 +0100834#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400835 printf("some error: 0x%08lx\n", ievent);
836 return 0;
837 }
838 if (ievent & FEC_IEVENT_HBERR) {
839 /* Heartbeat error */
840 writel(0x00000001 | readl(&fec->eth->x_cntrl),
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100841 &fec->eth->x_cntrl);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400842 }
843 if (ievent & FEC_IEVENT_GRA) {
844 /* Graceful stop complete */
845 if (readl(&fec->eth->x_cntrl) & 0x00000001) {
Jagan Teki484f0212016-12-06 00:00:49 +0100846#ifdef CONFIG_DM_ETH
847 fecmxc_halt(dev);
848#else
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400849 fec_halt(dev);
Jagan Teki484f0212016-12-06 00:00:49 +0100850#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400851 writel(~0x00000001 & readl(&fec->eth->x_cntrl),
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100852 &fec->eth->x_cntrl);
Jagan Teki484f0212016-12-06 00:00:49 +0100853#ifdef CONFIG_DM_ETH
854 fecmxc_init(dev);
855#else
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400856 fec_init(dev, fec->bd);
Jagan Teki484f0212016-12-06 00:00:49 +0100857#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400858 }
859 }
860
861 /*
Eric Nelson3d2f7272012-03-15 18:33:25 +0000862 * Read the buffer status. Before the status can be read, the data cache
863 * must be invalidated, because the data in RAM might have been changed
864 * by DMA. The descriptors are properly aligned to cachelines so there's
865 * no need to worry they'd overlap.
866 *
867 * WARNING: By invalidating the descriptor here, we also invalidate
868 * the descriptors surrounding this one. Therefore we can NOT change the
869 * contents of this descriptor nor the surrounding ones. The problem is
870 * that in order to mark the descriptor as processed, we need to change
871 * the descriptor. The solution is to mark the whole cache line when all
872 * descriptors in the cache line are processed.
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400873 */
Ye Lie2670912018-01-10 13:20:44 +0800874 addr = (ulong)rbd;
Eric Nelson3d2f7272012-03-15 18:33:25 +0000875 addr &= ~(ARCH_DMA_MINALIGN - 1);
876 size = roundup(sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
877 invalidate_dcache_range(addr, addr + size);
878
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400879 bd_status = readw(&rbd->status);
880 debug("fec_recv: status 0x%x\n", bd_status);
881
882 if (!(bd_status & FEC_RBD_EMPTY)) {
883 if ((bd_status & FEC_RBD_LAST) && !(bd_status & FEC_RBD_ERR) &&
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100884 ((readw(&rbd->data_length) - 4) > 14)) {
885 /* Get buffer address and size */
Albert ARIBAUD \(3ADEV\)13420302015-06-19 14:18:27 +0200886 addr = readl(&rbd->data_pointer);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400887 frame_length = readw(&rbd->data_length) - 4;
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100888 /* Invalidate data cache over the buffer */
Marek Vasut4325d242012-08-26 10:19:21 +0000889 end = roundup(addr + frame_length, ARCH_DMA_MINALIGN);
890 addr &= ~(ARCH_DMA_MINALIGN - 1);
891 invalidate_dcache_range(addr, end);
Eric Nelson3d2f7272012-03-15 18:33:25 +0000892
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100893 /* Fill the buffer and pass it to upper layers */
Eric Nelson3d2f7272012-03-15 18:33:25 +0000894#ifdef CONFIG_FEC_MXC_SWAP_PACKET
Albert ARIBAUD \(3ADEV\)13420302015-06-19 14:18:27 +0200895 swap_packet((uint32_t *)addr, frame_length);
Marek Vasut6a5fd4c2011-11-08 23:18:10 +0000896#endif
Ye Libd7e5382018-03-28 20:54:11 +0800897
898#ifdef CONFIG_DM_ETH
899 memcpy(*packetp, (char *)addr, frame_length);
900#else
Albert ARIBAUD \(3ADEV\)13420302015-06-19 14:18:27 +0200901 memcpy(buff, (char *)addr, frame_length);
Joe Hershberger9f09a362015-04-08 01:41:06 -0500902 net_process_received_packet(buff, frame_length);
Ye Libd7e5382018-03-28 20:54:11 +0800903#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400904 len = frame_length;
905 } else {
906 if (bd_status & FEC_RBD_ERR)
Ye Lie2670912018-01-10 13:20:44 +0800907 debug("error frame: 0x%08lx 0x%08x\n",
908 addr, bd_status);
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400909 }
Eric Nelson3d2f7272012-03-15 18:33:25 +0000910
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400911 /*
Eric Nelson3d2f7272012-03-15 18:33:25 +0000912 * Free the current buffer, restart the engine and move forward
913 * to the next buffer. Here we check if the whole cacheline of
914 * descriptors was already processed and if so, we mark it free
915 * as whole.
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400916 */
Eric Nelson3d2f7272012-03-15 18:33:25 +0000917 size = RXDESC_PER_CACHELINE - 1;
918 if ((fec->rbd_index & size) == size) {
919 i = fec->rbd_index - size;
Ye Lie2670912018-01-10 13:20:44 +0800920 addr = (ulong)&fec->rbd_base[i];
Eric Nelson3d2f7272012-03-15 18:33:25 +0000921 for (; i <= fec->rbd_index ; i++) {
922 fec_rbd_clean(i == (FEC_RBD_NUM - 1),
923 &fec->rbd_base[i]);
924 }
925 flush_dcache_range(addr,
Jagan Tekic6cd8d52016-12-06 00:00:50 +0100926 addr + ARCH_DMA_MINALIGN);
Eric Nelson3d2f7272012-03-15 18:33:25 +0000927 }
928
Ilya Yanoke93a4a52009-07-21 19:32:21 +0400929 fec_rx_task_enable(fec);
930 fec->rbd_index = (fec->rbd_index + 1) % FEC_RBD_NUM;
931 }
932 debug("fec_recv: stop\n");
933
934 return len;
935}
936
Troy Kisky4c2ddec2012-10-22 16:40:44 +0000937static void fec_set_dev_name(char *dest, int dev_id)
938{
939 sprintf(dest, (dev_id == -1) ? "FEC" : "FEC%i", dev_id);
940}
941
Marek Vasut03880452013-10-12 20:36:25 +0200942static int fec_alloc_descs(struct fec_priv *fec)
943{
944 unsigned int size;
945 int i;
946 uint8_t *data;
Ye Lie2670912018-01-10 13:20:44 +0800947 ulong addr;
Marek Vasut03880452013-10-12 20:36:25 +0200948
949 /* Allocate TX descriptors. */
950 size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
951 fec->tbd_base = memalign(ARCH_DMA_MINALIGN, size);
952 if (!fec->tbd_base)
953 goto err_tx;
954
955 /* Allocate RX descriptors. */
956 size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
957 fec->rbd_base = memalign(ARCH_DMA_MINALIGN, size);
958 if (!fec->rbd_base)
959 goto err_rx;
960
961 memset(fec->rbd_base, 0, size);
962
963 /* Allocate RX buffers. */
964
965 /* Maximum RX buffer size. */
Fabio Estevam8b798b22014-08-25 13:34:16 -0300966 size = roundup(FEC_MAX_PKT_SIZE, FEC_DMA_RX_MINALIGN);
Marek Vasut03880452013-10-12 20:36:25 +0200967 for (i = 0; i < FEC_RBD_NUM; i++) {
Fabio Estevam8b798b22014-08-25 13:34:16 -0300968 data = memalign(FEC_DMA_RX_MINALIGN, size);
Marek Vasut03880452013-10-12 20:36:25 +0200969 if (!data) {
970 printf("%s: error allocating rxbuf %d\n", __func__, i);
971 goto err_ring;
972 }
973
974 memset(data, 0, size);
975
Ye Lie2670912018-01-10 13:20:44 +0800976 addr = (ulong)data;
977 fec->rbd_base[i].data_pointer = (uint32_t)addr;
Marek Vasut03880452013-10-12 20:36:25 +0200978 fec->rbd_base[i].status = FEC_RBD_EMPTY;
979 fec->rbd_base[i].data_length = 0;
980 /* Flush the buffer to memory. */
Ye Lie2670912018-01-10 13:20:44 +0800981 flush_dcache_range(addr, addr + size);
Marek Vasut03880452013-10-12 20:36:25 +0200982 }
983
984 /* Mark the last RBD to close the ring. */
985 fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;
986
987 fec->rbd_index = 0;
988 fec->tbd_index = 0;
989
990 return 0;
991
992err_ring:
Ye Lie2670912018-01-10 13:20:44 +0800993 for (; i >= 0; i--) {
994 addr = fec->rbd_base[i].data_pointer;
995 free((void *)addr);
996 }
Marek Vasut03880452013-10-12 20:36:25 +0200997 free(fec->rbd_base);
998err_rx:
999 free(fec->tbd_base);
1000err_tx:
1001 return -ENOMEM;
1002}
1003
1004static void fec_free_descs(struct fec_priv *fec)
1005{
1006 int i;
Ye Lie2670912018-01-10 13:20:44 +08001007 ulong addr;
Marek Vasut03880452013-10-12 20:36:25 +02001008
Ye Lie2670912018-01-10 13:20:44 +08001009 for (i = 0; i < FEC_RBD_NUM; i++) {
1010 addr = fec->rbd_base[i].data_pointer;
1011 free((void *)addr);
1012 }
Marek Vasut03880452013-10-12 20:36:25 +02001013 free(fec->rbd_base);
1014 free(fec->tbd_base);
1015}
1016
Peng Fan0c59c4f2018-03-28 20:54:12 +08001017struct mii_dev *fec_get_miibus(ulong base_addr, int dev_id)
Jagan Teki484f0212016-12-06 00:00:49 +01001018{
Peng Fan0c59c4f2018-03-28 20:54:12 +08001019 struct ethernet_regs *eth = (struct ethernet_regs *)base_addr;
Jagan Teki484f0212016-12-06 00:00:49 +01001020 struct mii_dev *bus;
1021 int ret;
1022
1023 bus = mdio_alloc();
1024 if (!bus) {
1025 printf("mdio_alloc failed\n");
1026 return NULL;
1027 }
1028 bus->read = fec_phy_read;
1029 bus->write = fec_phy_write;
1030 bus->priv = eth;
1031 fec_set_dev_name(bus->name, dev_id);
1032
1033 ret = mdio_register(bus);
1034 if (ret) {
1035 printf("mdio_register failed\n");
1036 free(bus);
1037 return NULL;
1038 }
1039 fec_mii_setspeed(eth);
1040 return bus;
1041}
1042
1043#ifndef CONFIG_DM_ETH
Troy Kiskydce4def2012-10-22 16:40:46 +00001044#ifdef CONFIG_PHYLIB
1045int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
1046 struct mii_dev *bus, struct phy_device *phydev)
1047#else
1048static int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
1049 struct mii_dev *bus, int phy_id)
1050#endif
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001051{
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001052 struct eth_device *edev;
Marek Vasutedcd6c02011-09-16 01:13:47 +02001053 struct fec_priv *fec;
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001054 unsigned char ethaddr[6];
Andy Duan8f8e4582017-04-10 19:44:35 +08001055 char mac[16];
Marek Vasut43b10302011-09-11 18:05:37 +00001056 uint32_t start;
1057 int ret = 0;
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001058
1059 /* create and fill edev struct */
1060 edev = (struct eth_device *)malloc(sizeof(struct eth_device));
1061 if (!edev) {
Marek Vasutedcd6c02011-09-16 01:13:47 +02001062 puts("fec_mxc: not enough malloc memory for eth_device\n");
Marek Vasut43b10302011-09-11 18:05:37 +00001063 ret = -ENOMEM;
1064 goto err1;
Marek Vasutedcd6c02011-09-16 01:13:47 +02001065 }
1066
1067 fec = (struct fec_priv *)malloc(sizeof(struct fec_priv));
1068 if (!fec) {
1069 puts("fec_mxc: not enough malloc memory for fec_priv\n");
Marek Vasut43b10302011-09-11 18:05:37 +00001070 ret = -ENOMEM;
1071 goto err2;
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001072 }
Marek Vasutedcd6c02011-09-16 01:13:47 +02001073
Nobuhiro Iwamatsu1843c5b2010-10-19 14:03:42 +09001074 memset(edev, 0, sizeof(*edev));
Marek Vasutedcd6c02011-09-16 01:13:47 +02001075 memset(fec, 0, sizeof(*fec));
1076
Marek Vasut03880452013-10-12 20:36:25 +02001077 ret = fec_alloc_descs(fec);
1078 if (ret)
1079 goto err3;
1080
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001081 edev->priv = fec;
1082 edev->init = fec_init;
1083 edev->send = fec_send;
1084 edev->recv = fec_recv;
1085 edev->halt = fec_halt;
Heiko Schocher9ada5e62010-04-27 07:43:52 +02001086 edev->write_hwaddr = fec_set_hwaddr;
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001087
Ye Lie2670912018-01-10 13:20:44 +08001088 fec->eth = (struct ethernet_regs *)(ulong)base_addr;
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001089 fec->bd = bd;
1090
Marek Vasutdbb4fce2011-09-11 18:05:33 +00001091 fec->xcv_type = CONFIG_FEC_XCV_TYPE;
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001092
1093 /* Reset chip. */
John Rigbye650e492010-01-25 23:12:55 -07001094 writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl);
Marek Vasut43b10302011-09-11 18:05:37 +00001095 start = get_timer(0);
1096 while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET) {
1097 if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
Vagrant Cascadian259b1fb2016-10-23 20:45:19 -07001098 printf("FEC MXC: Timeout resetting chip\n");
Marek Vasut03880452013-10-12 20:36:25 +02001099 goto err4;
Marek Vasut43b10302011-09-11 18:05:37 +00001100 }
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001101 udelay(10);
Marek Vasut43b10302011-09-11 18:05:37 +00001102 }
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001103
Marek Vasut335cbd22012-05-01 11:09:41 +00001104 fec_reg_setup(fec);
Troy Kisky4c2ddec2012-10-22 16:40:44 +00001105 fec_set_dev_name(edev->name, dev_id);
1106 fec->dev_id = (dev_id == -1) ? 0 : dev_id;
Troy Kiskydce4def2012-10-22 16:40:46 +00001107 fec->bus = bus;
1108 fec_mii_setspeed(bus->priv);
1109#ifdef CONFIG_PHYLIB
1110 fec->phydev = phydev;
1111 phy_connect_dev(phydev, edev);
1112 /* Configure phy */
1113 phy_config(phydev);
1114#else
Marek Vasutedcd6c02011-09-16 01:13:47 +02001115 fec->phy_id = phy_id;
Troy Kiskydce4def2012-10-22 16:40:46 +00001116#endif
1117 eth_register(edev);
Andy Duan8f8e4582017-04-10 19:44:35 +08001118 /* only support one eth device, the index number pointed by dev_id */
1119 edev->index = fec->dev_id;
Troy Kiskydce4def2012-10-22 16:40:46 +00001120
Andy Duan0eaaf832017-04-10 19:44:34 +08001121 if (fec_get_hwaddr(fec->dev_id, ethaddr) == 0) {
1122 debug("got MAC%d address from fuse: %pM\n", fec->dev_id, ethaddr);
Troy Kiskydce4def2012-10-22 16:40:46 +00001123 memcpy(edev->enetaddr, ethaddr, 6);
Andy Duan8f8e4582017-04-10 19:44:35 +08001124 if (fec->dev_id)
1125 sprintf(mac, "eth%daddr", fec->dev_id);
1126 else
1127 strcpy(mac, "ethaddr");
Simon Glass64b723f2017-08-03 12:22:12 -06001128 if (!env_get(mac))
Simon Glass8551d552017-08-03 12:22:11 -06001129 eth_env_set_enetaddr(mac, ethaddr);
Troy Kiskydce4def2012-10-22 16:40:46 +00001130 }
1131 return ret;
Marek Vasut03880452013-10-12 20:36:25 +02001132err4:
1133 fec_free_descs(fec);
Troy Kiskydce4def2012-10-22 16:40:46 +00001134err3:
1135 free(fec);
1136err2:
1137 free(edev);
1138err1:
1139 return ret;
1140}
1141
Troy Kiskydce4def2012-10-22 16:40:46 +00001142int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
1143{
1144 uint32_t base_mii;
1145 struct mii_dev *bus = NULL;
1146#ifdef CONFIG_PHYLIB
1147 struct phy_device *phydev = NULL;
1148#endif
1149 int ret;
1150
Peng Fana65e0362018-03-28 20:54:14 +08001151#ifdef CONFIG_FEC_MXC_MDIO_BASE
Troy Kisky2000c662012-02-07 14:08:47 +00001152 /*
1153 * The i.MX28 has two ethernet interfaces, but they are not equal.
1154 * Only the first one can access the MDIO bus.
1155 */
Peng Fana65e0362018-03-28 20:54:14 +08001156 base_mii = CONFIG_FEC_MXC_MDIO_BASE;
Troy Kisky2000c662012-02-07 14:08:47 +00001157#else
Troy Kiskydce4def2012-10-22 16:40:46 +00001158 base_mii = addr;
Troy Kisky2000c662012-02-07 14:08:47 +00001159#endif
Troy Kiskydce4def2012-10-22 16:40:46 +00001160 debug("eth_init: fec_probe(bd, %i, %i) @ %08x\n", dev_id, phy_id, addr);
1161 bus = fec_get_miibus(base_mii, dev_id);
1162 if (!bus)
1163 return -ENOMEM;
Troy Kisky2c42b3c2012-10-22 16:40:45 +00001164#ifdef CONFIG_PHYLIB
Troy Kiskydce4def2012-10-22 16:40:46 +00001165 phydev = phy_find_by_mask(bus, 1 << phy_id, PHY_INTERFACE_MODE_RGMII);
Troy Kisky2c42b3c2012-10-22 16:40:45 +00001166 if (!phydev) {
Måns Rullgårdc6e4a862015-12-08 15:38:46 +00001167 mdio_unregister(bus);
Troy Kisky2c42b3c2012-10-22 16:40:45 +00001168 free(bus);
Troy Kiskydce4def2012-10-22 16:40:46 +00001169 return -ENOMEM;
Troy Kisky2c42b3c2012-10-22 16:40:45 +00001170 }
Troy Kiskydce4def2012-10-22 16:40:46 +00001171 ret = fec_probe(bd, dev_id, addr, bus, phydev);
1172#else
1173 ret = fec_probe(bd, dev_id, addr, bus, phy_id);
Troy Kisky2c42b3c2012-10-22 16:40:45 +00001174#endif
Troy Kiskydce4def2012-10-22 16:40:46 +00001175 if (ret) {
1176#ifdef CONFIG_PHYLIB
1177 free(phydev);
1178#endif
Måns Rullgårdc6e4a862015-12-08 15:38:46 +00001179 mdio_unregister(bus);
Troy Kiskydce4def2012-10-22 16:40:46 +00001180 free(bus);
1181 }
Marek Vasut43b10302011-09-11 18:05:37 +00001182 return ret;
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001183}
1184
Troy Kisky4e0eae62012-10-22 16:40:42 +00001185#ifdef CONFIG_FEC_MXC_PHYADDR
1186int fecmxc_initialize(bd_t *bd)
1187{
1188 return fecmxc_initialize_multi(bd, -1, CONFIG_FEC_MXC_PHYADDR,
1189 IMX_FEC_BASE);
Ilya Yanoke93a4a52009-07-21 19:32:21 +04001190}
Troy Kisky4e0eae62012-10-22 16:40:42 +00001191#endif
Marek Vasut539ecee2011-09-11 18:05:36 +00001192
Troy Kisky2000c662012-02-07 14:08:47 +00001193#ifndef CONFIG_PHYLIB
Marek Vasut539ecee2011-09-11 18:05:36 +00001194int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))
1195{
1196 struct fec_priv *fec = (struct fec_priv *)dev->priv;
1197 fec->mii_postcall = cb;
1198 return 0;
Jagan Teki484f0212016-12-06 00:00:49 +01001199}
1200#endif
1201
1202#else
1203
Jagan Teki87e7f352016-12-06 00:00:51 +01001204static int fecmxc_read_rom_hwaddr(struct udevice *dev)
1205{
1206 struct fec_priv *priv = dev_get_priv(dev);
1207 struct eth_pdata *pdata = dev_get_platdata(dev);
1208
1209 return fec_get_hwaddr(priv->dev_id, pdata->enetaddr);
1210}
1211
Ye Libd7e5382018-03-28 20:54:11 +08001212static int fecmxc_free_pkt(struct udevice *dev, uchar *packet, int length)
1213{
1214 if (packet)
1215 free(packet);
1216
1217 return 0;
1218}
1219
Jagan Teki484f0212016-12-06 00:00:49 +01001220static const struct eth_ops fecmxc_ops = {
1221 .start = fecmxc_init,
1222 .send = fecmxc_send,
1223 .recv = fecmxc_recv,
Ye Libd7e5382018-03-28 20:54:11 +08001224 .free_pkt = fecmxc_free_pkt,
Jagan Teki484f0212016-12-06 00:00:49 +01001225 .stop = fecmxc_halt,
1226 .write_hwaddr = fecmxc_set_hwaddr,
Jagan Teki87e7f352016-12-06 00:00:51 +01001227 .read_rom_hwaddr = fecmxc_read_rom_hwaddr,
Jagan Teki484f0212016-12-06 00:00:49 +01001228};
1229
1230static int fec_phy_init(struct fec_priv *priv, struct udevice *dev)
1231{
1232 struct phy_device *phydev;
1233 int mask = 0xffffffff;
1234
Lukasz Majewski07b75a32018-04-15 21:45:54 +02001235#ifdef CONFIG_FEC_MXC_PHYADDR
Jagan Teki484f0212016-12-06 00:00:49 +01001236 mask = 1 << CONFIG_FEC_MXC_PHYADDR;
1237#endif
1238
1239 phydev = phy_find_by_mask(priv->bus, mask, priv->interface);
1240 if (!phydev)
1241 return -ENODEV;
1242
1243 phy_connect_dev(phydev, dev);
1244
1245 priv->phydev = phydev;
1246 phy_config(phydev);
1247
1248 return 0;
1249}
1250
Michael Trimarchi0e5cccf2018-06-17 15:22:39 +02001251#ifdef CONFIG_DM_GPIO
1252/* FEC GPIO reset */
1253static void fec_gpio_reset(struct fec_priv *priv)
1254{
1255 debug("fec_gpio_reset: fec_gpio_reset(dev)\n");
1256 if (dm_gpio_is_valid(&priv->phy_reset_gpio)) {
1257 dm_gpio_set_value(&priv->phy_reset_gpio, 1);
Martin Fuzzey9c3f97a2018-10-04 19:59:18 +02001258 mdelay(priv->reset_delay);
Michael Trimarchi0e5cccf2018-06-17 15:22:39 +02001259 dm_gpio_set_value(&priv->phy_reset_gpio, 0);
1260 }
1261}
1262#endif
1263
Jagan Teki484f0212016-12-06 00:00:49 +01001264static int fecmxc_probe(struct udevice *dev)
1265{
1266 struct eth_pdata *pdata = dev_get_platdata(dev);
1267 struct fec_priv *priv = dev_get_priv(dev);
1268 struct mii_dev *bus = NULL;
Jagan Teki484f0212016-12-06 00:00:49 +01001269 uint32_t start;
1270 int ret;
1271
1272 ret = fec_alloc_descs(priv);
1273 if (ret)
1274 return ret;
1275
Martin Fuzzey9a6a2c92018-10-04 19:59:20 +02001276#ifdef CONFIG_DM_REGULATOR
1277 if (priv->phy_supply) {
1278 ret = regulator_autoset(priv->phy_supply);
1279 if (ret) {
1280 printf("%s: Error enabling phy supply\n", dev->name);
1281 return ret;
1282 }
1283 }
1284#endif
1285
Michael Trimarchi0e5cccf2018-06-17 15:22:39 +02001286#ifdef CONFIG_DM_GPIO
1287 fec_gpio_reset(priv);
1288#endif
Jagan Teki484f0212016-12-06 00:00:49 +01001289 /* Reset chip. */
Jagan Tekic6cd8d52016-12-06 00:00:50 +01001290 writel(readl(&priv->eth->ecntrl) | FEC_ECNTRL_RESET,
1291 &priv->eth->ecntrl);
Jagan Teki484f0212016-12-06 00:00:49 +01001292 start = get_timer(0);
1293 while (readl(&priv->eth->ecntrl) & FEC_ECNTRL_RESET) {
1294 if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
1295 printf("FEC MXC: Timeout reseting chip\n");
1296 goto err_timeout;
1297 }
1298 udelay(10);
1299 }
1300
1301 fec_reg_setup(priv);
Jagan Teki484f0212016-12-06 00:00:49 +01001302
Peng Fanbd3e8cb2018-03-28 20:54:13 +08001303 priv->dev_id = dev->seq;
Peng Fana65e0362018-03-28 20:54:14 +08001304#ifdef CONFIG_FEC_MXC_MDIO_BASE
1305 bus = fec_get_miibus((ulong)CONFIG_FEC_MXC_MDIO_BASE, dev->seq);
1306#else
Peng Fanbd3e8cb2018-03-28 20:54:13 +08001307 bus = fec_get_miibus((ulong)priv->eth, dev->seq);
Peng Fana65e0362018-03-28 20:54:14 +08001308#endif
Lothar Waßmannd33e9ee2017-06-27 15:23:16 +02001309 if (!bus) {
1310 ret = -ENOMEM;
1311 goto err_mii;
1312 }
1313
1314 priv->bus = bus;
1315 priv->xcv_type = CONFIG_FEC_XCV_TYPE;
1316 priv->interface = pdata->phy_interface;
1317 ret = fec_phy_init(priv, dev);
1318 if (ret)
1319 goto err_phy;
1320
Jagan Teki484f0212016-12-06 00:00:49 +01001321 return 0;
1322
Jagan Teki484f0212016-12-06 00:00:49 +01001323err_phy:
1324 mdio_unregister(bus);
1325 free(bus);
1326err_mii:
Ye Li5fa556c2018-03-28 20:54:16 +08001327err_timeout:
Jagan Teki484f0212016-12-06 00:00:49 +01001328 fec_free_descs(priv);
1329 return ret;
Marek Vasut539ecee2011-09-11 18:05:36 +00001330}
Jagan Teki484f0212016-12-06 00:00:49 +01001331
1332static int fecmxc_remove(struct udevice *dev)
1333{
1334 struct fec_priv *priv = dev_get_priv(dev);
1335
1336 free(priv->phydev);
1337 fec_free_descs(priv);
1338 mdio_unregister(priv->bus);
1339 mdio_free(priv->bus);
1340
Martin Fuzzey9a6a2c92018-10-04 19:59:20 +02001341#ifdef CONFIG_DM_REGULATOR
1342 if (priv->phy_supply)
1343 regulator_set_enable(priv->phy_supply, false);
1344#endif
1345
Jagan Teki484f0212016-12-06 00:00:49 +01001346 return 0;
1347}
1348
1349static int fecmxc_ofdata_to_platdata(struct udevice *dev)
1350{
Michael Trimarchi0e5cccf2018-06-17 15:22:39 +02001351 int ret = 0;
Jagan Teki484f0212016-12-06 00:00:49 +01001352 struct eth_pdata *pdata = dev_get_platdata(dev);
1353 struct fec_priv *priv = dev_get_priv(dev);
1354 const char *phy_mode;
1355
Simon Glassba1dea42017-05-17 17:18:05 -06001356 pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
Jagan Teki484f0212016-12-06 00:00:49 +01001357 priv->eth = (struct ethernet_regs *)pdata->iobase;
1358
1359 pdata->phy_interface = -1;
Simon Glassdd79d6e2017-01-17 16:52:55 -07001360 phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
1361 NULL);
Jagan Teki484f0212016-12-06 00:00:49 +01001362 if (phy_mode)
1363 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
1364 if (pdata->phy_interface == -1) {
1365 debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
1366 return -EINVAL;
1367 }
1368
Martin Fuzzey9a6a2c92018-10-04 19:59:20 +02001369#ifdef CONFIG_DM_REGULATOR
1370 device_get_supply_regulator(dev, "phy-supply", &priv->phy_supply);
1371#endif
1372
Michael Trimarchi0e5cccf2018-06-17 15:22:39 +02001373#ifdef CONFIG_DM_GPIO
1374 ret = gpio_request_by_name(dev, "phy-reset-gpios", 0,
Martin Fuzzey185e3b82018-10-04 19:59:19 +02001375 &priv->phy_reset_gpio, GPIOD_IS_OUT);
1376 if (ret < 0)
1377 return 0; /* property is optional, don't return error! */
Jagan Teki484f0212016-12-06 00:00:49 +01001378
Martin Fuzzey185e3b82018-10-04 19:59:19 +02001379 priv->reset_delay = dev_read_u32_default(dev, "phy-reset-duration", 1);
Michael Trimarchi0e5cccf2018-06-17 15:22:39 +02001380 if (priv->reset_delay > 1000) {
Martin Fuzzey185e3b82018-10-04 19:59:19 +02001381 printf("FEC MXC: phy reset duration should be <= 1000ms\n");
1382 /* property value wrong, use default value */
1383 priv->reset_delay = 1;
Michael Trimarchi0e5cccf2018-06-17 15:22:39 +02001384 }
1385#endif
1386
Martin Fuzzey185e3b82018-10-04 19:59:19 +02001387 return 0;
Jagan Teki484f0212016-12-06 00:00:49 +01001388}
1389
1390static const struct udevice_id fecmxc_ids[] = {
1391 { .compatible = "fsl,imx6q-fec" },
Peng Fan56406302018-03-28 20:54:15 +08001392 { .compatible = "fsl,imx6sl-fec" },
1393 { .compatible = "fsl,imx6sx-fec" },
1394 { .compatible = "fsl,imx6ul-fec" },
Lukasz Majewski47311222018-04-15 21:54:22 +02001395 { .compatible = "fsl,imx53-fec" },
Jagan Teki484f0212016-12-06 00:00:49 +01001396 { }
1397};
1398
1399U_BOOT_DRIVER(fecmxc_gem) = {
1400 .name = "fecmxc",
1401 .id = UCLASS_ETH,
1402 .of_match = fecmxc_ids,
1403 .ofdata_to_platdata = fecmxc_ofdata_to_platdata,
1404 .probe = fecmxc_probe,
1405 .remove = fecmxc_remove,
1406 .ops = &fecmxc_ops,
1407 .priv_auto_alloc_size = sizeof(struct fec_priv),
1408 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
1409};
Troy Kisky2000c662012-02-07 14:08:47 +00001410#endif