aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-06-10 02:35:06 -0400
committerClemens Ladisch <clemens@ladisch.de>2010-06-10 02:35:06 -0400
commita1a1132bd83d0aea51d4f19be4b4a58a064a0131 (patch)
tree93352d6aa9fd8eaa0521fbeb65853cd9f485666e
parent27a2329f8235d6ce637463f5d83e98d760ef006e (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.c14
-rw-r--r--drivers/firewire/core.h4
-rw-r--r--drivers/firewire/ohci.c27
-rw-r--r--include/linux/firewire.h1
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
41struct fw_card_driver { 43struct 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
2089static 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
2074static void copy_iso_headers(struct iso_context *ctx, void *p) 2100static 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