diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Kconfig | 1 | ||||
-rw-r--r-- | drivers/spi/spi-bfin-sport.c | 15 | ||||
-rw-r--r-- | drivers/spi/spi-bfin5xx.c | 15 | ||||
-rw-r--r-- | drivers/spi/spi-clps711x.c | 69 | ||||
-rw-r--r-- | drivers/spi/spi-imx.c | 191 | ||||
-rw-r--r-- | drivers/spi/spi-loopback-test.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-mpc52xx-psc.c | 17 | ||||
-rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 145 | ||||
-rw-r--r-- | drivers/spi/spi-orion.c | 88 | ||||
-rw-r--r-- | drivers/spi/spi-pic32-sqi.c | 7 | ||||
-rw-r--r-- | drivers/spi/spi-pic32.c | 5 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx.c | 9 | ||||
-rw-r--r-- | drivers/spi/spi-rockchip.c | 17 | ||||
-rw-r--r-- | drivers/spi/spi.c | 28 |
14 files changed, 350 insertions, 259 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 4b931ec8d90b..d6fb8d4b7786 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -411,6 +411,7 @@ config SPI_OMAP24XX tristate "McSPI driver for OMAP" depends on HAS_DMA depends on ARCH_OMAP2PLUS || COMPILE_TEST + select SG_SPLIT help SPI master controller for OMAP24XX and later Multichannel SPI (McSPI) modules. diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index 6c967555a56a..01d0ba9c5942 100644 --- a/drivers/spi/spi-bfin-sport.c +++ b/drivers/spi/spi-bfin-sport.c @@ -64,8 +64,6 @@ struct bfin_sport_spi_master_data { /* Pin request list */ u16 *pin_req; - /* Driver message queue */ - struct workqueue_struct *workqueue; struct work_struct pump_messages; spinlock_t lock; struct list_head queue; @@ -300,7 +298,7 @@ bfin_sport_spi_giveback(struct bfin_sport_spi_master_data *drv_data) drv_data->cur_msg = NULL; drv_data->cur_transfer = NULL; drv_data->cur_chip = NULL; - queue_work(drv_data->workqueue, &drv_data->pump_messages); + schedule_work(&drv_data->pump_messages); spin_unlock_irqrestore(&drv_data->lock, flags); if (!drv_data->cs_change) @@ -556,7 +554,7 @@ bfin_sport_spi_transfer(struct spi_device *spi, struct spi_message *msg) list_add_tail(&msg->queue, &drv_data->queue); if (drv_data->run && !drv_data->busy) - queue_work(drv_data->workqueue, &drv_data->pump_messages); + schedule_work(&drv_data->pump_messages); spin_unlock_irqrestore(&drv_data->lock, flags); @@ -666,12 +664,7 @@ bfin_sport_spi_init_queue(struct bfin_sport_spi_master_data *drv_data) tasklet_init(&drv_data->pump_transfers, bfin_sport_spi_pump_transfers, (unsigned long)drv_data); - /* init messages workqueue */ INIT_WORK(&drv_data->pump_messages, bfin_sport_spi_pump_messages); - drv_data->workqueue = - create_singlethread_workqueue(dev_name(drv_data->master->dev.parent)); - if (drv_data->workqueue == NULL) - return -EBUSY; return 0; } @@ -694,7 +687,7 @@ bfin_sport_spi_start_queue(struct bfin_sport_spi_master_data *drv_data) drv_data->cur_chip = NULL; spin_unlock_irqrestore(&drv_data->lock, flags); - queue_work(drv_data->workqueue, &drv_data->pump_messages); + schedule_work(&drv_data->pump_messages); return 0; } @@ -738,7 +731,7 @@ bfin_sport_spi_destroy_queue(struct bfin_sport_spi_master_data *drv_data) if (status) return status; - destroy_workqueue(drv_data->workqueue); + flush_work(&drv_data->pump_messages); return 0; } diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 1e91325bf39c..249c7a3677c9 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -67,8 +67,6 @@ struct bfin_spi_master_data { /* BFIN hookup */ struct bfin5xx_spi_master *master_info; - /* Driver message queue */ - struct workqueue_struct *workqueue; struct work_struct pump_messages; spinlock_t lock; struct list_head queue; @@ -359,7 +357,7 @@ static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data) drv_data->cur_msg = NULL; drv_data->cur_transfer = NULL; drv_data->cur_chip = NULL; - queue_work(drv_data->workqueue, &drv_data->pump_messages); + schedule_work(&drv_data->pump_messages); spin_unlock_irqrestore(&drv_data->lock, flags); msg->state = NULL; @@ -946,7 +944,7 @@ static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg) list_add_tail(&msg->queue, &drv_data->queue); if (drv_data->running && !drv_data->busy) - queue_work(drv_data->workqueue, &drv_data->pump_messages); + schedule_work(&drv_data->pump_messages); spin_unlock_irqrestore(&drv_data->lock, flags); @@ -1177,12 +1175,7 @@ static int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data) tasklet_init(&drv_data->pump_transfers, bfin_spi_pump_transfers, (unsigned long)drv_data); - /* init messages workqueue */ INIT_WORK(&drv_data->pump_messages, bfin_spi_pump_messages); - drv_data->workqueue = create_singlethread_workqueue( - dev_name(drv_data->master->dev.parent)); - if (drv_data->workqueue == NULL) - return -EBUSY; return 0; } @@ -1204,7 +1197,7 @@ static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data) drv_data->cur_chip = NULL; spin_unlock_irqrestore(&drv_data->lock, flags); - queue_work(drv_data->workqueue, &drv_data->pump_messages); + schedule_work(&drv_data->pump_messages); return 0; } @@ -1246,7 +1239,7 @@ static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data) if (status != 0) return status; - destroy_workqueue(drv_data->workqueue); + flush_work(&drv_data->pump_messages); return 0; } diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index 8c30de0315e7..18193df2eba8 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -1,7 +1,7 @@ /* * CLPS711X SPI bus driver * - * Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru> + * Copyright (C) 2012-2016 Alexander Shiyan <shc_work@mail.ru> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -12,7 +12,6 @@ #include <linux/io.h> #include <linux/clk.h> #include <linux/gpio.h> -#include <linux/delay.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/platform_device.h> @@ -20,9 +19,8 @@ #include <linux/mfd/syscon.h> #include <linux/mfd/syscon/clps711x.h> #include <linux/spi/spi.h> -#include <linux/platform_data/spi-clps711x.h> -#define DRIVER_NAME "spi-clps711x" +#define DRIVER_NAME "clps711x-spi" #define SYNCIO_FRMLEN(x) ((x) << 8) #define SYNCIO_TXFRMEN (1 << 14) @@ -40,6 +38,17 @@ struct spi_clps711x_data { static int spi_clps711x_setup(struct spi_device *spi) { + if (!spi->controller_state) { + int ret; + + ret = devm_gpio_request(&spi->master->dev, spi->cs_gpio, + dev_name(&spi->master->dev)); + if (ret) + return ret; + + spi->controller_state = spi; + } + /* We are expect that SPI-device is not selected */ gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); @@ -104,20 +113,9 @@ static irqreturn_t spi_clps711x_isr(int irq, void *dev_id) static int spi_clps711x_probe(struct platform_device *pdev) { struct spi_clps711x_data *hw; - struct spi_clps711x_pdata *pdata = dev_get_platdata(&pdev->dev); struct spi_master *master; struct resource *res; - int i, irq, ret; - - if (!pdata) { - dev_err(&pdev->dev, "No platform data supplied\n"); - return -EINVAL; - } - - if (pdata->num_chipselect < 1) { - dev_err(&pdev->dev, "At least one CS must be defined\n"); - return -EINVAL; - } + int irq, ret; irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -127,40 +125,24 @@ static int spi_clps711x_probe(struct platform_device *pdev) if (!master) return -ENOMEM; - master->cs_gpios = devm_kzalloc(&pdev->dev, sizeof(int) * - pdata->num_chipselect, GFP_KERNEL); - if (!master->cs_gpios) { - ret = -ENOMEM; - goto err_out; - } - - master->bus_num = pdev->id; + master->bus_num = -1; master->mode_bits = SPI_CPHA | SPI_CS_HIGH; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8); - master->num_chipselect = pdata->num_chipselect; + master->dev.of_node = pdev->dev.of_node; master->setup = spi_clps711x_setup; master->prepare_message = spi_clps711x_prepare_message; master->transfer_one = spi_clps711x_transfer_one; hw = spi_master_get_devdata(master); - for (i = 0; i < master->num_chipselect; i++) { - master->cs_gpios[i] = pdata->chipselect[i]; - 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", i); - goto err_out; - } - } - hw->spi_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(hw->spi_clk)) { ret = PTR_ERR(hw->spi_clk); goto err_out; } - hw->syscon = syscon_regmap_lookup_by_pdevname("syscon.3"); + hw->syscon = + syscon_regmap_lookup_by_compatible("cirrus,ep7209-syscon3"); if (IS_ERR(hw->syscon)) { ret = PTR_ERR(hw->syscon); goto err_out; @@ -185,14 +167,8 @@ static int spi_clps711x_probe(struct platform_device *pdev) goto err_out; ret = devm_spi_register_master(&pdev->dev, master); - if (!ret) { - dev_info(&pdev->dev, - "SPI bus driver initialized. Master clock %u Hz\n", - master->max_speed_hz); + if (!ret) return 0; - } - - dev_err(&pdev->dev, "Failed to register master\n"); err_out: spi_master_put(master); @@ -200,9 +176,16 @@ err_out: return ret; } +static const struct of_device_id clps711x_spi_dt_ids[] = { + { .compatible = "cirrus,ep7209-spi", }, + { } +}; +MODULE_DEVICE_TABLE(of, clps711x_spi_dt_ids); + static struct platform_driver clps711x_spi_driver = { .driver = { .name = DRIVER_NAME, + .of_match_table = clps711x_spi_dt_ids, }, .probe = spi_clps711x_probe, }; diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 50769078e72e..f63cb30f9010 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -59,8 +59,6 @@ struct spi_imx_config { unsigned int speed_hz; unsigned int bpw; - unsigned int mode; - u8 cs; }; enum spi_imx_devtype { @@ -76,7 +74,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 +110,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) @@ -312,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; @@ -325,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; @@ -334,9 +331,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 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 +353,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); + if (spi->mode & SPI_CPHA) + 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); + 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(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); + if (spi->mode & SPI_CS_HIGH) + 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; @@ -385,7 +383,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, 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; @@ -424,12 +422,12 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, 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)) @@ -459,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; @@ -471,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; @@ -480,11 +478,10 @@ 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 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; @@ -496,14 +493,14 @@ static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx, 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 (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); @@ -512,12 +509,12 @@ static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx, 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) @@ -537,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; @@ -549,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; @@ -558,37 +555,36 @@ 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 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) << 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 (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); 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); } @@ -604,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; @@ -616,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; @@ -625,18 +621,18 @@ 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 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) << 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); @@ -644,12 +640,12 @@ static int __maybe_unused mx1_config(struct spi_imx_data *spi_imx, 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); } @@ -747,15 +743,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) @@ -859,8 +853,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 +883,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; } @@ -1050,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; @@ -1062,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; } @@ -1080,14 +1082,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 +1137,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 +1160,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]; + 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; - spi_imx->chipselect[i] = cs_gpio; - if (!gpio_is_valid(cs_gpio)) - continue; - - 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 +1251,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); diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c index cf4bb36bee25..faa1b133b0f1 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; diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c index 72d11ebefb28..42a8b8521f8f 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) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 1d237e93a289..d5157b2222ce 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -419,16 +419,13 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi, if (mcspi_dma->dma_tx) { struct dma_async_tx_descriptor *tx; - struct scatterlist sg; dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); - sg_init_table(&sg, 1); - sg_dma_address(&sg) = xfer->tx_dma; - sg_dma_len(&sg) = xfer->len; - - tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1, - DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, xfer->tx_sg.sgl, + xfer->tx_sg.nents, + DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (tx) { tx->callback = omap2_mcspi_tx_callback; tx->callback_param = spi; @@ -449,7 +446,10 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, { struct omap2_mcspi *mcspi; struct omap2_mcspi_dma *mcspi_dma; - unsigned int count, dma_count; + unsigned int count, transfer_reduction = 0; + struct scatterlist *sg_out[2]; + int nb_sizes = 0, out_mapped_nents[2], ret, x; + size_t sizes[2]; u32 l; int elements = 0; int word_len, element_count; @@ -457,10 +457,14 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, mcspi = spi_master_get_devdata(spi->master); mcspi_dma = &mcspi->dma_channels[spi->chip_select]; count = xfer->len; - dma_count = xfer->len; + /* + * In the "End-of-Transfer Procedure" section for DMA RX in OMAP35x TRM + * it mentions reducing DMA transfer length by one element in master + * normal mode. + */ if (mcspi->fifo_depth == 0) - dma_count -= es; + transfer_reduction = es; word_len = cs->word_len; l = mcspi_cached_chconf0(spi); @@ -474,20 +478,46 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, if (mcspi_dma->dma_rx) { struct dma_async_tx_descriptor *tx; - struct scatterlist sg; dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); + /* + * Reduce DMA transfer length by one more if McSPI is + * configured in turbo mode. + */ if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0) - dma_count -= es; + transfer_reduction += es; + + if (transfer_reduction) { + /* Split sgl into two. The second sgl won't be used. */ + sizes[0] = count - transfer_reduction; + sizes[1] = transfer_reduction; + nb_sizes = 2; + } else { + /* + * Don't bother splitting the sgl. This essentially + * clones the original sgl. + */ + sizes[0] = count; + nb_sizes = 1; + } + + ret = sg_split(xfer->rx_sg.sgl, xfer->rx_sg.nents, + 0, nb_sizes, + sizes, + sg_out, out_mapped_nents, + GFP_KERNEL); - sg_init_table(&sg, 1); - sg_dma_address(&sg) = xfer->rx_dma; - sg_dma_len(&sg) = dma_count; + if (ret < 0) { + dev_err(&spi->dev, "sg_split failed\n"); + return 0; + } - tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1, - DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | - DMA_CTRL_ACK); + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, + sg_out[0], + out_mapped_nents[0], + DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (tx) { tx->callback = omap2_mcspi_rx_callback; tx->callback_param = spi; @@ -501,12 +531,17 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, omap2_mcspi_set_dma_req(spi, 1, 1); wait_for_completion(&mcspi_dma->dma_rx_completion); - dma_unmap_single(mcspi->dev, xfer->rx_dma, count, - DMA_FROM_DEVICE); + + for (x = 0; x < nb_sizes; x++) + kfree(sg_out[x]); if (mcspi->fifo_depth > 0) return count; + /* + * Due to the DMA transfer length reduction the missing bytes must + * be read manually to receive all of the expected data. + */ omap2_mcspi_set_enable(spi, 0); elements = element_count - 1; @@ -615,8 +650,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) if (tx != NULL) { wait_for_completion(&mcspi_dma->dma_tx_completion); - dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len, - DMA_TO_DEVICE); if (mcspi->fifo_depth > 0) { irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS; @@ -1074,8 +1107,9 @@ static void omap2_mcspi_cleanup(struct spi_device *spi) gpio_free(spi->cs_gpio); } -static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi, - struct spi_device *spi, struct spi_transfer *t) +static int omap2_mcspi_transfer_one(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *t) { /* We only enable one channel at a time -- the one whose message is @@ -1085,7 +1119,7 @@ static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi, * chipselect with the FORCE bit ... CS != channel enable. */ - struct spi_master *master; + struct omap2_mcspi *mcspi; struct omap2_mcspi_dma *mcspi_dma; struct omap2_mcspi_cs *cs; struct omap2_mcspi_device_config *cd; @@ -1093,7 +1127,7 @@ static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi, int status = 0; u32 chconf; - master = spi->master; + mcspi = spi_master_get_devdata(master); mcspi_dma = mcspi->dma_channels + spi->chip_select; cs = spi->controller_state; cd = spi->controller_data; @@ -1153,7 +1187,8 @@ static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi, unsigned count; if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) && - (t->len >= DMA_MIN_BYTES)) + master->cur_msg_mapped && + master->can_dma(master, spi, t)) omap2_mcspi_set_fifo(spi, t, 1); omap2_mcspi_set_enable(spi, 1); @@ -1164,7 +1199,8 @@ static int omap2_mcspi_work_one(struct omap2_mcspi *mcspi, + OMAP2_MCSPI_TX0); if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) && - (t->len >= DMA_MIN_BYTES)) + master->cur_msg_mapped && + master->can_dma(master, spi, t)) count = omap2_mcspi_txrx_dma(spi, t); else count = omap2_mcspi_txrx_pio(spi, t); @@ -1233,55 +1269,11 @@ static int omap2_mcspi_prepare_message(struct spi_master *master, return 0; } -static int omap2_mcspi_transfer_one(struct spi_master *master, - struct spi_device *spi, struct spi_transfer *t) +static bool omap2_mcspi_can_dma(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *xfer) { - struct omap2_mcspi *mcspi; - struct omap2_mcspi_dma *mcspi_dma; - const void *tx_buf = t->tx_buf; - void *rx_buf = t->rx_buf; - unsigned len = t->len; - - mcspi = spi_master_get_devdata(master); - mcspi_dma = mcspi->dma_channels + spi->chip_select; - - if ((len && !(rx_buf || tx_buf))) { - dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", - t->speed_hz, - len, - tx_buf ? "tx" : "", - rx_buf ? "rx" : "", - t->bits_per_word); - return -EINVAL; - } - - if (len < DMA_MIN_BYTES) - goto skip_dma_map; - - if (mcspi_dma->dma_tx && tx_buf != NULL) { - t->tx_dma = dma_map_single(mcspi->dev, (void *) tx_buf, - len, DMA_TO_DEVICE); - if (dma_mapping_error(mcspi->dev, t->tx_dma)) { - dev_dbg(mcspi->dev, "dma %cX %d bytes error\n", - 'T', len); - return -EINVAL; - } - } - if (mcspi_dma->dma_rx && rx_buf != NULL) { - t->rx_dma = dma_map_single(mcspi->dev, rx_buf, t->len, - DMA_FROM_DEVICE); - if (dma_mapping_error(mcspi->dev, t->rx_dma)) { - dev_dbg(mcspi->dev, "dma %cX %d bytes error\n", - 'R', len); - if (tx_buf != NULL) - dma_unmap_single(mcspi->dev, t->tx_dma, - len, DMA_TO_DEVICE); - return -EINVAL; - } - } - -skip_dma_map: - return omap2_mcspi_work_one(mcspi, spi, t); + return (xfer->len >= DMA_MIN_BYTES); } static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) @@ -1361,6 +1353,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) master->setup = omap2_mcspi_setup; master->auto_runtime_pm = true; master->prepare_message = omap2_mcspi_prepare_message; + master->can_dma = omap2_mcspi_can_dma; master->transfer_one = omap2_mcspi_transfer_one; master->set_cs = omap2_mcspi_set_cs; master->cleanup = omap2_mcspi_cleanup; diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index a87cfd4ba17b..ded37025b445 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -18,6 +18,7 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_device.h> #include <linux/clk.h> #include <linux/sizes.h> @@ -43,6 +44,9 @@ #define ORION_SPI_INT_CAUSE_REG 0x10 #define ORION_SPI_TIMING_PARAMS_REG 0x18 +/* Register for the "Direct Mode" */ +#define SPI_DIRECT_WRITE_CONFIG_REG 0x20 + #define ORION_SPI_TMISO_SAMPLE_MASK (0x3 << 6) #define ORION_SPI_TMISO_SAMPLE_1 (1 << 6) #define ORION_SPI_TMISO_SAMPLE_2 (2 << 6) @@ -78,11 +82,18 @@ struct orion_spi_dev { bool is_errata_50mhz_ac; }; +struct orion_direct_acc { + void __iomem *vaddr; + u32 size; +}; + struct orion_spi { struct spi_master *master; void __iomem *base; struct clk *clk; const struct orion_spi_dev *devdata; + + struct orion_direct_acc direct_access[ORION_NUM_CHIPSELECTS]; }; static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg) @@ -372,10 +383,39 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) { unsigned int count; int word_len; + struct orion_spi *orion_spi; + int cs = spi->chip_select; word_len = spi->bits_per_word; count = xfer->len; + orion_spi = spi_master_get_devdata(spi->master); + + /* + * Use SPI direct write mode if base address is available. Otherwise + * fall back to PIO mode for this transfer. + */ + if ((orion_spi->direct_access[cs].vaddr) && (xfer->tx_buf) && + (word_len == 8)) { + unsigned int cnt = count / 4; + unsigned int rem = count % 4; + + /* + * Send the TX-data to the SPI device via the direct + * mapped address window + */ + iowrite32_rep(orion_spi->direct_access[cs].vaddr, + xfer->tx_buf, cnt); + if (rem) { + u32 *buf = (u32 *)xfer->tx_buf; + + iowrite8_rep(orion_spi->direct_access[cs].vaddr, + &buf[cnt], rem); + } + + return count; + } + if (word_len == 8) { const u8 *tx = xfer->tx_buf; u8 *rx = xfer->rx_buf; @@ -425,6 +465,10 @@ static int orion_spi_reset(struct orion_spi *orion_spi) { /* Verify that the CS is deasserted */ orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1); + + /* Don't deassert CS between the direct mapped SPI transfers */ + writel(0, spi_reg(orion_spi, SPI_DIRECT_WRITE_CONFIG_REG)); + return 0; } @@ -504,6 +548,7 @@ static int orion_spi_probe(struct platform_device *pdev) struct resource *r; unsigned long tclk_hz; int status = 0; + struct device_node *np; master = spi_alloc_master(&pdev->dev, sizeof(*spi)); if (master == NULL) { @@ -576,6 +621,49 @@ static int orion_spi_probe(struct platform_device *pdev) goto out_rel_clk; } + /* Scan all SPI devices of this controller for direct mapped devices */ + for_each_available_child_of_node(pdev->dev.of_node, np) { + u32 cs; + + /* Get chip-select number from the "reg" property */ + status = of_property_read_u32(np, "reg", &cs); + if (status) { + dev_err(&pdev->dev, + "%s has no valid 'reg' property (%d)\n", + np->full_name, status); + status = 0; + continue; + } + + /* + * Check if an address is configured for this SPI device. If + * not, the MBus mapping via the 'ranges' property in the 'soc' + * node is not configured and this device should not use the + * direct mode. In this case, just continue with the next + * device. + */ + status = of_address_to_resource(pdev->dev.of_node, cs + 1, r); + if (status) + continue; + + /* + * Only map one page for direct access. This is enough for the + * simple TX transfer which only writes to the first word. + * This needs to get extended for the direct SPI-NOR / SPI-NAND + * support, once this gets implemented. + */ + spi->direct_access[cs].vaddr = devm_ioremap(&pdev->dev, + r->start, + PAGE_SIZE); + if (!spi->direct_access[cs].vaddr) { + status = -ENOMEM; + goto out_rel_clk; + } + spi->direct_access[cs].size = PAGE_SIZE; + + dev_info(&pdev->dev, "CS%d configured for direct access\n", cs); + } + pm_runtime_set_active(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index ca3c8d94b290..c41abddab318 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -354,6 +354,7 @@ static int pic32_sqi_one_message(struct spi_master *master, struct spi_transfer *xfer; struct pic32_sqi *sqi; int ret = 0, mode; + unsigned long timeout; u32 val; sqi = spi_master_get_devdata(master); @@ -419,10 +420,10 @@ static int pic32_sqi_one_message(struct spi_master *master, writel(val, sqi->regs + PESQI_BD_CTRL_REG); /* wait for xfer completion */ - ret = wait_for_completion_timeout(&sqi->xfer_done, 5 * HZ); - if (ret <= 0) { + timeout = wait_for_completion_timeout(&sqi->xfer_done, 5 * HZ); + if (timeout == 0) { dev_err(&sqi->master->dev, "wait timedout/interrupted\n"); - ret = -EIO; + ret = -ETIMEDOUT; msg->status = ret; } else { /* success */ diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index 73db87f805a1..fefb688a3432 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -507,6 +507,7 @@ static int pic32_spi_one_transfer(struct spi_master *master, { struct pic32_spi *pic32s; bool dma_issued = false; + unsigned long timeout; int ret; pic32s = spi_master_get_devdata(master); @@ -553,8 +554,8 @@ static int pic32_spi_one_transfer(struct spi_master *master, } /* wait for completion */ - ret = wait_for_completion_timeout(&pic32s->xfer_done, 2 * HZ); - if (ret <= 0) { + timeout = wait_for_completion_timeout(&pic32s->xfer_done, 2 * HZ); + if (timeout == 0) { dev_err(&spi->dev, "wait error/timedout\n"); if (dma_issued) { dmaengine_terminate_all(master->dma_rx); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index fe07c0592b44..daf28443b7ad 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -585,7 +585,14 @@ static void reset_sccr1(struct driver_data *drv_data) u32 sccr1_reg; sccr1_reg = pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1; - sccr1_reg &= ~SSCR1_RFT; + switch (drv_data->ssp_type) { + case QUARK_X1000_SSP: + sccr1_reg &= ~QUARK_X1000_SSCR1_RFT; + break; + default: + sccr1_reg &= ~SSCR1_RFT; + break; + } sccr1_reg |= chip->threshold; pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg); } diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 1026e180eed7..7a58db4e3285 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -142,6 +142,12 @@ /* sclk_out: spi master internal logic in rk3x can support 50Mhz */ #define MAX_SCLK_OUT 50000000 +/* + * SPI_CTRLR1 is 16-bits, so we should support lengths of 0xffff + 1. However, + * the controller seems to hang when given 0x10000, so stick with this for now. + */ +#define ROCKCHIP_SPI_MAX_TRANLEN 0xffff + enum rockchip_ssi_type { SSI_MOTO_SPI = 0, SSI_TI_SSP, @@ -573,6 +579,11 @@ static void rockchip_spi_config(struct rockchip_spi *rs) dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div); } +static size_t rockchip_spi_max_transfer_size(struct spi_device *spi) +{ + return ROCKCHIP_SPI_MAX_TRANLEN; +} + static int rockchip_spi_transfer_one( struct spi_master *master, struct spi_device *spi, @@ -589,6 +600,11 @@ static int rockchip_spi_transfer_one( return -EINVAL; } + if (xfer->len > ROCKCHIP_SPI_MAX_TRANLEN) { + dev_err(rs->dev, "Transfer is too long (%d)\n", xfer->len); + return -EINVAL; + } + rs->speed = xfer->speed_hz; rs->bpw = xfer->bits_per_word; rs->n_bytes = rs->bpw >> 3; @@ -730,6 +746,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) master->prepare_message = rockchip_spi_prepare_message; master->unprepare_message = rockchip_spi_unprepare_message; master->transfer_one = rockchip_spi_transfer_one; + master->max_transfer_size = rockchip_spi_max_transfer_size; master->handle_err = rockchip_spi_handle_err; rs->dma_tx.ch = dma_request_chan(rs->dev, "tx"); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 77e6e45951f4..c9a8d544e467 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); |