Commit b859e7d1 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'spi-v3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi updates from Mark Brown:
 "Not a huge amount going on this release, mainly new drivers (there's a
  couple more waiting that didn't quite make the cut for this release
  too):

   - An interface for querying if the current transfer is the last in a
     message, allowing controllers that need special handling for the
     final transfer to use the core message parsing.
   - Support for Amlogic Meson SPIFC, Imagination Technologies SFPI,
     Intel Quark X1000 and Samsung Exynos 7 controllers"

* tag 'spi-v3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (38 commits)
  spi/s3c64xx: Remove redundant runtime PM management
  spi: fsl-spi: remove unused variable assignment
  spi: spi-fsl-spi: Return an error code in fsl_spi_do_one_msg()
  spi: core: Do not mangle error code from kthread_run()
  spi: fsl-espi: add (un)prepare_transfer_hardware calls to save power if SPI is not in use
  spi: fsl-(e)spi: migrate to generic master queueing
  spi/txx9: Deletion of an unnecessary check before the function call "clk_disable"
  spi: cadence: Fix 3-to-8 mux mode
  spi: cadence: Init HW after reading devicetree attributes
  spi: meson: Select REGMAP_MMIO
  spi: s3c64xx: add support for exynos7 SPI controller
  spi: spi-pxa2xx: SPI support for Intel Quark X1000
  spi: meson: meson_spifc_setup_speed() can be static
  spi: spi-pxa2xx: Add helpers for regiseters' accessing
  spi: spi-mxs: Fix mapping from vmalloc-ed buffer to scatter list
  spi: atmel: introduce probe deferring
  spi: atmel: remove compat for non DT board when requesting dma chan
  spi: meson: Add support for Amlogic Meson SPIFC
  spi: meson: Add device tree bindings documentation for SPIFC
  spi: core: Add spi_transfer_is_last() helper
  ...
