diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2010-06-10 02:35:06 -0400 |
---|---|---|
committer | Clemens Ladisch <clemens@ladisch.de> | 2010-06-10 02:35:06 -0400 |
commit | a1a1132bd83d0aea51d4f19be4b4a58a064a0131 (patch) | |
tree | 93352d6aa9fd8eaa0521fbeb65853cd9f485666e | |
parent | 27a2329f8235d6ce637463f5d83e98d760ef006e (diff) |
firewire: add CSR PRIORITY_BUDGET support
If supported by the OHCI controller, implement the PRIORITY_BUDGET
register, which is required for nodes that can use asynchronous
priority arbitration.
To allow the core to determine what features the lowlevel device
supports, add a new card driver callback.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
-rw-r--r-- | drivers/firewire/core-transaction.c | 14 | ||||
-rw-r--r-- | drivers/firewire/core.h | 4 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 27 | ||||
-rw-r--r-- | include/linux/firewire.h | 1 |
4 files changed, 46 insertions, 0 deletions
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 8146133818dc..a61eb3fb9573 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c | |||
@@ -1126,6 +1126,20 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, | |||
1126 | rcode = RCODE_TYPE_ERROR; | 1126 | rcode = RCODE_TYPE_ERROR; |
1127 | break; | 1127 | break; |
1128 | 1128 | ||
1129 | case CSR_PRIORITY_BUDGET: | ||
1130 | if (!(card->driver->get_features(card) & | ||
1131 | FEATURE_PRIORITY_BUDGET)) | ||
1132 | rcode = RCODE_ADDRESS_ERROR; | ||
1133 | else if (tcode == TCODE_READ_QUADLET_REQUEST) | ||
1134 | *data = cpu_to_be32(card->driver-> | ||
1135 | read_csr_reg(card, CSR_PRIORITY_BUDGET)); | ||
1136 | else if (tcode == TCODE_WRITE_QUADLET_REQUEST) | ||
1137 | card->driver->write_csr_reg(card, CSR_PRIORITY_BUDGET, | ||
1138 | be32_to_cpu(*data)); | ||
1139 | else | ||
1140 | rcode = RCODE_TYPE_ERROR; | ||
1141 | break; | ||
1142 | |||
1129 | case CSR_BROADCAST_CHANNEL: | 1143 | case CSR_BROADCAST_CHANNEL: |
1130 | if (tcode == TCODE_READ_QUADLET_REQUEST) | 1144 | if (tcode == TCODE_READ_QUADLET_REQUEST) |
1131 | *data = cpu_to_be32(card->broadcast_channel); | 1145 | *data = cpu_to_be32(card->broadcast_channel); |
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index efcdeb2e31e6..3b8c0f042f49 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h | |||
@@ -38,6 +38,8 @@ struct fw_packet; | |||
38 | #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) | 38 | #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) |
39 | #define BROADCAST_CHANNEL_VALID (1 << 30) | 39 | #define BROADCAST_CHANNEL_VALID (1 << 30) |
40 | 40 | ||
41 | #define FEATURE_PRIORITY_BUDGET 0x01 | ||
42 | |||
41 | struct fw_card_driver { | 43 | struct fw_card_driver { |
42 | /* | 44 | /* |
43 | * Enable the given card with the given initial config rom. | 45 | * Enable the given card with the given initial config rom. |
@@ -78,6 +80,8 @@ struct fw_card_driver { | |||
78 | u32 (*read_csr_reg)(struct fw_card *card, int csr_offset); | 80 | u32 (*read_csr_reg)(struct fw_card *card, int csr_offset); |
79 | void (*write_csr_reg)(struct fw_card *card, int csr_offset, u32 value); | 81 | void (*write_csr_reg)(struct fw_card *card, int csr_offset, u32 value); |
80 | 82 | ||
83 | unsigned int (*get_features)(struct fw_card *card); | ||
84 | |||
81 | struct fw_iso_context * | 85 | struct fw_iso_context * |
82 | (*allocate_iso_context)(struct fw_card *card, | 86 | (*allocate_iso_context)(struct fw_card *card, |
83 | int type, int channel, size_t header_size); | 87 | int type, int channel, size_t header_size); |
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 9c588fd01250..0e5413531785 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -170,6 +170,7 @@ struct fw_ohci { | |||
170 | int generation; | 170 | int generation; |
171 | int request_generation; /* for timestamping incoming requests */ | 171 | int request_generation; /* for timestamping incoming requests */ |
172 | unsigned quirks; | 172 | unsigned quirks; |
173 | unsigned int pri_req_max; | ||
173 | u32 bus_time; | 174 | u32 bus_time; |
174 | 175 | ||
175 | /* | 176 | /* |
@@ -1738,6 +1739,11 @@ static int ohci_enable(struct fw_card *card, | |||
1738 | reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25); | 1739 | reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25); |
1739 | ohci->bus_time = seconds & ~0x3f; | 1740 | ohci->bus_time = seconds & ~0x3f; |
1740 | 1741 | ||
1742 | /* Get implemented bits of the priority arbitration request counter. */ | ||
1743 | reg_write(ohci, OHCI1394_FairnessControl, 0x3f); | ||
1744 | ohci->pri_req_max = reg_read(ohci, OHCI1394_FairnessControl) & 0x3f; | ||
1745 | reg_write(ohci, OHCI1394_FairnessControl, 0); | ||
1746 | |||
1741 | ar_context_run(&ohci->ar_request_ctx); | 1747 | ar_context_run(&ohci->ar_request_ctx); |
1742 | ar_context_run(&ohci->ar_response_ctx); | 1748 | ar_context_run(&ohci->ar_response_ctx); |
1743 | 1749 | ||
@@ -2028,6 +2034,10 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset) | |||
2028 | value = reg_read(ohci, OHCI1394_ATRetries); | 2034 | value = reg_read(ohci, OHCI1394_ATRetries); |
2029 | return (value >> 4) & 0x0ffff00f; | 2035 | return (value >> 4) & 0x0ffff00f; |
2030 | 2036 | ||
2037 | case CSR_PRIORITY_BUDGET: | ||
2038 | return (reg_read(ohci, OHCI1394_FairnessControl) & 0x3f) | | ||
2039 | (ohci->pri_req_max << 8); | ||
2040 | |||
2031 | default: | 2041 | default: |
2032 | WARN_ON(1); | 2042 | WARN_ON(1); |
2033 | return 0; | 2043 | return 0; |
@@ -2065,12 +2075,28 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value) | |||
2065 | flush_writes(ohci); | 2075 | flush_writes(ohci); |
2066 | break; | 2076 | break; |
2067 | 2077 | ||
2078 | case CSR_PRIORITY_BUDGET: | ||
2079 | reg_write(ohci, OHCI1394_FairnessControl, value & 0x3f); | ||
2080 | flush_writes(ohci); | ||
2081 | break; | ||
2082 | |||
2068 | default: | 2083 | default: |
2069 | WARN_ON(1); | 2084 | WARN_ON(1); |
2070 | break; | 2085 | break; |
2071 | } | 2086 | } |
2072 | } | 2087 | } |
2073 | 2088 | ||
2089 | static unsigned int ohci_get_features(struct fw_card *card) | ||
2090 | { | ||
2091 | struct fw_ohci *ohci = fw_ohci(card); | ||
2092 | unsigned int features = 0; | ||
2093 | |||
2094 | if (ohci->pri_req_max != 0) | ||
2095 | features |= FEATURE_PRIORITY_BUDGET; | ||
2096 | |||
2097 | return features; | ||
2098 | } | ||
2099 | |||
2074 | static void copy_iso_headers(struct iso_context *ctx, void *p) | 2100 | static void copy_iso_headers(struct iso_context *ctx, void *p) |
2075 | { | 2101 | { |
2076 | int i = ctx->header_length; | 2102 | int i = ctx->header_length; |
@@ -2510,6 +2536,7 @@ static const struct fw_card_driver ohci_driver = { | |||
2510 | .enable_phys_dma = ohci_enable_phys_dma, | 2536 | .enable_phys_dma = ohci_enable_phys_dma, |
2511 | .read_csr_reg = ohci_read_csr_reg, | 2537 | .read_csr_reg = ohci_read_csr_reg, |
2512 | .write_csr_reg = ohci_write_csr_reg, | 2538 | .write_csr_reg = ohci_write_csr_reg, |
2539 | .get_features = ohci_get_features, | ||
2513 | 2540 | ||
2514 | .allocate_iso_context = ohci_allocate_iso_context, | 2541 | .allocate_iso_context = ohci_allocate_iso_context, |
2515 | .free_iso_context = ohci_free_iso_context, | 2542 | .free_iso_context = ohci_free_iso_context, |
diff --git a/include/linux/firewire.h b/include/linux/firewire.h index cdf8213c68ca..a50377d91254 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define CSR_CYCLE_TIME 0x200 | 32 | #define CSR_CYCLE_TIME 0x200 |
33 | #define CSR_BUS_TIME 0x204 | 33 | #define CSR_BUS_TIME 0x204 |
34 | #define CSR_BUSY_TIMEOUT 0x210 | 34 | #define CSR_BUSY_TIMEOUT 0x210 |
35 | #define CSR_PRIORITY_BUDGET 0x218 | ||
35 | #define CSR_BUS_MANAGER_ID 0x21c | 36 | #define CSR_BUS_MANAGER_ID 0x21c |
36 | #define CSR_BANDWIDTH_AVAILABLE 0x220 | 37 | #define CSR_BANDWIDTH_AVAILABLE 0x220 |
37 | #define CSR_CHANNELS_AVAILABLE 0x224 | 38 | #define CSR_CHANNELS_AVAILABLE 0x224 |