blob: 56cb7a506eadd2eb5e0036a0a9d1d722ee41ea45 [file] [log] [blame]
Christophe Leroy069fa832017-07-06 10:23:22 +02001/*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
9#include <command.h>
10#include <commproc.h>
11#include <malloc.h>
12#include <net.h>
Christophe Leroy394f9b32017-07-06 10:33:13 +020013#include <asm/io.h>
Christophe Leroy069fa832017-07-06 10:23:22 +020014
15#include <phy.h>
16
17DECLARE_GLOBAL_DATA_PTR;
18
19#if defined(CONFIG_CMD_NET) && \
20 (defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FEC1) || defined(CONFIG_ETHER_ON_FEC2))
21
22/* compatibility test, if only FEC_ENET defined assume ETHER on FEC1 */
23#if defined(FEC_ENET) && !defined(CONFIG_ETHER_ON_FEC1) && !defined(CONFIG_ETHER_ON_FEC2)
24#define CONFIG_ETHER_ON_FEC1 1
25#endif
26
27/* define WANT_MII when MII support is required */
28#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_FEC1_PHY) || defined(CONFIG_FEC2_PHY)
29#define WANT_MII
30#else
31#undef WANT_MII
32#endif
33
34#if defined(WANT_MII)
35#include <miiphy.h>
36
37#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
38#error "CONFIG_MII has to be defined!"
39#endif
40
41#endif
42
43#if defined(CONFIG_RMII) && !defined(WANT_MII)
44#error RMII support is unusable without a working PHY.
45#endif
46
47#ifdef CONFIG_SYS_DISCOVER_PHY
48static int mii_discover_phy(struct eth_device *dev);
49#endif
50
51int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
52int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
53 u16 value);
54
55static struct ether_fcc_info_s
56{
57 int ether_index;
58 int fecp_offset;
59 int phy_addr;
60 int actual_phy_addr;
61 int initialized;
62}
63 ether_fcc_info[] = {
64#if defined(CONFIG_ETHER_ON_FEC1)
65 {
66 0,
67 offsetof(immap_t, im_cpm.cp_fec1),
68#if defined(CONFIG_FEC1_PHY)
69 CONFIG_FEC1_PHY,
70#else
71 -1, /* discover */
72#endif
73 -1,
74 0,
75
76 },
77#endif
78#if defined(CONFIG_ETHER_ON_FEC2)
79 {
80 1,
81 offsetof(immap_t, im_cpm.cp_fec2),
82#if defined(CONFIG_FEC2_PHY)
83 CONFIG_FEC2_PHY,
84#else
85 -1,
86#endif
87 -1,
88 0,
89 },
90#endif
91};
92
93/* Ethernet Transmit and Receive Buffers */
94#define DBUF_LENGTH 1520
95
96#define TX_BUF_CNT 2
97
98#define TOUT_LOOP 100
99
100#define PKT_MAXBUF_SIZE 1518
101#define PKT_MINBUF_SIZE 64
102#define PKT_MAXBLR_SIZE 1520
103
104#ifdef __GNUC__
Christophe Leroy48f896d2017-07-06 10:33:17 +0200105static char txbuf[DBUF_LENGTH] __aligned(8);
Christophe Leroy069fa832017-07-06 10:23:22 +0200106#else
107#error txbuf must be aligned.
108#endif
109
110static uint rxIdx; /* index of the current RX buffer */
111static uint txIdx; /* index of the current TX buffer */
112
113/*
114 * FEC Ethernet Tx and Rx buffer descriptors allocated at the
115 * immr->udata_bd address on Dual-Port RAM
116 * Provide for Double Buffering
117 */
118
Christophe Leroy394f9b32017-07-06 10:33:13 +0200119struct common_buf_desc {
Christophe Leroy48f896d2017-07-06 10:33:17 +0200120 cbd_t rxbd[PKTBUFSRX]; /* Rx BD */
121 cbd_t txbd[TX_BUF_CNT]; /* Tx BD */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200122};
Christophe Leroy069fa832017-07-06 10:23:22 +0200123
Christophe Leroy394f9b32017-07-06 10:33:13 +0200124static struct common_buf_desc __iomem *rtx;
Christophe Leroy069fa832017-07-06 10:23:22 +0200125
126static int fec_send(struct eth_device *dev, void *packet, int length);
Christophe Leroy48f896d2017-07-06 10:33:17 +0200127static int fec_recv(struct eth_device *dev);
128static int fec_init(struct eth_device *dev, bd_t *bd);
129static void fec_halt(struct eth_device *dev);
Christophe Leroy069fa832017-07-06 10:23:22 +0200130#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
131static void __mii_init(void);
132#endif
133
134int fec_initialize(bd_t *bis)
135{
Christophe Leroy48f896d2017-07-06 10:33:17 +0200136 struct eth_device *dev;
Christophe Leroy069fa832017-07-06 10:23:22 +0200137 struct ether_fcc_info_s *efis;
138 int i;
139
140 for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200141 dev = malloc(sizeof(*dev));
142 if (dev == NULL)
143 hang();
144
145 memset(dev, 0, sizeof(*dev));
146
147 /* for FEC1 make sure that the name of the interface is the same
148 as the old one for compatibility reasons */
Christophe Leroy48f896d2017-07-06 10:33:17 +0200149 if (i == 0)
Christophe Leroy069fa832017-07-06 10:23:22 +0200150 strcpy(dev->name, "FEC");
Christophe Leroy48f896d2017-07-06 10:33:17 +0200151 else
152 sprintf(dev->name, "FEC%d",
Christophe Leroy069fa832017-07-06 10:23:22 +0200153 ether_fcc_info[i].ether_index + 1);
Christophe Leroy069fa832017-07-06 10:23:22 +0200154
155 efis = &ether_fcc_info[i];
156
157 /*
158 * reset actual phy addr
159 */
160 efis->actual_phy_addr = -1;
161
162 dev->priv = efis;
163 dev->init = fec_init;
164 dev->halt = fec_halt;
165 dev->send = fec_send;
166 dev->recv = fec_recv;
167
168 eth_register(dev);
169
170#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
171 int retval;
172 struct mii_dev *mdiodev = mdio_alloc();
173 if (!mdiodev)
174 return -ENOMEM;
175 strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
176 mdiodev->read = fec8xx_miiphy_read;
177 mdiodev->write = fec8xx_miiphy_write;
178
179 retval = mdio_register(mdiodev);
180 if (retval < 0)
181 return retval;
182#endif
183 }
184 return 1;
185}
186
187static int fec_send(struct eth_device *dev, void *packet, int length)
188{
189 int j, rc;
190 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200191 fec_t __iomem *fecp =
192 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200193
194 /* section 16.9.23.3
195 * Wait for ready
196 */
197 j = 0;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200198 while ((in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_READY) &&
199 (j < TOUT_LOOP)) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200200 udelay(1);
201 j++;
202 }
Christophe Leroy48f896d2017-07-06 10:33:17 +0200203 if (j >= TOUT_LOOP)
Christophe Leroy069fa832017-07-06 10:23:22 +0200204 printf("TX not ready\n");
Christophe Leroy069fa832017-07-06 10:23:22 +0200205
Christophe Leroy394f9b32017-07-06 10:33:13 +0200206 out_be32(&rtx->txbd[txIdx].cbd_bufaddr, (uint)packet);
207 out_be16(&rtx->txbd[txIdx].cbd_datlen, length);
208 setbits_be16(&rtx->txbd[txIdx].cbd_sc,
209 BD_ENET_TX_READY | BD_ENET_TX_LAST);
Christophe Leroy069fa832017-07-06 10:23:22 +0200210
211 /* Activate transmit Buffer Descriptor polling */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200212 /* Descriptor polling active */
213 out_be32(&fecp->fec_x_des_active, 0x01000000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200214
215 j = 0;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200216 while ((in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_READY) &&
217 (j < TOUT_LOOP)) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200218 udelay(1);
219 j++;
220 }
Christophe Leroy48f896d2017-07-06 10:33:17 +0200221 if (j >= TOUT_LOOP)
Christophe Leroy069fa832017-07-06 10:23:22 +0200222 printf("TX timeout\n");
Christophe Leroy48f896d2017-07-06 10:33:17 +0200223
Christophe Leroy069fa832017-07-06 10:23:22 +0200224 /* return only status bits */;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200225 rc = in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_STATS;
Christophe Leroy069fa832017-07-06 10:23:22 +0200226
227 txIdx = (txIdx + 1) % TX_BUF_CNT;
228
229 return rc;
230}
231
Christophe Leroy48f896d2017-07-06 10:33:17 +0200232static int fec_recv(struct eth_device *dev)
Christophe Leroy069fa832017-07-06 10:23:22 +0200233{
234 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200235 fec_t __iomem *fecp =
236 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200237 int length;
238
239 for (;;) {
240 /* section 16.9.23.2 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200241 if (in_be16(&rtx->rxbd[rxIdx].cbd_sc) & BD_ENET_RX_EMPTY) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200242 length = -1;
243 break; /* nothing received - leave for() loop */
244 }
245
Christophe Leroy394f9b32017-07-06 10:33:13 +0200246 length = in_be16(&rtx->rxbd[rxIdx].cbd_datlen);
Christophe Leroy069fa832017-07-06 10:23:22 +0200247
Christophe Leroy394f9b32017-07-06 10:33:13 +0200248 if (!(in_be16(&rtx->rxbd[rxIdx].cbd_sc) & 0x003f)) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200249 uchar *rx = net_rx_packets[rxIdx];
250
251 length -= 4;
252
253#if defined(CONFIG_CMD_CDP)
254 if ((rx[0] & 1) != 0 &&
255 memcmp((uchar *)rx, net_bcast_ethaddr, 6) != 0 &&
256 !is_cdp_packet((uchar *)rx))
257 rx = NULL;
258#endif
259 /*
260 * Pass the packet up to the protocol layers.
261 */
262 if (rx != NULL)
263 net_process_received_packet(rx, length);
264 }
265
266 /* Give the buffer back to the FEC. */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200267 out_be16(&rtx->rxbd[rxIdx].cbd_datlen, 0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200268
269 /* wrap around buffer index when necessary */
270 if ((rxIdx + 1) >= PKTBUFSRX) {
Christophe Leroy394f9b32017-07-06 10:33:13 +0200271 out_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc,
272 BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
Christophe Leroy069fa832017-07-06 10:23:22 +0200273 rxIdx = 0;
274 } else {
Christophe Leroy394f9b32017-07-06 10:33:13 +0200275 out_be16(&rtx->rxbd[rxIdx].cbd_sc, BD_ENET_RX_EMPTY);
Christophe Leroy069fa832017-07-06 10:23:22 +0200276 rxIdx++;
277 }
278
Christophe Leroy069fa832017-07-06 10:23:22 +0200279 /* Try to fill Buffer Descriptors */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200280 /* Descriptor polling active */
281 out_be32(&fecp->fec_r_des_active, 0x01000000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200282 }
283
284 return length;
285}
286
287/**************************************************************
288 *
289 * FEC Ethernet Initialization Routine
290 *
291 *************************************************************/
292
293#define FEC_ECNTRL_PINMUX 0x00000004
294#define FEC_ECNTRL_ETHER_EN 0x00000002
295#define FEC_ECNTRL_RESET 0x00000001
296
297#define FEC_RCNTRL_BC_REJ 0x00000010
298#define FEC_RCNTRL_PROM 0x00000008
299#define FEC_RCNTRL_MII_MODE 0x00000004
300#define FEC_RCNTRL_DRT 0x00000002
301#define FEC_RCNTRL_LOOP 0x00000001
302
303#define FEC_TCNTRL_FDEN 0x00000004
304#define FEC_TCNTRL_HBC 0x00000002
305#define FEC_TCNTRL_GTS 0x00000001
306
307#define FEC_RESET_DELAY 50
308
309#if defined(CONFIG_RMII)
310
311static inline void fec_10Mbps(struct eth_device *dev)
312{
313 struct ether_fcc_info_s *efis = dev->priv;
314 int fecidx = efis->ether_index;
315 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200316 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy069fa832017-07-06 10:23:22 +0200317
318 if ((unsigned int)fecidx >= 2)
319 hang();
320
Christophe Leroy394f9b32017-07-06 10:33:13 +0200321 setbits_be32(&immr->im_cpm.cp_cptr, mask);
Christophe Leroy069fa832017-07-06 10:23:22 +0200322}
323
324static inline void fec_100Mbps(struct eth_device *dev)
325{
326 struct ether_fcc_info_s *efis = dev->priv;
327 int fecidx = efis->ether_index;
328 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200329 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy069fa832017-07-06 10:23:22 +0200330
331 if ((unsigned int)fecidx >= 2)
332 hang();
333
Christophe Leroy394f9b32017-07-06 10:33:13 +0200334 clrbits_be32(&immr->im_cpm.cp_cptr, mask);
Christophe Leroy069fa832017-07-06 10:23:22 +0200335}
336
337#endif
338
339static inline void fec_full_duplex(struct eth_device *dev)
340{
341 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200342 fec_t __iomem *fecp =
343 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200344
Christophe Leroy394f9b32017-07-06 10:33:13 +0200345 clrbits_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_DRT);
346 setbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */
Christophe Leroy069fa832017-07-06 10:23:22 +0200347}
348
349static inline void fec_half_duplex(struct eth_device *dev)
350{
351 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200352 fec_t __iomem *fecp =
353 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200354
Christophe Leroy394f9b32017-07-06 10:33:13 +0200355 setbits_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_DRT);
356 clrbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD disable */
Christophe Leroy069fa832017-07-06 10:23:22 +0200357}
358
359static void fec_pin_init(int fecidx)
360{
361 bd_t *bd = gd->bd;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200362 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy069fa832017-07-06 10:23:22 +0200363
364 /*
365 * Set MII speed to 2.5 MHz or slightly below.
366 *
367 * According to the MPC860T (Rev. D) Fast ethernet controller user
368 * manual (6.2.14),
369 * the MII management interface clock must be less than or equal
370 * to 2.5 MHz.
371 * This MDC frequency is equal to system clock / (2 * MII_SPEED).
372 * Then MII_SPEED = system_clock / 2 * 2,5 MHz.
373 *
374 * All MII configuration is done via FEC1 registers:
375 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200376 out_be32(&immr->im_cpm.cp_fec1.fec_mii_speed,
377 ((bd->bi_intfreq + 4999999) / 5000000) << 1);
Christophe Leroy069fa832017-07-06 10:23:22 +0200378
Christophe Leroy23da3732017-07-06 10:33:21 +0200379#if defined(CONFIG_MPC885) && defined(WANT_MII)
Christophe Leroy069fa832017-07-06 10:23:22 +0200380 /* use MDC for MII */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200381 setbits_be16(&immr->im_ioport.iop_pdpar, 0x0080);
382 clrbits_be16(&immr->im_ioport.iop_pddir, 0x0080);
Christophe Leroy069fa832017-07-06 10:23:22 +0200383#endif
384
385 if (fecidx == 0) {
386#if defined(CONFIG_ETHER_ON_FEC1)
387
Christophe Leroy23da3732017-07-06 10:33:21 +0200388#if defined(CONFIG_MPC885) /* MPC87x/88x have got 2 FECs and different pinout */
Christophe Leroy069fa832017-07-06 10:23:22 +0200389
390#if !defined(CONFIG_RMII)
391
Christophe Leroy394f9b32017-07-06 10:33:13 +0200392 setbits_be16(&immr->im_ioport.iop_papar, 0xf830);
393 setbits_be16(&immr->im_ioport.iop_padir, 0x0830);
394 clrbits_be16(&immr->im_ioport.iop_padir, 0xf000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200395
Christophe Leroy394f9b32017-07-06 10:33:13 +0200396 setbits_be32(&immr->im_cpm.cp_pbpar, 0x00001001);
397 clrbits_be32(&immr->im_cpm.cp_pbdir, 0x00001001);
Christophe Leroy069fa832017-07-06 10:23:22 +0200398
Christophe Leroy394f9b32017-07-06 10:33:13 +0200399 setbits_be16(&immr->im_ioport.iop_pcpar, 0x000c);
400 clrbits_be16(&immr->im_ioport.iop_pcdir, 0x000c);
Christophe Leroy069fa832017-07-06 10:23:22 +0200401
Christophe Leroy394f9b32017-07-06 10:33:13 +0200402 setbits_be32(&immr->im_cpm.cp_pepar, 0x00000003);
403 setbits_be32(&immr->im_cpm.cp_pedir, 0x00000003);
404 clrbits_be32(&immr->im_cpm.cp_peso, 0x00000003);
Christophe Leroy069fa832017-07-06 10:23:22 +0200405
Christophe Leroy394f9b32017-07-06 10:33:13 +0200406 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000100);
Christophe Leroy069fa832017-07-06 10:23:22 +0200407
408#else
409
410#if !defined(CONFIG_FEC1_PHY_NORXERR)
Christophe Leroy394f9b32017-07-06 10:33:13 +0200411 setbits_be16(&immr->im_ioport.iop_papar, 0x1000);
412 clrbits_be16(&immr->im_ioport.iop_padir, 0x1000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200413#endif
Christophe Leroy394f9b32017-07-06 10:33:13 +0200414 setbits_be16(&immr->im_ioport.iop_papar, 0xe810);
415 setbits_be16(&immr->im_ioport.iop_padir, 0x0810);
416 clrbits_be16(&immr->im_ioport.iop_padir, 0xe000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200417
Christophe Leroy394f9b32017-07-06 10:33:13 +0200418 setbits_be32(&immr->im_cpm.cp_pbpar, 0x00000001);
419 clrbits_be32(&immr->im_cpm.cp_pbdir, 0x00000001);
Christophe Leroy069fa832017-07-06 10:23:22 +0200420
Christophe Leroy394f9b32017-07-06 10:33:13 +0200421 setbits_be32(&immr->im_cpm.cp_cptr, 0x00000100);
422 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000050);
Christophe Leroy069fa832017-07-06 10:23:22 +0200423
424#endif /* !CONFIG_RMII */
425
426#else
427 /*
428 * Configure all of port D for MII.
429 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200430 out_be16(&immr->im_ioport.iop_pdpar, 0x1fff);
431 out_be16(&immr->im_ioport.iop_pddir, 0x1fff);
Christophe Leroy069fa832017-07-06 10:23:22 +0200432#endif
433
434#endif /* CONFIG_ETHER_ON_FEC1 */
435 } else if (fecidx == 1) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200436#if defined(CONFIG_ETHER_ON_FEC2)
437
Christophe Leroy23da3732017-07-06 10:33:21 +0200438#if defined(CONFIG_MPC885) /* MPC87x/88x have got 2 FECs and different pinout */
Christophe Leroy069fa832017-07-06 10:23:22 +0200439
440#if !defined(CONFIG_RMII)
Christophe Leroy394f9b32017-07-06 10:33:13 +0200441 setbits_be32(&immr->im_cpm.cp_pepar, 0x0003fffc);
442 setbits_be32(&immr->im_cpm.cp_pedir, 0x0003fffc);
443 clrbits_be32(&immr->im_cpm.cp_peso, 0x000087fc);
444 setbits_be32(&immr->im_cpm.cp_peso, 0x00037800);
Christophe Leroy069fa832017-07-06 10:23:22 +0200445
Christophe Leroy394f9b32017-07-06 10:33:13 +0200446 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000080);
Christophe Leroy069fa832017-07-06 10:23:22 +0200447#else
448
449#if !defined(CONFIG_FEC2_PHY_NORXERR)
Christophe Leroy394f9b32017-07-06 10:33:13 +0200450 setbits_be32(&immr->im_cpm.cp_pepar, 0x00000010);
451 setbits_be32(&immr->im_cpm.cp_pedir, 0x00000010);
452 clrbits_be32(&immr->im_cpm.cp_peso, 0x00000010);
Christophe Leroy069fa832017-07-06 10:23:22 +0200453#endif
Christophe Leroy394f9b32017-07-06 10:33:13 +0200454 setbits_be32(&immr->im_cpm.cp_pepar, 0x00039620);
455 setbits_be32(&immr->im_cpm.cp_pedir, 0x00039620);
456 setbits_be32(&immr->im_cpm.cp_peso, 0x00031000);
457 clrbits_be32(&immr->im_cpm.cp_peso, 0x00008620);
Christophe Leroy069fa832017-07-06 10:23:22 +0200458
Christophe Leroy394f9b32017-07-06 10:33:13 +0200459 setbits_be32(&immr->im_cpm.cp_cptr, 0x00000080);
460 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000028);
Christophe Leroy069fa832017-07-06 10:23:22 +0200461#endif /* CONFIG_RMII */
462
Christophe Leroy23da3732017-07-06 10:33:21 +0200463#endif /* CONFIG_MPC885 */
Christophe Leroy069fa832017-07-06 10:23:22 +0200464
465#endif /* CONFIG_ETHER_ON_FEC2 */
Christophe Leroy069fa832017-07-06 10:23:22 +0200466 }
467}
468
Christophe Leroy394f9b32017-07-06 10:33:13 +0200469static int fec_reset(fec_t __iomem *fecp)
Christophe Leroy069fa832017-07-06 10:23:22 +0200470{
471 int i;
472
473 /* Whack a reset.
474 * A delay is required between a reset of the FEC block and
475 * initialization of other FEC registers because the reset takes
476 * some time to complete. If you don't delay, subsequent writes
477 * to FEC registers might get killed by the reset routine which is
478 * still in progress.
479 */
480
Christophe Leroy394f9b32017-07-06 10:33:13 +0200481 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
482 for (i = 0; (in_be32(&fecp->fec_ecntrl) & FEC_ECNTRL_RESET) &&
483 (i < FEC_RESET_DELAY); ++i)
Christophe Leroy48f896d2017-07-06 10:33:17 +0200484 udelay(1);
Christophe Leroy394f9b32017-07-06 10:33:13 +0200485
Christophe Leroy069fa832017-07-06 10:23:22 +0200486 if (i == FEC_RESET_DELAY)
487 return -1;
488
489 return 0;
490}
491
Christophe Leroy48f896d2017-07-06 10:33:17 +0200492static int fec_init(struct eth_device *dev, bd_t *bd)
Christophe Leroy069fa832017-07-06 10:23:22 +0200493{
494 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200495 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
496 fec_t __iomem *fecp =
497 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200498 int i;
499
500#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
501 /* the MII interface is connected to FEC1
502 * so for the miiphy_xxx function to work we must
503 * call mii_init since fec_halt messes the thing up
504 */
505 if (efis->ether_index != 0)
506 __mii_init();
507#endif
508
509 if (fec_reset(fecp) < 0)
Christophe Leroy48f896d2017-07-06 10:33:17 +0200510 printf("FEC_RESET_DELAY timeout\n");
Christophe Leroy069fa832017-07-06 10:23:22 +0200511
512 /* We use strictly polling mode only
513 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200514 out_be32(&fecp->fec_imask, 0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200515
516 /* Clear any pending interrupt
517 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200518 out_be32(&fecp->fec_ievent, 0xffc0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200519
520 /* No need to set the IVEC register */
521
522 /* Set station address
523 */
524#define ea dev->enetaddr
Christophe Leroy394f9b32017-07-06 10:33:13 +0200525 out_be32(&fecp->fec_addr_low, (ea[0] << 24) | (ea[1] << 16) |
526 (ea[2] << 8) | ea[3]);
527 out_be16(&fecp->fec_addr_high, (ea[4] << 8) | ea[5]);
Christophe Leroy069fa832017-07-06 10:23:22 +0200528#undef ea
529
530#if defined(CONFIG_CMD_CDP)
531 /*
532 * Turn on multicast address hash table
533 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200534 out_be32(&fecp->fec_hash_table_high, 0xffffffff);
535 out_be32(&fecp->fec_hash_table_low, 0xffffffff);
Christophe Leroy069fa832017-07-06 10:23:22 +0200536#else
537 /* Clear multicast address hash table
538 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200539 out_be32(&fecp->fec_hash_table_high, 0);
540 out_be32(&fecp->fec_hash_table_low, 0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200541#endif
542
543 /* Set maximum receive buffer size.
544 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200545 out_be32(&fecp->fec_r_buff_size, PKT_MAXBLR_SIZE);
Christophe Leroy069fa832017-07-06 10:23:22 +0200546
547 /* Set maximum frame length
548 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200549 out_be32(&fecp->fec_r_hash, PKT_MAXBUF_SIZE);
Christophe Leroy069fa832017-07-06 10:23:22 +0200550
551 /*
Christophe Leroy48f896d2017-07-06 10:33:17 +0200552 * Setup Buffers and Buffer Descriptors
Christophe Leroy069fa832017-07-06 10:23:22 +0200553 */
554 rxIdx = 0;
555 txIdx = 0;
556
557 if (!rtx)
Christophe Leroy394f9b32017-07-06 10:33:13 +0200558 rtx = (struct common_buf_desc __iomem *)
559 (immr->im_cpm.cp_dpmem + CPM_FEC_BASE);
Christophe Leroy069fa832017-07-06 10:23:22 +0200560 /*
561 * Setup Receiver Buffer Descriptors (13.14.24.18)
562 * Settings:
563 * Empty, Wrap
564 */
565 for (i = 0; i < PKTBUFSRX; i++) {
Christophe Leroy394f9b32017-07-06 10:33:13 +0200566 out_be16(&rtx->rxbd[i].cbd_sc, BD_ENET_RX_EMPTY);
567 out_be16(&rtx->rxbd[i].cbd_datlen, 0); /* Reset */
568 out_be32(&rtx->rxbd[i].cbd_bufaddr, (uint)net_rx_packets[i]);
Christophe Leroy069fa832017-07-06 10:23:22 +0200569 }
Christophe Leroy394f9b32017-07-06 10:33:13 +0200570 setbits_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc, BD_ENET_RX_WRAP);
Christophe Leroy069fa832017-07-06 10:23:22 +0200571
572 /*
573 * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
574 * Settings:
575 * Last, Tx CRC
576 */
577 for (i = 0; i < TX_BUF_CNT; i++) {
Christophe Leroy394f9b32017-07-06 10:33:13 +0200578 out_be16(&rtx->txbd[i].cbd_sc, BD_ENET_TX_LAST | BD_ENET_TX_TC);
579 out_be16(&rtx->txbd[i].cbd_datlen, 0); /* Reset */
580 out_be32(&rtx->txbd[i].cbd_bufaddr, (uint)txbuf);
Christophe Leroy069fa832017-07-06 10:23:22 +0200581 }
Christophe Leroy394f9b32017-07-06 10:33:13 +0200582 setbits_be16(&rtx->txbd[TX_BUF_CNT - 1].cbd_sc, BD_ENET_TX_WRAP);
Christophe Leroy069fa832017-07-06 10:23:22 +0200583
584 /* Set receive and transmit descriptor base
585 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200586 out_be32(&fecp->fec_r_des_start, (__force unsigned int)rtx->rxbd);
587 out_be32(&fecp->fec_x_des_start, (__force unsigned int)rtx->txbd);
Christophe Leroy069fa832017-07-06 10:23:22 +0200588
589 /* Enable MII mode
590 */
591 /* Half duplex mode */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200592 out_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT);
593 out_be32(&fecp->fec_x_cntrl, 0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200594
595 /* Enable big endian and don't care about SDMA FC.
596 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200597 out_be32(&fecp->fec_fun_code, 0x78000000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200598
599 /*
600 * Setup the pin configuration of the FEC
601 */
Christophe Leroy48f896d2017-07-06 10:33:17 +0200602 fec_pin_init(efis->ether_index);
Christophe Leroy069fa832017-07-06 10:23:22 +0200603
604 rxIdx = 0;
605 txIdx = 0;
606
607 /*
608 * Now enable the transmit and receive processing
609 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200610 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
Christophe Leroy069fa832017-07-06 10:23:22 +0200611
612 if (efis->phy_addr == -1) {
613#ifdef CONFIG_SYS_DISCOVER_PHY
614 /*
615 * wait for the PHY to wake up after reset
616 */
Christophe Leroy48f896d2017-07-06 10:33:17 +0200617 efis->actual_phy_addr = mii_discover_phy(dev);
Christophe Leroy069fa832017-07-06 10:23:22 +0200618
619 if (efis->actual_phy_addr == -1) {
Christophe Leroy48f896d2017-07-06 10:33:17 +0200620 printf("Unable to discover phy!\n");
Christophe Leroy069fa832017-07-06 10:23:22 +0200621 return -1;
622 }
623#else
624 efis->actual_phy_addr = -1;
625#endif
626 } else {
627 efis->actual_phy_addr = efis->phy_addr;
628 }
629
630#if defined(CONFIG_MII) && defined(CONFIG_RMII)
631 /*
632 * adapt the RMII speed to the speed of the phy
633 */
Christophe Leroy48f896d2017-07-06 10:33:17 +0200634 if (miiphy_speed(dev->name, efis->actual_phy_addr) == _100BASET)
635 fec_100Mbps(dev);
636 else
637 fec_10Mbps(dev);
Christophe Leroy069fa832017-07-06 10:23:22 +0200638#endif
639
640#if defined(CONFIG_MII)
641 /*
642 * adapt to the half/full speed settings
643 */
Christophe Leroy48f896d2017-07-06 10:33:17 +0200644 if (miiphy_duplex(dev->name, efis->actual_phy_addr) == FULL)
645 fec_full_duplex(dev);
646 else
647 fec_half_duplex(dev);
Christophe Leroy069fa832017-07-06 10:23:22 +0200648#endif
649
650 /* And last, try to fill Rx Buffer Descriptors */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200651 /* Descriptor polling active */
652 out_be32(&fecp->fec_r_des_active, 0x01000000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200653
654 efis->initialized = 1;
655
656 return 0;
657}
658
659
Christophe Leroy48f896d2017-07-06 10:33:17 +0200660static void fec_halt(struct eth_device *dev)
Christophe Leroy069fa832017-07-06 10:23:22 +0200661{
662 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200663 fec_t __iomem *fecp =
664 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200665 int i;
666
667 /* avoid halt if initialized; mii gets stuck otherwise */
668 if (!efis->initialized)
669 return;
670
671 /* Whack a reset.
672 * A delay is required between a reset of the FEC block and
673 * initialization of other FEC registers because the reset takes
674 * some time to complete. If you don't delay, subsequent writes
675 * to FEC registers might get killed by the reset routine which is
676 * still in progress.
677 */
678
Christophe Leroy394f9b32017-07-06 10:33:13 +0200679 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
680 for (i = 0; (in_be32(&fecp->fec_ecntrl) & FEC_ECNTRL_RESET) &&
681 (i < FEC_RESET_DELAY); ++i)
Christophe Leroy48f896d2017-07-06 10:33:17 +0200682 udelay(1);
Christophe Leroy394f9b32017-07-06 10:33:13 +0200683
Christophe Leroy069fa832017-07-06 10:23:22 +0200684 if (i == FEC_RESET_DELAY) {
Christophe Leroy48f896d2017-07-06 10:33:17 +0200685 printf("FEC_RESET_DELAY timeout\n");
Christophe Leroy069fa832017-07-06 10:23:22 +0200686 return;
687 }
688
689 efis->initialized = 0;
690}
691
692#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
693
694/* Make MII read/write commands for the FEC.
695*/
696
697#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \
698 (REG & 0x1f) << 18))
699
700#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \
701 (REG & 0x1f) << 18) | \
702 (VAL & 0xffff))
703
704/* Interrupt events/masks.
705*/
706#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
707#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
708#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */
709#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */
710#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */
711#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */
712#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */
713#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
714#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
715#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
716
717/* send command to phy using mii, wait for result */
718static uint
719mii_send(uint mii_cmd)
720{
721 uint mii_reply;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200722 fec_t __iomem *ep;
Christophe Leroy069fa832017-07-06 10:23:22 +0200723 int cnt;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200724 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy069fa832017-07-06 10:23:22 +0200725
Christophe Leroy394f9b32017-07-06 10:33:13 +0200726 ep = &immr->im_cpm.cp_fec;
Christophe Leroy069fa832017-07-06 10:23:22 +0200727
Christophe Leroy394f9b32017-07-06 10:33:13 +0200728 out_be32(&ep->fec_mii_data, mii_cmd); /* command to phy */
Christophe Leroy069fa832017-07-06 10:23:22 +0200729
730 /* wait for mii complete */
731 cnt = 0;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200732 while (!(in_be32(&ep->fec_ievent) & FEC_ENET_MII)) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200733 if (++cnt > 1000) {
734 printf("mii_send STUCK!\n");
735 break;
736 }
737 }
Christophe Leroy394f9b32017-07-06 10:33:13 +0200738 mii_reply = in_be32(&ep->fec_mii_data); /* result from phy */
739 out_be32(&ep->fec_ievent, FEC_ENET_MII); /* clear MII complete */
Christophe Leroy48f896d2017-07-06 10:33:17 +0200740 return mii_reply & 0xffff; /* data read from phy */
Christophe Leroy069fa832017-07-06 10:23:22 +0200741}
742#endif
743
744#if defined(CONFIG_SYS_DISCOVER_PHY)
745static int mii_discover_phy(struct eth_device *dev)
746{
747#define MAX_PHY_PASSES 11
748 uint phyno;
749 int pass;
750 uint phytype;
751 int phyaddr;
752
753 phyaddr = -1; /* didn't find a PHY yet */
754 for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
755 if (pass > 1) {
756 /* PHY may need more time to recover from reset.
757 * The LXT970 needs 50ms typical, no maximum is
758 * specified, so wait 10ms before try again.
759 * With 11 passes this gives it 100ms to wake up.
760 */
761 udelay(10000); /* wait 10ms */
762 }
763 for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {
764 phytype = mii_send(mk_mii_read(phyno, MII_PHYSID2));
765 if (phytype != 0xffff) {
766 phyaddr = phyno;
767 phytype |= mii_send(mk_mii_read(phyno,
768 MII_PHYSID1)) << 16;
769 }
770 }
771 }
Christophe Leroy48f896d2017-07-06 10:33:17 +0200772 if (phyaddr < 0)
Christophe Leroy069fa832017-07-06 10:23:22 +0200773 printf("No PHY device found.\n");
Christophe Leroy48f896d2017-07-06 10:33:17 +0200774
Christophe Leroy069fa832017-07-06 10:23:22 +0200775 return phyaddr;
776}
777#endif /* CONFIG_SYS_DISCOVER_PHY */
778
779#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && !defined(CONFIG_BITBANGMII)
780
781/****************************************************************************
782 * mii_init -- Initialize the MII via FEC 1 for MII command without ethernet
783 * This function is a subset of eth_init
784 ****************************************************************************
785 */
786static void __mii_init(void)
787{
Christophe Leroy394f9b32017-07-06 10:33:13 +0200788 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
789 fec_t __iomem *fecp = &immr->im_cpm.cp_fec;
Christophe Leroy069fa832017-07-06 10:23:22 +0200790
791 if (fec_reset(fecp) < 0)
Christophe Leroy48f896d2017-07-06 10:33:17 +0200792 printf("FEC_RESET_DELAY timeout\n");
Christophe Leroy069fa832017-07-06 10:23:22 +0200793
794 /* We use strictly polling mode only
795 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200796 out_be32(&fecp->fec_imask, 0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200797
798 /* Clear any pending interrupt
799 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200800 out_be32(&fecp->fec_ievent, 0xffc0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200801
802 /* Now enable the transmit and receive processing
803 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200804 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
Christophe Leroy069fa832017-07-06 10:23:22 +0200805}
806
Christophe Leroy48f896d2017-07-06 10:33:17 +0200807void mii_init(void)
Christophe Leroy069fa832017-07-06 10:23:22 +0200808{
809 int i;
810
811 __mii_init();
812
813 /* Setup the pin configuration of the FEC(s)
814 */
815 for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
816 fec_pin_init(ether_fcc_info[i].ether_index);
817}
818
819/*****************************************************************************
820 * Read and write a MII PHY register, routines used by MII Utilities
821 *
822 * FIXME: These routines are expected to return 0 on success, but mii_send
823 * does _not_ return an error code. Maybe 0xFFFF means error, i.e.
824 * no PHY connected...
825 * For now always return 0.
826 * FIXME: These routines only work after calling eth_init() at least once!
827 * Otherwise they hang in mii_send() !!! Sorry!
828 *****************************************************************************/
829
830int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
831{
832 unsigned short value = 0;
833 short rdreg; /* register working value */
834
835 rdreg = mii_send(mk_mii_read(addr, reg));
836
837 value = rdreg;
838 return value;
839}
840
841int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
842 u16 value)
843{
844 (void)mii_send(mk_mii_write(addr, reg, value));
845
846 return 0;
847}
848#endif
849
850#endif