Skip to content

Commit 925e7a6

Browse files
cladischStefan Richter
authored andcommitted
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 <[email protected]> Signed-off-by: Stefan Richter <[email protected]>
1 parent e7014da commit 925e7a6

File tree

3 files changed

+86
-3
lines changed

3 files changed

+86
-3
lines changed

drivers/firewire/core.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ struct fw_packet;
2727
#define PHY_LINK_ACTIVE 0x80
2828
#define PHY_CONTENDER 0x40
2929
#define PHY_BUS_RESET 0x40
30+
#define PHY_EXTENDED_REGISTERS 0xe0
3031
#define PHY_BUS_SHORT_RESET 0x40
3132
#define PHY_INT_STATUS_BITS 0x3c
33+
#define PHY_ENABLE_ACCEL 0x02
34+
#define PHY_ENABLE_MULTI 0x01
35+
#define PHY_PAGE_SELECT 0xe0
3236

3337
#define BANDWIDTH_AVAILABLE_INITIAL 4915
3438
#define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31)

drivers/firewire/ohci.c

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,13 +236,15 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
236236
#define QUIRK_CYCLE_TIMER 1
237237
#define QUIRK_RESET_PACKET 2
238238
#define QUIRK_BE_HEADERS 4
239+
#define QUIRK_NO_1394A 8
239240

240241
/* In case of multiple matches in ohci_quirks[], only the first one is used. */
241242
static const struct {
242243
unsigned short vendor, device, flags;
243244
} ohci_quirks[] = {
244245
{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER |
245-
QUIRK_RESET_PACKET},
246+
QUIRK_RESET_PACKET |
247+
QUIRK_NO_1394A},
246248
{PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET},
247249
{PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER},
248250
{PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER},
@@ -257,6 +259,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
257259
", nonatomic cycle timer = " __stringify(QUIRK_CYCLE_TIMER)
258260
", reset packet generation = " __stringify(QUIRK_RESET_PACKET)
259261
", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS)
262+
", no 1394a enhancements = " __stringify(QUIRK_NO_1394A)
260263
")");
261264

262265
#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
@@ -504,6 +507,27 @@ static int ohci_update_phy_reg(struct fw_card *card, int addr,
504507
return 0;
505508
}
506509

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+
507531
static int ar_context_add_page(struct ar_context *ctx)
508532
{
509533
struct device *dev = ctx->ohci->card.device;
@@ -1511,13 +1535,64 @@ static void copy_config_rom(__be32 *dest, const __be32 *src, size_t length)
15111535
memset(&dest[length], 0, CONFIG_ROM_SIZE - size);
15121536
}
15131537

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, &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+
15141589
static int ohci_enable(struct fw_card *card,
15151590
const __be32 *config_rom, size_t length)
15161591
{
15171592
struct fw_ohci *ohci = fw_ohci(card);
15181593
struct pci_dev *dev = to_pci_dev(card->device);
15191594
u32 lps;
1520-
int i;
1595+
int i, err;
15211596

15221597
if (software_reset(ohci)) {
15231598
fw_error("Failed to reset ohci card.\n");
@@ -1581,6 +1656,10 @@ static int ohci_enable(struct fw_card *card,
15811656
if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
15821657
reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
15831658

1659+
err = configure_1394a_enhancements(ohci);
1660+
if (err < 0)
1661+
return err;
1662+
15841663
/* Activate link_on bit and contender bit in our self ID packets.*/
15851664
if (ohci_update_phy_reg(card, 4, 0,
15861665
PHY_LINK_ACTIVE | PHY_CONTENDER) < 0)

drivers/firewire/ohci.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
#define OHCI1394_PhyControl_ReadDone 0x80000000
6868
#define OHCI1394_PhyControl_ReadData(r) (((r) & 0x00ff0000) >> 16)
6969
#define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000)
70-
#define OHCI1394_PhyControl_WriteDone 0x00004000
70+
#define OHCI1394_PhyControl_WritePending 0x00004000
7171
#define OHCI1394_IsochronousCycleTimer 0x0F0
7272
#define OHCI1394_AsReqFilterHiSet 0x100
7373
#define OHCI1394_AsReqFilterHiClear 0x104

0 commit comments

Comments
 (0)