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>
This commit is contained in:
Clemens Ladisch 2010-06-10 08:35:06 +02:00
parent 27a2329f82
commit a1a1132bd8
4 changed files with 46 additions and 0 deletions

View File

@ -1126,6 +1126,20 @@ static void handle_registers(struct fw_card *card, struct fw_request *request,
rcode = RCODE_TYPE_ERROR;
break;
case CSR_PRIORITY_BUDGET:
if (!(card->driver->get_features(card) &
FEATURE_PRIORITY_BUDGET))
rcode = RCODE_ADDRESS_ERROR;
else if (tcode == TCODE_READ_QUADLET_REQUEST)
*data = cpu_to_be32(card->driver->
read_csr_reg(card, CSR_PRIORITY_BUDGET));
else if (tcode == TCODE_WRITE_QUADLET_REQUEST)
card->driver->write_csr_reg(card, CSR_PRIORITY_BUDGET,
be32_to_cpu(*data));
else
rcode = RCODE_TYPE_ERROR;
break;
case CSR_BROADCAST_CHANNEL:
if (tcode == TCODE_READ_QUADLET_REQUEST)
*data = cpu_to_be32(card->broadcast_channel);

View File

@ -38,6 +38,8 @@ struct fw_packet;
#define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31)
#define BROADCAST_CHANNEL_VALID (1 << 30)
#define FEATURE_PRIORITY_BUDGET 0x01
struct fw_card_driver {
/*
* Enable the given card with the given initial config rom.
@ -78,6 +80,8 @@ struct fw_card_driver {
u32 (*read_csr_reg)(struct fw_card *card, int csr_offset);
void (*write_csr_reg)(struct fw_card *card, int csr_offset, u32 value);
unsigned int (*get_features)(struct fw_card *card);
struct fw_iso_context *
(*allocate_iso_context)(struct fw_card *card,
int type, int channel, size_t header_size);

View File

@ -170,6 +170,7 @@ struct fw_ohci {
int generation;
int request_generation; /* for timestamping incoming requests */
unsigned quirks;
unsigned int pri_req_max;
u32 bus_time;
/*
@ -1738,6 +1739,11 @@ static int ohci_enable(struct fw_card *card,
reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25);
ohci->bus_time = seconds & ~0x3f;
/* Get implemented bits of the priority arbitration request counter. */
reg_write(ohci, OHCI1394_FairnessControl, 0x3f);
ohci->pri_req_max = reg_read(ohci, OHCI1394_FairnessControl) & 0x3f;
reg_write(ohci, OHCI1394_FairnessControl, 0);
ar_context_run(&ohci->ar_request_ctx);
ar_context_run(&ohci->ar_response_ctx);
@ -2028,6 +2034,10 @@ static u32 ohci_read_csr_reg(struct fw_card *card, int csr_offset)
value = reg_read(ohci, OHCI1394_ATRetries);
return (value >> 4) & 0x0ffff00f;
case CSR_PRIORITY_BUDGET:
return (reg_read(ohci, OHCI1394_FairnessControl) & 0x3f) |
(ohci->pri_req_max << 8);
default:
WARN_ON(1);
return 0;
@ -2065,12 +2075,28 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value)
flush_writes(ohci);
break;
case CSR_PRIORITY_BUDGET:
reg_write(ohci, OHCI1394_FairnessControl, value & 0x3f);
flush_writes(ohci);
break;
default:
WARN_ON(1);
break;
}
}
static unsigned int ohci_get_features(struct fw_card *card)
{
struct fw_ohci *ohci = fw_ohci(card);
unsigned int features = 0;
if (ohci->pri_req_max != 0)
features |= FEATURE_PRIORITY_BUDGET;
return features;
}
static void copy_iso_headers(struct iso_context *ctx, void *p)
{
int i = ctx->header_length;
@ -2510,6 +2536,7 @@ static const struct fw_card_driver ohci_driver = {
.enable_phys_dma = ohci_enable_phys_dma,
.read_csr_reg = ohci_read_csr_reg,
.write_csr_reg = ohci_write_csr_reg,
.get_features = ohci_get_features,
.allocate_iso_context = ohci_allocate_iso_context,
.free_iso_context = ohci_free_iso_context,

View File

@ -32,6 +32,7 @@
#define CSR_CYCLE_TIME 0x200
#define CSR_BUS_TIME 0x204
#define CSR_BUSY_TIMEOUT 0x210
#define CSR_PRIORITY_BUDGET 0x218
#define CSR_BUS_MANAGER_ID 0x21c
#define CSR_BANDWIDTH_AVAILABLE 0x220
#define CSR_CHANNELS_AVAILABLE 0x224