diff options
-rw-r--r-- | drivers/firewire/core.h | 4 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 83 | ||||
-rw-r--r-- | drivers/firewire/ohci.h | 2 |
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. */ |
241 | static const struct { | 242 | static 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 | ||
510 | static 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 | |||
507 | static int ar_context_add_page(struct ar_context *ctx) | 531 | static 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 | ||
1538 | static 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, ®) < 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 | |||
1514 | static int ohci_enable(struct fw_card *card, | 1589 | static 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 |