aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ibm_newemac
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ibm_newemac')
-rw-r--r--drivers/net/ibm_newemac/Kconfig12
-rw-r--r--drivers/net/ibm_newemac/core.c42
-rw-r--r--drivers/net/ibm_newemac/core.h6
-rw-r--r--drivers/net/ibm_newemac/mal.c60
-rw-r--r--drivers/net/ibm_newemac/mal.h34
-rw-r--r--drivers/net/ibm_newemac/phy.c84
-rw-r--r--drivers/net/ibm_newemac/phy.h2
7 files changed, 226 insertions, 14 deletions
diff --git a/drivers/net/ibm_newemac/Kconfig b/drivers/net/ibm_newemac/Kconfig
index bcec7320895c..78a1628c9892 100644
--- a/drivers/net/ibm_newemac/Kconfig
+++ b/drivers/net/ibm_newemac/Kconfig
@@ -62,3 +62,15 @@ config IBM_NEW_EMAC_TAH
62config IBM_NEW_EMAC_EMAC4 62config IBM_NEW_EMAC_EMAC4
63 bool 63 bool
64 default n 64 default n
65
66config IBM_NEW_EMAC_NO_FLOW_CTRL
67 bool
68 default n
69
70config IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
71 bool
72 default n
73
74config IBM_NEW_EMAC_MAL_COMMON_ERR
75 bool
76 default n
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 58dfd32ccca8..efcf21c9f5c7 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -202,13 +202,15 @@ static inline int emac_phy_supports_gige(int phy_mode)
202{ 202{
203 return phy_mode == PHY_MODE_GMII || 203 return phy_mode == PHY_MODE_GMII ||
204 phy_mode == PHY_MODE_RGMII || 204 phy_mode == PHY_MODE_RGMII ||
205 phy_mode == PHY_MODE_SGMII ||
205 phy_mode == PHY_MODE_TBI || 206 phy_mode == PHY_MODE_TBI ||
206 phy_mode == PHY_MODE_RTBI; 207 phy_mode == PHY_MODE_RTBI;
207} 208}
208 209
209static inline int emac_phy_gpcs(int phy_mode) 210static inline int emac_phy_gpcs(int phy_mode)
210{ 211{
211 return phy_mode == PHY_MODE_TBI || 212 return phy_mode == PHY_MODE_SGMII ||
213 phy_mode == PHY_MODE_TBI ||
212 phy_mode == PHY_MODE_RTBI; 214 phy_mode == PHY_MODE_RTBI;
213} 215}
214 216
@@ -562,8 +564,9 @@ static int emac_configure(struct emac_instance *dev)
562 switch (dev->phy.speed) { 564 switch (dev->phy.speed) {
563 case SPEED_1000: 565 case SPEED_1000:
564 if (emac_phy_gpcs(dev->phy.mode)) { 566 if (emac_phy_gpcs(dev->phy.mode)) {
565 mr1 |= EMAC_MR1_MF_1000GPCS | 567 mr1 |= EMAC_MR1_MF_1000GPCS | EMAC_MR1_MF_IPPA(
566 EMAC_MR1_MF_IPPA(dev->phy.address); 568 (dev->phy.gpcs_address != 0xffffffff) ?
569 dev->phy.gpcs_address : dev->phy.address);
567 570
568 /* Put some arbitrary OUI, Manuf & Rev IDs so we can 571 /* Put some arbitrary OUI, Manuf & Rev IDs so we can
569 * identify this GPCS PHY later. 572 * identify this GPCS PHY later.
@@ -675,8 +678,12 @@ static int emac_configure(struct emac_instance *dev)
675 out_be32(&p->iser, r); 678 out_be32(&p->iser, r);
676 679
677 /* We need to take GPCS PHY out of isolate mode after EMAC reset */ 680 /* We need to take GPCS PHY out of isolate mode after EMAC reset */
678 if (emac_phy_gpcs(dev->phy.mode)) 681 if (emac_phy_gpcs(dev->phy.mode)) {
679 emac_mii_reset_phy(&dev->phy); 682 if (dev->phy.gpcs_address != 0xffffffff)
683 emac_mii_reset_gpcs(&dev->phy);
684 else
685 emac_mii_reset_phy(&dev->phy);
686 }
680 687
681 return 0; 688 return 0;
682} 689}
@@ -881,7 +888,9 @@ static int emac_mdio_read(struct net_device *ndev, int id, int reg)
881 struct emac_instance *dev = netdev_priv(ndev); 888 struct emac_instance *dev = netdev_priv(ndev);
882 int res; 889 int res;
883 890
884 res = __emac_mdio_read(dev->mdio_instance ? dev->mdio_instance : dev, 891 res = __emac_mdio_read((dev->mdio_instance &&
892 dev->phy.gpcs_address != id) ?
893 dev->mdio_instance : dev,
885 (u8) id, (u8) reg); 894 (u8) id, (u8) reg);
886 return res; 895 return res;
887} 896}
@@ -890,7 +899,9 @@ static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
890{ 899{
891 struct emac_instance *dev = netdev_priv(ndev); 900 struct emac_instance *dev = netdev_priv(ndev);
892 901
893 __emac_mdio_write(dev->mdio_instance ? dev->mdio_instance : dev, 902 __emac_mdio_write((dev->mdio_instance &&
903 dev->phy.gpcs_address != id) ?
904 dev->mdio_instance : dev,
894 (u8) id, (u8) reg, (u16) val); 905 (u8) id, (u8) reg, (u16) val);
895} 906}
896 907
@@ -2382,7 +2393,11 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
2382 * XXX I probably should move these settings to the dev tree 2393 * XXX I probably should move these settings to the dev tree
2383 */ 2394 */
2384 dev->phy.address = -1; 2395 dev->phy.address = -1;
2385 dev->phy.features = SUPPORTED_100baseT_Full | SUPPORTED_MII; 2396 dev->phy.features = SUPPORTED_MII;
2397 if (emac_phy_supports_gige(dev->phy_mode))
2398 dev->phy.features |= SUPPORTED_1000baseT_Full;
2399 else
2400 dev->phy.features |= SUPPORTED_100baseT_Full;
2386 dev->phy.pause = 1; 2401 dev->phy.pause = 1;
2387 2402
2388 return 0; 2403 return 0;
@@ -2421,7 +2436,9 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
2421 * Note that the busy_phy_map is currently global 2436 * Note that the busy_phy_map is currently global
2422 * while it should probably be per-ASIC... 2437 * while it should probably be per-ASIC...
2423 */ 2438 */
2424 dev->phy.address = dev->cell_index; 2439 dev->phy.gpcs_address = dev->gpcs_address;
2440 if (dev->phy.gpcs_address == 0xffffffff)
2441 dev->phy.address = dev->cell_index;
2425 } 2442 }
2426 2443
2427 emac_configure(dev); 2444 emac_configure(dev);
@@ -2531,6 +2548,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
2531 dev->phy_address = 0xffffffff; 2548 dev->phy_address = 0xffffffff;
2532 if (emac_read_uint_prop(np, "phy-map", &dev->phy_map, 0)) 2549 if (emac_read_uint_prop(np, "phy-map", &dev->phy_map, 0))
2533 dev->phy_map = 0xffffffff; 2550 dev->phy_map = 0xffffffff;
2551 if (emac_read_uint_prop(np, "gpcs-address", &dev->gpcs_address, 0))
2552 dev->gpcs_address = 0xffffffff;
2534 if (emac_read_uint_prop(np->parent, "clock-frequency", &dev->opb_bus_freq, 1)) 2553 if (emac_read_uint_prop(np->parent, "clock-frequency", &dev->opb_bus_freq, 1))
2535 return -ENXIO; 2554 return -ENXIO;
2536 if (emac_read_uint_prop(np, "tah-device", &dev->tah_ph, 0)) 2555 if (emac_read_uint_prop(np, "tah-device", &dev->tah_ph, 0))
@@ -2585,6 +2604,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
2585 if (of_device_is_compatible(np, "ibm,emac-440ep") || 2604 if (of_device_is_compatible(np, "ibm,emac-440ep") ||
2586 of_device_is_compatible(np, "ibm,emac-440gr")) 2605 of_device_is_compatible(np, "ibm,emac-440gr"))
2587 dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX; 2606 dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
2607 if (of_device_is_compatible(np, "ibm,emac-405ez"))
2608 dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x;
2588 } 2609 }
2589 2610
2590 /* Fixup some feature bits based on the device tree */ 2611 /* Fixup some feature bits based on the device tree */
@@ -2842,6 +2863,9 @@ static int __devinit emac_probe(struct of_device *ofdev,
2842 ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2], 2863 ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
2843 ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]); 2864 ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
2844 2865
2866 if (dev->phy_mode == PHY_MODE_SGMII)
2867 printk(KERN_NOTICE "%s: in SGMII mode\n", ndev->name);
2868
2845 if (dev->phy.address >= 0) 2869 if (dev->phy.address >= 0)
2846 printk("%s: found %s PHY (0x%02x)\n", ndev->name, 2870 printk("%s: found %s PHY (0x%02x)\n", ndev->name,
2847 dev->phy.def->name, dev->phy.address); 2871 dev->phy.def->name, dev->phy.address);
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h
index 5ca70e55b6c5..18d56c6c4238 100644
--- a/drivers/net/ibm_newemac/core.h
+++ b/drivers/net/ibm_newemac/core.h
@@ -190,6 +190,9 @@ struct emac_instance {
190 struct delayed_work link_work; 190 struct delayed_work link_work;
191 int link_polling; 191 int link_polling;
192 192
193 /* GPCS PHY infos */
194 u32 gpcs_address;
195
193 /* Shared MDIO if any */ 196 /* Shared MDIO if any */
194 u32 mdio_ph; 197 u32 mdio_ph;
195 struct of_device *mdio_dev; 198 struct of_device *mdio_dev;
@@ -345,6 +348,9 @@ enum {
345#ifdef CONFIG_IBM_NEW_EMAC_RGMII 348#ifdef CONFIG_IBM_NEW_EMAC_RGMII
346 EMAC_FTR_HAS_RGMII | 349 EMAC_FTR_HAS_RGMII |
347#endif 350#endif
351#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
352 EMAC_FTR_NO_FLOW_CONTROL_40x |
353#endif
348 EMAC_FTR_460EX_PHY_CLK_FIX | 354 EMAC_FTR_460EX_PHY_CLK_FIX |
349 EMAC_FTR_440EP_PHY_CLK_FIX, 355 EMAC_FTR_440EP_PHY_CLK_FIX,
350}; 356};
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
index 10c267b2b961..1839d3f154a3 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ibm_newemac/mal.c
@@ -28,6 +28,7 @@
28#include <linux/delay.h> 28#include <linux/delay.h>
29 29
30#include "core.h" 30#include "core.h"
31#include <asm/dcr-regs.h>
31 32
32static int mal_count; 33static int mal_count;
33 34
@@ -279,6 +280,10 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance)
279 mal_schedule_poll(mal); 280 mal_schedule_poll(mal);
280 set_mal_dcrn(mal, MAL_TXEOBISR, r); 281 set_mal_dcrn(mal, MAL_TXEOBISR, r);
281 282
283 if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
284 mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
285 (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));
286
282 return IRQ_HANDLED; 287 return IRQ_HANDLED;
283} 288}
284 289
@@ -293,6 +298,10 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
293 mal_schedule_poll(mal); 298 mal_schedule_poll(mal);
294 set_mal_dcrn(mal, MAL_RXEOBISR, r); 299 set_mal_dcrn(mal, MAL_RXEOBISR, r);
295 300
301 if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
302 mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
303 (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));
304
296 return IRQ_HANDLED; 305 return IRQ_HANDLED;
297} 306}
298 307
@@ -336,6 +345,25 @@ static irqreturn_t mal_rxde(int irq, void *dev_instance)
336 return IRQ_HANDLED; 345 return IRQ_HANDLED;
337} 346}
338 347
348static irqreturn_t mal_int(int irq, void *dev_instance)
349{
350 struct mal_instance *mal = dev_instance;
351 u32 esr = get_mal_dcrn(mal, MAL_ESR);
352
353 if (esr & MAL_ESR_EVB) {
354 /* descriptor error */
355 if (esr & MAL_ESR_DE) {
356 if (esr & MAL_ESR_CIDT)
357 return mal_rxde(irq, dev_instance);
358 else
359 return mal_txde(irq, dev_instance);
360 } else { /* SERR */
361 return mal_serr(irq, dev_instance);
362 }
363 }
364 return IRQ_HANDLED;
365}
366
339void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac) 367void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)
340{ 368{
341 /* Spinlock-type semantics: only one caller disable poll at a time */ 369 /* Spinlock-type semantics: only one caller disable poll at a time */
@@ -493,6 +521,8 @@ static int __devinit mal_probe(struct of_device *ofdev,
493 unsigned int dcr_base; 521 unsigned int dcr_base;
494 const u32 *prop; 522 const u32 *prop;
495 u32 cfg; 523 u32 cfg;
524 unsigned long irqflags;
525 irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
496 526
497 mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL); 527 mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL);
498 if (!mal) { 528 if (!mal) {
@@ -542,11 +572,21 @@ static int __devinit mal_probe(struct of_device *ofdev,
542 goto fail; 572 goto fail;
543 } 573 }
544 574
575 if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez"))
576 mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |
577 MAL_FTR_COMMON_ERR_INT);
578
545 mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0); 579 mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0);
546 mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1); 580 mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1);
547 mal->serr_irq = irq_of_parse_and_map(ofdev->node, 2); 581 mal->serr_irq = irq_of_parse_and_map(ofdev->node, 2);
548 mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3); 582
549 mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4); 583 if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
584 mal->txde_irq = mal->rxde_irq = mal->serr_irq;
585 } else {
586 mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
587 mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
588 }
589
550 if (mal->txeob_irq == NO_IRQ || mal->rxeob_irq == NO_IRQ || 590 if (mal->txeob_irq == NO_IRQ || mal->rxeob_irq == NO_IRQ ||
551 mal->serr_irq == NO_IRQ || mal->txde_irq == NO_IRQ || 591 mal->serr_irq == NO_IRQ || mal->txde_irq == NO_IRQ ||
552 mal->rxde_irq == NO_IRQ) { 592 mal->rxde_irq == NO_IRQ) {
@@ -608,16 +648,26 @@ static int __devinit mal_probe(struct of_device *ofdev,
608 sizeof(struct mal_descriptor) * 648 sizeof(struct mal_descriptor) *
609 mal_rx_bd_offset(mal, i)); 649 mal_rx_bd_offset(mal, i));
610 650
611 err = request_irq(mal->serr_irq, mal_serr, 0, "MAL SERR", mal); 651 if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
652 irqflags = IRQF_SHARED;
653 hdlr_serr = hdlr_txde = hdlr_rxde = mal_int;
654 } else {
655 irqflags = 0;
656 hdlr_serr = mal_serr;
657 hdlr_txde = mal_txde;
658 hdlr_rxde = mal_rxde;
659 }
660
661 err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal);
612 if (err) 662 if (err)
613 goto fail2; 663 goto fail2;
614 err = request_irq(mal->txde_irq, mal_txde, 0, "MAL TX DE", mal); 664 err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal);
615 if (err) 665 if (err)
616 goto fail3; 666 goto fail3;
617 err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal); 667 err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
618 if (err) 668 if (err)
619 goto fail4; 669 goto fail4;
620 err = request_irq(mal->rxde_irq, mal_rxde, 0, "MAL RX DE", mal); 670 err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal);
621 if (err) 671 if (err)
622 goto fail5; 672 goto fail5;
623 err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal); 673 err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h
index 717dc38b6858..2f0a87360844 100644
--- a/drivers/net/ibm_newemac/mal.h
+++ b/drivers/net/ibm_newemac/mal.h
@@ -213,6 +213,8 @@ struct mal_instance {
213 struct of_device *ofdev; 213 struct of_device *ofdev;
214 int index; 214 int index;
215 spinlock_t lock; 215 spinlock_t lock;
216
217 unsigned int features;
216}; 218};
217 219
218static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg) 220static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg)
@@ -225,6 +227,38 @@ static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val)
225 dcr_write(mal->dcr_host, reg, val); 227 dcr_write(mal->dcr_host, reg, val);
226} 228}
227 229
230/* Features of various MAL implementations */
231
232/* Set if you have interrupt coalescing and you have to clear the SDR
233 * register for TXEOB and RXEOB interrupts to work
234 */
235#define MAL_FTR_CLEAR_ICINTSTAT 0x00000001
236
237/* Set if your MAL has SERR, TXDE, and RXDE OR'd into a single UIC
238 * interrupt
239 */
240#define MAL_FTR_COMMON_ERR_INT 0x00000002
241
242enum {
243 MAL_FTRS_ALWAYS = 0,
244
245 MAL_FTRS_POSSIBLE =
246#ifdef CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
247 MAL_FTR_CLEAR_ICINTSTAT |
248#endif
249#ifdef CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR
250 MAL_FTR_COMMON_ERR_INT |
251#endif
252 0,
253};
254
255static inline int mal_has_feature(struct mal_instance *dev,
256 unsigned long feature)
257{
258 return (MAL_FTRS_ALWAYS & feature) ||
259 (MAL_FTRS_POSSIBLE & dev->features & feature);
260}
261
228/* Register MAL devices */ 262/* Register MAL devices */
229int mal_init(void); 263int mal_init(void);
230void mal_exit(void); 264void mal_exit(void);
diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c
index 9164abb72d9b..c40cd8df2212 100644
--- a/drivers/net/ibm_newemac/phy.c
+++ b/drivers/net/ibm_newemac/phy.c
@@ -38,6 +38,16 @@ static inline void phy_write(struct mii_phy *phy, int reg, int val)
38 phy->mdio_write(phy->dev, phy->address, reg, val); 38 phy->mdio_write(phy->dev, phy->address, reg, val);
39} 39}
40 40
41static inline int gpcs_phy_read(struct mii_phy *phy, int reg)
42{
43 return phy->mdio_read(phy->dev, phy->gpcs_address, reg);
44}
45
46static inline void gpcs_phy_write(struct mii_phy *phy, int reg, int val)
47{
48 phy->mdio_write(phy->dev, phy->gpcs_address, reg, val);
49}
50
41int emac_mii_reset_phy(struct mii_phy *phy) 51int emac_mii_reset_phy(struct mii_phy *phy)
42{ 52{
43 int val; 53 int val;
@@ -62,6 +72,37 @@ int emac_mii_reset_phy(struct mii_phy *phy)
62 return limit <= 0; 72 return limit <= 0;
63} 73}
64 74
75int emac_mii_reset_gpcs(struct mii_phy *phy)
76{
77 int val;
78 int limit = 10000;
79
80 val = gpcs_phy_read(phy, MII_BMCR);
81 val &= ~(BMCR_ISOLATE | BMCR_ANENABLE);
82 val |= BMCR_RESET;
83 gpcs_phy_write(phy, MII_BMCR, val);
84
85 udelay(300);
86
87 while (limit--) {
88 val = gpcs_phy_read(phy, MII_BMCR);
89 if (val >= 0 && (val & BMCR_RESET) == 0)
90 break;
91 udelay(10);
92 }
93 if ((val & BMCR_ISOLATE) && limit > 0)
94 gpcs_phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
95
96 if (limit > 0 && phy->mode == PHY_MODE_SGMII) {
97 /* Configure GPCS interface to recommended setting for SGMII */
98 gpcs_phy_write(phy, 0x04, 0x8120); /* AsymPause, FDX */
99 gpcs_phy_write(phy, 0x07, 0x2801); /* msg_pg, toggle */
100 gpcs_phy_write(phy, 0x00, 0x0140); /* 1Gbps, FDX */
101 }
102
103 return limit <= 0;
104}
105
65static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise) 106static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
66{ 107{
67 int ctl, adv; 108 int ctl, adv;
@@ -332,6 +373,33 @@ static int m88e1111_init(struct mii_phy *phy)
332 return 0; 373 return 0;
333} 374}
334 375
376static int m88e1112_init(struct mii_phy *phy)
377{
378 /*
379 * Marvell 88E1112 PHY needs to have the SGMII MAC
380 * interace (page 2) properly configured to
381 * communicate with the 460EX/GT GPCS interface.
382 */
383
384 u16 reg_short;
385
386 pr_debug("%s: Marvell 88E1112 Ethernet\n", __func__);
387
388 /* Set access to Page 2 */
389 phy_write(phy, 0x16, 0x0002);
390
391 phy_write(phy, 0x00, 0x0040); /* 1Gbps */
392 reg_short = (u16)(phy_read(phy, 0x1a));
393 reg_short |= 0x8000; /* bypass Auto-Negotiation */
394 phy_write(phy, 0x1a, reg_short);
395 emac_mii_reset_phy(phy); /* reset MAC interface */
396
397 /* Reset access to Page 0 */
398 phy_write(phy, 0x16, 0x0000);
399
400 return 0;
401}
402
335static int et1011c_init(struct mii_phy *phy) 403static int et1011c_init(struct mii_phy *phy)
336{ 404{
337 u16 reg_short; 405 u16 reg_short;
@@ -384,11 +452,27 @@ static struct mii_phy_def m88e1111_phy_def = {
384 .ops = &m88e1111_phy_ops, 452 .ops = &m88e1111_phy_ops,
385}; 453};
386 454
455static struct mii_phy_ops m88e1112_phy_ops = {
456 .init = m88e1112_init,
457 .setup_aneg = genmii_setup_aneg,
458 .setup_forced = genmii_setup_forced,
459 .poll_link = genmii_poll_link,
460 .read_link = genmii_read_link
461};
462
463static struct mii_phy_def m88e1112_phy_def = {
464 .phy_id = 0x01410C90,
465 .phy_id_mask = 0x0ffffff0,
466 .name = "Marvell 88E1112 Ethernet",
467 .ops = &m88e1112_phy_ops,
468};
469
387static struct mii_phy_def *mii_phy_table[] = { 470static struct mii_phy_def *mii_phy_table[] = {
388 &et1011c_phy_def, 471 &et1011c_phy_def,
389 &cis8201_phy_def, 472 &cis8201_phy_def,
390 &bcm5248_phy_def, 473 &bcm5248_phy_def,
391 &m88e1111_phy_def, 474 &m88e1111_phy_def,
475 &m88e1112_phy_def,
392 &genmii_phy_def, 476 &genmii_phy_def,
393 NULL 477 NULL
394}; 478};
diff --git a/drivers/net/ibm_newemac/phy.h b/drivers/net/ibm_newemac/phy.h
index 1b65c81f6557..5d2bf4cbe50b 100644
--- a/drivers/net/ibm_newemac/phy.h
+++ b/drivers/net/ibm_newemac/phy.h
@@ -57,6 +57,7 @@ struct mii_phy {
57 or determined automaticaly */ 57 or determined automaticaly */
58 int address; /* PHY address */ 58 int address; /* PHY address */
59 int mode; /* PHY mode */ 59 int mode; /* PHY mode */
60 int gpcs_address; /* GPCS PHY address */
60 61
61 /* 1: autoneg enabled, 0: disabled */ 62 /* 1: autoneg enabled, 0: disabled */
62 int autoneg; 63 int autoneg;
@@ -81,5 +82,6 @@ struct mii_phy {
81 */ 82 */
82int emac_mii_phy_probe(struct mii_phy *phy, int address); 83int emac_mii_phy_probe(struct mii_phy *phy, int address);
83int emac_mii_reset_phy(struct mii_phy *phy); 84int emac_mii_reset_phy(struct mii_phy *phy);
85int emac_mii_reset_gpcs(struct mii_phy *phy);
84 86
85#endif /* __IBM_NEWEMAC_PHY_H */ 87#endif /* __IBM_NEWEMAC_PHY_H */