diff options
-rw-r--r-- | drivers/firewire/core-transaction.c | 12 | ||||
-rw-r--r-- | drivers/firewire/core.h | 2 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 35 | ||||
-rw-r--r-- | drivers/firewire/ohci.h | 1 |
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 | ||
1009 | static void update_split_timeout(struct fw_card *card) | 1014 | static 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 | |||
43 | struct fw_card_driver { | 45 | struct 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 |