Re: [PATCH] dw_spi: add DMA support

2010-12-01 Thread Feng Tang
On Tue, 30 Nov 2010 23:13:22 +0800
Linus Walleij linus.wall...@stericsson.com wrote:

 2010/11/23 Feng Tang feng.t...@intel.com:
 
  Thanks for the reviews, I made some dma change as you suggested, pls
  help to review.
 
 This is looking much better. I guess there is a corresponding patch to
 drivers/dma/* to provide the proper interfaces for this to work?
 Anyway, Acked-by: Linus Walleij linus.wall...@stericsson.com

Yes, there will be some changed to the corresponding dma driver. Thanks
again for the review

- Feng
 
 Yours,
 Linus Walleij

--
Increase Visibility of Your 3D Game App  Earn a Chance To Win $500!
Tap into the largest installed PC base  get more eyes on your game by
optimizing for Intel(R) Graphics Technology. Get started today with the
Intel(R) Software Partner Program. Five $500 cash prizes are up for grabs.
http://p.sf.net/sfu/intelisp-dev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH] dw_spi: add DMA support

2010-11-30 Thread Linus Walleij
2010/11/23 Feng Tang feng.t...@intel.com:

 Thanks for the reviews, I made some dma change as you suggested, pls
 help to review.

This is looking much better. I guess there is a corresponding patch to
drivers/dma/* to provide the proper interfaces for this to work?
Anyway, Acked-by: Linus Walleij linus.wall...@stericsson.com

Yours,
Linus Walleij

--
Increase Visibility of Your 3D Game App  Earn a Chance To Win $500!
Tap into the largest installed PC base  get more eyes on your game by
optimizing for Intel(R) Graphics Technology. Get started today with the
Intel(R) Software Partner Program. Five $500 cash prizes are up for grabs.
http://p.sf.net/sfu/intelisp-dev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH] dw_spi: add DMA support

2010-11-23 Thread Feng Tang


On Tue, 23 Nov 2010 14:48:39 +0800
Linus Walleij linus.ml.wall...@gmail.com wrote:

 This is much better than last time but I still have questions...
 
 2010/11/18 Alan Cox a...@lxorguk.ukuu.org.uk:
 
  +       /* 1. Init rx channel */
  +       rxs = dw_dma-dmas_rx;
  +       ds = rxs-dma_slave;
  +       ds-direction = DMA_FROM_DEVICE;
  +       rxs-hs_mode = LNW_DMA_HW_HS;
  +       rxs-cfg_mode = LNW_DMA_PER_TO_MEM;
  +       ds-src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
  +       ds-dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
  +       ds-src_maxburst = 16;
  +       ds-dst_maxburst = 16;
 
 This is great stuff! That is exactly how ds is to be set up.
 I would prefer that you don't dereference the this rxs thing here
 but whatever.
 
  +       dma_cap_zero(mask);
  +       dma_cap_set(DMA_MEMCPY, mask);
  +       dma_cap_set(DMA_SLAVE, mask);
 
 This is not elegant. Are you going to do memcpy() or slave
 transfers? What you want to do is fix your DMA engine so that
 just asking for DMA_SLAVE works.
 
  +       dma_cap_set(DMA_SLAVE, mask);
  +       dma_cap_set(DMA_MEMCPY, mask);
 
 Here again...
 
  +static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
  +{
 (...)
  +       flag = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
  +       if (dws-tx_dma) {
  +               txdesc =
  txchan-device-device_prep_dma_memcpy(txchan,
  +                               dws-dma_addr, dws-tx_dma,
  +                               dws-len, flag);
  +               txdesc-callback = dw_spi_dma_done;
  +               txdesc-callback_param = dws-tx_param;
  +       }
  +
  +       /* 3. start the RX dma transfer */
  +       if (dws-rx_dma) {
  +               rxdesc =
  rxchan-device-device_prep_dma_memcpy(rxchan,
  +                               dws-rx_dma, dws-dma_addr,
  +                               dws-len, flag);
  +               rxdesc-callback = dw_spi_dma_done;
  +               rxdesc-callback_param = dws-rx_param;
  +       }
 
 Using device_prep_dma_memcpy() for this is still nonsense, it should
 be device_prep_slave_sg().
 
 I know the DMA driver needs fixing in order for this to work properly,
 so why not fix it?
 
 These are the most important concerns I raised last iteration, so
 I challenge you to fix drivers/dma/dw_dmac.c or wherever the real
 problem sits.
 
 Can you describe where the problem with fixing this to use real
 slave sglists is?
 
 Yours,
 Linus Walleij

Hi Linus,

Thanks for the reviews, I made some dma change as you suggested, pls
help to review.

Thanks,
Feng

From b77efc5945e31442b53b285d6a3f77def376ebb3 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Tue, 23 Nov 2010 17:34:28 +0800
Subject: [PATCH] spi/dw_spi: add DMA support

dw_spi driver in upstream only supports PIO mode, and this patch
will support it to cowork with the Designware DMA controller used
on Intel Moorestown platform

It has been tested with a Option GTM501L 3G modem, to use DMA mode,
DMA controller 2 of Moorestown has to be enabled

Signed-off-by: Feng Tang feng.t...@intel.com
[Typo fix and renames to match intel_mid_dma renaming]
Signed-off-by: Vinod Koul vinod.k...@intel.com
[Clean up, change dma interface suggested by Linus Walleij]
Signed-off-by: Feng Tang feng.t...@intel.com
[Fix timing delay, add cpu_relax]
Signed-off-by: Arjan van de Ven ar...@linux.intel.com
Signed-off-by: Alan Cox a...@linux.intel.com
---
 drivers/spi/Kconfig|4 +
 drivers/spi/Makefile   |3 +-
 drivers/spi/dw_spi.c   |   48 ++
 drivers/spi/dw_spi_mid.c   |  225 
 drivers/spi/dw_spi_pci.c   |   14 ++-
 include/linux/spi/dw_spi.h |   24 -
 6 files changed, 288 insertions(+), 30 deletions(-)
 create mode 100644 drivers/spi/dw_spi_mid.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 78f9fd0..d53c830 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -396,6 +396,10 @@ config SPI_DW_PCI
tristate PCI interface driver for DW SPI core
depends on SPI_DESIGNWARE  PCI
 
+config SPI_DW_MID_DMA
+   bool DMA support for DW SPI controller on Intel Moorestown platform
+   depends on SPI_DW_PCI  INTEL_MID_DMAC
+
 config SPI_DW_MMIO
tristate Memory-mapped io interface driver for DW SPI core
depends on SPI_DESIGNWARE  HAVE_CLK
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 8bc1a5a..5e6e812 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,7 +17,8 @@ obj-$(CONFIG_SPI_BUTTERFLY)   += spi_butterfly.o
 obj-$(CONFIG_SPI_COLDFIRE_QSPI)+= coldfire_qspi.o
 obj-$(CONFIG_SPI_DAVINCI)  += davinci_spi.o
 obj-$(CONFIG_SPI_DESIGNWARE)   += dw_spi.o
-obj-$(CONFIG_SPI_DW_PCI)   += dw_spi_pci.o
+obj-$(CONFIG_SPI_DW_PCI)   += dw_spi_midpci.o
+dw_spi_midpci-objs := dw_spi_pci.o dw_spi_mid.o
 obj-$(CONFIG_SPI_DW_MMIO)  

Re: [PATCH] dw_spi: add DMA support

2010-11-22 Thread Linus Walleij
This is much better than last time but I still have questions...

2010/11/18 Alan Cox a...@lxorguk.ukuu.org.uk:

 +       /* 1. Init rx channel */
 +       rxs = dw_dma-dmas_rx;
 +       ds = rxs-dma_slave;
 +       ds-direction = DMA_FROM_DEVICE;
 +       rxs-hs_mode = LNW_DMA_HW_HS;
 +       rxs-cfg_mode = LNW_DMA_PER_TO_MEM;
 +       ds-src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 +       ds-dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 +       ds-src_maxburst = 16;
 +       ds-dst_maxburst = 16;

This is great stuff! That is exactly how ds is to be set up.
I would prefer that you don't dereference the this rxs thing here
but whatever.

 +       dma_cap_zero(mask);
 +       dma_cap_set(DMA_MEMCPY, mask);
 +       dma_cap_set(DMA_SLAVE, mask);

This is not elegant. Are you going to do memcpy() or slave
transfers? What you want to do is fix your DMA engine so that
just asking for DMA_SLAVE works.

 +       dma_cap_set(DMA_SLAVE, mask);
 +       dma_cap_set(DMA_MEMCPY, mask);

Here again...

 +static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
 +{
(...)
 +       flag = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
 +       if (dws-tx_dma) {
 +               txdesc = txchan-device-device_prep_dma_memcpy(txchan,
 +                               dws-dma_addr, dws-tx_dma,
 +                               dws-len, flag);
 +               txdesc-callback = dw_spi_dma_done;
 +               txdesc-callback_param = dws-tx_param;
 +       }
 +
 +       /* 3. start the RX dma transfer */
 +       if (dws-rx_dma) {
 +               rxdesc = rxchan-device-device_prep_dma_memcpy(rxchan,
 +                               dws-rx_dma, dws-dma_addr,
 +                               dws-len, flag);
 +               rxdesc-callback = dw_spi_dma_done;
 +               rxdesc-callback_param = dws-rx_param;
 +       }

Using device_prep_dma_memcpy() for this is still nonsense, it should be
device_prep_slave_sg().

I know the DMA driver needs fixing in order for this to work properly,
so why not fix it?

These are the most important concerns I raised last iteration, so
I challenge you to fix drivers/dma/dw_dmac.c or wherever the real
problem sits.

Can you describe where the problem with fixing this to use real
slave sglists is?

Yours,
Linus Walleij

--
Increase Visibility of Your 3D Game App  Earn a Chance To Win $500!
Tap into the largest installed PC base  get more eyes on your game by
optimizing for Intel(R) Graphics Technology. Get started today with the
Intel(R) Software Partner Program. Five $500 cash prizes are up for grabs.
http://p.sf.net/sfu/intelisp-dev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[PATCH] dw_spi: add DMA support

2010-11-18 Thread Alan Cox
From: Feng Tang feng.t...@intel.com

dw_spi driver in upstream only supports PIO mode, and this patch
will support it to cowork with the Designware DMA controller used
on Intel Moorestown platform

It has been tested with a Option GTM501L 3G modem, to use DMA mode,
DMA controller 2 of Moorestown has to be enabled

Signed-off-by: Feng Tang feng.t...@intel.com
[Typo fix and renames to match intel_mid_dma renaming]
Signed-off-by: Vinod Koul vinod.k...@intel.com
[Clean up]
Signed-off-by: Feng Tang feng.t...@intel.com
[Fix timing delay, add cpu_relax]
Signed-off-by: Arjan van de Ven ar...@linux.intel.com
Signed-off-by: Alan Cox a...@linux.intel.com
---

 drivers/spi/Kconfig|4 +
 drivers/spi/Makefile   |3 -
 drivers/spi/dw_spi.c   |   48 +
 drivers/spi/dw_spi_mid.c   |  246 
 drivers/spi/dw_spi_pci.c   |   14 ++-
 include/linux/spi/dw_spi.h |   15 +++
 6 files changed, 305 insertions(+), 25 deletions(-)
 create mode 100644 drivers/spi/dw_spi_mid.c


diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 82e45cf..6e6a638 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -404,6 +404,10 @@ config SPI_DW_PCI
tristate PCI interface driver for DW SPI core
depends on SPI_DESIGNWARE  PCI
 
+config SPI_DW_MID_DMA
+   bool DMA support for DW SPI controller on Intel Moorestown platform
+   depends on SPI_DW_PCI  INTEL_MID_DMAC
+
 config SPI_DW_MMIO
tristate Memory-mapped io interface driver for DW SPI core
depends on SPI_DESIGNWARE  HAVE_CLK
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index b427c2e..4949370 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,7 +17,8 @@ obj-$(CONFIG_SPI_BUTTERFLY)   += spi_butterfly.o
 obj-$(CONFIG_SPI_COLDFIRE_QSPI)+= coldfire_qspi.o
 obj-$(CONFIG_SPI_DAVINCI)  += davinci_spi.o
 obj-$(CONFIG_SPI_DESIGNWARE)   += dw_spi.o
-obj-$(CONFIG_SPI_DW_PCI)   += dw_spi_pci.o
+obj-$(CONFIG_SPI_DW_PCI)   += dw_spi_midpci.o
+dw_spi_midpci-objs := dw_spi_pci.o dw_spi_mid.o
 obj-$(CONFIG_SPI_DW_MMIO)  += dw_spi_mmio.o
 obj-$(CONFIG_SPI_EP93XX)   += ep93xx_spi.o
 obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 9043931..69cc223 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -164,20 +164,23 @@ static inline void mrst_spi_debugfs_remove(struct dw_spi 
*dws)
 
 static void wait_till_not_busy(struct dw_spi *dws)
 {
-   unsigned long end = jiffies + 1 + usecs_to_jiffies(1000);
+   unsigned long end = jiffies + 1 + usecs_to_jiffies(5000);
 
while (time_before(jiffies, end)) {
if (!(dw_readw(dws, sr)  SR_BUSY))
return;
+   cpu_relax();
}
dev_err(dws-master-dev,
-   DW SPI: Status keeps busy for 1000us after a read/write!\n);
+   DW SPI: Status keeps busy for 5000us after a read/write!\n);
 }
 
 static void flush(struct dw_spi *dws)
 {
-   while (dw_readw(dws, sr)  SR_RF_NOT_EMPT)
+   while (dw_readw(dws, sr)  SR_RF_NOT_EMPT) {
dw_readw(dws, dr);
+   cpu_relax();
+   }
 
wait_till_not_busy(dws);
 }
@@ -285,8 +288,10 @@ static void *next_transfer(struct dw_spi *dws)
  */
 static int map_dma_buffers(struct dw_spi *dws)
 {
-   if (!dws-cur_msg-is_dma_mapped || !dws-dma_inited
-   || !dws-cur_chip-enable_dma)
+   if (!dws-cur_msg-is_dma_mapped
+   || !dws-dma_inited
+   || !dws-cur_chip-enable_dma
+   || !dws-dma_ops)
return 0;
 
if (dws-cur_transfer-tx_dma)
@@ -338,7 +343,7 @@ static void int_error_stop(struct dw_spi *dws, const char 
*msg)
tasklet_schedule(dws-pump_transfers);
 }
 
-static void transfer_complete(struct dw_spi *dws)
+void dw_spi_xfer_done(struct dw_spi *dws)
 {
/* Update total byte transfered return count actual bytes read */
dws-cur_msg-actual_length += dws-len;
@@ -353,6 +358,7 @@ static void transfer_complete(struct dw_spi *dws)
} else
tasklet_schedule(dws-pump_transfers);
 }
+EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
 
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 {
@@ -384,7 +390,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
if (dws-tx_end  dws-tx)
spi_umask_intr(dws, SPI_INT_TXEI);
else
-   transfer_complete(dws);
+   dw_spi_xfer_done(dws);
}
 
return IRQ_HANDLED;
@@ -414,11 +420,7 @@ static void poll_transfer(struct dw_spi *dws)
while (dws-write(dws))
dws-read(dws);
 
-   transfer_complete(dws);
-}
-
-static void dma_transfer(struct dw_spi *dws, int cs_change)
-{
+   dw_spi_xfer_done(dws);
 }
 
 

Re: [PATCH] dw_spi: add DMA support

2010-10-24 Thread Alan Cox
 There *is* a generic runtime channel control interface as of
 kernel 2.6.36. Compare to this snippet from the PL022 DMA

Not when this driver was done.

 support that was merged into becoming 2.6.37 a day ago or so
 (behold the beauty in drivers/spi/amba-pl022.c):

Funnily enough I've already moved to using the proper fields in the next
version of all the DMA using patches so that bit is cool, but I've not
done the other stuff you then point out so I'll go through your example
and tidy up.


--
Nokia and ATT present the 2010 Calling All Innovators-North America contest
Create new apps  games for the Nokia N8 for consumers in  U.S. and Canada
$10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing
Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store 
http://p.sf.net/sfu/nokia-dev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH] dw_spi: add DMA support

