Commit 3aad3f03 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'spi-for-linus' of git://git.secretlab.ca/git/linux

Pull SPI changes from Grant Likely:
 "Changes to both core spi code and spi device drivers.  The driver
  changes are the usual set of bug fixes and platform enablement.

  Core code changes include:

   - More intelligent assignment of SPI bus numbers when using DT

   - Common mechanism for using gpios as CS lines

   - Pull checks for bits_per_word and transfer speed out of drivers and
     into core code

   - Ensure temporary DMA buffers are DMA safe"

* tag 'spi-for-linus' of git://git.secretlab.ca/git/linux: (50 commits)
  spi: Document cs_gpios and cs_gpio in kernel-doc
  spi/of: Fix initialization of cs_gpios array
  spi/pxa2xx: add support for Lynxpoint SPI controllers
  spi/pxa2xx: add support for Intel Low Power Subsystem SPI
  spi/pxa2xx: add support for SPI_LOOP
  spi/pxa2xx: add support for runtime PM
  spi/pxa2xx: add support for DMA engine
  spi/pxa2xx: break out the private DMA API usage into a separate file
  spi/ath79: add shutdown handler
  spi/mips-lantiq: set SPI_MASTER_HALF_DUPLEX flag
  spi/mips-lantiq: make use of spi_finalize_current_message
  spi/bcm63xx: work around inability to keep CS up
  spi/davinci: use request_threaded_irq() to fix deadlock
  spi/orion: Use module_platform_driver()
  spi/bcm63xx: reject transfers unable to transfer
  spi: Ensure memory used for spi_write_then_read() is DMA safe
  spi/spi-mpc512x-psc: init mode bits supported by the driver
  spi/mpc512x-psc: don't use obsolet cell-index property
  spi: Remove erroneous __init, __exit and __exit_p() references in drivers
  spi/s3c64xx: fix checkpatch warnings and error
  ...
