Merge branch 'spi-5.2' into spi-linus
This commit is contained in:
commit
2337ff4529
|
@ -273,6 +273,9 @@ static void spi_qup_read(struct spi_qup *controller, u32 *opflags)
|
||||||
writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
|
writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
|
||||||
controller->base + QUP_OPERATIONAL);
|
controller->base + QUP_OPERATIONAL);
|
||||||
|
|
||||||
|
if (!remainder)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
if (is_block_mode) {
|
if (is_block_mode) {
|
||||||
num_words = (remainder > words_per_block) ?
|
num_words = (remainder > words_per_block) ?
|
||||||
words_per_block : remainder;
|
words_per_block : remainder;
|
||||||
|
@ -302,11 +305,13 @@ static void spi_qup_read(struct spi_qup *controller, u32 *opflags)
|
||||||
* to refresh opflags value because MAX_INPUT_DONE_FLAG may now be
|
* to refresh opflags value because MAX_INPUT_DONE_FLAG may now be
|
||||||
* present and this is used to determine if transaction is complete
|
* present and this is used to determine if transaction is complete
|
||||||
*/
|
*/
|
||||||
*opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
|
exit:
|
||||||
if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG)
|
if (!remainder) {
|
||||||
writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
|
*opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
|
||||||
controller->base + QUP_OPERATIONAL);
|
if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG)
|
||||||
|
writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
|
||||||
|
controller->base + QUP_OPERATIONAL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spi_qup_write_to_fifo(struct spi_qup *controller, u32 num_words)
|
static void spi_qup_write_to_fifo(struct spi_qup *controller, u32 num_words)
|
||||||
|
@ -354,6 +359,10 @@ static void spi_qup_write(struct spi_qup *controller)
|
||||||
writel_relaxed(QUP_OP_OUT_SERVICE_FLAG,
|
writel_relaxed(QUP_OP_OUT_SERVICE_FLAG,
|
||||||
controller->base + QUP_OPERATIONAL);
|
controller->base + QUP_OPERATIONAL);
|
||||||
|
|
||||||
|
/* make sure the interrupt is valid */
|
||||||
|
if (!remainder)
|
||||||
|
return;
|
||||||
|
|
||||||
if (is_block_mode) {
|
if (is_block_mode) {
|
||||||
num_words = (remainder > words_per_block) ?
|
num_words = (remainder > words_per_block) ?
|
||||||
words_per_block : remainder;
|
words_per_block : remainder;
|
||||||
|
@ -567,10 +576,24 @@ static int spi_qup_do_pio(struct spi_device *spi, struct spi_transfer *xfer,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool spi_qup_data_pending(struct spi_qup *controller)
|
||||||
|
{
|
||||||
|
unsigned int remainder_tx, remainder_rx;
|
||||||
|
|
||||||
|
remainder_tx = DIV_ROUND_UP(spi_qup_len(controller) -
|
||||||
|
controller->tx_bytes, controller->w_size);
|
||||||
|
|
||||||
|
remainder_rx = DIV_ROUND_UP(spi_qup_len(controller) -
|
||||||
|
controller->rx_bytes, controller->w_size);
|
||||||
|
|
||||||
|
return remainder_tx || remainder_rx;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
|
static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct spi_qup *controller = dev_id;
|
struct spi_qup *controller = dev_id;
|
||||||
u32 opflags, qup_err, spi_err;
|
u32 opflags, qup_err, spi_err;
|
||||||
|
unsigned long flags;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS);
|
qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS);
|
||||||
|
@ -602,6 +625,11 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
|
||||||
error = -EIO;
|
error = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&controller->lock, flags);
|
||||||
|
if (!controller->error)
|
||||||
|
controller->error = error;
|
||||||
|
spin_unlock_irqrestore(&controller->lock, flags);
|
||||||
|
|
||||||
if (spi_qup_is_dma_xfer(controller->mode)) {
|
if (spi_qup_is_dma_xfer(controller->mode)) {
|
||||||
writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
|
writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
|
||||||
} else {
|
} else {
|
||||||
|
@ -610,11 +638,22 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
|
||||||
|
|
||||||
if (opflags & QUP_OP_OUT_SERVICE_FLAG)
|
if (opflags & QUP_OP_OUT_SERVICE_FLAG)
|
||||||
spi_qup_write(controller);
|
spi_qup_write(controller);
|
||||||
|
|
||||||
|
if (!spi_qup_data_pending(controller))
|
||||||
|
complete(&controller->done);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((opflags & QUP_OP_MAX_INPUT_DONE_FLAG) || error)
|
if (error)
|
||||||
complete(&controller->done);
|
complete(&controller->done);
|
||||||
|
|
||||||
|
if (opflags & QUP_OP_MAX_INPUT_DONE_FLAG) {
|
||||||
|
if (!spi_qup_is_dma_xfer(controller->mode)) {
|
||||||
|
if (spi_qup_data_pending(controller))
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
complete(&controller->done);
|
||||||
|
}
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#define CR_SSHIFT BIT(4)
|
#define CR_SSHIFT BIT(4)
|
||||||
#define CR_DFM BIT(6)
|
#define CR_DFM BIT(6)
|
||||||
#define CR_FSEL BIT(7)
|
#define CR_FSEL BIT(7)
|
||||||
#define CR_FTHRES_MASK GENMASK(12, 8)
|
#define CR_FTHRES_SHIFT 8
|
||||||
#define CR_TEIE BIT(16)
|
#define CR_TEIE BIT(16)
|
||||||
#define CR_TCIE BIT(17)
|
#define CR_TCIE BIT(17)
|
||||||
#define CR_FTIE BIT(18)
|
#define CR_FTIE BIT(18)
|
||||||
|
@ -463,7 +463,7 @@ static int stm32_qspi_setup(struct spi_device *spi)
|
||||||
flash->presc = presc;
|
flash->presc = presc;
|
||||||
|
|
||||||
mutex_lock(&qspi->lock);
|
mutex_lock(&qspi->lock);
|
||||||
qspi->cr_reg = FIELD_PREP(CR_FTHRES_MASK, 3) | CR_SSHIFT | CR_EN;
|
qspi->cr_reg = 3 << CR_FTHRES_SHIFT | CR_SSHIFT | CR_EN;
|
||||||
writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
|
writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
|
||||||
|
|
||||||
/* set dcr fsize to max address */
|
/* set dcr fsize to max address */
|
||||||
|
|
|
@ -328,7 +328,12 @@ static int uniphier_spi_transfer_one(struct spi_master *master,
|
||||||
struct spi_transfer *t)
|
struct spi_transfer *t)
|
||||||
{
|
{
|
||||||
struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
|
struct uniphier_spi_priv *priv = spi_master_get_devdata(master);
|
||||||
int status;
|
struct device *dev = master->dev.parent;
|
||||||
|
unsigned long time_left;
|
||||||
|
|
||||||
|
/* Terminate and return success for 0 byte length transfer */
|
||||||
|
if (!t->len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
uniphier_spi_setup_transfer(spi, t);
|
uniphier_spi_setup_transfer(spi, t);
|
||||||
|
|
||||||
|
@ -338,13 +343,15 @@ static int uniphier_spi_transfer_one(struct spi_master *master,
|
||||||
|
|
||||||
uniphier_spi_irq_enable(spi, SSI_IE_RCIE | SSI_IE_RORIE);
|
uniphier_spi_irq_enable(spi, SSI_IE_RCIE | SSI_IE_RORIE);
|
||||||
|
|
||||||
status = wait_for_completion_timeout(&priv->xfer_done,
|
time_left = wait_for_completion_timeout(&priv->xfer_done,
|
||||||
msecs_to_jiffies(SSI_TIMEOUT_MS));
|
msecs_to_jiffies(SSI_TIMEOUT_MS));
|
||||||
|
|
||||||
uniphier_spi_irq_disable(spi, SSI_IE_RCIE | SSI_IE_RORIE);
|
uniphier_spi_irq_disable(spi, SSI_IE_RCIE | SSI_IE_RORIE);
|
||||||
|
|
||||||
if (status < 0)
|
if (!time_left) {
|
||||||
return status;
|
dev_err(dev, "transfer timeout.\n");
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
return priv->error;
|
return priv->error;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue