summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJarod Wilson <jwilson@redhat.com>2008-03-28 10:02:50 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2008-04-18 17:55:34 +0200
commit022147242ff6e4b7ab770f00716063f48c088391 (patch)
treea59646ee968d029550fcb5d99ab2a9885a0f9377 /drivers
parent130d5496e2c9104dcabdaa5c19cd941770e20edc (diff)
firewire: fw-ohci: make sure HCControl register LPS bit is set
I've now witnessed multiple occasions where one of my controllers (a very poorly working JMicron PCIe card) fails to get its registers properly set up in ohci_enable(), apparently due to an occasionally very slow to initiate SClk. The easy fix for this problem is to add a tiny while loop to try again a time or three after initially enabling LPS before we move on (or give up). Of course, the card still isn't fully functional yet, but this gets it at least one tiny step closer... Signed-off-by: Jarod Wilson <jwilson@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/firewire/fw-ohci.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 973e762efc24..e88260b67611 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -1390,6 +1390,8 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
{
struct fw_ohci *ohci = fw_ohci(card);
struct pci_dev *dev = to_pci_dev(card->device);
+ u32 lps;
+ int i;
if (software_reset(ohci)) {
fw_error("Failed to reset ohci card.\n");
@@ -1401,13 +1403,24 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
* most of the registers. In fact, on some cards (ALI M5251),
* accessing registers in the SClk domain without LPS enabled
* will lock up the machine. Wait 50msec to make sure we have
- * full link enabled.
+ * full link enabled. However, with some cards (well, at least
+ * a JMicron PCIe card), we have to try again sometimes.
*/
reg_write(ohci, OHCI1394_HCControlSet,
OHCI1394_HCControl_LPS |
OHCI1394_HCControl_postedWriteEnable);
flush_writes(ohci);
- msleep(50);
+
+ for (lps = 0, i = 0; !lps && i < 3; i++) {
+ msleep(50);
+ lps = reg_read(ohci, OHCI1394_HCControlSet) &
+ OHCI1394_HCControl_LPS;
+ }
+
+ if (!lps) {
+ fw_error("Failed to set Link Power Status\n");
+ return -EIO;
+ }
reg_write(ohci, OHCI1394_HCControlClear,
OHCI1394_HCControl_noByteSwapData);