summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
authorTomer Maimon <tmaimon77@gmail.com>2021-01-13 23:00:08 +0300
committerJoel Stanley <joel@jms.id.au>2021-11-01 09:42:44 +0300
commit9209d221db6120d4b70063c9a158376ab3506e03 (patch)
tree860430b05c05356ee6482795fd9a3fc24441907e /drivers/spi
parentbb065bb8c6a3b279f6c497189c03cef2987d1b1a (diff)
downloadlinux-9209d221db6120d4b70063c9a158376ab3506e03.tar.xz
spi: npcm-pspi: Add full duplex support
Modify the IRQ handler in the NPCM PSPI driver to support SPI full duplex communication. OpenBMC-Staging-Count: 4 Signed-off-by: Tomer Maimon <tmaimon77@gmail.com> Link: https://lore.kernel.org/r/20210113200010.71845-11-tmaimon77@gmail.com Signed-off-by: Joel Stanley <joel@jms.id.au>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-npcm-pspi.c75
1 files changed, 30 insertions, 45 deletions
diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c
index 1668a347e003..02f0fcceaf19 100644
--- a/drivers/spi/spi-npcm-pspi.c
+++ b/drivers/spi/spi-npcm-pspi.c
@@ -195,22 +195,22 @@ static void npcm_pspi_setup_transfer(struct spi_device *spi,
static void npcm_pspi_send(struct npcm_pspi *priv)
{
int wsize;
- u16 val;
+ u16 val = 0;
wsize = min(bytes_per_word(priv->bits_per_word), priv->tx_bytes);
priv->tx_bytes -= wsize;
- if (!priv->tx_buf)
- return;
-
switch (wsize) {
case 1:
- val = *priv->tx_buf++;
+ if (priv->tx_buf)
+ val = *priv->tx_buf++;
iowrite8(val, NPCM_PSPI_DATA + priv->base);
break;
case 2:
- val = *priv->tx_buf++;
- val = *priv->tx_buf++ | (val << 8);
+ if (priv->tx_buf) {
+ val = *priv->tx_buf++;
+ val = *priv->tx_buf++ | (val << 8);
+ }
iowrite16(val, NPCM_PSPI_DATA + priv->base);
break;
default:
@@ -222,22 +222,24 @@ static void npcm_pspi_send(struct npcm_pspi *priv)
static void npcm_pspi_recv(struct npcm_pspi *priv)
{
int rsize;
- u16 val;
+ u16 val_16;
+ u8 val_8;
rsize = min(bytes_per_word(priv->bits_per_word), priv->rx_bytes);
priv->rx_bytes -= rsize;
- if (!priv->rx_buf)
- return;
-
switch (rsize) {
case 1:
- *priv->rx_buf++ = ioread8(priv->base + NPCM_PSPI_DATA);
+ val_8 = ioread8(priv->base + NPCM_PSPI_DATA);
+ if (priv->rx_buf)
+ *priv->rx_buf++ = val_8;
break;
case 2:
- val = ioread16(priv->base + NPCM_PSPI_DATA);
- *priv->rx_buf++ = (val >> 8);
- *priv->rx_buf++ = val & 0xff;
+ val_16 = ioread16(priv->base + NPCM_PSPI_DATA);
+ if (priv->rx_buf) {
+ *priv->rx_buf++ = (val_16 >> 8);
+ *priv->rx_buf++ = val_16 & 0xff;
+ }
break;
default:
WARN_ON_ONCE(1);
@@ -296,43 +298,26 @@ static irqreturn_t npcm_pspi_handler(int irq, void *dev_id)
struct npcm_pspi *priv = dev_id;
u8 stat;
- stat = ioread8(priv->base + NPCM_PSPI_STAT);
-
if (!priv->tx_buf && !priv->rx_buf)
return IRQ_NONE;
- if (priv->tx_buf) {
- if (stat & NPCM_PSPI_STAT_RBF) {
- ioread8(NPCM_PSPI_DATA + priv->base);
- if (priv->tx_bytes == 0) {
- npcm_pspi_disable(priv);
- complete(&priv->xfer_done);
- return IRQ_HANDLED;
- }
- }
-
- if ((stat & NPCM_PSPI_STAT_BSY) == 0)
- if (priv->tx_bytes)
- npcm_pspi_send(priv);
+ if (priv->tx_bytes == 0 && priv->rx_bytes == 0) {
+ npcm_pspi_disable(priv);
+ complete(&priv->xfer_done);
+ return IRQ_HANDLED;
}
- if (priv->rx_buf) {
- if (stat & NPCM_PSPI_STAT_RBF) {
- if (!priv->rx_bytes)
- return IRQ_NONE;
-
- npcm_pspi_recv(priv);
+ stat = ioread8(priv->base + NPCM_PSPI_STAT);
- if (!priv->rx_bytes) {
- npcm_pspi_disable(priv);
- complete(&priv->xfer_done);
- return IRQ_HANDLED;
- }
- }
+ /*
+ * first we do the read since if we do the write we previous read might
+ * be lost (indeed low chances)
+ */
+ if ((stat & NPCM_PSPI_STAT_RBF) && priv->rx_bytes)
+ npcm_pspi_recv(priv);
- if (((stat & NPCM_PSPI_STAT_BSY) == 0) && !priv->tx_buf)
- iowrite8(0x0, NPCM_PSPI_DATA + priv->base);
- }
+ if (((stat & NPCM_PSPI_STAT_BSY) == 0) && priv->tx_bytes)
+ npcm_pspi_send(priv);
return IRQ_HANDLED;
}