1
2
3
4
5
6
7
8
9
10
11
12#include <common.h>
13#include <net.h>
14#include <malloc.h>
15#include <linux/delay.h>
16#include <linux/errno.h>
17#include <linux/immap_qe.h>
18#include <asm/io.h>
19#include "uccf.h"
20#include "uec.h"
21#include "uec_phy.h"
22#include "miiphy.h"
23#include <fsl_qe.h>
24#include <phy.h>
25
26#if !defined(CONFIG_DM_ETH)
27
28#define ugphy_printk(format, arg...) \
29 printf(format "\n", ## arg)
30
31#define ugphy_dbg(format, arg...) \
32 ugphy_printk(format, ## arg)
33#define ugphy_err(format, arg...) \
34 ugphy_printk(format, ## arg)
35#define ugphy_info(format, arg...) \
36 ugphy_printk(format, ## arg)
37#define ugphy_warn(format, arg...) \
38 ugphy_printk(format, ## arg)
39
40#ifdef UEC_VERBOSE_DEBUG
41#define ugphy_vdbg ugphy_dbg
42#else
43#define ugphy_vdbg(ugeth, fmt, args...) do { } while (0)
44#endif
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77#ifndef CONFIG_FIXED_PHY
78#define CONFIG_FIXED_PHY 0xFFFFFFFF
79#endif
80
81#ifndef CONFIG_SYS_FIXED_PHY_PORTS
82#define CONFIG_SYS_FIXED_PHY_PORTS
83#endif
84
85struct fixed_phy_port {
86 char name[16];
87 unsigned int speed;
88 unsigned int duplex;
89};
90
91static const struct fixed_phy_port fixed_phy_port[] = {
92 CONFIG_SYS_FIXED_PHY_PORTS
93};
94
95
96
97
98
99
100
101
102
103
104
105
106
107#ifndef CONFIG_SYS_BITBANG_PHY_PORTS
108#define CONFIG_SYS_BITBANG_PHY_PORTS
109#endif
110
111#if defined(CONFIG_BITBANGMII)
112static const char * const bitbang_phy_port[] = {
113 CONFIG_SYS_BITBANG_PHY_PORTS
114};
115#endif
116
117static void config_genmii_advert(struct uec_mii_info *mii_info);
118static void genmii_setup_forced(struct uec_mii_info *mii_info);
119static void genmii_restart_aneg(struct uec_mii_info *mii_info);
120static int gbit_config_aneg(struct uec_mii_info *mii_info);
121static int genmii_config_aneg(struct uec_mii_info *mii_info);
122static int genmii_update_link(struct uec_mii_info *mii_info);
123static int genmii_read_status(struct uec_mii_info *mii_info);
124static u16 uec_phy_read(struct uec_mii_info *mii_info, u16 regnum);
125static void uec_phy_write(struct uec_mii_info *mii_info, u16 regnum,
126 u16 val);
127
128
129
130
131
132
133void uec_write_phy_reg(struct eth_device *dev, int mii_id, int regnum,
134 int value)
135{
136 struct uec_priv *ugeth = (struct uec_priv *)dev->priv;
137 uec_mii_t *ug_regs;
138 enum enet_tbi_mii_reg mii_reg = (enum enet_tbi_mii_reg)regnum;
139 u32 tmp_reg;
140
141#if defined(CONFIG_BITBANGMII)
142 u32 i = 0;
143
144 for (i = 0; i < ARRAY_SIZE(bitbang_phy_port); i++) {
145 if (strncmp(dev->name, bitbang_phy_port[i],
146 sizeof(dev->name)) == 0) {
147 (void)bb_miiphy_write(NULL, mii_id, regnum, value);
148 return;
149 }
150 }
151#endif
152
153 ug_regs = ugeth->uec_mii_regs;
154
155
156 out_be32 (&ug_regs->miimcom, 0);
157
158 tmp_reg = ((u32)mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
159 out_be32 (&ug_regs->miimadd, tmp_reg);
160
161
162 out_be32 (&ug_regs->miimcon, (u32)value);
163 sync();
164
165
166 while ((in_be32 (&ug_regs->miimind)) & MIIMIND_BUSY)
167 ;
168}
169
170
171
172
173
174
175int uec_read_phy_reg(struct eth_device *dev, int mii_id, int regnum)
176{
177 struct uec_priv *ugeth = (struct uec_priv *)dev->priv;
178 uec_mii_t *ug_regs;
179 enum enet_tbi_mii_reg mii_reg = (enum enet_tbi_mii_reg)regnum;
180 u32 tmp_reg;
181 u16 value;
182
183#if defined(CONFIG_BITBANGMII)
184 u32 i = 0;
185
186 for (i = 0; i < ARRAY_SIZE(bitbang_phy_port); i++) {
187 if (strncmp(dev->name, bitbang_phy_port[i],
188 sizeof(dev->name)) == 0) {
189 (void)bb_miiphy_read(NULL, mii_id, regnum, &value);
190 return value;
191 }
192 }
193#endif
194
195 ug_regs = ugeth->uec_mii_regs;
196
197
198 tmp_reg = ((u32)mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
199 out_be32 (&ug_regs->miimadd, tmp_reg);
200
201
202 out_be32 (&ug_regs->miimcom, 0);
203 sync();
204
205
206 out_be32 (&ug_regs->miimcom, MIIMCOM_READ_CYCLE);
207
208
209 while ((in_be32 (&ug_regs->miimind)) &
210 (MIIMIND_NOT_VALID | MIIMIND_BUSY))
211 ;
212
213
214 value = (u16)in_be32 (&ug_regs->miimstat);
215 if (value == 0xffff)
216 ugphy_vdbg
217 ("read wrong value : mii_id %d,mii_reg %d, base %08x",
218 mii_id, mii_reg, (u32)&ug_regs->miimcfg);
219
220 return value;
221}
222
223void mii_clear_phy_interrupt(struct uec_mii_info *mii_info)
224{
225 if (mii_info->phyinfo->ack_interrupt)
226 mii_info->phyinfo->ack_interrupt(mii_info);
227}
228
229void mii_configure_phy_interrupt(struct uec_mii_info *mii_info,
230 u32 interrupts)
231{
232 mii_info->interrupts = interrupts;
233 if (mii_info->phyinfo->config_intr)
234 mii_info->phyinfo->config_intr(mii_info);
235}
236
237
238
239
240
241static void config_genmii_advert(struct uec_mii_info *mii_info)
242{
243 u32 advertise;
244 u16 adv;
245
246
247 mii_info->advertising &= mii_info->phyinfo->features;
248 advertise = mii_info->advertising;
249
250
251 adv = uec_phy_read(mii_info, MII_ADVERTISE);
252 adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
253 if (advertise & ADVERTISED_10baseT_Half)
254 adv |= ADVERTISE_10HALF;
255 if (advertise & ADVERTISED_10baseT_Full)
256 adv |= ADVERTISE_10FULL;
257 if (advertise & ADVERTISED_100baseT_Half)
258 adv |= ADVERTISE_100HALF;
259 if (advertise & ADVERTISED_100baseT_Full)
260 adv |= ADVERTISE_100FULL;
261 uec_phy_write(mii_info, MII_ADVERTISE, adv);
262}
263
264static void genmii_setup_forced(struct uec_mii_info *mii_info)
265{
266 u16 ctrl;
267 u32 features = mii_info->phyinfo->features;
268
269 ctrl = uec_phy_read(mii_info, MII_BMCR);
270
271 ctrl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 |
272 BMCR_SPEED1000 | BMCR_ANENABLE);
273 ctrl |= BMCR_RESET;
274
275 switch (mii_info->speed) {
276 case SPEED_1000:
277 if (features & (SUPPORTED_1000baseT_Half
278 | SUPPORTED_1000baseT_Full)) {
279 ctrl |= BMCR_SPEED1000;
280 break;
281 }
282 mii_info->speed = SPEED_100;
283 case SPEED_100:
284 if (features & (SUPPORTED_100baseT_Half
285 | SUPPORTED_100baseT_Full)) {
286 ctrl |= BMCR_SPEED100;
287 break;
288 }
289 mii_info->speed = SPEED_10;
290 case SPEED_10:
291 if (features & (SUPPORTED_10baseT_Half
292 | SUPPORTED_10baseT_Full))
293 break;
294 default:
295 ugphy_err("%s: Bad speed!", mii_info->dev->name);
296 break;
297 }
298
299 uec_phy_write(mii_info, MII_BMCR, ctrl);
300}
301
302
303static void genmii_restart_aneg(struct uec_mii_info *mii_info)
304{
305 u16 ctl;
306
307 ctl = uec_phy_read(mii_info, MII_BMCR);
308 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
309 uec_phy_write(mii_info, MII_BMCR, ctl);
310}
311
312static int gbit_config_aneg(struct uec_mii_info *mii_info)
313{
314 u16 adv;
315 u32 advertise;
316
317 if (mii_info->autoneg) {
318
319 config_genmii_advert(mii_info);
320 advertise = mii_info->advertising;
321
322 adv = uec_phy_read(mii_info, MII_CTRL1000);
323 adv &= ~(ADVERTISE_1000FULL |
324 ADVERTISE_1000HALF);
325 if (advertise & SUPPORTED_1000baseT_Half)
326 adv |= ADVERTISE_1000HALF;
327 if (advertise & SUPPORTED_1000baseT_Full)
328 adv |= ADVERTISE_1000FULL;
329 uec_phy_write(mii_info, MII_CTRL1000, adv);
330
331
332 genmii_restart_aneg(mii_info);
333 } else {
334 genmii_setup_forced(mii_info);
335 }
336
337 return 0;
338}
339
340static int marvell_config_aneg(struct uec_mii_info *mii_info)
341{
342
343
344
345
346
347 uec_phy_write(mii_info, MII_BMCR, BMCR_RESET);
348
349 uec_phy_write(mii_info, 0x1d, 0x1f);
350 uec_phy_write(mii_info, 0x1e, 0x200c);
351 uec_phy_write(mii_info, 0x1d, 0x5);
352 uec_phy_write(mii_info, 0x1e, 0);
353 uec_phy_write(mii_info, 0x1e, 0x100);
354
355 gbit_config_aneg(mii_info);
356
357 return 0;
358}
359
360static int genmii_config_aneg(struct uec_mii_info *mii_info)
361{
362 if (mii_info->autoneg) {
363
364
365
366
367 if (!genmii_read_status(mii_info) && mii_info->link)
368 if (mii_info->duplex == DUPLEX_FULL &&
369 mii_info->speed == SPEED_100)
370 if (mii_info->advertising &
371 ADVERTISED_100baseT_Full)
372 return 0;
373
374 config_genmii_advert(mii_info);
375 genmii_restart_aneg(mii_info);
376 } else {
377 genmii_setup_forced(mii_info);
378 }
379
380 return 0;
381}
382
383static int genmii_update_link(struct uec_mii_info *mii_info)
384{
385 u16 status;
386
387
388 uec_phy_read(mii_info, MII_BMSR);
389
390
391
392
393
394 status = uec_phy_read(mii_info, MII_BMSR);
395 if ((status & BMSR_LSTATUS) && (status & BMSR_ANEGCAPABLE) &&
396 !(status & BMSR_ANEGCOMPLETE)) {
397 int i = 0;
398
399 while (!(status & BMSR_ANEGCOMPLETE)) {
400
401
402
403 if (i > UGETH_AN_TIMEOUT) {
404 mii_info->link = 0;
405 return 0;
406 }
407
408 i++;
409 udelay(1000);
410 status = uec_phy_read(mii_info, MII_BMSR);
411 }
412 mii_info->link = 1;
413 } else {
414 if (status & BMSR_LSTATUS)
415 mii_info->link = 1;
416 else
417 mii_info->link = 0;
418 }
419
420 return 0;
421}
422
423static int genmii_read_status(struct uec_mii_info *mii_info)
424{
425 u16 status;
426 int err;
427
428
429 err = genmii_update_link(mii_info);
430 if (err)
431 return err;
432
433 if (mii_info->autoneg) {
434 status = uec_phy_read(mii_info, MII_STAT1000);
435
436 if (status & (LPA_1000FULL | LPA_1000HALF)) {
437 mii_info->speed = SPEED_1000;
438 if (status & LPA_1000FULL)
439 mii_info->duplex = DUPLEX_FULL;
440 else
441 mii_info->duplex = DUPLEX_HALF;
442 } else {
443 status = uec_phy_read(mii_info, MII_LPA);
444
445 if (status & (LPA_10FULL | LPA_100FULL))
446 mii_info->duplex = DUPLEX_FULL;
447 else
448 mii_info->duplex = DUPLEX_HALF;
449 if (status & (LPA_100FULL | LPA_100HALF))
450 mii_info->speed = SPEED_100;
451 else
452 mii_info->speed = SPEED_10;
453 }
454 mii_info->pause = 0;
455 }
456
457
458
459
460 return 0;
461}
462
463static int bcm_init(struct uec_mii_info *mii_info)
464{
465 struct eth_device *edev = mii_info->dev;
466 struct uec_priv *uec = edev->priv;
467
468 gbit_config_aneg(mii_info);
469
470 if (uec->uec_info->enet_interface_type ==
471 PHY_INTERFACE_MODE_RGMII_RXID &&
472 uec->uec_info->speed == SPEED_1000) {
473 u16 val;
474 int cnt = 50;
475
476
477 do
478 val = uec_phy_read(mii_info, MII_BMSR);
479 while (--cnt && !(val & BMSR_ANEGCOMPLETE));
480
481
482 uec_phy_write(mii_info, 0x18, 0x7 | (7 << 12));
483
484 val = uec_phy_read(mii_info, 0x18);
485
486 val |= (1 << 8);
487 val |= (7 | (7 << 12));
488
489 val |= (1 << 15);
490 uec_phy_write(mii_info, 0x18, val);
491 }
492
493 return 0;
494}
495
496static int uec_marvell_init(struct uec_mii_info *mii_info)
497{
498 struct eth_device *edev = mii_info->dev;
499 struct uec_priv *uec = edev->priv;
500 phy_interface_t iface = uec->uec_info->enet_interface_type;
501 int speed = uec->uec_info->speed;
502
503 if (speed == SPEED_1000 &&
504 (iface == PHY_INTERFACE_MODE_RGMII_ID ||
505 iface == PHY_INTERFACE_MODE_RGMII_RXID ||
506 iface == PHY_INTERFACE_MODE_RGMII_TXID)) {
507 int temp;
508
509 temp = uec_phy_read(mii_info, MII_M1111_PHY_EXT_CR);
510 if (iface == PHY_INTERFACE_MODE_RGMII_ID) {
511 temp |= MII_M1111_RX_DELAY | MII_M1111_TX_DELAY;
512 } else if (iface == PHY_INTERFACE_MODE_RGMII_RXID) {
513 temp &= ~MII_M1111_TX_DELAY;
514 temp |= MII_M1111_RX_DELAY;
515 } else if (iface == PHY_INTERFACE_MODE_RGMII_TXID) {
516 temp &= ~MII_M1111_RX_DELAY;
517 temp |= MII_M1111_TX_DELAY;
518 }
519 uec_phy_write(mii_info, MII_M1111_PHY_EXT_CR, temp);
520
521 temp = uec_phy_read(mii_info, MII_M1111_PHY_EXT_SR);
522 temp &= ~MII_M1111_HWCFG_MODE_MASK;
523 temp |= MII_M1111_HWCFG_MODE_RGMII;
524 uec_phy_write(mii_info, MII_M1111_PHY_EXT_SR, temp);
525
526 uec_phy_write(mii_info, MII_BMCR, BMCR_RESET);
527 }
528
529 return 0;
530}
531
532static int marvell_read_status(struct uec_mii_info *mii_info)
533{
534 u16 status;
535 int err;
536
537
538 err = genmii_update_link(mii_info);
539 if (err)
540 return err;
541
542
543
544
545
546
547 if (mii_info->autoneg && mii_info->link) {
548 int speed;
549
550 status = uec_phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
551
552
553 if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
554 mii_info->duplex = DUPLEX_FULL;
555 else
556 mii_info->duplex = DUPLEX_HALF;
557
558
559 speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
560 switch (speed) {
561 case MII_M1011_PHY_SPEC_STATUS_1000:
562 mii_info->speed = SPEED_1000;
563 break;
564 case MII_M1011_PHY_SPEC_STATUS_100:
565 mii_info->speed = SPEED_100;
566 break;
567 default:
568 mii_info->speed = SPEED_10;
569 break;
570 }
571 mii_info->pause = 0;
572 }
573
574 return 0;
575}
576
577static int marvell_ack_interrupt(struct uec_mii_info *mii_info)
578{
579
580 uec_phy_read(mii_info, MII_M1011_IEVENT);
581
582 return 0;
583}
584
585static int marvell_config_intr(struct uec_mii_info *mii_info)
586{
587 if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
588 uec_phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
589 else
590 uec_phy_write(mii_info, MII_M1011_IMASK,
591 MII_M1011_IMASK_CLEAR);
592
593 return 0;
594}
595
596static int dm9161_init(struct uec_mii_info *mii_info)
597{
598
599 uec_phy_write(mii_info, MII_BMCR, uec_phy_read(mii_info, MII_BMCR) |
600 BMCR_RESET);
601
602 uec_phy_write(mii_info, MII_BMCR, uec_phy_read(mii_info, MII_BMCR) &
603 ~BMCR_ISOLATE);
604
605 uec_phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
606
607 config_genmii_advert(mii_info);
608
609 genmii_config_aneg(mii_info);
610
611 return 0;
612}
613
614static int dm9161_config_aneg(struct uec_mii_info *mii_info)
615{
616 return 0;
617}
618
619static int dm9161_read_status(struct uec_mii_info *mii_info)
620{
621 u16 status;
622 int err;
623
624
625 err = genmii_update_link(mii_info);
626 if (err)
627 return err;
628
629
630
631
632 if (mii_info->autoneg && mii_info->link) {
633 status = uec_phy_read(mii_info, MII_DM9161_SCSR);
634 if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
635 mii_info->speed = SPEED_100;
636 else
637 mii_info->speed = SPEED_10;
638
639 if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
640 mii_info->duplex = DUPLEX_FULL;
641 else
642 mii_info->duplex = DUPLEX_HALF;
643 }
644
645 return 0;
646}
647
648static int dm9161_ack_interrupt(struct uec_mii_info *mii_info)
649{
650
651 uec_phy_read(mii_info, MII_DM9161_INTR);
652
653 return 0;
654}
655
656static int dm9161_config_intr(struct uec_mii_info *mii_info)
657{
658 if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
659 uec_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
660 else
661 uec_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
662
663 return 0;
664}
665
666static void dm9161_close(struct uec_mii_info *mii_info)
667{
668}
669
670static int fixed_phy_aneg(struct uec_mii_info *mii_info)
671{
672 mii_info->autoneg = 0;
673 return 0;
674}
675
676static int fixed_phy_read_status(struct uec_mii_info *mii_info)
677{
678 int i = 0;
679
680 for (i = 0; i < ARRAY_SIZE(fixed_phy_port); i++) {
681 if (strncmp(mii_info->dev->name, fixed_phy_port[i].name,
682 strlen(mii_info->dev->name)) == 0) {
683 mii_info->speed = fixed_phy_port[i].speed;
684 mii_info->duplex = fixed_phy_port[i].duplex;
685 mii_info->link = 1;
686 mii_info->pause = 0;
687 break;
688 }
689 }
690 return 0;
691}
692
693static int smsc_config_aneg(struct uec_mii_info *mii_info)
694{
695 return 0;
696}
697
698static int smsc_read_status(struct uec_mii_info *mii_info)
699{
700 u16 status;
701 int err;
702
703
704 err = genmii_update_link(mii_info);
705 if (err)
706 return err;
707
708
709
710
711
712
713 if (mii_info->autoneg && mii_info->link) {
714 int val;
715
716 status = uec_phy_read(mii_info, 0x1f);
717 val = (status & 0x1c) >> 2;
718
719 switch (val) {
720 case 1:
721 mii_info->duplex = DUPLEX_HALF;
722 mii_info->speed = SPEED_10;
723 break;
724 case 5:
725 mii_info->duplex = DUPLEX_FULL;
726 mii_info->speed = SPEED_10;
727 break;
728 case 2:
729 mii_info->duplex = DUPLEX_HALF;
730 mii_info->speed = SPEED_100;
731 break;
732 case 6:
733 mii_info->duplex = DUPLEX_FULL;
734 mii_info->speed = SPEED_100;
735 break;
736 }
737 mii_info->pause = 0;
738 }
739
740 return 0;
741}
742
743static struct phy_info phy_info_dm9161 = {
744 .phy_id = 0x0181b880,
745 .phy_id_mask = 0x0ffffff0,
746 .name = "Davicom DM9161E",
747 .init = dm9161_init,
748 .config_aneg = dm9161_config_aneg,
749 .read_status = dm9161_read_status,
750 .close = dm9161_close,
751};
752
753static struct phy_info phy_info_dm9161a = {
754 .phy_id = 0x0181b8a0,
755 .phy_id_mask = 0x0ffffff0,
756 .name = "Davicom DM9161A",
757 .features = MII_BASIC_FEATURES,
758 .init = dm9161_init,
759 .config_aneg = dm9161_config_aneg,
760 .read_status = dm9161_read_status,
761 .ack_interrupt = dm9161_ack_interrupt,
762 .config_intr = dm9161_config_intr,
763 .close = dm9161_close,
764};
765
766static struct phy_info phy_info_marvell = {
767 .phy_id = 0x01410c00,
768 .phy_id_mask = 0xffffff00,
769 .name = "Marvell 88E11x1",
770 .features = MII_GBIT_FEATURES,
771 .init = &uec_marvell_init,
772 .config_aneg = &marvell_config_aneg,
773 .read_status = &marvell_read_status,
774 .ack_interrupt = &marvell_ack_interrupt,
775 .config_intr = &marvell_config_intr,
776};
777
778static struct phy_info phy_info_bcm5481 = {
779 .phy_id = 0x0143bca0,
780 .phy_id_mask = 0xffffff0,
781 .name = "Broadcom 5481",
782 .features = MII_GBIT_FEATURES,
783 .read_status = genmii_read_status,
784 .init = bcm_init,
785};
786
787static struct phy_info phy_info_fixedphy = {
788 .phy_id = CONFIG_FIXED_PHY,
789 .phy_id_mask = CONFIG_FIXED_PHY,
790 .name = "Fixed PHY",
791 .config_aneg = fixed_phy_aneg,
792 .read_status = fixed_phy_read_status,
793};
794
795static struct phy_info phy_info_smsclan8700 = {
796 .phy_id = 0x0007c0c0,
797 .phy_id_mask = 0xfffffff0,
798 .name = "SMSC LAN8700",
799 .features = MII_BASIC_FEATURES,
800 .config_aneg = smsc_config_aneg,
801 .read_status = smsc_read_status,
802};
803
804static struct phy_info phy_info_genmii = {
805 .phy_id = 0x00000000,
806 .phy_id_mask = 0x00000000,
807 .name = "Generic MII",
808 .features = MII_BASIC_FEATURES,
809 .config_aneg = genmii_config_aneg,
810 .read_status = genmii_read_status,
811};
812
813static struct phy_info *phy_info[] = {
814 &phy_info_dm9161,
815 &phy_info_dm9161a,
816 &phy_info_marvell,
817 &phy_info_bcm5481,
818 &phy_info_smsclan8700,
819 &phy_info_fixedphy,
820 &phy_info_genmii,
821 NULL
822};
823
824static u16 uec_phy_read(struct uec_mii_info *mii_info, u16 regnum)
825{
826 return mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
827}
828
829static void uec_phy_write(struct uec_mii_info *mii_info, u16 regnum, u16 val)
830{
831 mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val);
832}
833
834
835
836
837struct phy_info *uec_get_phy_info(struct uec_mii_info *mii_info)
838{
839 u16 phy_reg;
840 u32 phy_ID;
841 int i;
842 struct phy_info *info = NULL;
843
844
845 phy_reg = uec_phy_read(mii_info, MII_PHYSID1);
846 phy_ID = (phy_reg & 0xffff) << 16;
847
848
849 phy_reg = uec_phy_read(mii_info, MII_PHYSID2);
850 phy_ID |= (phy_reg & 0xffff);
851
852
853
854 for (i = 0; phy_info[i]; i++)
855 if (phy_info[i]->phy_id ==
856 (phy_ID & phy_info[i]->phy_id_mask)) {
857 info = phy_info[i];
858 break;
859 }
860
861
862 if (!info) {
863 ugphy_info("UEC: PHY id %x is not supported!", phy_ID);
864 return NULL;
865 }
866 ugphy_info("UEC: PHY is %s (%x)", info->name, phy_ID);
867
868 return info;
869}
870
871void marvell_phy_interface_mode(struct eth_device *dev, phy_interface_t type,
872 int speed)
873{
874 struct uec_priv *uec = (struct uec_priv *)dev->priv;
875 struct uec_mii_info *mii_info;
876 u16 status;
877
878 if (!uec->mii_info) {
879 printf("%s: the PHY not initialized\n", __func__);
880 return;
881 }
882 mii_info = uec->mii_info;
883
884 if (type == PHY_INTERFACE_MODE_RGMII) {
885 if (speed == SPEED_100) {
886 uec_phy_write(mii_info, 0x00, 0x9140);
887 uec_phy_write(mii_info, 0x1d, 0x001f);
888 uec_phy_write(mii_info, 0x1e, 0x200c);
889 uec_phy_write(mii_info, 0x1d, 0x0005);
890 uec_phy_write(mii_info, 0x1e, 0x0000);
891 uec_phy_write(mii_info, 0x1e, 0x0100);
892 uec_phy_write(mii_info, 0x09, 0x0e00);
893 uec_phy_write(mii_info, 0x04, 0x01e1);
894 uec_phy_write(mii_info, 0x00, 0x9140);
895 uec_phy_write(mii_info, 0x00, 0x1000);
896 mdelay(100);
897 uec_phy_write(mii_info, 0x00, 0x2900);
898 uec_phy_write(mii_info, 0x14, 0x0cd2);
899 uec_phy_write(mii_info, 0x00, 0xa100);
900 uec_phy_write(mii_info, 0x09, 0x0000);
901 uec_phy_write(mii_info, 0x1b, 0x800b);
902 uec_phy_write(mii_info, 0x04, 0x05e1);
903 uec_phy_write(mii_info, 0x00, 0xa100);
904 uec_phy_write(mii_info, 0x00, 0x2100);
905 mdelay(1000);
906 } else if (speed == SPEED_10) {
907 uec_phy_write(mii_info, 0x14, 0x8e40);
908 uec_phy_write(mii_info, 0x1b, 0x800b);
909 uec_phy_write(mii_info, 0x14, 0x0c82);
910 uec_phy_write(mii_info, 0x00, 0x8100);
911 mdelay(1000);
912 }
913 }
914
915
916 if (mii_info->autoneg) {
917 status = uec_phy_read(mii_info, MII_BMCR);
918 uec_phy_write(mii_info, MII_BMCR, status | BMCR_ANENABLE);
919 }
920
921}
922
923void change_phy_interface_mode(struct eth_device *dev,
924 phy_interface_t type, int speed)
925{
926#ifdef CONFIG_PHY_MODE_NEED_CHANGE
927 marvell_phy_interface_mode(dev, type, speed);
928#endif
929}
930#endif
931