diff options
author | Valentine Barshak <vbarshak@ru.mvista.com> | 2008-04-21 20:46:46 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-04-25 02:08:07 -0400 |
commit | 0925ab5d385b6cd1c435c82bfc01898c81f3d062 (patch) | |
tree | 55a8cf446bc641a8c1c47a43426043b314d7e5fe /drivers | |
parent | be63c09afe9153be6ba4373d1b69848cf2b32268 (diff) |
ibm_newemac: PowerPC 440GX EMAC PHY clock workaround
The PowerPC 440GX Taishan board fails to reset EMAC3 (reset timeout
error) if there's no link. Because of that it fails to find PHY
chip. The older ibm_emac driver had a workaround for that: the
EMAC_CLK_INTERNAL/EMAC_CLK_EXTERNAL macros, which toggle the Ethernet
Clock Select bit in the SDR0_MFR register. This patch does the same for
"ibm,emac-440gx" compatible chips. The workaround forces clock on -all-
EMACs, so we select clock under global emac_phy_map_lock.
BenH: Made that #ifdef CONFIG_PPC_DCR_NATIVE for now as dcri_* stuff
doesn't exist for MMIO type DCRs like Cell. Some future rework &
improvements of the DCR infrastructure will make that cleaner but
for now, this makes it work.
Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ibm_newemac/core.c | 18 | ||||
-rw-r--r-- | drivers/net/ibm_newemac/core.h | 8 |
2 files changed, 23 insertions, 3 deletions
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 7c66727359d4..4176dd6a2e83 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c | |||
@@ -43,6 +43,8 @@ | |||
43 | #include <asm/io.h> | 43 | #include <asm/io.h> |
44 | #include <asm/dma.h> | 44 | #include <asm/dma.h> |
45 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
46 | #include <asm/dcr.h> | ||
47 | #include <asm/dcr-regs.h> | ||
46 | 48 | ||
47 | #include "core.h" | 49 | #include "core.h" |
48 | 50 | ||
@@ -2333,6 +2335,11 @@ static int __devinit emac_init_phy(struct emac_instance *dev) | |||
2333 | dev->phy.mdio_read = emac_mdio_read; | 2335 | dev->phy.mdio_read = emac_mdio_read; |
2334 | dev->phy.mdio_write = emac_mdio_write; | 2336 | dev->phy.mdio_write = emac_mdio_write; |
2335 | 2337 | ||
2338 | /* Enable internal clock source */ | ||
2339 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
2340 | if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX)) | ||
2341 | dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS); | ||
2342 | #endif | ||
2336 | /* Configure EMAC with defaults so we can at least use MDIO | 2343 | /* Configure EMAC with defaults so we can at least use MDIO |
2337 | * This is needed mostly for 440GX | 2344 | * This is needed mostly for 440GX |
2338 | */ | 2345 | */ |
@@ -2365,6 +2372,12 @@ static int __devinit emac_init_phy(struct emac_instance *dev) | |||
2365 | if (!emac_mii_phy_probe(&dev->phy, i)) | 2372 | if (!emac_mii_phy_probe(&dev->phy, i)) |
2366 | break; | 2373 | break; |
2367 | } | 2374 | } |
2375 | |||
2376 | /* Enable external clock source */ | ||
2377 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
2378 | if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX)) | ||
2379 | dcri_clrset(SDR0, SDR0_MFR, SDR0_MFR_ECS, 0); | ||
2380 | #endif | ||
2368 | mutex_unlock(&emac_phy_map_lock); | 2381 | mutex_unlock(&emac_phy_map_lock); |
2369 | if (i == 0x20) { | 2382 | if (i == 0x20) { |
2370 | printk(KERN_WARNING "%s: can't find PHY!\n", np->full_name); | 2383 | printk(KERN_WARNING "%s: can't find PHY!\n", np->full_name); |
@@ -2490,8 +2503,11 @@ static int __devinit emac_init_config(struct emac_instance *dev) | |||
2490 | } | 2503 | } |
2491 | 2504 | ||
2492 | /* Check EMAC version */ | 2505 | /* Check EMAC version */ |
2493 | if (of_device_is_compatible(np, "ibm,emac4")) | 2506 | if (of_device_is_compatible(np, "ibm,emac4")) { |
2494 | dev->features |= EMAC_FTR_EMAC4; | 2507 | dev->features |= EMAC_FTR_EMAC4; |
2508 | if (of_device_is_compatible(np, "ibm,emac-440gx")) | ||
2509 | dev->features |= EMAC_FTR_440GX_PHY_CLK_FIX; | ||
2510 | } | ||
2495 | 2511 | ||
2496 | /* Fixup some feature bits based on the device tree */ | 2512 | /* Fixup some feature bits based on the device tree */ |
2497 | if (of_get_property(np, "has-inverted-stacr-oc", NULL)) | 2513 | if (of_get_property(np, "has-inverted-stacr-oc", NULL)) |
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h index 4e74d8287c65..96ec48266b4a 100644 --- a/drivers/net/ibm_newemac/core.h +++ b/drivers/net/ibm_newemac/core.h | |||
@@ -301,6 +301,10 @@ struct emac_instance { | |||
301 | * Set if we have new type STACR with STAOPC | 301 | * Set if we have new type STACR with STAOPC |
302 | */ | 302 | */ |
303 | #define EMAC_FTR_HAS_NEW_STACR 0x00000040 | 303 | #define EMAC_FTR_HAS_NEW_STACR 0x00000040 |
304 | /* | ||
305 | * Set if we need phy clock workaround for 440gx | ||
306 | */ | ||
307 | #define EMAC_FTR_440GX_PHY_CLK_FIX 0x00000080 | ||
304 | 308 | ||
305 | 309 | ||
306 | /* Right now, we don't quite handle the always/possible masks on the | 310 | /* Right now, we don't quite handle the always/possible masks on the |
@@ -312,8 +316,8 @@ enum { | |||
312 | 316 | ||
313 | EMAC_FTRS_POSSIBLE = | 317 | EMAC_FTRS_POSSIBLE = |
314 | #ifdef CONFIG_IBM_NEW_EMAC_EMAC4 | 318 | #ifdef CONFIG_IBM_NEW_EMAC_EMAC4 |
315 | EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR | | 319 | EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR | |
316 | EMAC_FTR_STACR_OC_INVERT | | 320 | EMAC_FTR_STACR_OC_INVERT | EMAC_FTR_440GX_PHY_CLK_FIX | |
317 | #endif | 321 | #endif |
318 | #ifdef CONFIG_IBM_NEW_EMAC_TAH | 322 | #ifdef CONFIG_IBM_NEW_EMAC_TAH |
319 | EMAC_FTR_HAS_TAH | | 323 | EMAC_FTR_HAS_TAH | |