forked from mirrors/linux
		
	spi: bcm-qspi: Fix bcm_qspi_bspi_read() performance
Let bcm_qspi_bspi_flash_read() return all the requested bytes by breaking up the reads for BSPI block into optimal chunks size that a BSPI block can handle. Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
		
							parent
							
								
									81ab52fd94
								
							
						
					
					
						commit
						345309fa7c
					
				
					 1 changed files with 45 additions and 36 deletions
				
			
		|  | @ -89,7 +89,7 @@ | ||||||
| #define BSPI_BPP_MODE_SELECT_MASK		BIT(8) | #define BSPI_BPP_MODE_SELECT_MASK		BIT(8) | ||||||
| #define BSPI_BPP_ADDR_SELECT_MASK		BIT(16) | #define BSPI_BPP_ADDR_SELECT_MASK		BIT(16) | ||||||
| 
 | 
 | ||||||
| #define BSPI_READ_LENGTH			256 | #define BSPI_READ_LENGTH			512 | ||||||
| 
 | 
 | ||||||
| /* MSPI register offsets */ | /* MSPI register offsets */ | ||||||
| #define MSPI_SPCR0_LSB				0x000 | #define MSPI_SPCR0_LSB				0x000 | ||||||
|  | @ -824,7 +824,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, | ||||||
| 				    struct spi_flash_read_message *msg) | 				    struct spi_flash_read_message *msg) | ||||||
| { | { | ||||||
| 	struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); | 	struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); | ||||||
| 	u32 addr = 0, len, len_words; | 	u32 addr = 0, len, rdlen, len_words; | ||||||
| 	int ret = 0; | 	int ret = 0; | ||||||
| 	unsigned long timeo = msecs_to_jiffies(100); | 	unsigned long timeo = msecs_to_jiffies(100); | ||||||
| 	struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc; | 	struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc; | ||||||
|  | @ -837,7 +837,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, | ||||||
| 	bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0); | 	bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * when using flex mode mode we need to send | 	 * when using flex mode we need to send | ||||||
| 	 * the upper address byte to bspi | 	 * the upper address byte to bspi | ||||||
| 	 */ | 	 */ | ||||||
| 	if (bcm_qspi_bspi_ver_three(qspi) == false) { | 	if (bcm_qspi_bspi_ver_three(qspi) == false) { | ||||||
|  | @ -851,47 +851,56 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, | ||||||
| 	else | 	else | ||||||
| 		addr = msg->from & 0x00ffffff; | 		addr = msg->from & 0x00ffffff; | ||||||
| 
 | 
 | ||||||
| 	/* set BSPI RAF buffer max read length */ |  | ||||||
| 	len = msg->len; |  | ||||||
| 	if (len > BSPI_READ_LENGTH) |  | ||||||
| 		len = BSPI_READ_LENGTH; |  | ||||||
| 
 |  | ||||||
| 	if (bcm_qspi_bspi_ver_three(qspi) == true) | 	if (bcm_qspi_bspi_ver_three(qspi) == true) | ||||||
| 		addr = (addr + 0xc00000) & 0xffffff; | 		addr = (addr + 0xc00000) & 0xffffff; | ||||||
| 
 | 
 | ||||||
| 	reinit_completion(&qspi->bspi_done); | 	/*
 | ||||||
| 	bcm_qspi_enable_bspi(qspi); | 	 * read into the entire buffer by breaking the reads | ||||||
| 	len_words = (len + 3) >> 2; | 	 * into RAF buffer read lengths | ||||||
| 	qspi->bspi_rf_msg = msg; | 	 */ | ||||||
| 	qspi->bspi_rf_msg_status = 0; | 	len = msg->len; | ||||||
| 	qspi->bspi_rf_msg_idx = 0; | 	qspi->bspi_rf_msg_idx = 0; | ||||||
| 	qspi->bspi_rf_msg_len = len; |  | ||||||
| 	dev_dbg(&qspi->pdev->dev, "bspi xfr addr 0x%x len 0x%x", addr, len); |  | ||||||
| 
 | 
 | ||||||
| 	bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr); | 	do { | ||||||
| 	bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words); | 		if (len > BSPI_READ_LENGTH) | ||||||
| 	bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0); | 			rdlen = BSPI_READ_LENGTH; | ||||||
|  | 		else | ||||||
|  | 			rdlen = len; | ||||||
| 
 | 
 | ||||||
| 	if (qspi->soc_intc) { | 		reinit_completion(&qspi->bspi_done); | ||||||
| 		/*
 | 		bcm_qspi_enable_bspi(qspi); | ||||||
| 		 * clear soc MSPI and BSPI interrupts and enable | 		len_words = (rdlen + 3) >> 2; | ||||||
| 		 * BSPI interrupts. | 		qspi->bspi_rf_msg = msg; | ||||||
| 		 */ | 		qspi->bspi_rf_msg_status = 0; | ||||||
| 		soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_BSPI_DONE); | 		qspi->bspi_rf_msg_len = rdlen; | ||||||
| 		soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, true); | 		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); | ||||||
|  | 		bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words); | ||||||
|  | 		bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0); | ||||||
|  | 		if (qspi->soc_intc) { | ||||||
|  | 			/*
 | ||||||
|  | 			 * clear soc MSPI and BSPI interrupts and enable | ||||||
|  | 			 * BSPI interrupts. | ||||||
|  | 			 */ | ||||||
|  | 			soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_BSPI_DONE); | ||||||
|  | 			soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, true); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 	/* Must flush previous writes before starting BSPI operation */ | 		/* Must flush previous writes before starting BSPI operation */ | ||||||
| 	mb(); | 		mb(); | ||||||
|  | 		bcm_qspi_bspi_lr_start(qspi); | ||||||
|  | 		if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) { | ||||||
|  | 			dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n"); | ||||||
|  | 			ret = -ETIMEDOUT; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 	bcm_qspi_bspi_lr_start(qspi); | 		/* set msg return length */ | ||||||
| 	if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) { | 		msg->retlen += rdlen; | ||||||
| 		dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n"); | 		addr += rdlen; | ||||||
| 		ret = -ETIMEDOUT; | 		len -= rdlen; | ||||||
| 	} else { | 	} while (len); | ||||||
| 		/* set the return length for the caller */ |  | ||||||
| 		msg->retlen = len; |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Kamal Dasu
						Kamal Dasu