parents 709d9f09 0e647037
...@@ -8,8 +8,10 @@ Required properties: ...@@ -8,8 +8,10 @@ Required properties:
- gpio-sck: GPIO spec for the SCK line to use - gpio-sck: GPIO spec for the SCK line to use
- gpio-miso: GPIO spec for the MISO line to use - gpio-miso: GPIO spec for the MISO line to use
- gpio-mosi: GPIO spec for the MOSI line to use - gpio-mosi: GPIO spec for the MOSI line to use
- cs-gpios: GPIOs to use for chipselect lines - cs-gpios: GPIOs to use for chipselect lines.
- num-chipselects: number of chipselect lines Not needed if num-chipselects = <0>.
- num-chipselects: Number of chipselect lines. Should be <0> if a single device
with no chip select is connected.
Example: Example:
......
IMG Synchronous Peripheral Flash Interface (SPFI) controller
Required properties:
- compatible: Must be "img,spfi".
- reg: Must contain the base address and length of the SPFI registers.
- interrupts: Must contain the SPFI interrupt.
- clocks: Must contain an entry for each entry in clock-names.
See ../clock/clock-bindings.txt for details.
- clock-names: Must include the following entries:
- spfi: SPI operating clock
- sys: SPI system interface clock
- dmas: Must contain an entry for each entry in dma-names.
See ../dma/dma.txt for details.
- dma-names: Must include the following entries:
- rx
- tx
- #address-cells: Must be 1.
- #size-cells: Must be 0.
Optional properties:
- img,supports-quad-mode: Should be set if the interface supports quad mode
SPI transfers.
Example:
spi@18100f00 {
compatible = "img,spfi";
reg = <0x18100f00 0x100>;
interrupts = <GIC_SHARED 22 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&spi_clk>, <&system_clk>;
clock-names = "spfi", "sys";
dmas = <&mdc 9 0xffffffff 0>, <&mdc 10 0xffffffff 0>;
dma-names = "rx", "tx";
#address-cells = <1>;
#size-cells = <0>;
};
Amlogic Meson SPI controllers
* SPIFC (SPI Flash Controller)
The Meson SPIFC is a controller optimized for communication with SPI
NOR memories, without DMA support and a 64-byte unified transmit /
receive buffer.
Required properties:
- compatible: should be "amlogic,meson6-spifc"
- reg: physical base address and length of the controller registers
- clocks: phandle of the input clock for the baud rate generator
- #address-cells: should be 1
- #size-cells: should be 0
spi@c1108c80 {
compatible = "amlogic,meson6-spifc";
reg = <0xc1108c80 0x80>;
clocks = <&clk81>;
#address-cells = <1>;
#size-cells = <0>;
};
...@@ -9,7 +9,7 @@ Required SoC Specific Properties: ...@@ -9,7 +9,7 @@ Required SoC Specific Properties:
- samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms - samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms
- samsung,s3c6410-spi: for s3c6410 platforms - samsung,s3c6410-spi: for s3c6410 platforms
- samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms - samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms
- samsung,exynos4210-spi: for exynos4 and exynos5 platforms - samsung,exynos7-spi: for exynos7 platforms
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
region. region.
......
...@@ -225,6 +225,13 @@ config SPI_GPIO ...@@ -225,6 +225,13 @@ config SPI_GPIO
GPIO operations, you should be able to leverage that for better GPIO operations, you should be able to leverage that for better
speed with a custom version of this driver; see the source code. speed with a custom version of this driver; see the source code.
config SPI_IMG_SPFI
tristate "IMG SPFI controller"
depends on MIPS || COMPILE_TEST
help
This enables support for the SPFI master controller found on
IMG SoCs.
config SPI_IMX config SPI_IMX
tristate "Freescale i.MX SPI controllers" tristate "Freescale i.MX SPI controllers"
depends on ARCH_MXC || COMPILE_TEST depends on ARCH_MXC || COMPILE_TEST
...@@ -301,6 +308,14 @@ config SPI_FSL_ESPI ...@@ -301,6 +308,14 @@ config SPI_FSL_ESPI
From MPC8536, 85xx platform uses the controller, and all P10xx, From MPC8536, 85xx platform uses the controller, and all P10xx,
P20xx, P30xx,P40xx, P50xx uses this controller. P20xx, P30xx,P40xx, P50xx uses this controller.
config SPI_MESON_SPIFC
tristate "Amlogic Meson SPIFC controller"
depends on ARCH_MESON || COMPILE_TEST
select REGMAP_MMIO
help
This enables master mode support for the SPIFC (SPI flash
controller) available in Amlogic Meson SoCs.
config SPI_OC_TINY config SPI_OC_TINY
tristate "OpenCores tiny SPI" tristate "OpenCores tiny SPI"
depends on GPIOLIB depends on GPIOLIB
...@@ -444,7 +459,7 @@ config SPI_S3C24XX_FIQ ...@@ -444,7 +459,7 @@ config SPI_S3C24XX_FIQ
config SPI_S3C64XX config SPI_S3C64XX
tristate "Samsung S3C64XX series type SPI" tristate "Samsung S3C64XX series type SPI"
depends on PLAT_SAMSUNG depends on (PLAT_SAMSUNG || ARCH_EXYNOS)
select S3C64XX_PL080 if ARCH_S3C64XX select S3C64XX_PL080 if ARCH_S3C64XX
help help
SPI driver for Samsung S3C64XX and newer SoCs. SPI driver for Samsung S3C64XX and newer SoCs.
......
...@@ -40,8 +40,10 @@ obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o ...@@ -40,8 +40,10 @@ obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
obj-$(CONFIG_SPI_GPIO) += spi-gpio.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o
obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o
obj-$(CONFIG_SPI_IMX) += spi-imx.o obj-$(CONFIG_SPI_IMX) += spi-imx.o
obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o
obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o
obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
/* SPI register offsets */ /* SPI register offsets */
#define SPI_CR 0x0000 #define SPI_CR 0x0000
...@@ -191,6 +192,8 @@ ...@@ -191,6 +192,8 @@
#define SPI_DMA_TIMEOUT (msecs_to_jiffies(1000)) #define SPI_DMA_TIMEOUT (msecs_to_jiffies(1000))
#define AUTOSUSPEND_TIMEOUT 2000
struct atmel_spi_dma { struct atmel_spi_dma {
struct dma_chan *chan_rx; struct dma_chan *chan_rx;
struct dma_chan *chan_tx; struct dma_chan *chan_tx;
...@@ -414,23 +417,6 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as, ...@@ -414,23 +417,6 @@ static int atmel_spi_dma_slave_config(struct atmel_spi *as,
return err; return err;
} }
static bool filter(struct dma_chan *chan, void *pdata)
{
struct atmel_spi_dma *sl_pdata = pdata;
struct at_dma_slave *sl;
if (!sl_pdata)
return false;
sl = &sl_pdata->dma_slave;
if (sl->dma_dev == chan->device->dev) {
chan->private = sl;
return true;
} else {
return false;
}
}
static int atmel_spi_configure_dma(struct atmel_spi *as) static int atmel_spi_configure_dma(struct atmel_spi *as)
{ {
struct dma_slave_config slave_config; struct dma_slave_config slave_config;
...@@ -441,19 +427,24 @@ static int atmel_spi_configure_dma(struct atmel_spi *as) ...@@ -441,19 +427,24 @@ static int atmel_spi_configure_dma(struct atmel_spi *as)
dma_cap_zero(mask); dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
as->dma.chan_tx = dma_request_slave_channel_compat(mask, filter, as->dma.chan_tx = dma_request_slave_channel_reason(dev, "tx");
&as->dma, if (IS_ERR(as->dma.chan_tx)) {
dev, "tx"); err = PTR_ERR(as->dma.chan_tx);
if (!as->dma.chan_tx) { if (err == -EPROBE_DEFER) {
dev_warn(dev, "no DMA channel available at the moment\n");
return err;
}
dev_err(dev, dev_err(dev,
"DMA TX channel not available, SPI unable to use DMA\n"); "DMA TX channel not available, SPI unable to use DMA\n");
err = -EBUSY; err = -EBUSY;
goto error; goto error;
} }
as->dma.chan_rx = dma_request_slave_channel_compat(mask, filter, /*
&as->dma, * No reason to check EPROBE_DEFER here since we have already requested
dev, "rx"); * tx channel. If it fails here, it's for another reason.
*/
as->dma.chan_rx = dma_request_slave_channel(dev, "rx");
if (!as->dma.chan_rx) { if (!as->dma.chan_rx) {
dev_err(dev, dev_err(dev,
...@@ -474,7 +465,7 @@ static int atmel_spi_configure_dma(struct atmel_spi *as) ...@@ -474,7 +465,7 @@ static int atmel_spi_configure_dma(struct atmel_spi *as)
error: error:
if (as->dma.chan_rx) if (as->dma.chan_rx)
dma_release_channel(as->dma.chan_rx); dma_release_channel(as->dma.chan_rx);
if (as->dma.chan_tx) if (!IS_ERR(as->dma.chan_tx))
dma_release_channel(as->dma.chan_tx); dma_release_channel(as->dma.chan_tx);
return err; return err;
} }
...@@ -482,11 +473,9 @@ static int atmel_spi_configure_dma(struct atmel_spi *as) ...@@ -482,11 +473,9 @@ static int atmel_spi_configure_dma(struct atmel_spi *as)
static void atmel_spi_stop_dma(struct atmel_spi *as) static void atmel_spi_stop_dma(struct atmel_spi *as)
{ {
if (as->dma.chan_rx) if (as->dma.chan_rx)
as->dma.chan_rx->device->device_control(as->dma.chan_rx, dmaengine_terminate_all(as->dma.chan_rx);
DMA_TERMINATE_ALL, 0);
if (as->dma.chan_tx) if (as->dma.chan_tx)
as->dma.chan_tx->device->device_control(as->dma.chan_tx, dmaengine_terminate_all(as->dma.chan_tx);
DMA_TERMINATE_ALL, 0);
} }
static void atmel_spi_release_dma(struct atmel_spi *as) static void atmel_spi_release_dma(struct atmel_spi *as)
...@@ -1315,6 +1304,7 @@ static int atmel_spi_probe(struct platform_device *pdev) ...@@ -1315,6 +1304,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
master->setup = atmel_spi_setup; master->setup = atmel_spi_setup;
master->transfer_one_message = atmel_spi_transfer_one_message; master->transfer_one_message = atmel_spi_transfer_one_message;
master->cleanup = atmel_spi_cleanup; master->cleanup = atmel_spi_cleanup;
master->auto_runtime_pm = true;
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
as = spi_master_get_devdata(master); as = spi_master_get_devdata(master);
...@@ -1347,8 +1337,11 @@ static int atmel_spi_probe(struct platform_device *pdev) ...@@ -1347,8 +1337,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
as->use_dma = false; as->use_dma = false;
as->use_pdc = false; as->use_pdc = false;
if (as->caps.has_dma_support) { if (as->caps.has_dma_support) {
if (atmel_spi_configure_dma(as) == 0) ret = atmel_spi_configure_dma(as);
if (ret == 0)
as->use_dma = true; as->use_dma = true;
else if (ret == -EPROBE_DEFER)
return ret;
} else { } else {
as->use_pdc = true; as->use_pdc = true;
} }
...@@ -1387,6 +1380,11 @@ static int atmel_spi_probe(struct platform_device *pdev) ...@@ -1387,6 +1380,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n", dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n",
(unsigned long)regs->start, irq); (unsigned long)regs->start, irq);
pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = devm_spi_register_master(&pdev->dev, master); ret = devm_spi_register_master(&pdev->dev, master);
if (ret) if (ret)
goto out_free_dma; goto out_free_dma;
...@@ -1394,6 +1392,9 @@ static int atmel_spi_probe(struct platform_device *pdev) ...@@ -1394,6 +1392,9 @@ static int atmel_spi_probe(struct platform_device *pdev)
return 0; return 0;
out_free_dma: out_free_dma:
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
if (as->use_dma) if (as->use_dma)
atmel_spi_release_dma(as); atmel_spi_release_dma(as);
...@@ -1415,6 +1416,8 @@ static int atmel_spi_remove(struct platform_device *pdev) ...@@ -1415,6 +1416,8 @@ static int atmel_spi_remove(struct platform_device *pdev)
struct spi_master *master = platform_get_drvdata(pdev); struct spi_master *master = platform_get_drvdata(pdev);
struct atmel_spi *as = spi_master_get_devdata(master); struct atmel_spi *as = spi_master_get_devdata(master);
pm_runtime_get_sync(&pdev->dev);
/* reset the hardware and block queue progress */ /* reset the hardware and block queue progress */
spin_lock_irq(&as->lock); spin_lock_irq(&as->lock);
if (as->use_dma) { if (as->use_dma) {
...@@ -1432,14 +1435,37 @@ static int atmel_spi_remove(struct platform_device *pdev) ...@@ -1432,14 +1435,37 @@ static int atmel_spi_remove(struct platform_device *pdev)
clk_disable_unprepare(as->clk); clk_disable_unprepare(as->clk);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
static int atmel_spi_runtime_suspend(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct atmel_spi *as = spi_master_get_devdata(master);
clk_disable_unprepare(as->clk);
pinctrl_pm_select_sleep_state(dev);
return 0;
}
static int atmel_spi_runtime_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct atmel_spi *as = spi_master_get_devdata(master);
pinctrl_pm_select_default_state(dev);
return clk_prepare_enable(as->clk);
}
static int atmel_spi_suspend(struct device *dev) static int atmel_spi_suspend(struct device *dev)
{ {
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct atmel_spi *as = spi_master_get_devdata(master);
int ret; int ret;
/* Stop the queue running */ /* Stop the queue running */
...@@ -1449,22 +1475,22 @@ static int atmel_spi_suspend(struct device *dev) ...@@ -1449,22 +1475,22 @@ static int atmel_spi_suspend(struct device *dev)
return ret; return ret;
} }
clk_disable_unprepare(as->clk); if (!pm_runtime_suspended(dev))
atmel_spi_runtime_suspend(dev);
pinctrl_pm_select_sleep_state(dev);
return 0; return 0;
} }
static int atmel_spi_resume(struct device *dev) static int atmel_spi_resume(struct device *dev)
{ {
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct atmel_spi *as = spi_master_get_devdata(master);
int ret; int ret;
pinctrl_pm_select_default_state(dev); if (!pm_runtime_suspended(dev)) {
ret = atmel_spi_runtime_resume(dev);
clk_prepare_enable(as->clk); if (ret)
return ret;
}
/* Start the queue running */ /* Start the queue running */
ret = spi_master_resume(master); ret = spi_master_resume(master);
...@@ -1474,8 +1500,11 @@ static int atmel_spi_resume(struct device *dev) ...@@ -1474,8 +1500,11 @@ static int atmel_spi_resume(struct device *dev)
return ret; return ret;
} }
static SIMPLE_DEV_PM_OPS(atmel_spi_pm_ops, atmel_spi_suspend, atmel_spi_resume); static const struct dev_pm_ops atmel_spi_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(atmel_spi_suspend, atmel_spi_resume)
SET_RUNTIME_PM_OPS(atmel_spi_runtime_suspend,
atmel_spi_runtime_resume, NULL)
};
#define ATMEL_SPI_PM_OPS (&atmel_spi_pm_ops) #define ATMEL_SPI_PM_OPS (&atmel_spi_pm_ops)
#else #else
#define ATMEL_SPI_PM_OPS NULL #define ATMEL_SPI_PM_OPS NULL
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#define CDNS_SPI_CR_CPHA_MASK 0x00000004 /* Clock Phase Control */ #define CDNS_SPI_CR_CPHA_MASK 0x00000004 /* Clock Phase Control */
#define CDNS_SPI_CR_CPOL_MASK 0x00000002 /* Clock Polarity Control */ #define CDNS_SPI_CR_CPOL_MASK 0x00000002 /* Clock Polarity Control */
#define CDNS_SPI_CR_SSCTRL_MASK 0x00003C00 /* Slave Select Mask */ #define CDNS_SPI_CR_SSCTRL_MASK 0x00003C00 /* Slave Select Mask */
#define CDNS_SPI_CR_PERI_SEL_MASK 0x00000200 /* Peripheral Select Decode */
#define CDNS_SPI_CR_BAUD_DIV_MASK 0x00000038 /* Baud Rate Divisor Mask */ #define CDNS_SPI_CR_BAUD_DIV_MASK 0x00000038 /* Baud Rate Divisor Mask */
#define CDNS_SPI_CR_MSTREN_MASK 0x00000001 /* Master Enable Mask */ #define CDNS_SPI_CR_MSTREN_MASK 0x00000001 /* Master Enable Mask */
#define CDNS_SPI_CR_MANSTRTEN_MASK 0x00008000 /* Manual TX Enable Mask */ #define CDNS_SPI_CR_MANSTRTEN_MASK 0x00008000 /* Manual TX Enable Mask */
...@@ -148,6 +149,11 @@ static inline void cdns_spi_write(struct cdns_spi *xspi, u32 offset, u32 val) ...@@ -148,6 +149,11 @@ static inline void cdns_spi_write(struct cdns_spi *xspi, u32 offset, u32 val)
*/ */
static void cdns_spi_init_hw(struct cdns_spi *xspi) static void cdns_spi_init_hw(struct cdns_spi *xspi)
{ {
u32 ctrl_reg = CDNS_SPI_CR_DEFAULT_MASK;
if (xspi->is_decoded_cs)
ctrl_reg |= CDNS_SPI_CR_PERI_SEL_MASK;
cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
CDNS_SPI_ER_DISABLE_MASK); CDNS_SPI_ER_DISABLE_MASK);
cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET,
...@@ -160,8 +166,7 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi) ...@@ -160,8 +166,7 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi)
cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET, cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET,
CDNS_SPI_IXR_ALL_MASK); CDNS_SPI_IXR_ALL_MASK);
cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg);
CDNS_SPI_CR_DEFAULT_MASK);
cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET,
CDNS_SPI_ER_ENABLE_MASK); CDNS_SPI_ER_ENABLE_MASK);
} }
...@@ -516,6 +521,17 @@ static int cdns_spi_probe(struct platform_device *pdev) ...@@ -516,6 +521,17 @@ static int cdns_spi_probe(struct platform_device *pdev)
goto clk_dis_apb; goto clk_dis_apb;
} }
ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
if (ret < 0)
master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS;
else
master->num_chipselect = num_cs;
ret = of_property_read_u32(pdev->dev.of_node, "is-decoded-cs",
&xspi->is_decoded_cs);
if (ret < 0)
xspi->is_decoded_cs = 0;
/* SPI controller initializations */ /* SPI controller initializations */
cdns_spi_init_hw(xspi); cdns_spi_init_hw(xspi);
...@@ -534,19 +550,6 @@ static int cdns_spi_probe(struct platform_device *pdev) ...@@ -534,19 +550,6 @@ static int cdns_spi_probe(struct platform_device *pdev)
goto remove_master; goto remove_master;
} }
ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
if (ret < 0)
master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS;
else
master->num_chipselect = num_cs;
ret = of_property_read_u32(pdev->dev.of_node, "is-decoded-cs",
&xspi->is_decoded_cs);
if (ret < 0)
xspi->is_decoded_cs = 0;
master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; master->prepare_transfer_hardware = cdns_prepare_transfer_hardware;
master->prepare_message = cdns_prepare_message; master->prepare_message = cdns_prepare_message;
master->transfer_one = cdns_transfer_one; master->transfer_one = cdns_transfer_one;
......
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
#include <linux/intel_mid_dma.h> #include <linux/intel_mid_dma.h>
#include <linux/pci.h> #include <linux/pci.h>
#define RX_BUSY 0
#define TX_BUSY 1
struct mid_dma { struct mid_dma {
struct intel_mid_dma_slave dmas_tx; struct intel_mid_dma_slave dmas_tx;
struct intel_mid_dma_slave dmas_rx; struct intel_mid_dma_slave dmas_rx;
...@@ -98,41 +101,26 @@ static void mid_spi_dma_exit(struct dw_spi *dws) ...@@ -98,41 +101,26 @@ static void mid_spi_dma_exit(struct dw_spi *dws)
} }
/* /*
* dws->dma_chan_done is cleared before the dma transfer starts, * dws->dma_chan_busy is set before the dma transfer starts, callback for tx
* callback for rx/tx channel will each increment it by 1. * channel will clear a corresponding bit.
* Reaching 2 means the whole spi transaction is done.
*/ */
static void dw_spi_dma_done(void *arg) static void dw_spi_dma_tx_done(void *arg)
{ {
struct dw_spi *dws = arg; struct dw_spi *dws = arg;
if (++dws->dma_chan_done != 2) if (test_and_clear_bit(TX_BUSY, &dws->dma_chan_busy) & BIT(RX_BUSY))
return; return;
dw_spi_xfer_done(dws); dw_spi_xfer_done(dws);
} }
static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) static struct dma_async_tx_descriptor *dw_spi_dma_prepare_tx(struct dw_spi *dws)
{ {
struct dma_async_tx_descriptor *txdesc, *rxdesc; struct dma_slave_config txconf;
struct dma_slave_config txconf, rxconf; struct dma_async_tx_descriptor *txdesc;
u16 dma_ctrl = 0;
/* 1. setup DMA related registers */
if (cs_change) {
spi_enable_chip(dws, 0);
dw_writew(dws, DW_SPI_DMARDLR, 0xf);
dw_writew(dws, DW_SPI_DMATDLR, 0x10);
if (dws->tx_dma)
dma_ctrl |= SPI_DMA_TDMAE;
if (dws->rx_dma)
dma_ctrl |= SPI_DMA_RDMAE;
dw_writew(dws, DW_SPI_DMACR, dma_ctrl);
spi_enable_chip(dws, 1);
}
dws->dma_chan_done = 0; if (!dws->tx_dma)
return NULL;
/* 2. Prepare the TX dma transfer */
txconf.direction = DMA_MEM_TO_DEV; txconf.direction = DMA_MEM_TO_DEV;
txconf.dst_addr = dws->dma_addr; txconf.dst_addr = dws->dma_addr;
txconf.dst_maxburst = LNW_DMA_MSIZE_16; txconf.dst_maxburst = LNW_DMA_MSIZE_16;
...@@ -151,10 +139,33 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) ...@@ -151,10 +139,33 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
1, 1,
DMA_MEM_TO_DEV, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
txdesc->callback = dw_spi_dma_done; txdesc->callback = dw_spi_dma_tx_done;
txdesc->callback_param = dws; txdesc->callback_param = dws;
/* 3. Prepare the RX dma transfer */ return txdesc;
}
/*
* dws->dma_chan_busy is set before the dma transfer starts, callback for rx
* channel will clear a corresponding bit.
*/
static void dw_spi_dma_rx_done(void *arg)
{
struct dw_spi *dws = arg;
if (test_and_clear_bit(RX_BUSY, &dws->dma_chan_busy) & BIT(TX_BUSY))
return;
dw_spi_xfer_done(dws);
}
static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws)
{
struct dma_slave_config rxconf;
struct dma_async_tx_descriptor *rxdesc;
if (!dws->rx_dma)
return NULL;
rxconf.direction = DMA_DEV_TO_MEM; rxconf.direction = DMA_DEV_TO_MEM;
rxconf.src_addr = dws->dma_addr; rxconf.src_addr = dws->dma_addr;
rxconf.src_maxburst = LNW_DMA_MSIZE_16; rxconf.src_maxburst = LNW_DMA_MSIZE_16;
...@@ -173,15 +184,56 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) ...@@ -173,15 +184,56 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
1, 1,
DMA_DEV_TO_MEM, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
rxdesc->callback = dw_spi_dma_done; rxdesc->callback = dw_spi_dma_rx_done;
rxdesc->callback_param = dws; rxdesc->callback_param = dws;
return rxdesc;
}
static void dw_spi_dma_setup(struct dw_spi *dws)
{
u16 dma_ctrl = 0;
spi_enable_chip(dws, 0);
dw_writew(dws, DW_SPI_DMARDLR, 0xf);
dw_writew(dws, DW_SPI_DMATDLR, 0x10);
if (dws->tx_dma)
dma_ctrl |= SPI_DMA_TDMAE;
if (dws->rx_dma)
dma_ctrl |= SPI_DMA_RDMAE;
dw_writew(dws, DW_SPI_DMACR, dma_ctrl);
spi_enable_chip(dws, 1);
}
static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
{
struct dma_async_tx_descriptor *txdesc, *rxdesc;
/* 1. setup DMA related registers */
if (cs_change)
dw_spi_dma_setup(dws);
/* 2. Prepare the TX dma transfer */
txdesc = dw_spi_dma_prepare_tx(dws);
/* 3. Prepare the RX dma transfer */
rxdesc = dw_spi_dma_prepare_rx(dws);
/* rx must be started before tx due to spi instinct */ /* rx must be started before tx due to spi instinct */
dmaengine_submit(rxdesc); if (rxdesc) {
dma_async_issue_pending(dws->rxchan); set_bit(RX_BUSY, &dws->dma_chan_busy);
dmaengine_submit(rxdesc);
dma_async_issue_pending(dws->rxchan);
}
dmaengine_submit(txdesc); if (txdesc) {
dma_async_issue_pending(dws->txchan); set_bit(TX_BUSY, &dws->dma_chan_busy);
dmaengine_submit(txdesc);
dma_async_issue_pending(dws->txchan);
}
return 0; return 0;
} }
......
...@@ -139,7 +139,7 @@ struct dw_spi { ...@@ -139,7 +139,7 @@ struct dw_spi {
struct scatterlist tx_sgl; struct scatterlist tx_sgl;
struct dma_chan *rxchan; struct dma_chan *rxchan;
struct scatterlist rx_sgl; struct scatterlist rx_sgl;
int dma_chan_done; unsigned long dma_chan_busy;
struct device *dma_dev; struct device *dma_dev;
dma_addr_t dma_addr; /* phy address of the Data register */ dma_addr_t dma_addr; /* phy address of the Data register */
struct dw_spi_dma_ops *dma_ops; struct dw_spi_dma_ops *dma_ops;
......
...@@ -56,12 +56,15 @@ void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi) ...@@ -56,12 +56,15 @@ void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi)
qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock, qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
QE_CR_PROTOCOL_UNSPECIFIED, 0); QE_CR_PROTOCOL_UNSPECIFIED, 0);
} else { } else {
cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
if (mspi->flags & SPI_CPM1) { if (mspi->flags & SPI_CPM1) {
out_be32(&mspi->pram->rstate, 0);
out_be16(&mspi->pram->rbptr, out_be16(&mspi->pram->rbptr,
in_be16(&mspi->pram->rbase)); in_be16(&mspi->pram->rbase));
out_be32(&mspi->pram->tstate, 0);
out_be16(&mspi->pram->tbptr, out_be16(&mspi->pram->tbptr,
in_be16(&mspi->pram->tbase)); in_be16(&mspi->pram->tbase));
} else {
cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
} }
} }
} }
......
...@@ -438,7 +438,7 @@ static int dspi_resume(struct device *dev) ...@@ -438,7 +438,7 @@ static int dspi_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(dspi_pm, dspi_suspend, dspi_resume); static SIMPLE_DEV_PM_OPS(dspi_pm, dspi_suspend, dspi_resume);
static struct regmap_config dspi_regmap_config = { static const struct regmap_config dspi_regmap_config = {
.reg_bits = 32, .reg_bits = 32,
.val_bits = 32, .val_bits = 32,
.reg_stride = 4, .reg_stride = 4,
...@@ -492,7 +492,6 @@ static int dspi_probe(struct platform_device *pdev) ...@@ -492,7 +492,6 @@ static int dspi_probe(struct platform_device *pdev)
goto out_master_put; goto out_master_put;
} }
dspi_regmap_config.lock_arg = dspi;
dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base, dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base,
&dspi_regmap_config); &dspi_regmap_config);
if (IS_ERR(dspi->regmap)) { if (IS_ERR(dspi->regmap)) {
......
...@@ -411,7 +411,8 @@ static void fsl_espi_rw_trans(struct spi_message *m, ...@@ -411,7 +411,8 @@ static void fsl_espi_rw_trans(struct spi_message *m,
kfree(local_buf); kfree(local_buf);
} }
static void fsl_espi_do_one_msg(struct spi_message *m) static int fsl_espi_do_one_msg(struct spi_master *master,
struct spi_message *m)
{ {
struct spi_transfer *t; struct spi_transfer *t;
u8 *rx_buf = NULL; u8 *rx_buf = NULL;
...@@ -441,8 +442,8 @@ static void fsl_espi_do_one_msg(struct spi_message *m) ...@@ -441,8 +442,8 @@ static void fsl_espi_do_one_msg(struct spi_message *m)
m->actual_length = espi_trans.actual_length; m->actual_length = espi_trans.actual_length;
m->status = espi_trans.status; m->status = espi_trans.status;
if (m->complete) spi_finalize_current_message(master);
m->complete(m->context); return 0;
} }
static int fsl_espi_setup(struct spi_device *spi) static int fsl_espi_setup(struct spi_device *spi)
...@@ -587,6 +588,38 @@ static void fsl_espi_remove(struct mpc8xxx_spi *mspi) ...@@ -587,6 +588,38 @@ static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
iounmap(mspi->reg_base); iounmap(mspi->reg_base);
} }
static int fsl_espi_suspend(struct spi_master *master)
{
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
u32 regval;
mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval &= ~SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
return 0;
}
static int fsl_espi_resume(struct spi_master *master)
{
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
u32 regval;
mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval |= SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
return 0;
}
static struct spi_master * fsl_espi_probe(struct device *dev, static struct spi_master * fsl_espi_probe(struct device *dev,
struct resource *mem, unsigned int irq) struct resource *mem, unsigned int irq)
{ {
...@@ -607,16 +640,16 @@ static struct spi_master * fsl_espi_probe(struct device *dev, ...@@ -607,16 +640,16 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
dev_set_drvdata(dev, master); dev_set_drvdata(dev, master);
ret = mpc8xxx_spi_probe(dev, mem, irq); mpc8xxx_spi_probe(dev, mem, irq);
if (ret)
goto err_probe;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
master->setup = fsl_espi_setup; master->setup = fsl_espi_setup;
master->cleanup = fsl_espi_cleanup; master->cleanup = fsl_espi_cleanup;
master->transfer_one_message = fsl_espi_do_one_msg;
master->prepare_transfer_hardware = fsl_espi_resume;
master->unprepare_transfer_hardware = fsl_espi_suspend;
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
mpc8xxx_spi->spi_remove = fsl_espi_remove; mpc8xxx_spi->spi_remove = fsl_espi_remove;
mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem)); mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
...@@ -762,25 +795,15 @@ static int of_fsl_espi_remove(struct platform_device *dev) ...@@ -762,25 +795,15 @@ static int of_fsl_espi_remove(struct platform_device *dev)
static int of_fsl_espi_suspend(struct device *dev) static int of_fsl_espi_suspend(struct device *dev)
{ {
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
u32 regval;
int ret; int ret;
mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
ret = spi_master_suspend(master); ret = spi_master_suspend(master);
if (ret) { if (ret) {
dev_warn(dev, "cannot suspend master\n"); dev_warn(dev, "cannot suspend master\n");
return ret; return ret;
} }
regval = mpc8xxx_spi_read_reg(&reg_base->mode); return fsl_espi_suspend(master);
regval &= ~SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
return 0;
} }
static int of_fsl_espi_resume(struct device *dev) static int of_fsl_espi_resume(struct device *dev)
......
...@@ -61,44 +61,6 @@ struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata) ...@@ -61,44 +61,6 @@ struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata)
return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata); return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
} }
static void mpc8xxx_spi_work(struct work_struct *work)
{
struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
work);
spin_lock_irq(&mpc8xxx_spi->lock);
while (!list_empty(&mpc8xxx_spi->queue)) {
struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
struct spi_message, queue);
list_del_init(&m->queue);
spin_unlock_irq(&mpc8xxx_spi->lock);
if (mpc8xxx_spi->spi_do_one_msg)
mpc8xxx_spi->spi_do_one_msg(m);
spin_lock_irq(&mpc8xxx_spi->lock);
}
spin_unlock_irq(&mpc8xxx_spi->lock);
}
int mpc8xxx_spi_transfer(struct spi_device *spi,
struct spi_message *m)
{
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
unsigned long flags;
m->actual_length = 0;
m->status = -EINPROGRESS;
spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
list_add_tail(&m->queue, &mpc8xxx_spi->queue);
queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
return 0;
}
const char *mpc8xxx_spi_strmode(unsigned int flags) const char *mpc8xxx_spi_strmode(unsigned int flags)
{ {
if (flags & SPI_QE_CPU_MODE) { if (flags & SPI_QE_CPU_MODE) {
...@@ -114,13 +76,12 @@ const char *mpc8xxx_spi_strmode(unsigned int flags) ...@@ -114,13 +76,12 @@ const char *mpc8xxx_spi_strmode(unsigned int flags)
return "CPU"; return "CPU";
} }
int mpc8xxx_spi_probe(struct device *dev, struct resource *mem, void mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
unsigned int irq) unsigned int irq)
{ {
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master; struct spi_master *master;
struct mpc8xxx_spi *mpc8xxx_spi; struct mpc8xxx_spi *mpc8xxx_spi;
int ret = 0;
master = dev_get_drvdata(dev); master = dev_get_drvdata(dev);
...@@ -128,7 +89,6 @@ int mpc8xxx_spi_probe(struct device *dev, struct resource *mem, ...@@ -128,7 +89,6 @@ int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
| SPI_LSB_FIRST | SPI_LOOP; | SPI_LSB_FIRST | SPI_LOOP;
master->transfer = mpc8xxx_spi_transfer;
master->dev.of_node = dev->of_node; master->dev.of_node = dev->of_node;
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
...@@ -147,22 +107,7 @@ int mpc8xxx_spi_probe(struct device *dev, struct resource *mem, ...@@ -147,22 +107,7 @@ int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
master->bus_num = pdata->bus_num; master->bus_num = pdata->bus_num;
master->num_chipselect = pdata->max_chipselect; master->num_chipselect = pdata->max_chipselect;
spin_lock_init(&mpc8xxx_spi->lock);
init_completion(&mpc8xxx_spi->done); init_completion(&mpc8xxx_spi->done);
INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
INIT_LIST_HEAD(&mpc8xxx_spi->queue);
mpc8xxx_spi->workqueue = create_singlethread_workqueue(
dev_name(master->dev.parent));
if (mpc8xxx_spi->workqueue == NULL) {
ret = -EBUSY;
goto err;
}
return 0;
err:
return ret;
} }
int mpc8xxx_spi_remove(struct device *dev) int mpc8xxx_spi_remove(struct device *dev)
...@@ -173,8 +118,6 @@ int mpc8xxx_spi_remove(struct device *dev) ...@@ -173,8 +118,6 @@ int mpc8xxx_spi_remove(struct device *dev)
master = dev_get_drvdata(dev); master = dev_get_drvdata(dev);
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
flush_workqueue(mpc8xxx_spi->workqueue);
destroy_workqueue(mpc8xxx_spi->workqueue);
spi_unregister_master(master); spi_unregister_master(master);
free_irq(mpc8xxx_spi->irq, mpc8xxx_spi); free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
......
...@@ -55,7 +55,6 @@ struct mpc8xxx_spi { ...@@ -55,7 +55,6 @@ struct mpc8xxx_spi {
u32(*get_tx) (struct mpc8xxx_spi *); u32(*get_tx) (struct mpc8xxx_spi *);
/* hooks for different controller driver */ /* hooks for different controller driver */
void (*spi_do_one_msg) (struct spi_message *m);
void (*spi_remove) (struct mpc8xxx_spi *mspi); void (*spi_remove) (struct mpc8xxx_spi *mspi);
unsigned int count; unsigned int count;
...@@ -78,12 +77,6 @@ struct mpc8xxx_spi { ...@@ -78,12 +77,6 @@ struct mpc8xxx_spi {
int bits_per_word, int msb_first); int bits_per_word, int msb_first);
#endif #endif
struct workqueue_struct *workqueue;
struct work_struct work;
struct list_head queue;
spinlock_t lock;
struct completion done; struct completion done;
}; };
...@@ -123,9 +116,8 @@ extern struct mpc8xxx_spi_probe_info *to_of_pinfo( ...@@ -123,9 +116,8 @@ extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
struct fsl_spi_platform_data *pdata); struct fsl_spi_platform_data *pdata);
extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi, extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
struct spi_transfer *t, unsigned int len); struct spi_transfer *t, unsigned int len);
extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m);
extern const char *mpc8xxx_spi_strmode(unsigned int flags); extern const char *mpc8xxx_spi_strmode(unsigned int flags);
extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem, extern void mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
unsigned int irq); unsigned int irq);
extern int mpc8xxx_spi_remove(struct device *dev); extern int mpc8xxx_spi_remove(struct device *dev);
extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev); extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev);
......
...@@ -353,7 +353,8 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t, ...@@ -353,7 +353,8 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
return mpc8xxx_spi->count; return mpc8xxx_spi->count;
} }
static void fsl_spi_do_one_msg(struct spi_message *m) static int fsl_spi_do_one_msg(struct spi_master *master,
struct spi_message *m)
{ {
struct spi_device *spi = m->spi; struct spi_device *spi = m->spi;
struct spi_transfer *t, *first; struct spi_transfer *t, *first;
...@@ -367,10 +368,9 @@ static void fsl_spi_do_one_msg(struct spi_message *m) ...@@ -367,10 +368,9 @@ static void fsl_spi_do_one_msg(struct spi_message *m)
list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) {
if ((first->bits_per_word != t->bits_per_word) || if ((first->bits_per_word != t->bits_per_word) ||
(first->speed_hz != t->speed_hz)) { (first->speed_hz != t->speed_hz)) {
status = -EINVAL;
dev_err(&spi->dev, dev_err(&spi->dev,
"bits_per_word/speed_hz should be same for the same SPI transfer\n"); "bits_per_word/speed_hz should be same for the same SPI transfer\n");
return; return -EINVAL;
} }
} }
...@@ -408,8 +408,7 @@ static void fsl_spi_do_one_msg(struct spi_message *m) ...@@ -408,8 +408,7 @@ static void fsl_spi_do_one_msg(struct spi_message *m)
} }
m->status = status; m->status = status;
if (m->complete) spi_finalize_current_message(master);
m->complete(m->context);
if (status || !cs_change) { if (status || !cs_change) {
ndelay(nsecs); ndelay(nsecs);
...@@ -417,6 +416,7 @@ static void fsl_spi_do_one_msg(struct spi_message *m) ...@@ -417,6 +416,7 @@ static void fsl_spi_do_one_msg(struct spi_message *m)
} }
fsl_spi_setup_transfer(spi, NULL); fsl_spi_setup_transfer(spi, NULL);
return 0;
} }
static int fsl_spi_setup(struct spi_device *spi) static int fsl_spi_setup(struct spi_device *spi)
...@@ -624,15 +624,13 @@ static struct spi_master * fsl_spi_probe(struct device *dev, ...@@ -624,15 +624,13 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
dev_set_drvdata(dev, master); dev_set_drvdata(dev, master);
ret = mpc8xxx_spi_probe(dev, mem, irq); mpc8xxx_spi_probe(dev, mem, irq);
if (ret)
goto err_probe;
master->setup = fsl_spi_setup; master->setup = fsl_spi_setup;
master->cleanup = fsl_spi_cleanup; master->cleanup = fsl_spi_cleanup;
master->transfer_one_message = fsl_spi_do_one_msg;
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg;
mpc8xxx_spi->spi_remove = fsl_spi_remove; mpc8xxx_spi->spi_remove = fsl_spi_remove;
mpc8xxx_spi->max_bits_per_word = 32; mpc8xxx_spi->max_bits_per_word = 32;
mpc8xxx_spi->type = fsl_spi_get_type(dev); mpc8xxx_spi->type = fsl_spi_get_type(dev);
...@@ -704,7 +702,6 @@ static struct spi_master * fsl_spi_probe(struct device *dev, ...@@ -704,7 +702,6 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
err_ioremap: err_ioremap:
fsl_spi_cpm_free(mpc8xxx_spi); fsl_spi_cpm_free(mpc8xxx_spi);
err_cpm_init: err_cpm_init:
err_probe:
spi_master_put(master); spi_master_put(master);
err: err:
return ERR_PTR(ret); return ERR_PTR(ret);
......
...@@ -48,7 +48,7 @@ struct spi_gpio { ...@@ -48,7 +48,7 @@ struct spi_gpio {
struct spi_bitbang bitbang; struct spi_bitbang bitbang;
struct spi_gpio_platform_data pdata; struct spi_gpio_platform_data pdata;
struct platform_device *pdev; struct platform_device *pdev;
int cs_gpios[0]; unsigned long cs_gpios[0];
}; };
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
...@@ -220,7 +220,7 @@ static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi, ...@@ -220,7 +220,7 @@ static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,
static void spi_gpio_chipselect(struct spi_device *spi, int is_active) static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
{ {
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
unsigned int cs = spi_gpio->cs_gpios[spi->chip_select]; unsigned long cs = spi_gpio->cs_gpios[spi->chip_select];
/* set initial clock polarity */ /* set initial clock polarity */
if (is_active) if (is_active)
...@@ -234,7 +234,7 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active) ...@@ -234,7 +234,7 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
static int spi_gpio_setup(struct spi_device *spi) static int spi_gpio_setup(struct spi_device *spi)
{ {
unsigned int cs; unsigned long cs;
int status = 0; int status = 0;
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
struct device_node *np = spi->master->dev.of_node; struct device_node *np = spi->master->dev.of_node;
...@@ -249,7 +249,7 @@ static int spi_gpio_setup(struct spi_device *spi) ...@@ -249,7 +249,7 @@ static int spi_gpio_setup(struct spi_device *spi)
/* /*
* ... otherwise, take it from spi->controller_data * ... otherwise, take it from spi->controller_data
*/ */
cs = (unsigned int)(uintptr_t) spi->controller_data; cs = (uintptr_t) spi->controller_data;
} }
if (!spi->controller_state) { if (!spi->controller_state) {
...@@ -277,7 +277,7 @@ static int spi_gpio_setup(struct spi_device *spi) ...@@ -277,7 +277,7 @@ static int spi_gpio_setup(struct spi_device *spi)
static void spi_gpio_cleanup(struct spi_device *spi) static void spi_gpio_cleanup(struct spi_device *spi)
{ {
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
unsigned int cs = spi_gpio->cs_gpios[spi->chip_select]; unsigned long cs = spi_gpio->cs_gpios[spi->chip_select];
if (cs != SPI_GPIO_NO_CHIPSELECT) if (cs != SPI_GPIO_NO_CHIPSELECT)
gpio_free(cs); gpio_free(cs);
...@@ -413,6 +413,7 @@ static int spi_gpio_probe(struct platform_device *pdev) ...@@ -413,6 +413,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
struct spi_gpio_platform_data *pdata; struct spi_gpio_platform_data *pdata;
u16 master_flags = 0; u16 master_flags = 0;
bool use_of = 0; bool use_of = 0;
int num_devices;
status = spi_gpio_probe_dt(pdev); status = spi_gpio_probe_dt(pdev);
if (status < 0) if (status < 0)
...@@ -422,16 +423,21 @@ static int spi_gpio_probe(struct platform_device *pdev) ...@@ -422,16 +423,21 @@ static int spi_gpio_probe(struct platform_device *pdev)
pdata = dev_get_platdata(&pdev->dev); pdata = dev_get_platdata(&pdev->dev);
#ifdef GENERIC_BITBANG #ifdef GENERIC_BITBANG
if (!pdata || !pdata->num_chipselect) if (!pdata || (!use_of && !pdata->num_chipselect))
return -ENODEV; return -ENODEV;
#endif #endif
if (use_of && !SPI_N_CHIPSEL)
num_devices = 1;
else
num_devices = SPI_N_CHIPSEL;
status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags); status = spi_gpio_request(pdata, dev_name(&pdev->dev), &master_flags);
if (status < 0) if (status < 0)
return status; return status;
master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio) + master = spi_alloc_master(&pdev->dev, sizeof(*spi_gpio) +
(sizeof(int) * SPI_N_CHIPSEL)); (sizeof(unsigned long) * num_devices));
if (!master) { if (!master) {
status = -ENOMEM; status = -ENOMEM;
goto gpio_free; goto gpio_free;
...@@ -446,7 +452,7 @@ static int spi_gpio_probe(struct platform_device *pdev) ...@@ -446,7 +452,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
master->flags = master_flags; master->flags = master_flags;
master->bus_num = pdev->id; master->bus_num = pdev->id;
master->num_chipselect = SPI_N_CHIPSEL; master->num_chipselect = num_devices;
master->setup = spi_gpio_setup; master->setup = spi_gpio_setup;
master->cleanup = spi_gpio_cleanup; master->cleanup = spi_gpio_cleanup;
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -461,9 +467,18 @@ static int spi_gpio_probe(struct platform_device *pdev) ...@@ -461,9 +467,18 @@ static int spi_gpio_probe(struct platform_device *pdev)
* property of the node. * property of the node.
*/ */
for (i = 0; i < SPI_N_CHIPSEL; i++) if (!SPI_N_CHIPSEL)
spi_gpio->cs_gpios[i] = spi_gpio->cs_gpios[0] = SPI_GPIO_NO_CHIPSELECT;
of_get_named_gpio(np, "cs-gpios", i); else
for (i = 0; i < SPI_N_CHIPSEL; i++) {
status = of_get_named_gpio(np, "cs-gpios", i);
if (status < 0) {
dev_err(&pdev->dev,
"invalid cs-gpios property\n");
goto gpio_free;
}
spi_gpio->cs_gpios[i] = status;
}
} }
#endif #endif
......
This diff is collapsed.
This diff is collapsed.
...@@ -182,7 +182,6 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, ...@@ -182,7 +182,6 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi,
int min, ret; int min, ret;
u32 ctrl0; u32 ctrl0;
struct page *vm_page; struct page *vm_page;
void *sg_buf;
struct { struct {
u32 pio[4]; u32 pio[4];
struct scatterlist sg; struct scatterlist sg;
...@@ -232,13 +231,14 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, ...@@ -232,13 +231,14 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi,
ret = -ENOMEM; ret = -ENOMEM;
goto err_vmalloc; goto err_vmalloc;
} }
sg_buf = page_address(vm_page) +
((size_t)buf & ~PAGE_MASK); sg_init_table(&dma_xfer[sg_count].sg, 1);
sg_set_page(&dma_xfer[sg_count].sg, vm_page,
min, offset_in_page(buf));
} else { } else {
sg_buf = buf; sg_init_one(&dma_xfer[sg_count].sg, buf, min);
} }
sg_init_one(&dma_xfer[sg_count].sg, sg_buf, min);
ret = dma_map_sg(ssp->dev, &dma_xfer[sg_count].sg, 1, ret = dma_map_sg(ssp->dev, &dma_xfer[sg_count].sg, 1,
(flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); (flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
...@@ -511,7 +511,7 @@ static int mxs_spi_probe(struct platform_device *pdev) ...@@ -511,7 +511,7 @@ static int mxs_spi_probe(struct platform_device *pdev)
init_completion(&spi->c); init_completion(&spi->c);
ret = devm_request_irq(&pdev->dev, irq_err, mxs_ssp_irq_handler, 0, ret = devm_request_irq(&pdev->dev, irq_err, mxs_ssp_irq_handler, 0,
DRIVER_NAME, ssp); dev_name(&pdev->dev), ssp);
if (ret) if (ret)
goto out_master_free; goto out_master_free;
......
...@@ -19,6 +19,7 @@ enum { ...@@ -19,6 +19,7 @@ enum {
PORT_BSW0, PORT_BSW0,
PORT_BSW1, PORT_BSW1,
PORT_BSW2, PORT_BSW2,
PORT_QUARK_X1000,
}; };
struct pxa_spi_info { struct pxa_spi_info {
...@@ -92,6 +93,12 @@ static struct pxa_spi_info spi_info_configs[] = { ...@@ -92,6 +93,12 @@ static struct pxa_spi_info spi_info_configs[] = {
.tx_param = &bsw2_tx_param, .tx_param = &bsw2_tx_param,
.rx_param = &bsw2_rx_param, .rx_param = &bsw2_rx_param,
}, },
[PORT_QUARK_X1000] = {
.type = QUARK_X1000_SSP,
.port_id = -1,
.num_chipselect = 1,
.max_clk_rate = 50000000,
},
}; };
static int pxa2xx_spi_pci_probe(struct pci_dev *dev, static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
...@@ -191,6 +198,7 @@ static void pxa2xx_spi_pci_remove(struct pci_dev *dev) ...@@ -191,6 +198,7 @@ static void pxa2xx_spi_pci_remove(struct pci_dev *dev)
static const struct pci_device_id pxa2xx_spi_pci_devices[] = { static const struct pci_device_id pxa2xx_spi_pci_devices[] = {
{ PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 }, { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 },
{ PCI_VDEVICE(INTEL, 0x0935), PORT_QUARK_X1000 },
{ PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT }, { PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT },
{ PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 }, { PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 },
{ PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 }, { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 },
......
This diff is collapsed.
...@@ -93,6 +93,7 @@ struct driver_data { ...@@ -93,6 +93,7 @@ struct driver_data {
struct chip_data { struct chip_data {
u32 cr0; u32 cr0;
u32 cr1; u32 cr1;
u32 dds_rate;
u32 psp; u32 psp;
u32 timeout; u32 timeout;
u8 n_bytes; u8 n_bytes;
...@@ -126,6 +127,7 @@ DEFINE_SSP_REG(SSCR1, 0x04) ...@@ -126,6 +127,7 @@ DEFINE_SSP_REG(SSCR1, 0x04)
DEFINE_SSP_REG(SSSR, 0x08) DEFINE_SSP_REG(SSSR, 0x08)
DEFINE_SSP_REG(SSITR, 0x0c) DEFINE_SSP_REG(SSITR, 0x0c)
DEFINE_SSP_REG(SSDR, 0x10) DEFINE_SSP_REG(SSDR, 0x10)
DEFINE_SSP_REG(DDS_RATE, 0x28) /* DDS Clock Rate */
DEFINE_SSP_REG(SSTO, 0x28) DEFINE_SSP_REG(SSTO, 0x28)
DEFINE_SSP_REG(SSPSP, 0x2c) DEFINE_SSP_REG(SSPSP, 0x2c)
DEFINE_SSP_REG(SSITF, SSITF) DEFINE_SSP_REG(SSITF, SSITF)
...@@ -141,18 +143,22 @@ DEFINE_SSP_REG(SSIRF, SSIRF) ...@@ -141,18 +143,22 @@ DEFINE_SSP_REG(SSIRF, SSIRF)
static inline int pxa25x_ssp_comp(struct driver_data *drv_data) static inline int pxa25x_ssp_comp(struct driver_data *drv_data)
{ {
if (drv_data->ssp_type == PXA25x_SSP) switch (drv_data->ssp_type) {
case PXA25x_SSP:
case CE4100_SSP:
case QUARK_X1000_SSP:
return 1; return 1;
if (drv_data->ssp_type == CE4100_SSP) default:
return 1; return 0;
return 0; }
} }
static inline void write_SSSR_CS(struct driver_data *drv_data, u32 val) static inline void write_SSSR_CS(struct driver_data *drv_data, u32 val)
{ {
void __iomem *reg = drv_data->ioaddr; void __iomem *reg = drv_data->ioaddr;
if (drv_data->ssp_type == CE4100_SSP) if (drv_data->ssp_type == CE4100_SSP ||
drv_data->ssp_type == QUARK_X1000_SSP)
val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK; val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
write_SSSR(val, reg); write_SSSR(val, reg);
......
...@@ -749,8 +749,6 @@ static int rockchip_spi_remove(struct platform_device *pdev) ...@@ -749,8 +749,6 @@ static int rockchip_spi_remove(struct platform_device *pdev)
if (rs->dma_rx.ch) if (rs->dma_rx.ch)
dma_release_channel(rs->dma_rx.ch); dma_release_channel(rs->dma_rx.ch);
spi_master_put(master);
return 0; return 0;
} }
......
...@@ -33,8 +33,9 @@ ...@@ -33,8 +33,9 @@
#include <linux/platform_data/spi-s3c64xx.h> #include <linux/platform_data/spi-s3c64xx.h>
#define MAX_SPI_PORTS 3 #define MAX_SPI_PORTS 6
#define S3C64XX_SPI_QUIRK_POLL (1 << 0) #define S3C64XX_SPI_QUIRK_POLL (1 << 0)
#define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1)
/* Registers and bit-fields */ /* Registers and bit-fields */
...@@ -78,6 +79,7 @@ ...@@ -78,6 +79,7 @@
#define S3C64XX_SPI_SLAVE_AUTO (1<<1) #define S3C64XX_SPI_SLAVE_AUTO (1<<1)
#define S3C64XX_SPI_SLAVE_SIG_INACT (1<<0) #define S3C64XX_SPI_SLAVE_SIG_INACT (1<<0)
#define S3C64XX_SPI_SLAVE_NSC_CNT_2 (2<<4)
#define S3C64XX_SPI_INT_TRAILING_EN (1<<6) #define S3C64XX_SPI_INT_TRAILING_EN (1<<6)
#define S3C64XX_SPI_INT_RX_OVERRUN_EN (1<<5) #define S3C64XX_SPI_INT_RX_OVERRUN_EN (1<<5)
...@@ -344,16 +346,8 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) ...@@ -344,16 +346,8 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
spi->dma_tx = sdd->tx_dma.ch; spi->dma_tx = sdd->tx_dma.ch;
} }
ret = pm_runtime_get_sync(&sdd->pdev->dev);
if (ret < 0) {
dev_err(dev, "Failed to enable device: %d\n", ret);
goto out_tx;
}
return 0; return 0;
out_tx:
dma_release_channel(sdd->tx_dma.ch);
out_rx: out_rx:
dma_release_channel(sdd->rx_dma.ch); dma_release_channel(sdd->rx_dma.ch);
out: out:
...@@ -370,7 +364,6 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi) ...@@ -370,7 +364,6 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
dma_release_channel(sdd->tx_dma.ch); dma_release_channel(sdd->tx_dma.ch);
} }
pm_runtime_put(&sdd->pdev->dev);
return 0; return 0;
} }
...@@ -717,7 +710,12 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, ...@@ -717,7 +710,12 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
enable_datapath(sdd, spi, xfer, use_dma); enable_datapath(sdd, spi, xfer, use_dma);
/* Start the signals */ /* Start the signals */
writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
else
writel(readl(sdd->regs + S3C64XX_SPI_SLAVE_SEL)
| S3C64XX_SPI_SLAVE_AUTO | S3C64XX_SPI_SLAVE_NSC_CNT_2,
sdd->regs + S3C64XX_SPI_SLAVE_SEL);
spin_unlock_irqrestore(&sdd->lock, flags); spin_unlock_irqrestore(&sdd->lock, flags);
...@@ -866,13 +864,15 @@ static int s3c64xx_spi_setup(struct spi_device *spi) ...@@ -866,13 +864,15 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
} }
pm_runtime_put(&sdd->pdev->dev); pm_runtime_put(&sdd->pdev->dev);
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
return 0; return 0;
setup_exit: setup_exit:
pm_runtime_put(&sdd->pdev->dev); pm_runtime_put(&sdd->pdev->dev);
/* setup() returns with device de-selected */ /* setup() returns with device de-selected */
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
if (gpio_is_valid(spi->cs_gpio)) if (gpio_is_valid(spi->cs_gpio))
gpio_free(spi->cs_gpio); gpio_free(spi->cs_gpio);
...@@ -946,7 +946,8 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) ...@@ -946,7 +946,8 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
sdd->cur_speed = 0; sdd->cur_speed = 0;
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); if (!(sdd->port_conf->quirks & S3C64XX_SPI_QUIRK_CS_AUTO))
writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
/* Disable Interrupts - we use Polling if not DMA mode */ /* Disable Interrupts - we use Polling if not DMA mode */
writel(0, regs + S3C64XX_SPI_INT_EN); writel(0, regs + S3C64XX_SPI_INT_EN);
...@@ -1341,6 +1342,15 @@ static struct s3c64xx_spi_port_config exynos5440_spi_port_config = { ...@@ -1341,6 +1342,15 @@ static struct s3c64xx_spi_port_config exynos5440_spi_port_config = {
.quirks = S3C64XX_SPI_QUIRK_POLL, .quirks = S3C64XX_SPI_QUIRK_POLL,
}; };
static struct s3c64xx_spi_port_config exynos7_spi_port_config = {
.fifo_lvl_mask = { 0x1ff, 0x7F, 0x7F, 0x7F, 0x7F, 0x1ff},
.rx_lvl_offset = 15,
.tx_st_done = 25,
.high_speed = true,
.clk_from_cmu = true,
.quirks = S3C64XX_SPI_QUIRK_CS_AUTO,
};
static struct platform_device_id s3c64xx_spi_driver_ids[] = { static struct platform_device_id s3c64xx_spi_driver_ids[] = {
{ {
.name = "s3c2443-spi", .name = "s3c2443-spi",
...@@ -1374,6 +1384,9 @@ static const struct of_device_id s3c64xx_spi_dt_match[] = { ...@@ -1374,6 +1384,9 @@ static const struct of_device_id s3c64xx_spi_dt_match[] = {
{ .compatible = "samsung,exynos5440-spi", { .compatible = "samsung,exynos5440-spi",
.data = (void *)&exynos5440_spi_port_config, .data = (void *)&exynos5440_spi_port_config,
}, },
{ .compatible = "samsung,exynos7-spi",
.data = (void *)&exynos7_spi_port_config,
},
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match); MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/dma-direction.h> #include <linux/dma-direction.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/reset.h>
#define DRIVER_NAME "sirfsoc_spi" #define DRIVER_NAME "sirfsoc_spi"
...@@ -134,6 +135,7 @@ ...@@ -134,6 +135,7 @@
ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE)) ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE))
#define SIRFSOC_MAX_CMD_BYTES 4 #define SIRFSOC_MAX_CMD_BYTES 4
#define SIRFSOC_SPI_DEFAULT_FRQ 1000000
struct sirfsoc_spi { struct sirfsoc_spi {
struct spi_bitbang bitbang; struct spi_bitbang bitbang;
...@@ -629,9 +631,6 @@ static int spi_sirfsoc_setup(struct spi_device *spi) ...@@ -629,9 +631,6 @@ static int spi_sirfsoc_setup(struct spi_device *spi)
{ {
struct sirfsoc_spi *sspi; struct sirfsoc_spi *sspi;
if (!spi->max_speed_hz)
return -EINVAL;
sspi = spi_master_get_devdata(spi->master); sspi = spi_master_get_devdata(spi->master);
if (spi->cs_gpio == -ENOENT) if (spi->cs_gpio == -ENOENT)
...@@ -649,6 +648,12 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -649,6 +648,12 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
int irq; int irq;
int i, ret; int i, ret;
ret = device_reset(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "SPI reset failed!\n");
return ret;
}
master = spi_alloc_master(&pdev->dev, sizeof(*sspi)); master = spi_alloc_master(&pdev->dev, sizeof(*sspi));
if (!master) { if (!master) {
dev_err(&pdev->dev, "Unable to allocate SPI master\n"); dev_err(&pdev->dev, "Unable to allocate SPI master\n");
...@@ -683,6 +688,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -683,6 +688,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) | master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) |
SPI_BPW_MASK(16) | SPI_BPW_MASK(32); SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
master->max_speed_hz = SIRFSOC_SPI_DEFAULT_FRQ;
sspi->bitbang.master->dev.of_node = pdev->dev.of_node; sspi->bitbang.master->dev.of_node = pdev->dev.of_node;
/* request DMA channels */ /* request DMA channels */
......
...@@ -402,8 +402,7 @@ static int txx9spi_probe(struct platform_device *dev) ...@@ -402,8 +402,7 @@ static int txx9spi_probe(struct platform_device *dev)
exit: exit:
if (c->workqueue) if (c->workqueue)
destroy_workqueue(c->workqueue); destroy_workqueue(c->workqueue);
if (c->clk) clk_disable(c->clk);
clk_disable(c->clk);
spi_master_put(master); spi_master_put(master);
return ret; return ret;
} }
......
...@@ -1001,7 +1001,7 @@ static int spi_init_queue(struct spi_master *master) ...@@ -1001,7 +1001,7 @@ static int spi_init_queue(struct spi_master *master)
dev_name(&master->dev)); dev_name(&master->dev));
if (IS_ERR(master->kworker_task)) { if (IS_ERR(master->kworker_task)) {
dev_err(&master->dev, "failed to create message pump task\n"); dev_err(&master->dev, "failed to create message pump task\n");
return -ENOMEM; return PTR_ERR(master->kworker_task);
} }
init_kthread_work(&master->pump_messages, spi_pump_messages); init_kthread_work(&master->pump_messages, spi_pump_messages);
......
...@@ -87,6 +87,7 @@ struct spidev_data { ...@@ -87,6 +87,7 @@ struct spidev_data {
unsigned users; unsigned users;
u8 *tx_buffer; u8 *tx_buffer;
u8 *rx_buffer; u8 *rx_buffer;
u32 speed_hz;
}; };
static LIST_HEAD(device_list); static LIST_HEAD(device_list);
...@@ -138,6 +139,7 @@ spidev_sync_write(struct spidev_data *spidev, size_t len) ...@@ -138,6 +139,7 @@ spidev_sync_write(struct spidev_data *spidev, size_t len)
struct spi_transfer t = { struct spi_transfer t = {
.tx_buf = spidev->tx_buffer, .tx_buf = spidev->tx_buffer,
.len = len, .len = len,
.speed_hz = spidev->speed_hz,
}; };
struct spi_message m; struct spi_message m;
...@@ -152,6 +154,7 @@ spidev_sync_read(struct spidev_data *spidev, size_t len) ...@@ -152,6 +154,7 @@ spidev_sync_read(struct spidev_data *spidev, size_t len)
struct spi_transfer t = { struct spi_transfer t = {
.rx_buf = spidev->rx_buffer, .rx_buf = spidev->rx_buffer,
.len = len, .len = len,
.speed_hz = spidev->speed_hz,
}; };
struct spi_message m; struct spi_message m;
...@@ -274,6 +277,8 @@ static int spidev_message(struct spidev_data *spidev, ...@@ -274,6 +277,8 @@ static int spidev_message(struct spidev_data *spidev,
k_tmp->bits_per_word = u_tmp->bits_per_word; k_tmp->bits_per_word = u_tmp->bits_per_word;
k_tmp->delay_usecs = u_tmp->delay_usecs; k_tmp->delay_usecs = u_tmp->delay_usecs;
k_tmp->speed_hz = u_tmp->speed_hz; k_tmp->speed_hz = u_tmp->speed_hz;
if (!k_tmp->speed_hz)
k_tmp->speed_hz = spidev->speed_hz;
#ifdef VERBOSE #ifdef VERBOSE
dev_dbg(&spidev->spi->dev, dev_dbg(&spidev->spi->dev,
" xfer len %zd %s%s%s%dbits %u usec %uHz\n", " xfer len %zd %s%s%s%dbits %u usec %uHz\n",
...@@ -377,7 +382,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -377,7 +382,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = __put_user(spi->bits_per_word, (__u8 __user *)arg); retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);
break; break;
case SPI_IOC_RD_MAX_SPEED_HZ: case SPI_IOC_RD_MAX_SPEED_HZ:
retval = __put_user(spi->max_speed_hz, (__u32 __user *)arg); retval = __put_user(spidev->speed_hz, (__u32 __user *)arg);
break; break;
/* write requests */ /* write requests */
...@@ -441,10 +446,11 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -441,10 +446,11 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
spi->max_speed_hz = tmp; spi->max_speed_hz = tmp;
retval = spi_setup(spi); retval = spi_setup(spi);
if (retval < 0) if (retval >= 0)
spi->max_speed_hz = save; spidev->speed_hz = tmp;
else else
dev_dbg(&spi->dev, "%d Hz (max)\n", tmp); dev_dbg(&spi->dev, "%d Hz (max)\n", tmp);
spi->max_speed_hz = save;
} }
break; break;
...@@ -570,6 +576,8 @@ static int spidev_release(struct inode *inode, struct file *filp) ...@@ -570,6 +576,8 @@ static int spidev_release(struct inode *inode, struct file *filp)
kfree(spidev->rx_buffer); kfree(spidev->rx_buffer);
spidev->rx_buffer = NULL; spidev->rx_buffer = NULL;
spidev->speed_hz = spidev->spi->max_speed_hz;
/* ... after we unbound from the underlying device? */ /* ... after we unbound from the underlying device? */
spin_lock_irq(&spidev->spi_lock); spin_lock_irq(&spidev->spi_lock);
dofree = (spidev->spi == NULL); dofree = (spidev->spi == NULL);
...@@ -650,6 +658,8 @@ static int spidev_probe(struct spi_device *spi) ...@@ -650,6 +658,8 @@ static int spidev_probe(struct spi_device *spi)
} }
mutex_unlock(&device_list_lock); mutex_unlock(&device_list_lock);
spidev->speed_hz = spi->max_speed_hz;
if (status == 0) if (status == 0)
spi_set_drvdata(spi, spidev); spi_set_drvdata(spi, spidev);
else else
......
...@@ -108,6 +108,25 @@ ...@@ -108,6 +108,25 @@
#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */ #define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */
#endif #endif
/* QUARK_X1000 SSCR0 bit definition */
#define QUARK_X1000_SSCR0_DSS (0x1F) /* Data Size Select (mask) */
#define QUARK_X1000_SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..32] */
#define QUARK_X1000_SSCR0_FRF (0x3 << 5) /* FRame Format (mask) */
#define QUARK_X1000_SSCR0_Motorola (0x0 << 5) /* Motorola's Serial Peripheral Interface (SPI) */
#define RX_THRESH_QUARK_X1000_DFLT 1
#define TX_THRESH_QUARK_X1000_DFLT 16
#define QUARK_X1000_SSSR_TFL_MASK (0x1F << 8) /* Transmit FIFO Level mask */
#define QUARK_X1000_SSSR_RFL_MASK (0x1F << 13) /* Receive FIFO Level mask */
#define QUARK_X1000_SSCR1_TFT (0x1F << 6) /* Transmit FIFO Threshold (mask) */
#define QUARK_X1000_SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..32] */
#define QUARK_X1000_SSCR1_RFT (0x1F << 11) /* Receive FIFO Threshold (mask) */
#define QUARK_X1000_SSCR1_RxTresh(x) (((x) - 1) << 11) /* level [1..32] */
#define QUARK_X1000_SSCR1_STRF (1 << 17) /* Select FIFO or EFWR */
#define QUARK_X1000_SSCR1_EFWR (1 << 16) /* Enable FIFO Write/Read */
/* extra bits in PXA255, PXA26x and PXA27x SSP ports */ /* extra bits in PXA255, PXA26x and PXA27x SSP ports */
#define SSCR0_TISSP (1 << 4) /* TI Sync Serial Protocol */ #define SSCR0_TISSP (1 << 4) /* TI Sync Serial Protocol */
#define SSCR0_PSP (3 << 4) /* PSP - Programmable Serial Protocol */ #define SSCR0_PSP (3 << 4) /* PSP - Programmable Serial Protocol */
...@@ -175,6 +194,7 @@ enum pxa_ssp_type { ...@@ -175,6 +194,7 @@ enum pxa_ssp_type {
PXA910_SSP, PXA910_SSP,
CE4100_SSP, CE4100_SSP,
LPSS_SSP, LPSS_SSP,
QUARK_X1000_SSP,
}; };
struct ssp_device { struct ssp_device {
......
...@@ -1049,4 +1049,10 @@ spi_unregister_device(struct spi_device *spi) ...@@ -1049,4 +1049,10 @@ spi_unregister_device(struct spi_device *spi)
extern const struct spi_device_id * extern const struct spi_device_id *
spi_get_device_id(const struct spi_device *sdev); spi_get_device_id(const struct spi_device *sdev);
static inline bool
spi_transfer_is_last(struct spi_master *master, struct spi_transfer *xfer)
{
return list_is_last(&xfer->transfer_list, &master->cur_msg->transfers);
}
#endif /* __LINUX_SPI_H */ #endif /* __LINUX_SPI_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment