aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firewire/core-transaction.c12
-rw-r--r--drivers/firewire/core.h2
-rw-r--r--drivers/firewire/ohci.c35
-rw-r--r--drivers/firewire/ohci.h1
4 files changed, 48 insertions, 2 deletions
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index dd8ef650a7cb..e0c6cce894cf 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -1003,7 +1003,12 @@ static u32 read_state_register(struct fw_card *card)
1003 * reset, but then cleared when the units are ready again, which 1003 * reset, but then cleared when the units are ready again, which
1004 * happens immediately for us. 1004 * happens immediately for us.
1005 */ 1005 */
1006 return 0; 1006 u32 value = 0x0000;
1007
1008 /* Bit 8 (cmstr): */
1009 value |= card->driver->read_csr_reg(card, CSR_STATE_CLEAR);
1010
1011 return value;
1007} 1012}
1008 1013
1009static void update_split_timeout(struct fw_card *card) 1014static void update_split_timeout(struct fw_card *card)
@@ -1034,6 +1039,8 @@ static void handle_registers(struct fw_card *card, struct fw_request *request,
1034 if (tcode == TCODE_READ_QUADLET_REQUEST) { 1039 if (tcode == TCODE_READ_QUADLET_REQUEST) {
1035 *data = cpu_to_be32(read_state_register(card)); 1040 *data = cpu_to_be32(read_state_register(card));
1036 } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { 1041 } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) {
1042 card->driver->write_csr_reg(card, CSR_STATE_CLEAR,
1043 be32_to_cpu(*data));
1037 } else { 1044 } else {
1038 rcode = RCODE_TYPE_ERROR; 1045 rcode = RCODE_TYPE_ERROR;
1039 } 1046 }
@@ -1043,7 +1050,8 @@ static void handle_registers(struct fw_card *card, struct fw_request *request,
1043 if (tcode == TCODE_READ_QUADLET_REQUEST) { 1050 if (tcode == TCODE_READ_QUADLET_REQUEST) {
1044 *data = cpu_to_be32(read_state_register(card)); 1051 *data = cpu_to_be32(read_state_register(card));
1045 } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) { 1052 } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) {
1046 /* FIXME: implement cmstr */ 1053 card->driver->write_csr_reg(card, CSR_STATE_SET,
1054 be32_to_cpu(*data));
1047 /* FIXME: implement abdicate */ 1055 /* FIXME: implement abdicate */
1048 } else { 1056 } else {
1049 rcode = RCODE_TYPE_ERROR; 1057 rcode = RCODE_TYPE_ERROR;
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 3b8c0f042f49..aaecdd1c1767 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -40,6 +40,8 @@ struct fw_packet;
40 40
41#define FEATURE_PRIORITY_BUDGET 0x01 41#define FEATURE_PRIORITY_BUDGET 0x01
42 42
43#define CSR_STATE_BIT_CMSTR (1 << 8)
44
43struct fw_card_driver { 45struct fw_card_driver {
44 /* 46 /*
45 * Enable the given card with the given initial config rom. 47 * Enable the given card with the given initial config rom.
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 {
172 unsigned quirks; 172 unsigned quirks;
173 unsigned int pri_req_max; 173 unsigned int pri_req_max;
174 u32 bus_time; 174 u32 bus_time;
175 bool is_root;
175 176
176 /* 177 /*
177 * Spinlock for accessing fw_ohci data. Never call out of 178 * Spinlock for accessing fw_ohci data. Never call out of
@@ -1400,6 +1401,7 @@ static void bus_reset_tasklet(unsigned long data)
1400 unsigned long flags; 1401 unsigned long flags;
1401 void *free_rom = NULL; 1402 void *free_rom = NULL;
1402 dma_addr_t free_rom_bus = 0; 1403 dma_addr_t free_rom_bus = 0;
1404 bool is_new_root;
1403 1405
1404 reg = reg_read(ohci, OHCI1394_NodeID); 1406 reg = reg_read(ohci, OHCI1394_NodeID);
1405 if (!(reg & OHCI1394_NodeID_idValid)) { 1407 if (!(reg & OHCI1394_NodeID_idValid)) {
@@ -1413,6 +1415,12 @@ static void bus_reset_tasklet(unsigned long data)
1413 ohci->node_id = reg & (OHCI1394_NodeID_busNumber | 1415 ohci->node_id = reg & (OHCI1394_NodeID_busNumber |
1414 OHCI1394_NodeID_nodeNumber); 1416 OHCI1394_NodeID_nodeNumber);
1415 1417
1418 is_new_root = (reg & OHCI1394_NodeID_root) != 0;
1419 if (!(ohci->is_root && is_new_root))
1420 reg_write(ohci, OHCI1394_LinkControlSet,
1421 OHCI1394_LinkControl_cycleMaster);
1422 ohci->is_root = is_new_root;
1423
1416 reg = reg_read(ohci, OHCI1394_SelfIDCount); 1424 reg = reg_read(ohci, OHCI1394_SelfIDCount);
1417 if (reg & OHCI1394_SelfIDCount_selfIDError) { 1425 if (reg & OHCI1394_SelfIDCount_selfIDError) {
1418 fw_notify("inconsistent self IDs\n"); 1426 fw_notify("inconsistent self IDs\n");
@@ -2013,6 +2021,16 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset)
2013 u32 value; 2021 u32 value;
2014 2022
2015 switch (csr_offset) { 2023 switch (csr_offset) {
2024 case CSR_STATE_CLEAR:
2025 case CSR_STATE_SET:
2026 /* the controller driver handles only the cmstr bit */
2027 if (ohci->is_root &&
2028 (reg_read(ohci, OHCI1394_LinkControlSet) &
2029 OHCI1394_LinkControl_cycleMaster))
2030 return CSR_STATE_BIT_CMSTR;
2031 else
2032 return 0;
2033
2016 case CSR_NODE_IDS: 2034 case CSR_NODE_IDS:
2017 return reg_read(ohci, OHCI1394_NodeID) << 16; 2035 return reg_read(ohci, OHCI1394_NodeID) << 16;
2018 2036
@@ -2050,6 +2068,23 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value)
2050 unsigned long flags; 2068 unsigned long flags;
2051 2069
2052 switch (csr_offset) { 2070 switch (csr_offset) {
2071 case CSR_STATE_CLEAR:
2072 /* the controller driver handles only the cmstr bit */
2073 if ((value & CSR_STATE_BIT_CMSTR) && ohci->is_root) {
2074 reg_write(ohci, OHCI1394_LinkControlClear,
2075 OHCI1394_LinkControl_cycleMaster);
2076 flush_writes(ohci);
2077 }
2078 break;
2079
2080 case CSR_STATE_SET:
2081 if ((value & CSR_STATE_BIT_CMSTR) && ohci->is_root) {
2082 reg_write(ohci, OHCI1394_LinkControlSet,
2083 OHCI1394_LinkControl_cycleMaster);
2084 flush_writes(ohci);
2085 }
2086 break;
2087
2053 case CSR_NODE_IDS: 2088 case CSR_NODE_IDS:
2054 reg_write(ohci, OHCI1394_NodeID, value >> 16); 2089 reg_write(ohci, OHCI1394_NodeID, value >> 16);
2055 flush_writes(ohci); 2090 flush_writes(ohci);
diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h
index 3bc9a5d744eb..0e6c5a466908 100644
--- a/drivers/firewire/ohci.h
+++ b/drivers/firewire/ohci.h
@@ -60,6 +60,7 @@
60#define OHCI1394_LinkControl_cycleSource (1 << 22) 60#define OHCI1394_LinkControl_cycleSource (1 << 22)
61#define OHCI1394_NodeID 0x0E8 61#define OHCI1394_NodeID 0x0E8
62#define OHCI1394_NodeID_idValid 0x80000000 62#define OHCI1394_NodeID_idValid 0x80000000
63#define OHCI1394_NodeID_root 0x40000000
63#define OHCI1394_NodeID_nodeNumber 0x0000003f 64#define OHCI1394_NodeID_nodeNumber 0x0000003f
64#define OHCI1394_NodeID_busNumber 0x0000ffc0 65#define OHCI1394_NodeID_busNumber 0x0000ffc0
65#define OHCI1394_PhyControl 0x0EC 66#define OHCI1394_PhyControl 0x0EC