blob: eaaea2d4e82a637b9e943d9a3d52498f15c2cf67 [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__
105static char txbuf[DBUF_LENGTH] __attribute__ ((aligned(8)));
106#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 Leroy069fa832017-07-06 10:23:22 +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);
127static 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);
130#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
131static void __mii_init(void);
132#endif
133
134int fec_initialize(bd_t *bis)
135{
136 struct eth_device* dev;
137 struct ether_fcc_info_s *efis;
138 int i;
139
140 for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++) {
141
142 dev = malloc(sizeof(*dev));
143 if (dev == NULL)
144 hang();
145
146 memset(dev, 0, sizeof(*dev));
147
148 /* for FEC1 make sure that the name of the interface is the same
149 as the old one for compatibility reasons */
150 if (i == 0) {
151 strcpy(dev->name, "FEC");
152 } else {
153 sprintf (dev->name, "FEC%d",
154 ether_fcc_info[i].ether_index + 1);
155 }
156
157 efis = &ether_fcc_info[i];
158
159 /*
160 * reset actual phy addr
161 */
162 efis->actual_phy_addr = -1;
163
164 dev->priv = efis;
165 dev->init = fec_init;
166 dev->halt = fec_halt;
167 dev->send = fec_send;
168 dev->recv = fec_recv;
169
170 eth_register(dev);
171
172#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
173 int retval;
174 struct mii_dev *mdiodev = mdio_alloc();
175 if (!mdiodev)
176 return -ENOMEM;
177 strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
178 mdiodev->read = fec8xx_miiphy_read;
179 mdiodev->write = fec8xx_miiphy_write;
180
181 retval = mdio_register(mdiodev);
182 if (retval < 0)
183 return retval;
184#endif
185 }
186 return 1;
187}
188
189static int fec_send(struct eth_device *dev, void *packet, int length)
190{
191 int j, rc;
192 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200193 fec_t __iomem *fecp =
194 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200195
196 /* section 16.9.23.3
197 * Wait for ready
198 */
199 j = 0;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200200 while ((in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_READY) &&
201 (j < TOUT_LOOP)) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200202 udelay(1);
203 j++;
204 }
205 if (j>=TOUT_LOOP) {
206 printf("TX not ready\n");
207 }
208
Christophe Leroy394f9b32017-07-06 10:33:13 +0200209 out_be32(&rtx->txbd[txIdx].cbd_bufaddr, (uint)packet);
210 out_be16(&rtx->txbd[txIdx].cbd_datlen, length);
211 setbits_be16(&rtx->txbd[txIdx].cbd_sc,
212 BD_ENET_TX_READY | BD_ENET_TX_LAST);
Christophe Leroy069fa832017-07-06 10:23:22 +0200213
214 /* Activate transmit Buffer Descriptor polling */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200215 /* Descriptor polling active */
216 out_be32(&fecp->fec_x_des_active, 0x01000000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200217
218 j = 0;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200219 while ((in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_READY) &&
220 (j < TOUT_LOOP)) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200221 udelay(1);
222 j++;
223 }
224 if (j>=TOUT_LOOP) {
225 printf("TX timeout\n");
226 }
227 /* return only status bits */;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200228 rc = in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_STATS;
Christophe Leroy069fa832017-07-06 10:23:22 +0200229
230 txIdx = (txIdx + 1) % TX_BUF_CNT;
231
232 return rc;
233}
234
235static int fec_recv (struct eth_device *dev)
236{
237 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200238 fec_t __iomem *fecp =
239 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200240 int length;
241
242 for (;;) {
243 /* section 16.9.23.2 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200244 if (in_be16(&rtx->rxbd[rxIdx].cbd_sc) & BD_ENET_RX_EMPTY) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200245 length = -1;
246 break; /* nothing received - leave for() loop */
247 }
248
Christophe Leroy394f9b32017-07-06 10:33:13 +0200249 length = in_be16(&rtx->rxbd[rxIdx].cbd_datlen);
Christophe Leroy069fa832017-07-06 10:23:22 +0200250
Christophe Leroy394f9b32017-07-06 10:33:13 +0200251 if (!(in_be16(&rtx->rxbd[rxIdx].cbd_sc) & 0x003f)) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200252 uchar *rx = net_rx_packets[rxIdx];
253
254 length -= 4;
255
256#if defined(CONFIG_CMD_CDP)
257 if ((rx[0] & 1) != 0 &&
258 memcmp((uchar *)rx, net_bcast_ethaddr, 6) != 0 &&
259 !is_cdp_packet((uchar *)rx))
260 rx = NULL;
261#endif
262 /*
263 * Pass the packet up to the protocol layers.
264 */
265 if (rx != NULL)
266 net_process_received_packet(rx, length);
267 }
268
269 /* Give the buffer back to the FEC. */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200270 out_be16(&rtx->rxbd[rxIdx].cbd_datlen, 0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200271
272 /* wrap around buffer index when necessary */
273 if ((rxIdx + 1) >= PKTBUFSRX) {
Christophe Leroy394f9b32017-07-06 10:33:13 +0200274 out_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc,
275 BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
Christophe Leroy069fa832017-07-06 10:23:22 +0200276 rxIdx = 0;
277 } else {
Christophe Leroy394f9b32017-07-06 10:33:13 +0200278 out_be16(&rtx->rxbd[rxIdx].cbd_sc, BD_ENET_RX_EMPTY);
Christophe Leroy069fa832017-07-06 10:23:22 +0200279 rxIdx++;
280 }
281
Christophe Leroy069fa832017-07-06 10:23:22 +0200282 /* Try to fill Buffer Descriptors */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200283 /* Descriptor polling active */
284 out_be32(&fecp->fec_r_des_active, 0x01000000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200285 }
286
287 return length;
288}
289
290/**************************************************************
291 *
292 * FEC Ethernet Initialization Routine
293 *
294 *************************************************************/
295
296#define FEC_ECNTRL_PINMUX 0x00000004
297#define FEC_ECNTRL_ETHER_EN 0x00000002
298#define FEC_ECNTRL_RESET 0x00000001
299
300#define FEC_RCNTRL_BC_REJ 0x00000010
301#define FEC_RCNTRL_PROM 0x00000008
302#define FEC_RCNTRL_MII_MODE 0x00000004
303#define FEC_RCNTRL_DRT 0x00000002
304#define FEC_RCNTRL_LOOP 0x00000001
305
306#define FEC_TCNTRL_FDEN 0x00000004
307#define FEC_TCNTRL_HBC 0x00000002
308#define FEC_TCNTRL_GTS 0x00000001
309
310#define FEC_RESET_DELAY 50
311
312#if defined(CONFIG_RMII)
313
314static inline void fec_10Mbps(struct eth_device *dev)
315{
316 struct ether_fcc_info_s *efis = dev->priv;
317 int fecidx = efis->ether_index;
318 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200319 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy069fa832017-07-06 10:23:22 +0200320
321 if ((unsigned int)fecidx >= 2)
322 hang();
323
Christophe Leroy394f9b32017-07-06 10:33:13 +0200324 setbits_be32(&immr->im_cpm.cp_cptr, mask);
Christophe Leroy069fa832017-07-06 10:23:22 +0200325}
326
327static inline void fec_100Mbps(struct eth_device *dev)
328{
329 struct ether_fcc_info_s *efis = dev->priv;
330 int fecidx = efis->ether_index;
331 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200332 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy069fa832017-07-06 10:23:22 +0200333
334 if ((unsigned int)fecidx >= 2)
335 hang();
336
Christophe Leroy394f9b32017-07-06 10:33:13 +0200337 clrbits_be32(&immr->im_cpm.cp_cptr, mask);
Christophe Leroy069fa832017-07-06 10:23:22 +0200338}
339
340#endif
341
342static inline void fec_full_duplex(struct eth_device *dev)
343{
344 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200345 fec_t __iomem *fecp =
346 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200347
Christophe Leroy394f9b32017-07-06 10:33:13 +0200348 clrbits_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_DRT);
349 setbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */
Christophe Leroy069fa832017-07-06 10:23:22 +0200350}
351
352static inline void fec_half_duplex(struct eth_device *dev)
353{
354 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200355 fec_t __iomem *fecp =
356 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200357
Christophe Leroy394f9b32017-07-06 10:33:13 +0200358 setbits_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_DRT);
359 clrbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD disable */
Christophe Leroy069fa832017-07-06 10:23:22 +0200360}
361
362static void fec_pin_init(int fecidx)
363{
364 bd_t *bd = gd->bd;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200365 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy069fa832017-07-06 10:23:22 +0200366
367 /*
368 * Set MII speed to 2.5 MHz or slightly below.
369 *
370 * According to the MPC860T (Rev. D) Fast ethernet controller user
371 * manual (6.2.14),
372 * the MII management interface clock must be less than or equal
373 * to 2.5 MHz.
374 * This MDC frequency is equal to system clock / (2 * MII_SPEED).
375 * Then MII_SPEED = system_clock / 2 * 2,5 MHz.
376 *
377 * All MII configuration is done via FEC1 registers:
378 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200379 out_be32(&immr->im_cpm.cp_fec1.fec_mii_speed,
380 ((bd->bi_intfreq + 4999999) / 5000000) << 1);
Christophe Leroy069fa832017-07-06 10:23:22 +0200381
382#if defined(CONFIG_MPC885_FAMILY) && defined(WANT_MII)
383 /* use MDC for MII */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200384 setbits_be16(&immr->im_ioport.iop_pdpar, 0x0080);
385 clrbits_be16(&immr->im_ioport.iop_pddir, 0x0080);
Christophe Leroy069fa832017-07-06 10:23:22 +0200386#endif
387
388 if (fecidx == 0) {
389#if defined(CONFIG_ETHER_ON_FEC1)
390
391#if defined(CONFIG_MPC885_FAMILY) /* MPC87x/88x have got 2 FECs and different pinout */
392
393#if !defined(CONFIG_RMII)
394
Christophe Leroy394f9b32017-07-06 10:33:13 +0200395 setbits_be16(&immr->im_ioport.iop_papar, 0xf830);
396 setbits_be16(&immr->im_ioport.iop_padir, 0x0830);
397 clrbits_be16(&immr->im_ioport.iop_padir, 0xf000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200398
Christophe Leroy394f9b32017-07-06 10:33:13 +0200399 setbits_be32(&immr->im_cpm.cp_pbpar, 0x00001001);
400 clrbits_be32(&immr->im_cpm.cp_pbdir, 0x00001001);
Christophe Leroy069fa832017-07-06 10:23:22 +0200401
Christophe Leroy394f9b32017-07-06 10:33:13 +0200402 setbits_be16(&immr->im_ioport.iop_pcpar, 0x000c);
403 clrbits_be16(&immr->im_ioport.iop_pcdir, 0x000c);
Christophe Leroy069fa832017-07-06 10:23:22 +0200404
Christophe Leroy394f9b32017-07-06 10:33:13 +0200405 setbits_be32(&immr->im_cpm.cp_pepar, 0x00000003);
406 setbits_be32(&immr->im_cpm.cp_pedir, 0x00000003);
407 clrbits_be32(&immr->im_cpm.cp_peso, 0x00000003);
Christophe Leroy069fa832017-07-06 10:23:22 +0200408
Christophe Leroy394f9b32017-07-06 10:33:13 +0200409 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000100);
Christophe Leroy069fa832017-07-06 10:23:22 +0200410
411#else
412
413#if !defined(CONFIG_FEC1_PHY_NORXERR)
Christophe Leroy394f9b32017-07-06 10:33:13 +0200414 setbits_be16(&immr->im_ioport.iop_papar, 0x1000);
415 clrbits_be16(&immr->im_ioport.iop_padir, 0x1000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200416#endif
Christophe Leroy394f9b32017-07-06 10:33:13 +0200417 setbits_be16(&immr->im_ioport.iop_papar, 0xe810);
418 setbits_be16(&immr->im_ioport.iop_padir, 0x0810);
419 clrbits_be16(&immr->im_ioport.iop_padir, 0xe000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200420
Christophe Leroy394f9b32017-07-06 10:33:13 +0200421 setbits_be32(&immr->im_cpm.cp_pbpar, 0x00000001);
422 clrbits_be32(&immr->im_cpm.cp_pbdir, 0x00000001);
Christophe Leroy069fa832017-07-06 10:23:22 +0200423
Christophe Leroy394f9b32017-07-06 10:33:13 +0200424 setbits_be32(&immr->im_cpm.cp_cptr, 0x00000100);
425 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000050);
Christophe Leroy069fa832017-07-06 10:23:22 +0200426
427#endif /* !CONFIG_RMII */
428
429#else
430 /*
431 * Configure all of port D for MII.
432 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200433 out_be16(&immr->im_ioport.iop_pdpar, 0x1fff);
434 out_be16(&immr->im_ioport.iop_pddir, 0x1fff);
Christophe Leroy069fa832017-07-06 10:23:22 +0200435#endif
436
437#endif /* CONFIG_ETHER_ON_FEC1 */
438 } else if (fecidx == 1) {
439
440#if defined(CONFIG_ETHER_ON_FEC2)
441
442#if defined(CONFIG_MPC885_FAMILY) /* MPC87x/88x have got 2 FECs and different pinout */
443
444#if !defined(CONFIG_RMII)
Christophe Leroy394f9b32017-07-06 10:33:13 +0200445 setbits_be32(&immr->im_cpm.cp_pepar, 0x0003fffc);
446 setbits_be32(&immr->im_cpm.cp_pedir, 0x0003fffc);
447 clrbits_be32(&immr->im_cpm.cp_peso, 0x000087fc);
448 setbits_be32(&immr->im_cpm.cp_peso, 0x00037800);
Christophe Leroy069fa832017-07-06 10:23:22 +0200449
Christophe Leroy394f9b32017-07-06 10:33:13 +0200450 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000080);
Christophe Leroy069fa832017-07-06 10:23:22 +0200451#else
452
453#if !defined(CONFIG_FEC2_PHY_NORXERR)
Christophe Leroy394f9b32017-07-06 10:33:13 +0200454 setbits_be32(&immr->im_cpm.cp_pepar, 0x00000010);
455 setbits_be32(&immr->im_cpm.cp_pedir, 0x00000010);
456 clrbits_be32(&immr->im_cpm.cp_peso, 0x00000010);
Christophe Leroy069fa832017-07-06 10:23:22 +0200457#endif
Christophe Leroy394f9b32017-07-06 10:33:13 +0200458 setbits_be32(&immr->im_cpm.cp_pepar, 0x00039620);
459 setbits_be32(&immr->im_cpm.cp_pedir, 0x00039620);
460 setbits_be32(&immr->im_cpm.cp_peso, 0x00031000);
461 clrbits_be32(&immr->im_cpm.cp_peso, 0x00008620);
Christophe Leroy069fa832017-07-06 10:23:22 +0200462
Christophe Leroy394f9b32017-07-06 10:33:13 +0200463 setbits_be32(&immr->im_cpm.cp_cptr, 0x00000080);
464 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000028);
Christophe Leroy069fa832017-07-06 10:23:22 +0200465#endif /* CONFIG_RMII */
466
467#endif /* CONFIG_MPC885_FAMILY */
468
469#endif /* CONFIG_ETHER_ON_FEC2 */
470
471 }
472}
473
Christophe Leroy394f9b32017-07-06 10:33:13 +0200474static int fec_reset(fec_t __iomem *fecp)
Christophe Leroy069fa832017-07-06 10:23:22 +0200475{
476 int i;
477
478 /* Whack a reset.
479 * A delay is required between a reset of the FEC block and
480 * initialization of other FEC registers because the reset takes
481 * some time to complete. If you don't delay, subsequent writes
482 * to FEC registers might get killed by the reset routine which is
483 * still in progress.
484 */
485
Christophe Leroy394f9b32017-07-06 10:33:13 +0200486 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
487 for (i = 0; (in_be32(&fecp->fec_ecntrl) & FEC_ECNTRL_RESET) &&
488 (i < FEC_RESET_DELAY); ++i)
Christophe Leroy069fa832017-07-06 10:23:22 +0200489 udelay (1);
Christophe Leroy394f9b32017-07-06 10:33:13 +0200490
Christophe Leroy069fa832017-07-06 10:23:22 +0200491 if (i == FEC_RESET_DELAY)
492 return -1;
493
494 return 0;
495}
496
497static int fec_init (struct eth_device *dev, bd_t * bd)
498{
499 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200500 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
501 fec_t __iomem *fecp =
502 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200503 int i;
504
505#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
506 /* the MII interface is connected to FEC1
507 * so for the miiphy_xxx function to work we must
508 * call mii_init since fec_halt messes the thing up
509 */
510 if (efis->ether_index != 0)
511 __mii_init();
512#endif
513
514 if (fec_reset(fecp) < 0)
515 printf ("FEC_RESET_DELAY timeout\n");
516
517 /* We use strictly polling mode only
518 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200519 out_be32(&fecp->fec_imask, 0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200520
521 /* Clear any pending interrupt
522 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200523 out_be32(&fecp->fec_ievent, 0xffc0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200524
525 /* No need to set the IVEC register */
526
527 /* Set station address
528 */
529#define ea dev->enetaddr
Christophe Leroy394f9b32017-07-06 10:33:13 +0200530 out_be32(&fecp->fec_addr_low, (ea[0] << 24) | (ea[1] << 16) |
531 (ea[2] << 8) | ea[3]);
532 out_be16(&fecp->fec_addr_high, (ea[4] << 8) | ea[5]);
Christophe Leroy069fa832017-07-06 10:23:22 +0200533#undef ea
534
535#if defined(CONFIG_CMD_CDP)
536 /*
537 * Turn on multicast address hash table
538 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200539 out_be32(&fecp->fec_hash_table_high, 0xffffffff);
540 out_be32(&fecp->fec_hash_table_low, 0xffffffff);
Christophe Leroy069fa832017-07-06 10:23:22 +0200541#else
542 /* Clear multicast address hash table
543 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200544 out_be32(&fecp->fec_hash_table_high, 0);
545 out_be32(&fecp->fec_hash_table_low, 0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200546#endif
547
548 /* Set maximum receive buffer size.
549 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200550 out_be32(&fecp->fec_r_buff_size, PKT_MAXBLR_SIZE);
Christophe Leroy069fa832017-07-06 10:23:22 +0200551
552 /* Set maximum frame length
553 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200554 out_be32(&fecp->fec_r_hash, PKT_MAXBUF_SIZE);
Christophe Leroy069fa832017-07-06 10:23:22 +0200555
556 /*
557 * Setup Buffers and Buffer Desriptors
558 */
559 rxIdx = 0;
560 txIdx = 0;
561
562 if (!rtx)
Christophe Leroy394f9b32017-07-06 10:33:13 +0200563 rtx = (struct common_buf_desc __iomem *)
564 (immr->im_cpm.cp_dpmem + CPM_FEC_BASE);
Christophe Leroy069fa832017-07-06 10:23:22 +0200565 /*
566 * Setup Receiver Buffer Descriptors (13.14.24.18)
567 * Settings:
568 * Empty, Wrap
569 */
570 for (i = 0; i < PKTBUFSRX; i++) {
Christophe Leroy394f9b32017-07-06 10:33:13 +0200571 out_be16(&rtx->rxbd[i].cbd_sc, BD_ENET_RX_EMPTY);
572 out_be16(&rtx->rxbd[i].cbd_datlen, 0); /* Reset */
573 out_be32(&rtx->rxbd[i].cbd_bufaddr, (uint)net_rx_packets[i]);
Christophe Leroy069fa832017-07-06 10:23:22 +0200574 }
Christophe Leroy394f9b32017-07-06 10:33:13 +0200575 setbits_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc, BD_ENET_RX_WRAP);
Christophe Leroy069fa832017-07-06 10:23:22 +0200576
577 /*
578 * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
579 * Settings:
580 * Last, Tx CRC
581 */
582 for (i = 0; i < TX_BUF_CNT; i++) {
Christophe Leroy394f9b32017-07-06 10:33:13 +0200583 out_be16(&rtx->txbd[i].cbd_sc, BD_ENET_TX_LAST | BD_ENET_TX_TC);
584 out_be16(&rtx->txbd[i].cbd_datlen, 0); /* Reset */
585 out_be32(&rtx->txbd[i].cbd_bufaddr, (uint)txbuf);
Christophe Leroy069fa832017-07-06 10:23:22 +0200586 }
Christophe Leroy394f9b32017-07-06 10:33:13 +0200587 setbits_be16(&rtx->txbd[TX_BUF_CNT - 1].cbd_sc, BD_ENET_TX_WRAP);
Christophe Leroy069fa832017-07-06 10:23:22 +0200588
589 /* Set receive and transmit descriptor base
590 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200591 out_be32(&fecp->fec_r_des_start, (__force unsigned int)rtx->rxbd);
592 out_be32(&fecp->fec_x_des_start, (__force unsigned int)rtx->txbd);
Christophe Leroy069fa832017-07-06 10:23:22 +0200593
594 /* Enable MII mode
595 */
596 /* Half duplex mode */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200597 out_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT);
598 out_be32(&fecp->fec_x_cntrl, 0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200599
600 /* Enable big endian and don't care about SDMA FC.
601 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200602 out_be32(&fecp->fec_fun_code, 0x78000000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200603
604 /*
605 * Setup the pin configuration of the FEC
606 */
607 fec_pin_init (efis->ether_index);
608
609 rxIdx = 0;
610 txIdx = 0;
611
612 /*
613 * Now enable the transmit and receive processing
614 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200615 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
Christophe Leroy069fa832017-07-06 10:23:22 +0200616
617 if (efis->phy_addr == -1) {
618#ifdef CONFIG_SYS_DISCOVER_PHY
619 /*
620 * wait for the PHY to wake up after reset
621 */
622 efis->actual_phy_addr = mii_discover_phy (dev);
623
624 if (efis->actual_phy_addr == -1) {
625 printf ("Unable to discover phy!\n");
626 return -1;
627 }
628#else
629 efis->actual_phy_addr = -1;
630#endif
631 } else {
632 efis->actual_phy_addr = efis->phy_addr;
633 }
634
635#if defined(CONFIG_MII) && defined(CONFIG_RMII)
636 /*
637 * adapt the RMII speed to the speed of the phy
638 */
639 if (miiphy_speed (dev->name, efis->actual_phy_addr) == _100BASET) {
640 fec_100Mbps (dev);
641 } else {
642 fec_10Mbps (dev);
643 }
644#endif
645
646#if defined(CONFIG_MII)
647 /*
648 * adapt to the half/full speed settings
649 */
650 if (miiphy_duplex (dev->name, efis->actual_phy_addr) == FULL) {
651 fec_full_duplex (dev);
652 } else {
653 fec_half_duplex (dev);
654 }
655#endif
656
657 /* And last, try to fill Rx Buffer Descriptors */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200658 /* Descriptor polling active */
659 out_be32(&fecp->fec_r_des_active, 0x01000000);
Christophe Leroy069fa832017-07-06 10:23:22 +0200660
661 efis->initialized = 1;
662
663 return 0;
664}
665
666
667static void fec_halt(struct eth_device* dev)
668{
669 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200670 fec_t __iomem *fecp =
671 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy069fa832017-07-06 10:23:22 +0200672 int i;
673
674 /* avoid halt if initialized; mii gets stuck otherwise */
675 if (!efis->initialized)
676 return;
677
678 /* Whack a reset.
679 * A delay is required between a reset of the FEC block and
680 * initialization of other FEC registers because the reset takes
681 * some time to complete. If you don't delay, subsequent writes
682 * to FEC registers might get killed by the reset routine which is
683 * still in progress.
684 */
685
Christophe Leroy394f9b32017-07-06 10:33:13 +0200686 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
687 for (i = 0; (in_be32(&fecp->fec_ecntrl) & FEC_ECNTRL_RESET) &&
688 (i < FEC_RESET_DELAY); ++i)
Christophe Leroy069fa832017-07-06 10:23:22 +0200689 udelay (1);
Christophe Leroy394f9b32017-07-06 10:33:13 +0200690
Christophe Leroy069fa832017-07-06 10:23:22 +0200691 if (i == FEC_RESET_DELAY) {
692 printf ("FEC_RESET_DELAY timeout\n");
693 return;
694 }
695
696 efis->initialized = 0;
697}
698
699#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
700
701/* Make MII read/write commands for the FEC.
702*/
703
704#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \
705 (REG & 0x1f) << 18))
706
707#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \
708 (REG & 0x1f) << 18) | \
709 (VAL & 0xffff))
710
711/* Interrupt events/masks.
712*/
713#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
714#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
715#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */
716#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */
717#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */
718#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */
719#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */
720#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
721#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
722#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
723
724/* send command to phy using mii, wait for result */
725static uint
726mii_send(uint mii_cmd)
727{
728 uint mii_reply;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200729 fec_t __iomem *ep;
Christophe Leroy069fa832017-07-06 10:23:22 +0200730 int cnt;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200731 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy069fa832017-07-06 10:23:22 +0200732
Christophe Leroy394f9b32017-07-06 10:33:13 +0200733 ep = &immr->im_cpm.cp_fec;
Christophe Leroy069fa832017-07-06 10:23:22 +0200734
Christophe Leroy394f9b32017-07-06 10:33:13 +0200735 out_be32(&ep->fec_mii_data, mii_cmd); /* command to phy */
Christophe Leroy069fa832017-07-06 10:23:22 +0200736
737 /* wait for mii complete */
738 cnt = 0;
Christophe Leroy394f9b32017-07-06 10:33:13 +0200739 while (!(in_be32(&ep->fec_ievent) & FEC_ENET_MII)) {
Christophe Leroy069fa832017-07-06 10:23:22 +0200740 if (++cnt > 1000) {
741 printf("mii_send STUCK!\n");
742 break;
743 }
744 }
Christophe Leroy394f9b32017-07-06 10:33:13 +0200745 mii_reply = in_be32(&ep->fec_mii_data); /* result from phy */
746 out_be32(&ep->fec_ievent, FEC_ENET_MII); /* clear MII complete */
Christophe Leroy069fa832017-07-06 10:23:22 +0200747 return (mii_reply & 0xffff); /* data read from phy */
748}
749#endif
750
751#if defined(CONFIG_SYS_DISCOVER_PHY)
752static int mii_discover_phy(struct eth_device *dev)
753{
754#define MAX_PHY_PASSES 11
755 uint phyno;
756 int pass;
757 uint phytype;
758 int phyaddr;
759
760 phyaddr = -1; /* didn't find a PHY yet */
761 for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
762 if (pass > 1) {
763 /* PHY may need more time to recover from reset.
764 * The LXT970 needs 50ms typical, no maximum is
765 * specified, so wait 10ms before try again.
766 * With 11 passes this gives it 100ms to wake up.
767 */
768 udelay(10000); /* wait 10ms */
769 }
770 for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {
771 phytype = mii_send(mk_mii_read(phyno, MII_PHYSID2));
772 if (phytype != 0xffff) {
773 phyaddr = phyno;
774 phytype |= mii_send(mk_mii_read(phyno,
775 MII_PHYSID1)) << 16;
776 }
777 }
778 }
779 if (phyaddr < 0) {
780 printf("No PHY device found.\n");
781 }
782 return phyaddr;
783}
784#endif /* CONFIG_SYS_DISCOVER_PHY */
785
786#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && !defined(CONFIG_BITBANGMII)
787
788/****************************************************************************
789 * mii_init -- Initialize the MII via FEC 1 for MII command without ethernet
790 * This function is a subset of eth_init
791 ****************************************************************************
792 */
793static void __mii_init(void)
794{
Christophe Leroy394f9b32017-07-06 10:33:13 +0200795 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
796 fec_t __iomem *fecp = &immr->im_cpm.cp_fec;
Christophe Leroy069fa832017-07-06 10:23:22 +0200797
798 if (fec_reset(fecp) < 0)
799 printf ("FEC_RESET_DELAY timeout\n");
800
801 /* We use strictly polling mode only
802 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200803 out_be32(&fecp->fec_imask, 0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200804
805 /* Clear any pending interrupt
806 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200807 out_be32(&fecp->fec_ievent, 0xffc0);
Christophe Leroy069fa832017-07-06 10:23:22 +0200808
809 /* Now enable the transmit and receive processing
810 */
Christophe Leroy394f9b32017-07-06 10:33:13 +0200811 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
Christophe Leroy069fa832017-07-06 10:23:22 +0200812}
813
814void mii_init (void)
815{
816 int i;
817
818 __mii_init();
819
820 /* Setup the pin configuration of the FEC(s)
821 */
822 for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
823 fec_pin_init(ether_fcc_info[i].ether_index);
824}
825
826/*****************************************************************************
827 * Read and write a MII PHY register, routines used by MII Utilities
828 *
829 * FIXME: These routines are expected to return 0 on success, but mii_send
830 * does _not_ return an error code. Maybe 0xFFFF means error, i.e.
831 * no PHY connected...
832 * For now always return 0.
833 * FIXME: These routines only work after calling eth_init() at least once!
834 * Otherwise they hang in mii_send() !!! Sorry!
835 *****************************************************************************/
836
837int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
838{
839 unsigned short value = 0;
840 short rdreg; /* register working value */
841
842 rdreg = mii_send(mk_mii_read(addr, reg));
843
844 value = rdreg;
845 return value;
846}
847
848int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
849 u16 value)
850{
851 (void)mii_send(mk_mii_write(addr, reg, value));
852
853 return 0;
854}
855#endif
856
857#endif