aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-04-04 09:19:54 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2010-04-10 10:51:14 -0400
commit925e7a6504966b838c519f009086982c68e0666f (patch)
tree38ead3a8ae51b973156f6238f7c6b3800d3d7d46
parente7014dada041982ae12ba7fd1967ca0ab0243e04 (diff)
firewire: ohci: enable 1394a enhancements
The OHCI spec says that, if the programPhyEnable bit is set, the driver is responsible for configuring the IEEE1394a enhancements within the PHY and the link consistently. So do this. Also add a quirk to allow disabling these enhancements; this is needed for the TSB12LV22 where ack accelerations are buggy (erratum b). Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r--drivers/firewire/core.h4
-rw-r--r--drivers/firewire/ohci.c83
-rw-r--r--drivers/firewire/ohci.h2
3 files changed, 86 insertions, 3 deletions
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index b2a7b651473a..7a9759bf6837 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -27,8 +27,12 @@ struct fw_packet;
27#define PHY_LINK_ACTIVE 0x80 27#define PHY_LINK_ACTIVE 0x80
28#define PHY_CONTENDER 0x40 28#define PHY_CONTENDER 0x40
29#define PHY_BUS_RESET 0x40 29#define PHY_BUS_RESET 0x40
30#define PHY_EXTENDED_REGISTERS 0xe0
30#define PHY_BUS_SHORT_RESET 0x40 31#define PHY_BUS_SHORT_RESET 0x40
31#define PHY_INT_STATUS_BITS 0x3c 32#define PHY_INT_STATUS_BITS 0x3c
33#define PHY_ENABLE_ACCEL 0x02
34#define PHY_ENABLE_MULTI 0x01
35#define PHY_PAGE_SELECT 0xe0
32 36
33#define BANDWIDTH_AVAILABLE_INITIAL 4915 37#define BANDWIDTH_AVAILABLE_INITIAL 4915
34#define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) 38#define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31)
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 525848f71c34..e934713f3fce 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -236,13 +236,15 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
236#define QUIRK_CYCLE_TIMER 1 236#define QUIRK_CYCLE_TIMER 1
237#define QUIRK_RESET_PACKET 2 237#define QUIRK_RESET_PACKET 2
238#define QUIRK_BE_HEADERS 4 238#define QUIRK_BE_HEADERS 4
239#define QUIRK_NO_1394A 8
239 240
240/* In case of multiple matches in ohci_quirks[], only the first one is used. */ 241/* In case of multiple matches in ohci_quirks[], only the first one is used. */
241static const struct { 242static const struct {
242 unsigned short vendor, device, flags; 243 unsigned short vendor, device, flags;
243} ohci_quirks[] = { 244} ohci_quirks[] = {
244 {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER | 245 {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER |
245 QUIRK_RESET_PACKET}, 246 QUIRK_RESET_PACKET |
247 QUIRK_NO_1394A},
246 {PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET}, 248 {PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET},
247 {PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, 249 {PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER},
248 {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, 250 {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER},
@@ -257,6 +259,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
257 ", nonatomic cycle timer = " __stringify(QUIRK_CYCLE_TIMER) 259 ", nonatomic cycle timer = " __stringify(QUIRK_CYCLE_TIMER)
258 ", reset packet generation = " __stringify(QUIRK_RESET_PACKET) 260 ", reset packet generation = " __stringify(QUIRK_RESET_PACKET)
259 ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS) 261 ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS)
262 ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A)
260 ")"); 263 ")");
261 264
262#ifdef CONFIG_FIREWIRE_OHCI_DEBUG 265#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
@@ -504,6 +507,27 @@ static int ohci_update_phy_reg(struct fw_card *card, int addr,
504 return 0; 507 return 0;
505} 508}
506 509
510static int read_paged_phy_reg(struct fw_card *card,
511 int page, int addr, u32 *value)
512{
513 struct fw_ohci *ohci = fw_ohci(card);
514 u32 reg;
515 int err;
516
517 err = ohci_update_phy_reg(card, 7, PHY_PAGE_SELECT, page << 5);
518 if (err < 0)
519 return err;
520 flush_writes(ohci);
521 msleep(2);
522 reg = reg_read(ohci, OHCI1394_PhyControl);
523 if ((reg & OHCI1394_PhyControl_WritePending) != 0) {
524 fw_error("failed to write phy reg bits\n");
525 return -EBUSY;
526 }
527
528 return read_phy_reg(card, addr, value);
529}
530
507static int ar_context_add_page(struct ar_context *ctx) 531static int ar_context_add_page(struct ar_context *ctx)
508{ 532{
509 struct device *dev = ctx->ohci->card.device; 533 struct device *dev = ctx->ohci->card.device;
@@ -1511,13 +1535,64 @@ static void copy_config_rom(__be32 *dest, const __be32 *src, size_t length)
1511 memset(&dest[length], 0, CONFIG_ROM_SIZE - size); 1535 memset(&dest[length], 0, CONFIG_ROM_SIZE - size);
1512} 1536}
1513 1537
1538static int configure_1394a_enhancements(struct fw_ohci *ohci)
1539{
1540 bool enable_1394a;
1541 u32 reg, phy_compliance;
1542 int clear, set, offset;
1543
1544 /* Check if the driver should configure link and PHY. */
1545 if (!(reg_read(ohci, OHCI1394_HCControlSet) &
1546 OHCI1394_HCControl_programPhyEnable))
1547 return 0;
1548
1549 /* Paranoia: check whether the PHY supports 1394a, too. */
1550 enable_1394a = false;
1551 if (read_phy_reg(&ohci->card, 2, &reg) < 0)
1552 return -EIO;
1553 if ((reg & PHY_EXTENDED_REGISTERS) == PHY_EXTENDED_REGISTERS) {
1554 if (read_paged_phy_reg(&ohci->card, 1, 8, &phy_compliance) < 0)
1555 return -EIO;
1556 if (phy_compliance >= 1)
1557 enable_1394a = true;
1558 }
1559
1560 if (ohci->quirks & QUIRK_NO_1394A)
1561 enable_1394a = false;
1562
1563 /* Configure PHY and link consistently. */
1564 if (enable_1394a) {
1565 clear = 0;
1566 set = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI;
1567 } else {
1568 clear = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI;
1569 set = 0;
1570 }
1571 if (ohci_update_phy_reg(&ohci->card, 5, clear, set) < 0)
1572 return -EIO;
1573 flush_writes(ohci);
1574 msleep(2);
1575
1576 if (enable_1394a)
1577 offset = OHCI1394_HCControlSet;
1578 else
1579 offset = OHCI1394_HCControlClear;
1580 reg_write(ohci, offset, OHCI1394_HCControl_aPhyEnhanceEnable);
1581
1582 /* Clean up: configuration has been taken care of. */
1583 reg_write(ohci, OHCI1394_HCControlClear,
1584 OHCI1394_HCControl_programPhyEnable);
1585
1586 return 0;
1587}
1588
1514static int ohci_enable(struct fw_card *card, 1589static int ohci_enable(struct fw_card *card,
1515 const __be32 *config_rom, size_t length) 1590 const __be32 *config_rom, size_t length)
1516{ 1591{
1517 struct fw_ohci *ohci = fw_ohci(card); 1592 struct fw_ohci *ohci = fw_ohci(card);
1518 struct pci_dev *dev = to_pci_dev(card->device); 1593 struct pci_dev *dev = to_pci_dev(card->device);
1519 u32 lps; 1594 u32 lps;
1520 int i; 1595 int i, err;
1521 1596
1522 if (software_reset(ohci)) { 1597 if (software_reset(ohci)) {
1523 fw_error("Failed to reset ohci card.\n"); 1598 fw_error("Failed to reset ohci card.\n");
@@ -1581,6 +1656,10 @@ static int ohci_enable(struct fw_card *card,
1581 if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) 1656 if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
1582 reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); 1657 reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
1583 1658
1659 err = configure_1394a_enhancements(ohci);
1660 if (err < 0)
1661 return err;
1662
1584 /* Activate link_on bit and contender bit in our self ID packets.*/ 1663 /* Activate link_on bit and contender bit in our self ID packets.*/
1585 if (ohci_update_phy_reg(card, 4, 0, 1664 if (ohci_update_phy_reg(card, 4, 0,
1586 PHY_LINK_ACTIVE | PHY_CONTENDER) < 0) 1665 PHY_LINK_ACTIVE | PHY_CONTENDER) < 0)
diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h
index ba492d85c516..d49e1469a986 100644
--- a/drivers/firewire/ohci.h
+++ b/drivers/firewire/ohci.h
@@ -67,7 +67,7 @@
67#define OHCI1394_PhyControl_ReadDone 0x80000000 67#define OHCI1394_PhyControl_ReadDone 0x80000000
68#define OHCI1394_PhyControl_ReadData(r) (((r) & 0x00ff0000) >> 16) 68#define OHCI1394_PhyControl_ReadData(r) (((r) & 0x00ff0000) >> 16)
69#define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000) 69#define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000)
70#define OHCI1394_PhyControl_WriteDone 0x00004000 70#define OHCI1394_PhyControl_WritePending 0x00004000
71#define OHCI1394_IsochronousCycleTimer 0x0F0 71#define OHCI1394_IsochronousCycleTimer 0x0F0
72#define OHCI1394_AsReqFilterHiSet 0x100 72#define OHCI1394_AsReqFilterHiSet 0x100
73#define OHCI1394_AsReqFilterHiClear 0x104 73#define OHCI1394_AsReqFilterHiClear 0x104