diff options
Diffstat (limited to 'drivers/spi/spi-geni-qcom.c')
| -rw-r--r-- | drivers/spi/spi-geni-qcom.c | 446 |
1 files changed, 302 insertions, 144 deletions
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 4e83cc5b445d..a0d8d3425c6c 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -12,7 +12,8 @@ #include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/pm_runtime.h> -#include <linux/qcom-geni-se.h> +#include <linux/property.h> +#include <linux/soc/qcom/geni-se.h> #include <linux/spi/spi.h> #include <linux/spinlock.h> @@ -35,7 +36,7 @@ #define CS_DEMUX_OUTPUT_SEL GENMASK(3, 0) #define SE_SPI_TRANS_CFG 0x25c -#define CS_TOGGLE BIT(0) +#define CS_TOGGLE BIT(1) #define SE_SPI_WORD_LEN 0x268 #define WORD_LEN_MSK GENMASK(9, 0) @@ -52,6 +53,9 @@ #define SPI_CS_CLK_DELAY_MSK GENMASK(19, 10) #define SPI_CS_CLK_DELAY_SHFT 10 +#define SE_SPI_SLAVE_EN (0x2BC) +#define SPI_SLAVE_EN BIT(0) + /* M_CMD OP codes for SPI */ #define SPI_TX_ONLY 1 #define SPI_RX_ONLY 2 @@ -87,6 +91,8 @@ struct spi_geni_master { struct completion cs_done; struct completion cancel_done; struct completion abort_done; + struct completion tx_reset_done; + struct completion rx_reset_done; unsigned int oversampling; spinlock_t lock; int irq; @@ -97,6 +103,16 @@ struct spi_geni_master { int cur_xfer_mode; }; +static void spi_slv_setup(struct spi_geni_master *mas) +{ + struct geni_se *se = &mas->se; + + writel(SPI_SLAVE_EN, se->base + SE_SPI_SLAVE_EN); + writel(GENI_IO_MUX_0_EN, se->base + GENI_OUTPUT_CTRL); + writel(START_TRIGGER, se->base + SE_GENI_CFG_SEQ_START); + dev_dbg(mas->dev, "spi slave setup done\n"); +} + static int get_spi_clk_cfg(unsigned int speed_hz, struct spi_geni_master *mas, unsigned int *clk_idx, @@ -129,23 +145,37 @@ static int get_spi_clk_cfg(unsigned int speed_hz, return ret; } -static void handle_fifo_timeout(struct spi_master *spi, - struct spi_message *msg) +static void handle_se_timeout(struct spi_controller *spi, + struct spi_message *msg) { - struct spi_geni_master *mas = spi_master_get_devdata(spi); + struct spi_geni_master *mas = spi_controller_get_devdata(spi); unsigned long time_left; struct geni_se *se = &mas->se; + const struct spi_transfer *xfer; spin_lock_irq(&mas->lock); - reinit_completion(&mas->cancel_done); - writel(0, se->base + SE_GENI_TX_WATERMARK_REG); + if (mas->cur_xfer_mode == GENI_SE_FIFO) + writel(0, se->base + SE_GENI_TX_WATERMARK_REG); + + xfer = mas->cur_xfer; mas->cur_xfer = NULL; + + if (spi->target) { + /* + * skip CMD Cancel sequnece since spi target + * doesn`t support CMD Cancel sequnece + */ + spin_unlock_irq(&mas->lock); + goto reset_if_dma; + } + + reinit_completion(&mas->cancel_done); geni_se_cancel_m_cmd(se); spin_unlock_irq(&mas->lock); time_left = wait_for_completion_timeout(&mas->cancel_done, HZ); if (time_left) - return; + goto reset_if_dma; spin_lock_irq(&mas->lock); reinit_completion(&mas->abort_done); @@ -162,23 +192,55 @@ static void handle_fifo_timeout(struct spi_master *spi, */ mas->abort_failed = true; } + +reset_if_dma: + if (mas->cur_xfer_mode == GENI_SE_DMA) { + if (xfer) { + if (xfer->tx_buf) { + spin_lock_irq(&mas->lock); + reinit_completion(&mas->tx_reset_done); + writel(1, se->base + SE_DMA_TX_FSM_RST); + spin_unlock_irq(&mas->lock); + time_left = wait_for_completion_timeout(&mas->tx_reset_done, HZ); + if (!time_left) + dev_err(mas->dev, "DMA TX RESET failed\n"); + } + if (xfer->rx_buf) { + spin_lock_irq(&mas->lock); + reinit_completion(&mas->rx_reset_done); + writel(1, se->base + SE_DMA_RX_FSM_RST); + spin_unlock_irq(&mas->lock); + time_left = wait_for_completion_timeout(&mas->rx_reset_done, HZ); + if (!time_left) + dev_err(mas->dev, "DMA RX RESET failed\n"); + } + } else { + /* + * This can happen if a timeout happened and we had to wait + * for lock in this function because isr was holding the lock + * and handling transfer completion at that time. + */ + dev_warn(mas->dev, "Cancel/Abort on completed SPI transfer\n"); + } + } } -static void handle_gpi_timeout(struct spi_master *spi, struct spi_message *msg) +static void handle_gpi_timeout(struct spi_controller *spi, struct spi_message *msg) { - struct spi_geni_master *mas = spi_master_get_devdata(spi); + struct spi_geni_master *mas = spi_controller_get_devdata(spi); dmaengine_terminate_sync(mas->tx); dmaengine_terminate_sync(mas->rx); } -static void spi_geni_handle_err(struct spi_master *spi, struct spi_message *msg) +static void spi_geni_handle_err(struct spi_controller *spi, struct spi_message *msg) { - struct spi_geni_master *mas = spi_master_get_devdata(spi); + struct spi_geni_master *mas = spi_controller_get_devdata(spi); switch (mas->cur_xfer_mode) { case GENI_SE_FIFO: - handle_fifo_timeout(spi, msg); + case GENI_SE_DMA: + handle_se_timeout(spi, msg); break; case GENI_GPI_DMA: handle_gpi_timeout(spi, msg); @@ -224,8 +286,8 @@ static bool spi_geni_is_abort_still_pending(struct spi_geni_master *mas) static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) { - struct spi_geni_master *mas = spi_master_get_devdata(slv->master); - struct spi_master *spi = dev_get_drvdata(mas->dev); + struct spi_geni_master *mas = spi_controller_get_devdata(slv->controller); + struct spi_controller *spi = dev_get_drvdata(mas->dev); struct geni_se *se = &mas->se; unsigned long time_left; @@ -250,6 +312,10 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) } mas->cs_flag = set_flag; + /* set xfer_mode to FIFO to complete cs_done in isr */ + mas->cur_xfer_mode = GENI_SE_FIFO; + geni_se_select_mode(se, mas->cur_xfer_mode); + reinit_completion(&mas->cs_done); if (set_flag) geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0); @@ -260,7 +326,7 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) time_left = wait_for_completion_timeout(&mas->cs_done, HZ); if (!time_left) { dev_warn(mas->dev, "Timeout setting chip select\n"); - handle_fifo_timeout(spi, NULL); + handle_se_timeout(spi, NULL); } exit: @@ -329,9 +395,9 @@ static int geni_spi_set_clock_and_bw(struct spi_geni_master *mas, } static int setup_fifo_params(struct spi_device *spi_slv, - struct spi_master *spi) + struct spi_controller *spi) { - struct spi_geni_master *mas = spi_master_get_devdata(spi); + struct spi_geni_master *mas = spi_controller_get_devdata(spi); struct geni_se *se = &mas->se; u32 loopback_cfg = 0, cpol = 0, cpha = 0, demux_output_inv = 0; u32 demux_sel; @@ -347,9 +413,9 @@ static int setup_fifo_params(struct spi_device *spi_slv, cpha = CPHA; if (spi_slv->mode & SPI_CS_HIGH) - demux_output_inv = BIT(spi_slv->chip_select); + demux_output_inv = BIT(spi_get_chipselect(spi_slv, 0)); - demux_sel = spi_slv->chip_select; + demux_sel = spi_get_chipselect(spi_slv, 0); mas->cur_bits_per_word = spi_slv->bits_per_word; spi_setup_word_len(mas, spi_slv->mode, spi_slv->bits_per_word); @@ -368,7 +434,7 @@ static int setup_fifo_params(struct spi_device *spi_slv, static void spi_gsi_callback_result(void *cb, const struct dmaengine_result *result) { - struct spi_master *spi = cb; + struct spi_controller *spi = cb; spi->cur_msg->status = -EIO; if (result->result != DMA_TRANS_NOERROR) { @@ -388,7 +454,7 @@ spi_gsi_callback_result(void *cb, const struct dmaengine_result *result) } static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas, - struct spi_device *spi_slv, struct spi_master *spi) + struct spi_device *spi_slv, struct spi_controller *spi) { unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK; struct dma_slave_config config = {}; @@ -425,7 +491,7 @@ static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas peripheral.loopback_en = !!(spi_slv->mode & SPI_LOOP); peripheral.clock_pol_high = !!(spi_slv->mode & SPI_CPOL); peripheral.data_pol_high = !!(spi_slv->mode & SPI_CPHA); - peripheral.cs = spi_slv->chip_select; + peripheral.cs = spi_get_chipselect(spi_slv, 0); peripheral.pack_en = true; peripheral.word_len = xfer->bits_per_word - MIN_WORD_LEN; @@ -477,23 +543,51 @@ static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas return 1; } +static u32 get_xfer_len_in_words(struct spi_transfer *xfer, + struct spi_geni_master *mas) +{ + u32 len; + + if (!(mas->cur_bits_per_word % MIN_WORD_LEN)) + len = xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word; + else + len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1); + len &= TRANS_LEN_MSK; + + return len; +} + static bool geni_can_dma(struct spi_controller *ctlr, struct spi_device *slv, struct spi_transfer *xfer) { - struct spi_geni_master *mas = spi_master_get_devdata(slv->master); + struct spi_geni_master *mas = spi_controller_get_devdata(slv->controller); + u32 len, fifo_size; + + if (mas->cur_xfer_mode == GENI_GPI_DMA) + return true; + + /* Set SE DMA mode for SPI target. */ + if (ctlr->target) + return true; - /* check if dma is supported */ - return mas->cur_xfer_mode != GENI_SE_FIFO; + len = get_xfer_len_in_words(xfer, mas); + fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_per_word; + + if (len > fifo_size) + return true; + else + return false; } -static int spi_geni_prepare_message(struct spi_master *spi, - struct spi_message *spi_msg) +static int spi_geni_prepare_message(struct spi_controller *spi, + struct spi_message *spi_msg) { - struct spi_geni_master *mas = spi_master_get_devdata(spi); + struct spi_geni_master *mas = spi_controller_get_devdata(spi); int ret; switch (mas->cur_xfer_mode) { case GENI_SE_FIFO: + case GENI_SE_DMA: if (spi_geni_is_abort_still_pending(mas)) return -EBUSY; ret = setup_fifo_params(spi_msg->spi, spi); @@ -510,6 +604,21 @@ static int spi_geni_prepare_message(struct spi_master *spi, return -EINVAL; } +static void spi_geni_release_dma_chan(void *data) +{ + struct spi_geni_master *mas = data; + + if (mas->rx) { + dma_release_channel(mas->rx); + mas->rx = NULL; + } + + if (mas->tx) { + dma_release_channel(mas->tx); + mas->tx = NULL; + } +} + static int spi_geni_grab_gpi_chan(struct spi_geni_master *mas) { int ret; @@ -528,6 +637,12 @@ static int spi_geni_grab_gpi_chan(struct spi_geni_master *mas) goto err_rx; } + ret = devm_add_action_or_reset(mas->dev, spi_geni_release_dma_chan, mas); + if (ret) { + dev_err(mas->dev, "Unable to add action.\n"); + return ret; + } + return 0; err_rx: @@ -538,21 +653,9 @@ err_tx: return ret; } -static void spi_geni_release_dma_chan(struct spi_geni_master *mas) -{ - if (mas->rx) { - dma_release_channel(mas->rx); - mas->rx = NULL; - } - - if (mas->tx) { - dma_release_channel(mas->tx); - mas->tx = NULL; - } -} - static int spi_geni_init(struct spi_geni_master *mas) { + struct spi_controller *spi = dev_get_drvdata(mas->dev); struct geni_se *se = &mas->se; unsigned int proto, major, minor, ver; u32 spi_tx_cfg, fifo_disable; @@ -561,7 +664,20 @@ static int spi_geni_init(struct spi_geni_master *mas) pm_runtime_get_sync(mas->dev); proto = geni_se_read_proto(se); - if (proto != GENI_SE_SPI) { + + if (spi->target) { + if (proto != GENI_SE_SPI_SLAVE) { + dev_err(mas->dev, "Invalid proto %d\n", proto); + goto out_pm; + } + spi_slv_setup(mas); + } else if (proto == GENI_SE_INVALID_PROTO) { + ret = geni_load_se_firmware(se, GENI_SE_SPI); + if (ret) { + dev_err(mas->dev, "spi master firmware load failed ret: %d\n", ret); + goto out_pm; + } + } else if (proto != GENI_SE_SPI) { dev_err(mas->dev, "Invalid proto %d\n", proto); goto out_pm; } @@ -595,9 +711,11 @@ static int spi_geni_init(struct spi_geni_master *mas) geni_se_select_mode(se, GENI_GPI_DMA); dev_dbg(mas->dev, "Using GPI DMA mode for SPI\n"); break; + } else if (ret == -EPROBE_DEFER) { + goto out_pm; } /* - * in case of failure to get dma channel, we can still do the + * in case of failure to get gpi dma channel, we can still do the * FIFO mode, so fallthrough */ dev_warn(mas->dev, "FIFO mode disabled, but couldn't get DMA, fall back to FIFO mode\n"); @@ -611,9 +729,11 @@ static int spi_geni_init(struct spi_geni_master *mas) } /* We always control CS manually */ - spi_tx_cfg = readl(se->base + SE_SPI_TRANS_CFG); - spi_tx_cfg &= ~CS_TOGGLE; - writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG); + if (!spi->target) { + spi_tx_cfg = readl(se->base + SE_SPI_TRANS_CFG); + spi_tx_cfg &= ~CS_TOGGLE; + writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG); + } out_pm: pm_runtime_put(mas->dev); @@ -716,9 +836,9 @@ static void geni_spi_handle_rx(struct spi_geni_master *mas) mas->rx_rem_bytes -= rx_bytes; } -static void setup_fifo_xfer(struct spi_transfer *xfer, +static int setup_se_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas, - u16 mode, struct spi_master *spi) + u16 mode, struct spi_controller *spi) { u32 m_cmd = 0; u32 len; @@ -748,16 +868,12 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, /* Speed and bits per word can be overridden per transfer */ ret = geni_spi_set_clock_and_bw(mas, xfer->speed_hz); if (ret) - return; + return ret; mas->tx_rem_bytes = 0; mas->rx_rem_bytes = 0; - if (!(mas->cur_bits_per_word % MIN_WORD_LEN)) - len = xfer->len * BITS_PER_BYTE / mas->cur_bits_per_word; - else - len = xfer->len / (mas->cur_bits_per_word / BITS_PER_BYTE + 1); - len &= TRANS_LEN_MSK; + len = get_xfer_len_in_words(xfer, mas); mas->cur_xfer = xfer; if (xfer->tx_buf) { @@ -773,23 +889,50 @@ static void setup_fifo_xfer(struct spi_transfer *xfer, } /* + * Select DMA mode if sgt are present; and with only 1 entry + * This is not a serious limitation because the xfer buffers are + * expected to fit into in 1 entry almost always, and if any + * doesn't for any reason we fall back to FIFO mode anyway + */ + if (!xfer->tx_sg.nents && !xfer->rx_sg.nents) + mas->cur_xfer_mode = GENI_SE_FIFO; + else if (xfer->tx_sg.nents > 1 || xfer->rx_sg.nents > 1) { + dev_warn_once(mas->dev, "Doing FIFO, cannot handle tx_nents-%d, rx_nents-%d\n", + xfer->tx_sg.nents, xfer->rx_sg.nents); + mas->cur_xfer_mode = GENI_SE_FIFO; + } else + mas->cur_xfer_mode = GENI_SE_DMA; + geni_se_select_mode(se, mas->cur_xfer_mode); + + /* * Lock around right before we start the transfer since our * interrupt could come in at any time now. */ spin_lock_irq(&mas->lock); geni_se_setup_m_cmd(se, m_cmd, FRAGMENTATION); - if (m_cmd & SPI_TX_ONLY) { + + if (mas->cur_xfer_mode == GENI_SE_DMA) { + if (m_cmd & SPI_RX_ONLY) + geni_se_rx_init_dma(se, sg_dma_address(xfer->rx_sg.sgl), + sg_dma_len(xfer->rx_sg.sgl)); + if (m_cmd & SPI_TX_ONLY) + geni_se_tx_init_dma(se, sg_dma_address(xfer->tx_sg.sgl), + sg_dma_len(xfer->tx_sg.sgl)); + } else if (m_cmd & SPI_TX_ONLY) { if (geni_spi_handle_tx(mas)) writel(mas->tx_wm, se->base + SE_GENI_TX_WATERMARK_REG); } + spin_unlock_irq(&mas->lock); + return ret; } -static int spi_geni_transfer_one(struct spi_master *spi, - struct spi_device *slv, - struct spi_transfer *xfer) +static int spi_geni_transfer_one(struct spi_controller *spi, + struct spi_device *slv, + struct spi_transfer *xfer) { - struct spi_geni_master *mas = spi_master_get_devdata(spi); + struct spi_geni_master *mas = spi_controller_get_devdata(spi); + int ret; if (spi_geni_is_abort_still_pending(mas)) return -EBUSY; @@ -798,17 +941,20 @@ static int spi_geni_transfer_one(struct spi_master *spi, if (!xfer->len) return 0; - if (mas->cur_xfer_mode == GENI_SE_FIFO) { - setup_fifo_xfer(xfer, mas, slv->mode, spi); - return 1; + if (mas->cur_xfer_mode == GENI_SE_FIFO || mas->cur_xfer_mode == GENI_SE_DMA) { + ret = setup_se_xfer(xfer, mas, slv->mode, spi); + /* SPI framework expects +ve ret code to wait for transfer complete */ + if (!ret) + ret = 1; + return ret; } return setup_gsi_xfer(xfer, mas, slv, spi); } static irqreturn_t geni_spi_isr(int irq, void *data) { - struct spi_master *spi = data; - struct spi_geni_master *mas = spi_master_get_devdata(spi); + struct spi_controller *spi = data; + struct spi_geni_master *mas = spi_controller_get_devdata(spi); struct geni_se *se = &mas->se; u32 m_irq; @@ -823,39 +969,62 @@ static irqreturn_t geni_spi_isr(int irq, void *data) spin_lock(&mas->lock); - if ((m_irq & M_RX_FIFO_WATERMARK_EN) || (m_irq & M_RX_FIFO_LAST_EN)) - geni_spi_handle_rx(mas); - - if (m_irq & M_TX_FIFO_WATERMARK_EN) - geni_spi_handle_tx(mas); - - if (m_irq & M_CMD_DONE_EN) { - if (mas->cur_xfer) { + if (mas->cur_xfer_mode == GENI_SE_FIFO) { + if ((m_irq & M_RX_FIFO_WATERMARK_EN) || (m_irq & M_RX_FIFO_LAST_EN)) + geni_spi_handle_rx(mas); + + if (m_irq & M_TX_FIFO_WATERMARK_EN) + geni_spi_handle_tx(mas); + + if (m_irq & M_CMD_DONE_EN) { + if (mas->cur_xfer) { + spi_finalize_current_transfer(spi); + mas->cur_xfer = NULL; + /* + * If this happens, then a CMD_DONE came before all the + * Tx buffer bytes were sent out. This is unusual, log + * this condition and disable the WM interrupt to + * prevent the system from stalling due an interrupt + * storm. + * + * If this happens when all Rx bytes haven't been + * received, log the condition. The only known time + * this can happen is if bits_per_word != 8 and some + * registers that expect xfer lengths in num spi_words + * weren't written correctly. + */ + if (mas->tx_rem_bytes) { + writel(0, se->base + SE_GENI_TX_WATERMARK_REG); + dev_err(mas->dev, "Premature done. tx_rem = %d bpw%d\n", + mas->tx_rem_bytes, mas->cur_bits_per_word); + } + if (mas->rx_rem_bytes) + dev_err(mas->dev, "Premature done. rx_rem = %d bpw%d\n", + mas->rx_rem_bytes, mas->cur_bits_per_word); + } else { + complete(&mas->cs_done); + } + } + } else if (mas->cur_xfer_mode == GENI_SE_DMA) { + const struct spi_transfer *xfer = mas->cur_xfer; + u32 dma_tx_status = readl_relaxed(se->base + SE_DMA_TX_IRQ_STAT); + u32 dma_rx_status = readl_relaxed(se->base + SE_DMA_RX_IRQ_STAT); + + if (dma_tx_status) + writel(dma_tx_status, se->base + SE_DMA_TX_IRQ_CLR); + if (dma_rx_status) + writel(dma_rx_status, se->base + SE_DMA_RX_IRQ_CLR); + if (dma_tx_status & TX_DMA_DONE) + mas->tx_rem_bytes = 0; + if (dma_rx_status & RX_DMA_DONE) + mas->rx_rem_bytes = 0; + if (dma_tx_status & TX_RESET_DONE) + complete(&mas->tx_reset_done); + if (dma_rx_status & RX_RESET_DONE) + complete(&mas->rx_reset_done); + if (!mas->tx_rem_bytes && !mas->rx_rem_bytes && xfer) { spi_finalize_current_transfer(spi); mas->cur_xfer = NULL; - /* - * If this happens, then a CMD_DONE came before all the - * Tx buffer bytes were sent out. This is unusual, log - * this condition and disable the WM interrupt to - * prevent the system from stalling due an interrupt - * storm. - * - * If this happens when all Rx bytes haven't been - * received, log the condition. The only known time - * this can happen is if bits_per_word != 8 and some - * registers that expect xfer lengths in num spi_words - * weren't written correctly. - */ - if (mas->tx_rem_bytes) { - writel(0, se->base + SE_GENI_TX_WATERMARK_REG); - dev_err(mas->dev, "Premature done. tx_rem = %d bpw%d\n", - mas->tx_rem_bytes, mas->cur_bits_per_word); - } - if (mas->rx_rem_bytes) - dev_err(mas->dev, "Premature done. rx_rem = %d bpw%d\n", - mas->rx_rem_bytes, mas->cur_bits_per_word); - } else { - complete(&mas->cs_done); } } @@ -887,7 +1056,7 @@ static irqreturn_t geni_spi_isr(int irq, void *data) static int spi_geni_probe(struct platform_device *pdev) { int ret, irq; - struct spi_master *spi; + struct spi_controller *spi; struct spi_geni_master *mas; void __iomem *base; struct clk *clk; @@ -909,12 +1078,12 @@ static int spi_geni_probe(struct platform_device *pdev) if (IS_ERR(clk)) return PTR_ERR(clk); - spi = devm_spi_alloc_master(dev, sizeof(*mas)); + spi = devm_spi_alloc_host(dev, sizeof(*mas)); if (!spi) return -ENOMEM; platform_set_drvdata(pdev, spi); - mas = spi_master_get_devdata(spi); + mas = spi_controller_get_devdata(spi); mas->irq = irq; mas->dev = dev; mas->se.dev = dev; @@ -938,6 +1107,7 @@ static int spi_geni_probe(struct platform_device *pdev) spi->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); spi->num_chipselect = 4; spi->max_speed_hz = 50000000; + spi->max_dma_len = 0xffff0; /* 24 bits for tx/rx dma length */ spi->prepare_message = spi_geni_prepare_message; spi->transfer_one = spi_geni_transfer_one; spi->can_dma = geni_can_dma; @@ -949,71 +1119,60 @@ static int spi_geni_probe(struct platform_device *pdev) init_completion(&mas->cs_done); init_completion(&mas->cancel_done); init_completion(&mas->abort_done); + init_completion(&mas->tx_reset_done); + init_completion(&mas->rx_reset_done); spin_lock_init(&mas->lock); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_set_autosuspend_delay(&pdev->dev, 250); - pm_runtime_enable(dev); ret = geni_icc_get(&mas->se, NULL); if (ret) - goto spi_geni_probe_runtime_disable; + return ret; + + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, 250); + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + + if (device_property_read_bool(&pdev->dev, "spi-slave")) + spi->target = true; + /* Set the bus quota to a reasonable value for register access */ mas->se.icc_paths[GENI_TO_CORE].avg_bw = Bps_to_icc(CORE_2X_50_MHZ); mas->se.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW; ret = geni_icc_set_bw(&mas->se); if (ret) - goto spi_geni_probe_runtime_disable; + return ret; ret = spi_geni_init(mas); if (ret) - goto spi_geni_probe_runtime_disable; + return ret; /* * check the mode supported and set_cs for fifo mode only * for dma (gsi) mode, the gsi will set cs based on params passed in * TRE */ - if (mas->cur_xfer_mode == GENI_SE_FIFO) + if (!spi->target && mas->cur_xfer_mode == GENI_SE_FIFO) spi->set_cs = spi_geni_set_cs; - ret = request_irq(mas->irq, geni_spi_isr, 0, dev_name(dev), spi); - if (ret) - goto spi_geni_release_dma; + /* + * TX is required per GSI spec, see setup_gsi_xfer(). + */ + if (mas->cur_xfer_mode == GENI_GPI_DMA) + spi->flags = SPI_CONTROLLER_MUST_TX; - ret = spi_register_master(spi); + ret = devm_request_irq(dev, mas->irq, geni_spi_isr, 0, dev_name(dev), spi); if (ret) - goto spi_geni_probe_free_irq; - - return 0; -spi_geni_probe_free_irq: - free_irq(mas->irq, spi); -spi_geni_release_dma: - spi_geni_release_dma_chan(mas); -spi_geni_probe_runtime_disable: - pm_runtime_disable(dev); - return ret; -} - -static int spi_geni_remove(struct platform_device *pdev) -{ - struct spi_master *spi = platform_get_drvdata(pdev); - struct spi_geni_master *mas = spi_master_get_devdata(spi); - - /* Unregister _before_ disabling pm_runtime() so we stop transfers */ - spi_unregister_master(spi); - - spi_geni_release_dma_chan(mas); + return ret; - free_irq(mas->irq, spi); - pm_runtime_disable(&pdev->dev); - return 0; + return devm_spi_register_controller(dev, spi); } static int __maybe_unused spi_geni_runtime_suspend(struct device *dev) { - struct spi_master *spi = dev_get_drvdata(dev); - struct spi_geni_master *mas = spi_master_get_devdata(spi); + struct spi_controller *spi = dev_get_drvdata(dev); + struct spi_geni_master *mas = spi_controller_get_devdata(spi); int ret; /* Drop the performance state vote */ @@ -1028,8 +1187,8 @@ static int __maybe_unused spi_geni_runtime_suspend(struct device *dev) static int __maybe_unused spi_geni_runtime_resume(struct device *dev) { - struct spi_master *spi = dev_get_drvdata(dev); - struct spi_geni_master *mas = spi_master_get_devdata(spi); + struct spi_controller *spi = dev_get_drvdata(dev); + struct spi_geni_master *mas = spi_controller_get_devdata(spi); int ret; ret = geni_icc_enable(&mas->se); @@ -1045,30 +1204,30 @@ static int __maybe_unused spi_geni_runtime_resume(struct device *dev) static int __maybe_unused spi_geni_suspend(struct device *dev) { - struct spi_master *spi = dev_get_drvdata(dev); + struct spi_controller *spi = dev_get_drvdata(dev); int ret; - ret = spi_master_suspend(spi); + ret = spi_controller_suspend(spi); if (ret) return ret; ret = pm_runtime_force_suspend(dev); if (ret) - spi_master_resume(spi); + spi_controller_resume(spi); return ret; } static int __maybe_unused spi_geni_resume(struct device *dev) { - struct spi_master *spi = dev_get_drvdata(dev); + struct spi_controller *spi = dev_get_drvdata(dev); int ret; ret = pm_runtime_force_resume(dev); if (ret) return ret; - ret = spi_master_resume(spi); + ret = spi_controller_resume(spi); if (ret) pm_runtime_force_suspend(dev); @@ -1089,7 +1248,6 @@ MODULE_DEVICE_TABLE(of, spi_geni_dt_match); static struct platform_driver spi_geni_driver = { .probe = spi_geni_probe, - .remove = spi_geni_remove, .driver = { .name = "geni_spi", .pm = &spi_geni_pm_ops, |
