blob: 4eb826028111c47d2038246e26d649165e111182 [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>
Simon Glass401d1c42020-10-30 21:38:53 -060014#include <asm/global_data.h>
Christophe Leroyba3da732017-07-06 10:33:13 +020015#include <asm/io.h>
Simon Glassc05ed002020-05-10 11:40:11 -060016#include <linux/delay.h>
Christophe Leroy907208c2017-07-06 10:23:22 +020017
18#include <phy.h>
Simon Glass68a6aa82019-11-14 12:57:31 -070019#include <linux/mii.h>
Christophe Leroy907208c2017-07-06 10:23:22 +020020
21DECLARE_GLOBAL_DATA_PTR;
22
Christophe Leroy907208c2017-07-06 10:23:22 +020023/* define WANT_MII when MII support is required */
24#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_FEC1_PHY) || defined(CONFIG_FEC2_PHY)
25#define WANT_MII
26#else
27#undef WANT_MII
28#endif
29
30#if defined(WANT_MII)
31#include <miiphy.h>
32
33#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
34#error "CONFIG_MII has to be defined!"
35#endif
36
37#endif
38
39#if defined(CONFIG_RMII) && !defined(WANT_MII)
40#error RMII support is unusable without a working PHY.
41#endif
42
43#ifdef CONFIG_SYS_DISCOVER_PHY
44static int mii_discover_phy(struct eth_device *dev);
45#endif
46
47int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
48int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
49 u16 value);
50
51static struct ether_fcc_info_s
52{
53 int ether_index;
54 int fecp_offset;
55 int phy_addr;
56 int actual_phy_addr;
57 int initialized;
58}
59 ether_fcc_info[] = {
60#if defined(CONFIG_ETHER_ON_FEC1)
61 {
62 0,
63 offsetof(immap_t, im_cpm.cp_fec1),
Christophe Leroy907208c2017-07-06 10:23:22 +020064 CONFIG_FEC1_PHY,
Christophe Leroy907208c2017-07-06 10:23:22 +020065 -1,
66 0,
67
68 },
69#endif
70#if defined(CONFIG_ETHER_ON_FEC2)
71 {
72 1,
73 offsetof(immap_t, im_cpm.cp_fec2),
Christophe Leroy907208c2017-07-06 10:23:22 +020074 CONFIG_FEC2_PHY,
Christophe Leroy907208c2017-07-06 10:23:22 +020075 -1,
76 0,
77 },
78#endif
79};
80
81/* Ethernet Transmit and Receive Buffers */
82#define DBUF_LENGTH 1520
83
84#define TX_BUF_CNT 2
85
86#define TOUT_LOOP 100
87
88#define PKT_MAXBUF_SIZE 1518
89#define PKT_MINBUF_SIZE 64
90#define PKT_MAXBLR_SIZE 1520
91
92#ifdef __GNUC__
Christophe Leroy70fd0712017-07-06 10:33:17 +020093static char txbuf[DBUF_LENGTH] __aligned(8);
Christophe Leroy907208c2017-07-06 10:23:22 +020094#else
95#error txbuf must be aligned.
96#endif
97
98static uint rxIdx; /* index of the current RX buffer */
99static uint txIdx; /* index of the current TX buffer */
100
101/*
102 * FEC Ethernet Tx and Rx buffer descriptors allocated at the
103 * immr->udata_bd address on Dual-Port RAM
104 * Provide for Double Buffering
105 */
106
Christophe Leroyba3da732017-07-06 10:33:13 +0200107struct common_buf_desc {
Christophe Leroy70fd0712017-07-06 10:33:17 +0200108 cbd_t rxbd[PKTBUFSRX]; /* Rx BD */
109 cbd_t txbd[TX_BUF_CNT]; /* Tx BD */
Christophe Leroyba3da732017-07-06 10:33:13 +0200110};
Christophe Leroy907208c2017-07-06 10:23:22 +0200111
Christophe Leroyba3da732017-07-06 10:33:13 +0200112static struct common_buf_desc __iomem *rtx;
Christophe Leroy907208c2017-07-06 10:23:22 +0200113
114static int fec_send(struct eth_device *dev, void *packet, int length);
Christophe Leroy70fd0712017-07-06 10:33:17 +0200115static int fec_recv(struct eth_device *dev);
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +0900116static int fec_init(struct eth_device *dev, struct bd_info *bd);
Christophe Leroy70fd0712017-07-06 10:33:17 +0200117static void fec_halt(struct eth_device *dev);
Christophe Leroy907208c2017-07-06 10:23:22 +0200118#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
119static void __mii_init(void);
120#endif
121
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +0900122int fec_initialize(struct bd_info *bis)
Christophe Leroy907208c2017-07-06 10:23:22 +0200123{
Christophe Leroy70fd0712017-07-06 10:33:17 +0200124 struct eth_device *dev;
Christophe Leroy907208c2017-07-06 10:23:22 +0200125 struct ether_fcc_info_s *efis;
126 int i;
127
128 for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200129 dev = malloc(sizeof(*dev));
130 if (dev == NULL)
131 hang();
132
133 memset(dev, 0, sizeof(*dev));
134
135 /* for FEC1 make sure that the name of the interface is the same
136 as the old one for compatibility reasons */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200137 if (i == 0)
Christophe Leroy907208c2017-07-06 10:23:22 +0200138 strcpy(dev->name, "FEC");
Christophe Leroy70fd0712017-07-06 10:33:17 +0200139 else
140 sprintf(dev->name, "FEC%d",
Christophe Leroy907208c2017-07-06 10:23:22 +0200141 ether_fcc_info[i].ether_index + 1);
Christophe Leroy907208c2017-07-06 10:23:22 +0200142
143 efis = &ether_fcc_info[i];
144
145 /*
146 * reset actual phy addr
147 */
148 efis->actual_phy_addr = -1;
149
150 dev->priv = efis;
151 dev->init = fec_init;
152 dev->halt = fec_halt;
153 dev->send = fec_send;
154 dev->recv = fec_recv;
155
156 eth_register(dev);
157
158#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
159 int retval;
160 struct mii_dev *mdiodev = mdio_alloc();
161 if (!mdiodev)
162 return -ENOMEM;
Vladimir Oltean56b9cae2021-09-27 14:21:53 +0300163 strlcpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
Christophe Leroy907208c2017-07-06 10:23:22 +0200164 mdiodev->read = fec8xx_miiphy_read;
165 mdiodev->write = fec8xx_miiphy_write;
166
167 retval = mdio_register(mdiodev);
168 if (retval < 0)
169 return retval;
170#endif
171 }
172 return 1;
173}
174
175static int fec_send(struct eth_device *dev, void *packet, int length)
176{
177 int j, rc;
178 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200179 fec_t __iomem *fecp =
180 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200181
182 /* section 16.9.23.3
183 * Wait for ready
184 */
185 j = 0;
Christophe Leroyba3da732017-07-06 10:33:13 +0200186 while ((in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_READY) &&
187 (j < TOUT_LOOP)) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200188 udelay(1);
189 j++;
190 }
Christophe Leroy70fd0712017-07-06 10:33:17 +0200191 if (j >= TOUT_LOOP)
Christophe Leroy907208c2017-07-06 10:23:22 +0200192 printf("TX not ready\n");
Christophe Leroy907208c2017-07-06 10:23:22 +0200193
Christophe Leroyba3da732017-07-06 10:33:13 +0200194 out_be32(&rtx->txbd[txIdx].cbd_bufaddr, (uint)packet);
195 out_be16(&rtx->txbd[txIdx].cbd_datlen, length);
196 setbits_be16(&rtx->txbd[txIdx].cbd_sc,
197 BD_ENET_TX_READY | BD_ENET_TX_LAST);
Christophe Leroy907208c2017-07-06 10:23:22 +0200198
199 /* Activate transmit Buffer Descriptor polling */
Christophe Leroyba3da732017-07-06 10:33:13 +0200200 /* Descriptor polling active */
201 out_be32(&fecp->fec_x_des_active, 0x01000000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200202
203 j = 0;
Christophe Leroyba3da732017-07-06 10:33:13 +0200204 while ((in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_READY) &&
205 (j < TOUT_LOOP)) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200206 udelay(1);
207 j++;
208 }
Christophe Leroy70fd0712017-07-06 10:33:17 +0200209 if (j >= TOUT_LOOP)
Christophe Leroy907208c2017-07-06 10:23:22 +0200210 printf("TX timeout\n");
Christophe Leroy70fd0712017-07-06 10:33:17 +0200211
Christophe Leroy907208c2017-07-06 10:23:22 +0200212 /* return only status bits */;
Christophe Leroyba3da732017-07-06 10:33:13 +0200213 rc = in_be16(&rtx->txbd[txIdx].cbd_sc) & BD_ENET_TX_STATS;
Christophe Leroy907208c2017-07-06 10:23:22 +0200214
215 txIdx = (txIdx + 1) % TX_BUF_CNT;
216
217 return rc;
218}
219
Christophe Leroy70fd0712017-07-06 10:33:17 +0200220static int fec_recv(struct eth_device *dev)
Christophe Leroy907208c2017-07-06 10:23:22 +0200221{
222 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200223 fec_t __iomem *fecp =
224 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200225 int length;
226
227 for (;;) {
228 /* section 16.9.23.2 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200229 if (in_be16(&rtx->rxbd[rxIdx].cbd_sc) & BD_ENET_RX_EMPTY) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200230 length = -1;
231 break; /* nothing received - leave for() loop */
232 }
233
Christophe Leroyba3da732017-07-06 10:33:13 +0200234 length = in_be16(&rtx->rxbd[rxIdx].cbd_datlen);
Christophe Leroy907208c2017-07-06 10:23:22 +0200235
Christophe Leroyba3da732017-07-06 10:33:13 +0200236 if (!(in_be16(&rtx->rxbd[rxIdx].cbd_sc) & 0x003f)) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200237 uchar *rx = net_rx_packets[rxIdx];
238
239 length -= 4;
240
241#if defined(CONFIG_CMD_CDP)
242 if ((rx[0] & 1) != 0 &&
243 memcmp((uchar *)rx, net_bcast_ethaddr, 6) != 0 &&
244 !is_cdp_packet((uchar *)rx))
245 rx = NULL;
246#endif
247 /*
248 * Pass the packet up to the protocol layers.
249 */
250 if (rx != NULL)
251 net_process_received_packet(rx, length);
252 }
253
254 /* Give the buffer back to the FEC. */
Christophe Leroyba3da732017-07-06 10:33:13 +0200255 out_be16(&rtx->rxbd[rxIdx].cbd_datlen, 0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200256
257 /* wrap around buffer index when necessary */
258 if ((rxIdx + 1) >= PKTBUFSRX) {
Christophe Leroyba3da732017-07-06 10:33:13 +0200259 out_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc,
260 BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
Christophe Leroy907208c2017-07-06 10:23:22 +0200261 rxIdx = 0;
262 } else {
Christophe Leroyba3da732017-07-06 10:33:13 +0200263 out_be16(&rtx->rxbd[rxIdx].cbd_sc, BD_ENET_RX_EMPTY);
Christophe Leroy907208c2017-07-06 10:23:22 +0200264 rxIdx++;
265 }
266
Christophe Leroy907208c2017-07-06 10:23:22 +0200267 /* Try to fill Buffer Descriptors */
Christophe Leroyba3da732017-07-06 10:33:13 +0200268 /* Descriptor polling active */
269 out_be32(&fecp->fec_r_des_active, 0x01000000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200270 }
271
272 return length;
273}
274
275/**************************************************************
276 *
277 * FEC Ethernet Initialization Routine
278 *
279 *************************************************************/
280
281#define FEC_ECNTRL_PINMUX 0x00000004
282#define FEC_ECNTRL_ETHER_EN 0x00000002
283#define FEC_ECNTRL_RESET 0x00000001
284
285#define FEC_RCNTRL_BC_REJ 0x00000010
286#define FEC_RCNTRL_PROM 0x00000008
287#define FEC_RCNTRL_MII_MODE 0x00000004
288#define FEC_RCNTRL_DRT 0x00000002
289#define FEC_RCNTRL_LOOP 0x00000001
290
291#define FEC_TCNTRL_FDEN 0x00000004
292#define FEC_TCNTRL_HBC 0x00000002
293#define FEC_TCNTRL_GTS 0x00000001
294
295#define FEC_RESET_DELAY 50
296
297#if defined(CONFIG_RMII)
298
299static inline void fec_10Mbps(struct eth_device *dev)
300{
301 struct ether_fcc_info_s *efis = dev->priv;
302 int fecidx = efis->ether_index;
303 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
Christophe Leroyba3da732017-07-06 10:33:13 +0200304 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy907208c2017-07-06 10:23:22 +0200305
306 if ((unsigned int)fecidx >= 2)
307 hang();
308
Christophe Leroyba3da732017-07-06 10:33:13 +0200309 setbits_be32(&immr->im_cpm.cp_cptr, mask);
Christophe Leroy907208c2017-07-06 10:23:22 +0200310}
311
312static inline void fec_100Mbps(struct eth_device *dev)
313{
314 struct ether_fcc_info_s *efis = dev->priv;
315 int fecidx = efis->ether_index;
316 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
Christophe Leroyba3da732017-07-06 10:33:13 +0200317 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy907208c2017-07-06 10:23:22 +0200318
319 if ((unsigned int)fecidx >= 2)
320 hang();
321
Christophe Leroyba3da732017-07-06 10:33:13 +0200322 clrbits_be32(&immr->im_cpm.cp_cptr, mask);
Christophe Leroy907208c2017-07-06 10:23:22 +0200323}
324
325#endif
326
327static inline void fec_full_duplex(struct eth_device *dev)
328{
329 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200330 fec_t __iomem *fecp =
331 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200332
Christophe Leroyba3da732017-07-06 10:33:13 +0200333 clrbits_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_DRT);
334 setbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */
Christophe Leroy907208c2017-07-06 10:23:22 +0200335}
336
337static inline void fec_half_duplex(struct eth_device *dev)
338{
339 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200340 fec_t __iomem *fecp =
341 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200342
Christophe Leroyba3da732017-07-06 10:33:13 +0200343 setbits_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_DRT);
344 clrbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD disable */
Christophe Leroy907208c2017-07-06 10:23:22 +0200345}
346
347static void fec_pin_init(int fecidx)
348{
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +0900349 struct bd_info *bd = gd->bd;
Christophe Leroyba3da732017-07-06 10:33:13 +0200350 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy907208c2017-07-06 10:23:22 +0200351
352 /*
353 * Set MII speed to 2.5 MHz or slightly below.
354 *
355 * According to the MPC860T (Rev. D) Fast ethernet controller user
356 * manual (6.2.14),
357 * the MII management interface clock must be less than or equal
358 * to 2.5 MHz.
359 * This MDC frequency is equal to system clock / (2 * MII_SPEED).
360 * Then MII_SPEED = system_clock / 2 * 2,5 MHz.
361 *
362 * All MII configuration is done via FEC1 registers:
363 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200364 out_be32(&immr->im_cpm.cp_fec1.fec_mii_speed,
365 ((bd->bi_intfreq + 4999999) / 5000000) << 1);
Christophe Leroy907208c2017-07-06 10:23:22 +0200366
Christophe Leroyb1e41d12017-07-06 10:33:21 +0200367#if defined(CONFIG_MPC885) && defined(WANT_MII)
Christophe Leroy907208c2017-07-06 10:23:22 +0200368 /* use MDC for MII */
Christophe Leroyba3da732017-07-06 10:33:13 +0200369 setbits_be16(&immr->im_ioport.iop_pdpar, 0x0080);
370 clrbits_be16(&immr->im_ioport.iop_pddir, 0x0080);
Christophe Leroy907208c2017-07-06 10:23:22 +0200371#endif
372
373 if (fecidx == 0) {
374#if defined(CONFIG_ETHER_ON_FEC1)
375
Christophe Leroyb1e41d12017-07-06 10:33:21 +0200376#if defined(CONFIG_MPC885) /* MPC87x/88x have got 2 FECs and different pinout */
Christophe Leroy907208c2017-07-06 10:23:22 +0200377
378#if !defined(CONFIG_RMII)
379
Christophe Leroyba3da732017-07-06 10:33:13 +0200380 setbits_be16(&immr->im_ioport.iop_papar, 0xf830);
381 setbits_be16(&immr->im_ioport.iop_padir, 0x0830);
382 clrbits_be16(&immr->im_ioport.iop_padir, 0xf000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200383
Christophe Leroyba3da732017-07-06 10:33:13 +0200384 setbits_be32(&immr->im_cpm.cp_pbpar, 0x00001001);
385 clrbits_be32(&immr->im_cpm.cp_pbdir, 0x00001001);
Christophe Leroy907208c2017-07-06 10:23:22 +0200386
Christophe Leroyba3da732017-07-06 10:33:13 +0200387 setbits_be16(&immr->im_ioport.iop_pcpar, 0x000c);
388 clrbits_be16(&immr->im_ioport.iop_pcdir, 0x000c);
Christophe Leroy907208c2017-07-06 10:23:22 +0200389
Christophe Leroyba3da732017-07-06 10:33:13 +0200390 setbits_be32(&immr->im_cpm.cp_pepar, 0x00000003);
391 setbits_be32(&immr->im_cpm.cp_pedir, 0x00000003);
392 clrbits_be32(&immr->im_cpm.cp_peso, 0x00000003);
Christophe Leroy907208c2017-07-06 10:23:22 +0200393
Christophe Leroyba3da732017-07-06 10:33:13 +0200394 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000100);
Christophe Leroy907208c2017-07-06 10:23:22 +0200395
396#else
397
398#if !defined(CONFIG_FEC1_PHY_NORXERR)
Christophe Leroyba3da732017-07-06 10:33:13 +0200399 setbits_be16(&immr->im_ioport.iop_papar, 0x1000);
400 clrbits_be16(&immr->im_ioport.iop_padir, 0x1000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200401#endif
Christophe Leroyba3da732017-07-06 10:33:13 +0200402 setbits_be16(&immr->im_ioport.iop_papar, 0xe810);
403 setbits_be16(&immr->im_ioport.iop_padir, 0x0810);
404 clrbits_be16(&immr->im_ioport.iop_padir, 0xe000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200405
Christophe Leroyba3da732017-07-06 10:33:13 +0200406 setbits_be32(&immr->im_cpm.cp_pbpar, 0x00000001);
407 clrbits_be32(&immr->im_cpm.cp_pbdir, 0x00000001);
Christophe Leroy907208c2017-07-06 10:23:22 +0200408
Christophe Leroyba3da732017-07-06 10:33:13 +0200409 setbits_be32(&immr->im_cpm.cp_cptr, 0x00000100);
410 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000050);
Christophe Leroy907208c2017-07-06 10:23:22 +0200411
412#endif /* !CONFIG_RMII */
413
414#else
415 /*
416 * Configure all of port D for MII.
417 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200418 out_be16(&immr->im_ioport.iop_pdpar, 0x1fff);
419 out_be16(&immr->im_ioport.iop_pddir, 0x1fff);
Christophe Leroy53193a42017-07-07 10:16:42 +0200420
421#if defined(CONFIG_TARGET_MCR3000)
422 out_be16(&immr->im_ioport.iop_papar, 0xBBFF);
423 out_be16(&immr->im_ioport.iop_padir, 0x04F0);
424 out_be16(&immr->im_ioport.iop_paodr, 0x0000);
425
426 out_be32(&immr->im_cpm.cp_pbpar, 0x000133FF);
427 out_be32(&immr->im_cpm.cp_pbdir, 0x0003BF0F);
428 out_be16(&immr->im_cpm.cp_pbodr, 0x0000);
429
430 out_be16(&immr->im_ioport.iop_pcpar, 0x0400);
431 out_be16(&immr->im_ioport.iop_pcdir, 0x0080);
432 out_be16(&immr->im_ioport.iop_pcso , 0x0D53);
433 out_be16(&immr->im_ioport.iop_pcint, 0x0000);
434
435 out_be16(&immr->im_ioport.iop_pdpar, 0x03FE);
436 out_be16(&immr->im_ioport.iop_pddir, 0x1C09);
437
438 setbits_be32(&immr->im_ioport.utmode, 0x80);
439#endif
Christophe Leroy907208c2017-07-06 10:23:22 +0200440#endif
441
442#endif /* CONFIG_ETHER_ON_FEC1 */
443 } else if (fecidx == 1) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200444#if defined(CONFIG_ETHER_ON_FEC2)
445
Christophe Leroyb1e41d12017-07-06 10:33:21 +0200446#if defined(CONFIG_MPC885) /* MPC87x/88x have got 2 FECs and different pinout */
Christophe Leroy907208c2017-07-06 10:23:22 +0200447
448#if !defined(CONFIG_RMII)
Christophe Leroyba3da732017-07-06 10:33:13 +0200449 setbits_be32(&immr->im_cpm.cp_pepar, 0x0003fffc);
450 setbits_be32(&immr->im_cpm.cp_pedir, 0x0003fffc);
451 clrbits_be32(&immr->im_cpm.cp_peso, 0x000087fc);
452 setbits_be32(&immr->im_cpm.cp_peso, 0x00037800);
Christophe Leroy907208c2017-07-06 10:23:22 +0200453
Christophe Leroyba3da732017-07-06 10:33:13 +0200454 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000080);
Christophe Leroy907208c2017-07-06 10:23:22 +0200455#else
456
457#if !defined(CONFIG_FEC2_PHY_NORXERR)
Christophe Leroyba3da732017-07-06 10:33:13 +0200458 setbits_be32(&immr->im_cpm.cp_pepar, 0x00000010);
459 setbits_be32(&immr->im_cpm.cp_pedir, 0x00000010);
460 clrbits_be32(&immr->im_cpm.cp_peso, 0x00000010);
Christophe Leroy907208c2017-07-06 10:23:22 +0200461#endif
Christophe Leroyba3da732017-07-06 10:33:13 +0200462 setbits_be32(&immr->im_cpm.cp_pepar, 0x00039620);
463 setbits_be32(&immr->im_cpm.cp_pedir, 0x00039620);
464 setbits_be32(&immr->im_cpm.cp_peso, 0x00031000);
465 clrbits_be32(&immr->im_cpm.cp_peso, 0x00008620);
Christophe Leroy907208c2017-07-06 10:23:22 +0200466
Christophe Leroyba3da732017-07-06 10:33:13 +0200467 setbits_be32(&immr->im_cpm.cp_cptr, 0x00000080);
468 clrbits_be32(&immr->im_cpm.cp_cptr, 0x00000028);
Christophe Leroy907208c2017-07-06 10:23:22 +0200469#endif /* CONFIG_RMII */
470
Christophe Leroyb1e41d12017-07-06 10:33:21 +0200471#endif /* CONFIG_MPC885 */
Christophe Leroy907208c2017-07-06 10:23:22 +0200472
473#endif /* CONFIG_ETHER_ON_FEC2 */
Christophe Leroy907208c2017-07-06 10:23:22 +0200474 }
475}
476
Christophe Leroyba3da732017-07-06 10:33:13 +0200477static int fec_reset(fec_t __iomem *fecp)
Christophe Leroy907208c2017-07-06 10:23:22 +0200478{
479 int i;
480
481 /* Whack a reset.
482 * A delay is required between a reset of the FEC block and
483 * initialization of other FEC registers because the reset takes
484 * some time to complete. If you don't delay, subsequent writes
485 * to FEC registers might get killed by the reset routine which is
486 * still in progress.
487 */
488
Christophe Leroyba3da732017-07-06 10:33:13 +0200489 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
490 for (i = 0; (in_be32(&fecp->fec_ecntrl) & FEC_ECNTRL_RESET) &&
491 (i < FEC_RESET_DELAY); ++i)
Christophe Leroy70fd0712017-07-06 10:33:17 +0200492 udelay(1);
Christophe Leroyba3da732017-07-06 10:33:13 +0200493
Christophe Leroy907208c2017-07-06 10:23:22 +0200494 if (i == FEC_RESET_DELAY)
495 return -1;
496
497 return 0;
498}
499
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +0900500static int fec_init(struct eth_device *dev, struct bd_info *bd)
Christophe Leroy907208c2017-07-06 10:23:22 +0200501{
502 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200503 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
504 fec_t __iomem *fecp =
505 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200506 int i;
507
508#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
509 /* the MII interface is connected to FEC1
510 * so for the miiphy_xxx function to work we must
511 * call mii_init since fec_halt messes the thing up
512 */
513 if (efis->ether_index != 0)
514 __mii_init();
515#endif
516
517 if (fec_reset(fecp) < 0)
Christophe Leroy70fd0712017-07-06 10:33:17 +0200518 printf("FEC_RESET_DELAY timeout\n");
Christophe Leroy907208c2017-07-06 10:23:22 +0200519
520 /* We use strictly polling mode only
521 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200522 out_be32(&fecp->fec_imask, 0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200523
524 /* Clear any pending interrupt
525 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200526 out_be32(&fecp->fec_ievent, 0xffc0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200527
528 /* No need to set the IVEC register */
529
530 /* Set station address
531 */
532#define ea dev->enetaddr
Christophe Leroyba3da732017-07-06 10:33:13 +0200533 out_be32(&fecp->fec_addr_low, (ea[0] << 24) | (ea[1] << 16) |
534 (ea[2] << 8) | ea[3]);
535 out_be16(&fecp->fec_addr_high, (ea[4] << 8) | ea[5]);
Christophe Leroy907208c2017-07-06 10:23:22 +0200536#undef ea
537
538#if defined(CONFIG_CMD_CDP)
539 /*
540 * Turn on multicast address hash table
541 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200542 out_be32(&fecp->fec_hash_table_high, 0xffffffff);
543 out_be32(&fecp->fec_hash_table_low, 0xffffffff);
Christophe Leroy907208c2017-07-06 10:23:22 +0200544#else
545 /* Clear multicast address hash table
546 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200547 out_be32(&fecp->fec_hash_table_high, 0);
548 out_be32(&fecp->fec_hash_table_low, 0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200549#endif
550
551 /* Set maximum receive buffer size.
552 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200553 out_be32(&fecp->fec_r_buff_size, PKT_MAXBLR_SIZE);
Christophe Leroy907208c2017-07-06 10:23:22 +0200554
555 /* Set maximum frame length
556 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200557 out_be32(&fecp->fec_r_hash, PKT_MAXBUF_SIZE);
Christophe Leroy907208c2017-07-06 10:23:22 +0200558
559 /*
Christophe Leroy70fd0712017-07-06 10:33:17 +0200560 * Setup Buffers and Buffer Descriptors
Christophe Leroy907208c2017-07-06 10:23:22 +0200561 */
562 rxIdx = 0;
563 txIdx = 0;
564
565 if (!rtx)
Christophe Leroyba3da732017-07-06 10:33:13 +0200566 rtx = (struct common_buf_desc __iomem *)
567 (immr->im_cpm.cp_dpmem + CPM_FEC_BASE);
Christophe Leroy907208c2017-07-06 10:23:22 +0200568 /*
569 * Setup Receiver Buffer Descriptors (13.14.24.18)
570 * Settings:
571 * Empty, Wrap
572 */
573 for (i = 0; i < PKTBUFSRX; i++) {
Christophe Leroyba3da732017-07-06 10:33:13 +0200574 out_be16(&rtx->rxbd[i].cbd_sc, BD_ENET_RX_EMPTY);
575 out_be16(&rtx->rxbd[i].cbd_datlen, 0); /* Reset */
576 out_be32(&rtx->rxbd[i].cbd_bufaddr, (uint)net_rx_packets[i]);
Christophe Leroy907208c2017-07-06 10:23:22 +0200577 }
Christophe Leroyba3da732017-07-06 10:33:13 +0200578 setbits_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc, BD_ENET_RX_WRAP);
Christophe Leroy907208c2017-07-06 10:23:22 +0200579
580 /*
581 * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
582 * Settings:
583 * Last, Tx CRC
584 */
585 for (i = 0; i < TX_BUF_CNT; i++) {
Christophe Leroyba3da732017-07-06 10:33:13 +0200586 out_be16(&rtx->txbd[i].cbd_sc, BD_ENET_TX_LAST | BD_ENET_TX_TC);
587 out_be16(&rtx->txbd[i].cbd_datlen, 0); /* Reset */
588 out_be32(&rtx->txbd[i].cbd_bufaddr, (uint)txbuf);
Christophe Leroy907208c2017-07-06 10:23:22 +0200589 }
Christophe Leroyba3da732017-07-06 10:33:13 +0200590 setbits_be16(&rtx->txbd[TX_BUF_CNT - 1].cbd_sc, BD_ENET_TX_WRAP);
Christophe Leroy907208c2017-07-06 10:23:22 +0200591
592 /* Set receive and transmit descriptor base
593 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200594 out_be32(&fecp->fec_r_des_start, (__force unsigned int)rtx->rxbd);
595 out_be32(&fecp->fec_x_des_start, (__force unsigned int)rtx->txbd);
Christophe Leroy907208c2017-07-06 10:23:22 +0200596
597 /* Enable MII mode
598 */
599 /* Half duplex mode */
Christophe Leroyba3da732017-07-06 10:33:13 +0200600 out_be32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT);
601 out_be32(&fecp->fec_x_cntrl, 0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200602
603 /* Enable big endian and don't care about SDMA FC.
604 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200605 out_be32(&fecp->fec_fun_code, 0x78000000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200606
607 /*
608 * Setup the pin configuration of the FEC
609 */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200610 fec_pin_init(efis->ether_index);
Christophe Leroy907208c2017-07-06 10:23:22 +0200611
612 rxIdx = 0;
613 txIdx = 0;
614
615 /*
616 * Now enable the transmit and receive processing
617 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200618 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
Christophe Leroy907208c2017-07-06 10:23:22 +0200619
620 if (efis->phy_addr == -1) {
621#ifdef CONFIG_SYS_DISCOVER_PHY
622 /*
623 * wait for the PHY to wake up after reset
624 */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200625 efis->actual_phy_addr = mii_discover_phy(dev);
Christophe Leroy907208c2017-07-06 10:23:22 +0200626
627 if (efis->actual_phy_addr == -1) {
Christophe Leroy70fd0712017-07-06 10:33:17 +0200628 printf("Unable to discover phy!\n");
Christophe Leroy907208c2017-07-06 10:23:22 +0200629 return -1;
630 }
631#else
632 efis->actual_phy_addr = -1;
633#endif
634 } else {
635 efis->actual_phy_addr = efis->phy_addr;
636 }
637
638#if defined(CONFIG_MII) && defined(CONFIG_RMII)
639 /*
640 * adapt the RMII speed to the speed of the phy
641 */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200642 if (miiphy_speed(dev->name, efis->actual_phy_addr) == _100BASET)
643 fec_100Mbps(dev);
644 else
645 fec_10Mbps(dev);
Christophe Leroy907208c2017-07-06 10:23:22 +0200646#endif
647
648#if defined(CONFIG_MII)
649 /*
650 * adapt to the half/full speed settings
651 */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200652 if (miiphy_duplex(dev->name, efis->actual_phy_addr) == FULL)
653 fec_full_duplex(dev);
654 else
655 fec_half_duplex(dev);
Christophe Leroy907208c2017-07-06 10:23:22 +0200656#endif
657
658 /* And last, try to fill Rx Buffer Descriptors */
Christophe Leroyba3da732017-07-06 10:33:13 +0200659 /* Descriptor polling active */
660 out_be32(&fecp->fec_r_des_active, 0x01000000);
Christophe Leroy907208c2017-07-06 10:23:22 +0200661
662 efis->initialized = 1;
663
664 return 0;
665}
666
667
Christophe Leroy70fd0712017-07-06 10:33:17 +0200668static void fec_halt(struct eth_device *dev)
Christophe Leroy907208c2017-07-06 10:23:22 +0200669{
670 struct ether_fcc_info_s *efis = dev->priv;
Christophe Leroyba3da732017-07-06 10:33:13 +0200671 fec_t __iomem *fecp =
672 (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset);
Christophe Leroy907208c2017-07-06 10:23:22 +0200673 int i;
674
675 /* avoid halt if initialized; mii gets stuck otherwise */
676 if (!efis->initialized)
677 return;
678
679 /* Whack a reset.
680 * A delay is required between a reset of the FEC block and
681 * initialization of other FEC registers because the reset takes
682 * some time to complete. If you don't delay, subsequent writes
683 * to FEC registers might get killed by the reset routine which is
684 * still in progress.
685 */
686
Christophe Leroyba3da732017-07-06 10:33:13 +0200687 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
688 for (i = 0; (in_be32(&fecp->fec_ecntrl) & FEC_ECNTRL_RESET) &&
689 (i < FEC_RESET_DELAY); ++i)
Christophe Leroy70fd0712017-07-06 10:33:17 +0200690 udelay(1);
Christophe Leroyba3da732017-07-06 10:33:13 +0200691
Christophe Leroy907208c2017-07-06 10:23:22 +0200692 if (i == FEC_RESET_DELAY) {
Christophe Leroy70fd0712017-07-06 10:33:17 +0200693 printf("FEC_RESET_DELAY timeout\n");
Christophe Leroy907208c2017-07-06 10:23:22 +0200694 return;
695 }
696
697 efis->initialized = 0;
698}
699
700#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
701
702/* Make MII read/write commands for the FEC.
703*/
704
705#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \
706 (REG & 0x1f) << 18))
707
708#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \
709 (REG & 0x1f) << 18) | \
710 (VAL & 0xffff))
711
712/* Interrupt events/masks.
713*/
714#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
715#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
716#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */
717#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */
718#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */
719#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */
720#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */
721#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
722#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
723#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
724
725/* send command to phy using mii, wait for result */
726static uint
727mii_send(uint mii_cmd)
728{
729 uint mii_reply;
Christophe Leroyba3da732017-07-06 10:33:13 +0200730 fec_t __iomem *ep;
Christophe Leroy907208c2017-07-06 10:23:22 +0200731 int cnt;
Christophe Leroyba3da732017-07-06 10:33:13 +0200732 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
Christophe Leroy907208c2017-07-06 10:23:22 +0200733
Christophe Leroyba3da732017-07-06 10:33:13 +0200734 ep = &immr->im_cpm.cp_fec;
Christophe Leroy907208c2017-07-06 10:23:22 +0200735
Christophe Leroyba3da732017-07-06 10:33:13 +0200736 out_be32(&ep->fec_mii_data, mii_cmd); /* command to phy */
Christophe Leroy907208c2017-07-06 10:23:22 +0200737
738 /* wait for mii complete */
739 cnt = 0;
Christophe Leroyba3da732017-07-06 10:33:13 +0200740 while (!(in_be32(&ep->fec_ievent) & FEC_ENET_MII)) {
Christophe Leroy907208c2017-07-06 10:23:22 +0200741 if (++cnt > 1000) {
742 printf("mii_send STUCK!\n");
743 break;
744 }
745 }
Christophe Leroyba3da732017-07-06 10:33:13 +0200746 mii_reply = in_be32(&ep->fec_mii_data); /* result from phy */
747 out_be32(&ep->fec_ievent, FEC_ENET_MII); /* clear MII complete */
Christophe Leroy70fd0712017-07-06 10:33:17 +0200748 return mii_reply & 0xffff; /* data read from phy */
Christophe Leroy907208c2017-07-06 10:23:22 +0200749}
750#endif
751
752#if defined(CONFIG_SYS_DISCOVER_PHY)
753static int mii_discover_phy(struct eth_device *dev)
754{
755#define MAX_PHY_PASSES 11
756 uint phyno;
757 int pass;
758 uint phytype;
759 int phyaddr;
760
761 phyaddr = -1; /* didn't find a PHY yet */
762 for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
763 if (pass > 1) {
764 /* PHY may need more time to recover from reset.
765 * The LXT970 needs 50ms typical, no maximum is
766 * specified, so wait 10ms before try again.
767 * With 11 passes this gives it 100ms to wake up.
768 */
769 udelay(10000); /* wait 10ms */
770 }
771 for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {
772 phytype = mii_send(mk_mii_read(phyno, MII_PHYSID2));
773 if (phytype != 0xffff) {
774 phyaddr = phyno;
775 phytype |= mii_send(mk_mii_read(phyno,
776 MII_PHYSID1)) << 16;
777 }
778 }
779 }
Christophe Leroy70fd0712017-07-06 10:33:17 +0200780 if (phyaddr < 0)
Christophe Leroy907208c2017-07-06 10:23:22 +0200781 printf("No PHY device found.\n");
Christophe Leroy70fd0712017-07-06 10:33:17 +0200782
Christophe Leroy907208c2017-07-06 10:23:22 +0200783 return phyaddr;
784}
785#endif /* CONFIG_SYS_DISCOVER_PHY */
786
787#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && !defined(CONFIG_BITBANGMII)
788
789/****************************************************************************
790 * mii_init -- Initialize the MII via FEC 1 for MII command without ethernet
791 * This function is a subset of eth_init
792 ****************************************************************************
793 */
794static void __mii_init(void)
795{
Christophe Leroyba3da732017-07-06 10:33:13 +0200796 immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
797 fec_t __iomem *fecp = &immr->im_cpm.cp_fec;
Christophe Leroy907208c2017-07-06 10:23:22 +0200798
799 if (fec_reset(fecp) < 0)
Christophe Leroy70fd0712017-07-06 10:33:17 +0200800 printf("FEC_RESET_DELAY timeout\n");
Christophe Leroy907208c2017-07-06 10:23:22 +0200801
802 /* We use strictly polling mode only
803 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200804 out_be32(&fecp->fec_imask, 0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200805
806 /* Clear any pending interrupt
807 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200808 out_be32(&fecp->fec_ievent, 0xffc0);
Christophe Leroy907208c2017-07-06 10:23:22 +0200809
810 /* Now enable the transmit and receive processing
811 */
Christophe Leroyba3da732017-07-06 10:33:13 +0200812 out_be32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
Christophe Leroy907208c2017-07-06 10:23:22 +0200813}
814
Christophe Leroy70fd0712017-07-06 10:33:17 +0200815void mii_init(void)
Christophe Leroy907208c2017-07-06 10:23:22 +0200816{
817 int i;
818
819 __mii_init();
820
821 /* Setup the pin configuration of the FEC(s)
822 */
823 for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
824 fec_pin_init(ether_fcc_info[i].ether_index);
825}
826
827/*****************************************************************************
828 * Read and write a MII PHY register, routines used by MII Utilities
829 *
830 * FIXME: These routines are expected to return 0 on success, but mii_send
831 * does _not_ return an error code. Maybe 0xFFFF means error, i.e.
832 * no PHY connected...
833 * For now always return 0.
834 * FIXME: These routines only work after calling eth_init() at least once!
835 * Otherwise they hang in mii_send() !!! Sorry!
836 *****************************************************************************/
837
838int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
839{
840 unsigned short value = 0;
841 short rdreg; /* register working value */
842
843 rdreg = mii_send(mk_mii_read(addr, reg));
844
845 value = rdreg;
846 return value;
847}
848
849int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
850 u16 value)
851{
852 (void)mii_send(mk_mii_write(addr, reg, value));
853
854 return 0;
855}
856#endif