Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1a1132b authored by Clemens Ladisch's avatar Clemens Ladisch
Browse files

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: default avatarClemens Ladisch <clemens@ladisch.de>
parent 27a2329f
Loading
Loading
Loading
Loading
+14 −0
Original line number Original line Diff line number Diff line
@@ -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);
+4 −0
Original line number Original line Diff line number Diff line
@@ -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);
+27 −0
Original line number Original line Diff line number Diff line
@@ -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,
+1 −0
Original line number Original line Diff line number Diff line
@@ -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