2010-10-23 Thread Linus Walleij
2010/10/22 Alan Cox a...@lxorguk.ukuu.org.uk:

 (...)
 +static int mid_spi_dma_init(struct dw_spi *dws)
 +{
 +       struct mid_dma *dw_dma = dws-dma_priv;
 +       struct intel_mid_dma_slave *rxs, *txs;
 +       dma_cap_mask_t mask;
 +
 +       dws-txchan = NULL;
 +       dws-rxchan = NULL;
 +
 +       /*get pci device for DMA*/
 +       dws-dmac = pci_get_device(PCI_VENDOR_ID_INTEL, 0x813, NULL);
 +
 +       /* 1. Init rx channel */
 +       rxs = dw_dma-dmas_rx;
 +
 +       rxs-dirn = DMA_FROM_DEVICE;
 +       rxs-hs_mode = LNW_DMA_HW_HS;
 +       rxs-cfg_mode = LNW_DMA_PER_TO_MEM;
 +       rxs-src_width = LNW_DMA_WIDTH_16BIT;
 +       rxs-dst_width = LNW_DMA_WIDTH_32BIT;
 +       rxs-src_msize = LNW_DMA_MSIZE_16;
 +       rxs-dst_msize = LNW_DMA_MSIZE_16;

Hm, hm hm. You go configure these channel characteristics
by derferencing and writing private data.

There *is* a generic runtime channel control interface as of
kernel 2.6.36. Compare to this snippet from the PL022 DMA
support that was merged into becoming 2.6.37 a day ago or so
(behold the beauty in drivers/spi/amba-pl022.c):

struct dma_slave_config rx_conf = {
.src_addr = SSP_DR(pl022-phybase),
.direction = DMA_FROM_DEVICE,
.src_maxburst = pl022-vendor-fifodepth  1,
};
   (...)
struct dma_chan *rxchan = pl022-dma_rx_channel;

   (...)

switch (pl022-read) {
case READING_NULL:
/* Use the same as for writing */
rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
break;
case READING_U8:
rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
break;
case READING_U16:
rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
case READING_U32:
rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
}
rxchan-device-device_control(rxchan, DMA_SLAVE_CONFIG,
   (unsigned long) rx_conf);

I don't know if I'm particularly biased by being infatuated by my own
interface, but can't you just implement the DMA_SLAVE_CONFIG
command for the DW DMA controller instead of this
custom stuff?

 +       dma_cap_zero(mask);
 +       dma_cap_set(DMA_MEMCPY, mask);
 +       dma_cap_set(DMA_SLAVE, mask);

What are you doing? Normally you want *either* a memcpy channel
(which wouldn't require the kind of setup you do above, hell memcpy
shan't be any different from the C library function memcpy()!) *or*
you want a slave channel.

Most probably you should drop dma_cap_set(DMA_MEMCPY, mask),
if it is needed your DMAengine driver is likely weird.

Then I think I get the answer later on:

 +       dws-rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);

Aha generic DMA engine, that's cool! :)

So then again, use the DMA-engine configuration mechanism, and
get the slave channel will ya?

 (...)
 +static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
 (...)
 +       /* 3. start the RX dma transfer */
 +       if (dws-rx_dma) {
 +               rxdesc = rxchan-device-device_prep_dma_memcpy(rxchan,
 +                               dws-rx_dma, dws-dma_addr,
 +                               dws-len, flag);

So you're still using the memcpy() prepare function in order to
be able to supply the endpoint address. Incidentally, that is an
additional argument that you can pass to the generic channel
control mechanism using .src_addr/.dst_addr respectively.

And the DW controller does *indeed* have a
device_prep_slave_sg hook.

My recommendation: put generic channel control into the
DMA driver you're using and inspect amba-pl022.c for an
idea on how to do this.

Since the .device_prep_slave_sg command only takes
SGlists you will have to wrap your buffers in SGlists but
I'm working on a simplifying wrapper for that.

Yours,
Linus Walleij

--
Nokia and ATT present the 2010 Calling All Innovators-North America contest
Create new apps  games for the Nokia N8 for consumers in  U.S. and Canada
$10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing
Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store 
http://p.sf.net/sfu/nokia-dev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[PATCH] dw_spi: add DMA support

2010-10-22 Thread Alan Cox
From: Feng Tang feng.t...@intel.com

dw_spi driver in upstream only supports PIO mode, and this patch
will support it to cowork with the Designware DMA controller used
on Intel Moorestown platform

It has been tested with a Option GTM501L 3G modem, to use DMA mode,
DMA controller 2 of Moorestown has to be enabled

Signed-off-by: Feng Tang feng.t...@intel.com
[Typo fix and renames to match intel_mid_dma renaming]
Signed-off-by: Vinod Koul vinod.k...@intel.com
[Clean up]
Signed-off-by: Feng Tang feng.t...@intel.com
[Fix timing delay, add cpu_relax]
Signed-off-by: Arjan van de Ven ar...@linux.intel.com
Signed-off-by: Alan Cox a...@linux.intel.com
---

 drivers/spi/Kconfig|4 +
 drivers/spi/Makefile   |3 -
 drivers/spi/dw_spi.c   |   48 +
 drivers/spi/dw_spi_mid.c   |  243 
 drivers/spi/dw_spi_pci.c   |   14 ++-
 include/linux/spi/dw_spi.h |   15 +++
 6 files changed, 302 insertions(+), 25 deletions(-)
 create mode 100644 drivers/spi/dw_spi_mid.c


diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 82e45cf..6e6a638 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -404,6 +404,10 @@ config SPI_DW_PCI
tristate PCI interface driver for DW SPI core
depends on SPI_DESIGNWARE  PCI
 
+config SPI_DW_MID_DMA
+   bool DMA support for DW SPI controller on Intel Moorestown platform
+   depends on SPI_DW_PCI  INTEL_MID_DMAC
+
 config SPI_DW_MMIO
tristate Memory-mapped io interface driver for DW SPI core
depends on SPI_DESIGNWARE  HAVE_CLK
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index b427c2e..4949370 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -17,7 +17,8 @@ obj-$(CONFIG_SPI_BUTTERFLY)   += spi_butterfly.o
 obj-$(CONFIG_SPI_COLDFIRE_QSPI)+= coldfire_qspi.o
 obj-$(CONFIG_SPI_DAVINCI)  += davinci_spi.o
 obj-$(CONFIG_SPI_DESIGNWARE)   += dw_spi.o
-obj-$(CONFIG_SPI_DW_PCI)   += dw_spi_pci.o
+obj-$(CONFIG_SPI_DW_PCI)   += dw_spi_midpci.o
+dw_spi_midpci-objs := dw_spi_pci.o dw_spi_mid.o
 obj-$(CONFIG_SPI_DW_MMIO)  += dw_spi_mmio.o
 obj-$(CONFIG_SPI_EP93XX)   += ep93xx_spi.o
 obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 9043931..69cc223 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -164,20 +164,23 @@ static inline void mrst_spi_debugfs_remove(struct dw_spi 
*dws)
 
 static void wait_till_not_busy(struct dw_spi *dws)
 {
-   unsigned long end = jiffies + 1 + usecs_to_jiffies(1000);
+   unsigned long end = jiffies + 1 + usecs_to_jiffies(5000);
 
while (time_before(jiffies, end)) {
if (!(dw_readw(dws, sr)  SR_BUSY))
return;
+   cpu_relax();
}
dev_err(dws-master-dev,
-   DW SPI: Status keeps busy for 1000us after a read/write!\n);
+   DW SPI: Status keeps busy for 5000us after a read/write!\n);
 }
 
 static void flush(struct dw_spi *dws)
 {
-   while (dw_readw(dws, sr)  SR_RF_NOT_EMPT)
+   while (dw_readw(dws, sr)  SR_RF_NOT_EMPT) {
dw_readw(dws, dr);
+   cpu_relax();
+   }
 
wait_till_not_busy(dws);
 }
@@ -285,8 +288,10 @@ static void *next_transfer(struct dw_spi *dws)
  */
 static int map_dma_buffers(struct dw_spi *dws)
 {
-   if (!dws-cur_msg-is_dma_mapped || !dws-dma_inited
-   || !dws-cur_chip-enable_dma)
+   if (!dws-cur_msg-is_dma_mapped
+   || !dws-dma_inited
+   || !dws-cur_chip-enable_dma
+   || !dws-dma_ops)
return 0;
 
if (dws-cur_transfer-tx_dma)
@@ -338,7 +343,7 @@ static void int_error_stop(struct dw_spi *dws, const char 
*msg)
tasklet_schedule(dws-pump_transfers);
 }
 
-static void transfer_complete(struct dw_spi *dws)
+void dw_spi_xfer_done(struct dw_spi *dws)
 {
/* Update total byte transfered return count actual bytes read */
dws-cur_msg-actual_length += dws-len;
@@ -353,6 +358,7 @@ static void transfer_complete(struct dw_spi *dws)
} else
tasklet_schedule(dws-pump_transfers);
 }
+EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
 
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 {
@@ -384,7 +390,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
if (dws-tx_end  dws-tx)
spi_umask_intr(dws, SPI_INT_TXEI);
else
-   transfer_complete(dws);
+   dw_spi_xfer_done(dws);
}
 
return IRQ_HANDLED;
@@ -414,11 +420,7 @@ static void poll_transfer(struct dw_spi *dws)
while (dws-write(dws))
dws-read(dws);
 
-   transfer_complete(dws);
-}
-
-static void dma_transfer(struct dw_spi *dws, int cs_change)
-{
+   dw_spi_xfer_done(dws);
 }