Merge remote-tracking branches 'spi/topic/octeon', 'spi/topic/omap2-mcspi', 'spi/topic/orion', 'spi/topic/pic32' and 'spi/topic/pic32-sqi' into spi-next
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 @@
- "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 @@
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 @@
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>;
diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt
index 42d5954..1782286 100644
--- a/Documentation/devicetree/bindings/spi/spi-bus.txt
+++ b/Documentation/devicetree/bindings/spi/spi-bus.txt
@@ -8,11 +8,10 @@
The SPI master node requires the following properties:
- #address-cells - number of cells required to define a chip select
- address on the SPI bus.
+ address on the SPI bus.
- #size-cells - should be zero.
- compatible - name of SPI bus controller following generic names
- recommended practice.
-- cs-gpios - (optional) gpios chip select.
+ recommended practice.
No other properties are required in the SPI bus node. It is assumed
that a driver for an SPI bus device will understand that it is an SPI bus.
However, the binding does not attempt to define the specific method for
@@ -22,11 +21,12 @@
chip selects. Individual drivers can define additional properties to
support describing the chip select layout.
-Optional property:
-- num-cs : total number of chipselects
+Optional properties:
+- cs-gpios - gpios chip select.
+- num-cs - total number of chipselects.
-If cs-gpios is used the number of chip select will automatically increased
-with max(cs-gpios > hw cs)
+If cs-gpios is used the number of chip selects will be increased automatically
+with max(cs-gpios > hw cs).
So if for example the controller has 2 CS lines, and the cs-gpios
property looks like this:
@@ -45,29 +45,30 @@
contain the following properties.
- reg - (required) chip select address of device.
- compatible - (required) name of SPI device following generic names
- recommended practice
-- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
+ recommended practice.
+- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz.
- spi-cpol - (optional) Empty property indicating device requires
- inverse clock polarity (CPOL) mode
+ inverse clock polarity (CPOL) mode.
- spi-cpha - (optional) Empty property indicating device requires
- shifted clock phase (CPHA) mode
+ shifted clock phase (CPHA) mode.
- spi-cs-high - (optional) Empty property indicating device requires
- chip select active high
+ chip select active high.
- spi-3wire - (optional) Empty property indicating device requires
- 3-wire mode.
+ 3-wire mode.
- spi-lsb-first - (optional) Empty property indicating device requires
LSB first mode.
-- spi-tx-bus-width - (optional) The bus width(number of data wires) that
+- spi-tx-bus-width - (optional) The bus width (number of data wires) that is
used for MOSI. Defaults to 1 if not present.
-- spi-rx-bus-width - (optional) The bus width(number of data wires) that
+- spi-rx-bus-width - (optional) The bus width (number of data wires) that is
used for MISO. Defaults to 1 if not present.
- spi-rx-delay-us - (optional) Microsecond delay after a read transfer.
- spi-tx-delay-us - (optional) Microsecond delay after a write transfer.
Some SPI controllers and devices support Dual and Quad SPI transfer mode.
-It allows data in the SPI system to be transferred in 2 wires(DUAL) or 4 wires(QUAD).
+It allows data in the SPI system to be transferred using 2 wires (DUAL) or 4
+wires (QUAD).
Now the value that spi-tx-bus-width and spi-rx-bus-width can receive is
-only 1(SINGLE), 2(DUAL) and 4(QUAD).
+only 1 (SINGLE), 2 (DUAL) and 4 (QUAD).
Dual/Quad mode is not allowed when 3-wire mode is used.
If a gpio chipselect is used for the SPI slave the gpio number will be passed
diff --git a/Documentation/devicetree/bindings/spi/spi-clps711x.txt b/Documentation/devicetree/bindings/spi/spi-clps711x.txt
new file mode 100644
index 0000000..4c3ec13
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-clps711x.txt
@@ -0,0 +1,33 @@
+Serial Peripheral Interface on Cirrus Logic CL-PS71xx, EP72xx, EP73xx
+
+Required properties
+- #address-cells: must be <1>
+- #size-cells: must be <0>
+- compatible: should include "cirrus,ep7209-spi"
+- reg: Address and length of one register range
+- interrupts: one interrupt line
+- clocks: One entry, refers to the SPI bus clock
+- cs-gpios: Specifies the gpio pins to be used for chipselects.
+ See: Documentation/devicetree/bindings/spi/spi-bus.txt
+
+An additional register is present in the system controller,
+which is assumed to be in the same device tree, with and marked
+as compatible with "cirrus,ep7209-syscon3".
+
+Example:
+
+spi@80000500 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "cirrus,ep7209-spi";
+ reg = <0x80000500 0x4>;
+ interrupts = <15>;
+ clocks = <&clks CLPS711X_CLK_SPI>;
+ status = "disabled";
+};
+
+syscon3: syscon@80002200 {
+ compatible = "cirrus,ep7209-syscon3", "syscon";
+ reg = <0x80002200 0x40>;
+};
+
diff --git a/Documentation/devicetree/bindings/spi/spi-davinci.txt b/Documentation/devicetree/bindings/spi/spi-davinci.txt
index d1e914a..f5916c9 100644
--- a/Documentation/devicetree/bindings/spi/spi-davinci.txt
+++ b/Documentation/devicetree/bindings/spi/spi-davinci.txt
@@ -21,7 +21,7 @@
IP to the interrupt controller within the SoC. Possible values
are 0 and 1. Manual says one of the two possible interrupt
lines can be tied to the interrupt controller. Set this
- based on a specifc SoC configuration.
+ based on a specific SoC configuration.
- interrupts: interrupt number mapped to CPU.
- clocks: spi clk phandle
diff --git a/Documentation/devicetree/bindings/spi/spi-orion.txt b/Documentation/devicetree/bindings/spi/spi-orion.txt
index 98bc698..4f629cc 100644
--- a/Documentation/devicetree/bindings/spi/spi-orion.txt
+++ b/Documentation/devicetree/bindings/spi/spi-orion.txt
@@ -8,7 +8,15 @@
- "marvell,armada-380-spi", for the Armada 38x SoCs
- "marvell,armada-390-spi", for the Armada 39x SoCs
- "marvell,armada-xp-spi", for the Armada XP SoCs
-- reg : offset and length of the register set for the device
+- reg : offset and length of the register set for the device.
+ This property can optionally have additional entries to configure
+ the SPI direct access mode that some of the Marvell SoCs support
+ additionally to the normal indirect access (PIO) mode. The values
+ for the MBus "target" and "attribute" are defined in the Marvell
+ SoC "Functional Specifications" Manual in the chapter "Marvell
+ Core Processor Address Decoding".
+ The eight register sets following the control registers refer to
+ chip-select lines 0 through 7 respectively.
- cell-index : Which of multiple SPI controllers is this.
Optional properties:
- interrupts : Is currently not used.
@@ -23,3 +31,42 @@
interrupts = <23>;
status = "disabled";
};
+
+Example with SPI direct mode support (optionally):
+ spi0: spi@10600 {
+ compatible = "marvell,orion-spi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ reg = <MBUS_ID(0xf0, 0x01) 0x10600 0x28>, /* control */
+ <MBUS_ID(0x01, 0x1e) 0 0xffffffff>, /* CS0 */
+ <MBUS_ID(0x01, 0x5e) 0 0xffffffff>, /* CS1 */
+ <MBUS_ID(0x01, 0x9e) 0 0xffffffff>, /* CS2 */
+ <MBUS_ID(0x01, 0xde) 0 0xffffffff>, /* CS3 */
+ <MBUS_ID(0x01, 0x1f) 0 0xffffffff>, /* CS4 */
+ <MBUS_ID(0x01, 0x5f) 0 0xffffffff>, /* CS5 */
+ <MBUS_ID(0x01, 0x9f) 0 0xffffffff>, /* CS6 */
+ <MBUS_ID(0x01, 0xdf) 0 0xffffffff>; /* CS7 */
+ interrupts = <23>;
+ status = "disabled";
+ };
+
+To enable the direct mode, the board specific 'ranges' property in the
+'soc' node needs to add the entries for the desired SPI controllers
+and its chip-selects that are used in the direct mode instead of PIO
+mode. Here an example for this (SPI controller 0, device 1 and SPI
+controller 1, device 2 are used in direct mode. All other SPI device
+are used in the default indirect (PIO) mode):
+ soc {
+ /*
+ * Enable the SPI direct access by configuring an entry
+ * here in the board-specific ranges property
+ */
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000>, /* internal regs */
+ <MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>, /* BootROM */
+ <MBUS_ID(0x01, 0x5e) 0 0 0xf1100000 0x10000>, /* SPI0-DEV1 */
+ <MBUS_ID(0x01, 0x9a) 0 0 0xf1110000 0x10000>; /* SPI1-DEV2 */
+
+For further information on the MBus bindings, please see the MBus
+DT documentation:
+Documentation/devicetree/bindings/bus/mvebu-mbus.txt
diff --git a/Documentation/devicetree/bindings/spi/ti_qspi.txt b/Documentation/devicetree/bindings/spi/ti_qspi.txt
index 50b14f6..e65fde4 100644
--- a/Documentation/devicetree/bindings/spi/ti_qspi.txt
+++ b/Documentation/devicetree/bindings/spi/ti_qspi.txt
@@ -20,7 +20,7 @@
chipselect register and offset of that register.
NOTE: TI QSPI controller requires different pinmux and IODelay
-paramaters for Mode-0 and Mode-3 operations, which needs to be set up by
+parameters for Mode-0 and Mode-3 operations, which needs to be set up by
the bootloader (U-Boot). Default configuration only supports Mode-0
operation. Hence, "spi-cpol" and "spi-cpha" DT properties cannot be
specified in the slave nodes of TI QSPI controller without appropriate
diff --git a/MAINTAINERS b/MAINTAINERS
index 8c20323..7aa632f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10799,6 +10799,7 @@
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/
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 4b931ec..d6fb8d4 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -411,6 +411,7 @@
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 6c96755..01d0ba9 100644
--- a/drivers/spi/spi-bfin-sport.c
+++ b/drivers/spi/spi-bfin-sport.c
@@ -64,8 +64,6 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 1e91325..249c7a3 100644
--- a/drivers/spi/spi-bfin5xx.c
+++ b/drivers/spi/spi-bfin5xx.c
@@ -67,8 +67,6 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 8c30de0..18193df 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 @@
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 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 @@
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 @@
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 @@
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 50769078..f63cb30 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_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 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 @@
(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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
return ret;
}
- spi_imx->devtype_data->config(spi_imx, &config);
+ spi_imx->devtype_data->config(spi, &config);
return 0;
}
@@ -1050,6 +1042,8 @@
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 @@
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_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 @@
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 @@
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 @@
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 cf4bb36..faa1b13 100644
--- a/drivers/spi/spi-loopback-test.c
+++ b/drivers/spi/spi-loopback-test.c
@@ -536,7 +536,7 @@
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 72d11eb..42a8b85 100644
--- a/drivers/spi/spi-mpc52xx-psc.c
+++ b/drivers/spi/spi-mpc52xx-psc.c
@@ -42,7 +42,6 @@
u8 bits_per_word;
u8 busy;
- struct workqueue_struct *workqueue;
struct work_struct work;
struct list_head queue;
@@ -299,7 +298,7 @@
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 @@
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 @@
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 1d237e9..d5157b2 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -419,16 +419,13 @@
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 @@
{
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 @@
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 @@
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;
- sg_init_table(&sg, 1);
- sg_dma_address(&sg) = xfer->rx_dma;
- sg_dma_len(&sg) = dma_count;
+ 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;
+ }
- tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1,
- DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT |
- DMA_CTRL_ACK);
+ ret = sg_split(xfer->rx_sg.sgl, xfer->rx_sg.nents,
+ 0, nb_sizes,
+ sizes,
+ sg_out, out_mapped_nents,
+ GFP_KERNEL);
+
+ if (ret < 0) {
+ dev_err(&spi->dev, "sg_split failed\n");
+ return 0;
+ }
+
+ 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_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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
+ 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 @@
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 @@
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 a87cfd4..ded3702 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 @@
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 @@
{
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 @@
{
/* 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 @@
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 @@
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 ca3c8d9..c41abdd 100644
--- a/drivers/spi/spi-pic32-sqi.c
+++ b/drivers/spi/spi-pic32-sqi.c
@@ -354,6 +354,7 @@
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 @@
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 73db87f..fefb688 100644
--- a/drivers/spi/spi-pic32.c
+++ b/drivers/spi/spi-pic32.c
@@ -507,6 +507,7 @@
{
struct pic32_spi *pic32s;
bool dma_issued = false;
+ unsigned long timeout;
int ret;
pic32s = spi_master_get_devdata(master);
@@ -553,8 +554,8 @@
}
/* 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 fe07c05..daf2844 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -585,7 +585,14 @@
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 1026e18..7a58db4 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 @@
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 @@
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 @@
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 77e6e45..c9a8d54 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -849,6 +849,20 @@
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 @@
{
struct spi_master *master = spi->master;
+ struct device *rx_dev = NULL;
int ret;
if ((msg->opcode_nbits == SPI_NBITS_DUAL ||
@@ -2750,9 +2765,22 @@
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 @@
* @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 @@
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 */