summaryrefslogtreecommitdiff
path: root/drivers/firewire/ohci.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-06-10 08:36:37 +0200
committerClemens Ladisch <clemens@ladisch.de>2010-06-10 08:36:37 +0200
commit4ffb7a6a066e4be4577976d1c08e237c7479770a (patch)
treefd4c275e8ef894d60602e1b4d1f81150e54b32f8 /drivers/firewire/ohci.c
parent3d1f46eb60b155c705e389ecdf313f11b4b91976 (diff)
firewire: add CSR cmstr support
Implement the cmstr bit, which is required for cycle master capable nodes and tested for by the Base 1394 Test Suite. This bit allows the bus master to disable cycle start packets; there are bus master implementations that actually do this. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r--drivers/firewire/ohci.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 0e5413531785..1dcc2e427eb1 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -172,6 +172,7 @@ struct fw_ohci {
unsigned quirks;
unsigned int pri_req_max;
u32 bus_time;
+ bool is_root;
/*
* Spinlock for accessing fw_ohci data. Never call out of
@@ -1400,6 +1401,7 @@ static void bus_reset_tasklet(unsigned long data)
unsigned long flags;
void *free_rom = NULL;
dma_addr_t free_rom_bus = 0;
+ bool is_new_root;
reg = reg_read(ohci, OHCI1394_NodeID);
if (!(reg & OHCI1394_NodeID_idValid)) {
@@ -1413,6 +1415,12 @@ static void bus_reset_tasklet(unsigned long data)
ohci->node_id = reg & (OHCI1394_NodeID_busNumber |
OHCI1394_NodeID_nodeNumber);
+ is_new_root = (reg & OHCI1394_NodeID_root) != 0;
+ if (!(ohci->is_root && is_new_root))
+ reg_write(ohci, OHCI1394_LinkControlSet,
+ OHCI1394_LinkControl_cycleMaster);
+ ohci->is_root = is_new_root;
+
reg = reg_read(ohci, OHCI1394_SelfIDCount);
if (reg & OHCI1394_SelfIDCount_selfIDError) {
fw_notify("inconsistent self IDs\n");
@@ -2013,6 +2021,16 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset)
u32 value;
switch (csr_offset) {
+ case CSR_STATE_CLEAR:
+ case CSR_STATE_SET:
+ /* the controller driver handles only the cmstr bit */
+ if (ohci->is_root &&
+ (reg_read(ohci, OHCI1394_LinkControlSet) &
+ OHCI1394_LinkControl_cycleMaster))
+ return CSR_STATE_BIT_CMSTR;
+ else
+ return 0;
+
case CSR_NODE_IDS:
return reg_read(ohci, OHCI1394_NodeID) << 16;
@@ -2050,6 +2068,23 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value)
unsigned long flags;
switch (csr_offset) {
+ case CSR_STATE_CLEAR:
+ /* the controller driver handles only the cmstr bit */
+ if ((value & CSR_STATE_BIT_CMSTR) && ohci->is_root) {
+ reg_write(ohci, OHCI1394_LinkControlClear,
+ OHCI1394_LinkControl_cycleMaster);
+ flush_writes(ohci);
+ }
+ break;
+
+ case CSR_STATE_SET:
+ if ((value & CSR_STATE_BIT_CMSTR) && ohci->is_root) {
+ reg_write(ohci, OHCI1394_LinkControlSet,
+ OHCI1394_LinkControl_cycleMaster);
+ flush_writes(ohci);
+ }
+ break;
+
case CSR_NODE_IDS:
reg_write(ohci, OHCI1394_NodeID, value >> 16);
flush_writes(ohci);