blob: 81bda0697f04ef81e01f3744d1967a7a661c492f [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenkc6097192002-11-03 00:24:07 +00006 */
7
8#include <common.h>
9#include <malloc.h>
10#include <commproc.h>
11#include <net.h>
12#include <command.h>
13
Wolfgang Denkd87080b2006-03-31 18:32:53 +020014DECLARE_GLOBAL_DATA_PTR;
15
wdenkc6097192002-11-03 00:24:07 +000016#undef ET_DEBUG
17
Jon Loeliger44312832007-07-09 19:06:00 -050018#if defined(CONFIG_CMD_NET) && \
wdenka6ab4bf2004-04-15 21:31:56 +000019 (defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FEC1) || defined(CONFIG_ETHER_ON_FEC2))
20
21/* compatibility test, if only FEC_ENET defined assume ETHER on FEC1 */
22#if defined(FEC_ENET) && !defined(CONFIG_ETHER_ON_FEC1) && !defined(CONFIG_ETHER_ON_FEC2)
23#define CONFIG_ETHER_ON_FEC1 1
24#endif
25
26/* define WANT_MII when MII support is required */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020027#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_FEC1_PHY) || defined(CONFIG_FEC2_PHY)
wdenka6ab4bf2004-04-15 21:31:56 +000028#define WANT_MII
29#else
30#undef WANT_MII
31#endif
32
33#if defined(WANT_MII)
34#include <miiphy.h>
Marian Balakowicz63ff0042005-10-28 22:30:33 +020035
Jon Loeliger44312832007-07-09 19:06:00 -050036#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
Marian Balakowicz63ff0042005-10-28 22:30:33 +020037#error "CONFIG_MII has to be defined!"
38#endif
39
wdenka6ab4bf2004-04-15 21:31:56 +000040#endif
41
42#if defined(CONFIG_RMII) && !defined(WANT_MII)
43#error RMII support is unusable without a working PHY.
44#endif
wdenkc6097192002-11-03 00:24:07 +000045
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020046#ifdef CONFIG_SYS_DISCOVER_PHY
wdenka6ab4bf2004-04-15 21:31:56 +000047static int mii_discover_phy(struct eth_device *dev);
wdenkc6097192002-11-03 00:24:07 +000048#endif
49
Joe Hershberger5a49f172016-08-08 11:28:38 -050050int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
51int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
52 u16 value);
Marian Balakowicz63ff0042005-10-28 22:30:33 +020053
wdenka6ab4bf2004-04-15 21:31:56 +000054static struct ether_fcc_info_s
55{
56 int ether_index;
57 int fecp_offset;
wdenka6ab4bf2004-04-15 21:31:56 +000058 int phy_addr;
59 int actual_phy_addr;
wdenkc26e4542004-04-18 10:13:26 +000060 int initialized;
wdenka6ab4bf2004-04-15 21:31:56 +000061}
62 ether_fcc_info[] = {
63#if defined(CONFIG_ETHER_ON_FEC1)
64 {
65 0,
66 offsetof(immap_t, im_cpm.cp_fec1),
wdenka6ab4bf2004-04-15 21:31:56 +000067#if defined(CONFIG_FEC1_PHY)
68 CONFIG_FEC1_PHY,
69#else
70 -1, /* discover */
71#endif
72 -1,
wdenkc26e4542004-04-18 10:13:26 +000073 0,
wdenka6ab4bf2004-04-15 21:31:56 +000074
75 },
76#endif
77#if defined(CONFIG_ETHER_ON_FEC2)
78 {
79 1,
80 offsetof(immap_t, im_cpm.cp_fec2),
wdenka6ab4bf2004-04-15 21:31:56 +000081#if defined(CONFIG_FEC2_PHY)
82 CONFIG_FEC2_PHY,
83#else
84 -1,
85#endif
86 -1,
wdenkc26e4542004-04-18 10:13:26 +000087 0,
wdenka6ab4bf2004-04-15 21:31:56 +000088 },
89#endif
90};
91
wdenkc6097192002-11-03 00:24:07 +000092/* Ethernet Transmit and Receive Buffers */
93#define DBUF_LENGTH 1520
94
95#define TX_BUF_CNT 2
96
97#define TOUT_LOOP 100
98
99#define PKT_MAXBUF_SIZE 1518
100#define PKT_MINBUF_SIZE 64
101#define PKT_MAXBLR_SIZE 1520
102
wdenka6ab4bf2004-04-15 21:31:56 +0000103#ifdef __GNUC__
104static char txbuf[DBUF_LENGTH] __attribute__ ((aligned(8)));
105#else
106#error txbuf must be aligned.
107#endif
wdenkc6097192002-11-03 00:24:07 +0000108
109static uint rxIdx; /* index of the current RX buffer */
110static uint txIdx; /* index of the current TX buffer */
111
112/*
113 * FEC Ethernet Tx and Rx buffer descriptors allocated at the
114 * immr->udata_bd address on Dual-Port RAM
115 * Provide for Double Buffering
116 */
117
118typedef volatile struct CommonBufferDescriptor {
119 cbd_t rxbd[PKTBUFSRX]; /* Rx BD */
120 cbd_t txbd[TX_BUF_CNT]; /* Tx BD */
121} RTXBD;
122
123static RTXBD *rtx = NULL;
124
Wolfgang Denk1b10d072012-05-20 21:14:54 +0000125static int fec_send(struct eth_device *dev, void *packet, int length);
wdenkc6097192002-11-03 00:24:07 +0000126static int fec_recv(struct eth_device* dev);
127static int fec_init(struct eth_device* dev, bd_t * bd);
128static void fec_halt(struct eth_device* dev);
Wolfgang Denk08e99e12008-01-13 02:19:13 +0100129#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
Guennadi Liakhovetskid197ffd2007-11-29 21:15:56 +0100130static void __mii_init(void);
Wolfgang Denk08e99e12008-01-13 02:19:13 +0100131#endif
wdenkc6097192002-11-03 00:24:07 +0000132
133int fec_initialize(bd_t *bis)
134{
135 struct eth_device* dev;
wdenka6ab4bf2004-04-15 21:31:56 +0000136 struct ether_fcc_info_s *efis;
137 int i;
wdenkc6097192002-11-03 00:24:07 +0000138
Robert P. J. Dayb7707b02016-05-23 06:49:21 -0400139 for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++) {
wdenkc6097192002-11-03 00:24:07 +0000140
wdenka6ab4bf2004-04-15 21:31:56 +0000141 dev = malloc(sizeof(*dev));
142 if (dev == NULL)
143 hang();
wdenkc6097192002-11-03 00:24:07 +0000144
wdenka6ab4bf2004-04-15 21:31:56 +0000145 memset(dev, 0, sizeof(*dev));
wdenkc6097192002-11-03 00:24:07 +0000146
wdenka6ab4bf2004-04-15 21:31:56 +0000147 /* for FEC1 make sure that the name of the interface is the same
148 as the old one for compatibility reasons */
149 if (i == 0) {
Ben Whitten192bc692015-12-30 13:05:58 +0000150 strcpy(dev->name, "FEC");
wdenka6ab4bf2004-04-15 21:31:56 +0000151 } else {
Heiko Schocher48690d82010-07-20 17:45:02 +0200152 sprintf (dev->name, "FEC%d",
wdenka6ab4bf2004-04-15 21:31:56 +0000153 ether_fcc_info[i].ether_index + 1);
154 }
155
156 efis = &ether_fcc_info[i];
157
158 /*
159 * reset actual phy addr
160 */
161 efis->actual_phy_addr = -1;
162
163 dev->priv = efis;
164 dev->init = fec_init;
165 dev->halt = fec_halt;
166 dev->send = fec_send;
167 dev->recv = fec_recv;
168
169 eth_register(dev);
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200170
Jon Loeliger44312832007-07-09 19:06:00 -0500171#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
Joe Hershberger5a49f172016-08-08 11:28:38 -0500172 int retval;
173 struct mii_dev *mdiodev = mdio_alloc();
174 if (!mdiodev)
175 return -ENOMEM;
176 strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
177 mdiodev->read = fec8xx_miiphy_read;
178 mdiodev->write = fec8xx_miiphy_write;
179
180 retval = mdio_register(mdiodev);
181 if (retval < 0)
182 return retval;
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200183#endif
wdenka6ab4bf2004-04-15 21:31:56 +0000184 }
wdenkc6097192002-11-03 00:24:07 +0000185 return 1;
186}
187
Wolfgang Denk1b10d072012-05-20 21:14:54 +0000188static int fec_send(struct eth_device *dev, void *packet, int length)
wdenkc6097192002-11-03 00:24:07 +0000189{
190 int j, rc;
wdenka6ab4bf2004-04-15 21:31:56 +0000191 struct ether_fcc_info_s *efis = dev->priv;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200192 volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
wdenkc6097192002-11-03 00:24:07 +0000193
194 /* section 16.9.23.3
195 * Wait for ready
196 */
197 j = 0;
198 while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
199 udelay(1);
200 j++;
201 }
202 if (j>=TOUT_LOOP) {
203 printf("TX not ready\n");
204 }
205
206 rtx->txbd[txIdx].cbd_bufaddr = (uint)packet;
207 rtx->txbd[txIdx].cbd_datlen = length;
208 rtx->txbd[txIdx].cbd_sc |= BD_ENET_TX_READY | BD_ENET_TX_LAST;
209 __asm__ ("eieio");
210
211 /* Activate transmit Buffer Descriptor polling */
212 fecp->fec_x_des_active = 0x01000000; /* Descriptor polling active */
213
214 j = 0;
215 while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
wdenkc6097192002-11-03 00:24:07 +0000216 udelay(1);
wdenkc6097192002-11-03 00:24:07 +0000217 j++;
218 }
219 if (j>=TOUT_LOOP) {
220 printf("TX timeout\n");
221 }
222#ifdef ET_DEBUG
223 printf("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n",
224 __FILE__,__LINE__,__FUNCTION__,j,rtx->txbd[txIdx].cbd_sc,
225 (rtx->txbd[txIdx].cbd_sc & 0x003C)>>2);
226#endif
227 /* return only status bits */;
228 rc = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS);
229
230 txIdx = (txIdx + 1) % TX_BUF_CNT;
231
232 return rc;
233}
234
wdenka6ab4bf2004-04-15 21:31:56 +0000235static int fec_recv (struct eth_device *dev)
wdenkc6097192002-11-03 00:24:07 +0000236{
wdenka6ab4bf2004-04-15 21:31:56 +0000237 struct ether_fcc_info_s *efis = dev->priv;
238 volatile fec_t *fecp =
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200239 (volatile fec_t *) (CONFIG_SYS_IMMR + efis->fecp_offset);
wdenkc6097192002-11-03 00:24:07 +0000240 int length;
wdenkc6097192002-11-03 00:24:07 +0000241
wdenka6ab4bf2004-04-15 21:31:56 +0000242 for (;;) {
243 /* section 16.9.23.2 */
244 if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
245 length = -1;
246 break; /* nothing received - leave for() loop */
247 }
wdenkc6097192002-11-03 00:24:07 +0000248
wdenka6ab4bf2004-04-15 21:31:56 +0000249 length = rtx->rxbd[rxIdx].cbd_datlen;
wdenkc6097192002-11-03 00:24:07 +0000250
wdenka6ab4bf2004-04-15 21:31:56 +0000251 if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) {
wdenkc6097192002-11-03 00:24:07 +0000252#ifdef ET_DEBUG
wdenka6ab4bf2004-04-15 21:31:56 +0000253 printf ("%s[%d] err: %x\n",
254 __FUNCTION__, __LINE__,
255 rtx->rxbd[rxIdx].cbd_sc);
wdenkc6097192002-11-03 00:24:07 +0000256#endif
wdenka6ab4bf2004-04-15 21:31:56 +0000257 } else {
Joe Hershberger1fd92db2015-04-08 01:41:06 -0500258 uchar *rx = net_rx_packets[rxIdx];
wdenka6ab4bf2004-04-15 21:31:56 +0000259
260 length -= 4;
261
Jon Loeliger44312832007-07-09 19:06:00 -0500262#if defined(CONFIG_CMD_CDP)
Joe Hershberger0adb5b72015-04-08 01:41:04 -0500263 if ((rx[0] & 1) != 0 &&
264 memcmp((uchar *)rx, net_bcast_ethaddr, 6) != 0 &&
265 !is_cdp_packet((uchar *)rx))
wdenka6ab4bf2004-04-15 21:31:56 +0000266 rx = NULL;
267#endif
268 /*
269 * Pass the packet up to the protocol layers.
270 */
271 if (rx != NULL)
Joe Hershberger1fd92db2015-04-08 01:41:06 -0500272 net_process_received_packet(rx, length);
wdenka6ab4bf2004-04-15 21:31:56 +0000273 }
274
275 /* Give the buffer back to the FEC. */
276 rtx->rxbd[rxIdx].cbd_datlen = 0;
277
278 /* wrap around buffer index when necessary */
279 if ((rxIdx + 1) >= PKTBUFSRX) {
280 rtx->rxbd[PKTBUFSRX - 1].cbd_sc =
281 (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
282 rxIdx = 0;
283 } else {
284 rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
285 rxIdx++;
286 }
287
288 __asm__ ("eieio");
289
290 /* Try to fill Buffer Descriptors */
291 fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */
wdenkc6097192002-11-03 00:24:07 +0000292 }
293
wdenka6ab4bf2004-04-15 21:31:56 +0000294 return length;
wdenkc6097192002-11-03 00:24:07 +0000295}
296
297/**************************************************************
298 *
299 * FEC Ethernet Initialization Routine
300 *
301 *************************************************************/
302
303#define FEC_ECNTRL_PINMUX 0x00000004
304#define FEC_ECNTRL_ETHER_EN 0x00000002
305#define FEC_ECNTRL_RESET 0x00000001
306
307#define FEC_RCNTRL_BC_REJ 0x00000010
308#define FEC_RCNTRL_PROM 0x00000008
309#define FEC_RCNTRL_MII_MODE 0x00000004
310#define FEC_RCNTRL_DRT 0x00000002
311#define FEC_RCNTRL_LOOP 0x00000001
312
313#define FEC_TCNTRL_FDEN 0x00000004
314#define FEC_TCNTRL_HBC 0x00000002
315#define FEC_TCNTRL_GTS 0x00000001
316
317#define FEC_RESET_DELAY 50
318
wdenka6ab4bf2004-04-15 21:31:56 +0000319#if defined(CONFIG_RMII)
320
321static inline void fec_10Mbps(struct eth_device *dev)
wdenkc6097192002-11-03 00:24:07 +0000322{
wdenka6ab4bf2004-04-15 21:31:56 +0000323 struct ether_fcc_info_s *efis = dev->priv;
324 int fecidx = efis->ether_index;
325 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
wdenkc6097192002-11-03 00:24:07 +0000326
wdenka6ab4bf2004-04-15 21:31:56 +0000327 if ((unsigned int)fecidx >= 2)
328 hang();
329
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200330 ((volatile immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_cptr |= mask;
wdenka6ab4bf2004-04-15 21:31:56 +0000331}
332
333static inline void fec_100Mbps(struct eth_device *dev)
334{
335 struct ether_fcc_info_s *efis = dev->priv;
336 int fecidx = efis->ether_index;
337 uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
338
339 if ((unsigned int)fecidx >= 2)
340 hang();
341
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200342 ((volatile immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_cptr &= ~mask;
wdenka6ab4bf2004-04-15 21:31:56 +0000343}
344
345#endif
346
347static inline void fec_full_duplex(struct eth_device *dev)
348{
349 struct ether_fcc_info_s *efis = dev->priv;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200350 volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
wdenka6ab4bf2004-04-15 21:31:56 +0000351
352 fecp->fec_r_cntrl &= ~FEC_RCNTRL_DRT;
353 fecp->fec_x_cntrl |= FEC_TCNTRL_FDEN; /* FD enable */
354}
355
356static inline void fec_half_duplex(struct eth_device *dev)
357{
358 struct ether_fcc_info_s *efis = dev->priv;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200359 volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
wdenka6ab4bf2004-04-15 21:31:56 +0000360
361 fecp->fec_r_cntrl |= FEC_RCNTRL_DRT;
362 fecp->fec_x_cntrl &= ~FEC_TCNTRL_FDEN; /* FD disable */
363}
364
365static void fec_pin_init(int fecidx)
366{
wdenka6ab4bf2004-04-15 21:31:56 +0000367 bd_t *bd = gd->bd;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200368 volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
wdenka6ab4bf2004-04-15 21:31:56 +0000369
370 /*
371 * Set MII speed to 2.5 MHz or slightly below.
Wolfgang Denk90357f12011-11-04 15:55:21 +0000372 *
373 * According to the MPC860T (Rev. D) Fast ethernet controller user
374 * manual (6.2.14),
375 * the MII management interface clock must be less than or equal
376 * to 2.5 MHz.
377 * This MDC frequency is equal to system clock / (2 * MII_SPEED).
378 * Then MII_SPEED = system_clock / 2 * 2,5 MHz.
Markus Klotzbuecherd6cc73e2006-07-12 09:08:36 +0200379 *
380 * All MII configuration is done via FEC1 registers:
wdenka6ab4bf2004-04-15 21:31:56 +0000381 */
Markus Klotzbuecherd6cc73e2006-07-12 09:08:36 +0200382 immr->im_cpm.cp_fec1.fec_mii_speed = ((bd->bi_intfreq + 4999999) / 5000000) << 1;
wdenka6ab4bf2004-04-15 21:31:56 +0000383
wdenk11142572004-06-06 21:35:06 +0000384#if defined(CONFIG_MPC885_FAMILY) && defined(WANT_MII)
wdenka6ab4bf2004-04-15 21:31:56 +0000385 /* use MDC for MII */
386 immr->im_ioport.iop_pdpar |= 0x0080;
387 immr->im_ioport.iop_pddir &= ~0x0080;
388#endif
389
390 if (fecidx == 0) {
391#if defined(CONFIG_ETHER_ON_FEC1)
392
wdenk11142572004-06-06 21:35:06 +0000393#if defined(CONFIG_MPC885_FAMILY) /* MPC87x/88x have got 2 FECs and different pinout */
wdenka6ab4bf2004-04-15 21:31:56 +0000394
395#if !defined(CONFIG_RMII)
396
397 immr->im_ioport.iop_papar |= 0xf830;
398 immr->im_ioport.iop_padir |= 0x0830;
399 immr->im_ioport.iop_padir &= ~0xf000;
400
401 immr->im_cpm.cp_pbpar |= 0x00001001;
402 immr->im_cpm.cp_pbdir &= ~0x00001001;
403
404 immr->im_ioport.iop_pcpar |= 0x000c;
405 immr->im_ioport.iop_pcdir &= ~0x000c;
406
407 immr->im_cpm.cp_pepar |= 0x00000003;
408 immr->im_cpm.cp_pedir |= 0x00000003;
409 immr->im_cpm.cp_peso &= ~0x00000003;
410
411 immr->im_cpm.cp_cptr &= ~0x00000100;
412
413#else
414
415#if !defined(CONFIG_FEC1_PHY_NORXERR)
416 immr->im_ioport.iop_papar |= 0x1000;
417 immr->im_ioport.iop_padir &= ~0x1000;
418#endif
419 immr->im_ioport.iop_papar |= 0xe810;
420 immr->im_ioport.iop_padir |= 0x0810;
421 immr->im_ioport.iop_padir &= ~0xe000;
422
423 immr->im_cpm.cp_pbpar |= 0x00000001;
424 immr->im_cpm.cp_pbdir &= ~0x00000001;
425
426 immr->im_cpm.cp_cptr |= 0x00000100;
427 immr->im_cpm.cp_cptr &= ~0x00000050;
428
429#endif /* !CONFIG_RMII */
430
Marek Vasut4af5f0f2014-10-22 21:34:46 +0200431#else
wdenka6ab4bf2004-04-15 21:31:56 +0000432 /*
433 * Configure all of port D for MII.
434 */
435 immr->im_ioport.iop_pdpar = 0x1fff;
436
437 /*
438 * Bits moved from Rev. D onward
439 */
440 if ((get_immr(0) & 0xffff) < 0x0501)
441 immr->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */
442 else
443 immr->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */
wdenka6ab4bf2004-04-15 21:31:56 +0000444#endif
445
wdenka6ab4bf2004-04-15 21:31:56 +0000446#endif /* CONFIG_ETHER_ON_FEC1 */
447 } else if (fecidx == 1) {
448
449#if defined(CONFIG_ETHER_ON_FEC2)
450
wdenk11142572004-06-06 21:35:06 +0000451#if defined(CONFIG_MPC885_FAMILY) /* MPC87x/88x have got 2 FECs and different pinout */
wdenka6ab4bf2004-04-15 21:31:56 +0000452
453#if !defined(CONFIG_RMII)
wdenka6ab4bf2004-04-15 21:31:56 +0000454 immr->im_cpm.cp_pepar |= 0x0003fffc;
455 immr->im_cpm.cp_pedir |= 0x0003fffc;
456 immr->im_cpm.cp_peso &= ~0x000087fc;
457 immr->im_cpm.cp_peso |= 0x00037800;
458
459 immr->im_cpm.cp_cptr &= ~0x00000080;
460#else
461
462#if !defined(CONFIG_FEC2_PHY_NORXERR)
463 immr->im_cpm.cp_pepar |= 0x00000010;
464 immr->im_cpm.cp_pedir |= 0x00000010;
465 immr->im_cpm.cp_peso &= ~0x00000010;
466#endif
467 immr->im_cpm.cp_pepar |= 0x00039620;
468 immr->im_cpm.cp_pedir |= 0x00039620;
469 immr->im_cpm.cp_peso |= 0x00031000;
470 immr->im_cpm.cp_peso &= ~0x00008620;
471
472 immr->im_cpm.cp_cptr |= 0x00000080;
473 immr->im_cpm.cp_cptr &= ~0x00000028;
474#endif /* CONFIG_RMII */
475
wdenk11142572004-06-06 21:35:06 +0000476#endif /* CONFIG_MPC885_FAMILY */
wdenka6ab4bf2004-04-15 21:31:56 +0000477
478#endif /* CONFIG_ETHER_ON_FEC2 */
479
wdenkc6097192002-11-03 00:24:07 +0000480 }
wdenka6ab4bf2004-04-15 21:31:56 +0000481}
482
Guennadi Liakhovetskid197ffd2007-11-29 21:15:56 +0100483static int fec_reset(volatile fec_t *fecp)
484{
485 int i;
486
487 /* Whack a reset.
488 * A delay is required between a reset of the FEC block and
489 * initialization of other FEC registers because the reset takes
490 * some time to complete. If you don't delay, subsequent writes
491 * to FEC registers might get killed by the reset routine which is
492 * still in progress.
493 */
494
495 fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
496 for (i = 0;
497 (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
498 ++i) {
499 udelay (1);
500 }
501 if (i == FEC_RESET_DELAY)
502 return -1;
503
504 return 0;
505}
506
wdenka6ab4bf2004-04-15 21:31:56 +0000507static int fec_init (struct eth_device *dev, bd_t * bd)
508{
509 struct ether_fcc_info_s *efis = dev->priv;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200510 volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
wdenka6ab4bf2004-04-15 21:31:56 +0000511 volatile fec_t *fecp =
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200512 (volatile fec_t *) (CONFIG_SYS_IMMR + efis->fecp_offset);
wdenka6ab4bf2004-04-15 21:31:56 +0000513 int i;
514
Guennadi Liakhovetskid197ffd2007-11-29 21:15:56 +0100515#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
516 /* the MII interface is connected to FEC1
517 * so for the miiphy_xxx function to work we must
518 * call mii_init since fec_halt messes the thing up
wdenkc6097192002-11-03 00:24:07 +0000519 */
Guennadi Liakhovetskid197ffd2007-11-29 21:15:56 +0100520 if (efis->ether_index != 0)
521 __mii_init();
522#endif
523
524 if (fec_reset(fecp) < 0)
wdenkc6097192002-11-03 00:24:07 +0000525 printf ("FEC_RESET_DELAY timeout\n");
wdenkc6097192002-11-03 00:24:07 +0000526
527 /* We use strictly polling mode only
528 */
529 fecp->fec_imask = 0;
530
531 /* Clear any pending interrupt
532 */
533 fecp->fec_ievent = 0xffc0;
534
535 /* No need to set the IVEC register */
536
537 /* Set station address
538 */
Guennadi Liakhovetskid197ffd2007-11-29 21:15:56 +0100539#define ea dev->enetaddr
wdenka6ab4bf2004-04-15 21:31:56 +0000540 fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
541 fecp->fec_addr_high = (ea[4] << 8) | (ea[5]);
wdenkc6097192002-11-03 00:24:07 +0000542#undef ea
543
Jon Loeliger44312832007-07-09 19:06:00 -0500544#if defined(CONFIG_CMD_CDP)
wdenka6ab4bf2004-04-15 21:31:56 +0000545 /*
546 * Turn on multicast address hash table
547 */
548 fecp->fec_hash_table_high = 0xffffffff;
549 fecp->fec_hash_table_low = 0xffffffff;
550#else
wdenkc6097192002-11-03 00:24:07 +0000551 /* Clear multicast address hash table
552 */
553 fecp->fec_hash_table_high = 0;
wdenka6ab4bf2004-04-15 21:31:56 +0000554 fecp->fec_hash_table_low = 0;
555#endif
wdenkc6097192002-11-03 00:24:07 +0000556
557 /* Set maximum receive buffer size.
558 */
559 fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
560
561 /* Set maximum frame length
562 */
563 fecp->fec_r_hash = PKT_MAXBUF_SIZE;
564
565 /*
566 * Setup Buffers and Buffer Desriptors
567 */
568 rxIdx = 0;
569 txIdx = 0;
570
571 if (!rtx) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200572#ifdef CONFIG_SYS_ALLOC_DPRAM
wdenka6ab4bf2004-04-15 21:31:56 +0000573 rtx = (RTXBD *) (immr->im_cpm.cp_dpmem +
574 dpram_alloc_align (sizeof (RTXBD), 8));
wdenkc6097192002-11-03 00:24:07 +0000575#else
wdenka6ab4bf2004-04-15 21:31:56 +0000576 rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_FEC_BASE);
wdenkc6097192002-11-03 00:24:07 +0000577#endif
578 }
579 /*
580 * Setup Receiver Buffer Descriptors (13.14.24.18)
581 * Settings:
582 * Empty, Wrap
583 */
584 for (i = 0; i < PKTBUFSRX; i++) {
wdenka6ab4bf2004-04-15 21:31:56 +0000585 rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
586 rtx->rxbd[i].cbd_datlen = 0; /* Reset */
Joe Hershberger1fd92db2015-04-08 01:41:06 -0500587 rtx->rxbd[i].cbd_bufaddr = (uint) net_rx_packets[i];
wdenkc6097192002-11-03 00:24:07 +0000588 }
589 rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
590
591 /*
592 * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
593 * Settings:
594 * Last, Tx CRC
595 */
596 for (i = 0; i < TX_BUF_CNT; i++) {
wdenka6ab4bf2004-04-15 21:31:56 +0000597 rtx->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC;
598 rtx->txbd[i].cbd_datlen = 0; /* Reset */
wdenkc6097192002-11-03 00:24:07 +0000599 rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
600 }
601 rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
602
603 /* Set receive and transmit descriptor base
604 */
605 fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]);
606 fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]);
607
608 /* Enable MII mode
609 */
wdenka6ab4bf2004-04-15 21:31:56 +0000610#if 0 /* Full duplex mode */
wdenkc6097192002-11-03 00:24:07 +0000611 fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE;
612 fecp->fec_x_cntrl = FEC_TCNTRL_FDEN;
wdenka6ab4bf2004-04-15 21:31:56 +0000613#else /* Half duplex mode */
wdenkc6097192002-11-03 00:24:07 +0000614 fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT;
615 fecp->fec_x_cntrl = 0;
616#endif
617
618 /* Enable big endian and don't care about SDMA FC.
619 */
620 fecp->fec_fun_code = 0x78000000;
621
wdenka6ab4bf2004-04-15 21:31:56 +0000622 /*
623 * Setup the pin configuration of the FEC
wdenkc6097192002-11-03 00:24:07 +0000624 */
wdenka6ab4bf2004-04-15 21:31:56 +0000625 fec_pin_init (efis->ether_index);
wdenkc6097192002-11-03 00:24:07 +0000626
627 rxIdx = 0;
628 txIdx = 0;
629
wdenka6ab4bf2004-04-15 21:31:56 +0000630 /*
631 * Now enable the transmit and receive processing
wdenkc6097192002-11-03 00:24:07 +0000632 */
633 fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
634
wdenka6ab4bf2004-04-15 21:31:56 +0000635 if (efis->phy_addr == -1) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200636#ifdef CONFIG_SYS_DISCOVER_PHY
wdenka6ab4bf2004-04-15 21:31:56 +0000637 /*
638 * wait for the PHY to wake up after reset
639 */
640 efis->actual_phy_addr = mii_discover_phy (dev);
wdenk62b4ac92004-05-05 08:31:53 +0000641
wdenka6ab4bf2004-04-15 21:31:56 +0000642 if (efis->actual_phy_addr == -1) {
643 printf ("Unable to discover phy!\n");
Ben Warren422b1a02008-01-09 18:15:53 -0500644 return -1;
wdenka6ab4bf2004-04-15 21:31:56 +0000645 }
wdenk62b4ac92004-05-05 08:31:53 +0000646#else
647 efis->actual_phy_addr = -1;
648#endif
wdenka6ab4bf2004-04-15 21:31:56 +0000649 } else {
650 efis->actual_phy_addr = efis->phy_addr;
651 }
Guennadi Liakhovetskid197ffd2007-11-29 21:15:56 +0100652
wdenka6ab4bf2004-04-15 21:31:56 +0000653#if defined(CONFIG_MII) && defined(CONFIG_RMII)
654 /*
655 * adapt the RMII speed to the speed of the phy
wdenkc6097192002-11-03 00:24:07 +0000656 */
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200657 if (miiphy_speed (dev->name, efis->actual_phy_addr) == _100BASET) {
wdenka6ab4bf2004-04-15 21:31:56 +0000658 fec_100Mbps (dev);
659 } else {
660 fec_10Mbps (dev);
661 }
662#endif
663
664#if defined(CONFIG_MII)
665 /*
666 * adapt to the half/full speed settings
667 */
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200668 if (miiphy_duplex (dev->name, efis->actual_phy_addr) == FULL) {
wdenka6ab4bf2004-04-15 21:31:56 +0000669 fec_full_duplex (dev);
670 } else {
671 fec_half_duplex (dev);
672 }
wdenkc6097192002-11-03 00:24:07 +0000673#endif
674
675 /* And last, try to fill Rx Buffer Descriptors */
wdenka6ab4bf2004-04-15 21:31:56 +0000676 fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */
wdenkc6097192002-11-03 00:24:07 +0000677
wdenkc26e4542004-04-18 10:13:26 +0000678 efis->initialized = 1;
679
Ben Warren422b1a02008-01-09 18:15:53 -0500680 return 0;
wdenkc6097192002-11-03 00:24:07 +0000681}
682
683
wdenkc6097192002-11-03 00:24:07 +0000684static void fec_halt(struct eth_device* dev)
685{
wdenkc26e4542004-04-18 10:13:26 +0000686 struct ether_fcc_info_s *efis = dev->priv;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200687 volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
wdenkc26e4542004-04-18 10:13:26 +0000688 int i;
wdenkc6097192002-11-03 00:24:07 +0000689
wdenkc26e4542004-04-18 10:13:26 +0000690 /* avoid halt if initialized; mii gets stuck otherwise */
691 if (!efis->initialized)
692 return;
693
694 /* Whack a reset.
695 * A delay is required between a reset of the FEC block and
696 * initialization of other FEC registers because the reset takes
697 * some time to complete. If you don't delay, subsequent writes
698 * to FEC registers might get killed by the reset routine which is
699 * still in progress.
700 */
701
702 fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
703 for (i = 0;
704 (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
705 ++i) {
706 udelay (1);
707 }
708 if (i == FEC_RESET_DELAY) {
709 printf ("FEC_RESET_DELAY timeout\n");
710 return;
711 }
712
713 efis->initialized = 0;
wdenkc6097192002-11-03 00:24:07 +0000714}
wdenkc6097192002-11-03 00:24:07 +0000715
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200716#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
wdenkc6097192002-11-03 00:24:07 +0000717
718/* Make MII read/write commands for the FEC.
719*/
720
721#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \
722 (REG & 0x1f) << 18))
723
724#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \
725 (REG & 0x1f) << 18) | \
726 (VAL & 0xffff))
727
728/* Interrupt events/masks.
729*/
730#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
731#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
732#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */
733#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */
734#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */
735#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */
736#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */
737#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
738#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
739#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
740
741/* PHY identification
742 */
743#define PHY_ID_LXT970 0x78100000 /* LXT970 */
744#define PHY_ID_LXT971 0x001378e0 /* LXT971 and 972 */
745#define PHY_ID_82555 0x02a80150 /* Intel 82555 */
746#define PHY_ID_QS6612 0x01814400 /* QS6612 */
747#define PHY_ID_AMD79C784 0x00225610 /* AMD 79C784 */
748#define PHY_ID_LSI80225 0x0016f870 /* LSI 80225 */
749#define PHY_ID_LSI80225B 0x0016f880 /* LSI 80225/B */
wdenk180d3f72004-01-04 16:28:35 +0000750#define PHY_ID_DM9161 0x0181B880 /* Davicom DM9161 */
Markus Klotzbuecherb02d0172006-07-12 08:48:24 +0200751#define PHY_ID_KSM8995M 0x00221450 /* MICREL KS8995MA */
wdenkc6097192002-11-03 00:24:07 +0000752
753/* send command to phy using mii, wait for result */
754static uint
755mii_send(uint mii_cmd)
756{
757 uint mii_reply;
758 volatile fec_t *ep;
wdenkc26e4542004-04-18 10:13:26 +0000759 int cnt;
wdenkc6097192002-11-03 00:24:07 +0000760
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200761 ep = &(((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_fec);
wdenkc6097192002-11-03 00:24:07 +0000762
763 ep->fec_mii_data = mii_cmd; /* command to phy */
764
765 /* wait for mii complete */
wdenkc26e4542004-04-18 10:13:26 +0000766 cnt = 0;
767 while (!(ep->fec_ievent & FEC_ENET_MII)) {
768 if (++cnt > 1000) {
769 printf("mii_send STUCK!\n");
770 break;
771 }
772 }
wdenkc6097192002-11-03 00:24:07 +0000773 mii_reply = ep->fec_mii_data; /* result from phy */
774 ep->fec_ievent = FEC_ENET_MII; /* clear MII complete */
775#if 0
776 printf("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n",
777 __FILE__,__LINE__,__FUNCTION__,mii_cmd,mii_reply);
778#endif
779 return (mii_reply & 0xffff); /* data read from phy */
780}
Jon Loeliger44312832007-07-09 19:06:00 -0500781#endif
wdenkc6097192002-11-03 00:24:07 +0000782
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200783#if defined(CONFIG_SYS_DISCOVER_PHY)
wdenka6ab4bf2004-04-15 21:31:56 +0000784static int mii_discover_phy(struct eth_device *dev)
wdenkc6097192002-11-03 00:24:07 +0000785{
786#define MAX_PHY_PASSES 11
787 uint phyno;
788 int pass;
wdenka6ab4bf2004-04-15 21:31:56 +0000789 uint phytype;
790 int phyaddr;
wdenkc6097192002-11-03 00:24:07 +0000791
792 phyaddr = -1; /* didn't find a PHY yet */
793 for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
794 if (pass > 1) {
795 /* PHY may need more time to recover from reset.
796 * The LXT970 needs 50ms typical, no maximum is
797 * specified, so wait 10ms before try again.
798 * With 11 passes this gives it 100ms to wake up.
799 */
800 udelay(10000); /* wait 10ms */
801 }
802 for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {
Mike Frysinger8ef583a2010-12-23 15:40:12 -0500803 phytype = mii_send(mk_mii_read(phyno, MII_PHYSID2));
wdenkc6097192002-11-03 00:24:07 +0000804#ifdef ET_DEBUG
805 printf("PHY type 0x%x pass %d type ", phytype, pass);
806#endif
807 if (phytype != 0xffff) {
808 phyaddr = phyno;
wdenkc6097192002-11-03 00:24:07 +0000809 phytype |= mii_send(mk_mii_read(phyno,
Mike Frysinger8ef583a2010-12-23 15:40:12 -0500810 MII_PHYSID1)) << 16;
wdenkc6097192002-11-03 00:24:07 +0000811
812#ifdef ET_DEBUG
813 printf("PHY @ 0x%x pass %d type ",phyno,pass);
814 switch (phytype & 0xfffffff0) {
815 case PHY_ID_LXT970:
816 printf("LXT970\n");
817 break;
818 case PHY_ID_LXT971:
819 printf("LXT971\n");
820 break;
821 case PHY_ID_82555:
822 printf("82555\n");
823 break;
824 case PHY_ID_QS6612:
825 printf("QS6612\n");
826 break;
827 case PHY_ID_AMD79C784:
828 printf("AMD79C784\n");
829 break;
830 case PHY_ID_LSI80225B:
831 printf("LSI L80225/B\n");
832 break;
wdenk180d3f72004-01-04 16:28:35 +0000833 case PHY_ID_DM9161:
834 printf("Davicom DM9161\n");
835 break;
Markus Klotzbuecherb02d0172006-07-12 08:48:24 +0200836 case PHY_ID_KSM8995M:
837 printf("MICREL KS8995M\n");
838 break;
wdenkc6097192002-11-03 00:24:07 +0000839 default:
840 printf("0x%08x\n", phytype);
841 break;
842 }
843#endif
844 }
845 }
846 }
847 if (phyaddr < 0) {
848 printf("No PHY device found.\n");
849 }
wdenka6ab4bf2004-04-15 21:31:56 +0000850 return phyaddr;
wdenkc6097192002-11-03 00:24:07 +0000851}
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200852#endif /* CONFIG_SYS_DISCOVER_PHY */
wdenkc6097192002-11-03 00:24:07 +0000853
Jon Loeliger44312832007-07-09 19:06:00 -0500854#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && !defined(CONFIG_BITBANGMII)
wdenkc6097192002-11-03 00:24:07 +0000855
wdenkc6097192002-11-03 00:24:07 +0000856/****************************************************************************
Guennadi Liakhovetskid197ffd2007-11-29 21:15:56 +0100857 * mii_init -- Initialize the MII via FEC 1 for MII command without ethernet
wdenkc6097192002-11-03 00:24:07 +0000858 * This function is a subset of eth_init
859 ****************************************************************************
860 */
Guennadi Liakhovetskid197ffd2007-11-29 21:15:56 +0100861static void __mii_init(void)
wdenkc6097192002-11-03 00:24:07 +0000862{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200863 volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
wdenkc6097192002-11-03 00:24:07 +0000864 volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
wdenkc6097192002-11-03 00:24:07 +0000865
Guennadi Liakhovetskid197ffd2007-11-29 21:15:56 +0100866 if (fec_reset(fecp) < 0)
wdenkc6097192002-11-03 00:24:07 +0000867 printf ("FEC_RESET_DELAY timeout\n");
wdenkc6097192002-11-03 00:24:07 +0000868
869 /* We use strictly polling mode only
870 */
871 fecp->fec_imask = 0;
872
873 /* Clear any pending interrupt
874 */
875 fecp->fec_ievent = 0xffc0;
876
wdenkc6097192002-11-03 00:24:07 +0000877 /* Now enable the transmit and receive processing
878 */
879 fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
Guennadi Liakhovetskid197ffd2007-11-29 21:15:56 +0100880}
881
882void mii_init (void)
883{
884 int i;
885
886 __mii_init();
887
888 /* Setup the pin configuration of the FEC(s)
889 */
Robert P. J. Dayb7707b02016-05-23 06:49:21 -0400890 for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
Guennadi Liakhovetskid197ffd2007-11-29 21:15:56 +0100891 fec_pin_init(ether_fcc_info[i].ether_index);
wdenkc6097192002-11-03 00:24:07 +0000892}
wdenka6ab4bf2004-04-15 21:31:56 +0000893
wdenkc6097192002-11-03 00:24:07 +0000894/*****************************************************************************
895 * Read and write a MII PHY register, routines used by MII Utilities
896 *
897 * FIXME: These routines are expected to return 0 on success, but mii_send
898 * does _not_ return an error code. Maybe 0xFFFF means error, i.e.
899 * no PHY connected...
900 * For now always return 0.
901 * FIXME: These routines only work after calling eth_init() at least once!
902 * Otherwise they hang in mii_send() !!! Sorry!
903 *****************************************************************************/
904
Joe Hershberger5a49f172016-08-08 11:28:38 -0500905int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
wdenkc6097192002-11-03 00:24:07 +0000906{
Joe Hershberger5a49f172016-08-08 11:28:38 -0500907 unsigned short value = 0;
wdenkc6097192002-11-03 00:24:07 +0000908 short rdreg; /* register working value */
909
910#ifdef MII_DEBUG
911 printf ("miiphy_read(0x%x) @ 0x%x = ", reg, addr);
912#endif
913 rdreg = mii_send(mk_mii_read(addr, reg));
914
Joe Hershberger5a49f172016-08-08 11:28:38 -0500915 value = rdreg;
wdenkc6097192002-11-03 00:24:07 +0000916#ifdef MII_DEBUG
Joe Hershberger5a49f172016-08-08 11:28:38 -0500917 printf ("0x%04x\n", value);
wdenkc6097192002-11-03 00:24:07 +0000918#endif
Joe Hershberger5a49f172016-08-08 11:28:38 -0500919 return value;
wdenkc6097192002-11-03 00:24:07 +0000920}
921
Joe Hershberger5a49f172016-08-08 11:28:38 -0500922int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
923 u16 value)
wdenkc6097192002-11-03 00:24:07 +0000924{
wdenkc6097192002-11-03 00:24:07 +0000925#ifdef MII_DEBUG
926 printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
927#endif
Wolfgang Denk90357f12011-11-04 15:55:21 +0000928 (void)mii_send(mk_mii_write(addr, reg, value));
wdenkc6097192002-11-03 00:24:07 +0000929
930#ifdef MII_DEBUG
931 printf ("0x%04x\n", value);
932#endif
wdenkc6097192002-11-03 00:24:07 +0000933 return 0;
934}
Jon Loeliger44312832007-07-09 19:06:00 -0500935#endif
wdenkc6097192002-11-03 00:24:07 +0000936
Jon Loeliger068b60a2007-07-10 10:27:39 -0500937#endif