Commit 7020d769 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/davinci', 'spi/topic/doc',...

Merge remote-tracking branches 'spi/topic/davinci', 'spi/topic/doc', 'spi/topic/dw' and 'spi/topic/fsl' into spi-next
Davinci SPI controller device bindings Davinci SPI controller device bindings
Links on DM:
Keystone 2 - http://www.ti.com/lit/ug/sprugp2a/sprugp2a.pdf
dm644x - http://www.ti.com/lit/ug/sprue32a/sprue32a.pdf
OMAP-L138/da830 - http://www.ti.com/lit/ug/spruh77a/spruh77a.pdf
Required properties: Required properties:
- #address-cells: number of cells required to define a chip select - #address-cells: number of cells required to define a chip select
address on the SPI bus. Should be set to 1. address on the SPI bus. Should be set to 1.
...@@ -24,6 +29,30 @@ Optional: ...@@ -24,6 +29,30 @@ Optional:
cs-gpios = <0>, <0>, <0>, <&gpio1 30 0>, <&gpio1 31 0>; cs-gpios = <0>, <0>, <0>, <&gpio1 30 0>, <&gpio1 31 0>;
where first three are internal CS and last two are GPIO CS. where first three are internal CS and last two are GPIO CS.
Optional properties for slave devices:
SPI slave nodes can contain the following properties.
Not all SPI Peripherals from Texas Instruments support this.
Please check SPI peripheral documentation for a device before using these.
- ti,spi-wdelay : delay between transmission of words
(SPIFMTn.WDELAY, SPIDAT1.WDEL) must be specified in number of SPI module
clock periods.
delay = WDELAY * SPI_module_clock_period + 2 * SPI_module_clock_period
Below is timing diagram which shows functional meaning of
"ti,spi-wdelay" parameter.
+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
SPI_CLK | | | | | | | | | | | | | | | |
+----------+ +-+ +-+ +-+ +-+ +---------------------------+ +-+ +-+ +-
SPI_SOMI/SIMO+-----------------+ +-----------
+----------+ word1 +---------------------------+word2
+-----------------+ +-----------
WDELAY
<-------------------------->
Example of a NOR flash slave device (n25q032) connected to DaVinci Example of a NOR flash slave device (n25q032) connected to DaVinci
SPI controller device over the SPI bus. SPI controller device over the SPI bus.
...@@ -43,6 +72,7 @@ spi0:spi@20BF0000 { ...@@ -43,6 +72,7 @@ spi0:spi@20BF0000 {
compatible = "st,m25p32"; compatible = "st,m25p32";
spi-max-frequency = <25000000>; spi-max-frequency = <25000000>;
reg = <0>; reg = <0>;
ti,spi-wdelay = <8>;
partition@0 { partition@0 {
label = "u-boot-spl"; label = "u-boot-spl";
......
...@@ -601,13 +601,13 @@ THANKS TO ...@@ -601,13 +601,13 @@ THANKS TO
Contributors to Linux-SPI discussions include (in alphabetical order, Contributors to Linux-SPI discussions include (in alphabetical order,
by last name): by last name):
Mark Brown
David Brownell David Brownell
Russell King Russell King
Grant Likely
Dmitry Pervushin Dmitry Pervushin
Stephen Street Stephen Street
Mark Underwood Mark Underwood
Andrew Victor Andrew Victor
Vitaly Wool
Grant Likely
Mark Brown
Linus Walleij Linus Walleij
Vitaly Wool
...@@ -602,7 +602,7 @@ config SPI_DW_PCI ...@@ -602,7 +602,7 @@ config SPI_DW_PCI
depends on SPI_DESIGNWARE && PCI depends on SPI_DESIGNWARE && PCI
config SPI_DW_MID_DMA config SPI_DW_MID_DMA
bool "DMA support for DW SPI controller on Intel Moorestown platform" bool "DMA support for DW SPI controller on Intel MID platform"
depends on SPI_DW_PCI && INTEL_MID_DMAC depends on SPI_DW_PCI && INTEL_MID_DMAC
config SPI_DW_MMIO config SPI_DW_MMIO
......
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
/* SPIDAT1 (upper 16 bit defines) */ /* SPIDAT1 (upper 16 bit defines) */
#define SPIDAT1_CSHOLD_MASK BIT(12) #define SPIDAT1_CSHOLD_MASK BIT(12)
#define SPIDAT1_WDEL BIT(10)
/* SPIGCR1 */ /* SPIGCR1 */
#define SPIGCR1_CLKMOD_MASK BIT(1) #define SPIGCR1_CLKMOD_MASK BIT(1)
...@@ -213,6 +214,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) ...@@ -213,6 +214,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
{ {
struct davinci_spi *dspi; struct davinci_spi *dspi;
struct davinci_spi_platform_data *pdata; struct davinci_spi_platform_data *pdata;
struct davinci_spi_config *spicfg = spi->controller_data;
u8 chip_sel = spi->chip_select; u8 chip_sel = spi->chip_select;
u16 spidat1 = CS_DEFAULT; u16 spidat1 = CS_DEFAULT;
bool gpio_chipsel = false; bool gpio_chipsel = false;
...@@ -227,6 +229,10 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) ...@@ -227,6 +229,10 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
gpio = spi->cs_gpio; gpio = spi->cs_gpio;
} }
/* program delay transfers if tx_delay is non zero */
if (spicfg->wdelay)
spidat1 |= SPIDAT1_WDEL;
/* /*
* Board specific chip select logic decides the polarity and cs * Board specific chip select logic decides the polarity and cs
* line for the controller * line for the controller
...@@ -241,9 +247,9 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) ...@@ -241,9 +247,9 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
spidat1 |= SPIDAT1_CSHOLD_MASK; spidat1 |= SPIDAT1_CSHOLD_MASK;
spidat1 &= ~(0x1 << chip_sel); spidat1 &= ~(0x1 << chip_sel);
} }
iowrite16(spidat1, dspi->base + SPIDAT1 + 2);
} }
iowrite16(spidat1, dspi->base + SPIDAT1 + 2);
} }
/** /**
...@@ -289,7 +295,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, ...@@ -289,7 +295,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
int prescale; int prescale;
dspi = spi_master_get_devdata(spi->master); dspi = spi_master_get_devdata(spi->master);
spicfg = (struct davinci_spi_config *)spi->controller_data; spicfg = spi->controller_data;
if (!spicfg) if (!spicfg)
spicfg = &davinci_spi_default_cfg; spicfg = &davinci_spi_default_cfg;
...@@ -336,6 +342,14 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, ...@@ -336,6 +342,14 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
if (!(spi->mode & SPI_CPHA)) if (!(spi->mode & SPI_CPHA))
spifmt |= SPIFMT_PHASE_MASK; spifmt |= SPIFMT_PHASE_MASK;
/*
* Assume wdelay is used only on SPI peripherals that has this field
* in SPIFMTn register and when it's configured from board file or DT.
*/
if (spicfg->wdelay)
spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT)
& SPIFMT_WDELAY_MASK);
/* /*
* Version 1 hardware supports two basic SPI modes: * Version 1 hardware supports two basic SPI modes:
* - Standard SPI mode uses 4 pins, with chipselect * - Standard SPI mode uses 4 pins, with chipselect
...@@ -353,9 +367,6 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, ...@@ -353,9 +367,6 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
u32 delay = 0; u32 delay = 0;
spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT)
& SPIFMT_WDELAY_MASK);
if (spicfg->odd_parity) if (spicfg->odd_parity)
spifmt |= SPIFMT_ODD_PARITY_MASK; spifmt |= SPIFMT_ODD_PARITY_MASK;
...@@ -387,6 +398,26 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, ...@@ -387,6 +398,26 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
return 0; return 0;
} }
static int davinci_spi_of_setup(struct spi_device *spi)
{
struct davinci_spi_config *spicfg = spi->controller_data;
struct device_node *np = spi->dev.of_node;
u32 prop;
if (spicfg == NULL && np) {
spicfg = kzalloc(sizeof(*spicfg), GFP_KERNEL);
if (!spicfg)
return -ENOMEM;
*spicfg = davinci_spi_default_cfg;
/* override with dt configured values */
if (!of_property_read_u32(np, "ti,spi-wdelay", &prop))
spicfg->wdelay = (u8)prop;
spi->controller_data = spicfg;
}
return 0;
}
/** /**
* davinci_spi_setup - This functions will set default transfer method * davinci_spi_setup - This functions will set default transfer method
* @spi: spi device on which data transfer to be done * @spi: spi device on which data transfer to be done
...@@ -437,7 +468,16 @@ static int davinci_spi_setup(struct spi_device *spi) ...@@ -437,7 +468,16 @@ static int davinci_spi_setup(struct spi_device *spi)
else else
clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK); clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK);
return retval; return davinci_spi_of_setup(spi);
}
static void davinci_spi_cleanup(struct spi_device *spi)
{
struct davinci_spi_config *spicfg = spi->controller_data;
spi->controller_data = NULL;
if (spi->dev.of_node)
kfree(spicfg);
} }
static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status) static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status)
...@@ -951,6 +991,7 @@ static int davinci_spi_probe(struct platform_device *pdev) ...@@ -951,6 +991,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
master->num_chipselect = pdata->num_chipselect; master->num_chipselect = pdata->num_chipselect;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16);
master->setup = davinci_spi_setup; master->setup = davinci_spi_setup;
master->cleanup = davinci_spi_cleanup;
dspi->bitbang.chipselect = davinci_spi_chipselect; dspi->bitbang.chipselect = davinci_spi_chipselect;
dspi->bitbang.setup_transfer = davinci_spi_setup_transfer; dspi->bitbang.setup_transfer = davinci_spi_setup_transfer;
......
/* /*
* Special handling for DW core on Intel MID platform * Special handling for DW core on Intel MID platform
* *
* Copyright (c) 2009, Intel Corporation. * Copyright (c) 2009, 2014 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -39,22 +35,25 @@ static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param) ...@@ -39,22 +35,25 @@ static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
{ {
struct dw_spi *dws = param; struct dw_spi *dws = param;
return dws->dmac && (&dws->dmac->dev == chan->device->dev); return dws->dma_dev == chan->device->dev;
} }
static int mid_spi_dma_init(struct dw_spi *dws) static int mid_spi_dma_init(struct dw_spi *dws)
{ {
struct mid_dma *dw_dma = dws->dma_priv; struct mid_dma *dw_dma = dws->dma_priv;
struct pci_dev *dma_dev;
struct intel_mid_dma_slave *rxs, *txs; struct intel_mid_dma_slave *rxs, *txs;
dma_cap_mask_t mask; dma_cap_mask_t mask;
/* /*
* Get pci device for DMA controller, currently it could only * Get pci device for DMA controller, currently it could only
* be the DMA controller of either Moorestown or Medfield * be the DMA controller of Medfield
*/ */
dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0813, NULL); dma_dev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL);
if (!dws->dmac) if (!dma_dev)
dws->dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0827, NULL); return -ENODEV;
dws->dma_dev = &dma_dev->dev;
dma_cap_zero(mask); dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
...@@ -83,13 +82,18 @@ static int mid_spi_dma_init(struct dw_spi *dws) ...@@ -83,13 +82,18 @@ static int mid_spi_dma_init(struct dw_spi *dws)
free_rxchan: free_rxchan:
dma_release_channel(dws->rxchan); dma_release_channel(dws->rxchan);
err_exit: err_exit:
return -1; return -EBUSY;
} }
static void mid_spi_dma_exit(struct dw_spi *dws) static void mid_spi_dma_exit(struct dw_spi *dws)
{ {
if (!dws->dma_inited)
return;
dmaengine_terminate_all(dws->txchan);
dma_release_channel(dws->txchan); dma_release_channel(dws->txchan);
dmaengine_terminate_all(dws->rxchan);
dma_release_channel(dws->rxchan); dma_release_channel(dws->rxchan);
} }
...@@ -109,8 +113,7 @@ static void dw_spi_dma_done(void *arg) ...@@ -109,8 +113,7 @@ static void dw_spi_dma_done(void *arg)
static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
{ {
struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL; struct dma_async_tx_descriptor *txdesc, *rxdesc;
struct dma_chan *txchan, *rxchan;
struct dma_slave_config txconf, rxconf; struct dma_slave_config txconf, rxconf;
u16 dma_ctrl = 0; u16 dma_ctrl = 0;
...@@ -120,37 +123,34 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) ...@@ -120,37 +123,34 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
dw_writew(dws, DW_SPI_DMARDLR, 0xf); dw_writew(dws, DW_SPI_DMARDLR, 0xf);
dw_writew(dws, DW_SPI_DMATDLR, 0x10); dw_writew(dws, DW_SPI_DMATDLR, 0x10);
if (dws->tx_dma) if (dws->tx_dma)
dma_ctrl |= 0x2; dma_ctrl |= SPI_DMA_TDMAE;
if (dws->rx_dma) if (dws->rx_dma)
dma_ctrl |= 0x1; dma_ctrl |= SPI_DMA_RDMAE;
dw_writew(dws, DW_SPI_DMACR, dma_ctrl); dw_writew(dws, DW_SPI_DMACR, dma_ctrl);
spi_enable_chip(dws, 1); spi_enable_chip(dws, 1);
} }
dws->dma_chan_done = 0; dws->dma_chan_done = 0;
txchan = dws->txchan;
rxchan = dws->rxchan;
/* 2. Prepare the TX dma transfer */ /* 2. Prepare the TX dma transfer */
txconf.direction = DMA_MEM_TO_DEV; txconf.direction = DMA_MEM_TO_DEV;
txconf.dst_addr = dws->dma_addr; txconf.dst_addr = dws->dma_addr;
txconf.dst_maxburst = LNW_DMA_MSIZE_16; txconf.dst_maxburst = LNW_DMA_MSIZE_16;
txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; txconf.dst_addr_width = dws->dma_width;
txconf.device_fc = false; txconf.device_fc = false;
txchan->device->device_control(txchan, DMA_SLAVE_CONFIG, dmaengine_slave_config(dws->txchan, &txconf);
(unsigned long) &txconf);
memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl)); memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl));
dws->tx_sgl.dma_address = dws->tx_dma; dws->tx_sgl.dma_address = dws->tx_dma;
dws->tx_sgl.length = dws->len; dws->tx_sgl.length = dws->len;
txdesc = dmaengine_prep_slave_sg(txchan, txdesc = dmaengine_prep_slave_sg(dws->txchan,
&dws->tx_sgl, &dws->tx_sgl,
1, 1,
DMA_MEM_TO_DEV, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
txdesc->callback = dw_spi_dma_done; txdesc->callback = dw_spi_dma_done;
txdesc->callback_param = dws; txdesc->callback_param = dws;
...@@ -159,27 +159,30 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) ...@@ -159,27 +159,30 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
rxconf.src_addr = dws->dma_addr; rxconf.src_addr = dws->dma_addr;
rxconf.src_maxburst = LNW_DMA_MSIZE_16; rxconf.src_maxburst = LNW_DMA_MSIZE_16;
rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; rxconf.src_addr_width = dws->dma_width;
rxconf.device_fc = false; rxconf.device_fc = false;
rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG, dmaengine_slave_config(dws->rxchan, &rxconf);
(unsigned long) &rxconf);
memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl)); memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl));
dws->rx_sgl.dma_address = dws->rx_dma; dws->rx_sgl.dma_address = dws->rx_dma;
dws->rx_sgl.length = dws->len; dws->rx_sgl.length = dws->len;
rxdesc = dmaengine_prep_slave_sg(rxchan, rxdesc = dmaengine_prep_slave_sg(dws->rxchan,
&dws->rx_sgl, &dws->rx_sgl,
1, 1,
DMA_DEV_TO_MEM, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT); DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
rxdesc->callback = dw_spi_dma_done; rxdesc->callback = dw_spi_dma_done;
rxdesc->callback_param = dws; rxdesc->callback_param = dws;
/* rx must be started before tx due to spi instinct */ /* rx must be started before tx due to spi instinct */
rxdesc->tx_submit(rxdesc); dmaengine_submit(rxdesc);
txdesc->tx_submit(txdesc); dma_async_issue_pending(dws->rxchan);
dmaengine_submit(txdesc);
dma_async_issue_pending(dws->txchan);
return 0; return 0;
} }
...@@ -190,7 +193,7 @@ static struct dw_spi_dma_ops mid_dma_ops = { ...@@ -190,7 +193,7 @@ static struct dw_spi_dma_ops mid_dma_ops = {
}; };
#endif #endif
/* Some specific info for SPI0 controller on Moorestown */ /* Some specific info for SPI0 controller on Intel MID */
/* HW info for MRST CLk Control Unit, one 32b reg */ /* HW info for MRST CLk Control Unit, one 32b reg */
#define MRST_SPI_CLK_BASE 100000000 /* 100m */ #define MRST_SPI_CLK_BASE 100000000 /* 100m */
......
/* /*
* PCI interface driver for DW SPI Core * PCI interface driver for DW SPI Core
* *
* Copyright (c) 2009, Intel Corporation. * Copyright (c) 2009, 2014 Intel Corporation.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -32,17 +28,22 @@ struct dw_spi_pci { ...@@ -32,17 +28,22 @@ struct dw_spi_pci {
struct dw_spi dws; struct dw_spi dws;
}; };
static int spi_pci_probe(struct pci_dev *pdev, struct spi_pci_desc {
const struct pci_device_id *ent) int (*setup)(struct dw_spi *);
};
static struct spi_pci_desc spi_pci_mid_desc = {
.setup = dw_spi_mid_init,
};
static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
struct dw_spi_pci *dwpci; struct dw_spi_pci *dwpci;
struct dw_spi *dws; struct dw_spi *dws;
struct spi_pci_desc *desc = (struct spi_pci_desc *)ent->driver_data;
int pci_bar = 0; int pci_bar = 0;
int ret; int ret;
dev_info(&pdev->dev, "found PCI SPI controller(ID: %04x:%04x)\n",
pdev->vendor, pdev->device);
ret = pcim_enable_device(pdev); ret = pcim_enable_device(pdev);
if (ret) if (ret)
return ret; return ret;
...@@ -58,7 +59,7 @@ static int spi_pci_probe(struct pci_dev *pdev, ...@@ -58,7 +59,7 @@ static int spi_pci_probe(struct pci_dev *pdev,
/* Get basic io resource and map it */ /* Get basic io resource and map it */
dws->paddr = pci_resource_start(pdev, pci_bar); dws->paddr = pci_resource_start(pdev, pci_bar);
ret = pcim_iomap_regions(pdev, 1, dev_name(&pdev->dev)); ret = pcim_iomap_regions(pdev, 1 << pci_bar, pci_name(pdev));
if (ret) if (ret)
return ret; return ret;
...@@ -69,11 +70,11 @@ static int spi_pci_probe(struct pci_dev *pdev, ...@@ -69,11 +70,11 @@ static int spi_pci_probe(struct pci_dev *pdev,
dws->irq = pdev->irq; dws->irq = pdev->irq;
/* /*
* Specific handling for Intel MID paltforms, like dma setup, * Specific handling for paltforms, like dma setup,
* clock rate, FIFO depth. * clock rate, FIFO depth.
*/ */
if (pdev->device == 0x0800) { if (desc && desc->setup) {
ret = dw_spi_mid_init(dws); ret = desc->setup(dws);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -85,6 +86,9 @@ static int spi_pci_probe(struct pci_dev *pdev, ...@@ -85,6 +86,9 @@ static int spi_pci_probe(struct pci_dev *pdev,
/* PCI hook and SPI hook use the same drv data */ /* PCI hook and SPI hook use the same drv data */
pci_set_drvdata(pdev, dwpci); pci_set_drvdata(pdev, dwpci);
dev_info(&pdev->dev, "found PCI SPI controller(ID: %04x:%04x)\n",
pdev->vendor, pdev->device);
return 0; return 0;
} }
...@@ -95,41 +99,29 @@ static void spi_pci_remove(struct pci_dev *pdev) ...@@ -95,41 +99,29 @@ static void spi_pci_remove(struct pci_dev *pdev)
dw_spi_remove_host(&dwpci->dws); dw_spi_remove_host(&dwpci->dws);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int spi_suspend(struct pci_dev *pdev, pm_message_t state) static int spi_suspend(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev);
struct dw_spi_pci *dwpci = pci_get_drvdata(pdev); struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
int ret;
ret = dw_spi_suspend_host(&dwpci->dws); return dw_spi_suspend_host(&dwpci->dws);
if (ret)
return ret;
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
return ret;
} }
static int spi_resume(struct pci_dev *pdev) static int spi_resume(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev);
struct dw_spi_pci *dwpci = pci_get_drvdata(pdev); struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
int ret;
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
ret = pci_enable_device(pdev);
if (ret)
return ret;
return dw_spi_resume_host(&dwpci->dws); return dw_spi_resume_host(&dwpci->dws);
} }
#else
#define spi_suspend NULL
#define spi_resume NULL
#endif #endif
static SIMPLE_DEV_PM_OPS(dw_spi_pm_ops, spi_suspend, spi_resume);
static const struct pci_device_id pci_ids[] = { static const struct pci_device_id pci_ids[] = {
/* Intel MID platform SPI controller 0 */ /* Intel MID platform SPI controller 0 */
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) }, { PCI_VDEVICE(INTEL, 0x0800), (kernel_ulong_t)&spi_pci_mid_desc},
{}, {},
}; };
...@@ -138,8 +130,9 @@ static struct pci_driver dw_spi_driver = { ...@@ -138,8 +130,9 @@ static struct pci_driver dw_spi_driver = {
.id_table = pci_ids, .id_table = pci_ids,
.probe = spi_pci_probe, .probe = spi_pci_probe,
.remove = spi_pci_remove, .remove = spi_pci_remove,
.suspend = spi_suspend, .driver = {
.resume = spi_resume, .pm = &dw_spi_pm_ops,
},
}; };
module_pci_driver(dw_spi_driver); module_pci_driver(dw_spi_driver);
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * 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.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -59,22 +55,20 @@ struct chip_data { ...@@ -59,22 +55,20 @@ struct chip_data {
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
#define SPI_REGS_BUFSIZE 1024 #define SPI_REGS_BUFSIZE 1024
static ssize_t spi_show_regs(struct file *file, char __user *user_buf, static ssize_t dw_spi_show_regs(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct dw_spi *dws; struct dw_spi *dws = file->private_data;
char *buf; char *buf;
u32 len = 0; u32 len = 0;
ssize_t ret; ssize_t ret;
dws = file->private_data;
buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL); buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);
if (!buf) if (!buf)
return 0; return 0;
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
"MRST SPI0 registers:\n"); "%s registers:\n", dev_name(&dws->master->dev));
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
"=================================\n"); "=================================\n");
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
...@@ -110,41 +104,41 @@ static ssize_t spi_show_regs(struct file *file, char __user *user_buf, ...@@ -110,41 +104,41 @@ static ssize_t spi_show_regs(struct file *file, char __user *user_buf,
len += snprintf(buf + len, SPI_REGS_BUFSIZE - len, len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
"=================================\n"); "=================================\n");
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf); kfree(buf);
return ret; return ret;
} }
static const struct file_operations mrst_spi_regs_ops = { static const struct file_operations dw_spi_regs_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = simple_open, .open = simple_open,
.read = spi_show_regs, .read = dw_spi_show_regs,
.llseek = default_llseek, .llseek = default_llseek,
}; };
static int mrst_spi_debugfs_init(struct dw_spi *dws) static int dw_spi_debugfs_init(struct dw_spi *dws)
{ {
dws->debugfs = debugfs_create_dir("mrst_spi", NULL); dws->debugfs = debugfs_create_dir("dw_spi", NULL);
if (!dws->debugfs) if (!dws->debugfs)
return -ENOMEM; return -ENOMEM;
debugfs_create_file("registers", S_IFREG | S_IRUGO, debugfs_create_file("registers", S_IFREG | S_IRUGO,
dws->debugfs, (void *)dws, &mrst_spi_regs_ops); dws->debugfs, (void *)dws, &dw_spi_regs_ops);
return 0; return 0;
} }
static void mrst_spi_debugfs_remove(struct dw_spi *dws) static void dw_spi_debugfs_remove(struct dw_spi *dws)
{ {
debugfs_remove_recursive(dws->debugfs); debugfs_remove_recursive(dws->debugfs);
} }
#else #else
static inline int mrst_spi_debugfs_init(struct dw_spi *dws) static inline int dw_spi_debugfs_init(struct dw_spi *dws)
{ {
return 0; return 0;
} }
static inline void mrst_spi_debugfs_remove(struct dw_spi *dws) static inline void dw_spi_debugfs_remove(struct dw_spi *dws)
{ {
} }
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
...@@ -396,7 +390,7 @@ static void pump_transfers(unsigned long data) ...@@ -396,7 +390,7 @@ static void pump_transfers(unsigned long data)
goto early_exit; goto early_exit;
} }
/* Delay if requested at end of transfer*/ /* Delay if requested at end of transfer */
if (message->state == RUNNING_STATE) { if (message->state == RUNNING_STATE) {
previous = list_entry(transfer->transfer_list.prev, previous = list_entry(transfer->transfer_list.prev,
struct spi_transfer, struct spi_transfer,
...@@ -525,7 +519,7 @@ static int dw_spi_transfer_one_message(struct spi_master *master, ...@@ -525,7 +519,7 @@ static int dw_spi_transfer_one_message(struct spi_master *master,
struct dw_spi *dws = spi_master_get_devdata(master); struct dw_spi *dws = spi_master_get_devdata(master);
dws->cur_msg = msg; dws->cur_msg = msg;
/* Initial message state*/ /* Initial message state */
dws->cur_msg->state = START_STATE; dws->cur_msg->state = START_STATE;
dws->cur_transfer = list_entry(dws->cur_msg->transfers.next, dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,
struct spi_transfer, struct spi_transfer,
...@@ -596,6 +590,9 @@ static int dw_spi_setup(struct spi_device *spi) ...@@ -596,6 +590,9 @@ static int dw_spi_setup(struct spi_device *spi)
| (spi->mode << SPI_MODE_OFFSET) | (spi->mode << SPI_MODE_OFFSET)
| (chip->tmode << SPI_TMOD_OFFSET); | (chip->tmode << SPI_TMOD_OFFSET);
if (spi->mode & SPI_LOOP)
chip->cr0 |= 1 << SPI_SRL_OFFSET;
if (gpio_is_valid(spi->cs_gpio)) { if (gpio_is_valid(spi->cs_gpio)) {
ret = gpio_direction_output(spi->cs_gpio, ret = gpio_direction_output(spi->cs_gpio,
!(spi->mode & SPI_CS_HIGH)); !(spi->mode & SPI_CS_HIGH));
...@@ -655,8 +652,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -655,8 +652,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
dws->prev_chip = NULL; dws->prev_chip = NULL;
dws->dma_inited = 0; dws->dma_inited = 0;
dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60); dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
snprintf(dws->name, sizeof(dws->name), "dw_spi%d", snprintf(dws->name, sizeof(dws->name), "dw_spi%d", dws->bus_num);
dws->bus_num);
ret = devm_request_irq(dev, dws->irq, dw_spi_irq, IRQF_SHARED, ret = devm_request_irq(dev, dws->irq, dw_spi_irq, IRQF_SHARED,
dws->name, dws); dws->name, dws);
...@@ -665,7 +661,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -665,7 +661,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
goto err_free_master; goto err_free_master;
} }
master->mode_bits = SPI_CPOL | SPI_CPHA; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
master->bus_num = dws->bus_num; master->bus_num = dws->bus_num;
master->num_chipselect = dws->num_cs; master->num_chipselect = dws->num_cs;
...@@ -694,7 +690,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -694,7 +690,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
goto err_dma_exit; goto err_dma_exit;
} }
mrst_spi_debugfs_init(dws); dw_spi_debugfs_init(dws);
return 0; return 0;
err_dma_exit: err_dma_exit:
...@@ -711,7 +707,7 @@ void dw_spi_remove_host(struct dw_spi *dws) ...@@ -711,7 +707,7 @@ void dw_spi_remove_host(struct dw_spi *dws)
{ {
if (!dws) if (!dws)
return; return;
mrst_spi_debugfs_remove(dws); dw_spi_debugfs_remove(dws);
if (dws->dma_ops && dws->dma_ops->dma_exit) if (dws->dma_ops && dws->dma_ops->dma_exit)
dws->dma_ops->dma_exit(dws); dws->dma_ops->dma_exit(dws);
......
...@@ -74,6 +74,10 @@ ...@@ -74,6 +74,10 @@
#define SPI_INT_RXFI (1 << 4) #define SPI_INT_RXFI (1 << 4)
#define SPI_INT_MSTI (1 << 5) #define SPI_INT_MSTI (1 << 5)
/* Bit fields in DMACR */
#define SPI_DMA_RDMAE (1 << 0)
#define SPI_DMA_TDMAE (1 << 1)
/* TX RX interrupt level threshold, max can be 256 */ /* TX RX interrupt level threshold, max can be 256 */
#define SPI_INT_THRESHOLD 32 #define SPI_INT_THRESHOLD 32
...@@ -140,7 +144,6 @@ struct dw_spi { ...@@ -140,7 +144,6 @@ struct dw_spi {
dma_addr_t dma_addr; /* phy address of the Data register */ dma_addr_t dma_addr; /* phy address of the Data register */
struct dw_spi_dma_ops *dma_ops; struct dw_spi_dma_ops *dma_ops;
void *dma_priv; /* platform relate info */ void *dma_priv; /* platform relate info */
struct pci_dev *dmac;
/* Bus interface info */ /* Bus interface info */
void *priv; void *priv;
...@@ -217,11 +220,11 @@ static inline void spi_umask_intr(struct dw_spi *dws, u32 mask) ...@@ -217,11 +220,11 @@ static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
* Each SPI slave device to work with dw_api controller should * Each SPI slave device to work with dw_api controller should
* has such a structure claiming its working mode (PIO/DMA etc), * has such a structure claiming its working mode (PIO/DMA etc),
* which can be save in the "controller_data" member of the * which can be save in the "controller_data" member of the
* struct spi_device * struct spi_device.
*/ */
struct dw_spi_chip { struct dw_spi_chip {
u8 poll_mode; /* 0 for contoller polling mode */ u8 poll_mode; /* 1 for controller polling mode */
u8 type; /* SPI/SSP/Micrwire */ u8 type; /* SPI/SSP/MicroWire */
u8 enable_dma; u8 enable_dma;
void (*cs_control)(u32 command); void (*cs_control)(u32 command);
}; };
......
...@@ -15,17 +15,17 @@ ...@@ -15,17 +15,17 @@
* Free Software Foundation; either version 2 of the License, or (at your * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. * option) any later version.
*/ */
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/fsl_devices.h>
#include <linux/dma-mapping.h>
#include <linux/of_address.h>
#include <asm/cpm.h> #include <asm/cpm.h>
#include <asm/qe.h> #include <asm/qe.h>
#include <linux/dma-mapping.h>
#include <linux/fsl_devices.h>
#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/spi/spi.h>
#include <linux/types.h>
#include "spi-fsl-lib.h"
#include "spi-fsl-cpm.h" #include "spi-fsl-cpm.h"
#include "spi-fsl-lib.h"
#include "spi-fsl-spi.h" #include "spi-fsl-spi.h"
/* CPM1 and CPM2 are mutually exclusive. */ /* CPM1 and CPM2 are mutually exclusive. */
......
...@@ -13,22 +13,22 @@ ...@@ -13,22 +13,22 @@
* *
*/ */
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h> #include <linux/of.h>
#include <linux/errno.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/err.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/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_device.h>
#define DRIVER_NAME "fsl-dspi" #define DRIVER_NAME "fsl-dspi"
......
...@@ -8,19 +8,19 @@ ...@@ -8,19 +8,19 @@
* Free Software Foundation; either version 2 of the License, or (at your * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. * option) any later version.
*/ */
#include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/irq.h> #include <linux/err.h>
#include <linux/spi/spi.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h> #include <linux/fsl_devices.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/interrupt.h> #include <linux/platform_device.h>
#include <linux/err.h> #include <linux/spi/spi.h>
#include <sysdev/fsl_soc.h> #include <sysdev/fsl_soc.h>
#include "spi-fsl-lib.h" #include "spi-fsl-lib.h"
......
...@@ -16,10 +16,10 @@ ...@@ -16,10 +16,10 @@
* Free Software Foundation; either version 2 of the License, or (at your * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. * option) any later version.
*/ */
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/fsl_devices.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/fsl_devices.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
......
...@@ -19,25 +19,25 @@ ...@@ -19,25 +19,25 @@
* Free Software Foundation; either version 2 of the License, or (at your * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. * option) any later version.
*/ */
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/irq.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/fsl_devices.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/types.h>
#include "spi-fsl-lib.h" #include "spi-fsl-lib.h"
#include "spi-fsl-cpm.h" #include "spi-fsl-cpm.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment