Loading drivers/spi/spi-dw-mid.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -283,7 +283,7 @@ static void mid_spi_dma_stop(struct dw_spi *dws) } } } } static struct dw_spi_dma_ops mid_dma_ops = { static const struct dw_spi_dma_ops mid_dma_ops = { .dma_init = mid_spi_dma_init, .dma_init = mid_spi_dma_init, .dma_exit = mid_spi_dma_exit, .dma_exit = mid_spi_dma_exit, .dma_setup = mid_spi_dma_setup, .dma_setup = mid_spi_dma_setup, Loading drivers/spi/spi-dw.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -425,7 +425,7 @@ static int dw_spi_setup(struct spi_device *spi) chip->type = chip_info->type; chip->type = chip_info->type; } } chip->tmode = 0; /* Tx & Rx */ chip->tmode = SPI_TMOD_TR; if (gpio_is_valid(spi->cs_gpio)) { if (gpio_is_valid(spi->cs_gpio)) { ret = gpio_direction_output(spi->cs_gpio, ret = gpio_direction_output(spi->cs_gpio, Loading drivers/spi/spi-dw.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -130,7 +130,7 @@ struct dw_spi { struct dma_chan *rxchan; struct dma_chan *rxchan; unsigned long dma_chan_busy; unsigned long dma_chan_busy; dma_addr_t dma_addr; /* phy address of the Data register */ dma_addr_t dma_addr; /* phy address of the Data register */ struct dw_spi_dma_ops *dma_ops; const struct dw_spi_dma_ops *dma_ops; void *dma_tx; void *dma_tx; void *dma_rx; void *dma_rx; Loading drivers/spi/spi-fsl-espi.c +6 −0 Original line number Original line Diff line number Diff line Loading @@ -643,6 +643,11 @@ static int fsl_espi_runtime_resume(struct device *dev) } } #endif #endif static size_t fsl_espi_max_transfer_size(struct spi_device *spi) { return SPCOM_TRANLEN_MAX; } static struct spi_master * fsl_espi_probe(struct device *dev, static struct spi_master * fsl_espi_probe(struct device *dev, struct resource *mem, unsigned int irq) struct resource *mem, unsigned int irq) { { Loading Loading @@ -670,6 +675,7 @@ static struct spi_master * fsl_espi_probe(struct device *dev, master->cleanup = fsl_espi_cleanup; master->cleanup = fsl_espi_cleanup; master->transfer_one_message = fsl_espi_do_one_msg; master->transfer_one_message = fsl_espi_do_one_msg; master->auto_runtime_pm = true; master->auto_runtime_pm = true; master->max_transfer_size = fsl_espi_max_transfer_size; mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master); Loading drivers/spi/spi-imx.c +67 −34 Original line number Original line Diff line number Diff line Loading @@ -104,9 +104,7 @@ struct spi_imx_data { unsigned int dma_is_inited; unsigned int dma_is_inited; unsigned int dma_finished; unsigned int dma_finished; bool usedma; bool usedma; u32 rx_wml; u32 wml; u32 tx_wml; u32 rxt_wml; struct completion dma_rx_completion; struct completion dma_rx_completion; struct completion dma_tx_completion; struct completion dma_tx_completion; Loading @@ -124,9 +122,14 @@ static inline int is_imx35_cspi(struct spi_imx_data *d) return d->devtype_data->devtype == IMX35_CSPI; return d->devtype_data->devtype == IMX35_CSPI; } } static inline int is_imx51_ecspi(struct spi_imx_data *d) { return d->devtype_data->devtype == IMX51_ECSPI; } static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d) static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d) { { return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8; return is_imx51_ecspi(d) ? 64 : 8; } } #define MXC_SPI_BUF_RX(type) \ #define MXC_SPI_BUF_RX(type) \ Loading Loading @@ -201,9 +204,8 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, { { struct spi_imx_data *spi_imx = spi_master_get_devdata(master); struct spi_imx_data *spi_imx = spi_master_get_devdata(master); if (spi_imx->dma_is_inited if (spi_imx->dma_is_inited && && transfer->len > spi_imx->rx_wml * sizeof(u32) transfer->len > spi_imx->wml * sizeof(u32)) && transfer->len > spi_imx->tx_wml * sizeof(u32)) return true; return true; return false; return false; } } Loading Loading @@ -244,6 +246,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, #define MX51_ECSPI_STAT 0x18 #define MX51_ECSPI_STAT 0x18 #define MX51_ECSPI_STAT_RR (1 << 3) #define MX51_ECSPI_STAT_RR (1 << 3) #define MX51_ECSPI_TESTREG 0x20 #define MX51_ECSPI_TESTREG_LBC BIT(31) /* MX51 eCSPI */ /* MX51 eCSPI */ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi, static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi, unsigned int *fres) unsigned int *fres) Loading Loading @@ -313,7 +318,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, { { u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0; u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0; u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg; u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg; u32 clk = config->speed_hz, delay; u32 clk = config->speed_hz, delay, reg; /* /* * The hardware seems to have a race condition when changing modes. The * The hardware seems to have a race condition when changing modes. The Loading Loading @@ -351,7 +356,16 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, else else cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs); cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs); /* CTRL register always go first to bring out controller from reset */ writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); reg = readl(spi_imx->base + MX51_ECSPI_TESTREG); if (config->mode & SPI_LOOP) reg |= MX51_ECSPI_TESTREG_LBC; else reg &= ~MX51_ECSPI_TESTREG_LBC; writel(reg, spi_imx->base + MX51_ECSPI_TESTREG); writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); /* /* Loading @@ -378,10 +392,9 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, if (spi_imx->dma_is_inited) { if (spi_imx->dma_is_inited) { dma = readl(spi_imx->base + MX51_ECSPI_DMA); dma = readl(spi_imx->base + MX51_ECSPI_DMA); spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2; rx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RX_WML_OFFSET; rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET; tx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_TX_WML_OFFSET; tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET; rxt_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET; rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET; dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK & ~MX51_ECSPI_DMA_RX_WML_MASK & ~MX51_ECSPI_DMA_RX_WML_MASK & ~MX51_ECSPI_DMA_RXT_WML_MASK) & ~MX51_ECSPI_DMA_RXT_WML_MASK) Loading Loading @@ -832,18 +845,21 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, if (of_machine_is_compatible("fsl,imx6dl")) if (of_machine_is_compatible("fsl,imx6dl")) return 0; return 0; spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2; /* Prepare for TX DMA: */ /* Prepare for TX DMA: */ master->dma_tx = dma_request_slave_channel(dev, "tx"); master->dma_tx = dma_request_slave_channel_reason(dev, "tx"); if (!master->dma_tx) { if (IS_ERR(master->dma_tx)) { dev_err(dev, "cannot get the TX DMA channel!\n"); ret = PTR_ERR(master->dma_tx); ret = -EINVAL; dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret); master->dma_tx = NULL; goto err; goto err; } } slave_config.direction = DMA_MEM_TO_DEV; slave_config.direction = DMA_MEM_TO_DEV; slave_config.dst_addr = res->start + MXC_CSPITXDATA; slave_config.dst_addr = res->start + MXC_CSPITXDATA; slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 2; slave_config.dst_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_tx, &slave_config); ret = dmaengine_slave_config(master->dma_tx, &slave_config); if (ret) { if (ret) { dev_err(dev, "error in TX dma configuration.\n"); dev_err(dev, "error in TX dma configuration.\n"); Loading @@ -851,17 +867,18 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, } } /* Prepare for RX : */ /* Prepare for RX : */ master->dma_rx = dma_request_slave_channel(dev, "rx"); master->dma_rx = dma_request_slave_channel_reason(dev, "rx"); if (!master->dma_rx) { if (IS_ERR(master->dma_rx)) { dev_dbg(dev, "cannot get the DMA channel.\n"); ret = PTR_ERR(master->dma_rx); ret = -EINVAL; dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret); master->dma_rx = NULL; goto err; goto err; } } slave_config.direction = DMA_DEV_TO_MEM; slave_config.direction = DMA_DEV_TO_MEM; slave_config.src_addr = res->start + MXC_CSPIRXDATA; slave_config.src_addr = res->start + MXC_CSPIRXDATA; slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2; slave_config.src_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_rx, &slave_config); ret = dmaengine_slave_config(master->dma_rx, &slave_config); if (ret) { if (ret) { dev_err(dev, "error in RX dma configuration.\n"); dev_err(dev, "error in RX dma configuration.\n"); Loading @@ -874,8 +891,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, master->max_dma_len = MAX_SDMA_BD_BYTES; master->max_dma_len = MAX_SDMA_BD_BYTES; spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX | spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; SPI_MASTER_MUST_TX; spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2; spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2; spi_imx->dma_is_inited = 1; spi_imx->dma_is_inited = 1; return 0; return 0; Loading Loading @@ -942,14 +957,22 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, dma = readl(spi_imx->base + MX51_ECSPI_DMA); dma = readl(spi_imx->base + MX51_ECSPI_DMA); dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK); dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK); /* Change RX_DMA_LENGTH trigger dma fetch tail data */ /* Change RX_DMA_LENGTH trigger dma fetch tail data */ left = transfer->len % spi_imx->rxt_wml; left = transfer->len % spi_imx->wml; if (left) if (left) writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET), writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET), spi_imx->base + MX51_ECSPI_DMA); spi_imx->base + MX51_ECSPI_DMA); /* * 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); dma_async_issue_pending(master->dma_tx); spi_imx->devtype_data->trigger(spi_imx); spi_imx->devtype_data->trigger(spi_imx); dma_async_issue_pending(master->dma_tx); dma_async_issue_pending(master->dma_rx); /* Wait SDMA to finish the data transfer.*/ /* Wait SDMA to finish the data transfer.*/ timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion, timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion, IMX_DMA_TIMEOUT); IMX_DMA_TIMEOUT); Loading @@ -958,6 +981,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, dev_driver_string(&master->dev), dev_driver_string(&master->dev), dev_name(&master->dev)); dev_name(&master->dev)); dmaengine_terminate_all(master->dma_tx); dmaengine_terminate_all(master->dma_tx); dmaengine_terminate_all(master->dma_rx); } else { } else { timeout = wait_for_completion_timeout( timeout = wait_for_completion_timeout( &spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT); &spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT); Loading @@ -968,8 +992,9 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, spi_imx->devtype_data->reset(spi_imx); spi_imx->devtype_data->reset(spi_imx); dmaengine_terminate_all(master->dma_rx); dmaengine_terminate_all(master->dma_rx); } } dma &= ~MX51_ECSPI_DMA_RXT_WML_MASK; writel(dma | writel(dma | spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET, spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET, spi_imx->base + MX51_ECSPI_DMA); spi_imx->base + MX51_ECSPI_DMA); } } Loading Loading @@ -1117,6 +1142,9 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx = spi_master_get_devdata(master); spi_imx = spi_master_get_devdata(master); spi_imx->bitbang.master = master; spi_imx->bitbang.master = master; spi_imx->devtype_data = of_id ? of_id->data : (struct spi_imx_devtype_data *)pdev->id_entry->driver_data; for (i = 0; i < master->num_chipselect; i++) { for (i = 0; i < master->num_chipselect; i++) { int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); if (!gpio_is_valid(cs_gpio) && mxc_platform_info) if (!gpio_is_valid(cs_gpio) && mxc_platform_info) Loading @@ -1142,12 +1170,11 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message; spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message; spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; if (is_imx51_ecspi(spi_imx)) spi_imx->bitbang.master->mode_bits |= SPI_LOOP; init_completion(&spi_imx->xfer_done); init_completion(&spi_imx->xfer_done); spi_imx->devtype_data = of_id ? of_id->data : (struct spi_imx_devtype_data *) pdev->id_entry->driver_data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi_imx->base = devm_ioremap_resource(&pdev->dev, res); spi_imx->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(spi_imx->base)) { if (IS_ERR(spi_imx->base)) { Loading Loading @@ -1193,9 +1220,15 @@ static int spi_imx_probe(struct platform_device *pdev) * Only validated on i.mx6 now, can remove the constrain if validated on * Only validated on i.mx6 now, can remove the constrain if validated on * other chips. * other chips. */ */ if (spi_imx->devtype_data == &imx51_ecspi_devtype_data if (is_imx51_ecspi(spi_imx)) { && spi_imx_sdma_init(&pdev->dev, spi_imx, master, res)) ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master, res); dev_err(&pdev->dev, "dma setup error,use pio instead\n"); if (ret == -EPROBE_DEFER) goto out_clk_put; if (ret < 0) dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret); } spi_imx->devtype_data->reset(spi_imx); spi_imx->devtype_data->reset(spi_imx); Loading Loading
drivers/spi/spi-dw-mid.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -283,7 +283,7 @@ static void mid_spi_dma_stop(struct dw_spi *dws) } } } } static struct dw_spi_dma_ops mid_dma_ops = { static const struct dw_spi_dma_ops mid_dma_ops = { .dma_init = mid_spi_dma_init, .dma_init = mid_spi_dma_init, .dma_exit = mid_spi_dma_exit, .dma_exit = mid_spi_dma_exit, .dma_setup = mid_spi_dma_setup, .dma_setup = mid_spi_dma_setup, Loading
drivers/spi/spi-dw.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -425,7 +425,7 @@ static int dw_spi_setup(struct spi_device *spi) chip->type = chip_info->type; chip->type = chip_info->type; } } chip->tmode = 0; /* Tx & Rx */ chip->tmode = SPI_TMOD_TR; if (gpio_is_valid(spi->cs_gpio)) { if (gpio_is_valid(spi->cs_gpio)) { ret = gpio_direction_output(spi->cs_gpio, ret = gpio_direction_output(spi->cs_gpio, Loading
drivers/spi/spi-dw.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -130,7 +130,7 @@ struct dw_spi { struct dma_chan *rxchan; struct dma_chan *rxchan; unsigned long dma_chan_busy; unsigned long dma_chan_busy; dma_addr_t dma_addr; /* phy address of the Data register */ dma_addr_t dma_addr; /* phy address of the Data register */ struct dw_spi_dma_ops *dma_ops; const struct dw_spi_dma_ops *dma_ops; void *dma_tx; void *dma_tx; void *dma_rx; void *dma_rx; Loading
drivers/spi/spi-fsl-espi.c +6 −0 Original line number Original line Diff line number Diff line Loading @@ -643,6 +643,11 @@ static int fsl_espi_runtime_resume(struct device *dev) } } #endif #endif static size_t fsl_espi_max_transfer_size(struct spi_device *spi) { return SPCOM_TRANLEN_MAX; } static struct spi_master * fsl_espi_probe(struct device *dev, static struct spi_master * fsl_espi_probe(struct device *dev, struct resource *mem, unsigned int irq) struct resource *mem, unsigned int irq) { { Loading Loading @@ -670,6 +675,7 @@ static struct spi_master * fsl_espi_probe(struct device *dev, master->cleanup = fsl_espi_cleanup; master->cleanup = fsl_espi_cleanup; master->transfer_one_message = fsl_espi_do_one_msg; master->transfer_one_message = fsl_espi_do_one_msg; master->auto_runtime_pm = true; master->auto_runtime_pm = true; master->max_transfer_size = fsl_espi_max_transfer_size; mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master); Loading
drivers/spi/spi-imx.c +67 −34 Original line number Original line Diff line number Diff line Loading @@ -104,9 +104,7 @@ struct spi_imx_data { unsigned int dma_is_inited; unsigned int dma_is_inited; unsigned int dma_finished; unsigned int dma_finished; bool usedma; bool usedma; u32 rx_wml; u32 wml; u32 tx_wml; u32 rxt_wml; struct completion dma_rx_completion; struct completion dma_rx_completion; struct completion dma_tx_completion; struct completion dma_tx_completion; Loading @@ -124,9 +122,14 @@ static inline int is_imx35_cspi(struct spi_imx_data *d) return d->devtype_data->devtype == IMX35_CSPI; return d->devtype_data->devtype == IMX35_CSPI; } } static inline int is_imx51_ecspi(struct spi_imx_data *d) { return d->devtype_data->devtype == IMX51_ECSPI; } static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d) static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d) { { return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8; return is_imx51_ecspi(d) ? 64 : 8; } } #define MXC_SPI_BUF_RX(type) \ #define MXC_SPI_BUF_RX(type) \ Loading Loading @@ -201,9 +204,8 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, { { struct spi_imx_data *spi_imx = spi_master_get_devdata(master); struct spi_imx_data *spi_imx = spi_master_get_devdata(master); if (spi_imx->dma_is_inited if (spi_imx->dma_is_inited && && transfer->len > spi_imx->rx_wml * sizeof(u32) transfer->len > spi_imx->wml * sizeof(u32)) && transfer->len > spi_imx->tx_wml * sizeof(u32)) return true; return true; return false; return false; } } Loading Loading @@ -244,6 +246,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, #define MX51_ECSPI_STAT 0x18 #define MX51_ECSPI_STAT 0x18 #define MX51_ECSPI_STAT_RR (1 << 3) #define MX51_ECSPI_STAT_RR (1 << 3) #define MX51_ECSPI_TESTREG 0x20 #define MX51_ECSPI_TESTREG_LBC BIT(31) /* MX51 eCSPI */ /* MX51 eCSPI */ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi, static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi, unsigned int *fres) unsigned int *fres) Loading Loading @@ -313,7 +318,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, { { u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0; u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0; u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg; u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg; u32 clk = config->speed_hz, delay; u32 clk = config->speed_hz, delay, reg; /* /* * The hardware seems to have a race condition when changing modes. The * The hardware seems to have a race condition when changing modes. The Loading Loading @@ -351,7 +356,16 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, else else cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs); cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs); /* CTRL register always go first to bring out controller from reset */ writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); reg = readl(spi_imx->base + MX51_ECSPI_TESTREG); if (config->mode & SPI_LOOP) reg |= MX51_ECSPI_TESTREG_LBC; else reg &= ~MX51_ECSPI_TESTREG_LBC; writel(reg, spi_imx->base + MX51_ECSPI_TESTREG); writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); /* /* Loading @@ -378,10 +392,9 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, if (spi_imx->dma_is_inited) { if (spi_imx->dma_is_inited) { dma = readl(spi_imx->base + MX51_ECSPI_DMA); dma = readl(spi_imx->base + MX51_ECSPI_DMA); spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2; rx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RX_WML_OFFSET; rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET; tx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_TX_WML_OFFSET; tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET; rxt_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET; rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET; dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK & ~MX51_ECSPI_DMA_RX_WML_MASK & ~MX51_ECSPI_DMA_RX_WML_MASK & ~MX51_ECSPI_DMA_RXT_WML_MASK) & ~MX51_ECSPI_DMA_RXT_WML_MASK) Loading Loading @@ -832,18 +845,21 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, if (of_machine_is_compatible("fsl,imx6dl")) if (of_machine_is_compatible("fsl,imx6dl")) return 0; return 0; spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2; /* Prepare for TX DMA: */ /* Prepare for TX DMA: */ master->dma_tx = dma_request_slave_channel(dev, "tx"); master->dma_tx = dma_request_slave_channel_reason(dev, "tx"); if (!master->dma_tx) { if (IS_ERR(master->dma_tx)) { dev_err(dev, "cannot get the TX DMA channel!\n"); ret = PTR_ERR(master->dma_tx); ret = -EINVAL; dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret); master->dma_tx = NULL; goto err; goto err; } } slave_config.direction = DMA_MEM_TO_DEV; slave_config.direction = DMA_MEM_TO_DEV; slave_config.dst_addr = res->start + MXC_CSPITXDATA; slave_config.dst_addr = res->start + MXC_CSPITXDATA; slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 2; slave_config.dst_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_tx, &slave_config); ret = dmaengine_slave_config(master->dma_tx, &slave_config); if (ret) { if (ret) { dev_err(dev, "error in TX dma configuration.\n"); dev_err(dev, "error in TX dma configuration.\n"); Loading @@ -851,17 +867,18 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, } } /* Prepare for RX : */ /* Prepare for RX : */ master->dma_rx = dma_request_slave_channel(dev, "rx"); master->dma_rx = dma_request_slave_channel_reason(dev, "rx"); if (!master->dma_rx) { if (IS_ERR(master->dma_rx)) { dev_dbg(dev, "cannot get the DMA channel.\n"); ret = PTR_ERR(master->dma_rx); ret = -EINVAL; dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret); master->dma_rx = NULL; goto err; goto err; } } slave_config.direction = DMA_DEV_TO_MEM; slave_config.direction = DMA_DEV_TO_MEM; slave_config.src_addr = res->start + MXC_CSPIRXDATA; slave_config.src_addr = res->start + MXC_CSPIRXDATA; slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2; slave_config.src_maxburst = spi_imx->wml; ret = dmaengine_slave_config(master->dma_rx, &slave_config); ret = dmaengine_slave_config(master->dma_rx, &slave_config); if (ret) { if (ret) { dev_err(dev, "error in RX dma configuration.\n"); dev_err(dev, "error in RX dma configuration.\n"); Loading @@ -874,8 +891,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, master->max_dma_len = MAX_SDMA_BD_BYTES; master->max_dma_len = MAX_SDMA_BD_BYTES; spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX | spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; SPI_MASTER_MUST_TX; spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2; spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2; spi_imx->dma_is_inited = 1; spi_imx->dma_is_inited = 1; return 0; return 0; Loading Loading @@ -942,14 +957,22 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, dma = readl(spi_imx->base + MX51_ECSPI_DMA); dma = readl(spi_imx->base + MX51_ECSPI_DMA); dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK); dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK); /* Change RX_DMA_LENGTH trigger dma fetch tail data */ /* Change RX_DMA_LENGTH trigger dma fetch tail data */ left = transfer->len % spi_imx->rxt_wml; left = transfer->len % spi_imx->wml; if (left) if (left) writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET), writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET), spi_imx->base + MX51_ECSPI_DMA); spi_imx->base + MX51_ECSPI_DMA); /* * 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); dma_async_issue_pending(master->dma_tx); spi_imx->devtype_data->trigger(spi_imx); spi_imx->devtype_data->trigger(spi_imx); dma_async_issue_pending(master->dma_tx); dma_async_issue_pending(master->dma_rx); /* Wait SDMA to finish the data transfer.*/ /* Wait SDMA to finish the data transfer.*/ timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion, timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion, IMX_DMA_TIMEOUT); IMX_DMA_TIMEOUT); Loading @@ -958,6 +981,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, dev_driver_string(&master->dev), dev_driver_string(&master->dev), dev_name(&master->dev)); dev_name(&master->dev)); dmaengine_terminate_all(master->dma_tx); dmaengine_terminate_all(master->dma_tx); dmaengine_terminate_all(master->dma_rx); } else { } else { timeout = wait_for_completion_timeout( timeout = wait_for_completion_timeout( &spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT); &spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT); Loading @@ -968,8 +992,9 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, spi_imx->devtype_data->reset(spi_imx); spi_imx->devtype_data->reset(spi_imx); dmaengine_terminate_all(master->dma_rx); dmaengine_terminate_all(master->dma_rx); } } dma &= ~MX51_ECSPI_DMA_RXT_WML_MASK; writel(dma | writel(dma | spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET, spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET, spi_imx->base + MX51_ECSPI_DMA); spi_imx->base + MX51_ECSPI_DMA); } } Loading Loading @@ -1117,6 +1142,9 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx = spi_master_get_devdata(master); spi_imx = spi_master_get_devdata(master); spi_imx->bitbang.master = master; spi_imx->bitbang.master = master; spi_imx->devtype_data = of_id ? of_id->data : (struct spi_imx_devtype_data *)pdev->id_entry->driver_data; for (i = 0; i < master->num_chipselect; i++) { for (i = 0; i < master->num_chipselect; i++) { int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); if (!gpio_is_valid(cs_gpio) && mxc_platform_info) if (!gpio_is_valid(cs_gpio) && mxc_platform_info) Loading @@ -1142,12 +1170,11 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message; spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message; spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; if (is_imx51_ecspi(spi_imx)) spi_imx->bitbang.master->mode_bits |= SPI_LOOP; init_completion(&spi_imx->xfer_done); init_completion(&spi_imx->xfer_done); spi_imx->devtype_data = of_id ? of_id->data : (struct spi_imx_devtype_data *) pdev->id_entry->driver_data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi_imx->base = devm_ioremap_resource(&pdev->dev, res); spi_imx->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(spi_imx->base)) { if (IS_ERR(spi_imx->base)) { Loading Loading @@ -1193,9 +1220,15 @@ static int spi_imx_probe(struct platform_device *pdev) * Only validated on i.mx6 now, can remove the constrain if validated on * Only validated on i.mx6 now, can remove the constrain if validated on * other chips. * other chips. */ */ if (spi_imx->devtype_data == &imx51_ecspi_devtype_data if (is_imx51_ecspi(spi_imx)) { && spi_imx_sdma_init(&pdev->dev, spi_imx, master, res)) ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master, res); dev_err(&pdev->dev, "dma setup error,use pio instead\n"); if (ret == -EPROBE_DEFER) goto out_clk_put; if (ret < 0) dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret); } spi_imx->devtype_data->reset(spi_imx); spi_imx->devtype_data->reset(spi_imx); Loading