drivers/spi: reduce confusion in the API
Julius brought up confusion about the current spi api in [1]. In order alleviate the confusion stemming from supporting x86 spi flash controllers: - Remove spi_xfer_two_vectors() which was fusing transactions to accomodate the limitations of the spi controllers themselves. - Add spi_flash_vector_helper() for the x86 spi flash controllers to utilize in validating driver/controller current assumptions. - Remove the xfer() callback in the x86 spi flash drivers which will trigger an error as these controllers can't support the api. [1] https://mail.coreboot.org/pipermail/coreboot/2018-April/086561.html Change-Id: Id88adc6ad5234c29a739d43521c5f344bb7d3217 Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://review.coreboot.org/25745 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
		@@ -146,56 +146,3 @@ int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int spi_xfer_combine_two_vectors(const struct spi_slave *slave,
 | 
			
		||||
					struct spi_op *v1, struct spi_op *v2)
 | 
			
		||||
{
 | 
			
		||||
	struct spi_op op = {
 | 
			
		||||
		.dout = v1->dout, .bytesout = v1->bytesout,
 | 
			
		||||
		.din = v2->din, .bytesin = v2->bytesin,
 | 
			
		||||
	};
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Combine two vectors only if:
 | 
			
		||||
	 * v1 has non-NULL dout and NULL din and
 | 
			
		||||
	 * v2 has non-NULL din and NULL dout and
 | 
			
		||||
	 *
 | 
			
		||||
	 * In all other cases, do not combine the two vectors.
 | 
			
		||||
	 */
 | 
			
		||||
	if ((!v1->dout || v1->din) || (v2->dout || !v2->din))
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	ret = spi_xfer_single_op(slave, &op);
 | 
			
		||||
	v1->status = v2->status = op.status;
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Helper function to allow chipsets to combine two vectors if possible. This
 | 
			
		||||
 * function can only handle upto 2 vectors.
 | 
			
		||||
 *
 | 
			
		||||
 * Two vectors are combined if first vector has a non-NULL dout and NULL din and
 | 
			
		||||
 * second vector has a non-NULL din and NULL dout. Otherwise, each vector is
 | 
			
		||||
 * operated upon one at a time.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns 0 on success and non-zero on failure.
 | 
			
		||||
 */
 | 
			
		||||
int spi_xfer_two_vectors(const struct spi_slave *slave,
 | 
			
		||||
			struct spi_op vectors[], size_t count)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	assert (count <= 2);
 | 
			
		||||
 | 
			
		||||
	if (count == 2) {
 | 
			
		||||
		ret = spi_xfer_combine_two_vectors(slave, &vectors[0],
 | 
			
		||||
						&vectors[1]);
 | 
			
		||||
 | 
			
		||||
		if (!ret || (vectors[0].status != SPI_OP_NOT_EXECUTED))
 | 
			
		||||
			return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return spi_xfer_vector_default(slave, vectors, count);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -519,3 +519,51 @@ int spi_flash_ctrlr_protect_region(const struct spi_flash *flash,
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int spi_flash_vector_helper(const struct spi_slave *slave,
 | 
			
		||||
	struct spi_op vectors[], size_t count,
 | 
			
		||||
	int (*func)(const struct spi_slave *slave, const void *dout,
 | 
			
		||||
		    size_t bytesout, void *din, size_t bytesin))
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	void *din;
 | 
			
		||||
	size_t bytes_in;
 | 
			
		||||
 | 
			
		||||
	if (count < 1 || count > 2)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	/* SPI flash commands always have a command first... */
 | 
			
		||||
	if (!vectors[0].dout || !vectors[0].bytesout)
 | 
			
		||||
		return -1;
 | 
			
		||||
	/* And not read any data during the command. */
 | 
			
		||||
	if (vectors[0].din || vectors[0].bytesin)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	if (count == 2) {
 | 
			
		||||
		/* If response bytes requested ensure the buffer is valid. */
 | 
			
		||||
		if (vectors[1].bytesin && !vectors[1].din)
 | 
			
		||||
			return -1;
 | 
			
		||||
		/* No sends can accompany a receive. */
 | 
			
		||||
		if (vectors[1].dout || vectors[1].bytesout)
 | 
			
		||||
			return -1;
 | 
			
		||||
		din = vectors[1].din;
 | 
			
		||||
		bytes_in = vectors[1].bytesin;
 | 
			
		||||
	} else {
 | 
			
		||||
		din = NULL;
 | 
			
		||||
		bytes_in = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = func(slave, vectors[0].dout, vectors[0].bytesout, din, bytes_in);
 | 
			
		||||
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		vectors[0].status = SPI_OP_FAILURE;
 | 
			
		||||
		if (count == 2)
 | 
			
		||||
			vectors[1].status = SPI_OP_FAILURE;
 | 
			
		||||
	} else {
 | 
			
		||||
		vectors[0].status = SPI_OP_SUCCESS;
 | 
			
		||||
		if (count == 2)
 | 
			
		||||
			vectors[1].status = SPI_OP_SUCCESS;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user