Loading drivers/spi/spi-imx.c +183 −158 Original line number Diff line number Diff line Loading @@ -56,7 +56,6 @@ /* The maximum bytes that a sdma BD can transfer.*/ #define MAX_SDMA_BD_BYTES (1 << 15) #define IMX_DMA_TIMEOUT (msecs_to_jiffies(3000)) struct spi_imx_config { unsigned int speed_hz; unsigned int bpw; Loading Loading @@ -86,12 +85,18 @@ struct spi_imx_devtype_data { struct spi_imx_data { struct spi_bitbang bitbang; struct device *dev; struct completion xfer_done; void __iomem *base; unsigned long base_phys; struct clk *clk_per; struct clk *clk_ipg; unsigned long spi_clk; unsigned int spi_bus_clk; unsigned int bytes_per_word; unsigned int count; void (*tx)(struct spi_imx_data *); Loading @@ -101,8 +106,6 @@ struct spi_imx_data { unsigned int txfifo; /* number of words pushed in tx FIFO */ /* DMA */ unsigned int dma_is_inited; unsigned int dma_finished; bool usedma; u32 wml; struct completion dma_rx_completion; Loading Loading @@ -199,15 +202,35 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin, return 7; } static int spi_imx_bytes_per_word(const int bpw) { return DIV_ROUND_UP(bpw, BITS_PER_BYTE); } static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, struct spi_transfer *transfer) { struct spi_imx_data *spi_imx = spi_master_get_devdata(master); unsigned int bpw = transfer->bits_per_word; if (spi_imx->dma_is_inited && transfer->len >= spi_imx->wml && (transfer->len % spi_imx->wml) == 0) return true; if (!master->dma_rx) return false; if (!bpw) bpw = spi->bits_per_word; bpw = spi_imx_bytes_per_word(bpw); if (bpw != 1 && bpw != 2 && bpw != 4) return false; if (transfer->len < spi_imx->wml * bpw) return false; if (transfer->len % (spi_imx->wml * bpw)) return false; return true; } #define MX51_ECSPI_CTRL 0x08 Loading @@ -232,16 +255,13 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, #define MX51_ECSPI_INT_RREN (1 << 3) #define MX51_ECSPI_DMA 0x14 #define MX51_ECSPI_DMA_TX_WML_OFFSET 0 #define MX51_ECSPI_DMA_TX_WML_MASK 0x3F #define MX51_ECSPI_DMA_RX_WML_OFFSET 16 #define MX51_ECSPI_DMA_RX_WML_MASK (0x3F << 16) #define MX51_ECSPI_DMA_RXT_WML_OFFSET 24 #define MX51_ECSPI_DMA_RXT_WML_MASK (0x3F << 24) #define MX51_ECSPI_DMA_TX_WML(wml) ((wml) & 0x3f) #define MX51_ECSPI_DMA_RX_WML(wml) (((wml) & 0x3f) << 16) #define MX51_ECSPI_DMA_RXT_WML(wml) (((wml) & 0x3f) << 24) #define MX51_ECSPI_DMA_TEDEN_OFFSET 7 #define MX51_ECSPI_DMA_RXDEN_OFFSET 23 #define MX51_ECSPI_DMA_RXTDEN_OFFSET 31 #define MX51_ECSPI_DMA_TEDEN (1 << 7) #define MX51_ECSPI_DMA_RXDEN (1 << 23) #define MX51_ECSPI_DMA_RXTDEN (1 << 31) #define MX51_ECSPI_STAT 0x18 #define MX51_ECSPI_STAT_RR (1 << 3) Loading @@ -250,14 +270,15 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, #define MX51_ECSPI_TESTREG_LBC BIT(31) /* MX51 eCSPI */ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi, unsigned int *fres) static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx, unsigned int fspi, unsigned int *fres) { /* * there are two 4-bit dividers, the pre-divider divides by * $pre, the post-divider by 2^$post */ unsigned int pre, post; unsigned int fin = spi_imx->spi_clk; if (unlikely(fspi > fin)) return 0; Loading @@ -270,14 +291,14 @@ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi, post = max(4U, post) - 4; if (unlikely(post > 0xf)) { pr_err("%s: cannot set clock freq: %u (base freq: %u)\n", __func__, fspi, fin); dev_err(spi_imx->dev, "cannot set clock freq: %u (base freq: %u)\n", fspi, fin); return 0xff; } pre = DIV_ROUND_UP(fin, fspi << post) - 1; pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n", dev_dbg(spi_imx->dev, "%s: fin: %u, fspi: %u, post: %u, pre: %u\n", __func__, fin, fspi, post, pre); /* Resulting frequency for the SCLK line. */ Loading @@ -302,22 +323,17 @@ static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx) { u32 reg = readl(spi_imx->base + MX51_ECSPI_CTRL); u32 reg; if (!spi_imx->usedma) reg = readl(spi_imx->base + MX51_ECSPI_CTRL); reg |= MX51_ECSPI_CTRL_XCH; else if (!spi_imx->dma_finished) reg |= MX51_ECSPI_CTRL_SMC; else reg &= ~MX51_ECSPI_CTRL_SMC; writel(reg, spi_imx->base + MX51_ECSPI_CTRL); } static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, struct spi_imx_config *config) { u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0; u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg; u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0; u32 clk = config->speed_hz, delay, reg; /* Loading @@ -330,7 +346,8 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, ctrl |= MX51_ECSPI_CTRL_MODE_MASK; /* set clock speed */ ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, &clk); ctrl |= mx51_ecspi_clkdiv(spi_imx, config->speed_hz, &clk); spi_imx->spi_bus_clk = clk; /* set chip select to use */ ctrl |= MX51_ECSPI_CTRL_CS(config->cs); Loading @@ -341,20 +358,16 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, if (config->mode & SPI_CPHA) cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs); else cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(config->cs); if (config->mode & SPI_CPOL) { cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs); cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs); } else { cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(config->cs); cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(config->cs); } if (config->mode & SPI_CS_HIGH) cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs); else cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs); if (spi_imx->usedma) ctrl |= MX51_ECSPI_CTRL_SMC; /* CTRL register always go first to bring out controller from reset */ writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); Loading Loading @@ -389,22 +402,12 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, * Configure the DMA register: setup the watermark * and enable DMA request. */ if (spi_imx->dma_is_inited) { dma = readl(spi_imx->base + MX51_ECSPI_DMA); rx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RX_WML_OFFSET; tx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_TX_WML_OFFSET; rxt_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET; dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK & ~MX51_ECSPI_DMA_RX_WML_MASK & ~MX51_ECSPI_DMA_RXT_WML_MASK) | rx_wml_cfg | tx_wml_cfg | rxt_wml_cfg |(1 << MX51_ECSPI_DMA_TEDEN_OFFSET) |(1 << MX51_ECSPI_DMA_RXDEN_OFFSET) |(1 << MX51_ECSPI_DMA_RXTDEN_OFFSET); writel(dma, spi_imx->base + MX51_ECSPI_DMA); } writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml) | MX51_ECSPI_DMA_TX_WML(spi_imx->wml) | MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) | MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN | MX51_ECSPI_DMA_RXTDEN, spi_imx->base + MX51_ECSPI_DMA); return 0; } Loading Loading @@ -784,11 +787,63 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id) return IRQ_HANDLED; } static int spi_imx_dma_configure(struct spi_master *master, int bytes_per_word) { int ret; enum dma_slave_buswidth buswidth; struct dma_slave_config rx = {}, tx = {}; struct spi_imx_data *spi_imx = spi_master_get_devdata(master); if (bytes_per_word == spi_imx->bytes_per_word) /* Same as last time */ return 0; switch (bytes_per_word) { case 4: buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; break; case 2: buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; break; case 1: buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; break; default: return -EINVAL; } tx.direction = DMA_MEM_TO_DEV; tx.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA; tx.dst_addr_width = buswidth; tx.dst_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_tx, &tx); if (ret) { dev_err(spi_imx->dev, "TX dma configuration failed with %d\n", ret); return ret; } rx.direction = DMA_DEV_TO_MEM; rx.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA; rx.src_addr_width = buswidth; rx.src_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_rx, &rx); if (ret) { dev_err(spi_imx->dev, "RX dma configuration failed with %d\n", ret); return ret; } spi_imx->bytes_per_word = bytes_per_word; return 0; } static int spi_imx_setupxfer(struct spi_device *spi, struct spi_transfer *t) { struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); struct spi_imx_config config; int ret; config.bpw = t ? t->bits_per_word : spi->bits_per_word; config.speed_hz = t ? t->speed_hz : spi->max_speed_hz; Loading @@ -812,6 +867,18 @@ static int spi_imx_setupxfer(struct spi_device *spi, spi_imx->tx = spi_imx_buf_tx_u32; } if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t)) spi_imx->usedma = 1; else spi_imx->usedma = 0; if (spi_imx->usedma) { ret = spi_imx_dma_configure(spi->master, spi_imx_bytes_per_word(config.bpw)); if (ret) return ret; } spi_imx->devtype_data->config(spi_imx, &config); return 0; Loading @@ -830,15 +897,11 @@ static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx) dma_release_channel(master->dma_tx); master->dma_tx = NULL; } spi_imx->dma_is_inited = 0; } static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, struct spi_master *master, const struct resource *res) struct spi_master *master) { struct dma_slave_config slave_config = {}; int ret; /* use pio mode for i.mx6dl chip TKT238285 */ Loading @@ -856,16 +919,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, goto err; } slave_config.direction = DMA_MEM_TO_DEV; slave_config.dst_addr = res->start + MXC_CSPITXDATA; slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.dst_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_tx, &slave_config); if (ret) { dev_err(dev, "error in TX dma configuration.\n"); goto err; } /* Prepare for RX : */ master->dma_rx = dma_request_slave_channel_reason(dev, "rx"); if (IS_ERR(master->dma_rx)) { Loading @@ -875,15 +928,7 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, goto err; } slave_config.direction = DMA_DEV_TO_MEM; slave_config.src_addr = res->start + MXC_CSPIRXDATA; slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.src_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_rx, &slave_config); if (ret) { dev_err(dev, "error in RX dma configuration.\n"); goto err; } spi_imx_dma_configure(master, 1); init_completion(&spi_imx->dma_rx_completion); init_completion(&spi_imx->dma_tx_completion); Loading @@ -891,7 +936,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, master->max_dma_len = MAX_SDMA_BD_BYTES; spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; spi_imx->dma_is_inited = 1; return 0; err: Loading @@ -913,95 +957,81 @@ static void spi_imx_dma_tx_callback(void *cookie) complete(&spi_imx->dma_tx_completion); } static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size) { unsigned long timeout = 0; /* Time with actual data transfer and CS change delay related to HW */ timeout = (8 + 4) * size / spi_imx->spi_bus_clk; /* Add extra second for scheduler related activities */ timeout += 1; /* Double calculated timeout */ return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC); } static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, struct spi_transfer *transfer) { struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL; int ret; struct dma_async_tx_descriptor *desc_tx, *desc_rx; unsigned long transfer_timeout; unsigned long timeout; struct spi_master *master = spi_imx->bitbang.master; struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg; if (tx) { desc_tx = dmaengine_prep_slave_sg(master->dma_tx, tx->sgl, tx->nents, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) goto tx_nodma; desc_tx->callback = spi_imx_dma_tx_callback; desc_tx->callback_param = (void *)spi_imx; dmaengine_submit(desc_tx); } if (rx) { /* * The TX DMA setup starts the transfer, so make sure RX is configured * before TX. */ desc_rx = dmaengine_prep_slave_sg(master->dma_rx, rx->sgl, rx->nents, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_rx) goto rx_nodma; return -EINVAL; desc_rx->callback = spi_imx_dma_rx_callback; desc_rx->callback_param = (void *)spi_imx; dmaengine_submit(desc_rx); } reinit_completion(&spi_imx->dma_rx_completion); reinit_completion(&spi_imx->dma_tx_completion); dma_async_issue_pending(master->dma_rx); /* Trigger the cspi module. */ spi_imx->dma_finished = 0; desc_tx = dmaengine_prep_slave_sg(master->dma_tx, tx->sgl, tx->nents, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) { dmaengine_terminate_all(master->dma_tx); return -EINVAL; } /* * Set these order to avoid potential RX overflow. The overflow may * happen if we enable SPI HW before starting RX DMA due to rescheduling * for another task and/or interrupt. * So RX DMA enabled first to make sure data would be read out from FIFO * ASAP. TX DMA enabled next to start filling TX FIFO with new data. * And finaly SPI HW enabled to start actual data transfer. */ dma_async_issue_pending(master->dma_rx); desc_tx->callback = spi_imx_dma_tx_callback; desc_tx->callback_param = (void *)spi_imx; dmaengine_submit(desc_tx); reinit_completion(&spi_imx->dma_tx_completion); dma_async_issue_pending(master->dma_tx); spi_imx->devtype_data->trigger(spi_imx); transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len); /* Wait SDMA to finish the data transfer.*/ timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion, IMX_DMA_TIMEOUT); transfer_timeout); if (!timeout) { pr_warn("%s %s: I/O Error in DMA TX\n", dev_driver_string(&master->dev), dev_name(&master->dev)); dev_err(spi_imx->dev, "I/O Error in DMA TX\n"); dmaengine_terminate_all(master->dma_tx); dmaengine_terminate_all(master->dma_rx); } else { timeout = wait_for_completion_timeout( &spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT); return -ETIMEDOUT; } timeout = wait_for_completion_timeout(&spi_imx->dma_rx_completion, transfer_timeout); if (!timeout) { pr_warn("%s %s: I/O Error in DMA RX\n", dev_driver_string(&master->dev), dev_name(&master->dev)); dev_err(&master->dev, "I/O Error in DMA RX\n"); spi_imx->devtype_data->reset(spi_imx); dmaengine_terminate_all(master->dma_rx); return -ETIMEDOUT; } } spi_imx->dma_finished = 1; spi_imx->devtype_data->trigger(spi_imx); if (!timeout) ret = -ETIMEDOUT; else ret = transfer->len; return ret; rx_nodma: dmaengine_terminate_all(master->dma_tx); tx_nodma: pr_warn_once("%s %s: DMA not available, falling back to PIO\n", dev_driver_string(&master->dev), dev_name(&master->dev)); return -EAGAIN; return transfer->len; } static int spi_imx_pio_transfer(struct spi_device *spi, Loading @@ -1028,18 +1058,11 @@ static int spi_imx_pio_transfer(struct spi_device *spi, static int spi_imx_transfer(struct spi_device *spi, struct spi_transfer *transfer) { int ret; struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); if (spi_imx->bitbang.master->can_dma && spi_imx_can_dma(spi_imx->bitbang.master, spi, transfer)) { spi_imx->usedma = true; ret = spi_imx_dma_transfer(spi_imx, transfer); if (ret != -EAGAIN) return ret; } spi_imx->usedma = false; if (spi_imx->usedma) return spi_imx_dma_transfer(spi_imx, transfer); else return spi_imx_pio_transfer(spi, transfer); } Loading Loading @@ -1130,6 +1153,7 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx = spi_master_get_devdata(master); spi_imx->bitbang.master = master; spi_imx->dev = &pdev->dev; spi_imx->devtype_data = of_id ? of_id->data : (struct spi_imx_devtype_data *)pdev->id_entry->driver_data; Loading Loading @@ -1170,6 +1194,7 @@ static int spi_imx_probe(struct platform_device *pdev) ret = PTR_ERR(spi_imx->base); goto out_master_put; } spi_imx->base_phys = res->start; irq = platform_get_irq(pdev, 0); if (irq < 0) { Loading Loading @@ -1210,7 +1235,7 @@ static int spi_imx_probe(struct platform_device *pdev) * other chips. */ if (is_imx51_ecspi(spi_imx)) { ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master, res); ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master); if (ret == -EPROBE_DEFER) goto out_clk_put; Loading Loading
drivers/spi/spi-imx.c +183 −158 Original line number Diff line number Diff line Loading @@ -56,7 +56,6 @@ /* The maximum bytes that a sdma BD can transfer.*/ #define MAX_SDMA_BD_BYTES (1 << 15) #define IMX_DMA_TIMEOUT (msecs_to_jiffies(3000)) struct spi_imx_config { unsigned int speed_hz; unsigned int bpw; Loading Loading @@ -86,12 +85,18 @@ struct spi_imx_devtype_data { struct spi_imx_data { struct spi_bitbang bitbang; struct device *dev; struct completion xfer_done; void __iomem *base; unsigned long base_phys; struct clk *clk_per; struct clk *clk_ipg; unsigned long spi_clk; unsigned int spi_bus_clk; unsigned int bytes_per_word; unsigned int count; void (*tx)(struct spi_imx_data *); Loading @@ -101,8 +106,6 @@ struct spi_imx_data { unsigned int txfifo; /* number of words pushed in tx FIFO */ /* DMA */ unsigned int dma_is_inited; unsigned int dma_finished; bool usedma; u32 wml; struct completion dma_rx_completion; Loading Loading @@ -199,15 +202,35 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin, return 7; } static int spi_imx_bytes_per_word(const int bpw) { return DIV_ROUND_UP(bpw, BITS_PER_BYTE); } static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, struct spi_transfer *transfer) { struct spi_imx_data *spi_imx = spi_master_get_devdata(master); unsigned int bpw = transfer->bits_per_word; if (spi_imx->dma_is_inited && transfer->len >= spi_imx->wml && (transfer->len % spi_imx->wml) == 0) return true; if (!master->dma_rx) return false; if (!bpw) bpw = spi->bits_per_word; bpw = spi_imx_bytes_per_word(bpw); if (bpw != 1 && bpw != 2 && bpw != 4) return false; if (transfer->len < spi_imx->wml * bpw) return false; if (transfer->len % (spi_imx->wml * bpw)) return false; return true; } #define MX51_ECSPI_CTRL 0x08 Loading @@ -232,16 +255,13 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, #define MX51_ECSPI_INT_RREN (1 << 3) #define MX51_ECSPI_DMA 0x14 #define MX51_ECSPI_DMA_TX_WML_OFFSET 0 #define MX51_ECSPI_DMA_TX_WML_MASK 0x3F #define MX51_ECSPI_DMA_RX_WML_OFFSET 16 #define MX51_ECSPI_DMA_RX_WML_MASK (0x3F << 16) #define MX51_ECSPI_DMA_RXT_WML_OFFSET 24 #define MX51_ECSPI_DMA_RXT_WML_MASK (0x3F << 24) #define MX51_ECSPI_DMA_TX_WML(wml) ((wml) & 0x3f) #define MX51_ECSPI_DMA_RX_WML(wml) (((wml) & 0x3f) << 16) #define MX51_ECSPI_DMA_RXT_WML(wml) (((wml) & 0x3f) << 24) #define MX51_ECSPI_DMA_TEDEN_OFFSET 7 #define MX51_ECSPI_DMA_RXDEN_OFFSET 23 #define MX51_ECSPI_DMA_RXTDEN_OFFSET 31 #define MX51_ECSPI_DMA_TEDEN (1 << 7) #define MX51_ECSPI_DMA_RXDEN (1 << 23) #define MX51_ECSPI_DMA_RXTDEN (1 << 31) #define MX51_ECSPI_STAT 0x18 #define MX51_ECSPI_STAT_RR (1 << 3) Loading @@ -250,14 +270,15 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, #define MX51_ECSPI_TESTREG_LBC BIT(31) /* MX51 eCSPI */ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi, unsigned int *fres) static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx, unsigned int fspi, unsigned int *fres) { /* * there are two 4-bit dividers, the pre-divider divides by * $pre, the post-divider by 2^$post */ unsigned int pre, post; unsigned int fin = spi_imx->spi_clk; if (unlikely(fspi > fin)) return 0; Loading @@ -270,14 +291,14 @@ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi, post = max(4U, post) - 4; if (unlikely(post > 0xf)) { pr_err("%s: cannot set clock freq: %u (base freq: %u)\n", __func__, fspi, fin); dev_err(spi_imx->dev, "cannot set clock freq: %u (base freq: %u)\n", fspi, fin); return 0xff; } pre = DIV_ROUND_UP(fin, fspi << post) - 1; pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n", dev_dbg(spi_imx->dev, "%s: fin: %u, fspi: %u, post: %u, pre: %u\n", __func__, fin, fspi, post, pre); /* Resulting frequency for the SCLK line. */ Loading @@ -302,22 +323,17 @@ static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx) { u32 reg = readl(spi_imx->base + MX51_ECSPI_CTRL); u32 reg; if (!spi_imx->usedma) reg = readl(spi_imx->base + MX51_ECSPI_CTRL); reg |= MX51_ECSPI_CTRL_XCH; else if (!spi_imx->dma_finished) reg |= MX51_ECSPI_CTRL_SMC; else reg &= ~MX51_ECSPI_CTRL_SMC; writel(reg, spi_imx->base + MX51_ECSPI_CTRL); } static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, struct spi_imx_config *config) { u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0; u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg; u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0; u32 clk = config->speed_hz, delay, reg; /* Loading @@ -330,7 +346,8 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, ctrl |= MX51_ECSPI_CTRL_MODE_MASK; /* set clock speed */ ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, &clk); ctrl |= mx51_ecspi_clkdiv(spi_imx, config->speed_hz, &clk); spi_imx->spi_bus_clk = clk; /* set chip select to use */ ctrl |= MX51_ECSPI_CTRL_CS(config->cs); Loading @@ -341,20 +358,16 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, if (config->mode & SPI_CPHA) cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs); else cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(config->cs); if (config->mode & SPI_CPOL) { cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs); cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs); } else { cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(config->cs); cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(config->cs); } if (config->mode & SPI_CS_HIGH) cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs); else cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs); if (spi_imx->usedma) ctrl |= MX51_ECSPI_CTRL_SMC; /* CTRL register always go first to bring out controller from reset */ writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); Loading Loading @@ -389,22 +402,12 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, * Configure the DMA register: setup the watermark * and enable DMA request. */ if (spi_imx->dma_is_inited) { dma = readl(spi_imx->base + MX51_ECSPI_DMA); rx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RX_WML_OFFSET; tx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_TX_WML_OFFSET; rxt_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET; dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK & ~MX51_ECSPI_DMA_RX_WML_MASK & ~MX51_ECSPI_DMA_RXT_WML_MASK) | rx_wml_cfg | tx_wml_cfg | rxt_wml_cfg |(1 << MX51_ECSPI_DMA_TEDEN_OFFSET) |(1 << MX51_ECSPI_DMA_RXDEN_OFFSET) |(1 << MX51_ECSPI_DMA_RXTDEN_OFFSET); writel(dma, spi_imx->base + MX51_ECSPI_DMA); } writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml) | MX51_ECSPI_DMA_TX_WML(spi_imx->wml) | MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) | MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN | MX51_ECSPI_DMA_RXTDEN, spi_imx->base + MX51_ECSPI_DMA); return 0; } Loading Loading @@ -784,11 +787,63 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id) return IRQ_HANDLED; } static int spi_imx_dma_configure(struct spi_master *master, int bytes_per_word) { int ret; enum dma_slave_buswidth buswidth; struct dma_slave_config rx = {}, tx = {}; struct spi_imx_data *spi_imx = spi_master_get_devdata(master); if (bytes_per_word == spi_imx->bytes_per_word) /* Same as last time */ return 0; switch (bytes_per_word) { case 4: buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; break; case 2: buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; break; case 1: buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; break; default: return -EINVAL; } tx.direction = DMA_MEM_TO_DEV; tx.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA; tx.dst_addr_width = buswidth; tx.dst_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_tx, &tx); if (ret) { dev_err(spi_imx->dev, "TX dma configuration failed with %d\n", ret); return ret; } rx.direction = DMA_DEV_TO_MEM; rx.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA; rx.src_addr_width = buswidth; rx.src_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_rx, &rx); if (ret) { dev_err(spi_imx->dev, "RX dma configuration failed with %d\n", ret); return ret; } spi_imx->bytes_per_word = bytes_per_word; return 0; } static int spi_imx_setupxfer(struct spi_device *spi, struct spi_transfer *t) { struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); struct spi_imx_config config; int ret; config.bpw = t ? t->bits_per_word : spi->bits_per_word; config.speed_hz = t ? t->speed_hz : spi->max_speed_hz; Loading @@ -812,6 +867,18 @@ static int spi_imx_setupxfer(struct spi_device *spi, spi_imx->tx = spi_imx_buf_tx_u32; } if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t)) spi_imx->usedma = 1; else spi_imx->usedma = 0; if (spi_imx->usedma) { ret = spi_imx_dma_configure(spi->master, spi_imx_bytes_per_word(config.bpw)); if (ret) return ret; } spi_imx->devtype_data->config(spi_imx, &config); return 0; Loading @@ -830,15 +897,11 @@ static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx) dma_release_channel(master->dma_tx); master->dma_tx = NULL; } spi_imx->dma_is_inited = 0; } static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, struct spi_master *master, const struct resource *res) struct spi_master *master) { struct dma_slave_config slave_config = {}; int ret; /* use pio mode for i.mx6dl chip TKT238285 */ Loading @@ -856,16 +919,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, goto err; } slave_config.direction = DMA_MEM_TO_DEV; slave_config.dst_addr = res->start + MXC_CSPITXDATA; slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.dst_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_tx, &slave_config); if (ret) { dev_err(dev, "error in TX dma configuration.\n"); goto err; } /* Prepare for RX : */ master->dma_rx = dma_request_slave_channel_reason(dev, "rx"); if (IS_ERR(master->dma_rx)) { Loading @@ -875,15 +928,7 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, goto err; } slave_config.direction = DMA_DEV_TO_MEM; slave_config.src_addr = res->start + MXC_CSPIRXDATA; slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.src_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_rx, &slave_config); if (ret) { dev_err(dev, "error in RX dma configuration.\n"); goto err; } spi_imx_dma_configure(master, 1); init_completion(&spi_imx->dma_rx_completion); init_completion(&spi_imx->dma_tx_completion); Loading @@ -891,7 +936,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, master->max_dma_len = MAX_SDMA_BD_BYTES; spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; spi_imx->dma_is_inited = 1; return 0; err: Loading @@ -913,95 +957,81 @@ static void spi_imx_dma_tx_callback(void *cookie) complete(&spi_imx->dma_tx_completion); } static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size) { unsigned long timeout = 0; /* Time with actual data transfer and CS change delay related to HW */ timeout = (8 + 4) * size / spi_imx->spi_bus_clk; /* Add extra second for scheduler related activities */ timeout += 1; /* Double calculated timeout */ return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC); } static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, struct spi_transfer *transfer) { struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL; int ret; struct dma_async_tx_descriptor *desc_tx, *desc_rx; unsigned long transfer_timeout; unsigned long timeout; struct spi_master *master = spi_imx->bitbang.master; struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg; if (tx) { desc_tx = dmaengine_prep_slave_sg(master->dma_tx, tx->sgl, tx->nents, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) goto tx_nodma; desc_tx->callback = spi_imx_dma_tx_callback; desc_tx->callback_param = (void *)spi_imx; dmaengine_submit(desc_tx); } if (rx) { /* * The TX DMA setup starts the transfer, so make sure RX is configured * before TX. */ desc_rx = dmaengine_prep_slave_sg(master->dma_rx, rx->sgl, rx->nents, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_rx) goto rx_nodma; return -EINVAL; desc_rx->callback = spi_imx_dma_rx_callback; desc_rx->callback_param = (void *)spi_imx; dmaengine_submit(desc_rx); } reinit_completion(&spi_imx->dma_rx_completion); reinit_completion(&spi_imx->dma_tx_completion); dma_async_issue_pending(master->dma_rx); /* Trigger the cspi module. */ spi_imx->dma_finished = 0; desc_tx = dmaengine_prep_slave_sg(master->dma_tx, tx->sgl, tx->nents, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc_tx) { dmaengine_terminate_all(master->dma_tx); return -EINVAL; } /* * Set these order to avoid potential RX overflow. The overflow may * happen if we enable SPI HW before starting RX DMA due to rescheduling * for another task and/or interrupt. * So RX DMA enabled first to make sure data would be read out from FIFO * ASAP. TX DMA enabled next to start filling TX FIFO with new data. * And finaly SPI HW enabled to start actual data transfer. */ dma_async_issue_pending(master->dma_rx); desc_tx->callback = spi_imx_dma_tx_callback; desc_tx->callback_param = (void *)spi_imx; dmaengine_submit(desc_tx); reinit_completion(&spi_imx->dma_tx_completion); dma_async_issue_pending(master->dma_tx); spi_imx->devtype_data->trigger(spi_imx); transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len); /* Wait SDMA to finish the data transfer.*/ timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion, IMX_DMA_TIMEOUT); transfer_timeout); if (!timeout) { pr_warn("%s %s: I/O Error in DMA TX\n", dev_driver_string(&master->dev), dev_name(&master->dev)); dev_err(spi_imx->dev, "I/O Error in DMA TX\n"); dmaengine_terminate_all(master->dma_tx); dmaengine_terminate_all(master->dma_rx); } else { timeout = wait_for_completion_timeout( &spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT); return -ETIMEDOUT; } timeout = wait_for_completion_timeout(&spi_imx->dma_rx_completion, transfer_timeout); if (!timeout) { pr_warn("%s %s: I/O Error in DMA RX\n", dev_driver_string(&master->dev), dev_name(&master->dev)); dev_err(&master->dev, "I/O Error in DMA RX\n"); spi_imx->devtype_data->reset(spi_imx); dmaengine_terminate_all(master->dma_rx); return -ETIMEDOUT; } } spi_imx->dma_finished = 1; spi_imx->devtype_data->trigger(spi_imx); if (!timeout) ret = -ETIMEDOUT; else ret = transfer->len; return ret; rx_nodma: dmaengine_terminate_all(master->dma_tx); tx_nodma: pr_warn_once("%s %s: DMA not available, falling back to PIO\n", dev_driver_string(&master->dev), dev_name(&master->dev)); return -EAGAIN; return transfer->len; } static int spi_imx_pio_transfer(struct spi_device *spi, Loading @@ -1028,18 +1058,11 @@ static int spi_imx_pio_transfer(struct spi_device *spi, static int spi_imx_transfer(struct spi_device *spi, struct spi_transfer *transfer) { int ret; struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); if (spi_imx->bitbang.master->can_dma && spi_imx_can_dma(spi_imx->bitbang.master, spi, transfer)) { spi_imx->usedma = true; ret = spi_imx_dma_transfer(spi_imx, transfer); if (ret != -EAGAIN) return ret; } spi_imx->usedma = false; if (spi_imx->usedma) return spi_imx_dma_transfer(spi_imx, transfer); else return spi_imx_pio_transfer(spi, transfer); } Loading Loading @@ -1130,6 +1153,7 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx = spi_master_get_devdata(master); spi_imx->bitbang.master = master; spi_imx->dev = &pdev->dev; spi_imx->devtype_data = of_id ? of_id->data : (struct spi_imx_devtype_data *)pdev->id_entry->driver_data; Loading Loading @@ -1170,6 +1194,7 @@ static int spi_imx_probe(struct platform_device *pdev) ret = PTR_ERR(spi_imx->base); goto out_master_put; } spi_imx->base_phys = res->start; irq = platform_get_irq(pdev, 0); if (irq < 0) { Loading Loading @@ -1210,7 +1235,7 @@ static int spi_imx_probe(struct platform_device *pdev) * other chips. */ if (is_imx51_ecspi(spi_imx)) { ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master, res); ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master); if (ret == -EPROBE_DEFER) goto out_clk_put; Loading