Loading drivers/spi/spi-geni-qcom.c +80 −4 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ struct spi_geni_master { spinlock_t lock; int irq; bool cs_flag; bool abort_failed; }; static int get_spi_clk_cfg(unsigned int speed_hz, Loading Loading @@ -141,8 +142,49 @@ static void handle_fifo_timeout(struct spi_master *spi, spin_unlock_irq(&mas->lock); time_left = wait_for_completion_timeout(&mas->abort_done, HZ); if (!time_left) if (!time_left) { dev_err(mas->dev, "Failed to cancel/abort m_cmd\n"); /* * No need for a lock since SPI core has a lock and we never * access this from an interrupt. */ mas->abort_failed = true; } } static bool spi_geni_is_abort_still_pending(struct spi_geni_master *mas) { struct geni_se *se = &mas->se; u32 m_irq, m_irq_en; if (!mas->abort_failed) return false; /* * The only known case where a transfer times out and then a cancel * times out then an abort times out is if something is blocking our * interrupt handler from running. Avoid starting any new transfers * until that sorts itself out. */ spin_lock_irq(&mas->lock); m_irq = readl(se->base + SE_GENI_M_IRQ_STATUS); m_irq_en = readl(se->base + SE_GENI_M_IRQ_EN); spin_unlock_irq(&mas->lock); if (m_irq & m_irq_en) { dev_err(mas->dev, "Interrupts pending after abort: %#010x\n", m_irq & m_irq_en); return true; } /* * If we're here the problem resolved itself so no need to check more * on future transfers. */ mas->abort_failed = false; return false; } static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) Loading @@ -158,10 +200,21 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) if (set_flag == mas->cs_flag) return; mas->cs_flag = set_flag; pm_runtime_get_sync(mas->dev); if (spi_geni_is_abort_still_pending(mas)) { dev_err(mas->dev, "Can't set chip select\n"); goto exit; } spin_lock_irq(&mas->lock); if (mas->cur_xfer) { dev_err(mas->dev, "Can't set CS when prev xfer running\n"); spin_unlock_irq(&mas->lock); goto exit; } mas->cs_flag = set_flag; reinit_completion(&mas->cs_done); if (set_flag) geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0); Loading @@ -170,9 +223,12 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) spin_unlock_irq(&mas->lock); time_left = wait_for_completion_timeout(&mas->cs_done, HZ); if (!time_left) if (!time_left) { dev_warn(mas->dev, "Timeout setting chip select\n"); handle_fifo_timeout(spi, NULL); } exit: pm_runtime_put(mas->dev); } Loading Loading @@ -280,6 +336,9 @@ static int spi_geni_prepare_message(struct spi_master *spi, int ret; struct spi_geni_master *mas = spi_master_get_devdata(spi); if (spi_geni_is_abort_still_pending(mas)) return -EBUSY; ret = setup_fifo_params(spi_msg->spi, spi); if (ret) dev_err(mas->dev, "Couldn't select mode %d\n", ret); Loading Loading @@ -354,6 +413,12 @@ static bool geni_spi_handle_tx(struct spi_geni_master *mas) unsigned int bytes_per_fifo_word = geni_byte_per_fifo_word(mas); unsigned int i = 0; /* Stop the watermark IRQ if nothing to send */ if (!mas->cur_xfer) { writel(0, se->base + SE_GENI_TX_WATERMARK_REG); return false; } max_bytes = (mas->tx_fifo_depth - mas->tx_wm) * bytes_per_fifo_word; if (mas->tx_rem_bytes < max_bytes) max_bytes = mas->tx_rem_bytes; Loading Loading @@ -396,6 +461,14 @@ static void geni_spi_handle_rx(struct spi_geni_master *mas) if (rx_last_byte_valid && rx_last_byte_valid < 4) rx_bytes -= bytes_per_fifo_word - rx_last_byte_valid; } /* Clear out the FIFO and bail if nowhere to put it */ if (!mas->cur_xfer) { for (i = 0; i < DIV_ROUND_UP(rx_bytes, bytes_per_fifo_word); i++) readl(se->base + SE_GENI_RX_FIFOn); return; } if (mas->rx_rem_bytes < rx_bytes) rx_bytes = mas->rx_rem_bytes; Loading Loading @@ -495,6 +568,9 @@ static int spi_geni_transfer_one(struct spi_master *spi, { struct spi_geni_master *mas = spi_master_get_devdata(spi); if (spi_geni_is_abort_still_pending(mas)) return -EBUSY; /* Terminate and return success for 0 byte length transfer */ if (!xfer->len) return 0; Loading drivers/spi/spi-stm32.c +2 −2 Original line number Diff line number Diff line Loading @@ -493,9 +493,9 @@ static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi, u32 xfer_len) /* align packet size with data registers access */ if (spi->cur_bpw > 8) fthlv -= (fthlv % 2); /* multiple of 2 */ fthlv += (fthlv % 2) ? 1 : 0; else fthlv -= (fthlv % 4); /* multiple of 4 */ fthlv += (fthlv % 4) ? (4 - (fthlv % 4)) : 0; if (!fthlv) fthlv = 1; Loading Loading
drivers/spi/spi-geni-qcom.c +80 −4 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ struct spi_geni_master { spinlock_t lock; int irq; bool cs_flag; bool abort_failed; }; static int get_spi_clk_cfg(unsigned int speed_hz, Loading Loading @@ -141,8 +142,49 @@ static void handle_fifo_timeout(struct spi_master *spi, spin_unlock_irq(&mas->lock); time_left = wait_for_completion_timeout(&mas->abort_done, HZ); if (!time_left) if (!time_left) { dev_err(mas->dev, "Failed to cancel/abort m_cmd\n"); /* * No need for a lock since SPI core has a lock and we never * access this from an interrupt. */ mas->abort_failed = true; } } static bool spi_geni_is_abort_still_pending(struct spi_geni_master *mas) { struct geni_se *se = &mas->se; u32 m_irq, m_irq_en; if (!mas->abort_failed) return false; /* * The only known case where a transfer times out and then a cancel * times out then an abort times out is if something is blocking our * interrupt handler from running. Avoid starting any new transfers * until that sorts itself out. */ spin_lock_irq(&mas->lock); m_irq = readl(se->base + SE_GENI_M_IRQ_STATUS); m_irq_en = readl(se->base + SE_GENI_M_IRQ_EN); spin_unlock_irq(&mas->lock); if (m_irq & m_irq_en) { dev_err(mas->dev, "Interrupts pending after abort: %#010x\n", m_irq & m_irq_en); return true; } /* * If we're here the problem resolved itself so no need to check more * on future transfers. */ mas->abort_failed = false; return false; } static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) Loading @@ -158,10 +200,21 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) if (set_flag == mas->cs_flag) return; mas->cs_flag = set_flag; pm_runtime_get_sync(mas->dev); if (spi_geni_is_abort_still_pending(mas)) { dev_err(mas->dev, "Can't set chip select\n"); goto exit; } spin_lock_irq(&mas->lock); if (mas->cur_xfer) { dev_err(mas->dev, "Can't set CS when prev xfer running\n"); spin_unlock_irq(&mas->lock); goto exit; } mas->cs_flag = set_flag; reinit_completion(&mas->cs_done); if (set_flag) geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0); Loading @@ -170,9 +223,12 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) spin_unlock_irq(&mas->lock); time_left = wait_for_completion_timeout(&mas->cs_done, HZ); if (!time_left) if (!time_left) { dev_warn(mas->dev, "Timeout setting chip select\n"); handle_fifo_timeout(spi, NULL); } exit: pm_runtime_put(mas->dev); } Loading Loading @@ -280,6 +336,9 @@ static int spi_geni_prepare_message(struct spi_master *spi, int ret; struct spi_geni_master *mas = spi_master_get_devdata(spi); if (spi_geni_is_abort_still_pending(mas)) return -EBUSY; ret = setup_fifo_params(spi_msg->spi, spi); if (ret) dev_err(mas->dev, "Couldn't select mode %d\n", ret); Loading Loading @@ -354,6 +413,12 @@ static bool geni_spi_handle_tx(struct spi_geni_master *mas) unsigned int bytes_per_fifo_word = geni_byte_per_fifo_word(mas); unsigned int i = 0; /* Stop the watermark IRQ if nothing to send */ if (!mas->cur_xfer) { writel(0, se->base + SE_GENI_TX_WATERMARK_REG); return false; } max_bytes = (mas->tx_fifo_depth - mas->tx_wm) * bytes_per_fifo_word; if (mas->tx_rem_bytes < max_bytes) max_bytes = mas->tx_rem_bytes; Loading Loading @@ -396,6 +461,14 @@ static void geni_spi_handle_rx(struct spi_geni_master *mas) if (rx_last_byte_valid && rx_last_byte_valid < 4) rx_bytes -= bytes_per_fifo_word - rx_last_byte_valid; } /* Clear out the FIFO and bail if nowhere to put it */ if (!mas->cur_xfer) { for (i = 0; i < DIV_ROUND_UP(rx_bytes, bytes_per_fifo_word); i++) readl(se->base + SE_GENI_RX_FIFOn); return; } if (mas->rx_rem_bytes < rx_bytes) rx_bytes = mas->rx_rem_bytes; Loading Loading @@ -495,6 +568,9 @@ static int spi_geni_transfer_one(struct spi_master *spi, { struct spi_geni_master *mas = spi_master_get_devdata(spi); if (spi_geni_is_abort_still_pending(mas)) return -EBUSY; /* Terminate and return success for 0 byte length transfer */ if (!xfer->len) return 0; Loading
drivers/spi/spi-stm32.c +2 −2 Original line number Diff line number Diff line Loading @@ -493,9 +493,9 @@ static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi, u32 xfer_len) /* align packet size with data registers access */ if (spi->cur_bpw > 8) fthlv -= (fthlv % 2); /* multiple of 2 */ fthlv += (fthlv % 2) ? 1 : 0; else fthlv -= (fthlv % 4); /* multiple of 4 */ fthlv += (fthlv % 4) ? (4 - (fthlv % 4)) : 0; if (!fthlv) fthlv = 1; Loading