parents 10b6339e 095c3752
Renesas MSIOF spi controller
Required properties:
- compatible : "renesas,sh-msiof" for SuperH or
"renesas,sh-mobile-msiof" for SH Mobile series
- reg : Offset and length of the register set for the device
- interrupts : interrupt line used by MSIOF
Optional properties:
- num-cs : total number of chip-selects
- renesas,tx-fifo-size : Overrides the default tx fifo size given in words
- renesas,rx-fifo-size : Overrides the default rx fifo size given in words
...@@ -7168,6 +7168,7 @@ F: drivers/clk/spear/ ...@@ -7168,6 +7168,7 @@ F: drivers/clk/spear/
SPI SUBSYSTEM SPI SUBSYSTEM
M: Grant Likely <grant.likely@secretlab.ca> M: Grant Likely <grant.likely@secretlab.ca>
M: Mark Brown <broonie@opensource.wolfsonmicro.com>
L: spi-devel-general@lists.sourceforge.net L: spi-devel-general@lists.sourceforge.net
Q: http://patchwork.kernel.org/project/spi-devel-general/list/ Q: http://patchwork.kernel.org/project/spi-devel-general/list/
T: git git://git.secretlab.ca/git/linux-2.6.git T: git git://git.secretlab.ca/git/linux-2.6.git
......
...@@ -297,9 +297,20 @@ config SPI_PPC4xx ...@@ -297,9 +297,20 @@ config SPI_PPC4xx
help help
This selects a driver for the PPC4xx SPI Controller. This selects a driver for the PPC4xx SPI Controller.
config SPI_PXA2XX_PXADMA
bool "PXA2xx SSP legacy PXA DMA API support"
depends on SPI_PXA2XX && ARCH_PXA
help
Enable PXA private legacy DMA API support. Note that this is
deprecated in favor of generic DMA engine API.
config SPI_PXA2XX_DMA
def_bool y
depends on SPI_PXA2XX && !SPI_PXA2XX_PXADMA
config SPI_PXA2XX config SPI_PXA2XX
tristate "PXA2xx SSP SPI master" tristate "PXA2xx SSP SPI master"
depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL depends on ARCH_PXA || PCI || ACPI
select PXA_SSP if ARCH_PXA select PXA_SSP if ARCH_PXA
help help
This enables using a PXA2xx or Sodaville SSP port as a SPI master This enables using a PXA2xx or Sodaville SSP port as a SPI master
...@@ -307,7 +318,7 @@ config SPI_PXA2XX ...@@ -307,7 +318,7 @@ config SPI_PXA2XX
additional documentation can be found a Documentation/spi/pxa2xx. additional documentation can be found a Documentation/spi/pxa2xx.
config SPI_PXA2XX_PCI config SPI_PXA2XX_PCI
def_bool SPI_PXA2XX && X86_32 && PCI def_tristate SPI_PXA2XX && PCI
config SPI_RSPI config SPI_RSPI
tristate "Renesas RSPI controller" tristate "Renesas RSPI controller"
......
...@@ -47,7 +47,10 @@ obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o ...@@ -47,7 +47,10 @@ obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o
obj-$(CONFIG_SPI_ORION) += spi-orion.o obj-$(CONFIG_SPI_ORION) += spi-orion.o
obj-$(CONFIG_SPI_PL022) += spi-pl022.o obj-$(CONFIG_SPI_PL022) += spi-pl022.o
obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx.o spi-pxa2xx-platform-objs := spi-pxa2xx.o
spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_PXADMA) += spi-pxa2xx-pxadma.o
spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o
obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
......
...@@ -134,7 +134,7 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t) ...@@ -134,7 +134,7 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
hw->tx = t->tx_buf; hw->tx = t->tx_buf;
hw->rx = t->rx_buf; hw->rx = t->rx_buf;
hw->count = 0; hw->count = 0;
hw->bytes_per_word = (t->bits_per_word ? : spi->bits_per_word) / 8; hw->bytes_per_word = t->bits_per_word / 8;
hw->len = t->len / hw->bytes_per_word; hw->len = t->len / hw->bytes_per_word;
if (hw->irq >= 0) { if (hw->irq >= 0) {
......
...@@ -24,17 +24,24 @@ ...@@ -24,17 +24,24 @@
#include <linux/spi/spi_bitbang.h> #include <linux/spi/spi_bitbang.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <asm/mach-ath79/ar71xx_regs.h> #include <asm/mach-ath79/ar71xx_regs.h>
#include <asm/mach-ath79/ath79_spi_platform.h> #include <asm/mach-ath79/ath79_spi_platform.h>
#define DRV_NAME "ath79-spi" #define DRV_NAME "ath79-spi"
#define ATH79_SPI_RRW_DELAY_FACTOR 12000
#define MHZ (1000 * 1000)
struct ath79_spi { struct ath79_spi {
struct spi_bitbang bitbang; struct spi_bitbang bitbang;
u32 ioc_base; u32 ioc_base;
u32 reg_ctrl; u32 reg_ctrl;
void __iomem *base; void __iomem *base;
struct clk *clk;
unsigned rrw_delay;
}; };
static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg) static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
...@@ -52,6 +59,12 @@ static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi) ...@@ -52,6 +59,12 @@ static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi)
return spi_master_get_devdata(spi->master); return spi_master_get_devdata(spi->master);
} }
static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned nsecs)
{
if (nsecs > sp->rrw_delay)
ndelay(nsecs - sp->rrw_delay);
}
static void ath79_spi_chipselect(struct spi_device *spi, int is_active) static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
{ {
struct ath79_spi *sp = ath79_spidev_to_sp(spi); struct ath79_spi *sp = ath79_spidev_to_sp(spi);
...@@ -83,15 +96,8 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active) ...@@ -83,15 +96,8 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
} }
static int ath79_spi_setup_cs(struct spi_device *spi) static void ath79_spi_enable(struct ath79_spi *sp)
{ {
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
struct ath79_spi_controller_data *cdata;
cdata = spi->controller_data;
if (spi->chip_select && !cdata)
return -EINVAL;
/* enable GPIO mode */ /* enable GPIO mode */
ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
...@@ -101,44 +107,48 @@ static int ath79_spi_setup_cs(struct spi_device *spi) ...@@ -101,44 +107,48 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
/* TODO: setup speed? */ /* TODO: setup speed? */
ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
}
if (spi->chip_select) { static void ath79_spi_disable(struct ath79_spi *sp)
int status = 0; {
/* restore CTRL register */
ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
/* disable GPIO mode */
ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
}
status = gpio_request(cdata->gpio, dev_name(&spi->dev)); static int ath79_spi_setup_cs(struct spi_device *spi)
if (status) {
return status; struct ath79_spi_controller_data *cdata;
int status;
status = gpio_direction_output(cdata->gpio, cdata = spi->controller_data;
spi->mode & SPI_CS_HIGH); if (spi->chip_select && !cdata)
if (status) { return -EINVAL;
gpio_free(cdata->gpio);
return status; status = 0;
} if (spi->chip_select) {
} else { unsigned long flags;
flags = GPIOF_DIR_OUT;
if (spi->mode & SPI_CS_HIGH) if (spi->mode & SPI_CS_HIGH)
sp->ioc_base |= AR71XX_SPI_IOC_CS0; flags |= GPIOF_INIT_HIGH;
else else
sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; flags |= GPIOF_INIT_LOW;
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
status = gpio_request_one(cdata->gpio, flags,
dev_name(&spi->dev));
} }
return 0; return status;
} }
static void ath79_spi_cleanup_cs(struct spi_device *spi) static void ath79_spi_cleanup_cs(struct spi_device *spi)
{ {
struct ath79_spi *sp = ath79_spidev_to_sp(spi);
if (spi->chip_select) { if (spi->chip_select) {
struct ath79_spi_controller_data *cdata = spi->controller_data; struct ath79_spi_controller_data *cdata = spi->controller_data;
gpio_free(cdata->gpio); gpio_free(cdata->gpio);
} }
/* restore CTRL register */
ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
/* disable GPIO mode */
ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
} }
static int ath79_spi_setup(struct spi_device *spi) static int ath79_spi_setup(struct spi_device *spi)
...@@ -184,7 +194,11 @@ static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs, ...@@ -184,7 +194,11 @@ static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
/* setup MSB (to slave) on trailing edge */ /* setup MSB (to slave) on trailing edge */
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out); ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
ath79_spi_delay(sp, nsecs);
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK); ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
ath79_spi_delay(sp, nsecs);
if (bits == 1)
ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
word <<= 1; word <<= 1;
} }
...@@ -198,6 +212,7 @@ static int ath79_spi_probe(struct platform_device *pdev) ...@@ -198,6 +212,7 @@ static int ath79_spi_probe(struct platform_device *pdev)
struct ath79_spi *sp; struct ath79_spi *sp;
struct ath79_spi_platform_data *pdata; struct ath79_spi_platform_data *pdata;
struct resource *r; struct resource *r;
unsigned long rate;
int ret; int ret;
master = spi_alloc_master(&pdev->dev, sizeof(*sp)); master = spi_alloc_master(&pdev->dev, sizeof(*sp));
...@@ -236,12 +251,39 @@ static int ath79_spi_probe(struct platform_device *pdev) ...@@ -236,12 +251,39 @@ static int ath79_spi_probe(struct platform_device *pdev)
goto err_put_master; goto err_put_master;
} }
sp->clk = clk_get(&pdev->dev, "ahb");
if (IS_ERR(sp->clk)) {
ret = PTR_ERR(sp->clk);
goto err_unmap;
}
ret = clk_enable(sp->clk);
if (ret)
goto err_clk_put;
rate = DIV_ROUND_UP(clk_get_rate(sp->clk), MHZ);
if (!rate) {
ret = -EINVAL;
goto err_clk_disable;
}
sp->rrw_delay = ATH79_SPI_RRW_DELAY_FACTOR / rate;
dev_dbg(&pdev->dev, "register read/write delay is %u nsecs\n",
sp->rrw_delay);
ath79_spi_enable(sp);
ret = spi_bitbang_start(&sp->bitbang); ret = spi_bitbang_start(&sp->bitbang);
if (ret) if (ret)
goto err_unmap; goto err_disable;
return 0; return 0;
err_disable:
ath79_spi_disable(sp);
err_clk_disable:
clk_disable(sp->clk);
err_clk_put:
clk_put(sp->clk);
err_unmap: err_unmap:
iounmap(sp->base); iounmap(sp->base);
err_put_master: err_put_master:
...@@ -256,6 +298,9 @@ static int ath79_spi_remove(struct platform_device *pdev) ...@@ -256,6 +298,9 @@ static int ath79_spi_remove(struct platform_device *pdev)
struct ath79_spi *sp = platform_get_drvdata(pdev); struct ath79_spi *sp = platform_get_drvdata(pdev);
spi_bitbang_stop(&sp->bitbang); spi_bitbang_stop(&sp->bitbang);
ath79_spi_disable(sp);
clk_disable(sp->clk);
clk_put(sp->clk);
iounmap(sp->base); iounmap(sp->base);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
spi_master_put(sp->bitbang.master); spi_master_put(sp->bitbang.master);
...@@ -263,9 +308,15 @@ static int ath79_spi_remove(struct platform_device *pdev) ...@@ -263,9 +308,15 @@ static int ath79_spi_remove(struct platform_device *pdev)
return 0; return 0;
} }
static void ath79_spi_shutdown(struct platform_device *pdev)
{
ath79_spi_remove(pdev);
}
static struct platform_driver ath79_spi_driver = { static struct platform_driver ath79_spi_driver = {
.probe = ath79_spi_probe, .probe = ath79_spi_probe,
.remove = ath79_spi_remove, .remove = ath79_spi_remove,
.shutdown = ath79_spi_shutdown,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -1088,7 +1088,7 @@ static struct platform_driver atmel_spi_driver = { ...@@ -1088,7 +1088,7 @@ static struct platform_driver atmel_spi_driver = {
.suspend = atmel_spi_suspend, .suspend = atmel_spi_suspend,
.resume = atmel_spi_resume, .resume = atmel_spi_resume,
.probe = atmel_spi_probe, .probe = atmel_spi_probe,
.remove = __exit_p(atmel_spi_remove), .remove = atmel_spi_remove,
}; };
module_platform_driver(atmel_spi_driver); module_platform_driver(atmel_spi_driver);
......
...@@ -717,7 +717,7 @@ static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw) ...@@ -717,7 +717,7 @@ static void au1550_spi_bits_handlers_set(struct au1550_spi *hw, int bpw)
} }
} }
static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw) static void au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
{ {
u32 stat, cfg; u32 stat, cfg;
...@@ -766,7 +766,7 @@ static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw) ...@@ -766,7 +766,7 @@ static void __init au1550_spi_setup_psc_as_spi(struct au1550_spi *hw)
} }
static int __init au1550_spi_probe(struct platform_device *pdev) static int au1550_spi_probe(struct platform_device *pdev)
{ {
struct au1550_spi *hw; struct au1550_spi *hw;
struct spi_master *master; struct spi_master *master;
...@@ -968,7 +968,7 @@ static int __init au1550_spi_probe(struct platform_device *pdev) ...@@ -968,7 +968,7 @@ static int __init au1550_spi_probe(struct platform_device *pdev)
return err; return err;
} }
static int __exit au1550_spi_remove(struct platform_device *pdev) static int au1550_spi_remove(struct platform_device *pdev)
{ {
struct au1550_spi *hw = platform_get_drvdata(pdev); struct au1550_spi *hw = platform_get_drvdata(pdev);
...@@ -997,7 +997,7 @@ static int __exit au1550_spi_remove(struct platform_device *pdev) ...@@ -997,7 +997,7 @@ static int __exit au1550_spi_remove(struct platform_device *pdev)
MODULE_ALIAS("platform:au1550-spi"); MODULE_ALIAS("platform:au1550-spi");
static struct platform_driver au1550_spi_drv = { static struct platform_driver au1550_spi_drv = {
.remove = __exit_p(au1550_spi_remove), .remove = au1550_spi_remove,
.driver = { .driver = {
.name = "au1550-spi", .name = "au1550-spi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#define PFX KBUILD_MODNAME #define PFX KBUILD_MODNAME
#define BCM63XX_SPI_MAX_PREPEND 15
struct bcm63xx_spi { struct bcm63xx_spi {
struct completion done; struct completion done;
...@@ -49,16 +51,10 @@ struct bcm63xx_spi { ...@@ -49,16 +51,10 @@ struct bcm63xx_spi {
unsigned int msg_type_shift; unsigned int msg_type_shift;
unsigned int msg_ctl_width; unsigned int msg_ctl_width;
/* Data buffers */
const unsigned char *tx_ptr;
unsigned char *rx_ptr;
/* data iomem */ /* data iomem */
u8 __iomem *tx_io; u8 __iomem *tx_io;
const u8 __iomem *rx_io; const u8 __iomem *rx_io;
int remaining_bytes;
struct clk *clk; struct clk *clk;
struct platform_device *pdev; struct platform_device *pdev;
}; };
...@@ -175,24 +171,17 @@ static int bcm63xx_spi_setup(struct spi_device *spi) ...@@ -175,24 +171,17 @@ static int bcm63xx_spi_setup(struct spi_device *spi)
return 0; return 0;
} }
/* Fill the TX FIFO with as many bytes as possible */ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs) unsigned int num_transfers)
{
u8 size;
/* Fill the Tx FIFO with as many bytes as possible */
size = bs->remaining_bytes < bs->fifo_size ? bs->remaining_bytes :
bs->fifo_size;
memcpy_toio(bs->tx_io, bs->tx_ptr, size);
bs->remaining_bytes -= size;
}
static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
struct spi_transfer *t)
{ {
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
u16 msg_ctl; u16 msg_ctl;
u16 cmd; u16 cmd;
u8 rx_tail;
unsigned int i, timeout = 0, prepend_len = 0, len = 0;
struct spi_transfer *t = first;
bool do_rx = false;
bool do_tx = false;
/* Disable the CMD_DONE interrupt */ /* Disable the CMD_DONE interrupt */
bcm_spi_writeb(bs, 0, SPI_INT_MASK); bcm_spi_writeb(bs, 0, SPI_INT_MASK);
...@@ -200,25 +189,45 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi, ...@@ -200,25 +189,45 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
t->tx_buf, t->rx_buf, t->len); t->tx_buf, t->rx_buf, t->len);
/* Transmitter is inhibited */ if (num_transfers > 1 && t->tx_buf && t->len <= BCM63XX_SPI_MAX_PREPEND)
bs->tx_ptr = t->tx_buf; prepend_len = t->len;
bs->rx_ptr = t->rx_buf;
if (t->tx_buf) { /* prepare the buffer */
bs->remaining_bytes = t->len; for (i = 0; i < num_transfers; i++) {
bcm63xx_spi_fill_tx_fifo(bs); if (t->tx_buf) {
do_tx = true;
memcpy_toio(bs->tx_io + len, t->tx_buf, t->len);
/* don't prepend more than one tx */
if (t != first)
prepend_len = 0;
}
if (t->rx_buf) {
do_rx = true;
/* prepend is half-duplex write only */
if (t == first)
prepend_len = 0;
}
len += t->len;
t = list_entry(t->transfer_list.next, struct spi_transfer,
transfer_list);
} }
len -= prepend_len;
init_completion(&bs->done); init_completion(&bs->done);
/* Fill in the Message control register */ /* Fill in the Message control register */
msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT); msg_ctl = (len << SPI_BYTE_CNT_SHIFT);
if (t->rx_buf && t->tx_buf) if (do_rx && do_tx && prepend_len == 0)
msg_ctl |= (SPI_FD_RW << bs->msg_type_shift); msg_ctl |= (SPI_FD_RW << bs->msg_type_shift);
else if (t->rx_buf) else if (do_rx)
msg_ctl |= (SPI_HD_R << bs->msg_type_shift); msg_ctl |= (SPI_HD_R << bs->msg_type_shift);
else if (t->tx_buf) else if (do_tx)
msg_ctl |= (SPI_HD_W << bs->msg_type_shift); msg_ctl |= (SPI_HD_W << bs->msg_type_shift);
switch (bs->msg_ctl_width) { switch (bs->msg_ctl_width) {
...@@ -232,14 +241,41 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi, ...@@ -232,14 +241,41 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
/* Issue the transfer */ /* Issue the transfer */
cmd = SPI_CMD_START_IMMEDIATE; cmd = SPI_CMD_START_IMMEDIATE;
cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT); cmd |= (prepend_len << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT); cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT);
bcm_spi_writew(bs, cmd, SPI_CMD); bcm_spi_writew(bs, cmd, SPI_CMD);
/* Enable the CMD_DONE interrupt */ /* Enable the CMD_DONE interrupt */
bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK); bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
return t->len - bs->remaining_bytes; timeout = wait_for_completion_timeout(&bs->done, HZ);
if (!timeout)
return -ETIMEDOUT;
/* read out all data */
rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
if (do_rx && rx_tail != len)
return -EIO;
if (!rx_tail)
return 0;
len = 0;
t = first;
/* Read out all the data */
for (i = 0; i < num_transfers; i++) {
if (t->rx_buf)
memcpy_fromio(t->rx_buf, bs->rx_io + len, t->len);
if (t != first || prepend_len == 0)
len += t->len;
t = list_entry(t->transfer_list.next, struct spi_transfer,
transfer_list);
}
return 0;
} }
static int bcm63xx_spi_prepare_transfer(struct spi_master *master) static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
...@@ -264,41 +300,76 @@ static int bcm63xx_spi_transfer_one(struct spi_master *master, ...@@ -264,41 +300,76 @@ static int bcm63xx_spi_transfer_one(struct spi_master *master,
struct spi_message *m) struct spi_message *m)
{ {
struct bcm63xx_spi *bs = spi_master_get_devdata(master); struct bcm63xx_spi *bs = spi_master_get_devdata(master);
struct spi_transfer *t; struct spi_transfer *t, *first = NULL;
struct spi_device *spi = m->spi; struct spi_device *spi = m->spi;
int status = 0; int status = 0;
unsigned int timeout = 0; unsigned int n_transfers = 0, total_len = 0;
bool can_use_prepend = false;
/*
* This SPI controller does not support keeping CS active after a
* transfer.
* Work around this by merging as many transfers we can into one big
* full-duplex transfers.
*/
list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) {
unsigned int len = t->len;
u8 rx_tail;
status = bcm63xx_spi_check_transfer(spi, t); status = bcm63xx_spi_check_transfer(spi, t);
if (status < 0) if (status < 0)
goto exit; goto exit;
/* configure adapter for a new transfer */ if (!first)
bcm63xx_spi_setup_transfer(spi, t); first = t;
n_transfers++;
total_len += t->len;
if (n_transfers == 2 && !first->rx_buf && !t->tx_buf &&
first->len <= BCM63XX_SPI_MAX_PREPEND)
can_use_prepend = true;
else if (can_use_prepend && t->tx_buf)
can_use_prepend = false;
/* we can only transfer one fifo worth of data */
if ((can_use_prepend &&
total_len > (bs->fifo_size + BCM63XX_SPI_MAX_PREPEND)) ||
(!can_use_prepend && total_len > bs->fifo_size)) {
dev_err(&spi->dev, "unable to do transfers larger than FIFO size (%i > %i)\n",
total_len, bs->fifo_size);
status = -EINVAL;
goto exit;
}
/* all combined transfers have to have the same speed */
if (t->speed_hz != first->speed_hz) {
dev_err(&spi->dev, "unable to change speed between transfers\n");
status = -EINVAL;
goto exit;
}
while (len) { /* CS will be deasserted directly after transfer */
/* send the data */ if (t->delay_usecs) {
len -= bcm63xx_txrx_bufs(spi, t); dev_err(&spi->dev, "unable to keep CS asserted after transfer\n");
status = -EINVAL;
goto exit;
}
if (t->cs_change ||
list_is_last(&t->transfer_list, &m->transfers)) {
/* configure adapter for a new transfer */
bcm63xx_spi_setup_transfer(spi, first);
timeout = wait_for_completion_timeout(&bs->done, HZ); /* send the data */
if (!timeout) { status = bcm63xx_txrx_bufs(spi, first, n_transfers);
status = -ETIMEDOUT; if (status)
goto exit; goto exit;
}
/* read out all data */ m->actual_length += total_len;
rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
/* Read out all the data */ first = NULL;
if (rx_tail) n_transfers = 0;
memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail); total_len = 0;
can_use_prepend = false;
} }
m->actual_length += t->len;
} }
exit: exit:
m->status = status; m->status = status;
......
...@@ -416,8 +416,7 @@ bfin_sport_spi_pump_transfers(unsigned long data) ...@@ -416,8 +416,7 @@ bfin_sport_spi_pump_transfers(unsigned long data)
drv_data->cs_change = transfer->cs_change; drv_data->cs_change = transfer->cs_change;
/* Bits per word setup */ /* Bits per word setup */
bits_per_word = transfer->bits_per_word ? : bits_per_word = transfer->bits_per_word;
message->spi->bits_per_word ? : 8;
if (bits_per_word % 16 == 0) if (bits_per_word % 16 == 0)
drv_data->ops = &bfin_sport_transfer_ops_u16; drv_data->ops = &bfin_sport_transfer_ops_u16;
else else
......
...@@ -642,8 +642,7 @@ static void bfin_spi_pump_transfers(unsigned long data) ...@@ -642,8 +642,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
drv_data->cs_change = transfer->cs_change; drv_data->cs_change = transfer->cs_change;
/* Bits per word setup */ /* Bits per word setup */
bits_per_word = transfer->bits_per_word ? : bits_per_word = transfer->bits_per_word;
message->spi->bits_per_word ? : 8;
if (bits_per_word % 16 == 0) { if (bits_per_word % 16 == 0) {
drv_data->n_bytes = bits_per_word/8; drv_data->n_bytes = bits_per_word/8;
drv_data->len = (transfer->len) >> 1; drv_data->len = (transfer->len) >> 1;
...@@ -1274,7 +1273,7 @@ static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data) ...@@ -1274,7 +1273,7 @@ static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
return 0; return 0;
} }
static int __init bfin_spi_probe(struct platform_device *pdev) static int bfin_spi_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct bfin5xx_spi_master *platform_info; struct bfin5xx_spi_master *platform_info;
......
...@@ -69,7 +69,7 @@ static unsigned bitbang_txrx_8( ...@@ -69,7 +69,7 @@ static unsigned bitbang_txrx_8(
unsigned ns, unsigned ns,
struct spi_transfer *t struct spi_transfer *t
) { ) {
unsigned bits = t->bits_per_word ? : spi->bits_per_word; unsigned bits = t->bits_per_word;
unsigned count = t->len; unsigned count = t->len;
const u8 *tx = t->tx_buf; const u8 *tx = t->tx_buf;
u8 *rx = t->rx_buf; u8 *rx = t->rx_buf;
...@@ -95,7 +95,7 @@ static unsigned bitbang_txrx_16( ...@@ -95,7 +95,7 @@ static unsigned bitbang_txrx_16(
unsigned ns, unsigned ns,
struct spi_transfer *t struct spi_transfer *t
) { ) {
unsigned bits = t->bits_per_word ? : spi->bits_per_word; unsigned bits = t->bits_per_word;
unsigned count = t->len; unsigned count = t->len;
const u16 *tx = t->tx_buf; const u16 *tx = t->tx_buf;
u16 *rx = t->rx_buf; u16 *rx = t->rx_buf;
...@@ -121,7 +121,7 @@ static unsigned bitbang_txrx_32( ...@@ -121,7 +121,7 @@ static unsigned bitbang_txrx_32(
unsigned ns, unsigned ns,
struct spi_transfer *t struct spi_transfer *t
) { ) {
unsigned bits = t->bits_per_word ? : spi->bits_per_word; unsigned bits = t->bits_per_word;
unsigned count = t->len; unsigned count = t->len;
const u32 *tx = t->tx_buf; const u32 *tx = t->tx_buf;
u32 *rx = t->rx_buf; u32 *rx = t->rx_buf;
...@@ -427,40 +427,41 @@ EXPORT_SYMBOL_GPL(spi_bitbang_transfer); ...@@ -427,40 +427,41 @@ EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
*/ */
int spi_bitbang_start(struct spi_bitbang *bitbang) int spi_bitbang_start(struct spi_bitbang *bitbang)
{ {
int status; struct spi_master *master = bitbang->master;
int status;
if (!bitbang->master || !bitbang->chipselect) if (!master || !bitbang->chipselect)
return -EINVAL; return -EINVAL;
INIT_WORK(&bitbang->work, bitbang_work); INIT_WORK(&bitbang->work, bitbang_work);
spin_lock_init(&bitbang->lock); spin_lock_init(&bitbang->lock);
INIT_LIST_HEAD(&bitbang->queue); INIT_LIST_HEAD(&bitbang->queue);
if (!bitbang->master->mode_bits) if (!master->mode_bits)
bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
if (!bitbang->master->transfer) if (!master->transfer)
bitbang->master->transfer = spi_bitbang_transfer; master->transfer = spi_bitbang_transfer;
if (!bitbang->txrx_bufs) { if (!bitbang->txrx_bufs) {
bitbang->use_dma = 0; bitbang->use_dma = 0;
bitbang->txrx_bufs = spi_bitbang_bufs; bitbang->txrx_bufs = spi_bitbang_bufs;
if (!bitbang->master->setup) { if (!master->setup) {
if (!bitbang->setup_transfer) if (!bitbang->setup_transfer)
bitbang->setup_transfer = bitbang->setup_transfer =
spi_bitbang_setup_transfer; spi_bitbang_setup_transfer;
bitbang->master->setup = spi_bitbang_setup; master->setup = spi_bitbang_setup;
bitbang->master->cleanup = spi_bitbang_cleanup; master->cleanup = spi_bitbang_cleanup;
} }
} else if (!bitbang->master->setup) } else if (!master->setup)
return -EINVAL; return -EINVAL;
if (bitbang->master->transfer == spi_bitbang_transfer && if (master->transfer == spi_bitbang_transfer &&
!bitbang->setup_transfer) !bitbang->setup_transfer)
return -EINVAL; return -EINVAL;
/* this task is the only thing to touch the SPI bits */ /* this task is the only thing to touch the SPI bits */
bitbang->busy = 0; bitbang->busy = 0;
bitbang->workqueue = create_singlethread_workqueue( bitbang->workqueue = create_singlethread_workqueue(
dev_name(bitbang->master->dev.parent)); dev_name(master->dev.parent));
if (bitbang->workqueue == NULL) { if (bitbang->workqueue == NULL) {
status = -EBUSY; status = -EBUSY;
goto err1; goto err1;
...@@ -469,7 +470,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) ...@@ -469,7 +470,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
/* driver may get busy before register() returns, especially /* driver may get busy before register() returns, especially
* if someone registered boardinfo for devices * if someone registered boardinfo for devices
*/ */
status = spi_register_master(bitbang->master); status = spi_register_master(master);
if (status < 0) if (status < 0)
goto err2; goto err2;
......
...@@ -68,7 +68,7 @@ static int spi_clps711x_setup_xfer(struct spi_device *spi, ...@@ -68,7 +68,7 @@ static int spi_clps711x_setup_xfer(struct spi_device *spi,
struct spi_transfer *xfer) struct spi_transfer *xfer)
{ {
u32 speed = xfer->speed_hz ? : spi->max_speed_hz; u32 speed = xfer->speed_hz ? : spi->max_speed_hz;
u8 bpw = xfer->bits_per_word ? : spi->bits_per_word; u8 bpw = xfer->bits_per_word;
struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master); struct spi_clps711x_data *hw = spi_master_get_devdata(spi->master);
if (bpw != 8) { if (bpw != 8) {
......
...@@ -329,8 +329,7 @@ static int mcfqspi_transfer_one_message(struct spi_master *master, ...@@ -329,8 +329,7 @@ static int mcfqspi_transfer_one_message(struct spi_master *master,
mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high); mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high);
mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE); mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE);
if ((t->bits_per_word ? t->bits_per_word : if (t->bits_per_word == 8)
spi->bits_per_word) == 8)
mcfqspi_transfer_msg8(mcfqspi, t->len, t->tx_buf, mcfqspi_transfer_msg8(mcfqspi, t->len, t->tx_buf,
t->rx_buf); t->rx_buf);
else else
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/edma.h> #include <linux/edma.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h> #include <linux/spi/spi_bitbang.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -135,7 +137,7 @@ struct davinci_spi { ...@@ -135,7 +137,7 @@ struct davinci_spi {
int dma_rx_chnum; int dma_rx_chnum;
int dma_tx_chnum; int dma_tx_chnum;
struct davinci_spi_platform_data *pdata; struct davinci_spi_platform_data pdata;
void (*get_rx)(u32 rx_data, struct davinci_spi *); void (*get_rx)(u32 rx_data, struct davinci_spi *);
u32 (*get_tx)(struct davinci_spi *); u32 (*get_tx)(struct davinci_spi *);
...@@ -213,7 +215,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) ...@@ -213,7 +215,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
bool gpio_chipsel = false; bool gpio_chipsel = false;
dspi = spi_master_get_devdata(spi->master); dspi = spi_master_get_devdata(spi->master);
pdata = dspi->pdata; pdata = &dspi->pdata;
if (pdata->chip_sel && chip_sel < pdata->num_chipselect && if (pdata->chip_sel && chip_sel < pdata->num_chipselect &&
pdata->chip_sel[chip_sel] != SPI_INTERN_CS) pdata->chip_sel[chip_sel] != SPI_INTERN_CS)
...@@ -392,7 +394,7 @@ static int davinci_spi_setup(struct spi_device *spi) ...@@ -392,7 +394,7 @@ static int davinci_spi_setup(struct spi_device *spi)
struct davinci_spi_platform_data *pdata; struct davinci_spi_platform_data *pdata;
dspi = spi_master_get_devdata(spi->master); dspi = spi_master_get_devdata(spi->master);
pdata = dspi->pdata; pdata = &dspi->pdata;
/* if bits per word length is zero then set it default 8 */ /* if bits per word length is zero then set it default 8 */
if (!spi->bits_per_word) if (!spi->bits_per_word)
...@@ -534,7 +536,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -534,7 +536,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
struct scatterlist sg_rx, sg_tx; struct scatterlist sg_rx, sg_tx;
dspi = spi_master_get_devdata(spi->master); dspi = spi_master_get_devdata(spi->master);
pdata = dspi->pdata; pdata = &dspi->pdata;
spicfg = (struct davinci_spi_config *)spi->controller_data; spicfg = (struct davinci_spi_config *)spi->controller_data;
if (!spicfg) if (!spicfg)
spicfg = &davinci_spi_default_cfg; spicfg = &davinci_spi_default_cfg;
...@@ -699,6 +701,19 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -699,6 +701,19 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
return ret; return ret;
} }
/**
* dummy_thread_fn - dummy thread function
* @irq: IRQ number for this SPI Master
* @context_data: structure for SPI Master controller davinci_spi
*
* This is to satisfy the request_threaded_irq() API so that the irq
* handler is called in interrupt context.
*/
static irqreturn_t dummy_thread_fn(s32 irq, void *data)
{
return IRQ_HANDLED;
}
/** /**
* davinci_spi_irq - Interrupt handler for SPI Master Controller * davinci_spi_irq - Interrupt handler for SPI Master Controller
* @irq: IRQ number for this SPI Master * @irq: IRQ number for this SPI Master
...@@ -758,6 +773,70 @@ static int davinci_spi_request_dma(struct davinci_spi *dspi) ...@@ -758,6 +773,70 @@ static int davinci_spi_request_dma(struct davinci_spi *dspi)
return r; return r;
} }
#if defined(CONFIG_OF)
static const struct of_device_id davinci_spi_of_match[] = {
{
.compatible = "ti,dm644x-spi",
},
{
.compatible = "ti,da8xx-spi",
.data = (void *)SPI_VERSION_2,
},
{ },
};
MODULE_DEVICE_TABLE(of, davini_spi_of_match);
/**
* spi_davinci_get_pdata - Get platform data from DTS binding
* @pdev: ptr to platform data
* @dspi: ptr to driver data
*
* Parses and populates pdata in dspi from device tree bindings.
*
* NOTE: Not all platform data params are supported currently.
*/
static int spi_davinci_get_pdata(struct platform_device *pdev,
struct davinci_spi *dspi)
{
struct device_node *node = pdev->dev.of_node;
struct davinci_spi_platform_data *pdata;
unsigned int num_cs, intr_line = 0;
const struct of_device_id *match;
pdata = &dspi->pdata;
pdata->version = SPI_VERSION_1;
match = of_match_device(of_match_ptr(davinci_spi_of_match),
&pdev->dev);
if (!match)
return -ENODEV;
/* match data has the SPI version number for SPI_VERSION_2 */
if (match->data == (void *)SPI_VERSION_2)
pdata->version = SPI_VERSION_2;
/*
* default num_cs is 1 and all chipsel are internal to the chip
* indicated by chip_sel being NULL. GPIO based CS is not
* supported yet in DT bindings.
*/
num_cs = 1;
of_property_read_u32(node, "num-cs", &num_cs);
pdata->num_chipselect = num_cs;
of_property_read_u32(node, "ti,davinci-spi-intr-line", &intr_line);
pdata->intr_line = intr_line;
return 0;
}
#else
#define davinci_spi_of_match NULL
static struct davinci_spi_platform_data
*spi_davinci_get_pdata(struct platform_device *pdev,
struct davinci_spi *dspi)
{
return -ENODEV;
}
#endif
/** /**
* davinci_spi_probe - probe function for SPI Master Controller * davinci_spi_probe - probe function for SPI Master Controller
* @pdev: platform_device structure which contains plateform specific data * @pdev: platform_device structure which contains plateform specific data
...@@ -780,12 +859,6 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -780,12 +859,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
int i = 0, ret = 0; int i = 0, ret = 0;
u32 spipc0; u32 spipc0;
pdata = pdev->dev.platform_data;
if (pdata == NULL) {
ret = -ENODEV;
goto err;
}
master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi)); master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi));
if (master == NULL) { if (master == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -800,6 +873,19 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -800,6 +873,19 @@ static int davinci_spi_probe(struct platform_device *pdev)
goto free_master; goto free_master;
} }
if (pdev->dev.platform_data) {
pdata = pdev->dev.platform_data;
dspi->pdata = *pdata;
} else {
/* update dspi pdata with that from the DT */
ret = spi_davinci_get_pdata(pdev, dspi);
if (ret < 0)
goto free_master;
}
/* pdata in dspi is now updated and point pdata to that */
pdata = &dspi->pdata;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) { if (r == NULL) {
ret = -ENOENT; ret = -ENOENT;
...@@ -807,7 +893,6 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -807,7 +893,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
} }
dspi->pbase = r->start; dspi->pbase = r->start;
dspi->pdata = pdata;
mem = request_mem_region(r->start, resource_size(r), pdev->name); mem = request_mem_region(r->start, resource_size(r), pdev->name);
if (mem == NULL) { if (mem == NULL) {
...@@ -827,8 +912,8 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -827,8 +912,8 @@ static int davinci_spi_probe(struct platform_device *pdev)
goto unmap_io; goto unmap_io;
} }
ret = request_irq(dspi->irq, davinci_spi_irq, 0, dev_name(&pdev->dev), ret = request_threaded_irq(dspi->irq, davinci_spi_irq, dummy_thread_fn,
dspi); 0, dev_name(&pdev->dev), dspi);
if (ret) if (ret)
goto unmap_io; goto unmap_io;
...@@ -843,8 +928,9 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -843,8 +928,9 @@ static int davinci_spi_probe(struct platform_device *pdev)
ret = -ENODEV; ret = -ENODEV;
goto put_master; goto put_master;
} }
clk_enable(dspi->clk); clk_prepare_enable(dspi->clk);
master->dev.of_node = pdev->dev.of_node;
master->bus_num = pdev->id; master->bus_num = pdev->id;
master->num_chipselect = pdata->num_chipselect; master->num_chipselect = pdata->num_chipselect;
master->setup = davinci_spi_setup; master->setup = davinci_spi_setup;
...@@ -927,7 +1013,7 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -927,7 +1013,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
dma_release_channel(dspi->dma_rx); dma_release_channel(dspi->dma_rx);
dma_release_channel(dspi->dma_tx); dma_release_channel(dspi->dma_tx);
free_clk: free_clk:
clk_disable(dspi->clk); clk_disable_unprepare(dspi->clk);
clk_put(dspi->clk); clk_put(dspi->clk);
put_master: put_master:
spi_master_put(master); spi_master_put(master);
...@@ -963,7 +1049,7 @@ static int davinci_spi_remove(struct platform_device *pdev) ...@@ -963,7 +1049,7 @@ static int davinci_spi_remove(struct platform_device *pdev)
spi_bitbang_stop(&dspi->bitbang); spi_bitbang_stop(&dspi->bitbang);
clk_disable(dspi->clk); clk_disable_unprepare(dspi->clk);
clk_put(dspi->clk); clk_put(dspi->clk);
spi_master_put(master); spi_master_put(master);
free_irq(dspi->irq, dspi); free_irq(dspi->irq, dspi);
...@@ -978,6 +1064,7 @@ static struct platform_driver davinci_spi_driver = { ...@@ -978,6 +1064,7 @@ static struct platform_driver davinci_spi_driver = {
.driver = { .driver = {
.name = "spi_davinci", .name = "spi_davinci",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = davinci_spi_of_match,
}, },
.probe = davinci_spi_probe, .probe = davinci_spi_probe,
.remove = davinci_spi_remove, .remove = davinci_spi_remove,
......
...@@ -446,7 +446,7 @@ static inline int bits_per_word(const struct ep93xx_spi *espi) ...@@ -446,7 +446,7 @@ static inline int bits_per_word(const struct ep93xx_spi *espi)
struct spi_message *msg = espi->current_msg; struct spi_message *msg = espi->current_msg;
struct spi_transfer *t = msg->state; struct spi_transfer *t = msg->state;
return t->bits_per_word ? t->bits_per_word : msg->spi->bits_per_word; return t->bits_per_word;
} }
static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t)
......
...@@ -398,7 +398,7 @@ static int falcon_sflash_xfer_one(struct spi_master *master, ...@@ -398,7 +398,7 @@ static int falcon_sflash_xfer_one(struct spi_master *master,
} }
m->status = ret; m->status = ret;
m->complete(m->context); spi_finalize_current_message(master);
return 0; return 0;
} }
...@@ -423,6 +423,7 @@ static int falcon_sflash_probe(struct platform_device *pdev) ...@@ -423,6 +423,7 @@ static int falcon_sflash_probe(struct platform_device *pdev)
master->mode_bits = SPI_MODE_3; master->mode_bits = SPI_MODE_3;
master->num_chipselect = 1; master->num_chipselect = 1;
master->flags = SPI_MASTER_HALF_DUPLEX;
master->bus_num = -1; master->bus_num = -1;
master->setup = falcon_sflash_setup; master->setup = falcon_sflash_setup;
master->prepare_transfer_hardware = falcon_sflash_prepare_xfer; master->prepare_transfer_hardware = falcon_sflash_prepare_xfer;
......
...@@ -365,9 +365,26 @@ static int spi_gpio_probe_dt(struct platform_device *pdev) ...@@ -365,9 +365,26 @@ static int spi_gpio_probe_dt(struct platform_device *pdev)
if (!pdata) if (!pdata)
return -ENOMEM; return -ENOMEM;
pdata->sck = of_get_named_gpio(np, "gpio-sck", 0); ret = of_get_named_gpio(np, "gpio-sck", 0);
pdata->miso = of_get_named_gpio(np, "gpio-miso", 0); if (ret < 0) {
pdata->mosi = of_get_named_gpio(np, "gpio-mosi", 0); dev_err(&pdev->dev, "gpio-sck property not found\n");
goto error_free;
}
pdata->sck = ret;
ret = of_get_named_gpio(np, "gpio-miso", 0);
if (ret < 0) {
dev_info(&pdev->dev, "gpio-miso property not found, switching to no-rx mode\n");
pdata->miso = SPI_GPIO_NO_MISO;
} else
pdata->miso = ret;
ret = of_get_named_gpio(np, "gpio-mosi", 0);
if (ret < 0) {
dev_info(&pdev->dev, "gpio-mosi property not found, switching to no-tx mode\n");
pdata->mosi = SPI_GPIO_NO_MOSI;
} else
pdata->mosi = ret;
ret = of_property_read_u32(np, "num-chipselects", &tmp); ret = of_property_read_u32(np, "num-chipselects", &tmp);
if (ret < 0) { if (ret < 0) {
......
...@@ -949,3 +949,4 @@ module_platform_driver(spi_imx_driver); ...@@ -949,3 +949,4 @@ module_platform_driver(spi_imx_driver);
MODULE_DESCRIPTION("SPI Master Controller driver"); MODULE_DESCRIPTION("SPI Master Controller driver");
MODULE_AUTHOR("Sascha Hauer, Pengutronix"); MODULE_AUTHOR("Sascha Hauer, Pengutronix");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRIVER_NAME);
...@@ -438,6 +438,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, ...@@ -438,6 +438,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
master->num_chipselect = pdata->max_chipselect; master->num_chipselect = pdata->max_chipselect;
} }
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
master->setup = mpc512x_psc_spi_setup; master->setup = mpc512x_psc_spi_setup;
master->transfer = mpc512x_psc_spi_transfer; master->transfer = mpc512x_psc_spi_transfer;
master->cleanup = mpc512x_psc_spi_cleanup; master->cleanup = mpc512x_psc_spi_cleanup;
...@@ -522,17 +523,11 @@ static int mpc512x_psc_spi_of_probe(struct platform_device *op) ...@@ -522,17 +523,11 @@ static int mpc512x_psc_spi_of_probe(struct platform_device *op)
regaddr64 = of_translate_address(op->dev.of_node, regaddr_p); regaddr64 = of_translate_address(op->dev.of_node, regaddr_p);
/* get PSC id (0..11, used by port_config) */ /* get PSC id (0..11, used by port_config) */
if (op->dev.platform_data == NULL) { id = of_alias_get_id(op->dev.of_node, "spi");
const u32 *psc_nump; if (id < 0) {
dev_err(&op->dev, "no alias id for %s\n",
psc_nump = of_get_property(op->dev.of_node, "cell-index", NULL); op->dev.of_node->full_name);
if (!psc_nump || *psc_nump > 11) { return id;
dev_err(&op->dev, "mpc512x_psc_spi: Device node %s "
"has invalid cell-index property\n",
op->dev.of_node->full_name);
return -EINVAL;
}
id = *psc_nump;
} }
return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64, return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
......
...@@ -241,6 +241,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, ...@@ -241,6 +241,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
INIT_COMPLETION(spi->c); INIT_COMPLETION(spi->c);
ctrl0 = readl(ssp->base + HW_SSP_CTRL0); ctrl0 = readl(ssp->base + HW_SSP_CTRL0);
ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT;
ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs); ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs);
if (*first) if (*first)
...@@ -256,8 +257,10 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, ...@@ -256,8 +257,10 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
if ((sg_count + 1 == sgs) && *last) if ((sg_count + 1 == sgs) && *last)
ctrl0 |= BM_SSP_CTRL0_IGNORE_CRC; ctrl0 |= BM_SSP_CTRL0_IGNORE_CRC;
if (ssp->devid == IMX23_SSP) if (ssp->devid == IMX23_SSP) {
ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT;
ctrl0 |= min; ctrl0 |= min;
}
dma_xfer[sg_count].pio[0] = ctrl0; dma_xfer[sg_count].pio[0] = ctrl0;
dma_xfer[sg_count].pio[3] = min; dma_xfer[sg_count].pio[3] = min;
......
...@@ -481,7 +481,7 @@ static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) ...@@ -481,7 +481,7 @@ static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m)
return 0; return 0;
} }
static int __init omap1_spi100k_reset(struct omap1_spi100k *spi100k) static int omap1_spi100k_reset(struct omap1_spi100k *spi100k)
{ {
return 0; return 0;
} }
...@@ -560,7 +560,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev) ...@@ -560,7 +560,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
return status; return status;
} }
static int __exit omap1_spi100k_remove(struct platform_device *pdev) static int omap1_spi100k_remove(struct platform_device *pdev)
{ {
struct spi_master *master; struct spi_master *master;
struct omap1_spi100k *spi100k; struct omap1_spi100k *spi100k;
...@@ -604,7 +604,7 @@ static struct platform_driver omap1_spi100k_driver = { ...@@ -604,7 +604,7 @@ static struct platform_driver omap1_spi100k_driver = {
.name = "omap1_spi100k", .name = "omap1_spi100k",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.remove = __exit_p(omap1_spi100k_remove), .remove = omap1_spi100k_remove,
}; };
......
...@@ -476,7 +476,7 @@ static void uwire_off(struct uwire_spi *uwire) ...@@ -476,7 +476,7 @@ static void uwire_off(struct uwire_spi *uwire)
spi_master_put(uwire->bitbang.master); spi_master_put(uwire->bitbang.master);
} }
static int __init uwire_probe(struct platform_device *pdev) static int uwire_probe(struct platform_device *pdev)
{ {
struct spi_master *master; struct spi_master *master;
struct uwire_spi *uwire; struct uwire_spi *uwire;
...@@ -536,7 +536,7 @@ static int __init uwire_probe(struct platform_device *pdev) ...@@ -536,7 +536,7 @@ static int __init uwire_probe(struct platform_device *pdev)
return status; return status;
} }
static int __exit uwire_remove(struct platform_device *pdev) static int uwire_remove(struct platform_device *pdev)
{ {
struct uwire_spi *uwire = dev_get_drvdata(&pdev->dev); struct uwire_spi *uwire = dev_get_drvdata(&pdev->dev);
int status; int status;
...@@ -557,7 +557,7 @@ static struct platform_driver uwire_driver = { ...@@ -557,7 +557,7 @@ static struct platform_driver uwire_driver = {
.name = "omap_uwire", .name = "omap_uwire",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.remove = __exit_p(uwire_remove), .remove = uwire_remove,
// suspend ... unuse ck // suspend ... unuse ck
// resume ... use ck // resume ... use ck
}; };
......
...@@ -298,10 +298,10 @@ static void omap2_mcspi_rx_callback(void *data) ...@@ -298,10 +298,10 @@ static void omap2_mcspi_rx_callback(void *data)
struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select];
complete(&mcspi_dma->dma_rx_completion);
/* We must disable the DMA RX request */ /* We must disable the DMA RX request */
omap2_mcspi_set_dma_req(spi, 1, 0); omap2_mcspi_set_dma_req(spi, 1, 0);
complete(&mcspi_dma->dma_rx_completion);
} }
static void omap2_mcspi_tx_callback(void *data) static void omap2_mcspi_tx_callback(void *data)
...@@ -310,10 +310,10 @@ static void omap2_mcspi_tx_callback(void *data) ...@@ -310,10 +310,10 @@ static void omap2_mcspi_tx_callback(void *data)
struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select]; struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select];
complete(&mcspi_dma->dma_tx_completion);
/* We must disable the DMA TX request */ /* We must disable the DMA TX request */
omap2_mcspi_set_dma_req(spi, 0, 0); omap2_mcspi_set_dma_req(spi, 0, 0);
complete(&mcspi_dma->dma_tx_completion);
} }
static void omap2_mcspi_tx_dma(struct spi_device *spi, static void omap2_mcspi_tx_dma(struct spi_device *spi,
...@@ -927,6 +927,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -927,6 +927,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
struct spi_device *spi; struct spi_device *spi;
struct spi_transfer *t = NULL; struct spi_transfer *t = NULL;
struct spi_master *master;
int cs_active = 0; int cs_active = 0;
struct omap2_mcspi_cs *cs; struct omap2_mcspi_cs *cs;
struct omap2_mcspi_device_config *cd; struct omap2_mcspi_device_config *cd;
...@@ -935,6 +936,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -935,6 +936,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
u32 chconf; u32 chconf;
spi = m->spi; spi = m->spi;
master = spi->master;
cs = spi->controller_state; cs = spi->controller_state;
cd = spi->controller_data; cd = spi->controller_data;
...@@ -952,6 +954,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -952,6 +954,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
if (!t->speed_hz && !t->bits_per_word) if (!t->speed_hz && !t->bits_per_word)
par_override = 0; par_override = 0;
} }
if (cd && cd->cs_per_word) {
chconf = mcspi->ctx.modulctrl;
chconf &= ~OMAP2_MCSPI_MODULCTRL_SINGLE;
mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf);
mcspi->ctx.modulctrl =
mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
}
if (!cs_active) { if (!cs_active) {
omap2_mcspi_force_cs(spi, 1); omap2_mcspi_force_cs(spi, 1);
...@@ -1013,6 +1023,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -1013,6 +1023,14 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
if (cs_active) if (cs_active)
omap2_mcspi_force_cs(spi, 0); omap2_mcspi_force_cs(spi, 0);
if (cd && cd->cs_per_word) {
chconf = mcspi->ctx.modulctrl;
chconf |= OMAP2_MCSPI_MODULCTRL_SINGLE;
mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, chconf);
mcspi->ctx.modulctrl =
mcspi_read_cs_reg(spi, OMAP2_MCSPI_MODULCTRL);
}
omap2_mcspi_set_enable(spi, 0); omap2_mcspi_set_enable(spi, 0);
m->status = status; m->status = status;
...@@ -1020,7 +1038,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) ...@@ -1020,7 +1038,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
} }
static int omap2_mcspi_transfer_one_message(struct spi_master *master, static int omap2_mcspi_transfer_one_message(struct spi_master *master,
struct spi_message *m) struct spi_message *m)
{ {
struct omap2_mcspi *mcspi; struct omap2_mcspi *mcspi;
struct spi_transfer *t; struct spi_transfer *t;
...@@ -1041,7 +1059,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, ...@@ -1041,7 +1059,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
|| (len && !(rx_buf || tx_buf)) || (len && !(rx_buf || tx_buf))
|| (t->bits_per_word && || (t->bits_per_word &&
( t->bits_per_word < 4 ( t->bits_per_word < 4
|| t->bits_per_word > 32))) { || t->bits_per_word > 32))) {
dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", dev_dbg(mcspi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n",
t->speed_hz, t->speed_hz,
len, len,
...@@ -1052,8 +1070,8 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, ...@@ -1052,8 +1070,8 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master,
} }
if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) { if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n", dev_dbg(mcspi->dev, "speed_hz %d below minimum %d Hz\n",
t->speed_hz, t->speed_hz,
OMAP2_MCSPI_MAX_FREQ >> 15); OMAP2_MCSPI_MAX_FREQ >> 15);
return -EINVAL; return -EINVAL;
} }
...@@ -1099,7 +1117,7 @@ static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) ...@@ -1099,7 +1117,7 @@ static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
return ret; return ret;
mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE,
OMAP2_MCSPI_WAKEUPENABLE_WKEN); OMAP2_MCSPI_WAKEUPENABLE_WKEN);
ctx->wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN; ctx->wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
omap2_mcspi_set_master_mode(master); omap2_mcspi_set_master_mode(master);
...@@ -1228,7 +1246,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1228,7 +1246,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
sprintf(dma_ch_name, "rx%d", i); sprintf(dma_ch_name, "rx%d", i);
dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
dma_ch_name); dma_ch_name);
if (!dma_res) { if (!dma_res) {
dev_dbg(&pdev->dev, "cannot get DMA RX channel\n"); dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
status = -ENODEV; status = -ENODEV;
...@@ -1238,7 +1256,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1238,7 +1256,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start; mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
sprintf(dma_ch_name, "tx%d", i); sprintf(dma_ch_name, "tx%d", i);
dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA, dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
dma_ch_name); dma_ch_name);
if (!dma_res) { if (!dma_res) {
dev_dbg(&pdev->dev, "cannot get DMA TX channel\n"); dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
status = -ENODEV; status = -ENODEV;
...@@ -1254,7 +1272,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1254,7 +1272,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
pinctrl = devm_pinctrl_get_select_default(&pdev->dev); pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(pinctrl)) if (IS_ERR(pinctrl))
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
"pins are not configured from the driver\n"); "pins are not configured from the driver\n");
pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
......
...@@ -366,7 +366,7 @@ static int orion_spi_transfer_one_message(struct spi_master *master, ...@@ -366,7 +366,7 @@ static int orion_spi_transfer_one_message(struct spi_master *master,
return 0; return 0;
} }
static int __init orion_spi_reset(struct orion_spi *orion_spi) static int orion_spi_reset(struct orion_spi *orion_spi)
{ {
/* Verify that the CS is deasserted */ /* Verify that the CS is deasserted */
orion_spi_set_cs(orion_spi, 0); orion_spi_set_cs(orion_spi, 0);
...@@ -396,7 +396,7 @@ static int orion_spi_setup(struct spi_device *spi) ...@@ -396,7 +396,7 @@ static int orion_spi_setup(struct spi_device *spi)
return 0; return 0;
} }
static int __init orion_spi_probe(struct platform_device *pdev) static int orion_spi_probe(struct platform_device *pdev)
{ {
struct spi_master *master; struct spi_master *master;
struct orion_spi *spi; struct orion_spi *spi;
...@@ -479,7 +479,7 @@ static int __init orion_spi_probe(struct platform_device *pdev) ...@@ -479,7 +479,7 @@ static int __init orion_spi_probe(struct platform_device *pdev)
} }
static int __exit orion_spi_remove(struct platform_device *pdev) static int orion_spi_remove(struct platform_device *pdev)
{ {
struct spi_master *master; struct spi_master *master;
struct resource *r; struct resource *r;
...@@ -513,20 +513,11 @@ static struct platform_driver orion_spi_driver = { ...@@ -513,20 +513,11 @@ static struct platform_driver orion_spi_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_match_ptr(orion_spi_of_match_table), .of_match_table = of_match_ptr(orion_spi_of_match_table),
}, },
.remove = __exit_p(orion_spi_remove), .probe = orion_spi_probe,
.remove = orion_spi_remove,
}; };
static int __init orion_spi_init(void) module_platform_driver(orion_spi_driver);
{
return platform_driver_probe(&orion_spi_driver, orion_spi_probe);
}
module_init(orion_spi_init);
static void __exit orion_spi_exit(void)
{
platform_driver_unregister(&orion_spi_driver);
}
module_exit(orion_spi_exit);
MODULE_DESCRIPTION("Orion SPI driver"); MODULE_DESCRIPTION("Orion SPI driver");
MODULE_AUTHOR("Shadi Ammouri <shadi@marvell.com>"); MODULE_AUTHOR("Shadi Ammouri <shadi@marvell.com>");
......
...@@ -389,7 +389,7 @@ static void free_gpios(struct ppc4xx_spi *hw) ...@@ -389,7 +389,7 @@ static void free_gpios(struct ppc4xx_spi *hw)
/* /*
* platform_device layer stuff... * platform_device layer stuff...
*/ */
static int __init spi_ppc4xx_of_probe(struct platform_device *op) static int spi_ppc4xx_of_probe(struct platform_device *op)
{ {
struct ppc4xx_spi *hw; struct ppc4xx_spi *hw;
struct spi_master *master; struct spi_master *master;
...@@ -560,7 +560,7 @@ static int __init spi_ppc4xx_of_probe(struct platform_device *op) ...@@ -560,7 +560,7 @@ static int __init spi_ppc4xx_of_probe(struct platform_device *op)
return ret; return ret;
} }
static int __exit spi_ppc4xx_of_remove(struct platform_device *op) static int spi_ppc4xx_of_remove(struct platform_device *op)
{ {
struct spi_master *master = dev_get_drvdata(&op->dev); struct spi_master *master = dev_get_drvdata(&op->dev);
struct ppc4xx_spi *hw = spi_master_get_devdata(master); struct ppc4xx_spi *hw = spi_master_get_devdata(master);
...@@ -583,7 +583,7 @@ MODULE_DEVICE_TABLE(of, spi_ppc4xx_of_match); ...@@ -583,7 +583,7 @@ MODULE_DEVICE_TABLE(of, spi_ppc4xx_of_match);
static struct platform_driver spi_ppc4xx_of_driver = { static struct platform_driver spi_ppc4xx_of_driver = {
.probe = spi_ppc4xx_of_probe, .probe = spi_ppc4xx_of_probe,
.remove = __exit_p(spi_ppc4xx_of_remove), .remove = spi_ppc4xx_of_remove,
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
/*
* PXA2xx SPI DMA engine support.
*
* Copyright (C) 2013, Intel Corporation
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/pxa2xx_ssp.h>
#include <linux/scatterlist.h>
#include <linux/sizes.h>
#include <linux/spi/spi.h>
#include <linux/spi/pxa2xx_spi.h>
#include "spi-pxa2xx.h"
static int pxa2xx_spi_map_dma_buffer(struct driver_data *drv_data,
enum dma_data_direction dir)
{
int i, nents, len = drv_data->len;
struct scatterlist *sg;
struct device *dmadev;
struct sg_table *sgt;
void *buf, *pbuf;
/*
* Some DMA controllers have problems transferring buffers that are
* not multiple of 4 bytes. So we truncate the transfer so that it
* is suitable for such controllers, and handle the trailing bytes
* manually after the DMA completes.
*
* REVISIT: It would be better if this information could be
* retrieved directly from the DMA device in a similar way than
* ->copy_align etc. is done.
*/
len = ALIGN(drv_data->len, 4);
if (dir == DMA_TO_DEVICE) {
dmadev = drv_data->tx_chan->device->dev;
sgt = &drv_data->tx_sgt;
buf = drv_data->tx;
drv_data->tx_map_len = len;
} else {
dmadev = drv_data->rx_chan->device->dev;
sgt = &drv_data->rx_sgt;
buf = drv_data->rx;
drv_data->rx_map_len = len;
}
nents = DIV_ROUND_UP(len, SZ_2K);
if (nents != sgt->nents) {
int ret;
sg_free_table(sgt);
ret = sg_alloc_table(sgt, nents, GFP_KERNEL);
if (ret)
return ret;
}
pbuf = buf;
for_each_sg(sgt->sgl, sg, sgt->nents, i) {
size_t bytes = min_t(size_t, len, SZ_2K);
if (buf)
sg_set_buf(sg, pbuf, bytes);
else
sg_set_buf(sg, drv_data->dummy, bytes);
pbuf += bytes;
len -= bytes;
}
nents = dma_map_sg(dmadev, sgt->sgl, sgt->nents, dir);
if (!nents)
return -ENOMEM;
return nents;
}
static void pxa2xx_spi_unmap_dma_buffer(struct driver_data *drv_data,
enum dma_data_direction dir)
{
struct device *dmadev;
struct sg_table *sgt;
if (dir == DMA_TO_DEVICE) {
dmadev = drv_data->tx_chan->device->dev;
sgt = &drv_data->tx_sgt;
} else {
dmadev = drv_data->rx_chan->device->dev;
sgt = &drv_data->rx_sgt;
}
dma_unmap_sg(dmadev, sgt->sgl, sgt->nents, dir);
}
static void pxa2xx_spi_unmap_dma_buffers(struct driver_data *drv_data)
{
if (!drv_data->dma_mapped)
return;
pxa2xx_spi_unmap_dma_buffer(drv_data, DMA_FROM_DEVICE);
pxa2xx_spi_unmap_dma_buffer(drv_data, DMA_TO_DEVICE);
drv_data->dma_mapped = 0;
}
static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data,
bool error)
{
struct spi_message *msg = drv_data->cur_msg;
/*
* It is possible that one CPU is handling ROR interrupt and other
* just gets DMA completion. Calling pump_transfers() twice for the
* same transfer leads to problems thus we prevent concurrent calls
* by using ->dma_running.
*/
if (atomic_dec_and_test(&drv_data->dma_running)) {
void __iomem *reg = drv_data->ioaddr;
/*
* If the other CPU is still handling the ROR interrupt we
* might not know about the error yet. So we re-check the
* ROR bit here before we clear the status register.
*/
if (!error) {
u32 status = read_SSSR(reg) & drv_data->mask_sr;
error = status & SSSR_ROR;
}
/* Clear status & disable interrupts */
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
write_SSSR_CS(drv_data, drv_data->clear_sr);
if (!pxa25x_ssp_comp(drv_data))
write_SSTO(0, reg);
if (!error) {
pxa2xx_spi_unmap_dma_buffers(drv_data);
/* Handle the last bytes of unaligned transfer */
drv_data->tx += drv_data->tx_map_len;
drv_data->write(drv_data);
drv_data->rx += drv_data->rx_map_len;
drv_data->read(drv_data);
msg->actual_length += drv_data->len;
msg->state = pxa2xx_spi_next_transfer(drv_data);
} else {
/* In case we got an error we disable the SSP now */
write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
msg->state = ERROR_STATE;
}
tasklet_schedule(&drv_data->pump_transfers);
}
}
static void pxa2xx_spi_dma_callback(void *data)
{
pxa2xx_spi_dma_transfer_complete(data, false);
}
static struct dma_async_tx_descriptor *
pxa2xx_spi_dma_prepare_one(struct driver_data *drv_data,
enum dma_transfer_direction dir)
{
struct pxa2xx_spi_master *pdata = drv_data->master_info;
struct chip_data *chip = drv_data->cur_chip;
enum dma_slave_buswidth width;
struct dma_slave_config cfg;
struct dma_chan *chan;
struct sg_table *sgt;
int nents, ret;
switch (drv_data->n_bytes) {
case 1:
width = DMA_SLAVE_BUSWIDTH_1_BYTE;
break;
case 2:
width = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
default:
width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
}
memset(&cfg, 0, sizeof(cfg));
cfg.direction = dir;
if (dir == DMA_MEM_TO_DEV) {
cfg.dst_addr = drv_data->ssdr_physical;
cfg.dst_addr_width = width;
cfg.dst_maxburst = chip->dma_burst_size;
cfg.slave_id = pdata->tx_slave_id;
sgt = &drv_data->tx_sgt;
nents = drv_data->tx_nents;
chan = drv_data->tx_chan;
} else {
cfg.src_addr = drv_data->ssdr_physical;
cfg.src_addr_width = width;
cfg.src_maxburst = chip->dma_burst_size;
cfg.slave_id = pdata->rx_slave_id;
sgt = &drv_data->rx_sgt;
nents = drv_data->rx_nents;
chan = drv_data->rx_chan;
}
ret = dmaengine_slave_config(chan, &cfg);
if (ret) {
dev_warn(&drv_data->pdev->dev, "DMA slave config failed\n");
return NULL;
}
return dmaengine_prep_slave_sg(chan, sgt->sgl, nents, dir,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
}
static bool pxa2xx_spi_dma_filter(struct dma_chan *chan, void *param)
{
const struct pxa2xx_spi_master *pdata = param;
return chan->chan_id == pdata->tx_chan_id ||
chan->chan_id == pdata->rx_chan_id;
}
bool pxa2xx_spi_dma_is_possible(size_t len)
{
return len <= MAX_DMA_LEN;
}
int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data)
{
const struct chip_data *chip = drv_data->cur_chip;
int ret;
if (!chip->enable_dma)
return 0;
/* Don't bother with DMA if we can't do even a single burst */
if (drv_data->len < chip->dma_burst_size)
return 0;
ret = pxa2xx_spi_map_dma_buffer(drv_data, DMA_TO_DEVICE);
if (ret <= 0) {
dev_warn(&drv_data->pdev->dev, "failed to DMA map TX\n");
return 0;
}
drv_data->tx_nents = ret;
ret = pxa2xx_spi_map_dma_buffer(drv_data, DMA_FROM_DEVICE);
if (ret <= 0) {
pxa2xx_spi_unmap_dma_buffer(drv_data, DMA_TO_DEVICE);
dev_warn(&drv_data->pdev->dev, "failed to DMA map RX\n");
return 0;
}
drv_data->rx_nents = ret;
return 1;
}
irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
{
u32 status;
status = read_SSSR(drv_data->ioaddr) & drv_data->mask_sr;
if (status & SSSR_ROR) {
dev_err(&drv_data->pdev->dev, "FIFO overrun\n");
dmaengine_terminate_all(drv_data->rx_chan);
dmaengine_terminate_all(drv_data->tx_chan);
pxa2xx_spi_dma_transfer_complete(drv_data, true);
return IRQ_HANDLED;
}
return IRQ_NONE;
}
int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst)
{
struct dma_async_tx_descriptor *tx_desc, *rx_desc;
tx_desc = pxa2xx_spi_dma_prepare_one(drv_data, DMA_MEM_TO_DEV);
if (!tx_desc) {
dev_err(&drv_data->pdev->dev,
"failed to get DMA TX descriptor\n");
return -EBUSY;
}
rx_desc = pxa2xx_spi_dma_prepare_one(drv_data, DMA_DEV_TO_MEM);
if (!rx_desc) {
dev_err(&drv_data->pdev->dev,
"failed to get DMA RX descriptor\n");
return -EBUSY;
}
/* We are ready when RX completes */
rx_desc->callback = pxa2xx_spi_dma_callback;
rx_desc->callback_param = drv_data;
dmaengine_submit(rx_desc);
dmaengine_submit(tx_desc);
return 0;
}
void pxa2xx_spi_dma_start(struct driver_data *drv_data)
{
dma_async_issue_pending(drv_data->rx_chan);
dma_async_issue_pending(drv_data->tx_chan);
atomic_set(&drv_data->dma_running, 1);
}
int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
{
struct pxa2xx_spi_master *pdata = drv_data->master_info;
dma_cap_mask_t mask;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
drv_data->dummy = devm_kzalloc(&drv_data->pdev->dev, SZ_2K, GFP_KERNEL);
if (!drv_data->dummy)
return -ENOMEM;
drv_data->tx_chan = dma_request_channel(mask, pxa2xx_spi_dma_filter,
pdata);
if (!drv_data->tx_chan)
return -ENODEV;
drv_data->rx_chan = dma_request_channel(mask, pxa2xx_spi_dma_filter,
pdata);
if (!drv_data->rx_chan) {
dma_release_channel(drv_data->tx_chan);
drv_data->tx_chan = NULL;
return -ENODEV;
}
return 0;
}
void pxa2xx_spi_dma_release(struct driver_data *drv_data)
{
if (drv_data->rx_chan) {
dmaengine_terminate_all(drv_data->rx_chan);
dma_release_channel(drv_data->rx_chan);
sg_free_table(&drv_data->rx_sgt);
drv_data->rx_chan = NULL;
}
if (drv_data->tx_chan) {
dmaengine_terminate_all(drv_data->tx_chan);
dma_release_channel(drv_data->tx_chan);
sg_free_table(&drv_data->tx_sgt);
drv_data->tx_chan = NULL;
}
}
void pxa2xx_spi_dma_resume(struct driver_data *drv_data)
{
}
int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
struct spi_device *spi,
u8 bits_per_word, u32 *burst_code,
u32 *threshold)
{
struct pxa2xx_spi_chip *chip_info = spi->controller_data;
/*
* If the DMA burst size is given in chip_info we use that,
* otherwise we use the default. Also we use the default FIFO
* thresholds for now.
*/
*burst_code = chip_info ? chip_info->dma_burst_size : 16;
*threshold = SSCR1_RxTresh(RX_THRESH_DFLT)
| SSCR1_TxTresh(TX_THRESH_DFLT);
return 0;
}
...@@ -8,147 +8,58 @@ ...@@ -8,147 +8,58 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
struct ce4100_info {
struct ssp_device ssp;
struct platform_device *spi_pdev;
};
static DEFINE_MUTEX(ssp_lock);
static LIST_HEAD(ssp_list);
struct ssp_device *pxa_ssp_request(int port, const char *label)
{
struct ssp_device *ssp = NULL;
mutex_lock(&ssp_lock);
list_for_each_entry(ssp, &ssp_list, node) {
if (ssp->port_id == port && ssp->use_count == 0) {
ssp->use_count++;
ssp->label = label;
break;
}
}
mutex_unlock(&ssp_lock);
if (&ssp->node == &ssp_list)
return NULL;
return ssp;
}
EXPORT_SYMBOL_GPL(pxa_ssp_request);
void pxa_ssp_free(struct ssp_device *ssp)
{
mutex_lock(&ssp_lock);
if (ssp->use_count) {
ssp->use_count--;
ssp->label = NULL;
} else
dev_err(&ssp->pdev->dev, "device already free\n");
mutex_unlock(&ssp_lock);
}
EXPORT_SYMBOL_GPL(pxa_ssp_free);
static int ce4100_spi_probe(struct pci_dev *dev, static int ce4100_spi_probe(struct pci_dev *dev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct platform_device_info pi;
int ret; int ret;
resource_size_t phys_beg;
resource_size_t phys_len;
struct ce4100_info *spi_info;
struct platform_device *pdev; struct platform_device *pdev;
struct pxa2xx_spi_master spi_pdata; struct pxa2xx_spi_master spi_pdata;
struct ssp_device *ssp; struct ssp_device *ssp;
ret = pci_enable_device(dev); ret = pcim_enable_device(dev);
if (ret) if (ret)
return ret; return ret;
phys_beg = pci_resource_start(dev, 0); ret = pcim_iomap_regions(dev, 1 << 0, "PXA2xx SPI");
phys_len = pci_resource_len(dev, 0); if (!ret)
if (!request_mem_region(phys_beg, phys_len,
"CE4100 SPI")) {
dev_err(&dev->dev, "Can't request register space.\n");
ret = -EBUSY;
return ret; return ret;
}
pdev = platform_device_alloc("pxa2xx-spi", dev->devfn);
spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
if (!pdev || !spi_info ) {
ret = -ENOMEM;
goto err_nomem;
}
memset(&spi_pdata, 0, sizeof(spi_pdata)); memset(&spi_pdata, 0, sizeof(spi_pdata));
spi_pdata.num_chipselect = dev->devfn; spi_pdata.num_chipselect = dev->devfn;
ret = platform_device_add_data(pdev, &spi_pdata, sizeof(spi_pdata)); ssp = &spi_pdata.ssp;
if (ret)
goto err_nomem;
pdev->dev.parent = &dev->dev;
pdev->dev.of_node = dev->dev.of_node;
ssp = &spi_info->ssp;
ssp->phys_base = pci_resource_start(dev, 0); ssp->phys_base = pci_resource_start(dev, 0);
ssp->mmio_base = ioremap(phys_beg, phys_len); ssp->mmio_base = pcim_iomap_table(dev)[0];
if (!ssp->mmio_base) { if (!ssp->mmio_base) {
dev_err(&pdev->dev, "failed to ioremap() registers\n"); dev_err(&dev->dev, "failed to ioremap() registers\n");
ret = -EIO; return -EIO;
goto err_nomem;
} }
ssp->irq = dev->irq; ssp->irq = dev->irq;
ssp->port_id = pdev->id; ssp->port_id = dev->devfn;
ssp->type = PXA25x_SSP; ssp->type = PXA25x_SSP;
mutex_lock(&ssp_lock); memset(&pi, 0, sizeof(pi));
list_add(&ssp->node, &ssp_list); pi.parent = &dev->dev;
mutex_unlock(&ssp_lock); pi.name = "pxa2xx-spi";
pi.id = ssp->port_id;
pi.data = &spi_pdata;
pi.size_data = sizeof(spi_pdata);
pci_set_drvdata(dev, spi_info); pdev = platform_device_register_full(&pi);
if (!pdev)
return -ENOMEM;
ret = platform_device_add(pdev); pci_set_drvdata(dev, pdev);
if (ret)
goto err_dev_add;
return ret; return 0;
err_dev_add:
pci_set_drvdata(dev, NULL);
mutex_lock(&ssp_lock);
list_del(&ssp->node);
mutex_unlock(&ssp_lock);
iounmap(ssp->mmio_base);
err_nomem:
release_mem_region(phys_beg, phys_len);
platform_device_put(pdev);
kfree(spi_info);
return ret;
} }
static void ce4100_spi_remove(struct pci_dev *dev) static void ce4100_spi_remove(struct pci_dev *dev)
{ {
struct ce4100_info *spi_info; struct platform_device *pdev = pci_get_drvdata(dev);
struct ssp_device *ssp;
spi_info = pci_get_drvdata(dev);
ssp = &spi_info->ssp;
platform_device_unregister(spi_info->spi_pdev);
iounmap(ssp->mmio_base);
release_mem_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
mutex_lock(&ssp_lock);
list_del(&ssp->node);
mutex_unlock(&ssp_lock);
pci_set_drvdata(dev, NULL); platform_device_unregister(pdev);
pci_disable_device(dev);
kfree(spi_info);
} }
static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = { static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
......
/*
* PXA2xx SPI private DMA support.
*
* Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/pxa2xx_ssp.h>
#include <linux/spi/spi.h>
#include <linux/spi/pxa2xx_spi.h>
#include "spi-pxa2xx.h"
#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
bool pxa2xx_spi_dma_is_possible(size_t len)
{
/* Try to map dma buffer and do a dma transfer if successful, but
* only if the length is non-zero and less than MAX_DMA_LEN.
*
* Zero-length non-descriptor DMA is illegal on PXA2xx; force use
* of PIO instead. Care is needed above because the transfer may
* have have been passed with buffers that are already dma mapped.
* A zero-length transfer in PIO mode will not try to write/read
* to/from the buffers
*
* REVISIT large transfers are exactly where we most want to be
* using DMA. If this happens much, split those transfers into
* multiple DMA segments rather than forcing PIO.
*/
return len > 0 && len <= MAX_DMA_LEN;
}
int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data)
{
struct spi_message *msg = drv_data->cur_msg;
struct device *dev = &msg->spi->dev;
if (!drv_data->cur_chip->enable_dma)
return 0;
if (msg->is_dma_mapped)
return drv_data->rx_dma && drv_data->tx_dma;
if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
return 0;
/* Modify setup if rx buffer is null */
if (drv_data->rx == NULL) {
*drv_data->null_dma_buf = 0;
drv_data->rx = drv_data->null_dma_buf;
drv_data->rx_map_len = 4;
} else
drv_data->rx_map_len = drv_data->len;
/* Modify setup if tx buffer is null */
if (drv_data->tx == NULL) {
*drv_data->null_dma_buf = 0;
drv_data->tx = drv_data->null_dma_buf;
drv_data->tx_map_len = 4;
} else
drv_data->tx_map_len = drv_data->len;
/* Stream map the tx buffer. Always do DMA_TO_DEVICE first
* so we flush the cache *before* invalidating it, in case
* the tx and rx buffers overlap.
*/
drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
drv_data->tx_map_len, DMA_TO_DEVICE);
if (dma_mapping_error(dev, drv_data->tx_dma))
return 0;
/* Stream map the rx buffer */
drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
drv_data->rx_map_len, DMA_FROM_DEVICE);
if (dma_mapping_error(dev, drv_data->rx_dma)) {
dma_unmap_single(dev, drv_data->tx_dma,
drv_data->tx_map_len, DMA_TO_DEVICE);
return 0;
}
return 1;
}
static void pxa2xx_spi_unmap_dma_buffers(struct driver_data *drv_data)
{
struct device *dev;
if (!drv_data->dma_mapped)
return;
if (!drv_data->cur_msg->is_dma_mapped) {
dev = &drv_data->cur_msg->spi->dev;
dma_unmap_single(dev, drv_data->rx_dma,
drv_data->rx_map_len, DMA_FROM_DEVICE);
dma_unmap_single(dev, drv_data->tx_dma,
drv_data->tx_map_len, DMA_TO_DEVICE);
}
drv_data->dma_mapped = 0;
}
static int wait_ssp_rx_stall(void const __iomem *ioaddr)
{
unsigned long limit = loops_per_jiffy << 1;
while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
cpu_relax();
return limit;
}
static int wait_dma_channel_stop(int channel)
{
unsigned long limit = loops_per_jiffy << 1;
while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
cpu_relax();
return limit;
}
static void pxa2xx_spi_dma_error_stop(struct driver_data *drv_data,
const char *msg)
{
void __iomem *reg = drv_data->ioaddr;
/* Stop and reset */
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
write_SSSR_CS(drv_data, drv_data->clear_sr);
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
if (!pxa25x_ssp_comp(drv_data))
write_SSTO(0, reg);
pxa2xx_spi_flush(drv_data);
write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
pxa2xx_spi_unmap_dma_buffers(drv_data);
dev_err(&drv_data->pdev->dev, "%s\n", msg);
drv_data->cur_msg->state = ERROR_STATE;
tasklet_schedule(&drv_data->pump_transfers);
}
static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data)
{
void __iomem *reg = drv_data->ioaddr;
struct spi_message *msg = drv_data->cur_msg;
/* Clear and disable interrupts on SSP and DMA channels*/
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
write_SSSR_CS(drv_data, drv_data->clear_sr);
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
dev_err(&drv_data->pdev->dev,
"dma_handler: dma rx channel stop failed\n");
if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
dev_err(&drv_data->pdev->dev,
"dma_transfer: ssp rx stall failed\n");
pxa2xx_spi_unmap_dma_buffers(drv_data);
/* update the buffer pointer for the amount completed in dma */
drv_data->rx += drv_data->len -
(DCMD(drv_data->rx_channel) & DCMD_LENGTH);
/* read trailing data from fifo, it does not matter how many
* bytes are in the fifo just read until buffer is full
* or fifo is empty, which ever occurs first */
drv_data->read(drv_data);
/* return count of what was actually read */
msg->actual_length += drv_data->len -
(drv_data->rx_end - drv_data->rx);
/* Transfer delays and chip select release are
* handled in pump_transfers or giveback
*/
/* Move to next transfer */
msg->state = pxa2xx_spi_next_transfer(drv_data);
/* Schedule transfer tasklet */
tasklet_schedule(&drv_data->pump_transfers);
}
void pxa2xx_spi_dma_handler(int channel, void *data)
{
struct driver_data *drv_data = data;
u32 irq_status = DCSR(channel) & DMA_INT_MASK;
if (irq_status & DCSR_BUSERR) {
if (channel == drv_data->tx_channel)
pxa2xx_spi_dma_error_stop(drv_data,
"dma_handler: bad bus address on tx channel");
else
pxa2xx_spi_dma_error_stop(drv_data,
"dma_handler: bad bus address on rx channel");
return;
}
/* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
if ((channel == drv_data->tx_channel)
&& (irq_status & DCSR_ENDINTR)
&& (drv_data->ssp_type == PXA25x_SSP)) {
/* Wait for rx to stall */
if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
dev_err(&drv_data->pdev->dev,
"dma_handler: ssp rx stall failed\n");
/* finish this transfer, start the next */
pxa2xx_spi_dma_transfer_complete(drv_data);
}
}
irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
{
u32 irq_status;
void __iomem *reg = drv_data->ioaddr;
irq_status = read_SSSR(reg) & drv_data->mask_sr;
if (irq_status & SSSR_ROR) {
pxa2xx_spi_dma_error_stop(drv_data,
"dma_transfer: fifo overrun");
return IRQ_HANDLED;
}
/* Check for false positive timeout */
if ((irq_status & SSSR_TINT)
&& (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
write_SSSR(SSSR_TINT, reg);
return IRQ_HANDLED;
}
if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
/* Clear and disable timeout interrupt, do the rest in
* dma_transfer_complete */
if (!pxa25x_ssp_comp(drv_data))
write_SSTO(0, reg);
/* finish this transfer, start the next */
pxa2xx_spi_dma_transfer_complete(drv_data);
return IRQ_HANDLED;
}
/* Opps problem detected */
return IRQ_NONE;
}
int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst)
{
u32 dma_width;
switch (drv_data->n_bytes) {
case 1:
dma_width = DCMD_WIDTH1;
break;
case 2:
dma_width = DCMD_WIDTH2;
break;
default:
dma_width = DCMD_WIDTH4;
break;
}
/* Setup rx DMA Channel */
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
DTADR(drv_data->rx_channel) = drv_data->rx_dma;
if (drv_data->rx == drv_data->null_dma_buf)
/* No target address increment */
DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
| dma_width
| dma_burst
| drv_data->len;
else
DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
| DCMD_FLOWSRC
| dma_width
| dma_burst
| drv_data->len;
/* Setup tx DMA Channel */
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
DSADR(drv_data->tx_channel) = drv_data->tx_dma;
DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
if (drv_data->tx == drv_data->null_dma_buf)
/* No source address increment */
DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
| dma_width
| dma_burst
| drv_data->len;
else
DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
| DCMD_FLOWTRG
| dma_width
| dma_burst
| drv_data->len;
/* Enable dma end irqs on SSP to detect end of transfer */
if (drv_data->ssp_type == PXA25x_SSP)
DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
return 0;
}
void pxa2xx_spi_dma_start(struct driver_data *drv_data)
{
DCSR(drv_data->rx_channel) |= DCSR_RUN;
DCSR(drv_data->tx_channel) |= DCSR_RUN;
}
int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
{
struct device *dev = &drv_data->pdev->dev;
struct ssp_device *ssp = drv_data->ssp;
/* Get two DMA channels (rx and tx) */
drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx",
DMA_PRIO_HIGH,
pxa2xx_spi_dma_handler,
drv_data);
if (drv_data->rx_channel < 0) {
dev_err(dev, "problem (%d) requesting rx channel\n",
drv_data->rx_channel);
return -ENODEV;
}
drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
DMA_PRIO_MEDIUM,
pxa2xx_spi_dma_handler,
drv_data);
if (drv_data->tx_channel < 0) {
dev_err(dev, "problem (%d) requesting tx channel\n",
drv_data->tx_channel);
pxa_free_dma(drv_data->rx_channel);
return -ENODEV;
}
DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel;
DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel;
return 0;
}
void pxa2xx_spi_dma_release(struct driver_data *drv_data)
{
struct ssp_device *ssp = drv_data->ssp;
DRCMR(ssp->drcmr_rx) = 0;
DRCMR(ssp->drcmr_tx) = 0;
if (drv_data->tx_channel != 0)
pxa_free_dma(drv_data->tx_channel);
if (drv_data->rx_channel != 0)
pxa_free_dma(drv_data->rx_channel);
}
void pxa2xx_spi_dma_resume(struct driver_data *drv_data)
{
if (drv_data->rx_channel != -1)
DRCMR(drv_data->ssp->drcmr_rx) =
DRCMR_MAPVLD | drv_data->rx_channel;
if (drv_data->tx_channel != -1)
DRCMR(drv_data->ssp->drcmr_tx) =
DRCMR_MAPVLD | drv_data->tx_channel;
}
int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
struct spi_device *spi,
u8 bits_per_word, u32 *burst_code,
u32 *threshold)
{
struct pxa2xx_spi_chip *chip_info =
(struct pxa2xx_spi_chip *)spi->controller_data;
int bytes_per_word;
int burst_bytes;
int thresh_words;
int req_burst_size;
int retval = 0;
/* Set the threshold (in registers) to equal the same amount of data
* as represented by burst size (in bytes). The computation below
* is (burst_size rounded up to nearest 8 byte, word or long word)
* divided by (bytes/register); the tx threshold is the inverse of
* the rx, so that there will always be enough data in the rx fifo
* to satisfy a burst, and there will always be enough space in the
* tx fifo to accept a burst (a tx burst will overwrite the fifo if
* there is not enough space), there must always remain enough empty
* space in the rx fifo for any data loaded to the tx fifo.
* Whenever burst_size (in bytes) equals bits/word, the fifo threshold
* will be 8, or half the fifo;
* The threshold can only be set to 2, 4 or 8, but not 16, because
* to burst 16 to the tx fifo, the fifo would have to be empty;
* however, the minimum fifo trigger level is 1, and the tx will
* request service when the fifo is at this level, with only 15 spaces.
*/
/* find bytes/word */
if (bits_per_word <= 8)
bytes_per_word = 1;
else if (bits_per_word <= 16)
bytes_per_word = 2;
else
bytes_per_word = 4;
/* use struct pxa2xx_spi_chip->dma_burst_size if available */
if (chip_info)
req_burst_size = chip_info->dma_burst_size;
else {
switch (chip->dma_burst_size) {
default:
/* if the default burst size is not set,
* do it now */
chip->dma_burst_size = DCMD_BURST8;
case DCMD_BURST8:
req_burst_size = 8;
break;
case DCMD_BURST16:
req_burst_size = 16;
break;
case DCMD_BURST32:
req_burst_size = 32;
break;
}
}
if (req_burst_size <= 8) {
*burst_code = DCMD_BURST8;
burst_bytes = 8;
} else if (req_burst_size <= 16) {
if (bytes_per_word == 1) {
/* don't burst more than 1/2 the fifo */
*burst_code = DCMD_BURST8;
burst_bytes = 8;
retval = 1;
} else {
*burst_code = DCMD_BURST16;
burst_bytes = 16;
}
} else {
if (bytes_per_word == 1) {
/* don't burst more than 1/2 the fifo */
*burst_code = DCMD_BURST8;
burst_bytes = 8;
retval = 1;
} else if (bytes_per_word == 2) {
/* don't burst more than 1/2 the fifo */
*burst_code = DCMD_BURST16;
burst_bytes = 16;
retval = 1;
} else {
*burst_code = DCMD_BURST32;
burst_bytes = 32;
}
}
thresh_words = burst_bytes / bytes_per_word;
/* thresh_words will be between 2 and 8 */
*threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
| (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
return retval;
}
/* /*
* Copyright (C) 2005 Stephen Street / StreetFire Sound Labs * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
* Copyright (C) 2013, Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -24,17 +25,20 @@ ...@@ -24,17 +25,20 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/pxa2xx_spi.h> #include <linux/spi/pxa2xx_spi.h>
#include <linux/dma-mapping.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/acpi.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/delay.h> #include <asm/delay.h>
#include "spi-pxa2xx.h"
MODULE_AUTHOR("Stephen Street"); MODULE_AUTHOR("Stephen Street");
MODULE_DESCRIPTION("PXA2xx SSP SPI Controller"); MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
...@@ -45,12 +49,6 @@ MODULE_ALIAS("platform:pxa2xx-spi"); ...@@ -45,12 +49,6 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define TIMOUT_DFLT 1000 #define TIMOUT_DFLT 1000
#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
#define IS_DMA_ALIGNED(x) ((((u32)(x)) & 0x07) == 0)
#define MAX_DMA_LEN 8191
#define DMA_ALIGNMENT 8
/* /*
* for testing SSCR1 changes that require SSP restart, basically * for testing SSCR1 changes that require SSP restart, basically
* everything except the service and interrupt enables, the pxa270 developer * everything except the service and interrupt enables, the pxa270 developer
...@@ -65,115 +63,97 @@ MODULE_ALIAS("platform:pxa2xx-spi"); ...@@ -65,115 +63,97 @@ MODULE_ALIAS("platform:pxa2xx-spi");
| SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \ | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
| SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
#define DEFINE_SSP_REG(reg, off) \ #define LPSS_RX_THRESH_DFLT 64
static inline u32 read_##reg(void const __iomem *p) \ #define LPSS_TX_LOTHRESH_DFLT 160
{ return __raw_readl(p + (off)); } \ #define LPSS_TX_HITHRESH_DFLT 224
\
static inline void write_##reg(u32 v, void __iomem *p) \
{ __raw_writel(v, p + (off)); }
DEFINE_SSP_REG(SSCR0, 0x00)
DEFINE_SSP_REG(SSCR1, 0x04)
DEFINE_SSP_REG(SSSR, 0x08)
DEFINE_SSP_REG(SSITR, 0x0c)
DEFINE_SSP_REG(SSDR, 0x10)
DEFINE_SSP_REG(SSTO, 0x28)
DEFINE_SSP_REG(SSPSP, 0x2c)
#define START_STATE ((void*)0)
#define RUNNING_STATE ((void*)1)
#define DONE_STATE ((void*)2)
#define ERROR_STATE ((void*)-1)
#define QUEUE_RUNNING 0
#define QUEUE_STOPPED 1
struct driver_data {
/* Driver model hookup */
struct platform_device *pdev;
/* SSP Info */
struct ssp_device *ssp;
/* SPI framework hookup */ /* Offset from drv_data->lpss_base */
enum pxa_ssp_type ssp_type; #define SPI_CS_CONTROL 0x18
struct spi_master *master; #define SPI_CS_CONTROL_SW_MODE BIT(0)
#define SPI_CS_CONTROL_CS_HIGH BIT(1)
/* PXA hookup */ static bool is_lpss_ssp(const struct driver_data *drv_data)
struct pxa2xx_spi_master *master_info; {
return drv_data->ssp_type == LPSS_SSP;
/* DMA setup stuff */ }
int rx_channel;
int tx_channel;
u32 *null_dma_buf;
/* SSP register addresses */
void __iomem *ioaddr;
u32 ssdr_physical;
/* SSP masks*/
u32 dma_cr1;
u32 int_cr1;
u32 clear_sr;
u32 mask_sr;
/* Driver message queue */
struct workqueue_struct *workqueue;
struct work_struct pump_messages;
spinlock_t lock;
struct list_head queue;
int busy;
int run;
/* Message Transfer pump */
struct tasklet_struct pump_transfers;
/* Current message transfer state info */
struct spi_message* cur_msg;
struct spi_transfer* cur_transfer;
struct chip_data *cur_chip;
size_t len;
void *tx;
void *tx_end;
void *rx;
void *rx_end;
int dma_mapped;
dma_addr_t rx_dma;
dma_addr_t tx_dma;
size_t rx_map_len;
size_t tx_map_len;
u8 n_bytes;
u32 dma_width;
int (*write)(struct driver_data *drv_data);
int (*read)(struct driver_data *drv_data);
irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
void (*cs_control)(u32 command);
};
struct chip_data { /*
u32 cr0; * Read and write LPSS SSP private registers. Caller must first check that
u32 cr1; * is_lpss_ssp() returns true before these can be called.
u32 psp; */
u32 timeout; static u32 __lpss_ssp_read_priv(struct driver_data *drv_data, unsigned offset)
u8 n_bytes; {
u32 dma_width; WARN_ON(!drv_data->lpss_base);
u32 dma_burst_size; return readl(drv_data->lpss_base + offset);
u32 threshold; }
u32 dma_threshold;
u8 enable_dma;
u8 bits_per_word;
u32 speed_hz;
union {
int gpio_cs;
unsigned int frm;
};
int gpio_cs_inverted;
int (*write)(struct driver_data *drv_data);
int (*read)(struct driver_data *drv_data);
void (*cs_control)(u32 command);
};
static void pump_messages(struct work_struct *work); static void __lpss_ssp_write_priv(struct driver_data *drv_data,
unsigned offset, u32 value)
{
WARN_ON(!drv_data->lpss_base);
writel(value, drv_data->lpss_base + offset);
}
/*
* lpss_ssp_setup - perform LPSS SSP specific setup
* @drv_data: pointer to the driver private data
*
* Perform LPSS SSP specific setup. This function must be called first if
* one is going to use LPSS SSP private registers.
*/
static void lpss_ssp_setup(struct driver_data *drv_data)
{
unsigned offset = 0x400;
u32 value, orig;
if (!is_lpss_ssp(drv_data))
return;
/*
* Perform auto-detection of the LPSS SSP private registers. They
* can be either at 1k or 2k offset from the base address.
*/
orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
value = orig | SPI_CS_CONTROL_SW_MODE;
writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
if (value != (orig | SPI_CS_CONTROL_SW_MODE)) {
offset = 0x800;
goto detection_done;
}
value &= ~SPI_CS_CONTROL_SW_MODE;
writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL);
value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL);
if (value != orig) {
offset = 0x800;
goto detection_done;
}
detection_done:
/* Now set the LPSS base */
drv_data->lpss_base = drv_data->ioaddr + offset;
/* Enable software chip select control */
value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH;
__lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
}
static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
{
u32 value;
if (!is_lpss_ssp(drv_data))
return;
value = __lpss_ssp_read_priv(drv_data, SPI_CS_CONTROL);
if (enable)
value &= ~SPI_CS_CONTROL_CS_HIGH;
else
value |= SPI_CS_CONTROL_CS_HIGH;
__lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value);
}
static void cs_assert(struct driver_data *drv_data) static void cs_assert(struct driver_data *drv_data)
{ {
...@@ -189,8 +169,12 @@ static void cs_assert(struct driver_data *drv_data) ...@@ -189,8 +169,12 @@ static void cs_assert(struct driver_data *drv_data)
return; return;
} }
if (gpio_is_valid(chip->gpio_cs)) if (gpio_is_valid(chip->gpio_cs)) {
gpio_set_value(chip->gpio_cs, chip->gpio_cs_inverted); gpio_set_value(chip->gpio_cs, chip->gpio_cs_inverted);
return;
}
lpss_ssp_cs_control(drv_data, true);
} }
static void cs_deassert(struct driver_data *drv_data) static void cs_deassert(struct driver_data *drv_data)
...@@ -205,30 +189,15 @@ static void cs_deassert(struct driver_data *drv_data) ...@@ -205,30 +189,15 @@ static void cs_deassert(struct driver_data *drv_data)
return; return;
} }
if (gpio_is_valid(chip->gpio_cs)) if (gpio_is_valid(chip->gpio_cs)) {
gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted); gpio_set_value(chip->gpio_cs, !chip->gpio_cs_inverted);
} return;
}
static void write_SSSR_CS(struct driver_data *drv_data, u32 val)
{
void __iomem *reg = drv_data->ioaddr;
if (drv_data->ssp_type == CE4100_SSP)
val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
write_SSSR(val, reg);
}
static int pxa25x_ssp_comp(struct driver_data *drv_data) lpss_ssp_cs_control(drv_data, false);
{
if (drv_data->ssp_type == PXA25x_SSP)
return 1;
if (drv_data->ssp_type == CE4100_SSP)
return 1;
return 0;
} }
static int flush(struct driver_data *drv_data) int pxa2xx_spi_flush(struct driver_data *drv_data)
{ {
unsigned long limit = loops_per_jiffy << 1; unsigned long limit = loops_per_jiffy << 1;
...@@ -354,7 +323,7 @@ static int u32_reader(struct driver_data *drv_data) ...@@ -354,7 +323,7 @@ static int u32_reader(struct driver_data *drv_data)
return drv_data->rx == drv_data->rx_end; return drv_data->rx == drv_data->rx_end;
} }
static void *next_transfer(struct driver_data *drv_data) void *pxa2xx_spi_next_transfer(struct driver_data *drv_data)
{ {
struct spi_message *msg = drv_data->cur_msg; struct spi_message *msg = drv_data->cur_msg;
struct spi_transfer *trans = drv_data->cur_transfer; struct spi_transfer *trans = drv_data->cur_transfer;
...@@ -370,89 +339,15 @@ static void *next_transfer(struct driver_data *drv_data) ...@@ -370,89 +339,15 @@ static void *next_transfer(struct driver_data *drv_data)
return DONE_STATE; return DONE_STATE;
} }
static int map_dma_buffers(struct driver_data *drv_data)
{
struct spi_message *msg = drv_data->cur_msg;
struct device *dev = &msg->spi->dev;
if (!drv_data->cur_chip->enable_dma)
return 0;
if (msg->is_dma_mapped)
return drv_data->rx_dma && drv_data->tx_dma;
if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
return 0;
/* Modify setup if rx buffer is null */
if (drv_data->rx == NULL) {
*drv_data->null_dma_buf = 0;
drv_data->rx = drv_data->null_dma_buf;
drv_data->rx_map_len = 4;
} else
drv_data->rx_map_len = drv_data->len;
/* Modify setup if tx buffer is null */
if (drv_data->tx == NULL) {
*drv_data->null_dma_buf = 0;
drv_data->tx = drv_data->null_dma_buf;
drv_data->tx_map_len = 4;
} else
drv_data->tx_map_len = drv_data->len;
/* Stream map the tx buffer. Always do DMA_TO_DEVICE first
* so we flush the cache *before* invalidating it, in case
* the tx and rx buffers overlap.
*/
drv_data->tx_dma = dma_map_single(dev, drv_data->tx,
drv_data->tx_map_len, DMA_TO_DEVICE);
if (dma_mapping_error(dev, drv_data->tx_dma))
return 0;
/* Stream map the rx buffer */
drv_data->rx_dma = dma_map_single(dev, drv_data->rx,
drv_data->rx_map_len, DMA_FROM_DEVICE);
if (dma_mapping_error(dev, drv_data->rx_dma)) {
dma_unmap_single(dev, drv_data->tx_dma,
drv_data->tx_map_len, DMA_TO_DEVICE);
return 0;
}
return 1;
}
static void unmap_dma_buffers(struct driver_data *drv_data)
{
struct device *dev;
if (!drv_data->dma_mapped)
return;
if (!drv_data->cur_msg->is_dma_mapped) {
dev = &drv_data->cur_msg->spi->dev;
dma_unmap_single(dev, drv_data->rx_dma,
drv_data->rx_map_len, DMA_FROM_DEVICE);
dma_unmap_single(dev, drv_data->tx_dma,
drv_data->tx_map_len, DMA_TO_DEVICE);
}
drv_data->dma_mapped = 0;
}
/* caller already set message->status; dma and pio irqs are blocked */ /* caller already set message->status; dma and pio irqs are blocked */
static void giveback(struct driver_data *drv_data) static void giveback(struct driver_data *drv_data)
{ {
struct spi_transfer* last_transfer; struct spi_transfer* last_transfer;
unsigned long flags;
struct spi_message *msg; struct spi_message *msg;
spin_lock_irqsave(&drv_data->lock, flags);
msg = drv_data->cur_msg; msg = drv_data->cur_msg;
drv_data->cur_msg = NULL; drv_data->cur_msg = NULL;
drv_data->cur_transfer = NULL; drv_data->cur_transfer = NULL;
queue_work(drv_data->workqueue, &drv_data->pump_messages);
spin_unlock_irqrestore(&drv_data->lock, flags);
last_transfer = list_entry(msg->transfers.prev, last_transfer = list_entry(msg->transfers.prev,
struct spi_transfer, struct spi_transfer,
...@@ -481,13 +376,7 @@ static void giveback(struct driver_data *drv_data) ...@@ -481,13 +376,7 @@ static void giveback(struct driver_data *drv_data)
*/ */
/* get a pointer to the next message, if any */ /* get a pointer to the next message, if any */
spin_lock_irqsave(&drv_data->lock, flags); next_msg = spi_get_next_queued_message(drv_data->master);
if (list_empty(&drv_data->queue))
next_msg = NULL;
else
next_msg = list_entry(drv_data->queue.next,
struct spi_message, queue);
spin_unlock_irqrestore(&drv_data->lock, flags);
/* see if the next and current messages point /* see if the next and current messages point
* to the same chip * to the same chip
...@@ -498,168 +387,10 @@ static void giveback(struct driver_data *drv_data) ...@@ -498,168 +387,10 @@ static void giveback(struct driver_data *drv_data)
cs_deassert(drv_data); cs_deassert(drv_data);
} }
msg->state = NULL; spi_finalize_current_message(drv_data->master);
if (msg->complete)
msg->complete(msg->context);
drv_data->cur_chip = NULL; drv_data->cur_chip = NULL;
} }
static int wait_ssp_rx_stall(void const __iomem *ioaddr)
{
unsigned long limit = loops_per_jiffy << 1;
while ((read_SSSR(ioaddr) & SSSR_BSY) && --limit)
cpu_relax();
return limit;
}
static int wait_dma_channel_stop(int channel)
{
unsigned long limit = loops_per_jiffy << 1;
while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit)
cpu_relax();
return limit;
}
static void dma_error_stop(struct driver_data *drv_data, const char *msg)
{
void __iomem *reg = drv_data->ioaddr;
/* Stop and reset */
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
write_SSSR_CS(drv_data, drv_data->clear_sr);
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
if (!pxa25x_ssp_comp(drv_data))
write_SSTO(0, reg);
flush(drv_data);
write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
unmap_dma_buffers(drv_data);
dev_err(&drv_data->pdev->dev, "%s\n", msg);
drv_data->cur_msg->state = ERROR_STATE;
tasklet_schedule(&drv_data->pump_transfers);
}
static void dma_transfer_complete(struct driver_data *drv_data)
{
void __iomem *reg = drv_data->ioaddr;
struct spi_message *msg = drv_data->cur_msg;
/* Clear and disable interrupts on SSP and DMA channels*/
write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg);
write_SSSR_CS(drv_data, drv_data->clear_sr);
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
if (wait_dma_channel_stop(drv_data->rx_channel) == 0)
dev_err(&drv_data->pdev->dev,
"dma_handler: dma rx channel stop failed\n");
if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
dev_err(&drv_data->pdev->dev,
"dma_transfer: ssp rx stall failed\n");
unmap_dma_buffers(drv_data);
/* update the buffer pointer for the amount completed in dma */
drv_data->rx += drv_data->len -
(DCMD(drv_data->rx_channel) & DCMD_LENGTH);
/* read trailing data from fifo, it does not matter how many
* bytes are in the fifo just read until buffer is full
* or fifo is empty, which ever occurs first */
drv_data->read(drv_data);
/* return count of what was actually read */
msg->actual_length += drv_data->len -
(drv_data->rx_end - drv_data->rx);
/* Transfer delays and chip select release are
* handled in pump_transfers or giveback
*/
/* Move to next transfer */
msg->state = next_transfer(drv_data);
/* Schedule transfer tasklet */
tasklet_schedule(&drv_data->pump_transfers);
}
static void dma_handler(int channel, void *data)
{
struct driver_data *drv_data = data;
u32 irq_status = DCSR(channel) & DMA_INT_MASK;
if (irq_status & DCSR_BUSERR) {
if (channel == drv_data->tx_channel)
dma_error_stop(drv_data,
"dma_handler: "
"bad bus address on tx channel");
else
dma_error_stop(drv_data,
"dma_handler: "
"bad bus address on rx channel");
return;
}
/* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */
if ((channel == drv_data->tx_channel)
&& (irq_status & DCSR_ENDINTR)
&& (drv_data->ssp_type == PXA25x_SSP)) {
/* Wait for rx to stall */
if (wait_ssp_rx_stall(drv_data->ioaddr) == 0)
dev_err(&drv_data->pdev->dev,
"dma_handler: ssp rx stall failed\n");
/* finish this transfer, start the next */
dma_transfer_complete(drv_data);
}
}
static irqreturn_t dma_transfer(struct driver_data *drv_data)
{
u32 irq_status;
void __iomem *reg = drv_data->ioaddr;
irq_status = read_SSSR(reg) & drv_data->mask_sr;
if (irq_status & SSSR_ROR) {
dma_error_stop(drv_data, "dma_transfer: fifo overrun");
return IRQ_HANDLED;
}
/* Check for false positive timeout */
if ((irq_status & SSSR_TINT)
&& (DCSR(drv_data->tx_channel) & DCSR_RUN)) {
write_SSSR(SSSR_TINT, reg);
return IRQ_HANDLED;
}
if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) {
/* Clear and disable timeout interrupt, do the rest in
* dma_transfer_complete */
if (!pxa25x_ssp_comp(drv_data))
write_SSTO(0, reg);
/* finish this transfer, start the next */
dma_transfer_complete(drv_data);
return IRQ_HANDLED;
}
/* Opps problem detected */
return IRQ_NONE;
}
static void reset_sccr1(struct driver_data *drv_data) static void reset_sccr1(struct driver_data *drv_data)
{ {
void __iomem *reg = drv_data->ioaddr; void __iomem *reg = drv_data->ioaddr;
...@@ -681,7 +412,7 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg) ...@@ -681,7 +412,7 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg)
reset_sccr1(drv_data); reset_sccr1(drv_data);
if (!pxa25x_ssp_comp(drv_data)) if (!pxa25x_ssp_comp(drv_data))
write_SSTO(0, reg); write_SSTO(0, reg);
flush(drv_data); pxa2xx_spi_flush(drv_data);
write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg);
dev_err(&drv_data->pdev->dev, "%s\n", msg); dev_err(&drv_data->pdev->dev, "%s\n", msg);
...@@ -709,7 +440,7 @@ static void int_transfer_complete(struct driver_data *drv_data) ...@@ -709,7 +440,7 @@ static void int_transfer_complete(struct driver_data *drv_data)
*/ */
/* Move to next transfer */ /* Move to next transfer */
drv_data->cur_msg->state = next_transfer(drv_data); drv_data->cur_msg->state = pxa2xx_spi_next_transfer(drv_data);
/* Schedule transfer tasklet */ /* Schedule transfer tasklet */
tasklet_schedule(&drv_data->pump_transfers); tasklet_schedule(&drv_data->pump_transfers);
...@@ -789,10 +520,20 @@ static irqreturn_t ssp_int(int irq, void *dev_id) ...@@ -789,10 +520,20 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
{ {
struct driver_data *drv_data = dev_id; struct driver_data *drv_data = dev_id;
void __iomem *reg = drv_data->ioaddr; void __iomem *reg = drv_data->ioaddr;
u32 sccr1_reg = read_SSCR1(reg); u32 sccr1_reg;
u32 mask = drv_data->mask_sr; u32 mask = drv_data->mask_sr;
u32 status; u32 status;
/*
* The IRQ might be shared with other peripherals so we must first
* check that are we RPM suspended or not. If we are we assume that
* the IRQ was not for us (we shouldn't be RPM suspended when the
* interrupt is enabled).
*/
if (pm_runtime_suspended(&drv_data->pdev->dev))
return IRQ_NONE;
sccr1_reg = read_SSCR1(reg);
status = read_SSSR(reg); status = read_SSSR(reg);
/* Ignore possible writes if we don't need to write */ /* Ignore possible writes if we don't need to write */
...@@ -820,106 +561,12 @@ static irqreturn_t ssp_int(int irq, void *dev_id) ...@@ -820,106 +561,12 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
return drv_data->transfer_handler(drv_data); return drv_data->transfer_handler(drv_data);
} }
static int set_dma_burst_and_threshold(struct chip_data *chip, static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
struct spi_device *spi,
u8 bits_per_word, u32 *burst_code,
u32 *threshold)
{ {
struct pxa2xx_spi_chip *chip_info = unsigned long ssp_clk = drv_data->max_clk_rate;
(struct pxa2xx_spi_chip *)spi->controller_data; const struct ssp_device *ssp = drv_data->ssp;
int bytes_per_word;
int burst_bytes;
int thresh_words;
int req_burst_size;
int retval = 0;
/* Set the threshold (in registers) to equal the same amount of data
* as represented by burst size (in bytes). The computation below
* is (burst_size rounded up to nearest 8 byte, word or long word)
* divided by (bytes/register); the tx threshold is the inverse of
* the rx, so that there will always be enough data in the rx fifo
* to satisfy a burst, and there will always be enough space in the
* tx fifo to accept a burst (a tx burst will overwrite the fifo if
* there is not enough space), there must always remain enough empty
* space in the rx fifo for any data loaded to the tx fifo.
* Whenever burst_size (in bytes) equals bits/word, the fifo threshold
* will be 8, or half the fifo;
* The threshold can only be set to 2, 4 or 8, but not 16, because
* to burst 16 to the tx fifo, the fifo would have to be empty;
* however, the minimum fifo trigger level is 1, and the tx will
* request service when the fifo is at this level, with only 15 spaces.
*/
/* find bytes/word */ rate = min_t(int, ssp_clk, rate);
if (bits_per_word <= 8)
bytes_per_word = 1;
else if (bits_per_word <= 16)
bytes_per_word = 2;
else
bytes_per_word = 4;
/* use struct pxa2xx_spi_chip->dma_burst_size if available */
if (chip_info)
req_burst_size = chip_info->dma_burst_size;
else {
switch (chip->dma_burst_size) {
default:
/* if the default burst size is not set,
* do it now */
chip->dma_burst_size = DCMD_BURST8;
case DCMD_BURST8:
req_burst_size = 8;
break;
case DCMD_BURST16:
req_burst_size = 16;
break;
case DCMD_BURST32:
req_burst_size = 32;
break;
}
}
if (req_burst_size <= 8) {
*burst_code = DCMD_BURST8;
burst_bytes = 8;
} else if (req_burst_size <= 16) {
if (bytes_per_word == 1) {
/* don't burst more than 1/2 the fifo */
*burst_code = DCMD_BURST8;
burst_bytes = 8;
retval = 1;
} else {
*burst_code = DCMD_BURST16;
burst_bytes = 16;
}
} else {
if (bytes_per_word == 1) {
/* don't burst more than 1/2 the fifo */
*burst_code = DCMD_BURST8;
burst_bytes = 8;
retval = 1;
} else if (bytes_per_word == 2) {
/* don't burst more than 1/2 the fifo */
*burst_code = DCMD_BURST16;
burst_bytes = 16;
retval = 1;
} else {
*burst_code = DCMD_BURST32;
burst_bytes = 32;
}
}
thresh_words = burst_bytes / bytes_per_word;
/* thresh_words will be between 2 and 8 */
*threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT)
| (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT);
return retval;
}
static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate)
{
unsigned long ssp_clk = clk_get_rate(ssp->clk);
if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP) if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8; return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
...@@ -934,7 +581,6 @@ static void pump_transfers(unsigned long data) ...@@ -934,7 +581,6 @@ static void pump_transfers(unsigned long data)
struct spi_transfer *transfer = NULL; struct spi_transfer *transfer = NULL;
struct spi_transfer *previous = NULL; struct spi_transfer *previous = NULL;
struct chip_data *chip = NULL; struct chip_data *chip = NULL;
struct ssp_device *ssp = drv_data->ssp;
void __iomem *reg = drv_data->ioaddr; void __iomem *reg = drv_data->ioaddr;
u32 clk_div = 0; u32 clk_div = 0;
u8 bits = 0; u8 bits = 0;
...@@ -976,8 +622,8 @@ static void pump_transfers(unsigned long data) ...@@ -976,8 +622,8 @@ static void pump_transfers(unsigned long data)
cs_deassert(drv_data); cs_deassert(drv_data);
} }
/* Check for transfers that need multiple DMA segments */ /* Check if we can DMA this transfer */
if (transfer->len > MAX_DMA_LEN && chip->enable_dma) { if (!pxa2xx_spi_dma_is_possible(transfer->len) && chip->enable_dma) {
/* reject already-mapped transfers; PIO won't always work */ /* reject already-mapped transfers; PIO won't always work */
if (message->is_dma_mapped if (message->is_dma_mapped
...@@ -1000,21 +646,20 @@ static void pump_transfers(unsigned long data) ...@@ -1000,21 +646,20 @@ static void pump_transfers(unsigned long data)
} }
/* Setup the transfer state based on the type of transfer */ /* Setup the transfer state based on the type of transfer */
if (flush(drv_data) == 0) { if (pxa2xx_spi_flush(drv_data) == 0) {
dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n"); dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n");
message->status = -EIO; message->status = -EIO;
giveback(drv_data); giveback(drv_data);
return; return;
} }
drv_data->n_bytes = chip->n_bytes; drv_data->n_bytes = chip->n_bytes;
drv_data->dma_width = chip->dma_width;
drv_data->tx = (void *)transfer->tx_buf; drv_data->tx = (void *)transfer->tx_buf;
drv_data->tx_end = drv_data->tx + transfer->len; drv_data->tx_end = drv_data->tx + transfer->len;
drv_data->rx = transfer->rx_buf; drv_data->rx = transfer->rx_buf;
drv_data->rx_end = drv_data->rx + transfer->len; drv_data->rx_end = drv_data->rx + transfer->len;
drv_data->rx_dma = transfer->rx_dma; drv_data->rx_dma = transfer->rx_dma;
drv_data->tx_dma = transfer->tx_dma; drv_data->tx_dma = transfer->tx_dma;
drv_data->len = transfer->len & DCMD_LENGTH; drv_data->len = transfer->len;
drv_data->write = drv_data->tx ? chip->write : null_writer; drv_data->write = drv_data->tx ? chip->write : null_writer;
drv_data->read = drv_data->rx ? chip->read : null_reader; drv_data->read = drv_data->rx ? chip->read : null_reader;
...@@ -1031,25 +676,22 @@ static void pump_transfers(unsigned long data) ...@@ -1031,25 +676,22 @@ static void pump_transfers(unsigned long data)
if (transfer->bits_per_word) if (transfer->bits_per_word)
bits = transfer->bits_per_word; bits = transfer->bits_per_word;
clk_div = ssp_get_clk_div(ssp, speed); clk_div = ssp_get_clk_div(drv_data, speed);
if (bits <= 8) { if (bits <= 8) {
drv_data->n_bytes = 1; drv_data->n_bytes = 1;
drv_data->dma_width = DCMD_WIDTH1;
drv_data->read = drv_data->read != null_reader ? drv_data->read = drv_data->read != null_reader ?
u8_reader : null_reader; u8_reader : null_reader;
drv_data->write = drv_data->write != null_writer ? drv_data->write = drv_data->write != null_writer ?
u8_writer : null_writer; u8_writer : null_writer;
} else if (bits <= 16) { } else if (bits <= 16) {
drv_data->n_bytes = 2; drv_data->n_bytes = 2;
drv_data->dma_width = DCMD_WIDTH2;
drv_data->read = drv_data->read != null_reader ? drv_data->read = drv_data->read != null_reader ?
u16_reader : null_reader; u16_reader : null_reader;
drv_data->write = drv_data->write != null_writer ? drv_data->write = drv_data->write != null_writer ?
u16_writer : null_writer; u16_writer : null_writer;
} else if (bits <= 32) { } else if (bits <= 32) {
drv_data->n_bytes = 4; drv_data->n_bytes = 4;
drv_data->dma_width = DCMD_WIDTH4;
drv_data->read = drv_data->read != null_reader ? drv_data->read = drv_data->read != null_reader ?
u32_reader : null_reader; u32_reader : null_reader;
drv_data->write = drv_data->write != null_writer ? drv_data->write = drv_data->write != null_writer ?
...@@ -1058,7 +700,8 @@ static void pump_transfers(unsigned long data) ...@@ -1058,7 +700,8 @@ static void pump_transfers(unsigned long data)
/* if bits/word is changed in dma mode, then must check the /* if bits/word is changed in dma mode, then must check the
* thresholds and burst also */ * thresholds and burst also */
if (chip->enable_dma) { if (chip->enable_dma) {
if (set_dma_burst_and_threshold(chip, message->spi, if (pxa2xx_spi_set_dma_burst_and_threshold(chip,
message->spi,
bits, &dma_burst, bits, &dma_burst,
&dma_thresh)) &dma_thresh))
if (printk_ratelimit()) if (printk_ratelimit())
...@@ -1077,70 +720,21 @@ static void pump_transfers(unsigned long data) ...@@ -1077,70 +720,21 @@ static void pump_transfers(unsigned long data)
message->state = RUNNING_STATE; message->state = RUNNING_STATE;
/* Try to map dma buffer and do a dma transfer if successful, but
* only if the length is non-zero and less than MAX_DMA_LEN.
*
* Zero-length non-descriptor DMA is illegal on PXA2xx; force use
* of PIO instead. Care is needed above because the transfer may
* have have been passed with buffers that are already dma mapped.
* A zero-length transfer in PIO mode will not try to write/read
* to/from the buffers
*
* REVISIT large transfers are exactly where we most want to be
* using DMA. If this happens much, split those transfers into
* multiple DMA segments rather than forcing PIO.
*/
drv_data->dma_mapped = 0; drv_data->dma_mapped = 0;
if (drv_data->len > 0 && drv_data->len <= MAX_DMA_LEN) if (pxa2xx_spi_dma_is_possible(drv_data->len))
drv_data->dma_mapped = map_dma_buffers(drv_data); drv_data->dma_mapped = pxa2xx_spi_map_dma_buffers(drv_data);
if (drv_data->dma_mapped) { if (drv_data->dma_mapped) {
/* Ensure we have the correct interrupt handler */ /* Ensure we have the correct interrupt handler */
drv_data->transfer_handler = dma_transfer; drv_data->transfer_handler = pxa2xx_spi_dma_transfer;
/* Setup rx DMA Channel */ pxa2xx_spi_dma_prepare(drv_data, dma_burst);
DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL;
DSADR(drv_data->rx_channel) = drv_data->ssdr_physical;
DTADR(drv_data->rx_channel) = drv_data->rx_dma;
if (drv_data->rx == drv_data->null_dma_buf)
/* No target address increment */
DCMD(drv_data->rx_channel) = DCMD_FLOWSRC
| drv_data->dma_width
| dma_burst
| drv_data->len;
else
DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR
| DCMD_FLOWSRC
| drv_data->dma_width
| dma_burst
| drv_data->len;
/* Setup tx DMA Channel */
DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL;
DSADR(drv_data->tx_channel) = drv_data->tx_dma;
DTADR(drv_data->tx_channel) = drv_data->ssdr_physical;
if (drv_data->tx == drv_data->null_dma_buf)
/* No source address increment */
DCMD(drv_data->tx_channel) = DCMD_FLOWTRG
| drv_data->dma_width
| dma_burst
| drv_data->len;
else
DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR
| DCMD_FLOWTRG
| drv_data->dma_width
| dma_burst
| drv_data->len;
/* Enable dma end irqs on SSP to detect end of transfer */
if (drv_data->ssp_type == PXA25x_SSP)
DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
/* Clear status and start DMA engine */ /* Clear status and start DMA engine */
cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1; cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
write_SSSR(drv_data->clear_sr, reg); write_SSSR(drv_data->clear_sr, reg);
DCSR(drv_data->rx_channel) |= DCSR_RUN;
DCSR(drv_data->tx_channel) |= DCSR_RUN; pxa2xx_spi_dma_start(drv_data);
} else { } else {
/* Ensure we have the correct interrupt handler */ /* Ensure we have the correct interrupt handler */
drv_data->transfer_handler = interrupt_transfer; drv_data->transfer_handler = interrupt_transfer;
...@@ -1150,6 +744,13 @@ static void pump_transfers(unsigned long data) ...@@ -1150,6 +744,13 @@ static void pump_transfers(unsigned long data)
write_SSSR_CS(drv_data, drv_data->clear_sr); write_SSSR_CS(drv_data, drv_data->clear_sr);
} }
if (is_lpss_ssp(drv_data)) {
if ((read_SSIRF(reg) & 0xff) != chip->lpss_rx_threshold)
write_SSIRF(chip->lpss_rx_threshold, reg);
if ((read_SSITF(reg) & 0xffff) != chip->lpss_tx_threshold)
write_SSITF(chip->lpss_tx_threshold, reg);
}
/* see if we need to reload the config registers */ /* see if we need to reload the config registers */
if ((read_SSCR0(reg) != cr0) if ((read_SSCR0(reg) != cr0)
|| (read_SSCR1(reg) & SSCR1_CHANGE_MASK) != || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
...@@ -1176,31 +777,12 @@ static void pump_transfers(unsigned long data) ...@@ -1176,31 +777,12 @@ static void pump_transfers(unsigned long data)
write_SSCR1(cr1, reg); write_SSCR1(cr1, reg);
} }
static void pump_messages(struct work_struct *work) static int pxa2xx_spi_transfer_one_message(struct spi_master *master,
struct spi_message *msg)
{ {
struct driver_data *drv_data = struct driver_data *drv_data = spi_master_get_devdata(master);
container_of(work, struct driver_data, pump_messages);
unsigned long flags;
/* Lock queue and check for queue work */
spin_lock_irqsave(&drv_data->lock, flags);
if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
drv_data->busy = 0;
spin_unlock_irqrestore(&drv_data->lock, flags);
return;
}
/* Make sure we are not already running a message */
if (drv_data->cur_msg) {
spin_unlock_irqrestore(&drv_data->lock, flags);
return;
}
/* Extract head of queue */
drv_data->cur_msg = list_entry(drv_data->queue.next,
struct spi_message, queue);
list_del_init(&drv_data->cur_msg->queue);
drv_data->cur_msg = msg;
/* Initial message state*/ /* Initial message state*/
drv_data->cur_msg->state = START_STATE; drv_data->cur_msg->state = START_STATE;
drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
...@@ -1213,34 +795,27 @@ static void pump_messages(struct work_struct *work) ...@@ -1213,34 +795,27 @@ static void pump_messages(struct work_struct *work)
/* Mark as busy and launch transfers */ /* Mark as busy and launch transfers */
tasklet_schedule(&drv_data->pump_transfers); tasklet_schedule(&drv_data->pump_transfers);
return 0;
drv_data->busy = 1;
spin_unlock_irqrestore(&drv_data->lock, flags);
} }
static int transfer(struct spi_device *spi, struct spi_message *msg) static int pxa2xx_spi_prepare_transfer(struct spi_master *master)
{ {
struct driver_data *drv_data = spi_master_get_devdata(spi->master); struct driver_data *drv_data = spi_master_get_devdata(master);
unsigned long flags;
spin_lock_irqsave(&drv_data->lock, flags);
if (drv_data->run == QUEUE_STOPPED) {
spin_unlock_irqrestore(&drv_data->lock, flags);
return -ESHUTDOWN;
}
msg->actual_length = 0;
msg->status = -EINPROGRESS;
msg->state = START_STATE;
list_add_tail(&msg->queue, &drv_data->queue); pm_runtime_get_sync(&drv_data->pdev->dev);
return 0;
}
if (drv_data->run == QUEUE_RUNNING && !drv_data->busy) static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
queue_work(drv_data->workqueue, &drv_data->pump_messages); {
struct driver_data *drv_data = spi_master_get_devdata(master);
spin_unlock_irqrestore(&drv_data->lock, flags); /* Disable the SSP now */
write_SSCR0(read_SSCR0(drv_data->ioaddr) & ~SSCR0_SSE,
drv_data->ioaddr);
pm_runtime_mark_last_busy(&drv_data->pdev->dev);
pm_runtime_put_autosuspend(&drv_data->pdev->dev);
return 0; return 0;
} }
...@@ -1287,10 +862,18 @@ static int setup(struct spi_device *spi) ...@@ -1287,10 +862,18 @@ static int setup(struct spi_device *spi)
struct pxa2xx_spi_chip *chip_info = NULL; struct pxa2xx_spi_chip *chip_info = NULL;
struct chip_data *chip; struct chip_data *chip;
struct driver_data *drv_data = spi_master_get_devdata(spi->master); struct driver_data *drv_data = spi_master_get_devdata(spi->master);
struct ssp_device *ssp = drv_data->ssp;
unsigned int clk_div; unsigned int clk_div;
uint tx_thres = TX_THRESH_DFLT; uint tx_thres, tx_hi_thres, rx_thres;
uint rx_thres = RX_THRESH_DFLT;
if (is_lpss_ssp(drv_data)) {
tx_thres = LPSS_TX_LOTHRESH_DFLT;
tx_hi_thres = LPSS_TX_HITHRESH_DFLT;
rx_thres = LPSS_RX_THRESH_DFLT;
} else {
tx_thres = TX_THRESH_DFLT;
tx_hi_thres = 0;
rx_thres = RX_THRESH_DFLT;
}
if (!pxa25x_ssp_comp(drv_data) if (!pxa25x_ssp_comp(drv_data)
&& (spi->bits_per_word < 4 || spi->bits_per_word > 32)) { && (spi->bits_per_word < 4 || spi->bits_per_word > 32)) {
...@@ -1330,8 +913,6 @@ static int setup(struct spi_device *spi) ...@@ -1330,8 +913,6 @@ static int setup(struct spi_device *spi)
chip->gpio_cs = -1; chip->gpio_cs = -1;
chip->enable_dma = 0; chip->enable_dma = 0;
chip->timeout = TIMOUT_DFLT; chip->timeout = TIMOUT_DFLT;
chip->dma_burst_size = drv_data->master_info->enable_dma ?
DCMD_BURST8 : 0;
} }
/* protocol drivers may change the chip settings, so... /* protocol drivers may change the chip settings, so...
...@@ -1345,23 +926,37 @@ static int setup(struct spi_device *spi) ...@@ -1345,23 +926,37 @@ static int setup(struct spi_device *spi)
chip->timeout = chip_info->timeout; chip->timeout = chip_info->timeout;
if (chip_info->tx_threshold) if (chip_info->tx_threshold)
tx_thres = chip_info->tx_threshold; tx_thres = chip_info->tx_threshold;
if (chip_info->tx_hi_threshold)
tx_hi_thres = chip_info->tx_hi_threshold;
if (chip_info->rx_threshold) if (chip_info->rx_threshold)
rx_thres = chip_info->rx_threshold; rx_thres = chip_info->rx_threshold;
chip->enable_dma = drv_data->master_info->enable_dma; chip->enable_dma = drv_data->master_info->enable_dma;
chip->dma_threshold = 0; chip->dma_threshold = 0;
if (chip_info->enable_loopback) if (chip_info->enable_loopback)
chip->cr1 = SSCR1_LBM; chip->cr1 = SSCR1_LBM;
} else if (ACPI_HANDLE(&spi->dev)) {
/*
* Slave devices enumerated from ACPI namespace don't
* usually have chip_info but we still might want to use
* DMA with them.
*/
chip->enable_dma = drv_data->master_info->enable_dma;
} }
chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) | chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
(SSCR1_TxTresh(tx_thres) & SSCR1_TFT); (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
chip->lpss_rx_threshold = SSIRF_RxThresh(rx_thres);
chip->lpss_tx_threshold = SSITF_TxLoThresh(tx_thres)
| SSITF_TxHiThresh(tx_hi_thres);
/* set dma burst and threshold outside of chip_info path so that if /* set dma burst and threshold outside of chip_info path so that if
* chip_info goes away after setting chip->enable_dma, the * chip_info goes away after setting chip->enable_dma, the
* burst and threshold can still respond to changes in bits_per_word */ * burst and threshold can still respond to changes in bits_per_word */
if (chip->enable_dma) { if (chip->enable_dma) {
/* set up legal burst and threshold for dma */ /* set up legal burst and threshold for dma */
if (set_dma_burst_and_threshold(chip, spi, spi->bits_per_word, if (pxa2xx_spi_set_dma_burst_and_threshold(chip, spi,
spi->bits_per_word,
&chip->dma_burst_size, &chip->dma_burst_size,
&chip->dma_threshold)) { &chip->dma_threshold)) {
dev_warn(&spi->dev, "in setup: DMA burst size reduced " dev_warn(&spi->dev, "in setup: DMA burst size reduced "
...@@ -1369,7 +964,7 @@ static int setup(struct spi_device *spi) ...@@ -1369,7 +964,7 @@ static int setup(struct spi_device *spi)
} }
} }
clk_div = ssp_get_clk_div(ssp, spi->max_speed_hz); clk_div = ssp_get_clk_div(drv_data, spi->max_speed_hz);
chip->speed_hz = spi->max_speed_hz; chip->speed_hz = spi->max_speed_hz;
chip->cr0 = clk_div chip->cr0 = clk_div
...@@ -1382,32 +977,32 @@ static int setup(struct spi_device *spi) ...@@ -1382,32 +977,32 @@ static int setup(struct spi_device *spi)
chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0) chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
| (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0); | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
if (spi->mode & SPI_LOOP)
chip->cr1 |= SSCR1_LBM;
/* NOTE: PXA25x_SSP _could_ use external clocking ... */ /* NOTE: PXA25x_SSP _could_ use external clocking ... */
if (!pxa25x_ssp_comp(drv_data)) if (!pxa25x_ssp_comp(drv_data))
dev_dbg(&spi->dev, "%ld Hz actual, %s\n", dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
clk_get_rate(ssp->clk) drv_data->max_clk_rate
/ (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)), / (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)),
chip->enable_dma ? "DMA" : "PIO"); chip->enable_dma ? "DMA" : "PIO");
else else
dev_dbg(&spi->dev, "%ld Hz actual, %s\n", dev_dbg(&spi->dev, "%ld Hz actual, %s\n",
clk_get_rate(ssp->clk) / 2 drv_data->max_clk_rate / 2
/ (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)), / (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)),
chip->enable_dma ? "DMA" : "PIO"); chip->enable_dma ? "DMA" : "PIO");
if (spi->bits_per_word <= 8) { if (spi->bits_per_word <= 8) {
chip->n_bytes = 1; chip->n_bytes = 1;
chip->dma_width = DCMD_WIDTH1;
chip->read = u8_reader; chip->read = u8_reader;
chip->write = u8_writer; chip->write = u8_writer;
} else if (spi->bits_per_word <= 16) { } else if (spi->bits_per_word <= 16) {
chip->n_bytes = 2; chip->n_bytes = 2;
chip->dma_width = DCMD_WIDTH2;
chip->read = u16_reader; chip->read = u16_reader;
chip->write = u16_writer; chip->write = u16_writer;
} else if (spi->bits_per_word <= 32) { } else if (spi->bits_per_word <= 32) {
chip->cr0 |= SSCR0_EDSS; chip->cr0 |= SSCR0_EDSS;
chip->n_bytes = 4; chip->n_bytes = 4;
chip->dma_width = DCMD_WIDTH4;
chip->read = u32_reader; chip->read = u32_reader;
chip->write = u32_writer; chip->write = u32_writer;
} else { } else {
...@@ -1438,93 +1033,98 @@ static void cleanup(struct spi_device *spi) ...@@ -1438,93 +1033,98 @@ static void cleanup(struct spi_device *spi)
kfree(chip); kfree(chip);
} }
static int init_queue(struct driver_data *drv_data) #ifdef CONFIG_ACPI
static int pxa2xx_spi_acpi_add_dma(struct acpi_resource *res, void *data)
{ {
INIT_LIST_HEAD(&drv_data->queue); struct pxa2xx_spi_master *pdata = data;
spin_lock_init(&drv_data->lock);
if (res->type == ACPI_RESOURCE_TYPE_FIXED_DMA) {
drv_data->run = QUEUE_STOPPED; const struct acpi_resource_fixed_dma *dma;
drv_data->busy = 0;
dma = &res->data.fixed_dma;
tasklet_init(&drv_data->pump_transfers, if (pdata->tx_slave_id < 0) {
pump_transfers, (unsigned long)drv_data); pdata->tx_slave_id = dma->request_lines;
pdata->tx_chan_id = dma->channels;
INIT_WORK(&drv_data->pump_messages, pump_messages); } else if (pdata->rx_slave_id < 0) {
drv_data->workqueue = create_singlethread_workqueue( pdata->rx_slave_id = dma->request_lines;
dev_name(drv_data->master->dev.parent)); pdata->rx_chan_id = dma->channels;
if (drv_data->workqueue == NULL) }
return -EBUSY; }
return 0; /* Tell the ACPI core to skip this resource */
return 1;
} }
static int start_queue(struct driver_data *drv_data) static struct pxa2xx_spi_master *
pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
{ {
unsigned long flags; struct pxa2xx_spi_master *pdata;
struct list_head resource_list;
spin_lock_irqsave(&drv_data->lock, flags); struct acpi_device *adev;
struct ssp_device *ssp;
if (drv_data->run == QUEUE_RUNNING || drv_data->busy) { struct resource *res;
spin_unlock_irqrestore(&drv_data->lock, flags); int devid;
return -EBUSY;
if (!ACPI_HANDLE(&pdev->dev) ||
acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
return NULL;
pdata = devm_kzalloc(&pdev->dev, sizeof(*ssp), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev,
"failed to allocate memory for platform data\n");
return NULL;
} }
drv_data->run = QUEUE_RUNNING; res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
drv_data->cur_msg = NULL; if (!res)
drv_data->cur_transfer = NULL; return NULL;
drv_data->cur_chip = NULL;
spin_unlock_irqrestore(&drv_data->lock, flags);
queue_work(drv_data->workqueue, &drv_data->pump_messages);
return 0; ssp = &pdata->ssp;
}
static int stop_queue(struct driver_data *drv_data) ssp->phys_base = res->start;
{ ssp->mmio_base = devm_request_and_ioremap(&pdev->dev, res);
unsigned long flags; if (!ssp->mmio_base) {
unsigned limit = 500; dev_err(&pdev->dev, "failed to ioremap mmio_base\n");
int status = 0; return NULL;
spin_lock_irqsave(&drv_data->lock, flags);
/* This is a bit lame, but is optimized for the common execution path.
* A wait_queue on the drv_data->busy could be used, but then the common
* execution path (pump_messages) would be required to call wake_up or
* friends on every SPI message. Do this instead */
drv_data->run = QUEUE_STOPPED;
while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
spin_unlock_irqrestore(&drv_data->lock, flags);
msleep(10);
spin_lock_irqsave(&drv_data->lock, flags);
} }
if (!list_empty(&drv_data->queue) || drv_data->busy) ssp->clk = devm_clk_get(&pdev->dev, NULL);
status = -EBUSY; ssp->irq = platform_get_irq(pdev, 0);
ssp->type = LPSS_SSP;
ssp->pdev = pdev;
spin_unlock_irqrestore(&drv_data->lock, flags); ssp->port_id = -1;
if (adev->pnp.unique_id && !kstrtoint(adev->pnp.unique_id, 0, &devid))
ssp->port_id = devid;
return status; pdata->num_chipselect = 1;
} pdata->rx_slave_id = -1;
pdata->tx_slave_id = -1;
static int destroy_queue(struct driver_data *drv_data) INIT_LIST_HEAD(&resource_list);
{ acpi_dev_get_resources(adev, &resource_list, pxa2xx_spi_acpi_add_dma,
int status; pdata);
acpi_dev_free_resource_list(&resource_list);
status = stop_queue(drv_data); pdata->enable_dma = pdata->rx_slave_id >= 0 && pdata->tx_slave_id >= 0;
/* we are unloading the module or failing to load (only two calls
* to this routine), and neither call can handle a return value.
* However, destroy_workqueue calls flush_workqueue, and that will
* block until all work is done. If the reason that stop_queue
* timed out is that the work will never finish, then it does no
* good to call destroy_workqueue, so return anyway. */
if (status != 0)
return status;
destroy_workqueue(drv_data->workqueue); return pdata;
}
return 0; static struct acpi_device_id pxa2xx_spi_acpi_match[] = {
{ "INT33C0", 0 },
{ "INT33C1", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
#else
static inline struct pxa2xx_spi_master *
pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
{
return NULL;
} }
#endif
static int pxa2xx_spi_probe(struct platform_device *pdev) static int pxa2xx_spi_probe(struct platform_device *pdev)
{ {
...@@ -1535,11 +1135,21 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1535,11 +1135,21 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
struct ssp_device *ssp; struct ssp_device *ssp;
int status; int status;
platform_info = dev->platform_data; platform_info = dev_get_platdata(dev);
if (!platform_info) {
platform_info = pxa2xx_spi_acpi_get_pdata(pdev);
if (!platform_info) {
dev_err(&pdev->dev, "missing platform data\n");
return -ENODEV;
}
}
ssp = pxa_ssp_request(pdev->id, pdev->name); ssp = pxa_ssp_request(pdev->id, pdev->name);
if (ssp == NULL) { if (!ssp)
dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id); ssp = &platform_info->ssp;
if (!ssp->mmio_base) {
dev_err(&pdev->dev, "failed to get ssp\n");
return -ENODEV; return -ENODEV;
} }
...@@ -1558,19 +1168,21 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1558,19 +1168,21 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
master->dev.parent = &pdev->dev; master->dev.parent = &pdev->dev;
master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
ACPI_HANDLE_SET(&master->dev, ACPI_HANDLE(&pdev->dev));
/* the spi->mode bits understood by this driver: */ /* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
master->bus_num = pdev->id; master->bus_num = ssp->port_id;
master->num_chipselect = platform_info->num_chipselect; master->num_chipselect = platform_info->num_chipselect;
master->dma_alignment = DMA_ALIGNMENT; master->dma_alignment = DMA_ALIGNMENT;
master->cleanup = cleanup; master->cleanup = cleanup;
master->setup = setup; master->setup = setup;
master->transfer = transfer; master->transfer_one_message = pxa2xx_spi_transfer_one_message;
master->prepare_transfer_hardware = pxa2xx_spi_prepare_transfer;
master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer;
drv_data->ssp_type = ssp->type; drv_data->ssp_type = ssp->type;
drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data + drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT);
sizeof(struct driver_data)), 8);
drv_data->ioaddr = ssp->mmio_base; drv_data->ioaddr = ssp->mmio_base;
drv_data->ssdr_physical = ssp->phys_base + SSDR; drv_data->ssdr_physical = ssp->phys_base + SSDR;
...@@ -1581,7 +1193,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1581,7 +1193,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR; drv_data->mask_sr = SSSR_RFS | SSSR_TFS | SSSR_ROR;
} else { } else {
drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE; drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
drv_data->dma_cr1 = SSCR1_TSRE | SSCR1_RSRE | SSCR1_TINTE; drv_data->dma_cr1 = DEFAULT_DMA_CR1;
drv_data->clear_sr = SSSR_ROR | SSSR_TINT; drv_data->clear_sr = SSSR_ROR | SSSR_TINT;
drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR; drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR;
} }
...@@ -1597,35 +1209,17 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1597,35 +1209,17 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
drv_data->tx_channel = -1; drv_data->tx_channel = -1;
drv_data->rx_channel = -1; drv_data->rx_channel = -1;
if (platform_info->enable_dma) { if (platform_info->enable_dma) {
status = pxa2xx_spi_dma_setup(drv_data);
/* Get two DMA channels (rx and tx) */ if (status) {
drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx", dev_warn(dev, "failed to setup DMA, using PIO\n");
DMA_PRIO_HIGH, platform_info->enable_dma = false;
dma_handler,
drv_data);
if (drv_data->rx_channel < 0) {
dev_err(dev, "problem (%d) requesting rx channel\n",
drv_data->rx_channel);
status = -ENODEV;
goto out_error_irq_alloc;
} }
drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx",
DMA_PRIO_MEDIUM,
dma_handler,
drv_data);
if (drv_data->tx_channel < 0) {
dev_err(dev, "problem (%d) requesting tx channel\n",
drv_data->tx_channel);
status = -ENODEV;
goto out_error_dma_alloc;
}
DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel;
DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel;
} }
/* Enable SOC clock */ /* Enable SOC clock */
clk_enable(ssp->clk); clk_prepare_enable(ssp->clk);
drv_data->max_clk_rate = clk_get_rate(ssp->clk);
/* Load default SSP configuration */ /* Load default SSP configuration */
write_SSCR0(0, drv_data->ioaddr); write_SSCR0(0, drv_data->ioaddr);
...@@ -1640,41 +1234,29 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) ...@@ -1640,41 +1234,29 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
write_SSTO(0, drv_data->ioaddr); write_SSTO(0, drv_data->ioaddr);
write_SSPSP(0, drv_data->ioaddr); write_SSPSP(0, drv_data->ioaddr);
/* Initial and start queue */ lpss_ssp_setup(drv_data);
status = init_queue(drv_data);
if (status != 0) { tasklet_init(&drv_data->pump_transfers, pump_transfers,
dev_err(&pdev->dev, "problem initializing queue\n"); (unsigned long)drv_data);
goto out_error_clock_enabled;
}
status = start_queue(drv_data);
if (status != 0) {
dev_err(&pdev->dev, "problem starting queue\n");
goto out_error_clock_enabled;
}
/* Register with the SPI framework */ /* Register with the SPI framework */
platform_set_drvdata(pdev, drv_data); platform_set_drvdata(pdev, drv_data);
status = spi_register_master(master); status = spi_register_master(master);
if (status != 0) { if (status != 0) {
dev_err(&pdev->dev, "problem registering spi master\n"); dev_err(&pdev->dev, "problem registering spi master\n");
goto out_error_queue_alloc; goto out_error_clock_enabled;
} }
return status; pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
out_error_queue_alloc: return status;
destroy_queue(drv_data);
out_error_clock_enabled: out_error_clock_enabled:
clk_disable(ssp->clk); clk_disable_unprepare(ssp->clk);
pxa2xx_spi_dma_release(drv_data);
out_error_dma_alloc:
if (drv_data->tx_channel != -1)
pxa_free_dma(drv_data->tx_channel);
if (drv_data->rx_channel != -1)
pxa_free_dma(drv_data->rx_channel);
out_error_irq_alloc:
free_irq(ssp->irq, drv_data); free_irq(ssp->irq, drv_data);
out_error_master_alloc: out_error_master_alloc:
...@@ -1687,37 +1269,23 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) ...@@ -1687,37 +1269,23 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
{ {
struct driver_data *drv_data = platform_get_drvdata(pdev); struct driver_data *drv_data = platform_get_drvdata(pdev);
struct ssp_device *ssp; struct ssp_device *ssp;
int status = 0;
if (!drv_data) if (!drv_data)
return 0; return 0;
ssp = drv_data->ssp; ssp = drv_data->ssp;
/* Remove the queue */ pm_runtime_get_sync(&pdev->dev);
status = destroy_queue(drv_data);
if (status != 0)
/* the kernel does not check the return status of this
* this routine (mod->exit, within the kernel). Therefore
* nothing is gained by returning from here, the module is
* going away regardless, and we should not leave any more
* resources allocated than necessary. We cannot free the
* message memory in drv_data->queue, but we can release the
* resources below. I think the kernel should honor -EBUSY
* returns but... */
dev_err(&pdev->dev, "pxa2xx_spi_remove: workqueue will not "
"complete, message memory not freed\n");
/* Disable the SSP at the peripheral and SOC level */ /* Disable the SSP at the peripheral and SOC level */
write_SSCR0(0, drv_data->ioaddr); write_SSCR0(0, drv_data->ioaddr);
clk_disable(ssp->clk); clk_disable_unprepare(ssp->clk);
/* Release DMA */ /* Release DMA */
if (drv_data->master_info->enable_dma) { if (drv_data->master_info->enable_dma)
DRCMR(ssp->drcmr_rx) = 0; pxa2xx_spi_dma_release(drv_data);
DRCMR(ssp->drcmr_tx) = 0;
pxa_free_dma(drv_data->tx_channel); pm_runtime_put_noidle(&pdev->dev);
pxa_free_dma(drv_data->rx_channel); pm_runtime_disable(&pdev->dev);
}
/* Release IRQ */ /* Release IRQ */
free_irq(ssp->irq, drv_data); free_irq(ssp->irq, drv_data);
...@@ -1749,11 +1317,11 @@ static int pxa2xx_spi_suspend(struct device *dev) ...@@ -1749,11 +1317,11 @@ static int pxa2xx_spi_suspend(struct device *dev)
struct ssp_device *ssp = drv_data->ssp; struct ssp_device *ssp = drv_data->ssp;
int status = 0; int status = 0;
status = stop_queue(drv_data); status = spi_master_suspend(drv_data->master);
if (status != 0) if (status != 0)
return status; return status;
write_SSCR0(0, drv_data->ioaddr); write_SSCR0(0, drv_data->ioaddr);
clk_disable(ssp->clk); clk_disable_unprepare(ssp->clk);
return 0; return 0;
} }
...@@ -1764,18 +1332,13 @@ static int pxa2xx_spi_resume(struct device *dev) ...@@ -1764,18 +1332,13 @@ static int pxa2xx_spi_resume(struct device *dev)
struct ssp_device *ssp = drv_data->ssp; struct ssp_device *ssp = drv_data->ssp;
int status = 0; int status = 0;
if (drv_data->rx_channel != -1) pxa2xx_spi_dma_resume(drv_data);
DRCMR(drv_data->ssp->drcmr_rx) =
DRCMR_MAPVLD | drv_data->rx_channel;
if (drv_data->tx_channel != -1)
DRCMR(drv_data->ssp->drcmr_tx) =
DRCMR_MAPVLD | drv_data->tx_channel;
/* Enable the SSP clock */ /* Enable the SSP clock */
clk_enable(ssp->clk); clk_prepare_enable(ssp->clk);
/* Start the queue running */ /* Start the queue running */
status = start_queue(drv_data); status = spi_master_resume(drv_data->master);
if (status != 0) { if (status != 0) {
dev_err(dev, "problem starting queue (%d)\n", status); dev_err(dev, "problem starting queue (%d)\n", status);
return status; return status;
...@@ -1783,20 +1346,38 @@ static int pxa2xx_spi_resume(struct device *dev) ...@@ -1783,20 +1346,38 @@ static int pxa2xx_spi_resume(struct device *dev)
return 0; return 0;
} }
#endif
#ifdef CONFIG_PM_RUNTIME
static int pxa2xx_spi_runtime_suspend(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);
clk_disable_unprepare(drv_data->ssp->clk);
return 0;
}
static int pxa2xx_spi_runtime_resume(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);
clk_prepare_enable(drv_data->ssp->clk);
return 0;
}
#endif
static const struct dev_pm_ops pxa2xx_spi_pm_ops = { static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
.suspend = pxa2xx_spi_suspend, SET_SYSTEM_SLEEP_PM_OPS(pxa2xx_spi_suspend, pxa2xx_spi_resume)
.resume = pxa2xx_spi_resume, SET_RUNTIME_PM_OPS(pxa2xx_spi_runtime_suspend,
pxa2xx_spi_runtime_resume, NULL)
}; };
#endif
static struct platform_driver driver = { static struct platform_driver driver = {
.driver = { .driver = {
.name = "pxa2xx-spi", .name = "pxa2xx-spi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &pxa2xx_spi_pm_ops, .pm = &pxa2xx_spi_pm_ops,
#endif .acpi_match_table = ACPI_PTR(pxa2xx_spi_acpi_match),
}, },
.probe = pxa2xx_spi_probe, .probe = pxa2xx_spi_probe,
.remove = pxa2xx_spi_remove, .remove = pxa2xx_spi_remove,
......
/*
* Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
* Copyright (C) 2013, Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef SPI_PXA2XX_H
#define SPI_PXA2XX_H
#include <linux/atomic.h>
#include <linux/dmaengine.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/pxa2xx_ssp.h>
#include <linux/scatterlist.h>
#include <linux/sizes.h>
#include <linux/spi/spi.h>
#include <linux/spi/pxa2xx_spi.h>
struct driver_data {
/* Driver model hookup */
struct platform_device *pdev;
/* SSP Info */
struct ssp_device *ssp;
/* SPI framework hookup */
enum pxa_ssp_type ssp_type;
struct spi_master *master;
/* PXA hookup */
struct pxa2xx_spi_master *master_info;
/* PXA private DMA setup stuff */
int rx_channel;
int tx_channel;
u32 *null_dma_buf;
/* SSP register addresses */
void __iomem *ioaddr;
u32 ssdr_physical;
/* SSP masks*/
u32 dma_cr1;
u32 int_cr1;
u32 clear_sr;
u32 mask_sr;
/* Maximun clock rate */
unsigned long max_clk_rate;
/* Message Transfer pump */
struct tasklet_struct pump_transfers;
/* DMA engine support */
struct dma_chan *rx_chan;
struct dma_chan *tx_chan;
struct sg_table rx_sgt;
struct sg_table tx_sgt;
int rx_nents;
int tx_nents;
void *dummy;
atomic_t dma_running;
/* Current message transfer state info */
struct spi_message *cur_msg;
struct spi_transfer *cur_transfer;
struct chip_data *cur_chip;
size_t len;
void *tx;
void *tx_end;
void *rx;
void *rx_end;
int dma_mapped;
dma_addr_t rx_dma;
dma_addr_t tx_dma;
size_t rx_map_len;
size_t tx_map_len;
u8 n_bytes;
int (*write)(struct driver_data *drv_data);
int (*read)(struct driver_data *drv_data);
irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
void (*cs_control)(u32 command);
void __iomem *lpss_base;
};
struct chip_data {
u32 cr0;
u32 cr1;
u32 psp;
u32 timeout;
u8 n_bytes;
u32 dma_burst_size;
u32 threshold;
u32 dma_threshold;
u16 lpss_rx_threshold;
u16 lpss_tx_threshold;
u8 enable_dma;
u8 bits_per_word;
u32 speed_hz;
union {
int gpio_cs;
unsigned int frm;
};
int gpio_cs_inverted;
int (*write)(struct driver_data *drv_data);
int (*read)(struct driver_data *drv_data);
void (*cs_control)(u32 command);
};
#define DEFINE_SSP_REG(reg, off) \
static inline u32 read_##reg(void const __iomem *p) \
{ return __raw_readl(p + (off)); } \
\
static inline void write_##reg(u32 v, void __iomem *p) \
{ __raw_writel(v, p + (off)); }
DEFINE_SSP_REG(SSCR0, 0x00)
DEFINE_SSP_REG(SSCR1, 0x04)
DEFINE_SSP_REG(SSSR, 0x08)
DEFINE_SSP_REG(SSITR, 0x0c)
DEFINE_SSP_REG(SSDR, 0x10)
DEFINE_SSP_REG(SSTO, 0x28)
DEFINE_SSP_REG(SSPSP, 0x2c)
DEFINE_SSP_REG(SSITF, SSITF)
DEFINE_SSP_REG(SSIRF, SSIRF)
#define START_STATE ((void *)0)
#define RUNNING_STATE ((void *)1)
#define DONE_STATE ((void *)2)
#define ERROR_STATE ((void *)-1)
#define IS_DMA_ALIGNED(x) IS_ALIGNED((unsigned long)(x), DMA_ALIGNMENT)
#define DMA_ALIGNMENT 8
static inline int pxa25x_ssp_comp(struct driver_data *drv_data)
{
if (drv_data->ssp_type == PXA25x_SSP)
return 1;
if (drv_data->ssp_type == CE4100_SSP)
return 1;
return 0;
}
static inline void write_SSSR_CS(struct driver_data *drv_data, u32 val)
{
void __iomem *reg = drv_data->ioaddr;
if (drv_data->ssp_type == CE4100_SSP)
val |= read_SSSR(reg) & SSSR_ALT_FRM_MASK;
write_SSSR(val, reg);
}
extern int pxa2xx_spi_flush(struct driver_data *drv_data);
extern void *pxa2xx_spi_next_transfer(struct driver_data *drv_data);
/*
* Select the right DMA implementation.
*/
#if defined(CONFIG_SPI_PXA2XX_PXADMA)
#define SPI_PXA2XX_USE_DMA 1
#define MAX_DMA_LEN 8191
#define DEFAULT_DMA_CR1 (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TINTE)
#elif defined(CONFIG_SPI_PXA2XX_DMA)
#define SPI_PXA2XX_USE_DMA 1
#define MAX_DMA_LEN SZ_64K
#define DEFAULT_DMA_CR1 (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TRAIL)
#else
#undef SPI_PXA2XX_USE_DMA
#define MAX_DMA_LEN 0
#define DEFAULT_DMA_CR1 0
#endif
#ifdef SPI_PXA2XX_USE_DMA
extern bool pxa2xx_spi_dma_is_possible(size_t len);
extern int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data);
extern irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data);
extern int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst);
extern void pxa2xx_spi_dma_start(struct driver_data *drv_data);
extern int pxa2xx_spi_dma_setup(struct driver_data *drv_data);
extern void pxa2xx_spi_dma_release(struct driver_data *drv_data);
extern void pxa2xx_spi_dma_resume(struct driver_data *drv_data);
extern int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
struct spi_device *spi,
u8 bits_per_word,
u32 *burst_code,
u32 *threshold);
#else
static inline bool pxa2xx_spi_dma_is_possible(size_t len) { return false; }
static inline int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data)
{
return 0;
}
#define pxa2xx_spi_dma_transfer NULL
static inline void pxa2xx_spi_dma_prepare(struct driver_data *drv_data,
u32 dma_burst) {}
static inline void pxa2xx_spi_dma_start(struct driver_data *drv_data) {}
static inline int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
{
return 0;
}
static inline void pxa2xx_spi_dma_release(struct driver_data *drv_data) {}
static inline void pxa2xx_spi_dma_resume(struct driver_data *drv_data) {}
static inline int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
struct spi_device *spi,
u8 bits_per_word,
u32 *burst_code,
u32 *threshold)
{
return -ENODEV;
}
#endif
#endif /* SPI_PXA2XX_H */
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
#define S3C64XX_SPI_CLKSEL_SRCMSK (3<<9) #define S3C64XX_SPI_CLKSEL_SRCMSK (3<<9)
#define S3C64XX_SPI_CLKSEL_SRCSHFT 9 #define S3C64XX_SPI_CLKSEL_SRCSHFT 9
#define S3C64XX_SPI_ENCLK_ENABLE (1<<8) #define S3C64XX_SPI_ENCLK_ENABLE (1<<8)
#define S3C64XX_SPI_PSR_MASK 0xff #define S3C64XX_SPI_PSR_MASK 0xff
#define S3C64XX_SPI_MODE_CH_TSZ_BYTE (0<<29) #define S3C64XX_SPI_MODE_CH_TSZ_BYTE (0<<29)
#define S3C64XX_SPI_MODE_CH_TSZ_HALFWORD (1<<29) #define S3C64XX_SPI_MODE_CH_TSZ_HALFWORD (1<<29)
...@@ -697,7 +697,7 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, ...@@ -697,7 +697,7 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
INIT_COMPLETION(sdd->xfer_completion); INIT_COMPLETION(sdd->xfer_completion);
/* Only BPW and Speed may change across transfers */ /* Only BPW and Speed may change across transfers */
bpw = xfer->bits_per_word ? : spi->bits_per_word; bpw = xfer->bits_per_word;
speed = xfer->speed_hz ? : spi->max_speed_hz; speed = xfer->speed_hz ? : spi->max_speed_hz;
if (xfer->len % (bpw / 8)) { if (xfer->len % (bpw / 8)) {
...@@ -743,8 +743,7 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, ...@@ -743,8 +743,7 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
sdd->regs + S3C64XX_SPI_SLAVE_SEL); sdd->regs + S3C64XX_SPI_SLAVE_SEL);
if (status) { if (status) {
dev_err(&spi->dev, "I/O Error: " dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n",
"rx-%d tx-%d res:rx-%c tx-%c len-%d\n",
xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0, xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0,
(sdd->state & RXBUSY) ? 'f' : 'p', (sdd->state & RXBUSY) ? 'f' : 'p',
(sdd->state & TXBUSY) ? 'f' : 'p', (sdd->state & TXBUSY) ? 'f' : 'p',
...@@ -799,7 +798,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) ...@@ -799,7 +798,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi)
/* Acquire DMA channels */ /* Acquire DMA channels */
while (!acquire_dma(sdd)) while (!acquire_dma(sdd))
msleep(10); usleep_range(10000, 11000);
pm_runtime_get_sync(&sdd->pdev->dev); pm_runtime_get_sync(&sdd->pdev->dev);
...@@ -841,16 +840,14 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( ...@@ -841,16 +840,14 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
cs = kzalloc(sizeof(*cs), GFP_KERNEL); cs = kzalloc(sizeof(*cs), GFP_KERNEL);
if (!cs) { if (!cs) {
dev_err(&spi->dev, "could not allocate memory for controller" dev_err(&spi->dev, "could not allocate memory for controller data\n");
" data\n");
of_node_put(data_np); of_node_put(data_np);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
cs->line = of_get_named_gpio(data_np, "cs-gpio", 0); cs->line = of_get_named_gpio(data_np, "cs-gpio", 0);
if (!gpio_is_valid(cs->line)) { if (!gpio_is_valid(cs->line)) {
dev_err(&spi->dev, "chip select gpio is not specified or " dev_err(&spi->dev, "chip select gpio is not specified or invalid\n");
"invalid\n");
kfree(cs); kfree(cs);
of_node_put(data_np); of_node_put(data_np);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
...@@ -957,6 +954,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi) ...@@ -957,6 +954,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
if (spi->max_speed_hz >= speed) { if (spi->max_speed_hz >= speed) {
spi->max_speed_hz = speed; spi->max_speed_hz = speed;
} else { } else {
dev_err(&spi->dev, "Can't set %dHz transfer speed\n",
spi->max_speed_hz);
err = -EINVAL; err = -EINVAL;
goto setup_exit; goto setup_exit;
} }
...@@ -1076,8 +1075,8 @@ static int s3c64xx_spi_get_dmares( ...@@ -1076,8 +1075,8 @@ static int s3c64xx_spi_get_dmares(
if (!sdd->pdev->dev.of_node) { if (!sdd->pdev->dev.of_node) {
res = platform_get_resource(pdev, IORESOURCE_DMA, tx ? 0 : 1); res = platform_get_resource(pdev, IORESOURCE_DMA, tx ? 0 : 1);
if (!res) { if (!res) {
dev_err(&pdev->dev, "Unable to get SPI-%s dma " dev_err(&pdev->dev, "Unable to get SPI-%s dma resource\n",
"resource\n", chan_str); chan_str);
return -ENXIO; return -ENXIO;
} }
dma_data->dmach = res->start; dma_data->dmach = res->start;
...@@ -1133,8 +1132,7 @@ static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd) ...@@ -1133,8 +1132,7 @@ static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd)
gpio_free(sdd->gpios[idx]); gpio_free(sdd->gpios[idx]);
} }
static struct s3c64xx_spi_info * s3c64xx_spi_parse_dt( static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
struct device *dev)
{ {
struct s3c64xx_spi_info *sci; struct s3c64xx_spi_info *sci;
u32 temp; u32 temp;
...@@ -1146,16 +1144,14 @@ static struct s3c64xx_spi_info * s3c64xx_spi_parse_dt( ...@@ -1146,16 +1144,14 @@ static struct s3c64xx_spi_info * s3c64xx_spi_parse_dt(
} }
if (of_property_read_u32(dev->of_node, "samsung,spi-src-clk", &temp)) { if (of_property_read_u32(dev->of_node, "samsung,spi-src-clk", &temp)) {
dev_warn(dev, "spi bus clock parent not specified, using " dev_warn(dev, "spi bus clock parent not specified, using clock at index 0 as parent\n");
"clock at index 0 as parent\n");
sci->src_clk_nr = 0; sci->src_clk_nr = 0;
} else { } else {
sci->src_clk_nr = temp; sci->src_clk_nr = temp;
} }
if (of_property_read_u32(dev->of_node, "num-cs", &temp)) { if (of_property_read_u32(dev->of_node, "num-cs", &temp)) {
dev_warn(dev, "number of chip select lines not specified, " dev_warn(dev, "number of chip select lines not specified, assuming 1 chip select line\n");
"assuming 1 chip select line\n");
sci->num_cs = 1; sci->num_cs = 1;
} else { } else {
sci->num_cs = temp; sci->num_cs = temp;
...@@ -1195,7 +1191,7 @@ static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( ...@@ -1195,7 +1191,7 @@ static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config(
platform_get_device_id(pdev)->driver_data; platform_get_device_id(pdev)->driver_data;
} }
static int __init s3c64xx_spi_probe(struct platform_device *pdev) static int s3c64xx_spi_probe(struct platform_device *pdev)
{ {
struct resource *mem_res; struct resource *mem_res;
struct s3c64xx_spi_driver_data *sdd; struct s3c64xx_spi_driver_data *sdd;
...@@ -1245,8 +1241,8 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1245,8 +1241,8 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
ret = of_alias_get_id(pdev->dev.of_node, "spi"); ret = of_alias_get_id(pdev->dev.of_node, "spi");
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to get alias id, " dev_err(&pdev->dev, "failed to get alias id, errno %d\n",
"errno %d\n", ret); ret);
goto err0; goto err0;
} }
sdd->port_id = ret; sdd->port_id = ret;
...@@ -1280,7 +1276,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1280,7 +1276,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
if (sdd->regs == NULL) { if (sdd->regs == NULL) {
dev_err(&pdev->dev, "Unable to remap IO\n"); dev_err(&pdev->dev, "Unable to remap IO\n");
ret = -ENXIO; ret = -ENXIO;
goto err1; goto err0;
} }
if (!sci->cfg_gpio && pdev->dev.of_node) { if (!sci->cfg_gpio && pdev->dev.of_node) {
...@@ -1289,36 +1285,36 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1289,36 +1285,36 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
} else if (sci->cfg_gpio == NULL || sci->cfg_gpio()) { } else if (sci->cfg_gpio == NULL || sci->cfg_gpio()) {
dev_err(&pdev->dev, "Unable to config gpio\n"); dev_err(&pdev->dev, "Unable to config gpio\n");
ret = -EBUSY; ret = -EBUSY;
goto err2; goto err0;
} }
/* Setup clocks */ /* Setup clocks */
sdd->clk = clk_get(&pdev->dev, "spi"); sdd->clk = devm_clk_get(&pdev->dev, "spi");
if (IS_ERR(sdd->clk)) { if (IS_ERR(sdd->clk)) {
dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n"); dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
ret = PTR_ERR(sdd->clk); ret = PTR_ERR(sdd->clk);
goto err3; goto err1;
} }
if (clk_prepare_enable(sdd->clk)) { if (clk_prepare_enable(sdd->clk)) {
dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n"); dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
ret = -EBUSY; ret = -EBUSY;
goto err4; goto err1;
} }
sprintf(clk_name, "spi_busclk%d", sci->src_clk_nr); sprintf(clk_name, "spi_busclk%d", sci->src_clk_nr);
sdd->src_clk = clk_get(&pdev->dev, clk_name); sdd->src_clk = devm_clk_get(&pdev->dev, clk_name);
if (IS_ERR(sdd->src_clk)) { if (IS_ERR(sdd->src_clk)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Unable to acquire clock '%s'\n", clk_name); "Unable to acquire clock '%s'\n", clk_name);
ret = PTR_ERR(sdd->src_clk); ret = PTR_ERR(sdd->src_clk);
goto err5; goto err2;
} }
if (clk_prepare_enable(sdd->src_clk)) { if (clk_prepare_enable(sdd->src_clk)) {
dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name); dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name);
ret = -EBUSY; ret = -EBUSY;
goto err6; goto err2;
} }
/* Setup Deufult Mode */ /* Setup Deufult Mode */
...@@ -1328,11 +1324,12 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1328,11 +1324,12 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
init_completion(&sdd->xfer_completion); init_completion(&sdd->xfer_completion);
INIT_LIST_HEAD(&sdd->queue); INIT_LIST_HEAD(&sdd->queue);
ret = request_irq(irq, s3c64xx_spi_irq, 0, "spi-s3c64xx", sdd); ret = devm_request_irq(&pdev->dev, irq, s3c64xx_spi_irq, 0,
"spi-s3c64xx", sdd);
if (ret != 0) { if (ret != 0) {
dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n", dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n",
irq, ret); irq, ret);
goto err7; goto err3;
} }
writel(S3C64XX_SPI_INT_RX_OVERRUN_EN | S3C64XX_SPI_INT_RX_UNDERRUN_EN | writel(S3C64XX_SPI_INT_RX_OVERRUN_EN | S3C64XX_SPI_INT_RX_UNDERRUN_EN |
...@@ -1342,11 +1339,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1342,11 +1339,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
if (spi_register_master(master)) { if (spi_register_master(master)) {
dev_err(&pdev->dev, "cannot register SPI master\n"); dev_err(&pdev->dev, "cannot register SPI master\n");
ret = -EBUSY; ret = -EBUSY;
goto err8; goto err3;
} }
dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d " dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n",
"with %d Slaves attached\n",
sdd->port_id, master->num_chipselect); sdd->port_id, master->num_chipselect);
dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n", dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
mem_res->end, mem_res->start, mem_res->end, mem_res->start,
...@@ -1356,21 +1352,13 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1356,21 +1352,13 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
return 0; return 0;
err8: err3:
free_irq(irq, sdd);
err7:
clk_disable_unprepare(sdd->src_clk); clk_disable_unprepare(sdd->src_clk);
err6: err2:
clk_put(sdd->src_clk);
err5:
clk_disable_unprepare(sdd->clk); clk_disable_unprepare(sdd->clk);
err4: err1:
clk_put(sdd->clk);
err3:
if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node) if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node)
s3c64xx_spi_dt_gpio_free(sdd); s3c64xx_spi_dt_gpio_free(sdd);
err2:
err1:
err0: err0:
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
spi_master_put(master); spi_master_put(master);
...@@ -1389,13 +1377,9 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) ...@@ -1389,13 +1377,9 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
writel(0, sdd->regs + S3C64XX_SPI_INT_EN); writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
free_irq(platform_get_irq(pdev, 0), sdd);
clk_disable_unprepare(sdd->src_clk); clk_disable_unprepare(sdd->src_clk);
clk_put(sdd->src_clk);
clk_disable_unprepare(sdd->clk); clk_disable_unprepare(sdd->clk);
clk_put(sdd->clk);
if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node) if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node)
s3c64xx_spi_dt_gpio_free(sdd); s3c64xx_spi_dt_gpio_free(sdd);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
...@@ -592,6 +593,37 @@ static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs, ...@@ -592,6 +593,37 @@ static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs,
return 0; return 0;
} }
#ifdef CONFIG_OF
static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
{
struct sh_msiof_spi_info *info;
struct device_node *np = dev->of_node;
u32 num_cs = 0;
info = devm_kzalloc(dev, sizeof(struct sh_msiof_spi_info), GFP_KERNEL);
if (!info) {
dev_err(dev, "failed to allocate setup data\n");
return NULL;
}
/* Parse the MSIOF properties */
of_property_read_u32(np, "num-cs", &num_cs);
of_property_read_u32(np, "renesas,tx-fifo-size",
&info->tx_fifo_override);
of_property_read_u32(np, "renesas,rx-fifo-size",
&info->rx_fifo_override);
info->num_chipselect = num_cs;
return info;
}
#else
static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
{
return NULL;
}
#endif
static int sh_msiof_spi_probe(struct platform_device *pdev) static int sh_msiof_spi_probe(struct platform_device *pdev)
{ {
struct resource *r; struct resource *r;
...@@ -610,7 +642,17 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) ...@@ -610,7 +642,17 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
p = spi_master_get_devdata(master); p = spi_master_get_devdata(master);
platform_set_drvdata(pdev, p); platform_set_drvdata(pdev, p);
p->info = pdev->dev.platform_data; if (pdev->dev.of_node)
p->info = sh_msiof_spi_parse_dt(&pdev->dev);
else
p->info = pdev->dev.platform_data;
if (!p->info) {
dev_err(&pdev->dev, "failed to obtain device info\n");
ret = -ENXIO;
goto err1;
}
init_completion(&p->done); init_completion(&p->done);
p->clk = clk_get(&pdev->dev, NULL); p->clk = clk_get(&pdev->dev, NULL);
...@@ -715,6 +757,17 @@ static int sh_msiof_spi_runtime_nop(struct device *dev) ...@@ -715,6 +757,17 @@ static int sh_msiof_spi_runtime_nop(struct device *dev)
return 0; return 0;
} }
#ifdef CONFIG_OF
static const struct of_device_id sh_msiof_match[] = {
{ .compatible = "renesas,sh-msiof", },
{ .compatible = "renesas,sh-mobile-msiof", },
{},
};
MODULE_DEVICE_TABLE(of, sh_msiof_match);
#else
#define sh_msiof_match NULL
#endif
static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = { static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = {
.runtime_suspend = sh_msiof_spi_runtime_nop, .runtime_suspend = sh_msiof_spi_runtime_nop,
.runtime_resume = sh_msiof_spi_runtime_nop, .runtime_resume = sh_msiof_spi_runtime_nop,
...@@ -727,6 +780,7 @@ static struct platform_driver sh_msiof_spi_drv = { ...@@ -727,6 +780,7 @@ static struct platform_driver sh_msiof_spi_drv = {
.name = "spi_sh_msiof", .name = "spi_sh_msiof",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &sh_msiof_spi_dev_pm_ops, .pm = &sh_msiof_spi_dev_pm_ops,
.of_match_table = sh_msiof_match,
}, },
}; };
module_platform_driver(sh_msiof_spi_drv); module_platform_driver(sh_msiof_spi_drv);
......
...@@ -382,8 +382,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ...@@ -382,8 +382,7 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
sspi = spi_master_get_devdata(spi->master); sspi = spi_master_get_devdata(spi->master);
bits_per_word = t && t->bits_per_word ? t->bits_per_word : bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
spi->bits_per_word;
hz = t && t->speed_hz ? t->speed_hz : spi->max_speed_hz; hz = t && t->speed_hz ? t->speed_hz : spi->max_speed_hz;
/* Enable IO mode for RX, TX */ /* Enable IO mode for RX, TX */
...@@ -570,7 +569,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -570,7 +569,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
ret = -EINVAL; ret = -EINVAL;
goto free_pin; goto free_pin;
} }
clk_enable(sspi->clk); clk_prepare_enable(sspi->clk);
sspi->ctrl_freq = clk_get_rate(sspi->clk); sspi->ctrl_freq = clk_get_rate(sspi->clk);
init_completion(&sspi->done); init_completion(&sspi->done);
...@@ -594,7 +593,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -594,7 +593,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
return 0; return 0;
free_clk: free_clk:
clk_disable(sspi->clk); clk_disable_unprepare(sspi->clk);
clk_put(sspi->clk); clk_put(sspi->clk);
free_pin: free_pin:
pinctrl_put(sspi->p); pinctrl_put(sspi->p);
...@@ -618,7 +617,7 @@ static int spi_sirfsoc_remove(struct platform_device *pdev) ...@@ -618,7 +617,7 @@ static int spi_sirfsoc_remove(struct platform_device *pdev)
if (sspi->chipselect[i] > 0) if (sspi->chipselect[i] > 0)
gpio_free(sspi->chipselect[i]); gpio_free(sspi->chipselect[i]);
} }
clk_disable(sspi->clk); clk_disable_unprepare(sspi->clk);
clk_put(sspi->clk); clk_put(sspi->clk);
pinctrl_put(sspi->p); pinctrl_put(sspi->p);
spi_master_put(master); spi_master_put(master);
...@@ -659,6 +658,7 @@ static const struct dev_pm_ops spi_sirfsoc_pm_ops = { ...@@ -659,6 +658,7 @@ static const struct dev_pm_ops spi_sirfsoc_pm_ops = {
static const struct of_device_id spi_sirfsoc_of_match[] = { static const struct of_device_id spi_sirfsoc_of_match[] = {
{ .compatible = "sirf,prima2-spi", }, { .compatible = "sirf,prima2-spi", },
{ .compatible = "sirf,marco-spi", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, sirfsoc_spi_of_match); MODULE_DEVICE_TABLE(of, sirfsoc_spi_of_match);
......
...@@ -269,9 +269,7 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi, ...@@ -269,9 +269,7 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi,
u32 speed; u32 speed;
unsigned long command; unsigned long command;
speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz; speed = t->speed_hz;
if (!speed)
speed = tsd->spi_max_frequency;
if (speed != tsd->cur_speed) { if (speed != tsd->cur_speed) {
clk_set_rate(tsd->clk, speed); clk_set_rate(tsd->clk, speed);
tsd->cur_speed = speed; tsd->cur_speed = speed;
...@@ -319,6 +317,15 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi, ...@@ -319,6 +317,15 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi,
return tegra_sflash_start_cpu_based_transfer(tsd, t); return tegra_sflash_start_cpu_based_transfer(tsd, t);
} }
static int tegra_sflash_setup(struct spi_device *spi)
{
struct tegra_sflash_data *tsd = spi_master_get_devdata(spi->master);
/* Set speed to the spi max fequency if spi device has not set */
spi->max_speed_hz = spi->max_speed_hz ? : tsd->spi_max_frequency;
return 0;
}
static int tegra_sflash_transfer_one_message(struct spi_master *master, static int tegra_sflash_transfer_one_message(struct spi_master *master,
struct spi_message *msg) struct spi_message *msg)
{ {
...@@ -492,6 +499,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) ...@@ -492,6 +499,7 @@ static int tegra_sflash_probe(struct platform_device *pdev)
/* the spi->mode bits understood by this driver: */ /* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA; master->mode_bits = SPI_CPOL | SPI_CPHA;
master->setup = tegra_sflash_setup;
master->transfer_one_message = tegra_sflash_transfer_one_message; master->transfer_one_message = tegra_sflash_transfer_one_message;
master->num_chipselect = MAX_CHIP_SELECT; master->num_chipselect = MAX_CHIP_SELECT;
master->bus_num = -1; master->bus_num = -1;
......
...@@ -284,8 +284,7 @@ static unsigned tegra_slink_calculate_curr_xfer_param( ...@@ -284,8 +284,7 @@ static unsigned tegra_slink_calculate_curr_xfer_param(
unsigned max_len; unsigned max_len;
unsigned total_fifo_words; unsigned total_fifo_words;
bits_per_word = t->bits_per_word ? t->bits_per_word : bits_per_word = t->bits_per_word;
spi->bits_per_word;
tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1; tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1;
if (bits_per_word == 8 || bits_per_word == 16) { if (bits_per_word == 8 || bits_per_word == 16) {
...@@ -378,8 +377,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf( ...@@ -378,8 +377,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
} else { } else {
unsigned int bits_per_word; unsigned int bits_per_word;
bits_per_word = t->bits_per_word ? t->bits_per_word : bits_per_word = t->bits_per_word;
tspi->cur_spi->bits_per_word;
for (count = 0; count < rx_full_count; count++) { for (count = 0; count < rx_full_count; count++) {
x = tegra_slink_readl(tspi, SLINK_RX_FIFO); x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
for (i = 0; (i < tspi->bytes_per_word); i++) for (i = 0; (i < tspi->bytes_per_word); i++)
...@@ -444,8 +442,7 @@ static void tegra_slink_copy_spi_rxbuf_to_client_rxbuf( ...@@ -444,8 +442,7 @@ static void tegra_slink_copy_spi_rxbuf_to_client_rxbuf(
unsigned int x; unsigned int x;
unsigned int rx_mask, bits_per_word; unsigned int rx_mask, bits_per_word;
bits_per_word = t->bits_per_word ? t->bits_per_word : bits_per_word = t->bits_per_word;
tspi->cur_spi->bits_per_word;
rx_mask = (1 << bits_per_word) - 1; rx_mask = (1 << bits_per_word) - 1;
for (count = 0; count < tspi->curr_dma_words; count++) { for (count = 0; count < tspi->curr_dma_words; count++) {
x = tspi->rx_dma_buf[count]; x = tspi->rx_dma_buf[count];
...@@ -728,9 +725,7 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, ...@@ -728,9 +725,7 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
unsigned long command2; unsigned long command2;
bits_per_word = t->bits_per_word; bits_per_word = t->bits_per_word;
speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz; speed = t->speed_hz;
if (!speed)
speed = tspi->spi_max_frequency;
if (speed != tspi->cur_speed) { if (speed != tspi->cur_speed) {
clk_set_rate(tspi->clk, speed * 4); clk_set_rate(tspi->clk, speed * 4);
tspi->cur_speed = speed; tspi->cur_speed = speed;
...@@ -841,6 +836,8 @@ static int tegra_slink_setup(struct spi_device *spi) ...@@ -841,6 +836,8 @@ static int tegra_slink_setup(struct spi_device *spi)
BUG_ON(spi->chip_select >= MAX_CHIP_SELECT); BUG_ON(spi->chip_select >= MAX_CHIP_SELECT);
/* Set speed to the spi max fequency if spi device has not set */
spi->max_speed_hz = spi->max_speed_hz ? : tspi->spi_max_frequency;
ret = pm_runtime_get_sync(tspi->dev); ret = pm_runtime_get_sync(tspi->dev);
if (ret < 0) { if (ret < 0) {
dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret); dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret);
......
...@@ -189,9 +189,8 @@ static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m) ...@@ -189,9 +189,8 @@ static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m)
unsigned int len = t->len; unsigned int len = t->len;
unsigned int wsize; unsigned int wsize;
u32 speed_hz = t->speed_hz ? : spi->max_speed_hz; u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word; u8 bits_per_word = t->bits_per_word;
bits_per_word = bits_per_word ? : 8;
wsize = bits_per_word >> 3; /* in bytes */ wsize = bits_per_word >> 3; /* in bytes */
if (prev_speed_hz != speed_hz if (prev_speed_hz != speed_hz
...@@ -316,9 +315,8 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m) ...@@ -316,9 +315,8 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
/* check each transfer's parameters */ /* check each transfer's parameters */
list_for_each_entry (t, &m->transfers, transfer_list) { list_for_each_entry (t, &m->transfers, transfer_list) {
u32 speed_hz = t->speed_hz ? : spi->max_speed_hz; u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word; u8 bits_per_word = t->bits_per_word;
bits_per_word = bits_per_word ? : 8;
if (!t->tx_buf && !t->rx_buf && t->len) if (!t->tx_buf && !t->rx_buf && t->len)
return -EINVAL; return -EINVAL;
if (bits_per_word != 8 && bits_per_word != 16) if (bits_per_word != 8 && bits_per_word != 16)
...@@ -337,7 +335,7 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m) ...@@ -337,7 +335,7 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
return 0; return 0;
} }
static int __init txx9spi_probe(struct platform_device *dev) static int txx9spi_probe(struct platform_device *dev)
{ {
struct spi_master *master; struct spi_master *master;
struct txx9spi *c; struct txx9spi *c;
...@@ -432,7 +430,7 @@ static int __init txx9spi_probe(struct platform_device *dev) ...@@ -432,7 +430,7 @@ static int __init txx9spi_probe(struct platform_device *dev)
return ret; return ret;
} }
static int __exit txx9spi_remove(struct platform_device *dev) static int txx9spi_remove(struct platform_device *dev)
{ {
struct spi_master *master = spi_master_get(platform_get_drvdata(dev)); struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
struct txx9spi *c = spi_master_get_devdata(master); struct txx9spi *c = spi_master_get_devdata(master);
...@@ -450,7 +448,7 @@ static int __exit txx9spi_remove(struct platform_device *dev) ...@@ -450,7 +448,7 @@ static int __exit txx9spi_remove(struct platform_device *dev)
MODULE_ALIAS("platform:spi_txx9"); MODULE_ALIAS("platform:spi_txx9");
static struct platform_driver txx9spi_driver = { static struct platform_driver txx9spi_driver = {
.remove = __exit_p(txx9spi_remove), .remove = txx9spi_remove,
.driver = { .driver = {
.name = "spi_txx9", .name = "spi_txx9",
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -1080,7 +1080,8 @@ static int of_spi_register_master(struct spi_master *master) ...@@ -1080,7 +1080,8 @@ static int of_spi_register_master(struct spi_master *master)
if (!master->cs_gpios) if (!master->cs_gpios)
return -ENOMEM; return -ENOMEM;
memset(cs, -EINVAL, master->num_chipselect); for (i = 0; i < master->num_chipselect; i++)
cs[i] = -EINVAL;
for (i = 0; i < nb; i++) for (i = 0; i < nb; i++)
cs[i] = of_get_named_gpio(np, "cs-gpios", i); cs[i] = of_get_named_gpio(np, "cs-gpios", i);
...@@ -1135,6 +1136,9 @@ int spi_register_master(struct spi_master *master) ...@@ -1135,6 +1136,9 @@ int spi_register_master(struct spi_master *master)
if (master->num_chipselect == 0) if (master->num_chipselect == 0)
return -EINVAL; return -EINVAL;
if ((master->bus_num < 0) && master->dev.of_node)
master->bus_num = of_alias_get_id(master->dev.of_node, "spi");
/* convention: dynamically assigned bus IDs count down from the max */ /* convention: dynamically assigned bus IDs count down from the max */
if (master->bus_num < 0) { if (master->bus_num < 0) {
/* FIXME switch to an IDR based scheme, something like /* FIXME switch to an IDR based scheme, something like
...@@ -1366,12 +1370,14 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) ...@@ -1366,12 +1370,14 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
} }
/** /**
* Set transfer bits_per_word as spi device default if it is not * Set transfer bits_per_word and max speed as spi device default if
* set for this transfer. * it is not set for this transfer.
*/ */
list_for_each_entry(xfer, &message->transfers, transfer_list) { list_for_each_entry(xfer, &message->transfers, transfer_list) {
if (!xfer->bits_per_word) if (!xfer->bits_per_word)
xfer->bits_per_word = spi->bits_per_word; xfer->bits_per_word = spi->bits_per_word;
if (!xfer->speed_hz)
xfer->speed_hz = spi->max_speed_hz;
} }
message->spi = spi; message->spi = spi;
...@@ -1656,7 +1662,8 @@ int spi_write_then_read(struct spi_device *spi, ...@@ -1656,7 +1662,8 @@ int spi_write_then_read(struct spi_device *spi,
* using the pre-allocated buffer or the transfer is too large. * using the pre-allocated buffer or the transfer is too large.
*/ */
if ((n_tx + n_rx) > SPI_BUFSIZ || !mutex_trylock(&lock)) { if ((n_tx + n_rx) > SPI_BUFSIZ || !mutex_trylock(&lock)) {
local_buf = kmalloc(max((unsigned)SPI_BUFSIZ, n_tx + n_rx), GFP_KERNEL); local_buf = kmalloc(max((unsigned)SPI_BUFSIZ, n_tx + n_rx),
GFP_KERNEL | GFP_DMA);
if (!local_buf) if (!local_buf)
return -ENOMEM; return -ENOMEM;
} else { } else {
......
...@@ -22,6 +22,9 @@ struct omap2_mcspi_dev_attr { ...@@ -22,6 +22,9 @@ struct omap2_mcspi_dev_attr {
struct omap2_mcspi_device_config { struct omap2_mcspi_device_config {
unsigned turbo_mode:1; unsigned turbo_mode:1;
/* toggle chip select after every word */
unsigned cs_per_word:1;
}; };
#endif #endif
...@@ -155,6 +155,14 @@ ...@@ -155,6 +155,14 @@
#define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */ #define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */
#define SSACD_SCDX8 (1 << 7) /* SYSCLK division ratio select */ #define SSACD_SCDX8 (1 << 7) /* SYSCLK division ratio select */
/* LPSS SSP */
#define SSITF 0x44 /* TX FIFO trigger level */
#define SSITF_TxLoThresh(x) (((x) - 1) << 8)
#define SSITF_TxHiThresh(x) ((x) - 1)
#define SSIRF 0x48 /* RX FIFO trigger level */
#define SSIRF_RxThresh(x) ((x) - 1)
enum pxa_ssp_type { enum pxa_ssp_type {
SSP_UNDEFINED = 0, SSP_UNDEFINED = 0,
PXA25x_SSP, /* pxa 210, 250, 255, 26x */ PXA25x_SSP, /* pxa 210, 250, 255, 26x */
...@@ -164,6 +172,7 @@ enum pxa_ssp_type { ...@@ -164,6 +172,7 @@ enum pxa_ssp_type {
PXA168_SSP, PXA168_SSP,
PXA910_SSP, PXA910_SSP,
CE4100_SSP, CE4100_SSP,
LPSS_SSP,
}; };
struct ssp_device { struct ssp_device {
...@@ -206,6 +215,15 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg) ...@@ -206,6 +215,15 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg)
return __raw_readl(dev->mmio_base + reg); return __raw_readl(dev->mmio_base + reg);
} }
#ifdef CONFIG_ARCH_PXA
struct ssp_device *pxa_ssp_request(int port, const char *label); struct ssp_device *pxa_ssp_request(int port, const char *label);
void pxa_ssp_free(struct ssp_device *); void pxa_ssp_free(struct ssp_device *);
#else
static inline struct ssp_device *pxa_ssp_request(int port, const char *label)
{
return NULL;
}
static inline void pxa_ssp_free(struct ssp_device *ssp) {}
#endif
#endif #endif
...@@ -28,6 +28,15 @@ struct pxa2xx_spi_master { ...@@ -28,6 +28,15 @@ struct pxa2xx_spi_master {
u32 clock_enable; u32 clock_enable;
u16 num_chipselect; u16 num_chipselect;
u8 enable_dma; u8 enable_dma;
/* DMA engine specific config */
int rx_chan_id;
int tx_chan_id;
int rx_slave_id;
int tx_slave_id;
/* For non-PXA arches */
struct ssp_device ssp;
}; };
/* spi_board_info.controller_data for SPI slave devices, /* spi_board_info.controller_data for SPI slave devices,
...@@ -35,6 +44,7 @@ struct pxa2xx_spi_master { ...@@ -35,6 +44,7 @@ struct pxa2xx_spi_master {
*/ */
struct pxa2xx_spi_chip { struct pxa2xx_spi_chip {
u8 tx_threshold; u8 tx_threshold;
u8 tx_hi_threshold;
u8 rx_threshold; u8 rx_threshold;
u8 dma_burst_size; u8 dma_burst_size;
u32 timeout; u32 timeout;
...@@ -50,103 +60,5 @@ struct pxa2xx_spi_chip { ...@@ -50,103 +60,5 @@ struct pxa2xx_spi_chip {
extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info); extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info);
#else
/*
* This is the implemtation for CE4100 on x86. ARM defines them in mach/ or
* plat/ include path.
* The CE4100 does not provide DMA support. This bits are here to let the driver
* compile and will never be used. Maybe we get DMA support at a later point in
* time.
*/
#define DCSR(n) (n)
#define DSADR(n) (n)
#define DTADR(n) (n)
#define DCMD(n) (n)
#define DRCMR(n) (n)
#define DCSR_RUN (1 << 31) /* Run Bit */
#define DCSR_NODESC (1 << 30) /* No-Descriptor Fetch */
#define DCSR_STOPIRQEN (1 << 29) /* Stop Interrupt Enable */
#define DCSR_REQPEND (1 << 8) /* Request Pending (read-only) */
#define DCSR_STOPSTATE (1 << 3) /* Stop State (read-only) */
#define DCSR_ENDINTR (1 << 2) /* End Interrupt */
#define DCSR_STARTINTR (1 << 1) /* Start Interrupt */
#define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt */
#define DCSR_EORIRQEN (1 << 28) /* End of Receive Interrupt Enable */
#define DCSR_EORJMPEN (1 << 27) /* Jump to next descriptor on EOR */
#define DCSR_EORSTOPEN (1 << 26) /* STOP on an EOR */
#define DCSR_SETCMPST (1 << 25) /* Set Descriptor Compare Status */
#define DCSR_CLRCMPST (1 << 24) /* Clear Descriptor Compare Status */
#define DCSR_CMPST (1 << 10) /* The Descriptor Compare Status */
#define DCSR_EORINTR (1 << 9) /* The end of Receive */
#define DRCMR_MAPVLD (1 << 7) /* Map Valid */
#define DRCMR_CHLNUM 0x1f /* mask for Channel Number */
#define DDADR_DESCADDR 0xfffffff0 /* Address of next descriptor */
#define DDADR_STOP (1 << 0) /* Stop */
#define DCMD_INCSRCADDR (1 << 31) /* Source Address Increment Setting. */
#define DCMD_INCTRGADDR (1 << 30) /* Target Address Increment Setting. */
#define DCMD_FLOWSRC (1 << 29) /* Flow Control by the source. */
#define DCMD_FLOWTRG (1 << 28) /* Flow Control by the target. */
#define DCMD_STARTIRQEN (1 << 22) /* Start Interrupt Enable */
#define DCMD_ENDIRQEN (1 << 21) /* End Interrupt Enable */
#define DCMD_ENDIAN (1 << 18) /* Device Endian-ness. */
#define DCMD_BURST8 (1 << 16) /* 8 byte burst */
#define DCMD_BURST16 (2 << 16) /* 16 byte burst */
#define DCMD_BURST32 (3 << 16) /* 32 byte burst */
#define DCMD_WIDTH1 (1 << 14) /* 1 byte width */
#define DCMD_WIDTH2 (2 << 14) /* 2 byte width (HalfWord) */
#define DCMD_WIDTH4 (3 << 14) /* 4 byte width (Word) */
#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */
/*
* Descriptor structure for PXA's DMA engine
* Note: this structure must always be aligned to a 16-byte boundary.
*/
typedef enum {
DMA_PRIO_HIGH = 0,
DMA_PRIO_MEDIUM = 1,
DMA_PRIO_LOW = 2
} pxa_dma_prio;
/*
* DMA registration
*/
static inline int pxa_request_dma(char *name,
pxa_dma_prio prio,
void (*irq_handler)(int, void *),
void *data)
{
return -ENODEV;
}
static inline void pxa_free_dma(int dma_ch)
{
}
/*
* The CE4100 does not have the clk framework implemented and SPI clock can
* not be switched on/off or the divider changed.
*/
static inline void clk_disable(struct clk *clk)
{
}
static inline int clk_enable(struct clk *clk)
{
return 0;
}
static inline unsigned long clk_get_rate(struct clk *clk)
{
return 3686400;
}
#endif #endif
#endif #endif
...@@ -57,6 +57,8 @@ extern struct bus_type spi_bus_type; ...@@ -57,6 +57,8 @@ extern struct bus_type spi_bus_type;
* @modalias: Name of the driver to use with this device, or an alias * @modalias: Name of the driver to use with this device, or an alias
* for that name. This appears in the sysfs "modalias" attribute * for that name. This appears in the sysfs "modalias" attribute
* for driver coldplugging, and in uevents used for hotplugging * for driver coldplugging, and in uevents used for hotplugging
* @cs_gpio: gpio number of the chipselect line (optional, -EINVAL when
* when not using a GPIO line)
* *
* A @spi_device is used to interchange data between an SPI slave * A @spi_device is used to interchange data between an SPI slave
* (usually a discrete chip) and CPU memory. * (usually a discrete chip) and CPU memory.
...@@ -258,6 +260,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) ...@@ -258,6 +260,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* @unprepare_transfer_hardware: there are currently no more messages on the * @unprepare_transfer_hardware: there are currently no more messages on the
* queue so the subsystem notifies the driver that it may relax the * queue so the subsystem notifies the driver that it may relax the
* hardware by issuing this call * hardware by issuing this call
* @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
* number. Any individual value may be -EINVAL for CS lines that
* are not GPIOs (driven by the SPI controller itself).
* *
* Each SPI master controller can communicate with one or more @spi_device * Each SPI master controller can communicate with one or more @spi_device
* children. These make a small bus, sharing MOSI, MISO and SCK signals * children. These make a small bus, sharing MOSI, MISO and SCK signals
......
...@@ -62,8 +62,8 @@ ...@@ -62,8 +62,8 @@
*/ */
struct spi_gpio_platform_data { struct spi_gpio_platform_data {
unsigned sck; unsigned sck;
unsigned mosi; unsigned long mosi;
unsigned miso; unsigned long miso;
u16 num_chipselect; u16 num_chipselect;
}; };
......
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