blob: 69b2174ab3d676280f38083026977804da53b202 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Christophe Leroy907208c2017-07-06 10:23:22 +02002/*
3 * (C) Copyright 2000
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
Christophe Leroy907208c2017-07-06 10:23:22 +02005 */
6
7#include <common.h>
8#include <command.h>
Simon Glassdb41d652019-12-28 10:45:07 -07009#include <hang.h>
Christophe Leroy907208c2017-07-06 10:23:22 +020010#include <malloc.h>
11#include <net.h>
Christophe Leroy08dd9882017-07-13 15:10:08 +020012#include <netdev.h>
Christophe Leroy18f8d4c2018-03-16 17:20:43 +010013#include <asm/cpm_8xx.h>
Christophe Leroyba3da732017-07-06 10:33:13 +020014#include <asm/io.h>
Christophe Leroy907208c2017-07-06 10:23:22 +020015
16#include <phy.h>
Simon Glass68a6aa82019-11-14 12:57:31 -070017#include <linux/mii.h>
Christophe Leroy907208c2017-07-06 10:23:22 +020018
19DECLARE_GLOBAL_DATA_PTR;
20
Christophe Leroy907208c2017-07-06 10:23:22 +020021/* define WANT_MII when MII support is required */
22#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_FEC1_PHY) || defined(CONFIG_FEC2_PHY)
23#define WANT_MII
24#else
25#undef WANT_MII
26#endif
27
28#if defined(WANT_MII)
29#include <miiphy.h>
30
31#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
32#error "CONFIG_MII has to be defined!"
33#endif
34
35#endif
36
37#if defined(CONFIG_RMII) && !defined(WANT_MII)
38#error RMII support is unusable without a working PHY.
39#endif
40
41#ifdef CONFIG_SYS_DISCOVER_PHY
42static int mii_discover_phy(struct eth_device *dev);
43#endif
44
45int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
46int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
47 u16 value);
48
49static struct ether_fcc_info_s
50{
51 int ether_index;
52 int fecp_offset;
53 int phy_addr;
54 int actual_phy_addr;
55 int initialized;
56}
57 ether_fcc_info[] = {
58#if defined(CONFIG_ETHER_ON_FEC1)
59 {
60 0,
61 offsetof(immap_t, im_cpm.cp_fec1),
Christophe Leroy907208c2017-07-06 10:23:22 +020062 CONFIG_FEC1_PHY,
Christophe Leroy907208c2017-07-06 10:23:22 +020063 -1,
64 0,
65
66 },
67#endif
68#if defined(CONFIG_ETHER_ON_FEC2)
69 {
70 1,
71 offsetof(immap_t, im_cpm.cp_fec2),
Christophe Leroy907208c2017-07-06 10:23:22 +020072 CONFIG_FEC2_PHY,
Christophe Leroy907208c2017-07-06 10:23:22 +020073 -1,
74 0,
75 },
76#endif
77};
78
79/* Ethernet Transmit and Receive Buffers */
80#define DBUF_LENGTH 1520
81
82#define TX_BUF_CNT 2
83
84#define TOUT_LOOP 100
85
86#define PKT_MAXBUF_SIZE 1518
87#define PKT_MINBUF_SIZE 64
88#define PKT_MAXBLR_SIZE 1520
89
90#ifdef __GNUC__
Christophe Leroy70fd0712017-07-06 10:33:17 +020091static char txbuf[DBUF_LENGTH] __aligned(8);
Christophe Leroy907208c2017-07-06 10:23:22 +020092#else
93#error txbuf must be aligned.
94#endif
95
96static uint rxIdx; /* index of the current RX buffer */
97static uint txIdx; /* index of the current TX buffer */
98
99/*
100 * FEC Ethernet Tx and Rx buffer descriptors allocated at the
101 * immr->udata_bd address on Dual-Port RAM
102 * Provide for Double Buffering
103 */
104
Christophe Leroyba3da732017-07-06 10:33:13 +0200105struct common_buf_desc {
Christophe Leroy70fd0712017-07-06 10:33:17 +0200106 cbd_t rxbd[PKTBUFSRX]; /* Rx BD */
107 cbd_t txbd[TX_BUF_CNT]; /* Tx BD */
Christophe Leroyba3da732017-07-06 10:33:13 +0200108};
Christophe Leroy907208c2017-07-06 10:23:22 +0200109
Christophe Leroyba3da732017-07-06 10:33:13 +0200110static struct common_buf_desc __iomem *rtx;
Christophe Leroy907208c2017-07-06 10:23:22 +0200111
112static int fec_send(struct eth_device *dev, void *packet, int length);
Christophe Leroy70fd0712017-07-06 10:33:17 +0200113static int fec_recv(struct eth_device *dev);
114static int fec_init(struct eth_device *dev, bd_t *bd);
115static void fec_halt(struct eth_device *dev);
Christophe Leroy907208c2017-07-06 10:23:22 +0200116#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
117static void __mii_init(void);
118#endif
119
120int fec_initialize(bd_t *bis)
121{
Christophe Leroy70fd0712017-07-06 10:33:17 +0200122 struct eth_device *dev;
Christophe Leroy907208c2017-07-06 10:23:22 +0200123 struct ether_fcc_info_s *efis;
124 int i;
125
126 for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200127 dev = malloc(sizeof(*dev));
128 if (dev == NULL)
129 hang();
130
131 memset(dev, 0, sizeof(*dev));
132
133 /* for FEC1 make sure that the name of the interface is the same
134 as the old one for compatibility reasons */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200135 if (i == 0)
Christophe Leroy907208c2017-07-06 10:23:22 +0200136 strcpy(dev->name, "FEC");
Christophe Leroy70fd0712017-07-06 10:33:17 +0200137 else
138 sprintf(dev->name, "FEC%d",
Christophe Leroy907208c2017-07-06 10:23:22 +0200139 ether_fcc_info[i].ether_index + 1);
Christophe Leroy907208c2017-07-06 10:23:22 +0200140
141 efis = &ether_fcc_info[i];
142
143 /*
144 * reset actual phy addr
145 */
146 efis->actual_phy_addr = -1;
147
148 dev->priv = efis;
149 dev->init = fec_init;
150 dev->halt = fec_halt;
151 dev->send = fec_send;
152 dev->recv = fec_recv;
153
154 eth_register(dev);
155
156#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
157 int retval;
158 struct mii_dev *mdiodev = mdio_alloc();
159 if (!mdiodev)
160 return -ENOMEM;
161 strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
162 mdiodev->read = fec8xx_miiphy_read;
163 mdiodev->write = fec8xx_miiphy_write;
164
165 retval = mdio_register(mdiodev);
166 if (retval < 0)
167 return retval;
168#endif
169 }
170 return 1;
171}
172
173static int fec_send(struct eth_device *dev, void *packet, int length)
174{
175 int j, rc;
176 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200177 fec_t __iomem *fecp =
178 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200179
180 /* section 16.9.23.3
181 * Wait for ready
182 */
183 j = 0;
Christophe Leroyba3da732017-07-06 10:33:13 +0200184 while ((in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_READY) &&
185 (j < TOUT_LOOP)) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200186 udelay(1);
187 j++;
188 }
Christophe Leroy70fd0712017-07-06 10:33:17 +0200189 if (j >= TOUT_LOOP)
Christophe Leroy907208c2017-07-06 10:23:22 +0200190 printf("TX not ready\n");
Christophe Leroy907208c2017-07-06 10:23:22 +0200191
Christophe Leroyba3da732017-07-06 10:33:13 +0200192 out_be32(&rtx->txbd[txIdx].cbd_bufaddr, (uint)packet);
193 out_be16(&rtx->txbd[txIdx].cbd_datlen, length);
194 setbits_be16(&rtx->txbd[txIdx].cbd_sc,
195 BD_ENET_TX_READY | BD_ENET_TX_LAST);
Christophe Leroy907208c2017-07-06 10:23:22 +0200196
197 /* Activate transmit Buffer Descriptor polling */
Christophe Leroyba3da732017-07-06 10:33:13 +0200198 /* Descriptor polling active */
199 out_be32(&fecp->fec_x_des_active, 0x01000000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200200
201 j = 0;
Christophe Leroyba3da732017-07-06 10:33:13 +0200202 while ((in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_READY) &&
203 (j < TOUT_LOOP)) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200204 udelay(1);
205 j++;
206 }
Christophe Leroy70fd0712017-07-06 10:33:17 +0200207 if (j >= TOUT_LOOP)
Christophe Leroy907208c2017-07-06 10:23:22 +0200208 printf("TX timeout\n");
Christophe Leroy70fd0712017-07-06 10:33:17 +0200209
Christophe Leroy907208c2017-07-06 10:23:22 +0200210 /* return only status bits */;
Christophe Leroyba3da732017-07-06 10:33:13 +0200211 rc = in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_STATS;
Christophe Leroy907208c2017-07-06 10:23:22 +0200212
213 txIdx = (txIdx + 1) % TX_BUF_CNT;
214
215 return rc;
216}
217
Christophe Leroy70fd0712017-07-06 10:33:17 +0200218static int fec_recv(struct eth_device *dev)
Christophe Leroy907208c2017-07-06 10:23:22 +0200219{
220 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200221 fec_t __iomem *fecp =
222 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200223 int length;
224
225 for (;;) {
226 /* section 16.9.23.2 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200227 if (in_be16(&rtx->rxbd[rxIdx].cbd_sc) & BD_ENET_RX_EMPTY) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200228 length = -1;
229 break; /* nothing received - leave for() loop */
230 }
231
Christophe Leroyba3da732017-07-06 10:33:13 +0200232 length = in_be16(&rtx->rxbd[rxIdx].cbd_datlen);
Christophe Leroy907208c2017-07-06 10:23:22 +0200233
Christophe Leroyba3da732017-07-06 10:33:13 +0200234 if (!(in_be16(&rtx->rxbd[rxIdx].cbd_sc) & 0x003f)) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200235 uchar *rx = net_rx_packets[rxIdx];
236
237 length -= 4;
238
239#if defined(CONFIG_CMD_CDP)
240 if ((rx[0] & 1) != 0 &&
241 memcmp((uchar *)rx, net_bcast_ethaddr, 6) != 0 &&
242 !is_cdp_packet((uchar *)rx))
243 rx = NULL;
244#endif
245 /*
246 * Pass the packet up to the protocol layers.
247 */
248 if (rx != NULL)
249 net_process_received_packet(rx, length);
250 }
251
252 /* Give the buffer back to the FEC. */
Christophe Leroyba3da732017-07-06 10:33:13 +0200253 out_be16(&rtx->rxbd[rxIdx].cbd_datlen, 0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200254
255 /* wrap around buffer index when necessary */
256 if ((rxIdx + 1) >= PKTBUFSRX) {
Christophe Leroyba3da732017-07-06 10:33:13 +0200257 out_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc,
258 BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
Christophe Leroy907208c2017-07-06 10:23:22 +0200259 rxIdx = 0;
260 } else {
Christophe Leroyba3da732017-07-06 10:33:13 +0200261 out_be16(&rtx->rxbd[rxIdx].cbd_sc, BD_ENET_RX_EMPTY);
Christophe Leroy907208c2017-07-06 10:23:22 +0200262 rxIdx++;
263 }
264
Christophe Leroy907208c2017-07-06 10:23:22 +0200265 /* Try to fill Buffer Descriptors */
Christophe Leroyba3da732017-07-06 10:33:13 +0200266 /* Descriptor polling active */
267 out_be32(&fecp->fec_r_des_active, 0x01000000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200268 }
269
270 return length;
271}
272
273/**************************************************************
274 *
275 * FEC Ethernet Initialization Routine
276 *
277 *************************************************************/
278
279#define FEC_ECNTRL_PINMUX 0x00000004
280#define FEC_ECNTRL_ETHER_EN 0x00000002
281#define FEC_ECNTRL_RESET 0x00000001
282
283#define FEC_RCNTRL_BC_REJ 0x00000010
284#define FEC_RCNTRL_PROM 0x00000008
285#define FEC_RCNTRL_MII_MODE 0x00000004
286#define FEC_RCNTRL_DRT 0x00000002
287#define FEC_RCNTRL_LOOP 0x00000001
288
289#define FEC_TCNTRL_FDEN 0x00000004
290#define FEC_TCNTRL_HBC 0x00000002
291#define FEC_TCNTRL_GTS 0x00000001
292
293#define FEC_RESET_DELAY 50
294
295#if defined(CONFIG_RMII)
296
297static inline void fec_10Mbps(struct eth_device *dev)
298{
299 struct ether_fcc_info_s *efis = dev->priv;
300 int fecidx = efis->ether_index;
301 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
Christophe Leroyba3da732017-07-06 10:33:13 +0200302 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy907208c2017-07-06 10:23:22 +0200303
304 if ((unsigned int)fecidx >= 2)
305 hang();
306
Christophe Leroyba3da732017-07-06 10:33:13 +0200307 setbits_be32(&immr->im_cpm.cp_cptr, mask);
Christophe Leroy907208c2017-07-06 10:23:22 +0200308}
309
310static inline void fec_100Mbps(struct eth_device *dev)
311{
312 struct ether_fcc_info_s *efis = dev->priv;
313 int fecidx = efis->ether_index;
314 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
Christophe Leroyba3da732017-07-06 10:33:13 +0200315 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy907208c2017-07-06 10:23:22 +0200316
317 if ((unsigned int)fecidx >= 2)
318 hang();
319
Christophe Leroyba3da732017-07-06 10:33:13 +0200320 clrbits_be32(&immr->im_cpm.cp_cptr, mask);
Christophe Leroy907208c2017-07-06 10:23:22 +0200321}
322
323#endif
324
325static inline void fec_full_duplex(struct eth_device *dev)
326{
327 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200328 fec_t __iomem *fecp =
329 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200330
Christophe Leroyba3da732017-07-06 10:33:13 +0200331 clrbits_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_DRT);
332 setbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */
Christophe Leroy907208c2017-07-06 10:23:22 +0200333}
334
335static inline void fec_half_duplex(struct eth_device *dev)
336{
337 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200338 fec_t __iomem *fecp =
339 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200340
Christophe Leroyba3da732017-07-06 10:33:13 +0200341 setbits_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_DRT);
342 clrbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD disable */
Christophe Leroy907208c2017-07-06 10:23:22 +0200343}
344
345static void fec_pin_init(int fecidx)
346{
347 bd_t *bd = gd->bd;
Christophe Leroyba3da732017-07-06 10:33:13 +0200348 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy907208c2017-07-06 10:23:22 +0200349
350 /*
351 * Set MII speed to 2.5 MHz or slightly below.
352 *
353 * According to the MPC860T (Rev. D) Fast ethernet controller user
354 * manual (6.2.14),
355 * the MII management interface clock must be less than or equal
356 * to 2.5 MHz.
357 * This MDC frequency is equal to system clock / (2 * MII_SPEED).
358 * Then MII_SPEED = system_clock / 2 * 2,5 MHz.
359 *
360 * All MII configuration is done via FEC1 registers:
361 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200362 out_be32(&immr->im_cpm.cp_fec1.fec_mii_speed,
363 ((bd->bi_intfreq + 4999999) / 5000000) << 1);
Christophe Leroy907208c2017-07-06 10:23:22 +0200364
Christophe Leroyb1e41d12017-07-06 10:33:21 +0200365#if defined(CONFIG_MPC885) && defined(WANT_MII)
Christophe Leroy907208c2017-07-06 10:23:22 +0200366 /* use MDC for MII */
Christophe Leroyba3da732017-07-06 10:33:13 +0200367 setbits_be16(&immr->im_ioport.iop_pdpar, 0x0080);
368 clrbits_be16(&immr->im_ioport.iop_pddir, 0x0080);
Christophe Leroy907208c2017-07-06 10:23:22 +0200369#endif
370
371 if (fecidx == 0) {
372#if defined(CONFIG_ETHER_ON_FEC1)
373
Christophe Leroyb1e41d12017-07-06 10:33:21 +0200374#if defined(CONFIG_MPC885) /* MPC87x/88x have got 2 FECs and different pinout */
Christophe Leroy907208c2017-07-06 10:23:22 +0200375
376#if !defined(CONFIG_RMII)
377
Christophe Leroyba3da732017-07-06 10:33:13 +0200378 setbits_be16(&immr->im_ioport.iop_papar, 0xf830);
379 setbits_be16(&immr->im_ioport.iop_padir, 0x0830);
380 clrbits_be16(&immr->im_ioport.iop_padir, 0xf000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200381
Christophe Leroyba3da732017-07-06 10:33:13 +0200382 setbits_be32(&immr->im_cpm.cp_pbpar, 0x00001001);
383 clrbits_be32(&immr->im_cpm.cp_pbdir, 0x00001001);
Christophe Leroy907208c2017-07-06 10:23:22 +0200384
Christophe Leroyba3da732017-07-06 10:33:13 +0200385 setbits_be16(&immr->im_ioport.iop_pcpar, 0x000c);
386 clrbits_be16(&immr->im_ioport.iop_pcdir, 0x000c);
Christophe Leroy907208c2017-07-06 10:23:22 +0200387
Christophe Leroyba3da732017-07-06 10:33:13 +0200388 setbits_be32(&immr->im_cpm.cp_pepar, 0x00000003);
389 setbits_be32(&immr->im_cpm.cp_pedir, 0x00000003);
390 clrbits_be32(&immr->im_cpm.cp_peso, 0x00000003);
Christophe Leroy907208c2017-07-06 10:23:22 +0200391
Christophe Leroyba3da732017-07-06 10:33:13 +0200392 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000100);
Christophe Leroy907208c2017-07-06 10:23:22 +0200393
394#else
395
396#if !defined(CONFIG_FEC1_PHY_NORXERR)
Christophe Leroyba3da732017-07-06 10:33:13 +0200397 setbits_be16(&immr->im_ioport.iop_papar, 0x1000);
398 clrbits_be16(&immr->im_ioport.iop_padir, 0x1000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200399#endif
Christophe Leroyba3da732017-07-06 10:33:13 +0200400 setbits_be16(&immr->im_ioport.iop_papar, 0xe810);
401 setbits_be16(&immr->im_ioport.iop_padir, 0x0810);
402 clrbits_be16(&immr->im_ioport.iop_padir, 0xe000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200403
Christophe Leroyba3da732017-07-06 10:33:13 +0200404 setbits_be32(&immr->im_cpm.cp_pbpar, 0x00000001);
405 clrbits_be32(&immr->im_cpm.cp_pbdir, 0x00000001);
Christophe Leroy907208c2017-07-06 10:23:22 +0200406
Christophe Leroyba3da732017-07-06 10:33:13 +0200407 setbits_be32(&immr->im_cpm.cp_cptr, 0x00000100);
408 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000050);
Christophe Leroy907208c2017-07-06 10:23:22 +0200409
410#endif /* !CONFIG_RMII */
411
412#else
413 /*
414 * Configure all of port D for MII.
415 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200416 out_be16(&immr->im_ioport.iop_pdpar, 0x1fff);
417 out_be16(&immr->im_ioport.iop_pddir, 0x1fff);
Christophe Leroy53193a42017-07-07 10:16:42 +0200418
419#if defined(CONFIG_TARGET_MCR3000)
420 out_be16(&immr->im_ioport.iop_papar, 0xBBFF);
421 out_be16(&immr->im_ioport.iop_padir, 0x04F0);
422 out_be16(&immr->im_ioport.iop_paodr, 0x0000);
423
424 out_be32(&immr->im_cpm.cp_pbpar, 0x000133FF);
425 out_be32(&immr->im_cpm.cp_pbdir, 0x0003BF0F);
426 out_be16(&immr->im_cpm.cp_pbodr, 0x0000);
427
428 out_be16(&immr->im_ioport.iop_pcpar, 0x0400);
429 out_be16(&immr->im_ioport.iop_pcdir, 0x0080);
430 out_be16(&immr->im_ioport.iop_pcso , 0x0D53);
431 out_be16(&immr->im_ioport.iop_pcint, 0x0000);
432
433 out_be16(&immr->im_ioport.iop_pdpar, 0x03FE);
434 out_be16(&immr->im_ioport.iop_pddir, 0x1C09);
435
436 setbits_be32(&immr->im_ioport.utmode, 0x80);
437#endif
Christophe Leroy907208c2017-07-06 10:23:22 +0200438#endif
439
440#endif /* CONFIG_ETHER_ON_FEC1 */
441 } else if (fecidx == 1) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200442#if defined(CONFIG_ETHER_ON_FEC2)
443
Christophe Leroyb1e41d12017-07-06 10:33:21 +0200444#if defined(CONFIG_MPC885) /* MPC87x/88x have got 2 FECs and different pinout */
Christophe Leroy907208c2017-07-06 10:23:22 +0200445
446#if !defined(CONFIG_RMII)
Christophe Leroyba3da732017-07-06 10:33:13 +0200447 setbits_be32(&immr->im_cpm.cp_pepar, 0x0003fffc);
448 setbits_be32(&immr->im_cpm.cp_pedir, 0x0003fffc);
449 clrbits_be32(&immr->im_cpm.cp_peso, 0x000087fc);
450 setbits_be32(&immr->im_cpm.cp_peso, 0x00037800);
Christophe Leroy907208c2017-07-06 10:23:22 +0200451
Christophe Leroyba3da732017-07-06 10:33:13 +0200452 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000080);
Christophe Leroy907208c2017-07-06 10:23:22 +0200453#else
454
455#if !defined(CONFIG_FEC2_PHY_NORXERR)
Christophe Leroyba3da732017-07-06 10:33:13 +0200456 setbits_be32(&immr->im_cpm.cp_pepar, 0x00000010);
457 setbits_be32(&immr->im_cpm.cp_pedir, 0x00000010);
458 clrbits_be32(&immr->im_cpm.cp_peso, 0x00000010);
Christophe Leroy907208c2017-07-06 10:23:22 +0200459#endif
Christophe Leroyba3da732017-07-06 10:33:13 +0200460 setbits_be32(&immr->im_cpm.cp_pepar, 0x00039620);
461 setbits_be32(&immr->im_cpm.cp_pedir, 0x00039620);
462 setbits_be32(&immr->im_cpm.cp_peso, 0x00031000);
463 clrbits_be32(&immr->im_cpm.cp_peso, 0x00008620);
Christophe Leroy907208c2017-07-06 10:23:22 +0200464
Christophe Leroyba3da732017-07-06 10:33:13 +0200465 setbits_be32(&immr->im_cpm.cp_cptr, 0x00000080);
466 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000028);
Christophe Leroy907208c2017-07-06 10:23:22 +0200467#endif /* CONFIG_RMII */
468
Christophe Leroyb1e41d12017-07-06 10:33:21 +0200469#endif /* CONFIG_MPC885 */
Christophe Leroy907208c2017-07-06 10:23:22 +0200470
471#endif /* CONFIG_ETHER_ON_FEC2 */
Christophe Leroy907208c2017-07-06 10:23:22 +0200472 }
473}
474
Christophe Leroyba3da732017-07-06 10:33:13 +0200475static int fec_reset(fec_t __iomem *fecp)
Christophe Leroy907208c2017-07-06 10:23:22 +0200476{
477 int i;
478
479 /* Whack a reset.
480 * A delay is required between a reset of the FEC block and
481 * initialization of other FEC registers because the reset takes
482 * some time to complete. If you don't delay, subsequent writes
483 * to FEC registers might get killed by the reset routine which is
484 * still in progress.
485 */
486
Christophe Leroyba3da732017-07-06 10:33:13 +0200487 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
488 for (i = 0; (in_be32(&fecp->fec_ecntrl) & FEC_ECNTRL_RESET) &&
489 (i < FEC_RESET_DELAY); ++i)
Christophe Leroy70fd0712017-07-06 10:33:17 +0200490 udelay(1);
Christophe Leroyba3da732017-07-06 10:33:13 +0200491
Christophe Leroy907208c2017-07-06 10:23:22 +0200492 if (i == FEC_RESET_DELAY)
493 return -1;
494
495 return 0;
496}
497
Christophe Leroy70fd0712017-07-06 10:33:17 +0200498static int fec_init(struct eth_device *dev, bd_t *bd)
Christophe Leroy907208c2017-07-06 10:23:22 +0200499{
500 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200501 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
502 fec_t __iomem *fecp =
503 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200504 int i;
505
506#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
507 /* the MII interface is connected to FEC1
508 * so for the miiphy_xxx function to work we must
509 * call mii_init since fec_halt messes the thing up
510 */
511 if (efis->ether_index != 0)
512 __mii_init();
513#endif
514
515 if (fec_reset(fecp) < 0)
Christophe Leroy70fd0712017-07-06 10:33:17 +0200516 printf("FEC_RESET_DELAY timeout\n");
Christophe Leroy907208c2017-07-06 10:23:22 +0200517
518 /* We use strictly polling mode only
519 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200520 out_be32(&fecp->fec_imask, 0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200521
522 /* Clear any pending interrupt
523 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200524 out_be32(&fecp->fec_ievent, 0xffc0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200525
526 /* No need to set the IVEC register */
527
528 /* Set station address
529 */
530#define ea dev->enetaddr
Christophe Leroyba3da732017-07-06 10:33:13 +0200531 out_be32(&fecp->fec_addr_low, (ea[0] << 24) | (ea[1] << 16) |
532 (ea[2] << 8) | ea[3]);
533 out_be16(&fecp->fec_addr_high, (ea[4] << 8) | ea[5]);
Christophe Leroy907208c2017-07-06 10:23:22 +0200534#undef ea
535
536#if defined(CONFIG_CMD_CDP)
537 /*
538 * Turn on multicast address hash table
539 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200540 out_be32(&fecp->fec_hash_table_high, 0xffffffff);
541 out_be32(&fecp->fec_hash_table_low, 0xffffffff);
Christophe Leroy907208c2017-07-06 10:23:22 +0200542#else
543 /* Clear multicast address hash table
544 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200545 out_be32(&fecp->fec_hash_table_high, 0);
546 out_be32(&fecp->fec_hash_table_low, 0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200547#endif
548
549 /* Set maximum receive buffer size.
550 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200551 out_be32(&fecp->fec_r_buff_size, PKT_MAXBLR_SIZE);
Christophe Leroy907208c2017-07-06 10:23:22 +0200552
553 /* Set maximum frame length
554 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200555 out_be32(&fecp->fec_r_hash, PKT_MAXBUF_SIZE);
Christophe Leroy907208c2017-07-06 10:23:22 +0200556
557 /*
Christophe Leroy70fd0712017-07-06 10:33:17 +0200558 * Setup Buffers and Buffer Descriptors
Christophe Leroy907208c2017-07-06 10:23:22 +0200559 */
560 rxIdx = 0;
561 txIdx = 0;
562
563 if (!rtx)
Christophe Leroyba3da732017-07-06 10:33:13 +0200564 rtx = (struct common_buf_desc __iomem *)
565 (immr->im_cpm.cp_dpmem + CPM_FEC_BASE);
Christophe Leroy907208c2017-07-06 10:23:22 +0200566 /*
567 * Setup Receiver Buffer Descriptors (13.14.24.18)
568 * Settings:
569 * Empty, Wrap
570 */
571 for (i = 0; i < PKTBUFSRX; i++) {
Christophe Leroyba3da732017-07-06 10:33:13 +0200572 out_be16(&rtx->rxbd[i].cbd_sc, BD_ENET_RX_EMPTY);
573 out_be16(&rtx->rxbd[i].cbd_datlen, 0); /* Reset */
574 out_be32(&rtx->rxbd[i].cbd_bufaddr, (uint)net_rx_packets[i]);
Christophe Leroy907208c2017-07-06 10:23:22 +0200575 }
Christophe Leroyba3da732017-07-06 10:33:13 +0200576 setbits_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc, BD_ENET_RX_WRAP);
Christophe Leroy907208c2017-07-06 10:23:22 +0200577
578 /*
579 * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
580 * Settings:
581 * Last, Tx CRC
582 */
583 for (i = 0; i < TX_BUF_CNT; i++) {
Christophe Leroyba3da732017-07-06 10:33:13 +0200584 out_be16(&rtx->txbd[i].cbd_sc, BD_ENET_TX_LAST | BD_ENET_TX_TC);
585 out_be16(&rtx->txbd[i].cbd_datlen, 0); /* Reset */
586 out_be32(&rtx->txbd[i].cbd_bufaddr, (uint)txbuf);
Christophe Leroy907208c2017-07-06 10:23:22 +0200587 }
Christophe Leroyba3da732017-07-06 10:33:13 +0200588 setbits_be16(&rtx->txbd[TX_BUF_CNT - 1].cbd_sc, BD_ENET_TX_WRAP);
Christophe Leroy907208c2017-07-06 10:23:22 +0200589
590 /* Set receive and transmit descriptor base
591 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200592 out_be32(&fecp->fec_r_des_start, (__force unsigned int)rtx->rxbd);
593 out_be32(&fecp->fec_x_des_start, (__force unsigned int)rtx->txbd);
Christophe Leroy907208c2017-07-06 10:23:22 +0200594
595 /* Enable MII mode
596 */
597 /* Half duplex mode */
Christophe Leroyba3da732017-07-06 10:33:13 +0200598 out_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT);
599 out_be32(&fecp->fec_x_cntrl, 0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200600
601 /* Enable big endian and don't care about SDMA FC.
602 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200603 out_be32(&fecp->fec_fun_code, 0x78000000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200604
605 /*
606 * Setup the pin configuration of the FEC
607 */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200608 fec_pin_init(efis->ether_index);
Christophe Leroy907208c2017-07-06 10:23:22 +0200609
610 rxIdx = 0;
611 txIdx = 0;
612
613 /*
614 * Now enable the transmit and receive processing
615 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200616 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
Christophe Leroy907208c2017-07-06 10:23:22 +0200617
618 if (efis->phy_addr == -1) {
619#ifdef CONFIG_SYS_DISCOVER_PHY
620 /*
621 * wait for the PHY to wake up after reset
622 */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200623 efis->actual_phy_addr = mii_discover_phy(dev);
Christophe Leroy907208c2017-07-06 10:23:22 +0200624
625 if (efis->actual_phy_addr == -1) {
Christophe Leroy70fd0712017-07-06 10:33:17 +0200626 printf("Unable to discover phy!\n");
Christophe Leroy907208c2017-07-06 10:23:22 +0200627 return -1;
628 }
629#else
630 efis->actual_phy_addr = -1;
631#endif
632 } else {
633 efis->actual_phy_addr = efis->phy_addr;
634 }
635
636#if defined(CONFIG_MII) && defined(CONFIG_RMII)
637 /*
638 * adapt the RMII speed to the speed of the phy
639 */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200640 if (miiphy_speed(dev->name, efis->actual_phy_addr) == _100BASET)
641 fec_100Mbps(dev);
642 else
643 fec_10Mbps(dev);
Christophe Leroy907208c2017-07-06 10:23:22 +0200644#endif
645
646#if defined(CONFIG_MII)
647 /*
648 * adapt to the half/full speed settings
649 */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200650 if (miiphy_duplex(dev->name, efis->actual_phy_addr) == FULL)
651 fec_full_duplex(dev);
652 else
653 fec_half_duplex(dev);
Christophe Leroy907208c2017-07-06 10:23:22 +0200654#endif
655
656 /* And last, try to fill Rx Buffer Descriptors */
Christophe Leroyba3da732017-07-06 10:33:13 +0200657 /* Descriptor polling active */
658 out_be32(&fecp->fec_r_des_active, 0x01000000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200659
660 efis->initialized = 1;
661
662 return 0;
663}
664
665
Christophe Leroy70fd0712017-07-06 10:33:17 +0200666static void fec_halt(struct eth_device *dev)
Christophe Leroy907208c2017-07-06 10:23:22 +0200667{
668 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200669 fec_t __iomem *fecp =
670 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200671 int i;
672
673 /* avoid halt if initialized; mii gets stuck otherwise */
674 if (!efis->initialized)
675 return;
676
677 /* Whack a reset.
678 * A delay is required between a reset of the FEC block and
679 * initialization of other FEC registers because the reset takes
680 * some time to complete. If you don't delay, subsequent writes
681 * to FEC registers might get killed by the reset routine which is
682 * still in progress.
683 */
684
Christophe Leroyba3da732017-07-06 10:33:13 +0200685 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
686 for (i = 0; (in_be32(&fecp->fec_ecntrl) & FEC_ECNTRL_RESET) &&
687 (i < FEC_RESET_DELAY); ++i)
Christophe Leroy70fd0712017-07-06 10:33:17 +0200688 udelay(1);
Christophe Leroyba3da732017-07-06 10:33:13 +0200689
Christophe Leroy907208c2017-07-06 10:23:22 +0200690 if (i == FEC_RESET_DELAY) {
Christophe Leroy70fd0712017-07-06 10:33:17 +0200691 printf("FEC_RESET_DELAY timeout\n");
Christophe Leroy907208c2017-07-06 10:23:22 +0200692 return;
693 }
694
695 efis->initialized = 0;
696}
697
698#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
699
700/* Make MII read/write commands for the FEC.
701*/
702
703#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \
704 (REG & 0x1f) << 18))
705
706#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \
707 (REG & 0x1f) << 18) | \
708 (VAL & 0xffff))
709
710/* Interrupt events/masks.
711*/
712#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
713#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
714#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */
715#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */
716#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */
717#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */
718#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */
719#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
720#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
721#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
722
723/* send command to phy using mii, wait for result */
724static uint
725mii_send(uint mii_cmd)
726{
727 uint mii_reply;
Christophe Leroyba3da732017-07-06 10:33:13 +0200728 fec_t __iomem *ep;
Christophe Leroy907208c2017-07-06 10:23:22 +0200729 int cnt;
Christophe Leroyba3da732017-07-06 10:33:13 +0200730 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy907208c2017-07-06 10:23:22 +0200731
Christophe Leroyba3da732017-07-06 10:33:13 +0200732 ep = &immr->im_cpm.cp_fec;
Christophe Leroy907208c2017-07-06 10:23:22 +0200733
Christophe Leroyba3da732017-07-06 10:33:13 +0200734 out_be32(&ep->fec_mii_data, mii_cmd); /* command to phy */
Christophe Leroy907208c2017-07-06 10:23:22 +0200735
736 /* wait for mii complete */
737 cnt = 0;
Christophe Leroyba3da732017-07-06 10:33:13 +0200738 while (!(in_be32(&ep->fec_ievent) & FEC_ENET_MII)) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200739 if (++cnt > 1000) {
740 printf("mii_send STUCK!\n");
741 break;
742 }
743 }
Christophe Leroyba3da732017-07-06 10:33:13 +0200744 mii_reply = in_be32(&ep->fec_mii_data); /* result from phy */
745 out_be32(&ep->fec_ievent, FEC_ENET_MII); /* clear MII complete */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200746 return mii_reply & 0xffff; /* data read from phy */
Christophe Leroy907208c2017-07-06 10:23:22 +0200747}
748#endif
749
750#if defined(CONFIG_SYS_DISCOVER_PHY)
751static int mii_discover_phy(struct eth_device *dev)
752{
753#define MAX_PHY_PASSES 11
754 uint phyno;
755 int pass;
756 uint phytype;
757 int phyaddr;
758
759 phyaddr = -1; /* didn't find a PHY yet */
760 for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
761 if (pass > 1) {
762 /* PHY may need more time to recover from reset.
763 * The LXT970 needs 50ms typical, no maximum is
764 * specified, so wait 10ms before try again.
765 * With 11 passes this gives it 100ms to wake up.
766 */
767 udelay(10000); /* wait 10ms */
768 }
769 for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {
770 phytype = mii_send(mk_mii_read(phyno, MII_PHYSID2));
771 if (phytype != 0xffff) {
772 phyaddr = phyno;
773 phytype |= mii_send(mk_mii_read(phyno,
774 MII_PHYSID1)) << 16;
775 }
776 }
777 }
Christophe Leroy70fd0712017-07-06 10:33:17 +0200778 if (phyaddr < 0)
Christophe Leroy907208c2017-07-06 10:23:22 +0200779 printf("No PHY device found.\n");
Christophe Leroy70fd0712017-07-06 10:33:17 +0200780
Christophe Leroy907208c2017-07-06 10:23:22 +0200781 return phyaddr;
782}
783#endif /* CONFIG_SYS_DISCOVER_PHY */
784
785#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && !defined(CONFIG_BITBANGMII)
786
787/****************************************************************************
788 * mii_init -- Initialize the MII via FEC 1 for MII command without ethernet
789 * This function is a subset of eth_init
790 ****************************************************************************
791 */
792static void __mii_init(void)
793{
Christophe Leroyba3da732017-07-06 10:33:13 +0200794 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
795 fec_t __iomem *fecp = &immr->im_cpm.cp_fec;
Christophe Leroy907208c2017-07-06 10:23:22 +0200796
797 if (fec_reset(fecp) < 0)
Christophe Leroy70fd0712017-07-06 10:33:17 +0200798 printf("FEC_RESET_DELAY timeout\n");
Christophe Leroy907208c2017-07-06 10:23:22 +0200799
800 /* We use strictly polling mode only
801 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200802 out_be32(&fecp->fec_imask, 0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200803
804 /* Clear any pending interrupt
805 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200806 out_be32(&fecp->fec_ievent, 0xffc0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200807
808 /* Now enable the transmit and receive processing
809 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200810 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
Christophe Leroy907208c2017-07-06 10:23:22 +0200811}
812
Christophe Leroy70fd0712017-07-06 10:33:17 +0200813void mii_init(void)
Christophe Leroy907208c2017-07-06 10:23:22 +0200814{
815 int i;
816
817 __mii_init();
818
819 /* Setup the pin configuration of the FEC(s)
820 */
821 for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
822 fec_pin_init(ether_fcc_info[i].ether_index);
823}
824
825/*****************************************************************************
826 * Read and write a MII PHY register, routines used by MII Utilities
827 *
828 * FIXME: These routines are expected to return 0 on success, but mii_send
829 * does _not_ return an error code. Maybe 0xFFFF means error, i.e.
830 * no PHY connected...
831 * For now always return 0.
832 * FIXME: These routines only work after calling eth_init() at least once!
833 * Otherwise they hang in mii_send() !!! Sorry!
834 *****************************************************************************/
835
836int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
837{
838 unsigned short value = 0;
839 short rdreg; /* register working value */
840
841 rdreg = mii_send(mk_mii_read(addr, reg));
842
843 value = rdreg;
844 return value;
845}
846
847int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
848 u16 value)
849{
850 (void)mii_send(mk_mii_write(addr, reg, value));
851
852 return 0;
853}
854#endif