aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-10-06 20:15:07 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-10-06 20:15:07 -0400
commitfa6428ebfa2197841902b89cbc25334707e2f6eb (patch)
treed139b822bc5447198528defb29f0c0e90d89651c /drivers/net
parentc9b59da130b4430910e02a80816f317534cd5e53 (diff)
parent3d5fa877bdf65451c78c3b3d581355deea403b80 (diff)
Merge commit 'jwb/jwb-next'
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ibm_newemac/Kconfig12
-rw-r--r--drivers/net/ibm_newemac/core.c60
-rw-r--r--drivers/net/ibm_newemac/core.h11
-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, 249 insertions, 14 deletions
diff --git a/drivers/net/ibm_newemac/Kconfig b/drivers/net/ibm_newemac/Kconfig
index 70a3272ee998..44e5a0e9922a 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 ccd9d9058f6d..efcf21c9f5c7 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -130,6 +130,7 @@ static inline void emac_report_timeout_error(struct emac_instance *dev,
130 const char *error) 130 const char *error)
131{ 131{
132 if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX | 132 if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX |
133 EMAC_FTR_460EX_PHY_CLK_FIX |
133 EMAC_FTR_440EP_PHY_CLK_FIX)) 134 EMAC_FTR_440EP_PHY_CLK_FIX))
134 DBG(dev, "%s" NL, error); 135 DBG(dev, "%s" NL, error);
135 else if (net_ratelimit()) 136 else if (net_ratelimit())
@@ -201,13 +202,15 @@ static inline int emac_phy_supports_gige(int phy_mode)
201{ 202{
202 return phy_mode == PHY_MODE_GMII || 203 return phy_mode == PHY_MODE_GMII ||
203 phy_mode == PHY_MODE_RGMII || 204 phy_mode == PHY_MODE_RGMII ||
205 phy_mode == PHY_MODE_SGMII ||
204 phy_mode == PHY_MODE_TBI || 206 phy_mode == PHY_MODE_TBI ||
205 phy_mode == PHY_MODE_RTBI; 207 phy_mode == PHY_MODE_RTBI;
206} 208}
207 209
208static inline int emac_phy_gpcs(int phy_mode) 210static inline int emac_phy_gpcs(int phy_mode)
209{ 211{
210 return phy_mode == PHY_MODE_TBI || 212 return phy_mode == PHY_MODE_SGMII ||
213 phy_mode == PHY_MODE_TBI ||
211 phy_mode == PHY_MODE_RTBI; 214 phy_mode == PHY_MODE_RTBI;
212} 215}
213 216
@@ -351,10 +354,24 @@ static int emac_reset(struct emac_instance *dev)
351 emac_tx_disable(dev); 354 emac_tx_disable(dev);
352 } 355 }
353 356
357#ifdef CONFIG_PPC_DCR_NATIVE
358 /* Enable internal clock source */
359 if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
360 dcri_clrset(SDR0, SDR0_ETH_CFG,
361 0, SDR0_ETH_CFG_ECS << dev->cell_index);
362#endif
363
354 out_be32(&p->mr0, EMAC_MR0_SRST); 364 out_be32(&p->mr0, EMAC_MR0_SRST);
355 while ((in_be32(&p->mr0) & EMAC_MR0_SRST) && n) 365 while ((in_be32(&p->mr0) & EMAC_MR0_SRST) && n)
356 --n; 366 --n;
357 367
368#ifdef CONFIG_PPC_DCR_NATIVE
369 /* Enable external clock source */
370 if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
371 dcri_clrset(SDR0, SDR0_ETH_CFG,
372 SDR0_ETH_CFG_ECS << dev->cell_index, 0);
373#endif
374
358 if (n) { 375 if (n) {
359 dev->reset_failed = 0; 376 dev->reset_failed = 0;
360 return 0; 377 return 0;
@@ -547,8 +564,9 @@ static int emac_configure(struct emac_instance *dev)
547 switch (dev->phy.speed) { 564 switch (dev->phy.speed) {
548 case SPEED_1000: 565 case SPEED_1000:
549 if (emac_phy_gpcs(dev->phy.mode)) { 566 if (emac_phy_gpcs(dev->phy.mode)) {
550 mr1 |= EMAC_MR1_MF_1000GPCS | 567 mr1 |= EMAC_MR1_MF_1000GPCS | EMAC_MR1_MF_IPPA(
551 EMAC_MR1_MF_IPPA(dev->phy.address); 568 (dev->phy.gpcs_address != 0xffffffff) ?
569 dev->phy.gpcs_address : dev->phy.address);
552 570
553 /* Put some arbitrary OUI, Manuf & Rev IDs so we can 571 /* Put some arbitrary OUI, Manuf & Rev IDs so we can
554 * identify this GPCS PHY later. 572 * identify this GPCS PHY later.
@@ -660,8 +678,12 @@ static int emac_configure(struct emac_instance *dev)
660 out_be32(&p->iser, r); 678 out_be32(&p->iser, r);
661 679
662 /* 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 */
663 if (emac_phy_gpcs(dev->phy.mode)) 681 if (emac_phy_gpcs(dev->phy.mode)) {
664 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 }
665 687
666 return 0; 688 return 0;
667} 689}
@@ -866,7 +888,9 @@ static int emac_mdio_read(struct net_device *ndev, int id, int reg)
866 struct emac_instance *dev = netdev_priv(ndev); 888 struct emac_instance *dev = netdev_priv(ndev);
867 int res; 889 int res;
868 890
869 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,
870 (u8) id, (u8) reg); 894 (u8) id, (u8) reg);
871 return res; 895 return res;
872} 896}
@@ -875,7 +899,9 @@ static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
875{ 899{
876 struct emac_instance *dev = netdev_priv(ndev); 900 struct emac_instance *dev = netdev_priv(ndev);
877 901
878 __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,
879 (u8) id, (u8) reg, (u16) val); 905 (u8) id, (u8) reg, (u16) val);
880} 906}
881 907
@@ -2367,7 +2393,11 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
2367 * XXX I probably should move these settings to the dev tree 2393 * XXX I probably should move these settings to the dev tree
2368 */ 2394 */
2369 dev->phy.address = -1; 2395 dev->phy.address = -1;
2370 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;
2371 dev->phy.pause = 1; 2401 dev->phy.pause = 1;
2372 2402
2373 return 0; 2403 return 0;
@@ -2406,7 +2436,9 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
2406 * Note that the busy_phy_map is currently global 2436 * Note that the busy_phy_map is currently global
2407 * while it should probably be per-ASIC... 2437 * while it should probably be per-ASIC...
2408 */ 2438 */
2409 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;
2410 } 2442 }
2411 2443
2412 emac_configure(dev); 2444 emac_configure(dev);
@@ -2516,6 +2548,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
2516 dev->phy_address = 0xffffffff; 2548 dev->phy_address = 0xffffffff;
2517 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))
2518 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;
2519 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))
2520 return -ENXIO; 2554 return -ENXIO;
2521 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))
@@ -2559,6 +2593,9 @@ static int __devinit emac_init_config(struct emac_instance *dev)
2559 /* Check EMAC version */ 2593 /* Check EMAC version */
2560 if (of_device_is_compatible(np, "ibm,emac4sync")) { 2594 if (of_device_is_compatible(np, "ibm,emac4sync")) {
2561 dev->features |= (EMAC_FTR_EMAC4 | EMAC_FTR_EMAC4SYNC); 2595 dev->features |= (EMAC_FTR_EMAC4 | EMAC_FTR_EMAC4SYNC);
2596 if (of_device_is_compatible(np, "ibm,emac-460ex") ||
2597 of_device_is_compatible(np, "ibm,emac-460gt"))
2598 dev->features |= EMAC_FTR_460EX_PHY_CLK_FIX;
2562 } else if (of_device_is_compatible(np, "ibm,emac4")) { 2599 } else if (of_device_is_compatible(np, "ibm,emac4")) {
2563 dev->features |= EMAC_FTR_EMAC4; 2600 dev->features |= EMAC_FTR_EMAC4;
2564 if (of_device_is_compatible(np, "ibm,emac-440gx")) 2601 if (of_device_is_compatible(np, "ibm,emac-440gx"))
@@ -2567,6 +2604,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
2567 if (of_device_is_compatible(np, "ibm,emac-440ep") || 2604 if (of_device_is_compatible(np, "ibm,emac-440ep") ||
2568 of_device_is_compatible(np, "ibm,emac-440gr")) 2605 of_device_is_compatible(np, "ibm,emac-440gr"))
2569 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;
2570 } 2609 }
2571 2610
2572 /* Fixup some feature bits based on the device tree */ 2611 /* Fixup some feature bits based on the device tree */
@@ -2824,6 +2863,9 @@ static int __devinit emac_probe(struct of_device *ofdev,
2824 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],
2825 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]);
2826 2865
2866 if (dev->phy_mode == PHY_MODE_SGMII)
2867 printk(KERN_NOTICE "%s: in SGMII mode\n", ndev->name);
2868
2827 if (dev->phy.address >= 0) 2869 if (dev->phy.address >= 0)
2828 printk("%s: found %s PHY (0x%02x)\n", ndev->name, 2870 printk("%s: found %s PHY (0x%02x)\n", ndev->name,
2829 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 6545e69d12c3..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;
@@ -317,6 +320,10 @@ struct emac_instance {
317 * The 405EX and 460EX contain the EMAC4SYNC core 320 * The 405EX and 460EX contain the EMAC4SYNC core
318 */ 321 */
319#define EMAC_FTR_EMAC4SYNC 0x00000200 322#define EMAC_FTR_EMAC4SYNC 0x00000200
323/*
324 * Set if we need phy clock workaround for 460ex or 460gt
325 */
326#define EMAC_FTR_460EX_PHY_CLK_FIX 0x00000400
320 327
321 328
322/* Right now, we don't quite handle the always/possible masks on the 329/* Right now, we don't quite handle the always/possible masks on the
@@ -341,6 +348,10 @@ enum {
341#ifdef CONFIG_IBM_NEW_EMAC_RGMII 348#ifdef CONFIG_IBM_NEW_EMAC_RGMII
342 EMAC_FTR_HAS_RGMII | 349 EMAC_FTR_HAS_RGMII |
343#endif 350#endif
351#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
352 EMAC_FTR_NO_FLOW_CONTROL_40x |
353#endif
354 EMAC_FTR_460EX_PHY_CLK_FIX |
344 EMAC_FTR_440EP_PHY_CLK_FIX, 355 EMAC_FTR_440EP_PHY_CLK_FIX,
345}; 356};
346 357
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 eaa7262dc079..0b2413839b78 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 37bfeea8788a..606db53ef78e 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 */