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 |
