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:
parent
27a2329f82
commit
a1a1132bd8
4 changed files with 46 additions and 0 deletions
|
@ -1126,6 +1126,20 @@ static void handle_registers(struct fw_card *card, struct fw_request *request,
|
||||||
rcode = RCODE_TYPE_ERROR;
|
rcode = RCODE_TYPE_ERROR;
|
||||||
break;
|
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:
|
case CSR_BROADCAST_CHANNEL:
|
||||||
if (tcode == TCODE_READ_QUADLET_REQUEST)
|
if (tcode == TCODE_READ_QUADLET_REQUEST)
|
||||||
*data = cpu_to_be32(card->broadcast_channel);
|
*data = cpu_to_be32(card->broadcast_channel);
|
||||||
|
|
|
@ -38,6 +38,8 @@ struct fw_packet;
|
||||||
#define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31)
|
#define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31)
|
||||||
#define BROADCAST_CHANNEL_VALID (1 << 30)
|
#define BROADCAST_CHANNEL_VALID (1 << 30)
|
||||||
|
|
||||||
|
#define FEATURE_PRIORITY_BUDGET 0x01
|
||||||
|
|
||||||
struct fw_card_driver {
|
struct fw_card_driver {
|
||||||
/*
|
/*
|
||||||
* Enable the given card with the given initial config rom.
|
* 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);
|
u32 (*read_csr_reg)(struct fw_card *card, int csr_offset);
|
||||||
void (*write_csr_reg)(struct fw_card *card, int csr_offset, u32 value);
|
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 *
|
struct fw_iso_context *
|
||||||
(*allocate_iso_context)(struct fw_card *card,
|
(*allocate_iso_context)(struct fw_card *card,
|
||||||
int type, int channel, size_t header_size);
|
int type, int channel, size_t header_size);
|
||||||
|
|
|
@ -170,6 +170,7 @@ struct fw_ohci {
|
||||||
int generation;
|
int generation;
|
||||||
int request_generation; /* for timestamping incoming requests */
|
int request_generation; /* for timestamping incoming requests */
|
||||||
unsigned quirks;
|
unsigned quirks;
|
||||||
|
unsigned int pri_req_max;
|
||||||
u32 bus_time;
|
u32 bus_time;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1738,6 +1739,11 @@ static int ohci_enable(struct fw_card *card,
|
||||||
reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25);
|
reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25);
|
||||||
ohci->bus_time = seconds & ~0x3f;
|
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_request_ctx);
|
||||||
ar_context_run(&ohci->ar_response_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);
|
value = reg_read(ohci, OHCI1394_ATRetries);
|
||||||
return (value >> 4) & 0x0ffff00f;
|
return (value >> 4) & 0x0ffff00f;
|
||||||
|
|
||||||
|
case CSR_PRIORITY_BUDGET:
|
||||||
|
return (reg_read(ohci, OHCI1394_FairnessControl) & 0x3f) |
|
||||||
|
(ohci->pri_req_max << 8);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2065,12 +2075,28 @@ static void ohci_write_csr_reg(struct fw_card *card, int csr_offset, u32 value)
|
||||||
flush_writes(ohci);
|
flush_writes(ohci);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CSR_PRIORITY_BUDGET:
|
||||||
|
reg_write(ohci, OHCI1394_FairnessControl, value & 0x3f);
|
||||||
|
flush_writes(ohci);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
break;
|
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)
|
static void copy_iso_headers(struct iso_context *ctx, void *p)
|
||||||
{
|
{
|
||||||
int i = ctx->header_length;
|
int i = ctx->header_length;
|
||||||
|
@ -2510,6 +2536,7 @@ static const struct fw_card_driver ohci_driver = {
|
||||||
.enable_phys_dma = ohci_enable_phys_dma,
|
.enable_phys_dma = ohci_enable_phys_dma,
|
||||||
.read_csr_reg = ohci_read_csr_reg,
|
.read_csr_reg = ohci_read_csr_reg,
|
||||||
.write_csr_reg = ohci_write_csr_reg,
|
.write_csr_reg = ohci_write_csr_reg,
|
||||||
|
.get_features = ohci_get_features,
|
||||||
|
|
||||||
.allocate_iso_context = ohci_allocate_iso_context,
|
.allocate_iso_context = ohci_allocate_iso_context,
|
||||||
.free_iso_context = ohci_free_iso_context,
|
.free_iso_context = ohci_free_iso_context,
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define CSR_CYCLE_TIME 0x200
|
#define CSR_CYCLE_TIME 0x200
|
||||||
#define CSR_BUS_TIME 0x204
|
#define CSR_BUS_TIME 0x204
|
||||||
#define CSR_BUSY_TIMEOUT 0x210
|
#define CSR_BUSY_TIMEOUT 0x210
|
||||||
|
#define CSR_PRIORITY_BUDGET 0x218
|
||||||
#define CSR_BUS_MANAGER_ID 0x21c
|
#define CSR_BUS_MANAGER_ID 0x21c
|
||||||
#define CSR_BANDWIDTH_AVAILABLE 0x220
|
#define CSR_BANDWIDTH_AVAILABLE 0x220
|
||||||
#define CSR_CHANNELS_AVAILABLE 0x224
|
#define CSR_CHANNELS_AVAILABLE 0x224
|
||||||
|
|
Loading…
Add table
Reference in a new issue