From 87306eb7008ac87940c13c200ace585f7c860042 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 22 May 2016 11:06:21 +0200 Subject: spi: Add file patterns for spi device tree bindings Submitters of device tree binding documentation may forget to CC the subsystem maintainer if this is missing. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown diff --git a/MAINTAINERS b/MAINTAINERS index 7304d2e..bb1a63a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10777,6 +10777,7 @@ L: linux-spi@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git Q: http://patchwork.kernel.org/project/spi-devel-general/list/ S: Maintained +F: Documentation/devicetree/bindings/spi/ F: Documentation/spi/ F: drivers/spi/ F: include/linux/spi/ -- cgit v0.10.2 From f4502dd1da9b060a49d539eb754ff86cb97b89f0 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Wed, 8 Jun 2016 12:18:31 +0530 Subject: spi: Add DMA support for spi_flash_read() Few SPI devices provide accelerated read interfaces to read from SPI-NOR flash devices. These hardwares also support DMA to transfer data from flash to memory either via mem-to-mem DMA or dedicated slave DMA channels. Hence, add support for DMA in order to improve throughput and reduce CPU load. Use spi_map_buf() to get sg table for the buffer and pass it to SPI driver. Signed-off-by: Vignesh R Signed-off-by: Mark Brown diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 77e6e45..c9a8d54 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -849,6 +849,20 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg) return 0; } #else /* !CONFIG_HAS_DMA */ +static inline int spi_map_buf(struct spi_master *master, + struct device *dev, struct sg_table *sgt, + void *buf, size_t len, + enum dma_data_direction dir) +{ + return -EINVAL; +} + +static inline void spi_unmap_buf(struct spi_master *master, + struct device *dev, struct sg_table *sgt, + enum dma_data_direction dir) +{ +} + static inline int __spi_map_msg(struct spi_master *master, struct spi_message *msg) { @@ -2725,6 +2739,7 @@ int spi_flash_read(struct spi_device *spi, { struct spi_master *master = spi->master; + struct device *rx_dev = NULL; int ret; if ((msg->opcode_nbits == SPI_NBITS_DUAL || @@ -2750,9 +2765,22 @@ int spi_flash_read(struct spi_device *spi, return ret; } } + mutex_lock(&master->bus_lock_mutex); + if (master->dma_rx) { + rx_dev = master->dma_rx->device->dev; + ret = spi_map_buf(master, rx_dev, &msg->rx_sg, + msg->buf, msg->len, + DMA_FROM_DEVICE); + if (!ret) + msg->cur_msg_mapped = true; + } ret = master->spi_flash_read(spi, msg); + if (msg->cur_msg_mapped) + spi_unmap_buf(master, rx_dev, &msg->rx_sg, + DMA_FROM_DEVICE); mutex_unlock(&master->bus_lock_mutex); + if (master->auto_runtime_pm) pm_runtime_put(master->dev.parent); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 1f03483..7b53af4 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -1143,6 +1143,8 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd) * @opcode_nbits: number of lines to send opcode * @addr_nbits: number of lines to send address * @data_nbits: number of lines for data + * @rx_sg: Scatterlist for receive data read from flash + * @cur_msg_mapped: message has been mapped for DMA */ struct spi_flash_read_message { void *buf; @@ -1155,6 +1157,8 @@ struct spi_flash_read_message { u8 opcode_nbits; u8 addr_nbits; u8 data_nbits; + struct sg_table rx_sg; + bool cur_msg_mapped; }; /* SPI core interface for flash read support */ -- cgit v0.10.2 From b36581df7e788b674a4efbb8da7fe4a00c207e8b Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 8 Jun 2016 20:02:06 +0300 Subject: spi: imx: Using existing properties for chipselects Patch reuse existing "chip_select" and "cs_gpio(s)" fields from SPI core. Signed-off-by: Alexander Shiyan Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 50769078..cbcfb8b 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -60,7 +60,6 @@ struct spi_imx_config { unsigned int speed_hz; unsigned int bpw; unsigned int mode; - u8 cs; }; enum spi_imx_devtype { @@ -76,7 +75,7 @@ struct spi_imx_data; struct spi_imx_devtype_data { void (*intctrl)(struct spi_imx_data *, int); - int (*config)(struct spi_imx_data *, struct spi_imx_config *); + int (*config)(struct spi_device *, struct spi_imx_config *); void (*trigger)(struct spi_imx_data *); int (*rx_available)(struct spi_imx_data *); void (*reset)(struct spi_imx_data *); @@ -112,7 +111,6 @@ struct spi_imx_data { struct completion dma_tx_completion; const struct spi_imx_devtype_data *devtype_data; - int chipselect[0]; }; static inline int is_imx27_cspi(struct spi_imx_data *d) @@ -334,9 +332,10 @@ static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx) 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) +static int __maybe_unused mx51_ecspi_config(struct spi_device *spi, + struct spi_imx_config *config) { + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); u32 ctrl = MX51_ECSPI_CTRL_ENABLE; u32 clk = config->speed_hz, delay, reg; u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG); @@ -355,28 +354,28 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, spi_imx->spi_bus_clk = clk; /* set chip select to use */ - ctrl |= MX51_ECSPI_CTRL_CS(config->cs); + ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select); ctrl |= (config->bpw - 1) << MX51_ECSPI_CTRL_BL_OFFSET; - cfg |= MX51_ECSPI_CONFIG_SBBCTRL(config->cs); + cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select); if (config->mode & SPI_CPHA) - cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs); + cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select); else - cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(config->cs); + cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select); if (config->mode & SPI_CPOL) { - cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs); - cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs); + cfg |= MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select); + cfg |= MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select); } else { - cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(config->cs); - cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(config->cs); + cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select); + cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select); } if (config->mode & SPI_CS_HIGH) - cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs); + cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); else - cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs); + cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); if (spi_imx->usedma) ctrl |= MX51_ECSPI_CTRL_SMC; @@ -480,11 +479,11 @@ static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx) writel(reg, spi_imx->base + MXC_CSPICTRL); } -static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx, - struct spi_imx_config *config) +static int __maybe_unused mx31_config(struct spi_device *spi, + struct spi_imx_config *config) { + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; - int cs = spi_imx->chipselect[config->cs]; reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) << MX31_CSPICTRL_DR_SHIFT; @@ -502,8 +501,8 @@ static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx, reg |= MX31_CSPICTRL_POL; if (config->mode & SPI_CS_HIGH) reg |= MX31_CSPICTRL_SSPOL; - if (cs < 0) - reg |= (cs + 32) << + if (spi->cs_gpio < 0) + reg |= (spi->cs_gpio + 32) << (is_imx35_cspi(spi_imx) ? MX35_CSPICTRL_CS_SHIFT : MX31_CSPICTRL_CS_SHIFT); @@ -558,11 +557,11 @@ static void __maybe_unused mx21_trigger(struct spi_imx_data *spi_imx) writel(reg, spi_imx->base + MXC_CSPICTRL); } -static int __maybe_unused mx21_config(struct spi_imx_data *spi_imx, - struct spi_imx_config *config) +static int __maybe_unused mx21_config(struct spi_device *spi, + struct spi_imx_config *config) { + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER; - int cs = spi_imx->chipselect[config->cs]; unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18; reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz, max) << @@ -575,8 +574,8 @@ static int __maybe_unused mx21_config(struct spi_imx_data *spi_imx, reg |= MX21_CSPICTRL_POL; if (config->mode & SPI_CS_HIGH) reg |= MX21_CSPICTRL_SSPOL; - if (cs < 0) - reg |= (cs + 32) << MX21_CSPICTRL_CS_SHIFT; + if (spi->cs_gpio < 0) + reg |= (spi->cs_gpio + 32) << MX21_CSPICTRL_CS_SHIFT; writel(reg, spi_imx->base + MXC_CSPICTRL); @@ -625,9 +624,10 @@ static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx) writel(reg, spi_imx->base + MXC_CSPICTRL); } -static int __maybe_unused mx1_config(struct spi_imx_data *spi_imx, - struct spi_imx_config *config) +static int __maybe_unused mx1_config(struct spi_device *spi, + struct spi_imx_config *config) { + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER; reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) << @@ -747,15 +747,13 @@ MODULE_DEVICE_TABLE(of, spi_imx_dt_ids); static void spi_imx_chipselect(struct spi_device *spi, int is_active) { - struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); - int gpio = spi_imx->chipselect[spi->chip_select]; int active = is_active != BITBANG_CS_INACTIVE; int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH); - if (!gpio_is_valid(gpio)) + if (!gpio_is_valid(spi->cs_gpio)) return; - gpio_set_value(gpio, dev_is_lowactive ^ active); + gpio_set_value(spi->cs_gpio, dev_is_lowactive ^ active); } static void spi_imx_push(struct spi_imx_data *spi_imx) @@ -860,7 +858,6 @@ static int spi_imx_setupxfer(struct spi_device *spi, config.bpw = t ? t->bits_per_word : spi->bits_per_word; config.speed_hz = t ? t->speed_hz : spi->max_speed_hz; config.mode = spi->mode; - config.cs = spi->chip_select; if (!config.speed_hz) config.speed_hz = spi->max_speed_hz; @@ -891,7 +888,7 @@ static int spi_imx_setupxfer(struct spi_device *spi, return ret; } - spi_imx->devtype_data->config(spi_imx, &config); + spi_imx->devtype_data->config(spi, &config); return 0; } @@ -1080,14 +1077,12 @@ static int spi_imx_transfer(struct spi_device *spi, static int spi_imx_setup(struct spi_device *spi) { - struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); - int gpio = spi_imx->chipselect[spi->chip_select]; - dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __func__, spi->mode, spi->bits_per_word, spi->max_speed_hz); - if (gpio_is_valid(gpio)) - gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); + if (gpio_is_valid(spi->cs_gpio)) + gpio_direction_output(spi->cs_gpio, + spi->mode & SPI_CS_HIGH ? 0 : 1); spi_imx_chipselect(spi, BITBANG_CS_INACTIVE); @@ -1137,31 +1132,21 @@ static int spi_imx_probe(struct platform_device *pdev) struct spi_master *master; struct spi_imx_data *spi_imx; struct resource *res; - int i, ret, num_cs, irq; + int i, ret, irq; if (!np && !mxc_platform_info) { dev_err(&pdev->dev, "can't get the platform data\n"); return -EINVAL; } - ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs); - if (ret < 0) { - if (mxc_platform_info) - num_cs = mxc_platform_info->num_chipselect; - else - return ret; - } - - master = spi_alloc_master(&pdev->dev, - sizeof(struct spi_imx_data) + sizeof(int) * num_cs); + master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data)); if (!master) return -ENOMEM; platform_set_drvdata(pdev, master); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); - master->bus_num = pdev->id; - master->num_chipselect = num_cs; + master->bus_num = np ? -1 : pdev->id; spi_imx = spi_master_get_devdata(master); spi_imx->bitbang.master = master; @@ -1170,22 +1155,16 @@ static int spi_imx_probe(struct platform_device *pdev) 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++) { - int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); - if (!gpio_is_valid(cs_gpio) && mxc_platform_info) - cs_gpio = mxc_platform_info->chipselect[i]; - - spi_imx->chipselect[i] = cs_gpio; - if (!gpio_is_valid(cs_gpio)) - continue; + if (mxc_platform_info) { + master->num_chipselect = mxc_platform_info->num_chipselect; + master->cs_gpios = devm_kzalloc(&master->dev, + sizeof(int) * master->num_chipselect, GFP_KERNEL); + if (!master->cs_gpios) + return -ENOMEM; - ret = devm_gpio_request(&pdev->dev, spi_imx->chipselect[i], - DRIVER_NAME); - if (ret) { - dev_err(&pdev->dev, "can't get cs gpios\n"); - goto out_master_put; - } - } + for (i = 0; i < master->num_chipselect; i++) + master->cs_gpios[i] = mxc_platform_info->chipselect[i]; + } spi_imx->bitbang.chipselect = spi_imx_chipselect; spi_imx->bitbang.setup_transfer = spi_imx_setupxfer; @@ -1267,6 +1246,19 @@ static int spi_imx_probe(struct platform_device *pdev) goto out_clk_put; } + for (i = 0; i < master->num_chipselect; i++) { + if (!gpio_is_valid(master->cs_gpios[i])) + continue; + + ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i], + DRIVER_NAME); + if (ret) { + dev_err(&pdev->dev, "Can't get CS GPIO %i\n", + master->cs_gpios[i]); + goto out_clk_put; + } + } + dev_info(&pdev->dev, "probed\n"); clk_disable(spi_imx->clk_ipg); -- cgit v0.10.2 From c0c7a5d7962a4e2ad8626c33e2a2f6ee3bb3dbab Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 8 Jun 2016 20:02:07 +0300 Subject: spi: imx: Remove unnecessary field "mode" from struct spi_imx_config SPI mode can be obtained directly from spi-device, there is no need to keep a copy. Signed-off-by: Alexander Shiyan Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index cbcfb8b..0aa38c2 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -59,7 +59,6 @@ struct spi_imx_config { unsigned int speed_hz; unsigned int bpw; - unsigned int mode; }; enum spi_imx_devtype { @@ -360,19 +359,19 @@ static int __maybe_unused mx51_ecspi_config(struct spi_device *spi, cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select); - if (config->mode & SPI_CPHA) + if (spi->mode & SPI_CPHA) cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select); else cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select); - if (config->mode & SPI_CPOL) { + if (spi->mode & SPI_CPOL) { cfg |= MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select); cfg |= MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select); } else { cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select); cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select); } - if (config->mode & SPI_CS_HIGH) + if (spi->mode & SPI_CS_HIGH) cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); else cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); @@ -384,7 +383,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_device *spi, writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); reg = readl(spi_imx->base + MX51_ECSPI_TESTREG); - if (config->mode & SPI_LOOP) + if (spi->mode & SPI_LOOP) reg |= MX51_ECSPI_TESTREG_LBC; else reg &= ~MX51_ECSPI_TESTREG_LBC; @@ -495,11 +494,11 @@ static int __maybe_unused mx31_config(struct spi_device *spi, reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT; } - if (config->mode & SPI_CPHA) + if (spi->mode & SPI_CPHA) reg |= MX31_CSPICTRL_PHA; - if (config->mode & SPI_CPOL) + if (spi->mode & SPI_CPOL) reg |= MX31_CSPICTRL_POL; - if (config->mode & SPI_CS_HIGH) + if (spi->mode & SPI_CS_HIGH) reg |= MX31_CSPICTRL_SSPOL; if (spi->cs_gpio < 0) reg |= (spi->cs_gpio + 32) << @@ -568,11 +567,11 @@ static int __maybe_unused mx21_config(struct spi_device *spi, MX21_CSPICTRL_DR_SHIFT; reg |= config->bpw - 1; - if (config->mode & SPI_CPHA) + if (spi->mode & SPI_CPHA) reg |= MX21_CSPICTRL_PHA; - if (config->mode & SPI_CPOL) + if (spi->mode & SPI_CPOL) reg |= MX21_CSPICTRL_POL; - if (config->mode & SPI_CS_HIGH) + if (spi->mode & SPI_CS_HIGH) reg |= MX21_CSPICTRL_SSPOL; if (spi->cs_gpio < 0) reg |= (spi->cs_gpio + 32) << MX21_CSPICTRL_CS_SHIFT; @@ -634,9 +633,9 @@ static int __maybe_unused mx1_config(struct spi_device *spi, MX1_CSPICTRL_DR_SHIFT; reg |= config->bpw - 1; - if (config->mode & SPI_CPHA) + if (spi->mode & SPI_CPHA) reg |= MX1_CSPICTRL_PHA; - if (config->mode & SPI_CPOL) + if (spi->mode & SPI_CPOL) reg |= MX1_CSPICTRL_POL; writel(reg, spi_imx->base + MXC_CSPICTRL); @@ -857,7 +856,6 @@ static int spi_imx_setupxfer(struct spi_device *spi, config.bpw = t ? t->bits_per_word : spi->bits_per_word; config.speed_hz = t ? t->speed_hz : spi->max_speed_hz; - config.mode = spi->mode; if (!config.speed_hz) config.speed_hz = spi->max_speed_hz; -- cgit v0.10.2 From f989bc69585f207cbcd20e4798c69f7a4a596dd9 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 8 Jun 2016 20:02:08 +0300 Subject: spi: imx: Remove "maybe_unused" attributes The SPI-driver no longer contains the conditions for various CPUs, so "maybe_unused" attributes is no longer needed. This patch removes these attributes. Signed-off-by: Alexander Shiyan Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 0aa38c2..cafe42c 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -309,7 +309,7 @@ static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx, (post << MX51_ECSPI_CTRL_POSTDIV_OFFSET); } -static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable) +static void mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable) { unsigned val = 0; @@ -322,7 +322,7 @@ static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int writel(val, spi_imx->base + MX51_ECSPI_INT); } -static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx) +static void mx51_ecspi_trigger(struct spi_imx_data *spi_imx) { u32 reg; @@ -331,8 +331,8 @@ static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx) writel(reg, spi_imx->base + MX51_ECSPI_CTRL); } -static int __maybe_unused mx51_ecspi_config(struct spi_device *spi, - struct spi_imx_config *config) +static int mx51_ecspi_config(struct spi_device *spi, + struct spi_imx_config *config) { struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); u32 ctrl = MX51_ECSPI_CTRL_ENABLE; @@ -422,12 +422,12 @@ static int __maybe_unused mx51_ecspi_config(struct spi_device *spi, return 0; } -static int __maybe_unused mx51_ecspi_rx_available(struct spi_imx_data *spi_imx) +static int mx51_ecspi_rx_available(struct spi_imx_data *spi_imx) { return readl(spi_imx->base + MX51_ECSPI_STAT) & MX51_ECSPI_STAT_RR; } -static void __maybe_unused mx51_ecspi_reset(struct spi_imx_data *spi_imx) +static void mx51_ecspi_reset(struct spi_imx_data *spi_imx) { /* drain receive buffer */ while (mx51_ecspi_rx_available(spi_imx)) @@ -457,7 +457,7 @@ static void __maybe_unused mx51_ecspi_reset(struct spi_imx_data *spi_imx) * the i.MX35 has a slightly different register layout for bits * we do not use here. */ -static void __maybe_unused mx31_intctrl(struct spi_imx_data *spi_imx, int enable) +static void mx31_intctrl(struct spi_imx_data *spi_imx, int enable) { unsigned int val = 0; @@ -469,7 +469,7 @@ static void __maybe_unused mx31_intctrl(struct spi_imx_data *spi_imx, int enable writel(val, spi_imx->base + MXC_CSPIINT); } -static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx) +static void mx31_trigger(struct spi_imx_data *spi_imx) { unsigned int reg; @@ -478,8 +478,7 @@ static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx) writel(reg, spi_imx->base + MXC_CSPICTRL); } -static int __maybe_unused mx31_config(struct spi_device *spi, - struct spi_imx_config *config) +static int mx31_config(struct spi_device *spi, struct spi_imx_config *config) { struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; @@ -510,12 +509,12 @@ static int __maybe_unused mx31_config(struct spi_device *spi, return 0; } -static int __maybe_unused mx31_rx_available(struct spi_imx_data *spi_imx) +static int mx31_rx_available(struct spi_imx_data *spi_imx) { return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR; } -static void __maybe_unused mx31_reset(struct spi_imx_data *spi_imx) +static void mx31_reset(struct spi_imx_data *spi_imx) { /* drain receive buffer */ while (readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR) @@ -535,7 +534,7 @@ static void __maybe_unused mx31_reset(struct spi_imx_data *spi_imx) #define MX21_CSPICTRL_DR_SHIFT 14 #define MX21_CSPICTRL_CS_SHIFT 19 -static void __maybe_unused mx21_intctrl(struct spi_imx_data *spi_imx, int enable) +static void mx21_intctrl(struct spi_imx_data *spi_imx, int enable) { unsigned int val = 0; @@ -547,7 +546,7 @@ static void __maybe_unused mx21_intctrl(struct spi_imx_data *spi_imx, int enable writel(val, spi_imx->base + MXC_CSPIINT); } -static void __maybe_unused mx21_trigger(struct spi_imx_data *spi_imx) +static void mx21_trigger(struct spi_imx_data *spi_imx) { unsigned int reg; @@ -556,8 +555,7 @@ static void __maybe_unused mx21_trigger(struct spi_imx_data *spi_imx) writel(reg, spi_imx->base + MXC_CSPICTRL); } -static int __maybe_unused mx21_config(struct spi_device *spi, - struct spi_imx_config *config) +static int mx21_config(struct spi_device *spi, struct spi_imx_config *config) { struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER; @@ -581,12 +579,12 @@ static int __maybe_unused mx21_config(struct spi_device *spi, return 0; } -static int __maybe_unused mx21_rx_available(struct spi_imx_data *spi_imx) +static int mx21_rx_available(struct spi_imx_data *spi_imx) { return readl(spi_imx->base + MXC_CSPIINT) & MX21_INTREG_RR; } -static void __maybe_unused mx21_reset(struct spi_imx_data *spi_imx) +static void mx21_reset(struct spi_imx_data *spi_imx) { writel(1, spi_imx->base + MXC_RESET); } @@ -602,7 +600,7 @@ static void __maybe_unused mx21_reset(struct spi_imx_data *spi_imx) #define MX1_CSPICTRL_MASTER (1 << 10) #define MX1_CSPICTRL_DR_SHIFT 13 -static void __maybe_unused mx1_intctrl(struct spi_imx_data *spi_imx, int enable) +static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable) { unsigned int val = 0; @@ -614,7 +612,7 @@ static void __maybe_unused mx1_intctrl(struct spi_imx_data *spi_imx, int enable) writel(val, spi_imx->base + MXC_CSPIINT); } -static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx) +static void mx1_trigger(struct spi_imx_data *spi_imx) { unsigned int reg; @@ -623,8 +621,7 @@ static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx) writel(reg, spi_imx->base + MXC_CSPICTRL); } -static int __maybe_unused mx1_config(struct spi_device *spi, - struct spi_imx_config *config) +static int mx1_config(struct spi_device *spi, struct spi_imx_config *config) { struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER; @@ -643,12 +640,12 @@ static int __maybe_unused mx1_config(struct spi_device *spi, return 0; } -static int __maybe_unused mx1_rx_available(struct spi_imx_data *spi_imx) +static int mx1_rx_available(struct spi_imx_data *spi_imx) { return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR; } -static void __maybe_unused mx1_reset(struct spi_imx_data *spi_imx) +static void mx1_reset(struct spi_imx_data *spi_imx) { writel(1, spi_imx->base + MXC_RESET); } -- cgit v0.10.2 From 956fff7189e586c646a179f00386d0ebf9f0fd8b Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 8 Jun 2016 20:02:09 +0300 Subject: spi: imx: Update DT binding documentation Mark "fsl,spi-num-chipselects" property as obsolete. Signed-off-by: Alexander Shiyan Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt index 523341a..8bc95e2 100644 --- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt +++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt @@ -11,7 +11,6 @@ Required properties: - "fsl,imx51-ecspi" for SPI compatible with the one integrated on i.MX51 - reg : Offset and length of the register set for the device - interrupts : Should contain CSPI/eCSPI interrupt -- fsl,spi-num-chipselects : Contains the number of the chipselect - cs-gpios : Specifies the gpio pins to be used for chipselects. - clocks : Clock specifiers for both ipg and per clocks. - clock-names : Clock names should include both "ipg" and "per" @@ -21,6 +20,9 @@ See the clock consumer binding, Documentation/devicetree/bindings/dma/dma.txt - dma-names: DMA request names should include "tx" and "rx" if present. +Obsolete properties: +- fsl,spi-num-chipselects : Contains the number of the chipselect + Example: ecspi@70010000 { @@ -29,7 +31,6 @@ ecspi@70010000 { compatible = "fsl,imx51-ecspi"; reg = <0x70010000 0x4000>; interrupts = <36>; - fsl,spi-num-chipselects = <2>; cs-gpios = <&gpio3 24 0>, /* GPIO3_24 */ <&gpio3 25 0>; /* GPIO3_25 */ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>; -- cgit v0.10.2 From ff1ba3dac08eb10bd096d799430e5d1494f2ddfb Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Tue, 21 Jun 2016 14:12:54 +0200 Subject: spi: imx: wait_for_completion_timeout(..) for PIO transfers In some rare cases I see the following 'task blocked' information. It looks like the PIO transfer has some problems and never succeeds. Make use of wait_for_completion_timeout(..) to detect this case and return -ETIMEDOUT. [ 240.246067] INFO: task hexdump:1660 blocked for more than 120 seconds. [ 240.246089] Not tainted 4.1.17 0000001 [ 240.246099] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 240.246109] hexdump D c0575548 0 1660 1 0x00000000 [ 240.246132] Backtrace: [ 240.246166] [] (__schedule) from [] (schedule+0x40/0xa4) [ 240.246176] r10:00000000 r9:c07f1300 r8:c07b8408 r7:c0576518 r6:7fffffff r5:7fffffff [ 240.246210] r4:ee972e7c [ 240.246233] [] (schedule) from [] (schedule_timeout+0x174/0x274) [ 240.246254] [] (schedule_timeout) from [] (wait_for_common+0xc0/0x164) [ 240.246263] r10:00000000 r9:c07f1300 r8:00000002 r7:00000000 r6:7fffffff r5:ee972e78 [ 240.246294] r4:ee972e7c [ 240.246314] [] (wait_for_common) from [] (wait_for_completion+0x20/0x24) [ 240.246324] r10:ee972e50 r8:00000001 r7:c3976200 r6:ee972c00 r5:ee972e50 r4:c2c87d28 [ 240.246367] [] (wait_for_completion) from [] (spi_imx_transfer+0xe8/0x3cc) [ 240.246393] [] (spi_imx_transfer) from [] (spi_bitbang_transfer_one+0xb4/0x250) [ 240.246403] r10:ee972e50 r8:00000001 r7:00000000 r6:c2c87da0 r5:00000000 r4:c2c87d28 [ 240.246443] [] (spi_bitbang_transfer_one) from [] (__spi_pump_messages+0x36c/0x6b4) [ 240.246452] r10:ee9e5010 r9:00000001 r8:ee9e5010 r7:00000000 r6:c2c87da0 r5:c2c87d6c [ 240.246483] r4:ee972c00 [ 240.246503] [] (__spi_pump_messages) from [] (__spi_sync+0x138/0x1e4) [ 240.246512] r10:00000000 r9:00000000 r8:c03f25a8 r7:00000000 r6:ee972c00 r5:c3976200 [ 240.246542] r4:c2c87da0 [ 240.246562] [] (__spi_sync) from [] (spi_sync+0x1c/0x20) [ 240.246571] r10:00040000 r9:00000000 r8:c3976200 r7:00000000 r6:ee973300 r5:c2c87da0 [ 240.246602] r4:ee973014 [ 240.246623] [] (spi_sync) from [] (m25p80_read+0xf8/0x124) [ 240.246641] [] (m25p80_read) from [] (spi_nor_read+0x64/0x80) [ 240.246651] r10:00004000 r8:00004000 r7:00000000 r6:00040000 r5:00000000 r4:ee973014 [ 240.246698] [] (spi_nor_read) from [] (mtd_read+0x98/0xcc) [ 240.246708] r7:c2c87ea0 r6:ee973098 r5:00000000 r4:001c0000 [ 240.246740] [] (mtd_read) from [] (mtdchar_read+0xcc/0x204) [ 240.246750] r9:ed424000 r8:00000000 r7:b495d018 r6:c2c87f78 r5:00000000 r4:00040000 [ 240.246793] [] (mtdchar_read) from [] (__vfs_read+0x3c/0xe0) [ 240.246803] r10:00004000 r9:00000000 r8:c2c87f78 r7:b495d018 r6:c2c87f78 r5:c05c8104 [ 240.246833] r4:c32fe600 [ 240.246852] [] (__vfs_read) from [] (vfs_read+0x98/0x154) [ 240.246861] r10:00000000 r8:00040000 r7:00004000 r6:c2c87f78 r5:b495d018 r4:c32fe600 [ 240.246899] [] (vfs_read) from [] (SyS_read+0x50/0x90) [ 240.246908] r10:00000000 r8:00040000 r7:b495d018 r6:00004000 r5:c32fe601 r4:c32fe600 [ 240.246953] [] (SyS_read) from [] (ret_fast_syscall+0x0/0x3c) [ 240.246962] r9:c2c86000 r8:c000fc04 r7:00000003 r6:00004000 r5:00000000 r4:b495d018 Signed-off-by: Christian Gmeiner Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index cafe42c..f63cb30 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1042,6 +1042,8 @@ static int spi_imx_pio_transfer(struct spi_device *spi, struct spi_transfer *transfer) { struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); + unsigned long transfer_timeout; + unsigned long timeout; spi_imx->tx_buf = transfer->tx_buf; spi_imx->rx_buf = transfer->rx_buf; @@ -1054,7 +1056,15 @@ static int spi_imx_pio_transfer(struct spi_device *spi, spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE); - wait_for_completion(&spi_imx->xfer_done); + transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len); + + timeout = wait_for_completion_timeout(&spi_imx->xfer_done, + transfer_timeout); + if (!timeout) { + dev_err(&spi->dev, "I/O Error in PIO\n"); + spi_imx->devtype_data->reset(spi_imx); + return -ETIMEDOUT; + } return transfer->len; } -- cgit v0.10.2 From b7ddfb9f496e23eafccd1d630f25b68f105e0ee8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 28 Jun 2016 13:15:08 +0100 Subject: spi: loopback-test: fix spelling mistake: "missmatch" -> "mismatch" trivial fix to spelling mistake in dev_err message Signed-off-by: Colin Ian King Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c index cf4bb36..faa1b13 100644 --- a/drivers/spi/spi-loopback-test.c +++ b/drivers/spi/spi-loopback-test.c @@ -536,7 +536,7 @@ static int spi_test_check_loopback_result(struct spi_device *spi, mismatch_error: dev_err(&spi->dev, - "loopback strangeness - transfer missmatch on byte %04zx - expected 0x%02x, but got 0x%02x\n", + "loopback strangeness - transfer mismatch on byte %04zx - expected 0x%02x, but got 0x%02x\n", i, txb, rxb); return -EINVAL; -- cgit v0.10.2 From ac96b737cdec77023bf2ead142a3875174af0c7a Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Sat, 2 Jul 2016 14:27:06 +0530 Subject: spi: spi-mpc52xx-psc: Remove deprecated create_singlethread_workqueue The workqueue "workqueue" has a single work item(&mps->work) doesn't require ordering. Also, it is not being used on a memory reclaim path. Hence, the singlethreaded workqueue has been replaced with the use of system_wq. System workqueues have been able to handle high level of concurrency for a long time now and hence it's not required to have a singlethreaded workqueue just to gain concurrency. Unlike a dedicated per-cpu workqueue created with create_singlethread_workqueue(), system_wq allows multiple work items to overlap executions even on the same CPU; however, a per-cpu workqueue doesn't have any CPU locality or global ordering guarantee unless the target CPU is explicitly specified and thus the increase of local concurrency shouldn't make any difference. Work item has been flushed in mpc52xx_psc_spi_of_remove() to ensure that nothing is pending while disconnecting the driver. Signed-off-by: Bhaktipriya Shridhar Acked-by: Tejun Heo Signed-off-by: Mark Brown diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c index 72d11eb..42a8b85 100644 --- a/drivers/spi/spi-mpc52xx-psc.c +++ b/drivers/spi/spi-mpc52xx-psc.c @@ -42,7 +42,6 @@ struct mpc52xx_psc_spi { u8 bits_per_word; u8 busy; - struct workqueue_struct *workqueue; struct work_struct work; struct list_head queue; @@ -299,7 +298,7 @@ static int mpc52xx_psc_spi_transfer(struct spi_device *spi, spin_lock_irqsave(&mps->lock, flags); list_add_tail(&m->queue, &mps->queue); - queue_work(mps->workqueue, &mps->work); + schedule_work(&mps->work); spin_unlock_irqrestore(&mps->lock, flags); return 0; @@ -425,21 +424,12 @@ static int mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr, INIT_WORK(&mps->work, mpc52xx_psc_spi_work); INIT_LIST_HEAD(&mps->queue); - mps->workqueue = create_singlethread_workqueue( - dev_name(master->dev.parent)); - if (mps->workqueue == NULL) { - ret = -EBUSY; - goto free_irq; - } - ret = spi_register_master(master); if (ret < 0) - goto unreg_master; + goto free_irq; return ret; -unreg_master: - destroy_workqueue(mps->workqueue); free_irq: free_irq(mps->irq, mps); free_master: @@ -484,8 +474,7 @@ static int mpc52xx_psc_spi_of_remove(struct platform_device *op) struct spi_master *master = spi_master_get(platform_get_drvdata(op)); struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master); - flush_workqueue(mps->workqueue); - destroy_workqueue(mps->workqueue); + flush_work(&mps->work); spi_unregister_master(master); free_irq(mps->irq, mps); if (mps->psc) -- cgit v0.10.2