diff options
Diffstat (limited to 'drivers/spi/spi-bcm-qspi.c')
| -rw-r--r-- | drivers/spi/spi-bcm-qspi.c | 162 | 
1 files changed, 83 insertions, 79 deletions
diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 6573152ce893..8612525fa4e3 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -30,6 +30,7 @@  #include <linux/platform_device.h>  #include <linux/slab.h>  #include <linux/spi/spi.h> +#include <linux/spi/spi-mem.h>  #include <linux/sysfs.h>  #include <linux/types.h>  #include "spi-bcm-qspi.h" @@ -215,10 +216,10 @@ struct bcm_qspi {  	int bspi_maj_rev;  	int bspi_min_rev;  	int bspi_enabled; -	struct spi_flash_read_message *bspi_rf_msg; -	u32 bspi_rf_msg_idx; -	u32 bspi_rf_msg_len; -	u32 bspi_rf_msg_status; +	const struct spi_mem_op *bspi_rf_op; +	u32 bspi_rf_op_idx; +	u32 bspi_rf_op_len; +	u32 bspi_rf_op_status;  	struct bcm_xfer_mode xfer_mode;  	u32 s3_strap_override_ctrl;  	bool bspi_mode; @@ -313,26 +314,26 @@ static inline void bcm_qspi_bspi_lr_clear(struct bcm_qspi *qspi)  static void bcm_qspi_bspi_lr_data_read(struct bcm_qspi *qspi)  { -	u32 *buf = (u32 *)qspi->bspi_rf_msg->buf; +	u32 *buf = (u32 *)qspi->bspi_rf_op->data.buf.in;  	u32 data = 0; -	dev_dbg(&qspi->pdev->dev, "xfer %p rx %p rxlen %d\n", qspi->bspi_rf_msg, -		qspi->bspi_rf_msg->buf, qspi->bspi_rf_msg_len); +	dev_dbg(&qspi->pdev->dev, "xfer %p rx %p rxlen %d\n", qspi->bspi_rf_op, +		qspi->bspi_rf_op->data.buf.in, qspi->bspi_rf_op_len);  	while (!bcm_qspi_bspi_lr_is_fifo_empty(qspi)) {  		data = bcm_qspi_bspi_lr_read_fifo(qspi); -		if (likely(qspi->bspi_rf_msg_len >= 4) && +		if (likely(qspi->bspi_rf_op_len >= 4) &&  		    IS_ALIGNED((uintptr_t)buf, 4)) { -			buf[qspi->bspi_rf_msg_idx++] = data; -			qspi->bspi_rf_msg_len -= 4; +			buf[qspi->bspi_rf_op_idx++] = data; +			qspi->bspi_rf_op_len -= 4;  		} else {  			/* Read out remaining bytes, make sure*/ -			u8 *cbuf = (u8 *)&buf[qspi->bspi_rf_msg_idx]; +			u8 *cbuf = (u8 *)&buf[qspi->bspi_rf_op_idx];  			data = cpu_to_le32(data); -			while (qspi->bspi_rf_msg_len) { +			while (qspi->bspi_rf_op_len) {  				*cbuf++ = (u8)data;  				data >>= 8; -				qspi->bspi_rf_msg_len--; +				qspi->bspi_rf_op_len--;  			}  		}  	} @@ -349,14 +350,12 @@ static void bcm_qspi_bspi_set_xfer_params(struct bcm_qspi *qspi, u8 cmd_byte,  }  static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi, -				       struct spi_flash_read_message *msg, -				       int hp) +				       const struct spi_mem_op *op, int hp)  {  	int bpc = 0, bpp = 0; -	u8 command = msg->read_opcode; -	int width  = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE; -	int addrlen = msg->addr_width; -	int addr_nbits = msg->addr_nbits ? msg->addr_nbits : SPI_NBITS_SINGLE; +	u8 command = op->cmd.opcode; +	int width  = op->cmd.buswidth ? op->cmd.buswidth : SPI_NBITS_SINGLE; +	int addrlen = op->addr.nbytes * 8;  	int flex_mode = 1;  	dev_dbg(&qspi->pdev->dev, "set flex mode w %x addrlen %x hp %d\n", @@ -365,7 +364,7 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi,  	if (addrlen == BSPI_ADDRLEN_4BYTES)  		bpp = BSPI_BPP_ADDR_SELECT_MASK; -	bpp |= msg->dummy_bytes * (8/addr_nbits); +	bpp |= (op->dummy.nbytes * 8) / op->dummy.buswidth;  	switch (width) {  	case SPI_NBITS_SINGLE: @@ -397,11 +396,10 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi,  }  static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi, -				      struct spi_flash_read_message *msg, -				      int hp) +				      const struct spi_mem_op *op, int hp)  { -	int width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE; -	int addrlen = msg->addr_width; +	int width = op->data.buswidth ? op->data.buswidth : SPI_NBITS_SINGLE; +	int addrlen = op->addr.nbytes;  	u32 data = bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL);  	dev_dbg(&qspi->pdev->dev, "set override mode w %x addrlen %x hp %d\n", @@ -437,17 +435,17 @@ static int bcm_qspi_bspi_set_override(struct bcm_qspi *qspi,  	/* set the override mode */  	data |=	BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE;  	bcm_qspi_write(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL, data); -	bcm_qspi_bspi_set_xfer_params(qspi, msg->read_opcode, 0, 0, 0); +	bcm_qspi_bspi_set_xfer_params(qspi, op->cmd.opcode, 0, 0, 0);  	return 0;  }  static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi, -				  struct spi_flash_read_message *msg, int hp) +				  const struct spi_mem_op *op, int hp)  {  	int error = 0; -	int width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE; -	int addrlen = msg->addr_width; +	int width = op->data.buswidth ? op->data.buswidth : SPI_NBITS_SINGLE; +	int addrlen = op->addr.nbytes;  	/* default mode */  	qspi->xfer_mode.flex_mode = true; @@ -460,12 +458,12 @@ static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi,  		if (val & mask || qspi->s3_strap_override_ctrl & mask) {  			qspi->xfer_mode.flex_mode = false;  			bcm_qspi_write(qspi, BSPI, BSPI_FLEX_MODE_ENABLE, 0); -			error = bcm_qspi_bspi_set_override(qspi, msg, hp); +			error = bcm_qspi_bspi_set_override(qspi, op, hp);  		}  	}  	if (qspi->xfer_mode.flex_mode) -		error = bcm_qspi_bspi_set_flex_mode(qspi, msg, hp); +		error = bcm_qspi_bspi_set_flex_mode(qspi, op, hp);  	if (error) {  		dev_warn(&qspi->pdev->dev, @@ -802,19 +800,20 @@ done:  	return slot;  } -static int bcm_qspi_bspi_flash_read(struct spi_device *spi, -				    struct spi_flash_read_message *msg) +static int bcm_qspi_bspi_exec_mem_op(struct spi_device *spi, +				     const struct spi_mem_op *op)  {  	struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); -	u32 addr = 0, len, rdlen, len_words; +	u32 addr = 0, len, rdlen, len_words, from = 0;  	int ret = 0;  	unsigned long timeo = msecs_to_jiffies(100);  	struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;  	if (bcm_qspi_bspi_ver_three(qspi)) -		if (msg->addr_width == BSPI_ADDRLEN_4BYTES) +		if (op->addr.nbytes == BSPI_ADDRLEN_4BYTES)  			return -EIO; +	from = op->addr.val;  	bcm_qspi_chip_select(qspi, spi->chip_select);  	bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0); @@ -823,15 +822,15 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,  	 * the upper address byte to bspi  	 */  	if (bcm_qspi_bspi_ver_three(qspi) == false) { -		addr = msg->from & 0xff000000; +		addr = from & 0xff000000;  		bcm_qspi_write(qspi, BSPI,  			       BSPI_BSPI_FLASH_UPPER_ADDR_BYTE, addr);  	}  	if (!qspi->xfer_mode.flex_mode) -		addr = msg->from; +		addr = from;  	else -		addr = msg->from & 0x00ffffff; +		addr = from & 0x00ffffff;  	if (bcm_qspi_bspi_ver_three(qspi) == true)  		addr = (addr + 0xc00000) & 0xffffff; @@ -840,8 +839,8 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,  	 * read into the entire buffer by breaking the reads  	 * into RAF buffer read lengths  	 */ -	len = msg->len; -	qspi->bspi_rf_msg_idx = 0; +	len = op->data.nbytes; +	qspi->bspi_rf_op_idx = 0;  	do {  		if (len > BSPI_READ_LENGTH) @@ -852,9 +851,9 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,  		reinit_completion(&qspi->bspi_done);  		bcm_qspi_enable_bspi(qspi);  		len_words = (rdlen + 3) >> 2; -		qspi->bspi_rf_msg = msg; -		qspi->bspi_rf_msg_status = 0; -		qspi->bspi_rf_msg_len = rdlen; +		qspi->bspi_rf_op = op; +		qspi->bspi_rf_op_status = 0; +		qspi->bspi_rf_op_len = rdlen;  		dev_dbg(&qspi->pdev->dev,  			"bspi xfr addr 0x%x len 0x%x", addr, rdlen);  		bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr); @@ -879,7 +878,6 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi,  		}  		/* set msg return length */ -		msg->retlen += rdlen;  		addr += rdlen;  		len -= rdlen;  	} while (len); @@ -914,61 +912,63 @@ static int bcm_qspi_transfer_one(struct spi_master *master,  	return 0;  } -static int bcm_qspi_mspi_flash_read(struct spi_device *spi, -				    struct spi_flash_read_message *msg) +static int bcm_qspi_mspi_exec_mem_op(struct spi_device *spi, +				     const struct spi_mem_op *op)  { -	struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); +	struct spi_master *master = spi->master; +	struct bcm_qspi *qspi = spi_master_get_devdata(master);  	struct spi_transfer t[2]; -	u8 cmd[6]; -	int ret; +	u8 cmd[6] = { }; +	int ret, i;  	memset(cmd, 0, sizeof(cmd));  	memset(t, 0, sizeof(t));  	/* tx */  	/* opcode is in cmd[0] */ -	cmd[0] = msg->read_opcode; -	cmd[1] = msg->from >> (msg->addr_width * 8 -  8); -	cmd[2] = msg->from >> (msg->addr_width * 8 - 16); -	cmd[3] = msg->from >> (msg->addr_width * 8 - 24); -	cmd[4] = msg->from >> (msg->addr_width * 8 - 32); +	cmd[0] = op->cmd.opcode; +	for (i = 0; i < op->addr.nbytes; i++) +		cmd[1 + i] = op->addr.val >> (8 * (op->addr.nbytes - i - 1)); +  	t[0].tx_buf = cmd; -	t[0].len = msg->addr_width + msg->dummy_bytes + 1; +	t[0].len = op->addr.nbytes + op->dummy.nbytes + 1;  	t[0].bits_per_word = spi->bits_per_word; -	t[0].tx_nbits = msg->opcode_nbits; +	t[0].tx_nbits = op->cmd.buswidth;  	/* lets mspi know that this is not last transfer */  	qspi->trans_pos.mspi_last_trans = false; -	ret = bcm_qspi_transfer_one(spi->master, spi, &t[0]); +	ret = bcm_qspi_transfer_one(master, spi, &t[0]);  	/* rx */  	qspi->trans_pos.mspi_last_trans = true;  	if (!ret) {  		/* rx */ -		t[1].rx_buf = msg->buf; -		t[1].len = msg->len; -		t[1].rx_nbits =  msg->data_nbits; +		t[1].rx_buf = op->data.buf.in; +		t[1].len = op->data.nbytes; +		t[1].rx_nbits =  op->data.buswidth;  		t[1].bits_per_word = spi->bits_per_word; -		ret = bcm_qspi_transfer_one(spi->master, spi, &t[1]); +		ret = bcm_qspi_transfer_one(master, spi, &t[1]);  	} -	if (!ret) -		msg->retlen = msg->len; -  	return ret;  } -static int bcm_qspi_flash_read(struct spi_device *spi, -			       struct spi_flash_read_message *msg) +static int bcm_qspi_exec_mem_op(struct spi_mem *mem, +				const struct spi_mem_op *op)  { +	struct spi_device *spi = mem->spi;  	struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);  	int ret = 0;  	bool mspi_read = false; -	u32 addr, len; +	u32 addr = 0, len;  	u_char *buf; -	buf = msg->buf; -	addr = msg->from; -	len = msg->len; +	if (!op->data.nbytes || !op->addr.nbytes || op->addr.nbytes > 4 || +	    op->data.dir != SPI_MEM_DATA_IN) +		return -ENOTSUPP; + +	buf = op->data.buf.in; +	addr = op->addr.val; +	len = op->data.nbytes;  	if (bcm_qspi_bspi_ver_three(qspi) == true) {  		/* @@ -990,12 +990,12 @@ static int bcm_qspi_flash_read(struct spi_device *spi,  		mspi_read = true;  	if (mspi_read) -		return bcm_qspi_mspi_flash_read(spi, msg); +		return bcm_qspi_mspi_exec_mem_op(spi, op); -	ret = bcm_qspi_bspi_set_mode(qspi, msg, -1); +	ret = bcm_qspi_bspi_set_mode(qspi, op, -1);  	if (!ret) -		ret = bcm_qspi_bspi_flash_read(spi, msg); +		ret = bcm_qspi_bspi_exec_mem_op(spi, op);  	return ret;  } @@ -1034,10 +1034,10 @@ static irqreturn_t bcm_qspi_bspi_lr_l2_isr(int irq, void *dev_id)  	struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;  	u32 status = qspi_dev_id->irqp->mask; -	if (qspi->bspi_enabled && qspi->bspi_rf_msg) { +	if (qspi->bspi_enabled && qspi->bspi_rf_op) {  		bcm_qspi_bspi_lr_data_read(qspi); -		if (qspi->bspi_rf_msg_len == 0) { -			qspi->bspi_rf_msg = NULL; +		if (qspi->bspi_rf_op_len == 0) { +			qspi->bspi_rf_op = NULL;  			if (qspi->soc_intc) {  				/* disable soc BSPI interrupt */  				soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, @@ -1046,7 +1046,7 @@ static irqreturn_t bcm_qspi_bspi_lr_l2_isr(int irq, void *dev_id)  				status = INTR_BSPI_LR_SESSION_DONE_MASK;  			} -			if (qspi->bspi_rf_msg_status) +			if (qspi->bspi_rf_op_status)  				bcm_qspi_bspi_lr_clear(qspi);  			else  				bcm_qspi_bspi_flush_prefetch_buffers(qspi); @@ -1058,7 +1058,7 @@ static irqreturn_t bcm_qspi_bspi_lr_l2_isr(int irq, void *dev_id)  	}  	status &= INTR_BSPI_LR_SESSION_DONE_MASK; -	if (qspi->bspi_enabled && status && qspi->bspi_rf_msg_len == 0) +	if (qspi->bspi_enabled && status && qspi->bspi_rf_op_len == 0)  		complete(&qspi->bspi_done);  	return IRQ_HANDLED; @@ -1071,7 +1071,7 @@ static irqreturn_t bcm_qspi_bspi_lr_err_l2_isr(int irq, void *dev_id)  	struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;  	dev_err(&qspi->pdev->dev, "BSPI INT error\n"); -	qspi->bspi_rf_msg_status = -EIO; +	qspi->bspi_rf_op_status = -EIO;  	if (qspi->soc_intc)  		/* clear soc interrupt */  		soc_intc->bcm_qspi_int_ack(soc_intc, BSPI_ERR); @@ -1194,6 +1194,10 @@ static void bcm_qspi_hw_uninit(struct bcm_qspi *qspi)  } +static const struct spi_controller_mem_ops bcm_qspi_mem_ops = { +	.exec_op = bcm_qspi_exec_mem_op, +}; +  static const struct of_device_id bcm_qspi_of_match[] = {  	{ .compatible = "brcm,spi-bcm-qspi" },  	{}, @@ -1236,7 +1240,7 @@ int bcm_qspi_probe(struct platform_device *pdev,  	master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_RX_DUAL | SPI_RX_QUAD;  	master->setup = bcm_qspi_setup;  	master->transfer_one = bcm_qspi_transfer_one; -	master->spi_flash_read = bcm_qspi_flash_read; +	master->mem_ops = &bcm_qspi_mem_ops;  	master->cleanup = bcm_qspi_cleanup;  	master->dev.of_node = dev->of_node;  	master->num_chipselect = NUM_CHIPSELECT;  | 
