Re: [PATCH RESEND] intel_mid_ssp_spi: Moorestown and Medfield SPI for SSP devices

2012-02-09 Thread Feng Tang
Hi Grant,

On Thu, 9 Feb 2012 07:31:21 -0800
Grant Likely grant.lik...@secretlab.ca wrote:

 On Wed, Feb 08, 2012 at 10:41:10AM +, Alan Cox wrote:
  From: Mathieu SOULARD mathieux.soul...@intel.com
  
  This driver is a fusion of various internal drivers into a single
  driver for the SPI slave/master on the Intel Moorestown and Medfield
  SSP devices.
  
  Signed-off-by: Mathieu SOULARD mathieux.soul...@intel.com
  [Queueing and runtime pm added]
  Signed-off-by: Kristen Carlson Accardi kris...@linux.intel.com
  [Ported to the -next tree DMA engine]
  Signed-off-by: Alan Cox a...@linux.intel.com
  ---
  
   drivers/spi/Kconfig |8 
   drivers/spi/Makefile|2 
   drivers/spi/spi-intel-mid-ssp.c | 1426
  +++ drivers/spi/spi-intel-mid-ssp.h |
  308 
 
 If this is merging several of the drivers, what is the plan for the existing
 SPI_DESIGNWARE and SPI_TOPCLIFF_PCH drivers?  Or are those for different
 devices?

The DESIGNWARE controller has a different HW IP core, so the 2 drivers can't
be merged. And for the TOPCLIFF one, seems it also use a different HW IP than
this one, so I guess it can't be merged either.

Thanks,
Feng

--
Virtualization  Cloud Management Using Capacity Planning
Cloud computing makes use of virtualization - but cloud computing 
also focuses on allowing computing to be delivered as a service.
http://www.accelacomm.com/jaw/sfnl/114/51521223/
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH] spi: spi-dw: fix all sparse warnings

2011-09-20 Thread Feng Tang
On Wed, 21 Sep 2011 04:50:00 +0800
Grant Likely grant.lik...@secretlab.ca wrote:

 On Tue, Sep 20, 2011 at 11:06:17AM -0700, H Hartley Sweeten wrote:
  The dw_{read,write}[lw] macros produce sparse warnings everytime
  they are used.  The read ones cause:
  
  warning: cast removes address space of expression
  warning: incorrect type in argument 1 (different address spaces)
 expected void const volatile [noderef] asn:2*addr
 got unsigned int *noident
  
  And the write ones:
  
  warning: cast removes address space of expression
  warning: incorrect type in argument 2 (different address spaces)
 expected void volatile [noderef] asn:2*addr
 got unsigned int *noident
  
  Fix this by removing struct dw_spi_reg and converting all the
  register offsets to #defines. Then convert the macros into inlined
  functions so that proper type checking can occur.
  
  While here, also fix the three sparse warnings in spi-dw-mid.c due
  to the return value of ioremap_nocache being stored in a u32 * not a
  void __iomem *.
  
  With these changes the spi-dw* files all build with no sparse
  warnings.
  
  Signed-off-by: H Hartley Sweeten hswee...@visionengravers.com
  Cc: Grant Likely grant.lik...@secretlab.ca
 
 Looks good to me.  Feng, does this look okay to you?

Yes, the patch looks good to me, thanks

- Feng
 
 g.
 
  
  ---
  
  diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
  index 130e555..e743a45 100644
  --- a/drivers/spi/spi-dw-mid.c
  +++ b/drivers/spi/spi-dw-mid.c
  @@ -116,13 +116,13 @@ static int mid_spi_dma_transfer(struct dw_spi
  *dws, int cs_change) /* 1. setup DMA related registers */
  if (cs_change) {
  spi_enable_chip(dws, 0);
  -   dw_writew(dws, dmardlr, 0xf);
  -   dw_writew(dws, dmatdlr, 0x10);
  +   dw_writew(dws, DW_SPI_DMARDLR, 0xf);
  +   dw_writew(dws, DW_SPI_DMATDLR, 0x10);
  if (dws-tx_dma)
  dma_ctrl |= 0x2;
  if (dws-rx_dma)
  dma_ctrl |= 0x1;
  -   dw_writew(dws, dmacr, dma_ctrl);
  +   dw_writew(dws, DW_SPI_DMACR, dma_ctrl);
  spi_enable_chip(dws, 1);
  }
   
  @@ -200,7 +200,8 @@ static struct dw_spi_dma_ops mid_dma_ops = {
   
   int dw_spi_mid_init(struct dw_spi *dws)
   {
  -   u32 *clk_reg, clk_cdiv;
  +   void __iomem *clk_reg;
  +   u32 clk_cdiv;
   
  clk_reg = ioremap_nocache(MRST_CLK_SPI0_REG, 16);
  if (!clk_reg)
  diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
  index 0b99320..082458d 100644
  --- a/drivers/spi/spi-dw.c
  +++ b/drivers/spi/spi-dw.c
  @@ -89,35 +89,35 @@ static ssize_t  spi_show_regs(struct file
  *file, char __user *user_buf, len += snprintf(buf + len,
  SPI_REGS_BUFSIZE - len, =\n);
  len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   CTRL0: \t\t0x%08x\n, dw_readl(dws,
  ctrl0));
  +   CTRL0: \t\t0x%08x\n, dw_readl(dws,
  DW_SPI_CTRL0)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   CTRL1: \t\t0x%08x\n, dw_readl(dws,
  ctrl1));
  +   CTRL1: \t\t0x%08x\n, dw_readl(dws,
  DW_SPI_CTRL1)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   SSIENR: \t0x%08x\n, dw_readl(dws,
  ssienr));
  +   SSIENR: \t0x%08x\n, dw_readl(dws,
  DW_SPI_SSIENR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   SER: \t\t0x%08x\n, dw_readl(dws, ser));
  +   SER: \t\t0x%08x\n, dw_readl(dws,
  DW_SPI_SER)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   BAUDR: \t\t0x%08x\n, dw_readl(dws,
  baudr));
  +   BAUDR: \t\t0x%08x\n, dw_readl(dws,
  DW_SPI_BAUDR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   TXFTLR: \t0x%08x\n, dw_readl(dws,
  txfltr));
  +   TXFTLR: \t0x%08x\n, dw_readl(dws,
  DW_SPI_TXFLTR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   RXFTLR: \t0x%08x\n, dw_readl(dws,
  rxfltr));
  +   RXFTLR: \t0x%08x\n, dw_readl(dws,
  DW_SPI_RXFLTR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   TXFLR: \t\t0x%08x\n, dw_readl(dws,
  txflr));
  +   TXFLR: \t\t0x%08x\n, dw_readl(dws,
  DW_SPI_TXFLR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   RXFLR: \t\t0x%08x\n, dw_readl(dws,
  rxflr));
  +   RXFLR: \t\t0x%08x\n, dw_readl(dws,
  DW_SPI_RXFLR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   SR: \t\t0x%08x\n, dw_readl(dws, sr));
  +   SR: \t\t0x%08x\n, dw_readl(dws,
  DW_SPI_SR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   IMR: \t\t0x%08x\n, dw_readl(dws, imr));
  +   IMR: \t\t0x%08x\n, dw_readl(dws,
  DW_SPI_IMR)); len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
  -   ISR: 

[PATCH 1/2] spi_dw: move spi_dw_chip definition to a header file in include/linux/spi/

2011-09-08 Thread Feng Tang
So that it could be used to setup slave device's platform data, when platform
boot code enumerates and registers those spi slave devices.

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/spi-dw.h|   20 +---
 include/linux/spi/spi-dw-platform.h |   23 +++
 2 files changed, 24 insertions(+), 19 deletions(-)
 create mode 100644 include/linux/spi/spi-dw-platform.h

diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 8b7b07b..290688f 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -3,6 +3,7 @@
 
 #include linux/io.h
 #include linux/scatterlist.h
+#include linux/spi/spi-dw-platform.h
 
 /* Bit fields in CTRLR0 */
 #define SPI_DFS_OFFSET 0
@@ -49,12 +50,6 @@
 /* TX RX interrupt level threshold, max can be 256 */
 #define SPI_INT_THRESHOLD  32
 
-enum dw_ssi_type {
-   SSI_MOTO_SPI = 0,
-   SSI_TI_SSP,
-   SSI_NS_MICROWIRE,
-};
-
 struct dw_spi_reg {
u32 ctrl0;
u32 ctrl1;
@@ -209,19 +204,6 @@ static inline void spi_umask_intr(struct dw_spi *dws, u32 
mask)
dw_writel(dws, imr, new_mask);
 }
 
-/*
- * Each SPI slave device to work with dw_api controller should
- * has such a structure claiming its working mode (PIO/DMA etc),
- * which can be save in the controller_data member of the
- * struct spi_device
- */
-struct dw_spi_chip {
-   u8 poll_mode;   /* 0 for contoller polling mode */
-   u8 type;/* SPI/SSP/Micrwire */
-   u8 enable_dma;
-   void (*cs_control)(u32 command);
-};
-
 extern int dw_spi_add_host(struct dw_spi *dws);
 extern void dw_spi_remove_host(struct dw_spi *dws);
 extern int dw_spi_suspend_host(struct dw_spi *dws);
diff --git a/include/linux/spi/spi-dw-platform.h 
b/include/linux/spi/spi-dw-platform.h
new file mode 100644
index 000..7c283c6
--- /dev/null
+++ b/include/linux/spi/spi-dw-platform.h
@@ -0,0 +1,23 @@
+#ifndef SPI_DW_PLATFORM_HEADER_H
+#define SPI_DW_PLATFORM_HEADER_H
+
+enum dw_ssi_type {
+   SSI_MOTO_SPI = 0,
+   SSI_TI_SSP,
+   SSI_NS_MICROWIRE,
+};
+
+/*
+ * Each SPI slave device to work with dw_api controller should
+ * has such a structure claiming its working mode (PIO/DMA etc),
+ * which can be save in the controller_data member of the
+ * struct spi_device
+ */
+struct dw_spi_chip {
+   u8 poll_mode;   /* 0 for contoller polling mode */
+   u8 type;/* SPI/SSP/Micrwire */
+   u8 enable_dma;
+   void (*cs_control)(u32 command);
+};
+
+#endif /* SPI_DW_PLATFORM_HEADER_H */
-- 
1.7.1


--
Doing More with Less: The Next Generation Virtual Desktop 
What are the key obstacles that have prevented many mid-market businesses
from deploying virtual desktops?   How do next-generation virtual desktops
provide companies an easier-to-deploy, easier-to-manage and more affordable
virtual desktop model.http://www.accelacomm.com/jaw/sfnl/114/51426474/
___
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 spi number into spi irq desc

2011-07-07 Thread Feng Tang
Hi Shuo,

Looks ok to me, and thanks for the fix. One nit is do we have to use a char[48]
for the name?

Thanks,
Feng

On Fri, 8 Jul 2011 11:51:05 +0800
Liu, ShuoX shuox@intel.com wrote:

 From 2efa9dbb5c4b1d8fa798d1792498ae21fc3a9d04 Mon Sep 17 00:00:00 2001
 From: ShuoX Liu shuox@intel.com
 Date: Thu, 7 Jul 2011 16:09:41 +0800
 Subject: [PATCH] dw_spi: Add spi number into spi irq desc
 
 Signed-off-by: ShuoX Liu shuox@intel.com
 ---
  drivers/spi/dw_spi.c |4 +++-
  drivers/spi/dw_spi.h |1 +
  2 files changed, 4 insertions(+), 1 deletions(-)
 
 diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
 index 919fa9d..68a3026 100644
 --- a/drivers/spi/dw_spi.c
 +++ b/drivers/spi/dw_spi.c
 @@ -818,9 +818,11 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
   dws-prev_chip = NULL;
   dws-dma_inited = 0;
   dws-dma_addr = (dma_addr_t)(dws-paddr + 0x60);
 + snprintf(dws-name, sizeof(dws-name), dw_spi%d,
 + dws-bus_num);
  
   ret = request_irq(dws-irq, dw_spi_irq, IRQF_SHARED,
 - dw_spi, dws);
 + dws-name, dws);
   if (ret  0) {
   dev_err(master-dev, can not get IRQ\n);
   goto err_free_master;
 diff --git a/drivers/spi/dw_spi.h b/drivers/spi/dw_spi.h
 index 7a5e78d..c7b9165 100644
 --- a/drivers/spi/dw_spi.h
 +++ b/drivers/spi/dw_spi.h
 @@ -96,6 +96,7 @@ struct dw_spi {
   struct spi_device   *cur_dev;
   struct device   *parent_dev;
   enum dw_ssi_typetype;
 + charname[48];
  
   void __iomem*regs;
   unsigned long   paddr;



--
All of the data generated in your IT infrastructure is seriously valuable.
Why? It contains a definitive record of application performance, security 
threats, fraudulent activity, and more. Splunk takes this data and makes 
sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-d2d-c2
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH 00/11] RFC spi-dw updates

2011-06-22 Thread Feng Tang
Hi Dirk,

On Thu, 23 Jun 2011 10:00:02 +0800
dirk.brande...@gmail.com dirk.brande...@gmail.com wrote:

 From: Dirk Brandewie dirk.brande...@gmail.com
 
 This patch set contains a number of changes were buried inside of one
 large patch in my last patch set.  The rework of the message/transfer
 handling changes are not part of this patch set.
 
 
 This patch set applies after commit ca632f5 on spi/next
 
 
 Dirk Brandewie (11):
   spi-dw: expose platform data stucture.
   spi-dw: update function naming convention to match file naming
   spi-dw: change MRST prefix to generic prefix
   spi-dw: remove unused definition
   spi-dw: split spi_dw_enable_chip() into
 spi_dw_enable()/spi_dw_disable() spi-dw: Force error on out of range
 chip select. spi-dw: Set number of available chip selects correctly
   spi-dw: Ensure fifo lenght is set.
   spi-dw: Fix condition in spi_dw_{writer/reader}
   spi-dw: Move checking of max_speed_hz value to be a prerequisite in
 spi_dw_setup spi-dw: remove noop else clause

Most of the patches looks good to me, I'll reply to the rest separately.

Thanks,
Feng

 
  drivers/spi/spi-dw-mid.c   |   30 +++---
  drivers/spi/spi-dw-mmio.c  |   38 
  drivers/spi/spi-dw-pci.c   |   34 +++---
  drivers/spi/spi-dw.c   |  247
 
 drivers/spi/spi-dw.h   |   82 ++-
 include/linux/spi/spi-dw.h |   42  6 files changed, 241
 insertions(+), 232 deletions(-) create mode 100644
 include/linux/spi/spi-dw.h
 

--
Simplify data backup and recovery for your virtual environment with vRanger.
Installation's a snap, and flexible recovery options mean your data is safe,
secure and there when you need it. Data protection magic?
Nope - It's vRanger. Get your free trial download today.
http://p.sf.net/sfu/quest-sfdev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH 08/11] spi-dw: Ensure fifo lenght is set.

2011-06-22 Thread Feng Tang


On Thu, 23 Jun 2011 10:00:10 +0800
dirk.brande...@gmail.com dirk.brande...@gmail.com wrote:

 From: Dirk Brandewie dirk.brande...@gmail.com
 
 Bug on fifo_len not being set.  The fifo sizing routine does not work
 since the txfltr register can not be written while the controller is
 enabled. The max value of txfltr can be larger than the fifo.  The
 register allows values upto 0x3f (63) the fifo depth on the Intel
 SOC's if 40
 
 Signed-off-by: Dirk Brandewie dirk.brande...@gmail.com
 ---
  drivers/spi/spi-dw.c |   18 ++
  1 files changed, 2 insertions(+), 16 deletions(-)
 
 diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
 index ad92826..cc38aa0 100644
 --- a/drivers/spi/spi-dw.c
 +++ b/drivers/spi/spi-dw.c
 @@ -776,25 +776,11 @@ static int destroy_queue(struct spi_dw *dws)
  /* Restart the controller, disable all interrupts, clean rx fifo */
  static void spi_dw_hw_init(struct spi_dw *dws)
  {
 + BUG_ON(!dws-fifo_len);
 +
   spi_dw_disable(dws);
   spi_dw_mask_intr(dws, 0xff);
   spi_dw_enable(dws);
 -
 - /*
 -  * Try to detect the FIFO depth if not set by interface
 driver,
 -  * the depth could be from 2 to 256 from HW spec
 -  */
 - if (!dws-fifo_len) {
 - u32 fifo;
 - for (fifo = 2; fifo = 257; fifo++) {
 - dw_writew(dws, txfltr, fifo);
 - if (fifo != dw_readw(dws, txfltr))
 - break;
 - }
 -
 - dws-fifo_len = (fifo == 257) ? 0 : fifo;
 - dw_writew(dws, txfltr, 0);
 - }
  }

This code is requested by other community developers, the FIFO
length is adjustable for the dw_spi core when deployed on
different platforms, for those who are not certain about the
FIFO len, they can use this code to probe the FIFO len.

So we need to keep it.

  
  int __devinit spi_dw_add_host(struct spi_dw *dws)

--
Simplify data backup and recovery for your virtual environment with vRanger.
Installation's a snap, and flexible recovery options mean your data is safe,
secure and there when you need it. Data protection magic?
Nope - It's vRanger. Get your free trial download today.
http://p.sf.net/sfu/quest-sfdev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH 09/11] spi-dw: Fix condition in spi_dw_{writer/reader}

2011-06-22 Thread Feng Tang
On Thu, 23 Jun 2011 10:00:11 +0800
dirk.brande...@gmail.com dirk.brande...@gmail.com wrote:

 From: Dirk Brandewie dirk.brande...@gmail.com
 
 Fix the condition based on whether the current transfer has a tx/rx
 buffer.
 
 Signed-off-by: Dirk Brandewie dirk.brande...@gmail.com
 ---
  drivers/spi/spi-dw.c |6 +++---
  1 files changed, 3 insertions(+), 3 deletions(-)
 
 diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
 index cc38aa0..35b952b 100644
 --- a/drivers/spi/spi-dw.c
 +++ b/drivers/spi/spi-dw.c
 @@ -193,8 +193,8 @@ static void spi_dw_writer(struct spi_dw *dws)
   u16 txw = 0;
  
   while (max--) {
 - /* Set the tx word if the transfer's original tx
 is not null */
 - if (dws-tx_end - dws-len) {
 + /* Set the tx word if the transfer's tx is not
 null */
 + if (dws-tx) {

No, in current mainstream code, the dws-tx is changing, see code:
dws-tx += dws-n_bytes;
so we have to use if (dws-tx_end - dws-len) for now, maybe
we can use some bit to indicate whether the original tx is null

   if (dws-n_bytes == 1)
   txw = *(u8 *)(dws-tx);
   else
 @@ -213,7 +213,7 @@ static void spi_dw_reader(struct spi_dw *dws)
   while (max--) {
   rxw = dw_readw(dws, dr);
   /* Care rx only if the transfer's original rx is
 not null */
 - if (dws-rx_end - dws-len) {
 + if (dws-rx) {
   if (dws-n_bytes == 1)
   *(u8 *)(dws-rx) = rxw;
   else

--
Simplify data backup and recovery for your virtual environment with vRanger.
Installation's a snap, and flexible recovery options mean your data is safe,
secure and there when you need it. Data protection magic?
Nope - It's vRanger. Get your free trial download today.
http://p.sf.net/sfu/quest-sfdev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH 11/11] spi-dw: remove noop else clause

2011-06-22 Thread Feng Tang
On Thu, 23 Jun 2011 10:00:13 +0800
dirk.brande...@gmail.com dirk.brande...@gmail.com wrote:

 From: Dirk Brandewie dirk.brande...@gmail.com
 
 The value of spi-bits_per_word is checked on function entry to be 8
 or 16.  The else clause has no meaning since it can never be reached.
 
 Signed-off-by: Dirk Brandewie dirk.brande...@gmail.com
 ---
  drivers/spi/spi-dw.c |9 +++--
  1 files changed, 3 insertions(+), 6 deletions(-)
 
 diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
 index 7b3f607..5ddd45f 100644
 --- a/drivers/spi/spi-dw.c
 +++ b/drivers/spi/spi-dw.c
 @@ -667,17 +667,14 @@ static int spi_dw_setup(struct spi_device *spi)
   chip-enable_dma = chip_info-enable_dma;
   }
  
 - if (spi-bits_per_word = 8) {
 + if (spi-bits_per_word == 8) {
   chip-n_bytes = 1;
   chip-dma_width = 1;
 - } else if (spi-bits_per_word = 16) {
 + } else if (spi-bits_per_word == 16) {
   chip-n_bytes = 2;
   chip-dma_width = 2;
 - } else {
 - /* Never take 16b case for DW SPIC */
 - dev_err(spi-dev, invalid wordsize\n);
 - return -EINVAL;
   }

These else case is used to ban the slave spi devices which
try to use 32 bits per word mode. This is like to tell those
spi devices with 32 bpw capability we don't support 32b, pls
change

 +
   chip-bits_per_word = spi-bits_per_word;
  
   chip-speed_hz = spi-max_speed_hz;

--
Simplify data backup and recovery for your virtual environment with vRanger.
Installation's a snap, and flexible recovery options mean your data is safe,
secure and there when you need it. Data protection magic?
Nope - It's vRanger. Get your free trial download today.
http://p.sf.net/sfu/quest-sfdev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH 08/11] spi-dw: Ensure fifo lenght is set.

2011-06-22 Thread Feng Tang
On Thu, 23 Jun 2011 11:01:25 +0800
Dirk Brandewie dirk.brande...@gmail.com wrote:


  -  /*
  -   * Try to detect the FIFO depth if not set by interface
  driver,
  -   * the depth could be from 2 to 256 from HW spec
  -   */
  -  if (!dws-fifo_len) {
  -  u32 fifo;
  -  for (fifo = 2; fifo= 257; fifo++) {
  -  dw_writew(dws, txfltr, fifo);
  -  if (fifo != dw_readw(dws, txfltr))
  -  break;
  -  }
  -
  -  dws-fifo_len = (fifo == 257) ? 0 : fifo;
  -  dw_writew(dws, txfltr, 0);
  -  }
}
 
  This code is requested by other community developers, the FIFO
  length is adjustable for the dw_spi core when deployed on
  different platforms, for those who are not certain about the
  FIFO len, they can use this code to probe the FIFO len.
 
  So we need to keep it.
 
 
 Then I have bad documentation because document I have says that you
 can NOt write to txfltr while the controller is enabled.  The sizing
 routine as it stands can't work for the implementation in Moorsetown
 and Medfield.
 
 If there are other SOC's that are implementing different semantics
 for txfltr we will need to handle this differently and do some
 runtime detection of how the fifo should be sized.
 
 Can you give ne a reference to the person that requiested the sizing
 code so I can follow-up

Git-show c587b6fa0510

commit c587b6fa05106606053fc5e8e344f07cd34ace23
Author: Feng Tang feng.t...@intel.com
Date:   Thu Jan 21 10:41:10 2010 +0800

spi/dw_spi: add a FIFO depth detection

FIFO depth is configurable for each implementation of DW core,
so add a depth detection for those interface drivers who don't set
the fifo_len explicitly

Signed-off-by: Feng Tang feng.t...@intel.com
Acked-by: Jean-Hugues Deschenes jean-hugues.desche...@octasic.com
Signed-off-by: Grant Likely grant.lik...@secretlab.ca

I added the code per request from Jean-Hugues Deschenes.

Recently Alek Du has tested this code on his Medfield platform.

Thanks,
Feng

--
Simplify data backup and recovery for your virtual environment with vRanger.
Installation's a snap, and flexible recovery options mean your data is safe,
secure and there when you need it. Data protection magic?
Nope - It's vRanger. Get your free trial download today.
http://p.sf.net/sfu/quest-sfdev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH 09/11] spi-dw: Fix condition in spi_dw_{writer/reader}

2011-06-22 Thread Feng Tang
On Thu, 23 Jun 2011 11:09:34 +0800
Dirk Brandewie dirk.brande...@gmail.com wrote:

 On 06/22/2011 07:45 PM, Feng Tang wrote:
  On Thu, 23 Jun 2011 10:00:11 +0800
  dirk.brande...@gmail.comdirk.brande...@gmail.com  wrote:
 
  From: Dirk Brandewiedirk.brande...@gmail.com
 
  Fix the condition based on whether the current transfer has a tx/rx
  buffer.
 
  Signed-off-by: Dirk Brandewiedirk.brande...@gmail.com
  ---
drivers/spi/spi-dw.c |6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
 
  diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
  index cc38aa0..35b952b 100644
  --- a/drivers/spi/spi-dw.c
  +++ b/drivers/spi/spi-dw.c
  @@ -193,8 +193,8 @@ static void spi_dw_writer(struct spi_dw *dws)
 u16 txw = 0;
 
 while (max--) {
  -  /* Set the tx word if the transfer's original tx
  is not null */
  -  if (dws-tx_end - dws-len) {
  +  /* Set the tx word if the transfer's tx is not
  null */
  +  if (dws-tx) {
 
  No, in current mainstream code, the dws-tx is changing, see code:
  dws-tx += dws-n_bytes;
  so we have to use if (dws-tx_end - dws-len) for now, maybe
  we can use some bit to indicate whether the original tx is null
 
 If dws-tx is non-null then it points to a valid buffer, it is
 unconditionally set with dws-tx = (void *)transfer-tx_buf when the
 transfer is setup.  if the original transfer-tx_buf is non-null then
 this change works.

dws-tx is changing as I said, non-null doesn't mean the value is valid,
when the original tx is null, we don't access it at all, it's just a
indicator of whether the dws-len of zeor has been filled to FIFO.

This logic may looks confusing, but it's correct after years of test.

 
 
 if (dws-n_bytes == 1)
 txw = *(u8 *)(dws-tx);
 else
  @@ -213,7 +213,7 @@ static void spi_dw_reader(struct spi_dw *dws)
 while (max--) {
 rxw = dw_readw(dws, dr);
 /* Care rx only if the transfer's original rx
  is not null */
  -  if (dws-rx_end - dws-len) {
  +  if (dws-rx) {
 if (dws-n_bytes == 1)
 *(u8 *)(dws-rx) = rxw;
 else
 

--
Simplify data backup and recovery for your virtual environment with vRanger.
Installation's a snap, and flexible recovery options mean your data is safe,
secure and there when you need it. Data protection magic?
Nope - It's vRanger. Get your free trial download today.
http://p.sf.net/sfu/quest-sfdev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH 3/5] dw_spi: rework message processing

2011-06-16 Thread Feng Tang
On Fri, 17 Jun 2011 01:28:16 +0800
Dirk Brandewie dirk.brande...@gmail.com wrote:

 On 06/16/2011 07:00 AM, Feng Tang wrote:
  Hi Dirk,
 
  IMHO, the patch is too big, it contains too many changes to the
  original drivers, and we can't see clearly what you've changed to
  each logical code part or section, If possible, could you separate
  this patch to several small ones in a logical way.
 
  First, I have some questions, what devices have you tested with
  this patch? high speed, low speed? Do you have any performance data
  to show the benefit of this change? Current dw_spi driver has been
  tested with many devices, so to not break them or cause obvious
  regression, we have to be cautious.
 
 See Thread with grant for list of environments where it has been
 tested. The boot time of the platforms it is being used on decreased
 2-5 seconds with no regressions reported.  It has been in use/under
 test for ~3 months in various Meego and Android builds.  It clears
 all the bugs reported against the driver that I am aware of.  If you
 can give me pointers to teams/projects that are using v2.6.37+
 kernels I would be more that happy to provide them with patches for
 their kernel to ensure we get the most comprehensive test possible.

I was not asking about the environments, but the actual devices connect.
to and work with the dw_spi controller, here is a quote from one of
my previous email of devices listing:


I don't know all the devices and users, but here is what I know: I've tested
Max3110 spi-uart (in-tree), Option GTM501L high-speed 3G modem (out of tree),
ektf1236 spi touch screen (out of tree). Alek Du (Cced) should have tested
current dw_spi driver with some spi bluetooth device and modem device. Also
the original author fordw_spi_mmio.c Jean-Hugues Deschense should have some
experience too. 
-
Meego or Android doesn't mean much for a device driver, as all these OSes are
using the same Linux kernel.

Is 2-5 seconds boot time cuts the only performance data you got? The current
driver has 2 phases, first is the original one from me, the second is the 
optimization by Alek Du which introduce the batch operation for TX/RX FIFO, 
Alek mentioned the boot time cut too, so I guess the boot time gain is tested
against the original driver, not the current mainstream driver, right?

For the kernel version you mentioned, my thought is the kernel version diff
between 2.6.35 and 2.6.37 doesn't mean much to a simple dw_spi device driver's
performance? some users of dw_spi driver are still using 2.6.35 kernel with
all new optimizations back ported, I have no power to force them upgrade the
kernel, but if the dw_spi driver is the same, then the performance data is
mostly trustable.

 
 
  Here are some general comments according to the commit logs:
  1. I think the threaded irq handling is a good idea. And let driver
  chose to use poll or interrupt is good, some other spi controller
  driver has used that way for a long time
  2. Why you remove the cs_change code, in some case, the controller
  is only be used by one device, we don't need do the config for
  every single spi_transfer
 
 There is no guarantee that all the transfers in a given spi_message
 have the same values for  speed_hz, bits_per_word, cs_change and
 delay_usecs atleast nothing I could find put that restriction in
 place. Since we need to deal with possible changes (although
 unlikely) it gets rid some state we need to maintain and makes the
 code path common for all transfers.

right, if you look at the driver, cs_change is only judge condition
for judge, speed_hz, bits_per_word's change are counted in too. Otherwise
the driver should fail years ago.

 
  3. Why do you remove the chip select control code, dw_spi
  controller hw has some problem in chip select controller by SER,
  and thus many devices has to use external GPIO has their chip
  select, this is real world usages!
 
 Which devices/platforms are you referring to?  I was unable to find
 any platforms or client drivers using this functionality. If they are
 not public please respond internally.  In any case it is mute since I
 already agreed to put is back in in my response to Grant.

Some intel platforms used/are using that, I got requests to help them
on it. Also some community guys are using that (though I don't know the
detail),  as this piece of code is introduced by Shore George once made
some change according to their specific change, see commit 052dc7c4

 
  4. I saw you enable both TX/RX interrupt when doing interrupt
  transfer, spi devices' TX/RX are born to be simutaneous, when one
  word is sent over TX line, a RX word will be received from RX line,
  so both the orignal interrupt transfer handling written by me and
  the later optimization from Alek Du only enable TX interrupt, which
  will only generate half of IRQs

[PATCH v2 2/4] spi/dw_spi: remove the un-necessary flush()

2011-03-30 Thread Feng Tang
From: Alek Du alek...@intel.com

The flush() is used to drain all the left data in rx fifo, currently
is is always called together with disabling hw. But from spec, disabling
hw will also reset all the fifo, so flush() is not needed.

Signed-off-by: Alek Du alek...@intel.com
Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi.c |   15 +--
 1 files changed, 1 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index c4fca3d..d3aaf8d 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -173,17 +173,6 @@ static void wait_till_not_busy(struct dw_spi *dws)
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) {
-   dw_readw(dws, dr);
-   cpu_relax();
-   }
-
-   wait_till_not_busy(dws);
-}
-
-
 static int dw_writer(struct dw_spi *dws)
 {
u16 txw = 0;
@@ -297,8 +286,7 @@ static void giveback(struct dw_spi *dws)
 
 static void int_error_stop(struct dw_spi *dws, const char *msg)
 {
-   /* Stop and reset hw */
-   flush(dws);
+   /* Stop the hw */
spi_enable_chip(dws, 0);
 
dev_err(dws-master-dev, %s\n, msg);
@@ -800,7 +788,6 @@ static void spi_hw_init(struct dw_spi *dws)
spi_enable_chip(dws, 0);
spi_mask_intr(dws, 0xff);
spi_enable_chip(dws, 1);
-   flush(dws);
 
/*
 * Try to detect the FIFO depth if not set by interface driver,
-- 
1.7.0.4


--
Create and publish websites with WebMatrix
Use the most popular FREE web apps or write code yourself; 
WebMatrix provides all the features you need to develop and 
publish your website. http://p.sf.net/sfu/ms-webmatrix-sf
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[PATCH v2 1/4] spi/dw_spi: unify the low level read/write routines

2011-03-30 Thread Feng Tang
The original version has many duplicated codes for null/u8/u16 case,
so unify them to make it cleaner

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi.c |  103 +-
 drivers/spi/dw_spi.h |2 -
 2 files changed, 26 insertions(+), 79 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 9a61964..c4fca3d 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -58,8 +58,6 @@ struct chip_data {
u8 bits_per_word;
u16 clk_div;/* baud rate divider */
u32 speed_hz;   /* baud rate */
-   int (*write)(struct dw_spi *dws);
-   int (*read)(struct dw_spi *dws);
void (*cs_control)(u32 command);
 };
 
@@ -185,80 +183,45 @@ static void flush(struct dw_spi *dws)
wait_till_not_busy(dws);
 }
 
-static int null_writer(struct dw_spi *dws)
-{
-   u8 n_bytes = dws-n_bytes;
-
-   if (!(dw_readw(dws, sr)  SR_TF_NOT_FULL)
-   || (dws-tx == dws-tx_end))
-   return 0;
-   dw_writew(dws, dr, 0);
-   dws-tx += n_bytes;
 
-   wait_till_not_busy(dws);
-   return 1;
-}
-
-static int null_reader(struct dw_spi *dws)
+static int dw_writer(struct dw_spi *dws)
 {
-   u8 n_bytes = dws-n_bytes;
+   u16 txw = 0;
 
-   while ((dw_readw(dws, sr)  SR_RF_NOT_EMPT)
-(dws-rx  dws-rx_end)) {
-   dw_readw(dws, dr);
-   dws-rx += n_bytes;
-   }
-   wait_till_not_busy(dws);
-   return dws-rx == dws-rx_end;
-}
-
-static int u8_writer(struct dw_spi *dws)
-{
if (!(dw_readw(dws, sr)  SR_TF_NOT_FULL)
|| (dws-tx == dws-tx_end))
return 0;
 
-   dw_writew(dws, dr, *(u8 *)(dws-tx));
-   ++dws-tx;
-
-   wait_till_not_busy(dws);
-   return 1;
-}
-
-static int u8_reader(struct dw_spi *dws)
-{
-   while ((dw_readw(dws, sr)  SR_RF_NOT_EMPT)
-(dws-rx  dws-rx_end)) {
-   *(u8 *)(dws-rx) = dw_readw(dws, dr);
-   ++dws-rx;
+   /* Set the tx word if the transfer's original tx is not null */
+   if (dws-tx_end - dws-len) {
+   if (dws-n_bytes == 1)
+   txw = *(u8 *)(dws-tx);
+   else
+   txw = *(u16 *)(dws-tx);
}
 
-   wait_till_not_busy(dws);
-   return dws-rx == dws-rx_end;
-}
-
-static int u16_writer(struct dw_spi *dws)
-{
-   if (!(dw_readw(dws, sr)  SR_TF_NOT_FULL)
-   || (dws-tx == dws-tx_end))
-   return 0;
-
-   dw_writew(dws, dr, *(u16 *)(dws-tx));
-   dws-tx += 2;
+   dw_writew(dws, dr, txw);
+   dws-tx += dws-n_bytes;
 
wait_till_not_busy(dws);
return 1;
 }
 
-static int u16_reader(struct dw_spi *dws)
+static int dw_reader(struct dw_spi *dws)
 {
-   u16 temp;
+   u16 rxw;
 
while ((dw_readw(dws, sr)  SR_RF_NOT_EMPT)
 (dws-rx  dws-rx_end)) {
-   temp = dw_readw(dws, dr);
-   *(u16 *)(dws-rx) = temp;
-   dws-rx += 2;
+   rxw = dw_readw(dws, dr);
+   /* Care rx only if the transfer's original rx is not null */
+   if (dws-rx_end - dws-len) {
+   if (dws-n_bytes == 1)
+   *(u8 *)(dws-rx) = rxw;
+   else
+   *(u16 *)(dws-rx) = rxw;
+   }
+   dws-rx += dws-n_bytes;
}
 
wait_till_not_busy(dws);
@@ -383,8 +346,8 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
left = (left  int_level) ? int_level : left;
 
while (left--)
-   dws-write(dws);
-   dws-read(dws);
+   dw_writer(dws);
+   dw_reader(dws);
 
/* Re-enable the IRQ if there is still data left to tx */
if (dws-tx_end  dws-tx)
@@ -417,13 +380,13 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 /* Must be called inside pump_transfers() */
 static void poll_transfer(struct dw_spi *dws)
 {
-   while (dws-write(dws))
-   dws-read(dws);
+   while (dw_writer(dws))
+   dw_reader(dws);
/*
 * There is a possibility that the last word of a transaction
 * will be lost if data is not ready. Re-read to solve this issue.
 */
-   dws-read(dws);
+   dw_reader(dws);
 
dw_spi_xfer_done(dws);
 }
@@ -483,8 +446,6 @@ static void pump_transfers(unsigned long data)
dws-tx_end = dws-tx + transfer-len;
dws-rx = transfer-rx_buf;
dws-rx_end = dws-rx + transfer-len;
-   dws-write = dws-tx ? chip-write : null_writer;
-   dws-read = dws-rx ? chip-read : null_reader;
dws-cs_change = transfer-cs_change;
dws-len = dws-cur_transfer-len;
if (chip != dws-prev_chip)
@@ -520,18 +481,10 @@ static void pump_transfers(unsigned

[PATCH v2 0/4] patch serie for dw_spi driver

2011-03-30 Thread Feng Tang
Hi all,

Alek Du made some optimization for the dw_spi driver, the original driver
will wait for non-busy state after every work of read/write. With these
patches, driver will read/write as much as possible data from/to the HW
FIFO. The DMA mode transfer is not affected at all. There is also some
minor code cleanup.

Pls help to review, thanks!

v2 change:
* fix a typo about bits_per_word checking 
* re-generate the patches against v2.6.39-rc1

Thanks,
Feng
-

Alek Du (3):
  spi/dw_spi: remove the un-necessary flush()
  spi/dw_spi: change poll mode transfer from byte ops to batch ops
  spi/dw_spi: improve the interrupt mode with the batch ops

Feng Tang (1):
  spi/dw_spi: unify the low level read/write routines

 drivers/spi/dw_spi.c |  202 -
 drivers/spi/dw_spi.h |2 -
 2 files changed, 66 insertions(+), 138 deletions(-)


--
Create and publish websites with WebMatrix
Use the most popular FREE web apps or write code yourself; 
WebMatrix provides all the features you need to develop and 
publish your website. http://p.sf.net/sfu/ms-webmatrix-sf
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[PATCH v2 3/4] spi/dw_spi: change poll mode transfer from byte ops to batch ops

2011-03-30 Thread Feng Tang
From: Alek Du alek...@intel.com

Current poll transfer will read/write one word, then wait till the
hw is non-busy, it's not efficient. This patch will try to read/write
as many words as permitted by hardware FIFO depth.

Signed-off-by: Alek Du alek...@intel.com
Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi.c |   71 +
 1 files changed, 48 insertions(+), 23 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index d3aaf8d..7a2a722 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -160,6 +160,37 @@ static inline void mrst_spi_debugfs_remove(struct dw_spi 
*dws)
 }
 #endif /* CONFIG_DEBUG_FS */
 
+/* Return the max entries we can fill into tx fifo */
+static inline u32 tx_max(struct dw_spi *dws)
+{
+   u32 tx_left, tx_room, rxtx_gap;
+
+   tx_left = (dws-tx_end - dws-tx) / dws-n_bytes;
+   tx_room = dws-fifo_len - dw_readw(dws, txflr);
+
+   /*
+* Another concern is about the tx/rx mismatch, we
+* though to use (dws-fifo_len - rxflr - txflr) as
+* one maximum value for tx, but it doesn't cover the
+* data which is out of tx/rx fifo and inside the
+* shift registers. So a control from sw point of
+* view is taken.
+*/
+   rxtx_gap =  ((dws-rx_end - dws-rx) - (dws-tx_end - dws-tx))
+   / dws-n_bytes;
+
+   return min3(tx_left, tx_room, (u32) (dws-fifo_len - rxtx_gap));
+}
+
+/* Return the max entries we should read out of rx fifo */
+static inline u32 rx_max(struct dw_spi *dws)
+{
+   u32 rx_left = (dws-rx_end - dws-rx) / dws-n_bytes;
+
+   return min(rx_left, (u32)dw_readw(dws, rxflr));
+}
+
+
 static void wait_till_not_busy(struct dw_spi *dws)
 {
unsigned long end = jiffies + 1 + usecs_to_jiffies(5000);
@@ -175,33 +206,30 @@ static void wait_till_not_busy(struct dw_spi *dws)
 
 static int dw_writer(struct dw_spi *dws)
 {
+   u32 max = tx_max(dws);
u16 txw = 0;
 
-   if (!(dw_readw(dws, sr)  SR_TF_NOT_FULL)
-   || (dws-tx == dws-tx_end))
-   return 0;
-
-   /* Set the tx word if the transfer's original tx is not null */
-   if (dws-tx_end - dws-len) {
-   if (dws-n_bytes == 1)
-   txw = *(u8 *)(dws-tx);
-   else
-   txw = *(u16 *)(dws-tx);
+   while (max--) {
+   /* Set the tx word if the transfer's original tx is not null 
*/
+   if (dws-tx_end - dws-len) {
+   if (dws-n_bytes == 1)
+   txw = *(u8 *)(dws-tx);
+   else
+   txw = *(u16 *)(dws-tx);
+   }
+   dw_writew(dws, dr, txw);
+   dws-tx += dws-n_bytes;
}
 
-   dw_writew(dws, dr, txw);
-   dws-tx += dws-n_bytes;
-
-   wait_till_not_busy(dws);
return 1;
 }
 
 static int dw_reader(struct dw_spi *dws)
 {
+   u32 max = rx_max(dws);
u16 rxw;
 
-   while ((dw_readw(dws, sr)  SR_RF_NOT_EMPT)
-(dws-rx  dws-rx_end)) {
+   while (max--) {
rxw = dw_readw(dws, dr);
/* Care rx only if the transfer's original rx is not null */
if (dws-rx_end - dws-len) {
@@ -213,7 +241,6 @@ static int dw_reader(struct dw_spi *dws)
dws-rx += dws-n_bytes;
}
 
-   wait_till_not_busy(dws);
return dws-rx == dws-rx_end;
 }
 
@@ -368,13 +395,11 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 /* Must be called inside pump_transfers() */
 static void poll_transfer(struct dw_spi *dws)
 {
-   while (dw_writer(dws))
+   do {
+   dw_writer(dws);
dw_reader(dws);
-   /*
-* There is a possibility that the last word of a transaction
-* will be lost if data is not ready. Re-read to solve this issue.
-*/
-   dw_reader(dws);
+   cpu_relax();
+   } while (dws-rx_end  dws-rx);
 
dw_spi_xfer_done(dws);
 }
-- 
1.7.0.4


--
Create and publish websites with WebMatrix
Use the most popular FREE web apps or write code yourself; 
WebMatrix provides all the features you need to develop and 
publish your website. http://p.sf.net/sfu/ms-webmatrix-sf
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[PATCH v2 4/4] spi/dw_spi: improve the interrupt mode with the batch ops

2011-03-30 Thread Feng Tang
From: Alek Du alek...@intel.com

leverage the performance gain by change in low level
read/write batch operations

Signed-off-by: Alek Du alek...@intel.com
Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi.c |   63 -
 1 files changed, 16 insertions(+), 47 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 7a2a722..855ac4a 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -190,21 +190,7 @@ static inline u32 rx_max(struct dw_spi *dws)
return min(rx_left, (u32)dw_readw(dws, rxflr));
 }
 
-
-static void wait_till_not_busy(struct dw_spi *dws)
-{
-   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 5000us after a read/write!\n);
-}
-
-static int dw_writer(struct dw_spi *dws)
+static void dw_writer(struct dw_spi *dws)
 {
u32 max = tx_max(dws);
u16 txw = 0;
@@ -220,11 +206,9 @@ static int dw_writer(struct dw_spi *dws)
dw_writew(dws, dr, txw);
dws-tx += dws-n_bytes;
}
-
-   return 1;
 }
 
-static int dw_reader(struct dw_spi *dws)
+static void dw_reader(struct dw_spi *dws)
 {
u32 max = rx_max(dws);
u16 rxw;
@@ -240,8 +224,6 @@ static int dw_reader(struct dw_spi *dws)
}
dws-rx += dws-n_bytes;
}
-
-   return dws-rx == dws-rx_end;
 }
 
 static void *next_transfer(struct dw_spi *dws)
@@ -340,35 +322,28 @@ EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
 
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 {
-   u16 irq_status, irq_mask = 0x3f;
-   u32 int_level = dws-fifo_len / 2;
-   u32 left;
+   u16 irq_status = dw_readw(dws, isr);
 
-   irq_status = dw_readw(dws, isr)  irq_mask;
/* Error handling */
if (irq_status  (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {
dw_readw(dws, txoicr);
dw_readw(dws, rxoicr);
dw_readw(dws, rxuicr);
-   int_error_stop(dws, interrupt_transfer: fifo overrun);
+   int_error_stop(dws, interrupt_transfer: fifo 
overrun/underrun);
return IRQ_HANDLED;
}
 
+   dw_reader(dws);
+   if (dws-rx_end == dws-rx) {
+   spi_mask_intr(dws, SPI_INT_TXEI);
+   dw_spi_xfer_done(dws);
+   return IRQ_HANDLED;
+   }
if (irq_status  SPI_INT_TXEI) {
spi_mask_intr(dws, SPI_INT_TXEI);
-
-   left = (dws-tx_end - dws-tx) / dws-n_bytes;
-   left = (left  int_level) ? int_level : left;
-
-   while (left--)
-   dw_writer(dws);
-   dw_reader(dws);
-
-   /* Re-enable the IRQ if there is still data left to tx */
-   if (dws-tx_end  dws-tx)
-   spi_umask_intr(dws, SPI_INT_TXEI);
-   else
-   dw_spi_xfer_done(dws);
+   dw_writer(dws);
+   /* Enable TX irq always, it will be disabled when RX finished */
+   spi_umask_intr(dws, SPI_INT_TXEI);
}
 
return IRQ_HANDLED;
@@ -377,15 +352,13 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 {
struct dw_spi *dws = dev_id;
-   u16 irq_status, irq_mask = 0x3f;
+   u16 irq_status = dw_readw(dws, isr)  0x3f;
 
-   irq_status = dw_readw(dws, isr)  irq_mask;
if (!irq_status)
return IRQ_NONE;
 
if (!dws-cur_msg) {
spi_mask_intr(dws, SPI_INT_TXEI);
-   /* Never fail */
return IRQ_HANDLED;
}
 
@@ -492,12 +465,8 @@ static void pump_transfers(unsigned long data)
 
switch (bits) {
case 8:
-   dws-n_bytes = 1;
-   dws-dma_width = 1;
-   break;
case 16:
-   dws-n_bytes = 2;
-   dws-dma_width = 2;
+   dws-n_bytes = dws-dma_width = bits  3;
break;
default:
printk(KERN_ERR MRST SPI0: unsupported bits:
@@ -541,7 +510,7 @@ static void pump_transfers(unsigned long data)
txint_level = dws-fifo_len / 2;
txint_level = (templen  txint_level) ? txint_level : templen;
 
-   imask |= SPI_INT_TXEI;
+   imask |= SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | 
SPI_INT_RXOI;
dws-transfer_handler = interrupt_transfer;
}
 
-- 
1.7.0.4


--
Create and publish websites with WebMatrix
Use the most

Re: dw_spi CS control/transfer modes

2011-03-20 Thread Feng Tang
Hi Jamie,

On Sat, 19 Mar 2011 04:11:35 +0800
Jamie Iles ja...@jamieiles.com wrote:

 Hi,
 
 I have a platform with a DesignWare SSI and I'm trying to use the
 dw_spi block using a GPIO for the chip select to workaround the
 problem of CS changing and the device losing state (we have a SPI
 flash attached), and I've found that using interrupt driven
 transfers, reading the SPI flash results in very few interrupts from
 the controller and a sluggish system (and no data from the flash).
 
 However, I've found that removing the conditional transfer mode
 setting (effectively reverting commit 052dc7c45 [spi/dw_spi:
 conditional transfer mode changes]) allows everything to work fine by
 keeping the transfer mode to transmit+receive.

What version of code are you using? The cs_control will be default to
NULL if dw_spi_chip as the controller data doesn't explicitly set it,
and then that piece of code won't be called.

Thanks,
Feng

 
 Does anyone have any ideas on the best way to fix this?  That code
 must have been added for a reason so perhaps it's just a quirk on our 
 platform, but I'd be keen to know in what ways it's been tested
 before - afaict, no other in-tree platforms are using dw_spi with
 their own cs_control so it's difficult to know if perhaps these are
 all doing polled mode transfers.
 
 Thanks,
 
 Jamie
 
 --
 Colocation vs. Managed Hosting
 A question and answer guide to determining the best fit
 for your organization - today and in the future.
 http://p.sf.net/sfu/internap-sfd2d
 ___
 spi-devel-general mailing list
 spi-devel-general@lists.sourceforge.net
 https://lists.sourceforge.net/lists/listinfo/spi-devel-general

--
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[PATCH 2/4] spi/dw_spi: remove the un-necessary flush()

2011-03-18 Thread Feng Tang
The flush() is used to drain all the left data in rx fifo, currently
is is always called together with disabling hw. But from spec, disabling
hw will also reset all the fifo, so flush() is not needed.

Signed-off-by: Alek Du alek...@intel.com
Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi.c |   15 +--
 1 files changed, 1 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index c83f6b1..35ac2b9 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -173,17 +173,6 @@ static void wait_till_not_busy(struct dw_spi *dws)
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) {
-   dw_readw(dws, dr);
-   cpu_relax();
-   }
-
-   wait_till_not_busy(dws);
-}
-
-
 static int dw_writer(struct dw_spi *dws)
 {
u16 txw = 0;
@@ -297,8 +286,7 @@ static void giveback(struct dw_spi *dws)
 
 static void int_error_stop(struct dw_spi *dws, const char *msg)
 {
-   /* Stop and reset hw */
-   flush(dws);
+   /* Stop the hw */
spi_enable_chip(dws, 0);
 
dev_err(dws-master-dev, %s\n, msg);
@@ -800,7 +788,6 @@ static void spi_hw_init(struct dw_spi *dws)
spi_enable_chip(dws, 0);
spi_mask_intr(dws, 0xff);
spi_enable_chip(dws, 1);
-   flush(dws);
 
/*
 * Try to detect the FIFO depth if not set by interface driver,
-- 
1.7.0.4


--
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[PATCH 1/4] spi/dw_spi: unify the low level read/write routines

2011-03-18 Thread Feng Tang
The original version has many duplicated codes for null/u8/u16 case,
so unify them to make it cleaner

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi.c   |  103 +++-
 include/linux/spi/dw_spi.h |2 -
 2 files changed, 26 insertions(+), 79 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 22af77f..c83f6b1 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -58,8 +58,6 @@ struct chip_data {
u8 bits_per_word;
u16 clk_div;/* baud rate divider */
u32 speed_hz;   /* baud rate */
-   int (*write)(struct dw_spi *dws);
-   int (*read)(struct dw_spi *dws);
void (*cs_control)(u32 command);
 };
 
@@ -185,80 +183,45 @@ static void flush(struct dw_spi *dws)
wait_till_not_busy(dws);
 }
 
-static int null_writer(struct dw_spi *dws)
-{
-   u8 n_bytes = dws-n_bytes;
-
-   if (!(dw_readw(dws, sr)  SR_TF_NOT_FULL)
-   || (dws-tx == dws-tx_end))
-   return 0;
-   dw_writew(dws, dr, 0);
-   dws-tx += n_bytes;
 
-   wait_till_not_busy(dws);
-   return 1;
-}
-
-static int null_reader(struct dw_spi *dws)
+static int dw_writer(struct dw_spi *dws)
 {
-   u8 n_bytes = dws-n_bytes;
+   u16 txw = 0;
 
-   while ((dw_readw(dws, sr)  SR_RF_NOT_EMPT)
-(dws-rx  dws-rx_end)) {
-   dw_readw(dws, dr);
-   dws-rx += n_bytes;
-   }
-   wait_till_not_busy(dws);
-   return dws-rx == dws-rx_end;
-}
-
-static int u8_writer(struct dw_spi *dws)
-{
if (!(dw_readw(dws, sr)  SR_TF_NOT_FULL)
|| (dws-tx == dws-tx_end))
return 0;
 
-   dw_writew(dws, dr, *(u8 *)(dws-tx));
-   ++dws-tx;
-
-   wait_till_not_busy(dws);
-   return 1;
-}
-
-static int u8_reader(struct dw_spi *dws)
-{
-   while ((dw_readw(dws, sr)  SR_RF_NOT_EMPT)
-(dws-rx  dws-rx_end)) {
-   *(u8 *)(dws-rx) = dw_readw(dws, dr);
-   ++dws-rx;
+   /* Set the tx word if the transfer's original tx is not null */
+   if (dws-tx_end - dws-len) {
+   if (dws-n_bytes == 8)
+   txw = *(u8 *)(dws-tx);
+   else
+   txw = *(u16 *)(dws-tx);
}
 
-   wait_till_not_busy(dws);
-   return dws-rx == dws-rx_end;
-}
-
-static int u16_writer(struct dw_spi *dws)
-{
-   if (!(dw_readw(dws, sr)  SR_TF_NOT_FULL)
-   || (dws-tx == dws-tx_end))
-   return 0;
-
-   dw_writew(dws, dr, *(u16 *)(dws-tx));
-   dws-tx += 2;
+   dw_writew(dws, dr, txw);
+   dws-tx += dws-n_bytes;
 
wait_till_not_busy(dws);
return 1;
 }
 
-static int u16_reader(struct dw_spi *dws)
+static int dw_reader(struct dw_spi *dws)
 {
-   u16 temp;
+   u16 rxw;
 
while ((dw_readw(dws, sr)  SR_RF_NOT_EMPT)
 (dws-rx  dws-rx_end)) {
-   temp = dw_readw(dws, dr);
-   *(u16 *)(dws-rx) = temp;
-   dws-rx += 2;
+   rxw = dw_readw(dws, dr);
+   /* Care rx only if the transfer's original rx is not null */
+   if (dws-rx_end - dws-len) {
+   if (dws-n_bytes == 8)
+   *(u8 *)(dws-rx) = rxw;
+   else
+   *(u16 *)(dws-rx) = rxw;
+   }
+   dws-rx += dws-n_bytes;
}
 
wait_till_not_busy(dws);
@@ -383,8 +346,8 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
left = (left  int_level) ? int_level : left;
 
while (left--)
-   dws-write(dws);
-   dws-read(dws);
+   dw_writer(dws);
+   dw_reader(dws);
 
/* Re-enable the IRQ if there is still data left to tx */
if (dws-tx_end  dws-tx)
@@ -417,13 +380,13 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 /* Must be called inside pump_transfers() */
 static void poll_transfer(struct dw_spi *dws)
 {
-   while (dws-write(dws))
-   dws-read(dws);
+   while (dw_writer(dws))
+   dw_reader(dws);
/*
 * There is a possibility that the last word of a transaction
 * will be lost if data is not ready. Re-read to solve this issue.
 */
-   dws-read(dws);
+   dw_reader(dws);
 
dw_spi_xfer_done(dws);
 }
@@ -483,8 +446,6 @@ static void pump_transfers(unsigned long data)
dws-tx_end = dws-tx + transfer-len;
dws-rx = transfer-rx_buf;
dws-rx_end = dws-rx + transfer-len;
-   dws-write = dws-tx ? chip-write : null_writer;
-   dws-read = dws-rx ? chip-read : null_reader;
dws-cs_change = transfer-cs_change;
dws-len = dws-cur_transfer-len;
if (chip != dws-prev_chip)
@@ -520,18 +481,10 @@ static void pump_transfers

[PATCH 0/4] patch serie for dw_spi driver

2011-03-18 Thread Feng Tang
Hi all,

Alek Du made some optimization for the dw_spi driver, the original driver
will wait for non-busy state after every work of read/write. With these
patches, driver will read/write as much as possible data from/to the HW
FIFO. The DMA mode transfer is not affected at all. There is also some
minor code cleanup.

The patch serie is generated against 2.6.38 kernel.

Pls help to review, thanks!

- Feng

-
Feng Tang (4):
  spi/dw_spi: unify the low level read/write routines
  spi/dw_spi: remove the un-necessary flush()
  spi/dw_spi: change poll mode transfer from byte ops to batch ops
  spi/dw_spi: improve the interrupt mode with the batch ops

 drivers/spi/dw_spi.c   |  202 ++-
 include/linux/spi/dw_spi.h |2 -
 2 files changed, 66 insertions(+), 138 deletions(-)


--
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[PATCH 4/4] spi/dw_spi: improve the interrupt mode with the batch ops

2011-03-18 Thread Feng Tang
leverage the performance gain by change in low level
read/write batch operations

Signed-off-by: Alek Du alek...@intel.com
Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi.c |   63 -
 1 files changed, 16 insertions(+), 47 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index ba8b394..a063019 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -190,21 +190,7 @@ static inline u32 rx_max(struct dw_spi *dws)
return min(rx_left, (u32)dw_readw(dws, rxflr));
 }
 
-
-static void wait_till_not_busy(struct dw_spi *dws)
-{
-   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 5000us after a read/write!\n);
-}
-
-static int dw_writer(struct dw_spi *dws)
+static void dw_writer(struct dw_spi *dws)
 {
u32 max = tx_max(dws);
u16 txw = 0;
@@ -220,11 +206,9 @@ static int dw_writer(struct dw_spi *dws)
dw_writew(dws, dr, txw);
dws-tx += dws-n_bytes;
}
-
-   return 1;
 }
 
-static int dw_reader(struct dw_spi *dws)
+static void dw_reader(struct dw_spi *dws)
 {
u32 max = rx_max(dws);
u16 rxw;
@@ -240,8 +224,6 @@ static int dw_reader(struct dw_spi *dws)
}
dws-rx += dws-n_bytes;
}
-
-   return dws-rx == dws-rx_end;
 }
 
 static void *next_transfer(struct dw_spi *dws)
@@ -340,35 +322,28 @@ EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
 
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 {
-   u16 irq_status, irq_mask = 0x3f;
-   u32 int_level = dws-fifo_len / 2;
-   u32 left;
+   u16 irq_status = dw_readw(dws, isr);
 
-   irq_status = dw_readw(dws, isr)  irq_mask;
/* Error handling */
if (irq_status  (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {
dw_readw(dws, txoicr);
dw_readw(dws, rxoicr);
dw_readw(dws, rxuicr);
-   int_error_stop(dws, interrupt_transfer: fifo overrun);
+   int_error_stop(dws, interrupt_transfer: fifo 
overrun/underrun);
return IRQ_HANDLED;
}
 
+   dw_reader(dws);
+   if (dws-rx_end == dws-rx) {
+   spi_mask_intr(dws, SPI_INT_TXEI);
+   dw_spi_xfer_done(dws);
+   return IRQ_HANDLED;
+   }
if (irq_status  SPI_INT_TXEI) {
spi_mask_intr(dws, SPI_INT_TXEI);
-
-   left = (dws-tx_end - dws-tx) / dws-n_bytes;
-   left = (left  int_level) ? int_level : left;
-
-   while (left--)
-   dw_writer(dws);
-   dw_reader(dws);
-
-   /* Re-enable the IRQ if there is still data left to tx */
-   if (dws-tx_end  dws-tx)
-   spi_umask_intr(dws, SPI_INT_TXEI);
-   else
-   dw_spi_xfer_done(dws);
+   dw_writer(dws);
+   /* Enable TX irq always, it will be disabled when RX finished */
+   spi_umask_intr(dws, SPI_INT_TXEI);
}
 
return IRQ_HANDLED;
@@ -377,15 +352,13 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 {
struct dw_spi *dws = dev_id;
-   u16 irq_status, irq_mask = 0x3f;
+   u16 irq_status = dw_readw(dws, isr)  0x3f;
 
-   irq_status = dw_readw(dws, isr)  irq_mask;
if (!irq_status)
return IRQ_NONE;
 
if (!dws-cur_msg) {
spi_mask_intr(dws, SPI_INT_TXEI);
-   /* Never fail */
return IRQ_HANDLED;
}
 
@@ -492,12 +465,8 @@ static void pump_transfers(unsigned long data)
 
switch (bits) {
case 8:
-   dws-n_bytes = 1;
-   dws-dma_width = 1;
-   break;
case 16:
-   dws-n_bytes = 2;
-   dws-dma_width = 2;
+   dws-n_bytes = dws-dma_width = bits  3;
break;
default:
printk(KERN_ERR MRST SPI0: unsupported bits:
@@ -541,7 +510,7 @@ static void pump_transfers(unsigned long data)
txint_level = dws-fifo_len / 2;
txint_level = (templen  txint_level) ? txint_level : templen;
 
-   imask |= SPI_INT_TXEI;
+   imask |= SPI_INT_TXEI | SPI_INT_TXOI | SPI_INT_RXUI | 
SPI_INT_RXOI;
dws-transfer_handler = interrupt_transfer;
}
 
-- 
1.7.0.4


--
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit

[PATCH 3/4] spi/dw_spi: change poll mode transfer from byte ops to batch ops

2011-03-18 Thread Feng Tang
Current poll transfer will read/write one word, then wait till the
hw is non-busy, it's not efficient. This patch will try to read/write
as many words as permitted by hardware FIFO depth.

Signed-off-by: Alek Du alek...@intel.com
Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi.c |   71 +
 1 files changed, 48 insertions(+), 23 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 35ac2b9..ba8b394 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -160,6 +160,37 @@ static inline void mrst_spi_debugfs_remove(struct dw_spi 
*dws)
 }
 #endif /* CONFIG_DEBUG_FS */
 
+/* Return the max entries we can fill into tx fifo */
+static inline u32 tx_max(struct dw_spi *dws)
+{
+   u32 tx_left, tx_room, rxtx_gap;
+
+   tx_left = (dws-tx_end - dws-tx) / dws-n_bytes;
+   tx_room = dws-fifo_len - dw_readw(dws, txflr);
+
+   /*
+* Another concern is about the tx/rx mismatch, we
+* though to use (dws-fifo_len - rxflr - txflr) as
+* one maximum value for tx, but it doesn't cover the
+* data which is out of tx/rx fifo and inside the
+* shift registers. So a control from sw point of
+* view is taken.
+*/
+   rxtx_gap =  ((dws-rx_end - dws-rx) - (dws-tx_end - dws-tx))
+   / dws-n_bytes;
+
+   return min3(tx_left, tx_room, (u32) (dws-fifo_len - rxtx_gap));
+}
+
+/* Return the max entries we should read out of rx fifo */
+static inline u32 rx_max(struct dw_spi *dws)
+{
+   u32 rx_left = (dws-rx_end - dws-rx) / dws-n_bytes;
+
+   return min(rx_left, (u32)dw_readw(dws, rxflr));
+}
+
+
 static void wait_till_not_busy(struct dw_spi *dws)
 {
unsigned long end = jiffies + 1 + usecs_to_jiffies(5000);
@@ -175,33 +206,30 @@ static void wait_till_not_busy(struct dw_spi *dws)
 
 static int dw_writer(struct dw_spi *dws)
 {
+   u32 max = tx_max(dws);
u16 txw = 0;
 
-   if (!(dw_readw(dws, sr)  SR_TF_NOT_FULL)
-   || (dws-tx == dws-tx_end))
-   return 0;
-
-   /* Set the tx word if the transfer's original tx is not null */
-   if (dws-tx_end - dws-len) {
-   if (dws-n_bytes == 8)
-   txw = *(u8 *)(dws-tx);
-   else
-   txw = *(u16 *)(dws-tx);
+   while (max--) {
+   /* Set the tx word if the transfer's original tx is not null 
*/
+   if (dws-tx_end - dws-len) {
+   if (dws-n_bytes == 8)
+   txw = *(u8 *)(dws-tx);
+   else
+   txw = *(u16 *)(dws-tx);
+   }
+   dw_writew(dws, dr, txw);
+   dws-tx += dws-n_bytes;
}
 
-   dw_writew(dws, dr, txw);
-   dws-tx += dws-n_bytes;
-
-   wait_till_not_busy(dws);
return 1;
 }
 
 static int dw_reader(struct dw_spi *dws)
 {
+   u32 max = rx_max(dws);
u16 rxw;
 
-   while ((dw_readw(dws, sr)  SR_RF_NOT_EMPT)
-(dws-rx  dws-rx_end)) {
+   while (max--) {
rxw = dw_readw(dws, dr);
/* Care rx only if the transfer's original rx is not null */
if (dws-rx_end - dws-len) {
@@ -213,7 +241,6 @@ static int dw_reader(struct dw_spi *dws)
dws-rx += dws-n_bytes;
}
 
-   wait_till_not_busy(dws);
return dws-rx == dws-rx_end;
 }
 
@@ -368,13 +395,11 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 /* Must be called inside pump_transfers() */
 static void poll_transfer(struct dw_spi *dws)
 {
-   while (dw_writer(dws))
+   do {
+   dw_writer(dws);
dw_reader(dws);
-   /*
-* There is a possibility that the last word of a transaction
-* will be lost if data is not ready. Re-read to solve this issue.
-*/
-   dw_reader(dws);
+   cpu_relax();
+   } while (dws-rx_end  dws-rx);
 
dw_spi_xfer_done(dws);
 }
-- 
1.7.0.4


--
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH 4/4] spi/dw_spi: improve the interrupt mode with the batch ops

2011-03-18 Thread Feng Tang
Hi Alan,

On Fri, 18 Mar 2011 18:13:10 +0800
Alan Cox a...@linux.intel.com wrote:

 On Fri, 18 Mar 2011 15:50:56 +0800
 Feng Tang feng.t...@intel.com wrote:
 
  spi/dw_spi: improve the interrupt mode with the batch ops
 
 Look sane to me - only question I have is should the patches have a
 
 From: Alek Du ...
 
 on them ?


I've strongly requested Alek to make the patches himself, but he is too busy
with his project and just give me a .35 version dw_spi.c. So to get it 
quickly upstream, I manually separate his change, modify a little, combined
with mine, test, add some comments and his Signed-off.

I really don't know the From:  matters so much, and thought the signed-off
and the cover-letter already claim the right credit :). Is is possible
for Grant to change the From:  to Alek when he would like to merge these
patches?

Thanks,
Feng


--
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH] spi/dw_spi: move dw_spi.h into drivers/spi

2011-02-28 Thread Feng Tang


Looks good to me, thanks for the move.

- Feng

On Tue, 1 Mar 2011 04:50:55 +0800
Grant Likely grant.lik...@secretlab.ca wrote:

 include/linux/dw_spi.h only includes driver internal data.  It doesn't
 expose a platform_data configuration structure or similar (at least
 nothing in-tree).  This patch moves the header into drivers/spi so
 that the scope is limited to only the dw_spi_*.c driver files
 
 This patch also adds a missing #include linux/scatterlist.h that
 prevented the driver from building.
 
 Signed-off-by: Grant Likely grant.lik...@secretlab.ca
 Cc: Feng Tang feng.t...@intel.com
 Cc: spi-devel-general@lists.sourceforge.net
 ---
  drivers/spi/dw_spi.c   |4 -
  drivers/spi/dw_spi.h   |  233
 
 drivers/spi/dw_spi_mid.c   |3 - drivers/spi/dw_spi_mmio.c  |4
 + drivers/spi/dw_spi_pci.c   |3 -
  include/linux/spi/dw_spi.h |  233
  6 files changed, 242
 insertions(+), 238 deletions(-) create mode 100644
 drivers/spi/dw_spi.h delete mode 100644 include/linux/spi/dw_spi.h
 
 diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
 index 22af77f..9a61964 100644
 --- a/drivers/spi/dw_spi.c
 +++ b/drivers/spi/dw_spi.c
 @@ -22,10 +22,10 @@
  #include linux/highmem.h
  #include linux/delay.h
  #include linux/slab.h
 -
 -#include linux/spi/dw_spi.h
  #include linux/spi/spi.h
 
 +#include dw_spi.h
 +
  #ifdef CONFIG_DEBUG_FS
  #include linux/debugfs.h
  #endif
 diff --git a/drivers/spi/dw_spi.h b/drivers/spi/dw_spi.h
 new file mode 100644
 index 000..6cd10f6
 --- /dev/null
 +++ b/drivers/spi/dw_spi.h
 @@ -0,0 +1,233 @@
 +#ifndef DW_SPI_HEADER_H
 +#define DW_SPI_HEADER_H
 +
 +#include linux/io.h
 +
 +/* Bit fields in CTRLR0 */
 +#define SPI_DFS_OFFSET 0
 +
 +#define SPI_FRF_OFFSET 4
 +#define SPI_FRF_SPI0x0
 +#define SPI_FRF_SSP0x1
 +#define SPI_FRF_MICROWIRE  0x2
 +#define SPI_FRF_RESV   0x3
 +
 +#define SPI_MODE_OFFSET6
 +#define SPI_SCPH_OFFSET6
 +#define SPI_SCOL_OFFSET7
 +
 +#define SPI_TMOD_OFFSET8
 +#define SPI_TMOD_MASK  (0x3  SPI_TMOD_OFFSET)
 +#defineSPI_TMOD_TR 0x0 /*
 xmit  recv */ +#define SPI_TMOD_TO
 0x1 /* xmit only */ +#define
 SPI_TMOD_RO0x2 /* recv only */
 +#define SPI_TMOD_EPROMREAD 0x3 /* eeprom
 read mode */ + +#define SPI_SLVOE_OFFSET   10
 +#define SPI_SRL_OFFSET 11
 +#define SPI_CFS_OFFSET 12
 +
 +/* Bit fields in SR, 7 bits */
 +#define SR_MASK0x7f/*
 cover 7 bits */ +#define SR_BUSY(1 
 0) +#define SR_TF_NOT_FULL (1  1)
 +#define SR_TF_EMPT (1  2)
 +#define SR_RF_NOT_EMPT (1  3)
 +#define SR_RF_FULL (1  4)
 +#define SR_TX_ERR  (1  5)
 +#define SR_DCOL(1  6)
 +
 +/* Bit fields in ISR, IMR, RISR, 7 bits */
 +#define SPI_INT_TXEI   (1  0)
 +#define SPI_INT_TXOI   (1  1)
 +#define SPI_INT_RXUI   (1  2)
 +#define SPI_INT_RXOI   (1  3)
 +#define SPI_INT_RXFI   (1  4)
 +#define SPI_INT_MSTI   (1  5)
 +
 +/* TX RX interrupt level threshhold, max can be 256 */
 +#define SPI_INT_THRESHOLD  32
 +
 +enum dw_ssi_type {
 +   SSI_MOTO_SPI = 0,
 +   SSI_TI_SSP,
 +   SSI_NS_MICROWIRE,
 +};
 +
 +struct dw_spi_reg {
 +   u32 ctrl0;
 +   u32 ctrl1;
 +   u32 ssienr;
 +   u32 mwcr;
 +   u32 ser;
 +   u32 baudr;
 +   u32 txfltr;
 +   u32 rxfltr;
 +   u32 txflr;
 +   u32 rxflr;
 +   u32 sr;
 +   u32 imr;
 +   u32 isr;
 +   u32 risr;
 +   u32 txoicr;
 +   u32 rxoicr;
 +   u32 rxuicr;
 +   u32 msticr;
 +   u32 icr;
 +   u32 dmacr;
 +   u32 dmatdlr;
 +   u32 dmardlr;
 +   u32 idr;
 +   u32 version;
 +   u32 dr; /* Currently oper as 32 bits,
 +   though only low 16 bits matters */
 +} __packed;
 +
 +struct dw_spi;
 +struct dw_spi_dma_ops {
 +   int (*dma_init)(struct dw_spi *dws);
 +   void (*dma_exit)(struct dw_spi *dws);
 +   int (*dma_transfer)(struct dw_spi *dws, int cs_change);
 +};
 +
 +struct dw_spi {
 +   struct spi_master   *master;
 +   struct spi_device   *cur_dev;
 +   struct device   *parent_dev;
 +   enum dw_ssi_typetype;
 +
 +   void __iomem*regs;
 +   unsigned long   paddr;
 +   u32

Re: MRST SPI

2011-02-13 Thread Feng Tang
Hi Tom,

On Thu, 10 Feb 2011 18:48:00 +0800
Tom tom.spi.de...@gmail.com wrote:

 Hi All,
 
 I have a SPI device problem on MRST CDK.
 
 I use a GPIO as SS because my slave device expects the SS to be low
 between byte transfers.

The DW spi controller has a slave select register for that purpose, and
myself don't have experience of using an external GPIO lines for SS, so
no comment here.

 My probe function does a read as:
 
 int read_val;
 ---
 ---
 read_val = spi_w8r8(spi_dev,0x20);
  if ( read_val  0 )
 printk ( spi_read err\n);
 else
  printk ( spi_read %d\n,read_val );
 
 --
 
 The MRST SFI interface passes the device board info. Because, my
 device is not listed in the IA32 f/w I modified the MRST.c code
 sfi_handle_spi_dev function as:
 
 while(dev-name[0])
 {
 if (dev-type == SFI_DEV_TYPE_SPI 
 !strncmp(dev-name,
 spi_info-modalias, 16)) {
 if (!strncmp(spi_old_device,
 spi_info-modalias, 16)){
 strncpy (spi_info-modalias,
 spi_my_dev,16);
 pdata =
 dev-get_platform_data(spi_info); pr_info ( spi_old_device modalias
 to spi_my_dev );
 }
else
{
  pdata = dev-get_platform_data(spi_info);
}
   break;
 }
   dev++;
 }
 
 i also modified the devs_id array to change the platform_data
 
  {spi_old_dev, SFI_DEV_TYPE_SPI, 0, no_platform_data}
 
 The issue is  that for the spi_w8r8 call, i get multiple read
 (multiple * (8 clock cycles/SS toggle))on the SPI bus.
 
 Also regarding the spi-irq, is it the responsibility of the protocol
 driver to register for this irq and handle it or does the spi
 framework or master driver take care of this ?
 
 Any pointers would be really helpful. ( attached is the test code)

Suggest you refer the arch/platform/mrst/mrst.c about setting up
the max3110 spi device's platform and controller data, you can 
find it in Alan Cox's MID reference tree:

git://git.kernel.org/pub/scm/linux/kernel/git/alan/linux-2.6-mid-ref.git 

Thanks,
Feng

 
 Regards,
 Tom

--
The ultimate all-in-one performance toolkit: Intel(R) Parallel Studio XE:
Pinpoint memory and threading errors before they happen.
Find and fix more than 250 security defects in the development cycle.
Locate bottlenecks in serial and parallel code that limit performance.
http://p.sf.net/sfu/intel-dev2devfeb
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[Patch v2 2/3] spi/dw_spi: change to EXPORT_SYMBOL_GPL for exported APIs

2010-12-23 Thread Feng Tang
Acked-by: Grant Likely grant.lik...@secretlab.ca
Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi.c |8 
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 25238a8..b50bf5b 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -941,7 +941,7 @@ err_free_master:
 exit:
return ret;
 }
-EXPORT_SYMBOL(dw_spi_add_host);
+EXPORT_SYMBOL_GPL(dw_spi_add_host);
 
 void __devexit dw_spi_remove_host(struct dw_spi *dws)
 {
@@ -965,7 +965,7 @@ void __devexit dw_spi_remove_host(struct dw_spi *dws)
/* Disconnect from the SPI framework */
spi_unregister_master(dws-master);
 }
-EXPORT_SYMBOL(dw_spi_remove_host);
+EXPORT_SYMBOL_GPL(dw_spi_remove_host);
 
 int dw_spi_suspend_host(struct dw_spi *dws)
 {
@@ -978,7 +978,7 @@ int dw_spi_suspend_host(struct dw_spi *dws)
spi_set_clk(dws, 0);
return ret;
 }
-EXPORT_SYMBOL(dw_spi_suspend_host);
+EXPORT_SYMBOL_GPL(dw_spi_suspend_host);
 
 int dw_spi_resume_host(struct dw_spi *dws)
 {
@@ -990,7 +990,7 @@ int dw_spi_resume_host(struct dw_spi *dws)
dev_err(dws-master-dev, fail to start queue (%d)\n, ret);
return ret;
 }
-EXPORT_SYMBOL(dw_spi_resume_host);
+EXPORT_SYMBOL_GPL(dw_spi_resume_host);
 
 MODULE_AUTHOR(Feng Tang feng.t...@intel.com);
 MODULE_DESCRIPTION(Driver for DesignWare SPI controller core);
-- 
1.7.0.4


--
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and, 
should the need arise, upgrade to a full multi-node Oracle RAC database 
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[Patch v2 1/3] spi/dw_spi: Fix too short timeout in spi polling loop

2010-12-23 Thread Feng Tang
The SPI polling loop timeout only works with HZ=100 as the loop was
actually too short.

Also add appropriate cpu_relax() in the busy wait loops...

Acked-by: Grant Likely grant.lik...@secretlab.ca
Signed-off-by: Arjan van de Ven ar...@linux.intel.com
Signed-off-by: Alan Cox a...@linux.intel.com
---
 drivers/spi/dw_spi.c |9 ++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 0838c79..25238a8 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);
 }
-- 
1.7.0.4


--
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and, 
should the need arise, upgrade to a full multi-node Oracle RAC database 
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[Patch v2 3/3] spi/dw_spi: add DMA support

2010-12-23 Thread Feng Tang
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, at the same time it provides a general
framework to support dw_spi core to cowork with dma controllers on
other platforms

It has been tested with a Option GTM501L 3G modem and Infenion 60x60
modem. To use DMA mode, DMA controller 2 of Moorestown has to be enabled

Also change the dma interface suggested by Linus Walleij.

Acked-by: Linus Walleij linus.wall...@stericsson.com
Acked-by: Grant Likely grant.lik...@secretlab.ca
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
Signed-off-by: Alan Cox a...@linux.intel.com
---
 drivers/spi/Kconfig|4 +
 drivers/spi/Makefile   |3 +-
 drivers/spi/dw_spi.c   |   33 ---
 drivers/spi/dw_spi_mid.c   |  224 
 drivers/spi/dw_spi_pci.c   |   20 +++-
 include/linux/spi/dw_spi.h |   24 -
 6 files changed, 284 insertions(+), 24 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)  += 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 b50bf5b..497ecb3 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -288,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)
@@ -341,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;
@@ -356,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)
 {
@@ -387,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;
@@ -422,11 +425,7 @@ static void poll_transfer(struct dw_spi *dws)
 */
dws-read(dws);
 
-   transfer_complete(dws);
-}
-
-static void dma_transfer(struct dw_spi *dws, int cs_change)
-{
+   dw_spi_xfer_done(dws);
 }
 
 static void pump_transfers(unsigned long data)
@@ -608,7 +607,7 @@ static void pump_transfers(unsigned long data)
}
 
if (dws-dma_mapped)
-   dma_transfer(dws, cs_change);
+   dws-dma_ops-dma_transfer(dws, cs_change);
 
if (chip-poll_mode)
poll_transfer(dws);
@@ -904,11 +903,17 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
master-setup = dw_spi_setup;
master-transfer = dw_spi_transfer;
 
-   dws-dma_inited = 0;
-
/* Basic HW init */
spi_hw_init(dws);
 
+   if (dws-dma_ops  dws-dma_ops-dma_init) {
+   ret = dws-dma_ops-dma_init(dws);
+   if (ret) {
+   dev_warn(master-dev, DMA init failed\n);
+   dws

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-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: spi/spi: don't release the spi device twice

2010-11-23 Thread Feng Tang
Hi Sebastian,

On Tue, 23 Nov 2010 18:33:03 +0800
Sebastian Andrzej Siewior bige...@linutronix.de wrote:

 David Lamparter wrote:
  This code is the old code, before patch 3486008 which you're citing.
  3486008 does:
  
  -   dummy = device_for_each_child(master-dev.parent,
  master-dev,
  -   __unregister);
  +   dummy = device_for_each_child(master-dev, NULL,
  __unregister);
  
  Considering that this patch is in 2.6.36 (and 36.1), you seem to
  have mixed up your sources. Please make sure your checkout is
  current and unbroken...
 Hmmm.
 # git describe --long
 v2.6.37-rc3-0-g3561d43
 
 After looking at spi_unregister_master() in drivers/spi/spi.c, I see:
 
   dummy = device_for_each_child(master-dev.parent, master-dev,
   __unregister);
   device_unregister(master-dev);
   }
 
 This change got back in by:
 
 commit 2b9603a0d7e395fb844af90fba71448bc8019077
 Author: Feng Tang feng.t...@intel.com
 Date:   Mon Aug 2 15:52:15 2010 +0800
 
  spi: enable spi_board_info to be registered after spi_master
 
 which is v2.6.37-rc1~2^2~4. So I probably mixed up you with Feng.
 
 This thread starts at
 http://www.mail-archive.com/spi-devel-general@lists.sourceforge.net/msg05437.html
 
I checked my original patch which didn't touch the logic of 
spi_unregister_master() as
-
@@ -568,6 +592,10 @@  void spi_unregister_master(struct spi_master *master)
 {
int dummy;
 
+   mutex_lock(board_lock);
+   list_del(master-list);
+   mutex_unlock(board_lock);
+
dummy = device_for_each_child(master-dev.parent, master-dev,
__unregister);
device_unregister(master-dev);
-

So this should be a merge problem, which corrupt the commit from David's commit
3486008 spi: free children in spi_unregister_master, not siblings

Thanks,
Feng

--
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 v2] spi/spi: don't release the spi device twice

2010-11-23 Thread Feng Tang
On Wed, 24 Nov 2010 00:45:20 +0800
David Lamparter equi...@diac24.net wrote:

  This was fixed by David Lamparter in v2.6.36-rc5 3486008
  (spi: free children in spi_unregister_master, not siblings) and
  broken again in v2.6.37-rc1~2^2~4 during the merge of 2b9603a0
  (spi: enable spi_board_info to be registered after spi_master).
  
  Signed-off-by: Sebastian Andrzej Siewior bige...@linutronix.de
  ---
  -   dummy = device_for_each_child(master-dev.parent,
  master-dev,
  -   __unregister);
  +   dummy = device_for_each_child(master-dev, NULL,
  __unregister);
 
 Signed-off-by: David Lamparter equi...@diac24.net
 
 very simple merge/rebase/forward-port breakage...
 Feng, can you check 2b9603a0 for whether anything else got broken?
 

I just checked, all other parts should be ok.

Thanks,
Feng

--
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] spi: add a bits_per_word to struct spi_board_info

2010-09-08 Thread Feng Tang
Hi Grant,

On Thu, 9 Sep 2010 04:21:59 +0800
Grant Likely grant.lik...@secretlab.ca wrote:

   
Yes, driver itself
know the bits_per_word info best in most case, but there
is
some device (Option GTM501L spi modem) which supports
multiple
bits_per_mode option, and here platform code
   is the good place to set it.
   
   
   Not unless it knows which mode the driver uses...
   a kind of layering violation.
  
  spi_board_info has a member of mode, so for my platform, I prefer
  to set all these infos in platform code, while protocol driver can
  check if the preset infos like speed_hz/mode/bits_per_word are
  supported.
 
 The real problem is that spi_drivers are normally allowed to change
 bits_per_word as needed. 

For drivers who don't accept bits_per_word comes from platform code, it
could just ignores it and set the value it wants.

 If the spi_driver gets unbound and
 rebound, then the original platform-set value for bits_per_word is
 lost and the behaviour changes.  

Um, if you are talking about driver load/unload, then the bits_per_word
info won't get lost as it is set to spi_device from spi_board_info when
spi_new_device get called.

 If you really want to give the driver
 hints about the best setting for bits_per_word or similar, then you
 should probably use a driver-specific pdata structure.

Good point, really a solution to the GTM501L modem driver. But still,
adding the bits_per_word to spi_board_info will be more generic when
more devices which support multiple bits models show up.

Thanks,
Feng


--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH] spi: add a bits_per_word to struct spi_board_info

2010-09-08 Thread Feng Tang
On Thu, 9 Sep 2010 11:48:22 +0800
David Brownell davi...@pacbell.net wrote:

 You know, in retrospect, I shouldn't have put
 most of those SPI device setup params into the
 board setup data.
 
 There's one which MUST be there:  polarity of
 the chip select line.  The rest seem like they
 could (and arguably should) all be handled by
 driver-specific params.  (Possible exception:
 clock rate, which sometimes matters even when
 chips are not selected).
 
 At any rate, adding MORE driver-specific params
 (like bits-per-word) to board setup data seems
 like the wrong direction to go..

Agree. Thank you two for helping me get an overall picture of
configuring these parameters.

-Feng

--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[PATCH v2] spi/dw_spi: clean the cs_control code

2010-09-07 Thread Feng Tang
commit 052dc7c45i spi/dw_spi: conditional transfer mode change
introduced cs_control code, which has a bug by using bit offset
for spi mode to set transfer mode in control register. Also it
forces devices who don't need cs_control to re-configure the
control registers for each spi transfer. This patch will fix them

Signed-off-by: Feng Tang feng.t...@intel.com
Cc: David Brownell dbrown...@users.sourceforge.net
Cc: Grant Likely grant.lik...@secretlab.ca
Cc: George Shore geo...@georgeshore.com
---
 drivers/spi/dw_spi.c   |   17 +
 include/linux/spi/dw_spi.h |2 ++
 2 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index d256cb0..4b75a81 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -181,10 +181,6 @@ static void flush(struct dw_spi *dws)
wait_till_not_busy(dws);
 }
 
-static void null_cs_control(u32 command)
-{
-}
-
 static int null_writer(struct dw_spi *dws)
 {
u8 n_bytes = dws-n_bytes;
@@ -322,7 +318,7 @@ static void giveback(struct dw_spi *dws)
struct spi_transfer,
transfer_list);
 
-   if (!last_transfer-cs_change)
+   if (!last_transfer-cs_change  dws-cs_control)
dws-cs_control(MRST_SPI_DEASSERT);
 
msg-state = NULL;
@@ -544,13 +540,13 @@ static void pump_transfers(unsigned long data)
 */
if (dws-cs_control) {
if (dws-rx  dws-tx)
-   chip-tmode = 0x00;
+   chip-tmode = SPI_TMOD_TR;
else if (dws-rx)
-   chip-tmode = 0x02;
+   chip-tmode = SPI_TMOD_RO;
else
-   chip-tmode = 0x01;
+   chip-tmode = SPI_TMOD_TO;
 
-   cr0 = ~(0x3  SPI_MODE_OFFSET);
+   cr0 = ~SPI_TMOD_MASK;
cr0 |= (chip-tmode  SPI_TMOD_OFFSET);
}
 
@@ -699,9 +695,6 @@ static int dw_spi_setup(struct spi_device *spi)
chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
if (!chip)
return -ENOMEM;
-
-   chip-cs_control = null_cs_control;
-   chip-enable_dma = 0;
}
 
/*
diff --git a/include/linux/spi/dw_spi.h b/include/linux/spi/dw_spi.h
index cc813f9..c91302f 100644
--- a/include/linux/spi/dw_spi.h
+++ b/include/linux/spi/dw_spi.h
@@ -14,7 +14,9 @@
 #define SPI_MODE_OFFSET6
 #define SPI_SCPH_OFFSET6
 #define SPI_SCOL_OFFSET7
+
 #define SPI_TMOD_OFFSET8
+#define SPI_TMOD_MASK  (0x3  SPI_TMOD_OFFSET)
 #defineSPI_TMOD_TR 0x0 /* xmit  recv 
*/
 #define SPI_TMOD_TO0x1 /* xmit only */
 #define SPI_TMOD_RO0x2 /* recv only */
-- 
1.7.0.4


--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH] spi: add a bits_per_word to struct spi_board_info

2010-09-01 Thread Feng Tang
On Wed, 1 Sep 2010 23:46:18 +0800
David Brownell davi...@pacbell.net wrote:

 Re $SUBJECT ... consider it a quirk of how
 SPI devices get setup that this field isn't
 one of the ones the platform code can set up.
 
 I've thought about fixing this before,
 and decided against it:
 
 
  What is the use case that you would want to do
   this. Knowing what the bits_per_word should
  be is the responsibility of the spi device
  driver.  What is the  use-case where the
  driver wouldn't know what bits_per_word
  should be?
 
 What's the case where platform code could
 know better than the driver?

Grant also asked me the same question. Yes, driver itself
know the bits_per_word info best in most case, but there is
some device (Option GTM501L spi modem) which supports multiple
bits_per_mode option, and here platform code is the good place
to set it.

One of my intension of this patch is to save some extra spi_setup.
For many spi protocol drivers in kernel, spi_setup() will be
called twice for them, first time is inside spi_new_device(it calls
spi_add_device), the second time will be inside driver's probe
func, after setting bits_per_word info. So if we can set it before
registering board info, then the second spi_setup can be removed for
many drivers.

Thanks,
Feng



--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH] spi/dw_spi: clean the cs_control code

2010-09-01 Thread Feng Tang
On Wed, 1 Sep 2010 23:07:57 +0800
Grant Likely grant.lik...@secretlab.ca wrote:

 Hi Feng,
 
 On Wed, Sep 01, 2010 at 01:35:59PM +0800, Feng Tang wrote:
  commit 052dc7c45 introduced cs_control code,
 
 Be friendly to mere-mortals.  You should quote the patch title
 spi/dw_spi: conditional transfer mode changes in addition to the
 sha1 id.

Got it, thanks, will add it in V2

  @@ -544,13 +540,13 @@ static void pump_transfers(unsigned long data)
   */
  if (dws-cs_control) {
  if (dws-rx  dws-tx)
  -   chip-tmode = 0x00;
  +   chip-tmode = SPI_TMOD_TR;
  else if (dws-rx)
  -   chip-tmode = 0x02;
  +   chip-tmode = SPI_TMOD_RO;
  else
  -   chip-tmode = 0x01;
  +   chip-tmode = SPI_TMOD_TO;
   
  -   cr0 = ~(0x3  SPI_MODE_OFFSET);
  +   cr0 = ~SPI_TMOD_MASK;
  cr0 |= (chip-tmode  SPI_TMOD_OFFSET);
 
 Changing these values isn't mentioned in the patch description.  I
 assume this is not the bug fix because the #defines are the same
 values.

OK, it's a little confusing, there are 2 OFFSET here:
SPI_MODE_OFFSET (for spi mode 0/1/2 etc setting)
SPI_TMOD_OFFSET (for tx only/rx only/duplex)

So simple fix should be
-   cr0 = ~(0x3  SPI_MODE_OFFSET); 
+   cr0 = ~(0x3  SPI_TMOD_OFFSET);
while my new introduced SPI_TMOD_MASK make things complex :)

Thanks,
Feng

--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH] spi: add a bits_per_word to struct spi_board_info

2010-09-01 Thread Feng Tang
Hi David,


  Grant also asked me the same question.
 
 
 I saw him ask a different question (which
 I quoted) ...

My mistake, I tried to answer Grant's and your questions in one email to
keep the discussion in one thread.

 
 
  Yes, driver itself
  know the bits_per_word info best in most case, but there
  is
  some device (Option GTM501L spi modem) which supports
  multiple
  bits_per_mode option, and here platform code
 is the good place to set it.
 
 
 Not unless it knows which mode the driver uses...
 a kind of layering violation.

spi_board_info has a member of mode, so for my platform, I prefer to
set all these infos in platform code, while protocol driver can
check if the preset infos like speed_hz/mode/bits_per_word are supported.

I thought platform code have to know the detail of the spi device
when setting spi_board_info for it.

Also the following code quoted from spi_setup() indicates it supports
setting mode for spi_board_info

bad_bits = spi-mode  ~spi-master-mode_bits;
if (bad_bits) {
dev_dbg(spi-dev, setup: unsupported mode bits %x\n,
bad_bits);
return -EINVAL;
}

Thanks,
Feng




--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [PATCH] spi/dw_spi: Enable Intel Moorestown SPI controller 1

2010-08-31 Thread Feng Tang

NAK.

We should not export SPI1 has x86 core has no way to access its register.
though the device physically exists.

Thanks,
Feng

On Tue, 31 Aug 2010 14:14:16 +0800
Yong Wang yong.y.w...@linux.intel.com wrote:

 Enable Intel Moorestown SPI controller 1
 
 Signed-off-by: Yong Wang yong.y.w...@intel.com
 ---
  drivers/spi/dw_spi_pci.c |2 ++
  1 files changed, 2 insertions(+), 0 deletions(-)
 
 diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/dw_spi_pci.c
 index 1f52755..eec9d0b 100644
 --- a/drivers/spi/dw_spi_pci.c
 +++ b/drivers/spi/dw_spi_pci.c
 @@ -142,6 +142,8 @@ static int spi_resume(struct pci_dev *pdev)
  static const struct pci_device_id pci_ids[] __devinitdata = {
   /* Intel Moorestown platform SPI controller 0 */
   { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
 + /* Intel Moorestown platform SPI controller 1 */
 + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0801) },
   {},
  };
  

--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: controller_data handling through spidev.c

2010-08-31 Thread Feng Tang

 
 It's a sibling to the platform_data field, and
 should be set up with that.  Neither one should
 be assigned or understood by protocol drivers.


 
 Historically, controller_data was used ISTR to
 cope with tuning that the PXA SPI controller
 required (DMA etc).  Most controllers should
 have no need for it.
 

DW spi driver is also using the controller data, but as you said
protocol driver itself doesn't need set it. Platform code where
that spi device is registered (by spi_register_board_info) should
set up the controller data.

Thanks,
Feng

--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[PATCH] spi: add a bits_per_word to struct spi_board_info

2010-08-31 Thread Feng Tang
Currently a spi device's bits_per_word can only be inited
inside protocol driver's probe func, this patch will enable
platform code to specify this info when registering the
spi_board_info

Signed-off-by: Feng Tang feng.t...@intel.com
Cc: David Brownell dbrown...@users.sourceforge.net
Cc: Grant Likely grant.lik...@secretlab.ca
---
 drivers/spi/spi.c   |1 +
 include/linux/spi/spi.h |3 +++
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index a9e5c79..a8690e7 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -350,6 +350,7 @@ struct spi_device *spi_new_device(struct spi_master *master,
proxy-chip_select = chip-chip_select;
proxy-max_speed_hz = chip-max_speed_hz;
proxy-mode = chip-mode;
+   proxy-bits_per_word = chip-bits_per_word;
proxy-irq = chip-irq;
strlcpy(proxy-modalias, chip-modalias, sizeof(proxy-modalias));
proxy-dev.platform_data = (void *) chip-platform_data;
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 92e52a1..f36d0d5 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -698,6 +698,8 @@ static inline ssize_t spi_w8r16(struct spi_device *spi, u8 
cmd)
  * @mode: Initializes spi_device.mode; based on the chip datasheet, board
  * wiring (some devices support both 3WIRE and standard modes), and
  * possibly presence of an inverter in the chipselect path.
+ * @bits_per_word: Initializes spi_device.bits_per_word, usually it will
+ * be from 8 to 32 bits
  *
  * When adding new SPI devices to the device tree, these structures serve
  * as a partial device template.  They hold information which can't always
@@ -742,6 +744,7 @@ struct spi_board_info {
 * where the default of SPI_CS_HIGH = 0 is wrong.
 */
u8  mode;
+   u8  bits_per_word;
 
/* ... may need additional spi_device chip config data here.
 * avoid stuff protocol drivers can set; but include stuff
-- 
1.7.0.4


--
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v3] spi: enable spi_board_info to be registered after spi_master

2010-08-02 Thread Feng Tang
On Mon, 2 Aug 2010 13:53:25 +0800
Grant Likely grant.lik...@secretlab.ca wrote:

   /**
  @@ -365,6 +370,24 @@ struct spi_device *spi_new_device(struct
  spi_master *master, }
   EXPORT_SYMBOL_GPL(spi_new_device);
 
  +/* Has to be called when board_lock is acquired */
  +static void spi_scan_masterlist(struct spi_board_info *bi)
  +{
  +       struct spi_master *master;
  +       struct spi_device *dev;
  +
  +       list_for_each_entry(master, spi_master_list, list) {
  +               if (master-bus_num != bi-bus_num)
  +                       continue;
  +
  +               dev = spi_new_device(master, bi);
  +               if (!dev)
  +                       dev_err(master-dev.parent,
  +                               can't create new device for %s\n,
  +                               bi-modalias);
  +       }
  +}
  +
 
 The abstraction isn't quite at the right place because the same code
 block is now duplicated twice.  Consider the following instead:
 
 static void spi_match_master_to_boardinfo(struct spi_master *master,
   struct spi_board_info *bi)
 {
   struct spi_device *dev;
 
   if (master-bus_num != bi-bus_num)
   return;
 
   dev = spi_new_device(master, bi);
   if (!dev)
   dev_err(master-dev.parent, can't create new device
 for %s\n, bi-modalias);
 }
 
 And then from spi_register_board_info, do:
 
   list_for_each_entry(master, spi_master_list, list)
   spi_match_master_to_boardinfo(master, bi-boardinfo);
 
 And in spi_register_master, do:
 
   list_for_each_entry(bi, board_list, list)
   spi_match_master_to_boardinfo(master, bi-boardinfo);
 
 It will be less code that way.
 
 Otherwise, this patch looks good to me.  Unfortunately, it's too late
 for 2.6.36, but I'll pick it up into my test branch in prep for the
 2.6.37 cycle.
 
 Cheers,
 g.

Yeah, make much sense! Thanks for the thorough reviews.

- Feng



--
The Palm PDK Hot Apps Program offers developers who use the
Plug-In Development Kit to bring their C/C++ apps to Palm for a share
of $1 Million in cash or HP Products. Visit us here for more details:
http://p.sf.net/sfu/dev2dev-palm
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [PATCH v4] spi: enable spi_board_info to be registered after spi_master

2010-08-02 Thread Feng Tang
Hi All,

Pls review this patch. thanks,

-Feng

Changelog:
v4:
   * Abstract a spi_match_master_to_boardinfo() which will
 be called in scanning master/boardinfo list, suggested
 by Grant also.
v3:
   * As suggested by Grant, use one lock to protect the match
 between spi_master and spi board info
v2:
   * fix a typo in looping scan_masterlist()
   * fix one race condition found by Grant



From 799ff94edc90117afdbba223fb35cb36a1d2b4b4 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Tue, 27 Jul 2010 17:15:05 +0800
Subject: [PATCH] spi: enable spi_board_info to be registered after spi_master

Currently spi_register_board_info() has to be called before its related
spi_master be registered, otherwise these board info will be just ignored.

This patch will remove this order limit, it adds a global spi master list
like the existing global board info listr. Whenever a board info or a
spi_master is registered, the spi master list or board info list
will be scanned, and a new spi device will be created if there is a
master-board info match.

Cc: David Brownell dbrown...@users.sourceforge.net
Cc: Grant Likely grant.lik...@secretlab.ca
Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/spi.c   |   86 +++
 include/linux/spi/spi.h |3 ++
 2 files changed, 60 insertions(+), 29 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b3a1f92..70fb141 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -196,11 +196,16 @@ EXPORT_SYMBOL_GPL(spi_register_driver);
 
 struct boardinfo {
struct list_headlist;
-   unsignedn_board_info;
-   struct spi_board_info   board_info[0];
+   struct spi_board_info   board_info;
 };
 
 static LIST_HEAD(board_list);
+static LIST_HEAD(spi_master_list);
+
+/*
+ * Used to protect add/del opertion for board_info list and
+ * spi_master list, and their matching process
+ */
 static DEFINE_MUTEX(board_lock);
 
 /**
@@ -365,6 +370,30 @@ struct spi_device *spi_new_device(struct spi_master 
*master,
 }
 EXPORT_SYMBOL_GPL(spi_new_device);
 
+static void spi_match_master_to_boardinfo(struct spi_master *master,
+   struct spi_board_info *bi)
+{
+   struct spi_device *dev;
+
+   if (master-bus_num != bi-bus_num)
+   return;
+
+   dev = spi_new_device(master, bi);
+   if (!dev)
+   dev_err(master-dev.parent, can't create new device for %s\n,
+   bi-modalias);
+}
+
+
+/* Has to be called when board_lock is acquired */
+static void spi_scan_masterlist(struct spi_board_info *bi)
+{
+   struct spi_master *master;
+
+   list_for_each_entry(master, spi_master_list, list)
+   spi_match_master_to_boardinfo(master, bi);
+}
+
 /**
  * spi_register_board_info - register SPI devices for a given board
  * @info: array of chip descriptors
@@ -387,43 +416,36 @@ EXPORT_SYMBOL_GPL(spi_new_device);
 int __init
 spi_register_board_info(struct spi_board_info const *info, unsigned n)
 {
-   struct boardinfo*bi;
+   struct boardinfo *bi;
+   int i;
 
-   bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
+   bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);
if (!bi)
return -ENOMEM;
-   bi-n_board_info = n;
-   memcpy(bi-board_info, info, n * sizeof *info);
 
-   mutex_lock(board_lock);
-   list_add_tail(bi-list, board_list);
-   mutex_unlock(board_lock);
+   for (i = 0; i  n; i++, bi++, info++) {
+   memcpy(bi-board_info, info, sizeof(*info));
+   mutex_lock(board_lock);
+   list_add_tail(bi-list, board_list);
+   spi_scan_masterlist(bi-board_info);
+   mutex_unlock(board_lock);
+   }
+
return 0;
 }
 
-/* FIXME someone should add support for a __setup(spi, ...) that
+/*
+ * FIXME someone should add support for a __setup(spi, ...) that
  * creates board info from kernel command lines
+ *
+ * Should be called when board_lock is acquired
  */
-
 static void scan_boardinfo(struct spi_master *master)
 {
-   struct boardinfo*bi;
+   struct boardinfo *bi;
 
-   mutex_lock(board_lock);
-   list_for_each_entry(bi, board_list, list) {
-   struct spi_board_info   *chip = bi-board_info;
-   unsignedn;
-
-   for (n = bi-n_board_info; n  0; n--, chip++) {
-   if (chip-bus_num != master-bus_num)
-   continue;
-   /* NOTE: this relies on spi_new_device to
-* issue diagnostics when given bogus inputs
-*/
-   (void) spi_new_device(master, chip);
-   }
-   }
-   mutex_unlock(board_lock);
+   list_for_each_entry(bi, board_list

[spi-devel-general] [PATCH v3] spi: enable spi_board_info to be registered after spi_master

2010-08-01 Thread Feng Tang
Hi All,

Pls review this patch. thanks,

-Feng

Changelog:
v3:
   * As suggested by Grant, use one lock to protect the match
 between spi_master and spi board info
v2:
   * fix a typo in looping scan_masterlist()
   * fix one race condition found by Grant

From 28af337ec89225a0dfb7ca516545b7eff112e3b2 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Tue, 27 Jul 2010 17:15:05 +0800
Subject: [PATCH] spi: enable spi_board_info to be registered after spi_master

Currently spi_register_board_info() has to be called before its related
spi_master be registered, otherwise these board info will be just ignored.

This patch will remove this order limit, it adds a global spi master list
like the existing global board info listr. Whenever a board info or a
spi_master is registered, the spi master list or board info list
will be scanned, and a new spi device will be created if there is a
master-board info match.

Cc: David Brownell dbrown...@users.sourceforge.net
Cc: Grant Likely grant.lik...@secretlab.ca
Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/spi.c   |   84 --
 include/linux/spi/spi.h |3 ++
 2 files changed, 61 insertions(+), 26 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b3a1f92..8fb2337 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -196,11 +196,16 @@ EXPORT_SYMBOL_GPL(spi_register_driver);
 
 struct boardinfo {
struct list_headlist;
-   unsignedn_board_info;
-   struct spi_board_info   board_info[0];
+   struct spi_board_info   board_info;
 };
 
 static LIST_HEAD(board_list);
+static LIST_HEAD(spi_master_list);
+
+/*
+ * Used to protect add/del opertion for board_info list and
+ * spi_master list, and their matching process
+ */
 static DEFINE_MUTEX(board_lock);
 
 /**
@@ -365,6 +370,24 @@ struct spi_device *spi_new_device(struct spi_master 
*master,
 }
 EXPORT_SYMBOL_GPL(spi_new_device);
 
+/* Has to be called when board_lock is acquired */
+static void spi_scan_masterlist(struct spi_board_info *bi)
+{
+   struct spi_master *master;
+   struct spi_device *dev;
+
+   list_for_each_entry(master, spi_master_list, list) {
+   if (master-bus_num != bi-bus_num)
+   continue;
+
+   dev = spi_new_device(master, bi);
+   if (!dev)
+   dev_err(master-dev.parent,
+   can't create new device for %s\n,
+   bi-modalias);
+   }
+}
+
 /**
  * spi_register_board_info - register SPI devices for a given board
  * @info: array of chip descriptors
@@ -387,43 +410,46 @@ EXPORT_SYMBOL_GPL(spi_new_device);
 int __init
 spi_register_board_info(struct spi_board_info const *info, unsigned n)
 {
-   struct boardinfo*bi;
+   struct boardinfo *bi;
+   int i;
 
-   bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
+   bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);
if (!bi)
return -ENOMEM;
-   bi-n_board_info = n;
-   memcpy(bi-board_info, info, n * sizeof *info);
 
-   mutex_lock(board_lock);
-   list_add_tail(bi-list, board_list);
-   mutex_unlock(board_lock);
+   for (i = 0; i  n; i++, bi++, info++) {
+   memcpy(bi-board_info, info, sizeof(*info));
+   mutex_lock(board_lock);
+   list_add_tail(bi-list, board_list);
+   spi_scan_masterlist(bi-board_info);
+   mutex_unlock(board_lock);
+   }
+
return 0;
 }
 
-/* FIXME someone should add support for a __setup(spi, ...) that
+/*
+ * FIXME someone should add support for a __setup(spi, ...) that
  * creates board info from kernel command lines
+ *
+ * Should be called when board_lock is acquired
  */
-
 static void scan_boardinfo(struct spi_master *master)
 {
struct boardinfo*bi;
+   struct spi_device   *dev;
 
-   mutex_lock(board_lock);
list_for_each_entry(bi, board_list, list) {
-   struct spi_board_info   *chip = bi-board_info;
-   unsignedn;
-
-   for (n = bi-n_board_info; n  0; n--, chip++) {
-   if (chip-bus_num != master-bus_num)
-   continue;
-   /* NOTE: this relies on spi_new_device to
-* issue diagnostics when given bogus inputs
-*/
-   (void) spi_new_device(master, chip);
-   }
+   struct spi_board_info   *chip = bi-board_info;
+
+   if (chip-bus_num != master-bus_num)
+   continue;
+   dev = spi_new_device(master, chip);
+   if (!dev)
+   dev_err(master-dev.parent,
+   can't create new device for %s\n

Re: [spi-devel-general] [PATCH] spi/mpc5121: register spi child devices of spi node

2010-07-27 Thread Feng Tang
On Tue, 27 Jul 2010 14:28:57 +0800
David Brownell davi...@pacbell.net wrote:

 There are things wrong with the concept of this
 particular patch.  First, that it's mpc5121-only.
 Second, that it's not already handled as part of
 registering the platform's SPI devices.
 
 

Hi David, Grant,

This actually brings up another topic: currently spi_register_board_info()
has to be called before spi controller(master) get inited. But in some
case, to solve some device dependency issue, some spi slave device need
be delayed registering, can we adjust it to make register_board_info()
be callable after spi controller is inited? Which makes spi bus like
general pci/usb bus, where devices/drivers have no registering order limit.

Thanks,
Feng

--
The Palm PDK Hot Apps Program offers developers who use the
Plug-In Development Kit to bring their C/C++ apps to Palm for a share 
of $1 Million in cash or HP Products. Visit us here for more details:
http://ad.doubleclick.net/clk;226879339;13503038;l?
http://clk.atdmt.com/CRS/go/247765532/direct/01/
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH] spi/mpc5121: register spi child devices of spi node

2010-07-27 Thread Feng Tang
On Tue, 27 Jul 2010 15:00:29 +0800
Grant Likely grant.lik...@secretlab.ca wrote:

 On Tue, Jul 27, 2010 at 1:14 AM, Feng Tang feng.t...@intel.com
 wrote:
  On Tue, 27 Jul 2010 14:28:57 +0800
  David Brownell davi...@pacbell.net wrote:
 
  There are things wrong with the concept of this
  particular patch.  First, that it's mpc5121-only.
  Second, that it's not already handled as part of
  registering the platform's SPI devices.
 
 
 
  Hi David, Grant,
 
  This actually brings up another topic: currently
  spi_register_board_info() has to be called before spi
  controller(master) get inited. But in some case, to solve some
  device dependency issue, some spi slave device need be delayed
  registering, can we adjust it to make register_board_info() be
  callable after spi controller is inited? Which makes spi bus like
  general pci/usb bus, where devices/drivers have no registering
  order limit.
 
 Is spi_alloc_device()/spi_add_device() not suitable for your use-case?
 
 g.

Yes, I've thought about that, but spi_alloc_device() is called when you
know which spi_master it is connecting to, while our platform need kind
of blind registering (just register something to spi-bus).

Thanks,
Feng

--
The Palm PDK Hot Apps Program offers developers who use the
Plug-In Development Kit to bring their C/C++ apps to Palm for a share 
of $1 Million in cash or HP Products. Visit us here for more details:
http://ad.doubleclick.net/clk;226879339;13503038;l?
http://clk.atdmt.com/CRS/go/247765532/direct/01/
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH] spi/mpc5121: register spi child devices of spi node

2010-07-27 Thread Feng Tang
On Tue, 27 Jul 2010 15:07:28 +0800
David Brownell davi...@pacbell.net wrote:

 
 
 --- On Tue, 7/27/10, Feng Tang feng.t...@intel.com wrote:
 
  be delayed registering, can we adjust it to make
  register_board_info()
  be callable after spi controller is inited? Which makes spi
  bus like
  general pci/usb bus, where devices/drivers have no
  registering order limit.
 
 They require parents to be registered before children.
 In particular:  bus segments before devices on them.
 SPI is no different (nor should it be).
 
Sorry, I made a wrong example. 

What I want to say is the matching mechanism between spi board info
and spi master, currently they use bus number to match, but there is
a ordering limit now. For general device/driver matching in linux
device model, there is no such limit. Is it possible to remove the
order limit?

Thanks,
Feng 

--
The Palm PDK Hot Apps Program offers developers who use the
Plug-In Development Kit to bring their C/C++ apps to Palm for a share 
of $1 Million in cash or HP Products. Visit us here for more details:
http://ad.doubleclick.net/clk;226879339;13503038;l?
http://clk.atdmt.com/CRS/go/247765532/direct/01/
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH] spi/mpc5121: register spi child devices of spi node

2010-07-27 Thread Feng Tang
On Tue, 27 Jul 2010 15:27:50 +0800
David Brownell davi...@pacbell.net wrote:

 
 
 --- On Tue, 7/27/10, Feng Tang feng.t...@intel.com wrote:
 
  What I want to say is the matching mechanism between spi
  board info
  and spi master, currently they use bus number to match, but
  there is
  a ordering limit now. For general device/driver matching in
  linux
  device model, there is no such limit. Is it
  possible to remove the order limit?
 
 
 I have no idea what you mean.  Are you proposing
 to change how SPI busses are identified?  Lots of
 busses are numbered, SPI isn't unique; a device on
 PCI bus #2 is different from one on bus #1, etc.
 
 What do you mean by order limit  
 

In current spi core, spi_register_info() has to be
called before the spi controller driver call spi_register_master(),
then these board info will be matched and used to create a new
spi device.

But if spi_register_info() are called after its related spi master
is registered, then these info will be ignored and never get to
create a new spi device.

This is the order limit I want to describe :)

Thanks,
Feng

--
The Palm PDK Hot Apps Program offers developers who use the
Plug-In Development Kit to bring their C/C++ apps to Palm for a share 
of $1 Million in cash or HP Products. Visit us here for more details:
http://ad.doubleclick.net/clk;226879339;13503038;l?
http://clk.atdmt.com/CRS/go/247765532/direct/01/
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH] spi/mpc5121: register spi child devices of spi node

2010-07-27 Thread Feng Tang
On Tue, 27 Jul 2010 15:44:48 +0800
David Brownell davi...@pacbell.net wrote:

 
 
 --- On Tue, 7/27/10, Feng Tang feng.t...@intel.com wrote:
 
 
 
  In current spi core, spi_register_info() has to be
  called before the spi controller driver call
  spi_register_master(),
  then these board info will be matched and used to create a new spi
  device.
  
  But if spi_register_info() are called after its related spi master
  is registered, then these info will be ignored
  and never get to create a new spi device.
 
 That doesn't seem necessary.  Got patch?
 
 

I would first discuss it on mail list and get bless from you two.

I will try to make one patch.

Thanks,
Feng 


--
The Palm PDK Hot Apps Program offers developers who use the
Plug-In Development Kit to bring their C/C++ apps to Palm for a share 
of $1 Million in cash or HP Products. Visit us here for more details:
http://ad.doubleclick.net/clk;226879339;13503038;l?
http://clk.atdmt.com/CRS/go/247765532/direct/01/
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [PATCH] spi: enable spi_board_info to be registered after spi_master

2010-07-27 Thread Feng Tang
Currently spi_register_board_info() has to be called before its related
spi_master be registered, otherwise these board info will be just ignored.

This patch will remove this order limit, it adds a global spi master list
like the existing global board info listr. Whenever a board info is
registered, the spi master list will be scanned, and a new spi device will
be created if they match.

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/spi.c   |   66 +-
 include/linux/spi/spi.h |3 ++
 2 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b3a1f92..f4a5221 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -196,13 +196,16 @@ EXPORT_SYMBOL_GPL(spi_register_driver);
 
 struct boardinfo {
struct list_headlist;
-   unsignedn_board_info;
-   struct spi_board_info   board_info[0];
+   struct spi_board_info   board_info;
 };
 
 static LIST_HEAD(board_list);
 static DEFINE_MUTEX(board_lock);
 
+
+static LIST_HEAD(master_list);
+static DEFINE_MUTEX(master_lock);
+
 /**
  * spi_alloc_device - Allocate a new SPI device
  * @master: Controller to which device is connected
@@ -365,6 +368,19 @@ struct spi_device *spi_new_device(struct spi_master 
*master,
 }
 EXPORT_SYMBOL_GPL(spi_new_device);
 
+static void scan_masterlist(struct spi_board_info *bi)
+{
+   struct spi_master *master;
+
+   mutex_lock(master_lock);
+   list_for_each_entry(master, master_list, list) {
+   if (master-bus_num != bi-bus_num)
+   continue;
+   (void) spi_new_device(master, bi);
+   }
+   mutex_unlock(master_lock);
+}
+
 /**
  * spi_register_board_info - register SPI devices for a given board
  * @info: array of chip descriptors
@@ -387,41 +403,45 @@ EXPORT_SYMBOL_GPL(spi_new_device);
 int __init
 spi_register_board_info(struct spi_board_info const *info, unsigned n)
 {
-   struct boardinfo*bi;
+   struct boardinfo*bi, *tmp_bi;
+   int i;
 
-   bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
+   bi = kzalloc(n * sizeof *bi, GFP_KERNEL);
if (!bi)
return -ENOMEM;
-   bi-n_board_info = n;
-   memcpy(bi-board_info, info, n * sizeof *info);
 
+   tmp_bi = bi;
mutex_lock(board_lock);
-   list_add_tail(bi-list, board_list);
+   for (i = 0; i  n; i++, bi++, info++) {
+   memcpy(bi-board_info, info, sizeof *info);
+   list_add_tail(bi-list, board_list);
+   }
mutex_unlock(board_lock);
+
+   bi = tmp_bi;
+   for (i = 0; i  n; i++)
+   scan_masterlist(bi-board_info);
+
return 0;
 }
 
 /* FIXME someone should add support for a __setup(spi, ...) that
  * creates board info from kernel command lines
  */
-
 static void scan_boardinfo(struct spi_master *master)
 {
struct boardinfo*bi;
 
mutex_lock(board_lock);
list_for_each_entry(bi, board_list, list) {
-   struct spi_board_info   *chip = bi-board_info;
-   unsignedn;
-
-   for (n = bi-n_board_info; n  0; n--, chip++) {
-   if (chip-bus_num != master-bus_num)
-   continue;
-   /* NOTE: this relies on spi_new_device to
-* issue diagnostics when given bogus inputs
-*/
-   (void) spi_new_device(master, chip);
-   }
+   struct spi_board_info   *chip = bi-board_info;
+
+   if (chip-bus_num != master-bus_num)
+   continue;
+   /* NOTE: this relies on spi_new_device to
+* issue diagnostics when given bogus inputs
+*/
+   (void) spi_new_device(master, chip);
}
mutex_unlock(board_lock);
 }
@@ -537,6 +557,10 @@ int spi_register_master(struct spi_master *master)
dev_dbg(dev, registered master %s%s\n, dev_name(master-dev),
dynamic ?  (dynamic) : );
 
+   mutex_lock(master_lock);
+   list_add_tail(master-list, master_list);
+   mutex_unlock(master_lock);
+
/* populate children from any spi device tables */
scan_boardinfo(master);
status = 0;
@@ -568,6 +592,10 @@ void spi_unregister_master(struct spi_master *master)
 {
int dummy;
 
+   mutex_lock(master_lock);
+   list_del(master-list);
+   mutex_unlock(master_lock);
+
dummy = device_for_each_child(master-dev.parent, master-dev,
__unregister);
device_unregister(master-dev);
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index af56071..f4a29b6 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -204,6 +204,7 @@ static inline void spi_unregister_driver(struct

Re: [spi-devel-general] [PATCH] spi: enable spi_board_info to be registered after spi_master

2010-07-27 Thread Feng Tang
Hi Grant,

Thanks for your thorough reviews!

Will address most of the comments.



On Wed, 28 Jul 2010 01:27:16 +0800
Grant Likely grant.lik...@secretlab.ca wrote:

 
 for (i = 0, tmp_bi = bi; i  n; i++, tmp_bi++, info++)
 
  +               memcpy(bi-board_info, info, sizeof *info);
  +               list_add_tail(bi-list, board_list);
  +       }
         mutex_unlock(board_lock);
  +
  +       bi = tmp_bi;
  +       for (i = 0; i  n; i++)
  +               scan_masterlist(bi-board_info);
 
 How does this work?  The same board_info struct is passed to
 scan_masterlist() multiple times.

My bad, I tested 2 cases by calling register_board_info before and
after spi_register_master(), but only with one spi device. Will fix it


  @@ -537,6 +557,10 @@ int spi_register_master(struct spi_master
  *master) dev_dbg(dev, registered master %s%s\n,
  dev_name(master-dev), dynamic ?  (dynamic) : );
 
  +       mutex_lock(master_lock);
  +       list_add_tail(master-list, master_list);
  +       mutex_unlock(master_lock);
  +
 
 There seems to be a race condition here.  If a boardinfo is registered
 after this list add, but before scan_boardinfo(master), then a
 boardinfo can get parsed twice for a single master.  I think the
 proper thing to do is to hold the mutex over the whole operation; from
 registering the list or master, until after the scan is complete.
 

Good point. Maybe moving the list_add(master) after scan_boardinfo() 
can fix this race condition.

Thanks,
Feng

--
The Palm PDK Hot Apps Program offers developers who use the
Plug-In Development Kit to bring their C/C++ apps to Palm for a share 
of $1 Million in cash or HP Products. Visit us here for more details:
http://ad.doubleclick.net/clk;226879339;13503038;l?
http://clk.atdmt.com/CRS/go/247765532/direct/01/
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH] spi: enable spi_board_info to be registered after spi_master

2010-07-27 Thread Feng Tang
On Wed, 28 Jul 2010 09:23:06 +0800
Feng Tang feng.t...@intel.com wrote:

   @@ -537,6 +557,10 @@ int spi_register_master(struct spi_master
   *master) dev_dbg(dev, registered master %s%s\n,
   dev_name(master-dev), dynamic ?  (dynamic) : );
  
   +       mutex_lock(master_lock);
   +       list_add_tail(master-list, master_list);
   +       mutex_unlock(master_lock);
   +
  
  There seems to be a race condition here.  If a boardinfo is
  registered after this list add, but before scan_boardinfo(master),
  then a boardinfo can get parsed twice for a single master.  I think
  the proper thing to do is to hold the mutex over the whole
  operation; from registering the list or master, until after the
  scan is complete.
  
 
 Good point. Maybe moving the list_add(master) after scan_boardinfo() 
 can fix this race condition.

My solution still has problem, it was:

scan_boardinfo(master);

mutex_lock(spi_master_lock);
list_add_tail(master-list, spi_master_list);
mutex_unlock(spi_master_lock);

If another boardinfo registering just after scan_boardinfo() but before
list_add(), it will still get ignored.

I will just follow Grant's suggestion.

Thanks,
Feng

--
The Palm PDK Hot Apps Program offers developers who use the
Plug-In Development Kit to bring their C/C++ apps to Palm for a share 
of $1 Million in cash or HP Products. Visit us here for more details:
http://ad.doubleclick.net/clk;226879339;13503038;l?
http://clk.atdmt.com/CRS/go/247765532/direct/01/
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [PATCH v2] spi: enable spi_board_info to be registered after spi_master

2010-07-27 Thread Feng Tang
Currently spi_register_board_info() has to be called before its related
spi_master be registered, otherwise these board info will be just ignored.

This patch will remove this order limit, it adds a global spi master list
like the existing global board info listr. Whenever a board info is
registered, the spi master list will be scanned, and a new spi device will
be created if master and boardinfo match.

Cc: David Brownell dbrown...@users.sourceforge.net
Cc: Grant Likely grant.lik...@secretlab.ca
Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/spi.c   |   73 ++-
 include/linux/spi/spi.h |3 ++
 2 files changed, 56 insertions(+), 20 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b3a1f92..1266fb2 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -196,13 +196,16 @@ EXPORT_SYMBOL_GPL(spi_register_driver);
 
 struct boardinfo {
struct list_headlist;
-   unsignedn_board_info;
-   struct spi_board_info   board_info[0];
+   struct spi_board_info   board_info;
 };
 
 static LIST_HEAD(board_list);
 static DEFINE_MUTEX(board_lock);
 
+
+static LIST_HEAD(spi_master_list);
+static DEFINE_MUTEX(spi_master_lock);
+
 /**
  * spi_alloc_device - Allocate a new SPI device
  * @master: Controller to which device is connected
@@ -365,6 +368,25 @@ struct spi_device *spi_new_device(struct spi_master 
*master,
 }
 EXPORT_SYMBOL_GPL(spi_new_device);
 
+static void spi_scan_masterlist(struct spi_board_info *bi)
+{
+   struct spi_master *master;
+   struct spi_device *dev;
+
+   mutex_lock(spi_master_lock);
+   list_for_each_entry(master, spi_master_list, list) {
+   if (master-bus_num != bi-bus_num)
+   continue;
+
+   dev = spi_new_device(master, bi);
+   if (!dev)
+   dev_err(master-dev.parent,
+   can't create new device for %s\n,
+   bi-modalias);
+   }
+   mutex_unlock(spi_master_lock);
+}
+
 /**
  * spi_register_board_info - register SPI devices for a given board
  * @info: array of chip descriptors
@@ -387,41 +409,45 @@ EXPORT_SYMBOL_GPL(spi_new_device);
 int __init
 spi_register_board_info(struct spi_board_info const *info, unsigned n)
 {
-   struct boardinfo*bi;
+   struct boardinfo *bi, *tmp_bi;
+   int i;
 
-   bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
+   bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);
if (!bi)
return -ENOMEM;
-   bi-n_board_info = n;
-   memcpy(bi-board_info, info, n * sizeof *info);
 
mutex_lock(board_lock);
-   list_add_tail(bi-list, board_list);
+   for (i = 0, tmp_bi = bi; i  n; i++, tmp_bi++, info++) {
+   memcpy(tmp_bi-board_info, info, sizeof(*info));
+   list_add_tail(tmp_bi-list, board_list);
+   }
mutex_unlock(board_lock);
+
+   for (i = 0, tmp_bi = bi; i  n; i++, tmp_bi++)
+   spi_scan_masterlist(tmp_bi-board_info);
+
return 0;
 }
 
 /* FIXME someone should add support for a __setup(spi, ...) that
  * creates board info from kernel command lines
  */
-
 static void scan_boardinfo(struct spi_master *master)
 {
struct boardinfo*bi;
+   struct spi_device   *dev;
 
mutex_lock(board_lock);
list_for_each_entry(bi, board_list, list) {
-   struct spi_board_info   *chip = bi-board_info;
-   unsignedn;
-
-   for (n = bi-n_board_info; n  0; n--, chip++) {
-   if (chip-bus_num != master-bus_num)
-   continue;
-   /* NOTE: this relies on spi_new_device to
-* issue diagnostics when given bogus inputs
-*/
-   (void) spi_new_device(master, chip);
-   }
+   struct spi_board_info   *chip = bi-board_info;
+
+   if (chip-bus_num != master-bus_num)
+   continue;
+   dev = spi_new_device(master, chip);
+   if (!dev)
+   dev_err(master-dev.parent,
+   can't create new device for %s\n,
+   chip-modalias);
}
mutex_unlock(board_lock);
 }
@@ -537,15 +563,18 @@ int spi_register_master(struct spi_master *master)
dev_dbg(dev, registered master %s%s\n, dev_name(master-dev),
dynamic ?  (dynamic) : );
 
+   mutex_lock(spi_master_lock);
+   list_add_tail(master-list, spi_master_list);
/* populate children from any spi device tables */
scan_boardinfo(master);
+   mutex_unlock(spi_master_lock);
+
status = 0;
 done:
return status;
 }
 EXPORT_SYMBOL_GPL(spi_register_master);
 
-
 static int __unregister(struct device *dev

Re: [spi-devel-general] [PATCH v1 3/4] max3100: adds console support for MAX3100

2010-03-30 Thread Feng Tang
On Tue, 30 Mar 2010 14:49:57 +0800
christian pellegrin chrip...@fsfe.org wrote:

 On Tue, Mar 30, 2010 at 4:14 AM, Feng Tang feng.t...@intel.com
 wrote:
  On Mon, 29 Mar 2010 20:55:51 +0800
 
  When the HW works at 230400 bps, when we copy bulk data to the
  console, max3110 will probably receive about 20K characters, so the
  time for handling each char is 50us. If you use one char per spi
  transfer, it will have to execute 20K spi_transfer in one second,
  and each need be done in 50us, in this 50us you'll have to deal
  with controller IRQ handler + spi system overhead + tty receiving
  overhead. Is it a little over-killing to use one char per spi
  transfer? while the HW does have a 8 words RX FIFO
 
 this is too hackish, max3100 wasn't conceived this way. Let me point
 some problems of such an approach:
 
 1) latency on rx chars becomes very high because we can process
 incoming transfers only after a full 8 byte (or whatever the spi
 transfer dimension is). For a 9600 this is too much.
 
 2) even worse is that we can do flow control decision only on such
 boundary.
 
 3) this is not reliable: think of what happens if the actual SPI
 transfer speed we get will be slower that the one we requested. We
 won't be emptying the RX buffer fastly enough even if could.
 
 4) for low speeds we are going to monopolize the SPI bus for ages.

No words in my last email suggested to use dynamic SPI clock speed,
I admited that method is brutal and not mature when my driver was
reviewed. In early version of our 3110 driver, we don't use dynamic
clock speed, but the maxim clock supports by 3110, while we still use 
8 words buffer read for RX.

Let me cut my question clear: why not use the 8 words RX HW fifo? For
bulk RX in 230400 case, is 50us enough to handle controller IRQ +
spi subsystem overhead + tty receive overhead for one char per spi
transfer model?

 
 So I'm rather convinced that the SPI transfer has to happen as soon as
 possible at a SPI device driver level without any guess on how the
 data will be clocked out. I suggest you to improve the dw_spi driver
 for better performance.
Will consider that, thanks

 
  [[    ..00  iiuu  eessoo  44rr11((eeggffnn--77
   ggccvvrriinn11((bbnnuu1144bbnnuu [[    ..00
   BBOO--8800  1100--8800  uuaall))
 
 huh, here I'm seeing another kind of problem: the same char is
 repeated two times (for example BBOO is written instead of BIOS). I'm
 quite sure (but I will triple check shortly) the the console driver
 doesn't do this (it's quite an easy loop in max3100_console_work, I
 will check wit a printascii to another serial port what is sent). So I
 guess the problem can be in the SPI master driver: is it correctly
 handling the CS changes? Isn't it having problems with DMA for example
 (I always found DMA for small data transfer (such 2 bytes in this
 case) problematic (for example many platforms just do it on a 4 byte
 boundary))? Have you tested it with other devices?
 
Yes, the controller HW has a register to chose slave devices and thus
the HW CS handling is transparent to software. The controller supports several
slave devices connecting to it simultaneously, one is a 3G modem whose
throughput is about several Mega bits. The current in-tree controller driver
lacks DMA part, which is rejected as the related DMA controller driver never
show up publicly.



--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v1 3/4] max3100: adds console support for MAX3100

2010-03-29 Thread Feng Tang
On Mon, 29 Mar 2010 14:11:15 +0800
christian pellegrin chrip...@fsfe.org wrote:

  I modified the code a little and run it on our HW platform, it
  really show some sigh of life: it can boots to console (the print
  format is not so good), I can input command and it execute
  correctly, but very slow, I type 3 characters and it takes about 2
  seconds to echo back on screen and start the execution, and after
  about 1 minute, the console hang there and input stopped to work.
 
 never seen such a behavior. Which platform are you using? Which SPI
 driver? Do you have a low level printk (printascii) that puts output
 somewhere else so I can send you a patch with some debugging output?
 Can you log in some other way (like via network) and see if the CPU
 load is at 100% for some reason?

Hi,

Our platform is Intel Moorestown platform, and use a spi controller core
from Designware (drivers/spi/dw_*.c). I know the problem may probably be
caused by my setting, but the dw_spi driver works fine with our own
3110 driver.

For debug method, sadly I don't get another output port yet, but if you
have some debug patch, that's great, it will help when I find another debug
output than max3110.

 
  +             max3100_sr(s, tx, rx);
 
  It doesn't handle received characters here? If the console is
  printing out a bulk of message while user input some command, the
  command may be ignored. Myself have met the same problem in our
  driver.
 
 
 yes but I think it's quite difficult to solve this problem in every
 case. Console output is massively used only on boot when the user is
 not supposed to type a lot.

It's difficult but not impossible, actually our driver checks every word
read back and handle it if it contains a valid data

 
  +     if (next != s-console_tail) {
  +             s-console_buf[next] = ch;
  +             s-console_head = next;
  +     }
 
  Also I saw max3100_sr() uses cpu_to_be16() and be16_to_cpu(), is it
  really necessary, our platform is little-endian(x86), and I have to
  disable them to make the code work. Is your test platform
  big-endian?
 
 
 Have you configured your SPI controller as LSB first somehow, haven't
 you? BTW my platform is a quite usual ARM9 S3C2440 which is little
 endian.

yeah, you hit the point that our spi controller is LSB naturally (not
configured to), here may need a check for whether to do a swap


--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v1 3/4] max3100: adds console support for MAX3100

2010-03-29 Thread Feng Tang
On Mon, 29 Mar 2010 20:55:51 +0800
christian pellegrin chrip...@fsfe.org wrote:

 On Mon, Mar 29, 2010 at 9:06 AM, Feng Tang feng.t...@intel.com
 wrote:
 
  Our platform is Intel Moorestown platform, and use a spi controller
  core from Designware (drivers/spi/dw_*.c). I know the problem may
  probably be caused by my setting, but the dw_spi driver works fine
  with our own 3110 driver.
 
 I had a look at the dw_spi driver. The spi_transfer path queues some
 work to a worqueue that itself schedules a tasklet. I don't think this
 is good for latency, I won't bet that such an architecture could
 deliver good performance. Now I see why you needed to do only big fat
 SPI transfers. Anyway this doesn't justify the 2 seconds delay between
Hi

DW controller driver don't need max3110 driver to use big spi transfer,
the early version of our max3110 is also one word per spi transfer mode,
and the 2 drivers work fine, though the rx performance is not good (copy
 paste a bulk message to console).

Let me use some example to explain why I use big spi transfer for 3110:

When the HW works at 230400 bps, when we copy bulk data to the console,
max3110 will probably receive about 20K characters, so the time for
handling each char is 50us. If you use one char per spi transfer, it
will have to execute 20K spi_transfer in one second, and each need be
done in 50us, in this 50us you'll have to deal with controller IRQ 
handler + spi system overhead + tty receiving overhead. Is it a little
over-killing to use one char per spi transfer? while the HW does
have a 8 words RX FIFO 

 chars coming in and going out through the max31x0 you are seeing. I
 will try to analyze what's going on. BTW is only input slow or output
 is sluggish too? The initial messages from the console are coming out
 fast? If you disable the MAX3110 for console but you use just as a
 normal terminal (set console=/dev/null in the kernel command line and
 add getty 115200 /dev/ttyMAX0 in iniitab) is the interaction with the
 system fine? Thanks for helping sorting out this.

The output is not so slow as input, if we set the console=/dev/ttyMAX0,
the output is sluggish, looks like below, but when enter command line
console the output is smooth, while the input is very slow.

--
   kernel print log of max3100 over Moorestown platform
--

0.00] Moorestown CPU Lincroft identified
[[..00  iiuu  eessoo  44rr11((eeggffnn--77  
ggccvvrriinn11((bbnnuu1144bbnnuu
[[..00  BBOO--8800  1100--8800  uuaall))


]]  IISSee22::00
11 - 0f200 (usabl))
   [ .000  BIOS-e822:: 
022000110
00((eserved)
[0.00]  BIISSe820:: ee0 --0fec01000 (reseree))

  
]]  IISSee200
[[..00  BBOO--8800  ff00--  rrssrree))

  
]]NNttcc::NN
[[..00  8800uuddtt  aagg::((ssbbee  
==  rrssrree))


  00
00]]ee22  eeooeerrnnee  00aa--0011  uuaall))


]]llss__ffxx
2200mmxxaacc__ffxx00

]]MMRR  eeaall  yyee  nnaahhbbee


]]MMRR  iiee  aa
[[..00--  rrtt--aakk

[[..00--  rrtt--aakk]]  AABBuuaall

]]MMRR  aaiibbeerrnnee  
nnbbee::




 1) the console code has to check if the serial port associated to the
 same physical max3100 is up (console driver start their life much
 before serial ones).
 
 2) if yes send data to the tty associated to the serial driver.
 Locking is needed here.
 
 I will implement this ASAP.

cool!


--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH 3/3] max3100: adds console support for MAX3100

2010-03-21 Thread Feng Tang
On Fri, 19 Mar 2010 16:39:57 +0800
Christian Pellegrin chrip...@fsfe.org wrote:

 +#ifdef CONFIG_SERIAL_MAX3100_CONSOLE
 +
 +static void max3100_console_putchar(struct uart_port *port, int ch)
 +{
 + struct max3100_port *s = container_of(port, struct
 max3100_port, port);
 + unsigned long tout = 10 * HZ / 1000; /* 10ms */
 + unsigned long start;
 + u16 tx, rx;
 +
 + if (tout == 0)
 + tout = 1;
 + start = jiffies;
 + do {
 + tx = MAX3100_RC;
 + max3100_sr(s, tx, rx);

Hi Christian,

You'd better not call max3110_sr (which calls spi_sync) here, a console's
putchar() func may be called in some atomic context.

I used similar method when I started to implement a console, but then I switch
to current method in my 3110 driver: save the printk buffer inside putchar,
and wake up a thread to really handle the spi transfer later.

Thanks,
Feng
 + } while ((rx  MAX3100_T) == 0 
 +  !time_after(jiffies, start + tout));
 + tx = ch;
 + max3100_calc_parity(s, tx);
 + tx |= MAX3100_WD | MAX3100_RTS;
 + max3100_sr(s, tx, rx);
 +}
 +
 +static void max3100_console_write(struct console *co,
 +   const char *str, unsigned int
 count) +{
 + struct max3100_port *s = max3100s[co-index];;
 +
 + uart_console_write(s-port, str, count,
 max3100_console_putchar); +}


--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v6] serial: spi: add spi-uart driver for Maxim 3110

2010-03-17 Thread Feng Tang
On Wed, 17 Mar 2010 15:39:23 +0800
christian pellegrin chrip...@gmail.com wrote:

 On Wed, Mar 17, 2010 at 3:35 AM, Feng Tang feng.t...@intel.com
 wrote:
  Hi Christian,
 
 Hi,
 
  your driver is posted on public. And the reasons I still posted
  driver here are: 1. It provides a console
 
 I'll provide a patch to the mainline driver for the console. Let me
 just finish my daily job duties ;-)

Cool!! I can test that on my platform.

 
  2. It use buffer read/write to meet our performance goal, max3110
  doesn't have good FIFO, but spi controller have and we can leverage
  that for performance
 
 I think this line of thinking is wrong. SPI generic layer is well 
 generic. For example the platform I use is the S3C24xx which has a SPI
 shift register depth of just one byte. And using DMA is not an option
 because the setup of a DMA transfer takes tens of microseconds.
 Additionally the SPI driver in mainline is based on bit-banging which
 uses workqueues and so is limited by the fact that it fights with
 other sched_other processes. Unfortunately an alternative driver which
 was posted never got mainlined and we, who need it, have to maintain
 it ourself. But this is another story, the bottom line is that we have
 to cope with the most basic SPI support we can meet.

I'm no your side suggesting not to use DMA for 3110/3100, but David and
others have a valid point, we don't know what kind of SPI controller that
this driver will work with, and the driver has to be as general and
compatible as possible.

 
  this is exactly the problem I was facing: loosing chars on RX. I
 tracked the problem to a too long latency in awakening of the
 workqueue (the RX FIFO of the MAX3100 overflows). I will post shortly
 a patch that moves this to threaded interrupts which solved the
 problem on the S3C platform I mentioned above working at 115200. A
 quick and dirty fix for workqueues is posted here:
 http://www.evolware.org/chri/paciugo/index.html. Anyway it has to do
 with scheduling of processes so many more factors are concerned, like
 HZ and preemption being enabled.
 
 I will post some tests together with the patch, if you have some
 benchmarks you like to be run don't hesitate to send them. Thanks in
 advance!

heh, I don't have benchmarks but simply the copy/paste stuff and using
zmodem sometimes.
 
  I don't think this is a good idea to change speed. Just check the T
  bit to see when the TX buffer is empty and send at the maximum
  available speed. So the usage of the SPI bus is better.
  Yes, checking T bit is a good idea for single word transfer model,
  but it doesn't help when using buffer read/write
 
 I really don't understand why, can you elaborate on this?

Checking T bit has to be done in word level, send one word out, read one
back and check T bit inside one spi xfer.

Why not use the buffer model, the HW has a 8 words RX buffer, why not read
8 words back in one spi xfer, saving a lot of system cost. And if we make
the spi clk slightly slower than the baud rate, there will be no TX
overflow problem. 

 
  I didn't use kmalloc/kfree in my earlier submission, but other
  developers mentioned the buffer allocated here need be DMA safe, as
  3110 may work with many kinds of SPI controller, some of them only
  supports DMA mode.
 
 
 why you don't preallocate buffer for SPI transfers that are DMA-safe?
 For example the mcp251x driver
 (http://lxr.free-electrons.com/source/drivers/net/can/mcp251x.c?v=2.6.34-rc1)
 does this.
Some function will be called in several places, say re-entered, hard to use
a preallocate buffer.

 
  I guess you are using mthread_up to avoid awakening the main thread
  too many times. But this makes sense? Anyway because the awakening
  and the setting of the bit is not atomic it won't work anyway.
  Why this can't work? the test/set_bit are atomic operations. This
  bit check is not exclusive, it just try to save some waking up,
  though waking a already running thread doesn't cost too much as
  mentioned by Andrew
 
 First of all I think that the cost of re-awakening an already running
 thread is lower than the logic of testing bits. My note was just
 nit-picking: there is a window between when the task was woken-up and
 where you set the bit, so it doesn't guarantee you that you aren't
 awakening the thread more than once anyway.

OK, got your point now. test/set_bit's cost depends on the platform, 
and my simple test using perf tool showing it cost 10us level to wake
a running thread.
Anyway, re-wake it does no harm :)

Thanks,
Feng


--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general

Re: [spi-devel-general] [PATCH v6] serial: spi: add spi-uart driver for Maxim 3110

2010-03-16 Thread Feng Tang
Hi Christian,

Thanks for taking time to review the driver. Please see my answers inline

- Feng
On Wed, 17 Mar 2010 01:22:46 +0800
christian pellegrin chrip...@gmail.com wrote:

 On Thu, Mar 4, 2010 at 8:22 AM,
 spi-devel-general-requ...@lists.sourceforge.net wrote:
 
 
  Hi All,
 
 
 Hi, first of all let me apologize that I haven't see your previous
 versions of the driver. I completely missed them. I am the author of
 the max3100 driver. As far as I can see the max3110 is just a max3100
 with the TTL to EIA level converter. So, first of all, may I ask why
 you did start a new driver from scratch? I'm quite happy with the
I don't want to reinvent the wheel, as I have many more tasks to handle :)
My 3110 driver started to work in 2008(surely very basic at that time) before
your driver is posted on public. And the reasons I still posted driver here are:
1. It provides a console
2. It use buffer read/write to meet our performance goal, max3110 doesn't have
good FIFO, but spi controller have and we can leverage that for performance 

If we can cooperate to make current 3100 driver meet our expectation, I'm more
than happy to drop my 3110 one. I'd rather submit some bug fix for it than
posting 6 or more versions of code :)

 current one, the only problem I see is that it uses worqueues which
 are scheduled like normal processes and so under load their latency is
 *big*. I wanted to move to threaded interrupts (otherwise you have to
 use some ugly tricks to give workqueue threads real-time scheduling
 class) but was waiting for my beta testers^H^H^H^H^H^H^H^H^H^H^H^H^H
 customers to move to modern kernel that support them. Anyway the patch
 is trivial and I can provide it if there is some interest. A quick
 glance at your patch shows you are using the same sched_other threads
 so you will face the same problems. I saw you added console capability
 which isn't present in current driver, but it's easy to add (I didn't
 implement it initially because I don't see a good idea using the
 max3100 for initial bring-up of an embedded system because it relies
 on the SPI subsystem, worqueues, scheduler and such complicated
 things). Anyway keep in mind that the MAX3100 is rather low-end UART
 so don't push it too much.
It's not me push it too much, but I was pushed too much :)
We can't make the decision how the HW is used on all kinds of platforms. For
ours, we heavily rely on it as a sole console, and basic requirement is:
the datasheet say it supports 230400~300 baud rate, then driver guy need make
it work as it claims, like copying 500 bytes string somewhere and paste it on
this console in 230400/600 rate.

For the kernel early boot phase debug, I actually had another 3110
early_printk patch which can work right after the kernel starts

 
 I'm more than happy to work with you to have just one perfect (or
 almost perfect) driver instead of two of them half-done. See some
 comments inline.
Can't agree more, all I want is just a upstream driver which meets the basic
requirement.

 
  + * 1. From Max3110 spec, the Rx FIFO has 8 words, while the Tx
  FIFO only has
  + *    1 word. If SPI master controller doesn't support sclk
  frequency change,
  + *    then the char need be sent out one by one with some delay
 
 I don't think this is a good idea to change speed. Just check the T
 bit to see when the TX buffer is empty and send at the maximum
 available speed. So the usage of the SPI bus is better.
Yes, checking T bit is a good idea for single word transfer model, but it
doesn't help when using buffer read/write

 
  + *
  + * 2. Currently only RX availabe interrrupt is used
 
 yeah, this is one of the reasons why MAX31x0 sucks: when you change
 configuration of interrupts the  RX buffer is cleared. So you cannot
 activate/deactivate TX empty interrupt as needed.
 
  +static int use_irq = 1;
  +module_param(use_irq, int, 0444);
  +MODULE_PARM_DESC(use_irq, Whether using Max3110's IRQ
  capability);
 
 I don't think it's a good idea using an UART in polling mode, it just
 kills the system. Just pretend this is not possible otherwise some
 hardware guys will pester us to do this just to save an electric wire.
Yes, like Grant and others have mentioned, I plan to use spi-irq as the
condition, platform code which initialize the board_info should clear the
irq to 0 if they won't use IRQ for 3110

if (spi-irq)
request_irq(spi-irq,...);
else
start_read_thread;

 
 
  +       buf = kmalloc(8, GFP_KERNEL | GFP_DMA);
 
 you do kmalloc and kfree in routines that are called in quite tight
 loops: I guess it's an overkill for performance.

Overkill is just the word I have used when replying comments on my
earlier version :)

I didn't use kmalloc/kfree in my earlier submission, but other developers
mentioned the buffer allocated here need be DMA safe, as 3110 may work
with many kinds of SPI controller, some of them only supports DMA mode.

 
 are you sure it's sane to just ignore these 

Re: [spi-devel-general] [PATCH v6] serial: spi: add spi-uart driver for Maxim 3110

2010-03-11 Thread Feng Tang
On Mon, 8 Mar 2010 12:30:13 +0800
Grant Likely grant.lik...@secretlab.ca wrote:

 Hi Feng,
 
 I'm really concerned with this driver.  I think it needs a lot more
 work before it is ready for prime-time.  Again, you might want to
 consider asking Greg to add it to the staging tree while you clean
 stuff up and coordinate with the max3100 driver author.
 
 Comments below.

Hi Grant,

Thanks for the comments, will address them in future submission.

For your suggestion about merging with max3100.c, I did tried but failed
as the basic working model differ a lot, anyway I will recheck that.

- Feng 

--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v6] serial: spi: add spi-uart driver for Maxim 3110

2010-03-11 Thread Feng Tang
On Mon, 8 Mar 2010 12:12:34 +0800
Grant Likely grant.lik...@secretlab.ca wrote:


 
  Yep, here you touched a key point of the driver.
 
  In the early version of our driver, we used a fixed spi rate which
  is a little owner than its own working rate (3.684MHz) as a spi
  controller can hardly get a divided rate exactly same as 3110's
  clock , with that we can only handle one word per spi transfer, and
  have to add a udelay function for each transfer, and we even have
  to calculate the delay time for all kinds of the UART baud rate
  it's working with. struct spi_transfer has a member deay_usecs
  just for this case.
 
  One key point for SPI devices is they can't be accessed by CPU
  directly and has to go though tasklet or workqueue for each spi
  transfer. To improve performance, we chose to use buffer read/write
  to let one transfer contain more data, and use dynamic spi rate by
  setting spi_transfer-speed_hz for each baud rate accordingly.
  spi rate is set by spi controller drivers based on the speed_hz
  number and they should chose a lower spi rate than 3110's baud rate
  if can't find a same rate. For a spi controller support multiple
  devices including 3110, the delay from 3110 is inevitable no matter
  we use a explicit udelay or the dynamic spi rate.
 
  Till here, I have to say the spi_transfer of spi core is well
  designed, which provides bits_per_word/delay_usecs/speed_hz of
  great flexibility for developing spi device/controller drivers
 
 You're abusing the speed_hz setting of the SPI controller.  By
 clocking down the SPI bus, you're effectively using the SPI completion
 interrupt as a high resolution timer to schedule your character
 transmissions so that you don't overrun the max3110 which has no tx
 fifo.  Using a udelay is also the wrong thing to do because it chews
 up CPU cycles to achieve the same result.
 
 The correct thing to do is to either use a high resolution timer, or
 the IRQ from the MAX3110 itself to schedule your spi transfers, and
 set the SPI rate to the highest frequency that the MAX3110 can handle
 so that your driver neither hogs the SPI bus, nor wastes CPU cycles.
 You can improve the performance of the driver by using spi_async()
 instead of spi_sync() it enqueue the transfers so that you can handle
 everything at IRQ context and you don't need to drop into a workqueue
 to process the data.

Yes, using a high resolution timer instead of udelay is definitely better.
The reason we didn't use it is the delay for 115200 bps is about 90us,
which is shorter than the time of executing an hr_timer(IRQ handling and
precess waking stuff), but it's our HW's problem anyway.

But this doesn't help on buffer read/write, and only works for one word per
spi_transfer model as 3110 only has 1 word TX buffer and 8 word RX buffer.
We normally use such a test case, Ctrl+C a big string (500 Bytes), and Ctrl+V
it on the 3110 console, check if they are correctly received and echoed on
screen, one word per transfer can hardly make that, due to the cost in spi
layer and tty layer, while buffer read/write model can.

If speed_hz are not for this case, then where should it be used for,
spi core already has max_speed_hz specifying the maxim clock permitted by
HW. Using speed_hz does affect other devices connecting to the same controller,
but can we provide an option for the platform code to chose whether dynamic
lower spi clk is allowed, in case the spi controller has only 3110 as its
slave device.

Thanks,
Feng 
 
 
 g.

--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v6] serial: spi: add spi-uart driver for Maxim 3110

2010-03-07 Thread Feng Tang
On Fri, 5 Mar 2010 15:44:50 +0800
Erwin Authried ea...@softsys.co.at wrote:

 
 The spi rate and the uart clock aren't synchronized, what happens if
 the spi rate is slightly higher than the MAX3100's baud rate clock?
 In addition, if there are other devices on the spi bus, the bus will
 be occupied unnecessarily long, especially when low baudrates are
 used.
Hi Erwin,

Yep, here you touched a key point of the driver.

In the early version of our driver, we used a fixed spi rate which is a
little owner than its own working rate (3.684MHz) as a spi controller can
hardly get a divided rate exactly same as 3110's clock , with that we can only
handle one word per spi transfer, and have to add a udelay function for each
transfer, and we even have to calculate the delay time for all kinds of the
UART baud rate it's working with. struct spi_transfer has a member deay_usecs
just for this case.

One key point for SPI devices is they can't be accessed by CPU directly and has
to go though tasklet or workqueue for each spi transfer. To improve performance,
we chose to use buffer read/write to let one transfer contain more data, and use
dynamic spi rate by setting spi_transfer-speed_hz for each baud rate
accordingly. spi rate is set by spi controller drivers based on the speed_hz
number and they should chose a lower spi rate than 3110's baud rate if can't 
find
a same rate. For a spi controller support multiple devices including 3110, the
delay from 3110 is inevitable no matter we use a explicit udelay or the dynamic
spi rate.

Till here, I have to say the spi_transfer of spi core is well designed, which
provides bits_per_word/delay_usecs/speed_hz of great flexibility for developing
spi device/controller drivers

Thanks,
Feng


 
 One other small cosmetic thing:
 in serial_m3110_tx_empty(), TIOCSER_TEMT should be returned instead of
 1.
 
 -Erwin
 
 
 

--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v6] serial: spi: add spi-uart driver for Maxim 3110

2010-03-04 Thread Feng Tang

Hi Mokuno,

Thanks for the thorough review and good comments!
Some of your comments are answered inline, others will be addressed in future
 patch submission.

I would give v6 of this patch more time to be reviewed by community, so that
more comments can come and I can handle them altogether.

Thanks,
Feng

On Fri, 5 Mar 2010 02:46:07 +0800
Masakazu Mokuno mok...@sm.sony.co.jp wrote:

 Hi Feng,
 
 My comments inlined.
 
 On Thu, 4 Mar 2010 15:25:24 +0800
 Feng Tang feng.t...@intel.com wrote:
 

  + wait_queue_head_t wq;
  + struct task_struct *main_thread;
  + struct task_struct *read_thread;
  + spinlock_t lock;
 
 checkpatch.pl complained:
 
 CHECK: spinlock_t definition without comment
 #119: FILE: drivers/serial/max3110.c:53:
 +   spinlock_t lock;

A little strange, I'm using checkpatch.pl in kernel source, which doesn't
generate any warning. Which version are you using?



  +
  + /* If caller doesn't provide a buffer, then handle received
  char */
  + pbuf = rxbuf ? rxbuf : valid_str;
  +
  + for (i = 0, j = 0; i  M3110_RX_FIFO_DEPTH; i++) {
  + if (ibuf[i]  MAX3110_READ_DATA_AVAILABLE)
  + pbuf[j++] = ibuf[i]  0xff;
 
 else
 break;
 
 Can be added in order to optimize a bit :)
 There are other similar places where search valid received chars.

Reading Max3110 buffer is asynchronous operation, like for the reader thread,
spi controller will write 8 words of 0 to max3110, and read 8 words back, the
first word doesn't have a valid data doesn't mean the following don't, and we
need to check them all


  +static int max3110_main_thread(void *_max)
  +{
  + struct uart_max3110 *max = _max;
  + wait_queue_head_t *wq = max-wq;
  + int ret = 0;
  + struct circ_buf *xmit = max-con_xmit;
  +
  + init_waitqueue_head(wq);
  + pr_info(PR_FMT start main thread\n);
  +
  + do {
  + wait_event_interruptible(*wq,
  + max-flags || kthread_should_stop());
  + test_and_set_bit(0, max-mthread_up);
 
 The result of testing ignored. Why testing?

Andrew mentioned a race condition for using set/test_bit for mthread_up
flag, which I don't quiet follow due to my lack of SMP race experience,
mthread_up is not designed to make some code exclusive. And whether the main
thread can be woken up to run depends on the max-flags setting.

 
  +
  + if (use_irq  test_bit(M3110_IRQ_PENDING,
  max-flags)) {
  + max3110_con_receive(max);
  + clear_bit(M3110_IRQ_PENDING, max-flags);
  + }
 
 test_and_clear_bit()?
You mean 
if (use_irq  test_and_clear_bit(..))
max3110_con_receive(max);
?

Yes, it's better. I put clear_bit() after max3110_con_receive() because
I test that bit to decide whether we need wakeup the main thread again
in the ISR in old version submission.

  +
  + /* As we use thread to handle tx/rx, need set low latency */
  + port-state-port.tty-low_latency = 1;
  +
  + if (use_irq) {
  + ret = request_irq(max-irq, serial_m3110_irq,
  + IRQ_TYPE_EDGE_FALLING,
  max3110, max);
 
 According to the manufacturer's datasheet, it looks like MAX3110'irq
 is level interrupt. Refer Figure 6 of the datasheet.

Yep, good catch here, if there is RX data in buffer, the IRQ pin will
be asserted low always. But the IRQ line will usually be connected to
system through a GPIO pin, we use falling edge for GPIO pin IRQ trigger,
when 3110's IRQ is asserted, that GPIO pin will be changed from high to low,
the ISR and following handler will try to read all the RX data out to
make 3110's IRQ go back to high, waiting for another IRQ. 

  + if (baud == 230400)
  + clk_div = WC_BAUD_DR1;
 
 This if statement can be omitted as WC_BAUD_DR1 is 0 and clk_div
 becomes (-1 + 1).
Nice trick, but it may confuse readers without any explanation :)


  + max-port.type = PORT_MAX3110;
  + max-port.fifosize = 2; /* Only have 16b buffer */
 
 I guess MAX3110 has 8 chars RX FIFO and no TX FIFO.  If so, value 2 is
 OK here?
 
If you check the Figure 1 of the data sheet, there is still a TX buffer
there tough only one word :) or should I change it to 1? 

 
 
  +
  + max-main_thread = kthread_run(max3110_main_thread,
  + max, max3110_main);
  + if (IS_ERR(max-main_thread)) {
  + ret = PTR_ERR(max-main_thread);
  + goto err_kthread;
  + }
  +
  + pmax = max;
 
 If this driver supports only one instance of devices, how about
 declaring a global struct uart_m3100 instead of kmallc()?
If using global struct, the space will be allocated no matter the system
really have a Max3110, putting the allocation in probe() is flexible



--
Download Intel#174

[spi-devel-general] [PATCH v6] serial: spi: add spi-uart driver for Maxim 3110

2010-03-03 Thread Feng Tang
Hi All,

Here is a driver for Maxim 3110 SPI-UART device, please help to review.

It has been validated with Designware SPI controller (drivers/spi: dw_spi.c 
dw_spi_pci.c). It supports polling and IRQ mode, supports batch read, and
provides a console.

change log:
 since v5:
* Make the spi data buffer DMA safe, thanks to Mssakazu Mokuno, 
  David Brownell and Grant Likely for pointing the bug out
 since v4:
* Add explanation why not using DMA
* Fix a bug in max3110_read_multi()
 since v3:
* Remove the Designware controller related stuff
* Remove some initialization code which should be done in the platform
  setup code
* Add a missing change for drivers/serial/Makefile
 since v2:
* Address comments from Andrew Morton
* Use test/set_bit to avoid race condition for SMP/preempt case
* Fix bug related with endian order
 since v1:
* Address comments from Alan Cox
* Use a use_irq module parameter to runtime check whether
  to use IRQ mode
* Add the suspend/resume implementation

Thanks!
Feng


From 6ff1d75c34d9465d4ffce076350473bfaf5404a5 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Fri, 26 Feb 2010 11:37:29 +0800
Subject: [PATCH] serial: spi: add spi-uart driver for Maxim 3110

This is the driver for Max3110 SPI-UART device, which connect
to host with SPI interface. It supports baud rates from 300 to
230400, and supports both polling and IRQ mode, as well as
providing a console for system use

Its datasheet could be found here:
http://datasheets.maxim-ic.com/en/ds/MAX3110E-MAX3111E.pdf

Signed-off-by: Feng Tang feng.t...@intel.com
Cc: Andrew Morton a...@linux-foundation.org
Cc: David Brownell davi...@pacbell.net
Cc: Greg KH g...@kroah.com
Cc: Grant Likely grant.lik...@secretlab.ca
Acked-by: Alan Cox a...@linux.intel.com
---
 drivers/serial/Kconfig  |8 +
 drivers/serial/Makefile |1 +
 drivers/serial/max3110.c|  892 +++
 drivers/serial/max3110.h|   61 +++
 include/linux/serial_core.h |3 +
 5 files changed, 965 insertions(+), 0 deletions(-)
 create mode 100644 drivers/serial/max3110.c
 create mode 100644 drivers/serial/max3110.h

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 9ff47db..94aa282 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -688,6 +688,14 @@ config SERIAL_SA1100_CONSOLE
  your boot loader (lilo or loadlin) about how to pass options to the
  kernel at boot time.)
 
+config SERIAL_MAX3110
+   tristate SPI UART driver for Max3110
+   depends on SPI_MASTER
+   select SERIAL_CORE
+   select SERIAL_CORE_CONSOLE
+   help
+ This is the UART protocol driver for MAX3110 device
+
 config SERIAL_BFIN
tristate Blackfin serial port support
depends on BLACKFIN
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 5548fe7..b93d8a0 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
 obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
 obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o
 obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
+obj-$(CONFIG_SERIAL_MAX3110) += max3110.o
 obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
 obj-$(CONFIG_SERIAL_MUX) += mux.o
 obj-$(CONFIG_SERIAL_68328) += 68328serial.o
diff --git a/drivers/serial/max3110.c b/drivers/serial/max3110.c
new file mode 100644
index 000..9b39914
--- /dev/null
+++ b/drivers/serial/max3110.c
@@ -0,0 +1,892 @@
+/*
+ * max3110.c - spi uart protocol driver for Maxim 3110
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * Note:
+ * 1. From Max3110 spec, the Rx FIFO has 8 words, while the Tx FIFO only has
+ *1 word. If SPI master controller doesn't support sclk frequency change,
+ *then the char need be sent out one by one with some delay
+ *
+ * 2. Currently only RX availabe interrrupt is used
+ */
+
+#include linux/module.h
+#include linux/ioport.h
+#include linux/init.h
+#include linux/console.h
+#include linux/tty.h
+#include linux/tty_flip.h
+#include linux/serial_core.h
+#include linux/serial_reg.h
+#include linux/kthread.h
+#include linux/delay.h
+#include linux/spi/spi.h
+
+#include max3110.h

[spi-devel-general] [PATCH v5] serial: spi: add spi-uart driver for Maxim 3110

2010-03-02 Thread Feng Tang
Hi All,

Here is a driver for Maxim 3110 SPI-UART device, please help to review.

It has been validated with Designware SPI controller (drivers/spi: dw_spi.c 
dw_spi_pci.c). It supports polling and IRQ mode, supports batch read, and
provides a console.

change log:
 since v4:
* Add explanation why not using DMA
* Fix a bug in max3110_read_multi()
 since v3:
* Remove the Designware controller related stuff
* Remove some initialization code which should be done in the platform
  setup code
* Add a missing change for drivers/serial/Makefile
 since v2:
* Address comments from Andrew Morton
* Use test/set_bit to avoid race condition for SMP/preempt case
* Fix bug related with endian order
 since v1:
* Address comments from Alan Cox
* Use a use_irq module parameter to runtime check whether
  to use IRQ mode
* Add the suspend/resume implementation

Thanks!
Feng


From 6ea4918365f5eed04f82544f0da3efe93cb2cc20 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Fri, 26 Feb 2010 11:37:29 +0800
Subject: [PATCH] serial: spi: add spi-uart driver for Maxim 3110

This is the driver for Max3110 SPI-UART device, which connect
to host with SPI interface. It supports baud rates from 300 to
230400, and supports both polling and IRQ mode, as well as
providing a console for system use

Its datasheet could be found here:
http://datasheets.maxim-ic.com/en/ds/MAX3110E-MAX3111E.pdf

Signed-off-by: Feng Tang feng.t...@intel.com
Cc: David Brownell davi...@pacbell.net
Cc: Greg KH g...@kroah.com
Acked-by: Alan Cox a...@linux.intel.com
Acked-by: Grant Likely grant.lik...@secretlab.ca
---
 drivers/serial/Kconfig  |8 +
 drivers/serial/Makefile |1 +
 drivers/serial/max3110.c|  875 +++
 drivers/serial/max3110.h|   61 +++
 include/linux/serial_core.h |3 +
 5 files changed, 948 insertions(+), 0 deletions(-)
 create mode 100644 drivers/serial/max3110.c
 create mode 100644 drivers/serial/max3110.h

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 9ff47db..94aa282 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -688,6 +688,14 @@ config SERIAL_SA1100_CONSOLE
  your boot loader (lilo or loadlin) about how to pass options to the
  kernel at boot time.)
 
+config SERIAL_MAX3110
+   tristate SPI UART driver for Max3110
+   depends on SPI_MASTER
+   select SERIAL_CORE
+   select SERIAL_CORE_CONSOLE
+   help
+ This is the UART protocol driver for MAX3110 device
+
 config SERIAL_BFIN
tristate Blackfin serial port support
depends on BLACKFIN
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 5548fe7..b93d8a0 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
 obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
 obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o
 obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
+obj-$(CONFIG_SERIAL_MAX3110) += max3110.o
 obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
 obj-$(CONFIG_SERIAL_MUX) += mux.o
 obj-$(CONFIG_SERIAL_68328) += 68328serial.o
diff --git a/drivers/serial/max3110.c b/drivers/serial/max3110.c
new file mode 100644
index 000..aff0465
--- /dev/null
+++ b/drivers/serial/max3110.c
@@ -0,0 +1,875 @@
+/*
+ * max3110.c - spi uart protocol driver for Maxim 3110
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * Note:
+ * 1. From Max3110 spec, the Rx FIFO has 8 words, while the Tx FIFO only has
+ *1 word. If SPI master controller doesn't support sclk frequency change,
+ *then the char need be sent out one by one with some delay
+ *
+ * 2. Currently only RX availabe interrrupt is used
+ *
+ * 3. This driver doesn't support work with a spi cotnroller in DMA mode, and
+ *the reason for not using DMA is:
+ *a) Maxim 3110 is a low speed UART device, whose tx/rx buffer are very 
few,
+ *and using DMA may be over-killing when working as a system 
console(imaging
+ *we edit a text file on it)
+ *b) Handling only one 16b word transfer will be very common, but non-32b
+ *aligned DMA operation is not supported by all kinds of DMA controllers
+ *
+ *Some spi

Re: [spi-devel-general] [PATCH v5] serial: spi: add spi-uart driver for Maxim 3110

2010-03-02 Thread Feng Tang
On Wed, 3 Mar 2010 12:51:58 +0800
David Brownell davi...@pacbell.net wrote:

 On Tuesday 02 March 2010, Feng Tang wrote:
  + * 3. This driver doesn't support work with a spi cotnroller in
  DMA mode, 
 
 As Grant said:  That's a bug ... one that will randomly
 kick in based on whether the underlying SPI controller driver
 happens to use DMA for a given transaction.
 
 
From this perspective, yes, it's a bug that this driver use non DMA-safe
IO buffer, which prevents it to be portable for all kinds of controllers,
and I can make it DMA safe. 

But I still don't think it's a good idea to use DMA for Max3110 for
performance reason, I know there is some spi controller who only works in
DMA mode. 

Here comes another idea, can we add a capability flag in struct spi_master
indicating the master supporting poll or dma or both. Also we add similar
bits in struct spi_transfer indicating the this transfer wants to be handled
in poll or dma mode. For spi controller driver, it can claim its
capability when registering as a spi_master, for a spi device driver, it can
select the working mode based on spi_master's capability and set the working
mode in struct spi_transfer. Then controller and device don't need to guess
what the other is capable, and make the info public. Any thoughts?

Thanks,
Feng

--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v5] serial: spi: add spi-uart driver for Maxim 3110

2010-03-02 Thread Feng Tang

 
  Here comes another idea, can we add a capability flag in struct
  spi_master indicating the master supporting poll or dma or both.
  Also we add similar bits in struct spi_transfer indicating the this
  transfer wants to be handled in poll or dma mode.
 
 Let's not do either of those.  There's no need to introduce such
 complexity, or to enable the associated new failure modes and bugs.

This idea has nothing to do with the dma-safe problem you pointed out, I will
make the buffer dma safe anyway.

What I proposed just wants to provide some flexibility for protocol device
drivers, it will use dma-safe buffer always, but it prefer not to use DMA
for its one-word transfers, and hope to have a choice to do that. For current
existing controller and device drivers, they can simply ignore the new 
working mode setting in struct spi_master and spi_transfer and leave them
as 0.

Thanks,
Feng

 
 Much simpler to just use DMA-safe I/O buffers in the first place ...
 which is what pretty much every driver stack in Linux already expects
 or requires.
 
 - Dave
 

--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v4] serial: spi: add spi-uart driver for Maxim 3110

2010-03-01 Thread Feng Tang
On Fri, 26 Feb 2010 17:59:38 +0800
Masakazu Mokuno mok...@sm.sony.co.jp wrote:

 Hi,
 
  +   u8 *pbuf, valid_str[M3110_RX_FIFO_DEPTH];
  +   int i, j;
  +
  +   memset(obuf, 0, sizeof(obuf));
  +   memset(obuf, 0, sizeof(ibuf));
 
 memset(ibuf, 0, sizeof(ibuf))?

thanks for the catch, here is a follow on patch


diff --git a/drivers/serial/max3110.c b/drivers/serial/max3110.c
index 3283ba6..3dd2082 100644
--- a/drivers/serial/max3110.c
+++ b/drivers/serial/max3110.c
@@ -142,7 +142,7 @@ static int max3110_read_multi(struct uart_max3110 *max, u8 
*buf)
int i, j;
 
memset(obuf, 0, sizeof(obuf));
-   memset(obuf, 0, sizeof(ibuf));
+   memset(ibuf, 0, sizeof(ibuf));
 
if (max3110_write_then_read(max, obuf, ibuf,
M3110_RX_FIFO_DEPTH * 2, 1))

--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH v4] serial: spi: add spi-uart driver for Maxim 3110

2010-02-28 Thread Feng Tang
On Sat, 27 Feb 2010 03:41:42 +0800
David Brownell davi...@pacbell.net wrote:

 On Friday 26 February 2010, Masakazu Mokuno wrote:
   +static int max3110_read_multi(struct uart_max3110 *max, u8 *buf)
   +{
   + u16 obuf[M3110_RX_FIFO_DEPTH], ibuf[M3110_RX_FIFO_DEPTH];
  
  Doing I/O on stack is guaranteed safe for spi functions?
 
 Good catch ...  no it's not safe.
 
 No DMA-enabled programming interface allows it, including SPI.
Hi David,

I agree that DMA working mode must not use stack as IO buffer, and spi core
code(spi.c/spi.h) has clearly message stating that. But this driver doesn't
intend to use DMA by design. In early version of this patch there is some
controller specific data which show enable_dma = 0.

The reason of not using DMA for Maxim 3110 is, it is a low speed SPI UART
device, which only has one word (16b) TX buffer and 8 words RX buffer, using
DMA may benefit in some use case but will be over-kill for others. This
driver implement a console,  take one example of editing a file on the console,
each char we input will be echoed back on screen, which will use a spi_message
and a spi_transfer, if using DMA, that DMA operation length will be 2 bytes,
if the file been edited has 4K characters, there will be 4K DMA transactions,
which will occupy quiet some system load. 

Also whether a 16b word could be DMAed is still a question for some types of
DMA controllers, I know some platform whose DMA controllers can only  or
configured to only work with data at least 32 bits aligned. 

So in this driver, it leverages some options provided by SPI controller drivers
(pxa2xx and Designware) to chose not using DMA. 

Thanks,
Feng

 
 The Documentation/PCI/PCI-DMA-mapping.txt file has a section with
 the oddly punctuated title What memory is DMA'able?.  That's
 generic to all uses of DMA.  When it was moved to the PCI area,
 that information became harder to find ... but no less true for
 non-PCI contexts (sigh).  One relevant paragraph being:
 
   This rule also means that you may use neither kernel image addresses
   (items in data/text/bss segments), nor module image addresses, nor
   stack addresses for DMA.  These could all be mapped somewhere
 entirely different than the rest of physical memory.  Even if those
 classes of memory could physically work with DMA, you'd need to
 ensure the I/O buffers were cacheline-aligned.  Without that, you'd
 see cacheline sharing problems (data corruption) on CPUs with
 DMA-incoherent caches. (The CPU could write to one word, DMA would
 write to a different one in the same cache line, and one of them
 could be overwritten.)
 
 Those cacheline sharing problems are particularly bad for the stack,
 since the data corruption often includes return addresses.
 
 In short, passing a stack-based I/O buffer could work on some
 machines, but cause perplexing data corruption issues on others.  So
 don't try to do it any driver that claims to be portable.
 
 - Dave
 

--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [RFC][PATCH v3] serial: spi: add spi-uart driver for Maxim 3110

2010-02-24 Thread Feng Tang
On Thu, 25 Feb 2010 07:18:32 +0800
Andrew Morton a...@linux-foundation.org wrote:

  ...
 
  +static int max3110_main_thread(void *_max)
  +{
  +   struct uart_max3110 *max = _max;
  +   wait_queue_head_t *wq = max-wq;
  +   int ret = 0;
  +   struct circ_buf *xmit = max-con_xmit;
  +
  +   init_waitqueue_head(wq);
  +   pr_info(PR_FMT start main thread\n);
  +
  +   do {
  +   wait_event_interruptible(*wq,
  +   max-flags ||
  kthread_should_stop());
  +   set_bit(0, max-mthread_up);
  +
  +   if (use_irq  test_bit(M3110_IRQ_PENDING,
  max-flags)) {
  +   max3110_con_receive(max);
  +   clear_bit(M3110_IRQ_PENDING, max-flags);
  +   }
  +
  +   /* First handle console output */
  +   if (test_bit(M3110_CON_TX_NEED, max-flags)) {
  +   send_circ_buf(max, xmit);
  +   clear_bit(M3110_CON_TX_NEED, max-flags);
  +   }
  +
  +   /* Handle uart output */
  +   if (test_bit(M3110_UART_TX_NEED, max-flags)) {
  +   transmit_char(max);
  +   clear_bit(M3110_UART_TX_NEED, max-flags);
  +   }
  +   clear_bit(0, max-mthread_up);
  +   } while (!kthread_should_stop());
  +
  +   return ret;
  +}
  +
  +static irqreturn_t serial_m3110_irq(int irq, void *dev_id)
  +{
  +   struct uart_max3110 *max = dev_id;
  +
  +   /* max3110's irq is a falling edge, not level triggered,
  +* so no need to disable the irq */
  +   set_bit(M3110_IRQ_PENDING, max-flags);
  +
  +   if (!test_bit(0, max-mthread_up))
  +   wake_up_process(max-main_thread);
  +
  +   return IRQ_HANDLED;
  +}
 
 The manipulation of mthread_up here (and in several other places) is
 clearly quite racy.  If you hit that race, the thread will not wake up
 and the driver will sit there not doing anything until some other
 event happens.
 
 This is perhaps fixable with test_and_set_bit() and
 test_and_clear_bit() (need to think about that) or, of course, by
 adding locking.
 
 But a simpler fix is just to delete mthread_up altogether.
 wake_up_process() on a running process is an OK thing to do and
 hopefully isn't terribly slow.

Yes, wake_up_process won't harm a running process, our driver's case
is a little special, the console's write() func may call
wake_up_process() for every character in the buffer, thus we will
try to avoid to call it. mthread_up can't be removed as it is also
referenced in read_thread.

I prefer to use the test_and_set/clear_bit for mthread_up.

Thanks,
Feng

diff --git a/drivers/serial/max3110.c b/drivers/serial/max3110.c
index e8c44fa..d5bd71f 100644
--- a/drivers/serial/max3110.c
+++ b/drivers/serial/max3110.c
@@ -400,7 +400,7 @@ static int max3110_main_thread(void *_max)
do {
wait_event_interruptible(*wq,
max-flags || kthread_should_stop());
-   set_bit(0, max-mthread_up);
+   test_and_set_bit(0, max-mthread_up);
 
if (use_irq  test_bit(M3110_IRQ_PENDING, max-flags)) {
max3110_con_receive(max);
@@ -418,7 +418,7 @@ static int max3110_main_thread(void *_max)
transmit_char(max);
clear_bit(M3110_UART_TX_NEED, max-flags);
}
-   clear_bit(0, max-mthread_up);
+   test_and_clear_bit(0, max-mthread_up);
} while (!kthread_should_stop());
 
return ret;


--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [RFC][PATCH v3] serial: spi: add spi-uart driver for Maxim 3110

2010-02-24 Thread Feng Tang
On Thu, 25 Feb 2010 12:43:14 +0800
David Brownell davi...@pacbell.net wrote:

 On Tuesday 23 February 2010, Feng Tang wrote:
  
  +config SERIAL_MAX3110
  +   tristate SPI UART driver for Max3110
  +   select SERIAL_CORE
  +   select SERIAL_CORE_CONSOLE
 
 Shouldn't that depend on SPI_MASTER?  As it stands, you're
 permitting it to build on systems that you *know* don't have
 a prayer of running this code ... or often, even finishing
 the build.
 
 
  +   help
  +     This is the UART protocol driver for MAX3110 device
  +
  +config MAX3110_DESIGNWARE
 
 Having this depend on a specific underlying SPI master controller
 is not a good thing.  It should instead be written so that it
 runs correctly on *any* controller which exports the standard SPI
 programming interface.
 
 
 
  +   boolean Enable Max3110 to work with Designware controller
  +   default y
  +   depends on SERIAL_MAX3110
  +
 
 That is, stuff like this, from your max3110 driver:
 
  +
  +#ifdef CONFIG_MAX3110_DESIGNWARE
  +static struct dw_spi_chip spi_uart = {
  +   .poll_mode = 1,
  +   .enable_dma = 0,
  +   .type = SPI_FRF_SPI,
  +};
  +#endif
 
 Is completely irrelevant for other hardware ... or else
 (as with DMA, which should be enabled by default) is
 relevant, but shouldn't be parameterized.
 
 
  +   spi-mode = SPI_MODE_0;
  +   spi-bits_per_word = 16;
  +#ifdef CONFIG_MAX3110_DESIGNWARE
  +   spi-controller_data = spi_uart;
  +#endif
 
 That all looks fishy too.  SPI_MODE should have
 been set up as part of device creation.  Ditto
 any spi-controller_data ... normally, that all
 gets set up as part of board-specific setup.
 
 Normally one goes to a lot of effort to keep
 such board-specific code out of drivers.

Good point about the DW controller specific data, I'll remove them.
For those bits_per_word setting, I think we can put it here instead of
the board initialization code, as many types of boards can leverage the
setting here as it only works in 16b mode.

Thanks,
Feng

 
 - Dave
 

--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [RFC][PATCH] serial: spi: add spi-uart driver for Maxim 3110

2010-02-24 Thread Feng Tang
On Thu, 25 Feb 2010 12:47:13 +0800
David Brownell davi...@pacbell.net wrote:

 On Tuesday 29 December 2009, Erwin Authried wrote:
  I think there's no need for a MAX3100 **and** a MAX3110 driver,
  this is just confusing. The MAX3110 driver is identical to the
  MAX3100 from the software view, it is simply a MAX3100 with
  transceivers added to the chip. If there's any improvement, that
  should be merged into the existing MAX3100 driver.
 
 Assuming that's true ... who will resolve the issue?
 
Hi David,

I've answered Erwin's comments before in v1 submission cycle, following
is the quote:

I agree there should not be 2 drivers cover 1 family of HW, so this is a RFC.
I've thinked about merge with current 3100 code, but it depends on one char
per spi_transfer, while my driver relys on batch data transfer for efficiency.
Another key point is the console, SPI UART can't be directly accessed by
CPU, so every spi_transfer will go through tasklet/workqueue, which makes
supporting printk a big part of my driver.

I really did consider about that, but has no good clue, so I think better to
shape my driver first.

Thanks,
Feng

--
Download Intel#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [RFC][PATCH v3] serial: spi: add spi-uart driver for Maxim 3110

2010-02-23 Thread Feng Tang
Hi All,

Here is a driver for Maxim 3110 SPI-UART device, please help to review.

It has been validated with Designware SPI controller (drivers/spi: dw_spi.c 
dw_spi_pci.c). It supports polling and IRQ mode, supports batch read, and
provides a console.

change log:
 since v2:
* Address comments from Andrew Morton
* Use test/set_bit to avoid race condition for SMP/preempt case
* Fix bug related with endian order

 since v1:
* Address comments from Alan Cox
* Use a use_irq module parameter to runtime check whether
  to use IRQ mode
* Add the suspend/resume implementation

Thanks!
Feng

From 93455ea6fbf0bfb6494b88ea83296f26f29f7eee Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Tue, 23 Feb 2010 17:52:00 +0800
Subject: [PATCH] serial: spi: add spi-uart driver for Maxim 3110

This is the driver for Max3110 SPI-UART device, which connect
to host with SPI interface. It supports baud rates from 300 to
230400, and supports both polling and IRQ mode, as well as
providing a console for system use

Its datasheet could be found here:
http://datasheets.maxim-ic.com/en/ds/MAX3110E-MAX3111E.pdf

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/serial/Kconfig  |   12 +
 drivers/serial/max3110.c|  879 +++
 drivers/serial/max3110.h|   60 +++
 include/linux/serial_core.h |3 +
 4 files changed, 954 insertions(+), 0 deletions(-)
 create mode 100644 drivers/serial/max3110.c
 create mode 100644 drivers/serial/max3110.h

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 9ff47db..f7daf2f 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -688,6 +688,18 @@ config SERIAL_SA1100_CONSOLE
  your boot loader (lilo or loadlin) about how to pass options to the
  kernel at boot time.)
 
+config SERIAL_MAX3110
+   tristate SPI UART driver for Max3110
+   select SERIAL_CORE
+   select SERIAL_CORE_CONSOLE
+   help
+ This is the UART protocol driver for MAX3110 device
+
+config MAX3110_DESIGNWARE
+   boolean Enable Max3110 to work with Designware controller
+   default y
+   depends on SERIAL_MAX3110
+
 config SERIAL_BFIN
tristate Blackfin serial port support
depends on BLACKFIN
diff --git a/drivers/serial/max3110.c b/drivers/serial/max3110.c
new file mode 100644
index 000..e8c44fa
--- /dev/null
+++ b/drivers/serial/max3110.c
@@ -0,0 +1,879 @@
+/*
+ * max3110.c - spi uart protocol driver for Maxim 3110
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * Note:
+ * * From Max3110 spec, the Rx FIFO has 8 words, while the Tx FIFO only has
+ *   1 word. If SPI master controller doesn't support sclk frequency change,
+ *   then the char need be sent out one by one with some delay
+ *
+ * * Currently only RX availabe interrrupt is used
+ */
+
+#include linux/module.h
+#include linux/ioport.h
+#include linux/init.h
+#include linux/console.h
+#include linux/platform_device.h
+#include linux/tty.h
+#include linux/tty_flip.h
+#include linux/serial_core.h
+#include linux/serial_reg.h
+
+#include linux/kthread.h
+#include linux/delay.h
+#include linux/spi/spi.h
+#include linux/spi/dw_spi.h
+
+#include max3110.h
+
+#define PR_FMT max3110: 
+
+struct uart_max3110 {
+   struct uart_port port;
+   struct spi_device *spi;
+   char *name;
+
+   wait_queue_head_t wq;
+   struct task_struct *main_thread;
+   struct task_struct *read_thread;
+   spinlock_t lock;
+
+   u32 baud;
+   u16 cur_conf;
+   u8 clock;
+   u8 parity, word_7bits;
+   u16 irq;
+
+   /* bit map for UART status */
+   unsigned long flags;
+#define M3110_CON_TX_NEED  0
+#define M3110_UART_TX_NEED 1
+#define M3110_IRQ_PENDING  2
+   unsigned long mthread_up;
+
+   /* console buffer */
+   struct circ_buf con_xmit;
+};
+
+static struct uart_max3110 *pmax;
+
+static int use_irq = 1;
+module_param(use_irq, int, 0444);
+MODULE_PARM_DESC(use_irq, Whether using Max3110's IRQ capability);
+
+static void receive_chars(struct uart_max3110 *max,
+   unsigned char *str, int len);
+static int max3110_read_multi(struct uart_max3110 *max, u8 *buf);
+static void max3110_con_receive(struct

[spi-devel-general] [RFC][PATCH v2] serial: spi: add spi-uart driver for Maxim 3110

2010-02-08 Thread Feng Tang
Hi All,

Here is a driver for Maxim 3110 SPI-UART device, please help to review.

It has been validated with Designware SPI controller (drivers/spi: dw_spi.c 
dw_spi_pci.c). It supports polling and IRQ mode, supports batch read, and
provides a console.

change since v1:
* Address comments from Alan Cox
* Use a use_irq module parameter to runtime check whether
  to use IRQ mode
* Add the suspend/resume implementation

Thanks!
Feng

From 6d14c5d68cdae8d48b6d8a00b6653022f2b100d0 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Mon, 8 Feb 2010 16:02:59 +0800
Subject: [PATCH] serial: spi: add spi-uart driver for Maxim 3110

This is the driver for Max3110 SPI-UART device, which connect
to host with SPI interface. It supports baud rates from 300 to
230400, and supports both polling and IRQ mode, as well as
providing a console for system use

Its datasheet could be found here:
http://datasheets.maxim-ic.com/en/ds/MAX3110E-MAX3111E.pdf

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/serial/Kconfig  |   12 +
 drivers/serial/max3110.c|  848 +++
 drivers/serial/max3110.h|   59 +++
 include/linux/serial_core.h |3 +
 4 files changed, 922 insertions(+), 0 deletions(-)
 create mode 100644 drivers/serial/max3110.c
 create mode 100644 drivers/serial/max3110.h

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 9ff47db..f7daf2f 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -688,6 +688,18 @@ config SERIAL_SA1100_CONSOLE
  your boot loader (lilo or loadlin) about how to pass options to the
  kernel at boot time.)
 
+config SERIAL_MAX3110
+   tristate SPI UART driver for Max3110
+   select SERIAL_CORE
+   select SERIAL_CORE_CONSOLE
+   help
+ This is the UART protocol driver for MAX3110 device
+
+config MAX3110_DESIGNWARE
+   boolean Enable Max3110 to work with Designware controller
+   default y
+   depends on SERIAL_MAX3110
+
 config SERIAL_BFIN
tristate Blackfin serial port support
depends on BLACKFIN
diff --git a/drivers/serial/max3110.c b/drivers/serial/max3110.c
new file mode 100644
index 000..c7c012b
--- /dev/null
+++ b/drivers/serial/max3110.c
@@ -0,0 +1,848 @@
+/*
+ * max3110.c - spi uart protocol driver for Maxim 3110
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * Note:
+ * * From Max3110 spec, the Rx FIFO has 8 words, while the Tx FIFO only has
+ *   1 word. If SPI master controller doesn't support sclk frequency change,
+ *   then the char need be sent out one by one with some delay
+ *
+ * * Currently only RX availabe interrrupt is used
+ */
+
+#include linux/module.h
+#include linux/ioport.h
+#include linux/init.h
+#include linux/console.h
+#include linux/platform_device.h
+#include linux/tty.h
+#include linux/tty_flip.h
+#include linux/serial_core.h
+#include linux/serial_reg.h
+
+#include linux/kthread.h
+#include linux/delay.h
+#include asm/atomic.h
+#include linux/spi/spi.h
+#include linux/spi/dw_spi.h
+
+#include max3110.h
+
+#define PR_FMT max3110: 
+
+struct uart_max3110 {
+   struct uart_port port;
+   struct spi_device *spi;
+   char *name;
+
+   wait_queue_head_t wq;
+   struct task_struct *main_thread;
+   struct task_struct *read_thread;
+   int mthread_up;
+   spinlock_t lock;
+
+   u32 baud;
+   u16 cur_conf;
+   u8 clock;
+   u8 parity, word_7bits;
+
+   atomic_t uart_tx_need;
+
+   /* console related */
+   struct circ_buf con_xmit;
+   atomic_t con_tx_need;
+
+   /* irq related */
+   u16 irq;
+   atomic_t irq_pending;
+};
+
+static struct uart_max3110 *pmax;
+
+static int use_irq = 1;
+module_param(use_irq, int, 0444);
+MODULE_PARM_DESC(use_irq, Whether using Max3110's IRQ capability);
+
+static void receive_chars(struct uart_max3110 *max,
+   unsigned char *str, int len);
+static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf);
+static void max3110_con_receive(struct uart_max3110 *max);
+
+int max3110_write_then_read(struct uart_max3110 *max,
+   const u8 *txbuf, u8 *rxbuf, unsigned len, int always_fast)
+{
+   struct spi_device *spi = max-spi

Re: [spi-devel-general] [PATCH 3/3] spi: dw_spi: refine the IRQ mode working flow

2010-01-20 Thread Feng Tang
On Wed, 20 Jan 2010 20:44:03 +0800
Jean-Hugues Deschenes jean-hugues.desche...@octasic.com wrote:


  
 
  For FIFO depth, it depends on each specific implementation based on
  DW core, and interface driver would better set it. If fifo_len is
  not set in IRQ mode, core driver will set 0 as the TX interrupt
  threshold, which will only trigger the TXE IRQ when the TX FIFO is
  fully empty. This is my design thought. 
 I'm sorry; At first, I was under the impression that it referred to a 
 software FIFO.
 ...So could this be auto-detected from the [RT]XFTLR registers, then?
 

Yep, really a good idea, from the HW spec, the depth could be detected
from [RT}XTLR, will submit a patch for this.

Thanks,
Feng

--
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for Conference
attendees to learn about information security's most important issues through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [PATCH 1/3] spi: dw_spi: fix a bug in wait_till_not_busy()

2010-01-18 Thread Feng Tang
From 124fda393891d31debc2a3b760627edb18422203 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Fri, 25 Dec 2009 11:18:32 +0800
Subject: [PATCH 1/3] spi: dw_spi: fix a bug in wait_till_not_busy()

Make the driver wait at least  for 1 jiffie before issuing the
warning, no matter what HZ is set to

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 31620fa..521d680 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -161,7 +161,7 @@ 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 + usecs_to_jiffies(1000);
+   unsigned long end = jiffies + 1 + usecs_to_jiffies(1000);
 
while (time_before(jiffies, end)) {
if (!(dw_readw(dws, sr)  SR_BUSY))
-- 
1.6.0.4

--
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for Conference
attendees to learn about information security's most important issues through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [PATCH 2/3] spi0: dw_spi: add a missed dw_spi_remove_host() in exit sequence

2010-01-18 Thread Feng Tang
From 476cd29cdde8764b8491128f15c7739547af514f Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Mon, 28 Dec 2009 11:35:03 +0800
Subject: [PATCH 2/3] spi0: dw_spi: add a missed dw_spi_remove_host() in exit 
sequence

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi_pci.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/dw_spi_pci.c
index 34ba691..7980f14 100644
--- a/drivers/spi/dw_spi_pci.c
+++ b/drivers/spi/dw_spi_pci.c
@@ -98,6 +98,7 @@ static void __devexit spi_pci_remove(struct pci_dev *pdev)
struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
 
pci_set_drvdata(pdev, NULL);
+   dw_spi_remove_host(dwpci-dws);
iounmap(dwpci-dws.regs);
pci_release_region(pdev, 0);
kfree(dwpci);
-- 
1.6.0.4

--
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for Conference
attendees to learn about information security's most important issues through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [PATCH 3/3] spi: dw_spi: refine the IRQ mode working flow

2010-01-18 Thread Feng Tang
From e1a3ba6f5605e7d0ae568b3d747b5ff03f7e202c Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Tue, 19 Jan 2010 10:22:45 +0800
Subject: [PATCH 3/3] spi: dw_spi: refine the IRQ mode working flow

Now dw_spi core fully supports 3 transfer modes: pure polling,
DMA and IRQ mode. IRQ mode will use the FIFO half empty as
the IRQ trigger, so each interface driver need set the fifo_len,
so that core driver can handle it properly

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/dw_spi.c   |   64 ++-
 drivers/spi/dw_spi_pci.c   |1 +
 include/linux/spi/dw_spi.h |1 +
 3 files changed, 41 insertions(+), 25 deletions(-)

diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 521d680..1bb709b 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -358,6 +358,8 @@ static void transfer_complete(struct dw_spi *dws)
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 {
u16 irq_status, irq_mask = 0x3f;
+   u32 int_level = dws-fifo_len / 2;
+   u32 left;
 
irq_status = dw_readw(dws, isr)  irq_mask;
/* Error handling */
@@ -369,22 +371,23 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
return IRQ_HANDLED;
}
 
-   /* INT comes from tx */
-   if (dws-tx  (irq_status  SPI_INT_TXEI)) {
-   while (dws-tx  dws-tx_end)
+   if (irq_status  SPI_INT_TXEI) {
+   spi_mask_intr(dws, SPI_INT_TXEI);
+
+   left = (dws-tx_end - dws-tx) / dws-n_bytes;
+   left = (left  int_level) ? int_level : left;
+
+   while (left--)
dws-write(dws);
+   dws-read(dws);
 
-   if (dws-tx == dws-tx_end) {
-   spi_mask_intr(dws, SPI_INT_TXEI);
+   /* Re-enable the IRQ if there is still data left to tx */
+   if (dws-tx_end  dws-tx)
+   spi_umask_intr(dws, SPI_INT_TXEI);
+   else
transfer_complete(dws);
-   }
}
 
-   /* INT comes from rx */
-   if (dws-rx  (irq_status  SPI_INT_RXFI)) {
-   if (dws-read(dws))
-   transfer_complete(dws);
-   }
return IRQ_HANDLED;
 }
 
@@ -428,6 +431,7 @@ static void pump_transfers(unsigned long data)
u8 bits = 0;
u8 imask = 0;
u8 cs_change = 0;
+   u16 txint_level = 0;
u16 clk_div = 0;
u32 speed = 0;
u32 cr0 = 0;
@@ -438,6 +442,9 @@ static void pump_transfers(unsigned long data)
chip = dws-cur_chip;
spi = message-spi;
 
+   if (unlikely(!chip-clk_div))
+   chip-clk_div = dws-max_freq / chip-speed_hz;
+
if (message-state == ERROR_STATE) {
message-status = -EIO;
goto early_exit;
@@ -492,7 +499,7 @@ static void pump_transfers(unsigned long data)
 
/* clk_div doesn't support odd number */
clk_div = dws-max_freq / speed;
-   clk_div = (clk_div  1)  1;
+   clk_div = (clk_div + 1)  0xfffe;
 
chip-speed_hz = speed;
chip-clk_div = clk_div;
@@ -535,11 +542,16 @@ static void pump_transfers(unsigned long data)
/* Check if current transfer is a DMA transaction */
dws-dma_mapped = map_dma_buffers(dws);
 
+   /*
+* Interrupt mode
+* we only need set the TXEI IRQ, as TX/RX always happen syncronizely
+*/
if (!dws-dma_mapped  !chip-poll_mode) {
-   if (dws-rx)
-   imask |= SPI_INT_RXFI;
-   if (dws-tx)
-   imask |= SPI_INT_TXEI;
+   int templen = dws-len / dws-n_bytes;
+   txint_level = dws-fifo_len / 2;
+   txint_level = (templen  txint_level) ? txint_level : templen;
+
+   imask |= SPI_INT_TXEI;
dws-transfer_handler = interrupt_transfer;
}
 
@@ -549,21 +561,23 @@ static void pump_transfers(unsigned long data)
 *  2. clk_div is changed
 *  3. control value changes
 */
-   if (dw_readw(dws, ctrl0) != cr0 || cs_change || clk_div) {
+   if (dw_readw(dws, ctrl0) != cr0 || cs_change || clk_div || imask) {
spi_enable_chip(dws, 0);
 
if (dw_readw(dws, ctrl0) != cr0)
dw_writew(dws, ctrl0, cr0);
 
+   spi_set_clk(dws, clk_div ? clk_div : chip-clk_div);
+   spi_chip_sel(dws, spi-chip_select);
+
/* Set the interrupt mask, for poll mode just diable all int */
spi_mask_intr(dws, 0xff);
-   if (!chip-poll_mode)
+   if (imask)
spi_umask_intr(dws, imask);
+   if (txint_level)
+   dw_writew(dws, txfltr, txint_level

Re: [spi-devel-general] [PATCH] Memory-mapped Dwsignware SPI driver

2010-01-18 Thread Feng Tang

You may need modify the code a little, I just submit some code change :)
mainly about a dw_spi_remove_host() and fifo_len setting

Thanks,
Feng

On Tue, 19 Jan 2010 00:50:01 +0800
Jean-Hugues Deschenes jean-hugues.desche...@octasic.com wrote:

 Adds a memory-mapped I/O dw_spi platform device.
 
 Signed-off-by: Jean-Hugues Deschenes
 jean-hugues.desche...@octasic.com ---
  drivers/spi/Kconfig   |   16 
  drivers/spi/Makefile  |1 
  drivers/spi/dw_spi_mmio.c |  164
 + 3 files changed, 178
 insertions(+), 3 deletions(-) create mode 100644
 drivers/spi/dw_spi_mmio.c
 

--
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for Conference
attendees to learn about information security's most important issues through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [PATCH 0/3 v3] spi: controller driver for Designware SPI core and PCI interface

2009-10-12 Thread Feng Tang
Hi all,

This patch series adds driver for Designware SPI core + PCI interface, and
they are generated against kernel 2.6.32-rc4

0001: driver for the DW SPI core
0002: driver for PCI interface
0003: add DMA support

This driver has been verified on Intel Moorestown platform, with Maxim's
Max3110 UART device and Option's 3G modem GTM501L, both PIO and DMA works
fine, and these 2 slave devcies can work simultaneously.

0003 is RFC only, as it has dependency over DMA controller driver's acceptance
to mainline.

User can use dw_apb_ssi_db.pdf from Synopsys as HW datasheet

please help to review them.

---
change history:
v3
* address some review comments from Andrew Morton

v2
* divide the original one driver to core+interface framework
  according to David's comments

v1
* initial submission 

Thanks,
Feng

--
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [PATCH 2/3 v3] spi: add PCI interface driver for Designware SPI core

2009-10-12 Thread Feng Tang
From 08d9f64c47e2c76c6f417a6eb7f8f7f2ce45cb47 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Sat, 10 Oct 2009 14:57:33 +0800
Subject: [PATCH 2/3] spi: add PCI interface driver for Designware SPI core

This add the PCI interface driver for DW SPI core, it has
been tested on Intel Moorestown platform

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/Kconfig  |4 +
 drivers/spi/Makefile |1 +
 drivers/spi/dw_spi_pci.c |  169 ++
 3 files changed, 174 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/dw_spi_pci.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 6eb9621..bd39e80 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -250,6 +250,10 @@ config SPI_DESIGNWARE
help
  general driver for SPI controller core from DesignWare
 
+config SPI_DW_PCI
+   tristate PCI interface driver for DW SPI core
+   depends on SPI_DESIGNWARE  PCI
+
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 5cc4e19..51ebff0 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SPI_XILINX)  += xilinx_spi.o
 obj-$(CONFIG_SPI_SH_SCI)   += spi_sh_sci.o
 obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
 obj-$(CONFIG_SPI_DESIGNWARE)   += dw_spi.o
+obj-$(CONFIG_SPI_DW_PCI)   += dw_spi_pci.o
 #  ... add above this line ...
 
 # SPI protocol drivers (device/link on bus)
diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/dw_spi_pci.c
new file mode 100644
index 000..24809c9
--- /dev/null
+++ b/drivers/spi/dw_spi_pci.c
@@ -0,0 +1,169 @@
+/*
+ * mrst_spi_pci.c - PCI interface driver for DW SPI Core
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include linux/interrupt.h
+#include linux/pci.h
+#include linux/spi/dw_spi.h
+#include linux/spi/spi.h
+
+#define DRIVER_NAME dw_spi_pci
+
+struct dw_spi_pci {
+   struct pci_dev  *pdev;
+   struct dw_spi   dws;
+};
+
+static int __devinit spi_pci_probe(struct pci_dev *pdev,
+   const struct pci_device_id *ent)
+{
+   struct dw_spi_pci *dwpci;
+   struct dw_spi *dws;
+   int pci_bar = 0;
+   int ret;
+
+   printk(KERN_INFO DW: found PCI SPI controller(ID: %04x:%04x)\n,
+   pdev-vendor, pdev-device);
+
+   ret = pci_enable_device(pdev);
+   if (ret)
+   return ret;
+
+   dwpci = kzalloc(sizeof(struct dw_spi_pci), GFP_KERNEL);
+   if (!dwpci) {
+   ret = -ENOMEM;
+   goto err_disable;
+   }
+
+   dwpci-pdev = pdev;
+   dws = dwpci-dws;
+
+   /* Get basic io resource and map it */
+   dws-paddr = pci_resource_start(pdev, pci_bar);
+   dws-iolen = pci_resource_len(pdev, pci_bar);
+
+   ret = pci_request_region(pdev, pci_bar, dev_name(pdev-dev));
+   if (ret)
+   goto err_kfree;
+
+   dws-regs = ioremap_nocache((unsigned long)dws-paddr,
+   pci_resource_len(pdev, pci_bar));
+   if (!dws-regs) {
+   ret = -ENOMEM;
+   goto err_release_reg;
+   }
+
+   dws-parent_dev = pdev-dev;
+   dws-bus_num = 0;
+   dws-num_cs = 4;
+   dws-max_freq = 2500;   /* for Moorestwon */
+   dws-irq = pdev-irq;
+
+   ret = dw_spi_add_host(dws);
+   if (ret)
+   goto err_unmap;
+
+   /* PCI hook and SPI hook use the same drv data */
+   pci_set_drvdata(pdev, dwpci);
+   return 0;
+
+err_unmap:
+   iounmap(dws-regs);
+err_release_reg:
+   pci_release_region(pdev, pci_bar);
+err_kfree:
+   kfree(dwpci);
+err_disable:
+   pci_disable_device(pdev);
+   return ret;
+}
+
+static void __devexit spi_pci_remove(struct pci_dev *pdev)
+{
+   struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+
+   pci_set_drvdata(pdev, NULL);
+   iounmap(dwpci-dws.regs);
+   pci_release_region(pdev, 0);
+   kfree(dwpci);
+   pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM
+static int spi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+   struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+   int ret;
+
+   ret

[spi-devel-general] [PATCH 1/3 v3]spi: controller driver for Designware SPI core

2009-10-12 Thread Feng Tang
From 2945f4eab344742d878ea10a774285fe770e6b10 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Sat, 10 Oct 2009 14:55:48 +0800
Subject: [PATCH 1/3] spi: controller driver for Designware SPI core

Driver for the Designware SPI core, it supports multipul interfaces
like PCI/APB etc. User can use dw_apb_ssi_db.pdf from Synopsys as
HW datasheet.

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/Kconfig|6 +
 drivers/spi/Makefile   |1 +
 drivers/spi/dw_spi.c   |  941 
 include/linux/spi/dw_spi.h |  212 ++
 4 files changed, 1160 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/dw_spi.c
 create mode 100644 include/linux/spi/dw_spi.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 4b6f7cb..6eb9621 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -244,6 +244,12 @@ config SPI_XILINX
  See the OPB Serial Peripheral Interface (SPI) (v1.00e)
  Product Specification document (DS464) for hardware details.
 
+config SPI_DESIGNWARE
+   bool DesignWare SPI controller core support
+   depends on SPI_MASTER
+   help
+ general driver for SPI controller core from DesignWare
+
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 21a1182..5cc4e19 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_SPI_TXX9)+= spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)   += xilinx_spi.o
 obj-$(CONFIG_SPI_SH_SCI)   += spi_sh_sci.o
 obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
+obj-$(CONFIG_SPI_DESIGNWARE)   += dw_spi.o
 #  ... add above this line ...
 
 # SPI protocol drivers (device/link on bus)
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
new file mode 100644
index 000..3fd90a6
--- /dev/null
+++ b/drivers/spi/dw_spi.c
@@ -0,0 +1,941 @@
+/*
+ * dw_spi.c - Designware SPI core controller driver (refer pxa2xx_spi.c)
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include linux/dma-mapping.h
+#include linux/interrupt.h
+#include linux/highmem.h
+#include linux/delay.h
+
+#include linux/spi/dw_spi.h
+#include linux/spi/spi.h
+
+#ifdef CONFIG_DEBUG_FS
+#include linux/debugfs.h
+#endif
+
+#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
+
+#define MRST_SPI_DEASSERT  0
+#define MRST_SPI_ASSERT1
+
+/* Slave spi_dev related */
+struct chip_data {
+   u16 cr0;
+   u8 cs;  /* chip select pin */
+   u8 n_bytes; /* current is a 1/2/4 byte op */
+   u8 tmode;   /* TR/TO/RO/EEPROM */
+   u8 type;/* SPI/SSP/MicroWire */
+
+   u8 poll_mode;   /* 1 means use poll mode */
+
+   u32 dma_width;
+   u32 rx_threshold;
+   u32 tx_threshold;
+   u8 enable_dma;
+   u8 bits_per_word;
+   u16 clk_div;/* baud rate divider */
+   u32 speed_hz;   /* baud rate */
+   int (*write)(struct dw_spi *dws);
+   int (*read)(struct dw_spi *dws);
+   void (*cs_control)(u32 command);
+};
+
+#ifdef CONFIG_DEBUG_FS
+static int spi_show_regs_open(struct inode *inode, struct file *file)
+{
+   file-private_data = inode-i_private;
+   return 0;
+}
+
+#define SPI_REGS_BUFSIZE   1024
+static ssize_t  spi_show_regs(struct file *file, char __user *user_buf,
+   size_t count, loff_t *ppos)
+{
+   struct dw_spi *dws;
+   char *buf;
+   u32 len = 0;
+   ssize_t ret;
+
+   dws = file-private_data;
+
+   buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);
+   if (!buf)
+   return 0;
+
+   len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+   MRST SPI0 registers:\n);
+   len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+   =\n);
+   len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+   CTRL0: \t\t0x%08x\n, dw_readl(dws, ctrl0));
+   len += snprintf(buf + len

[spi-devel-general] [PATCH 3/3 v3][RFC] spi: DMA support for Designware core on Moorestown platform

2009-10-12 Thread Feng Tang
From 347b16b69df7d75cc5ab7060a7c5311e2856b932 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Tue, 4 Aug 2009 16:42:31 +0800
Subject: [PATCH 3/3] spi: DMA support for Designware core on Moorestown platform

Designware core can work with multiple DMA controllers for DMA
operation, and this patch supports it to cowork with the Designware
DMA controller used on Intel Moorestown platform

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/Kconfig|4 +
 drivers/spi/dw_spi.c   |  171 ++-
 include/linux/spi/dw_spi.h |6 ++
 3 files changed, 177 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index bd39e80..8132272 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -250,6 +250,10 @@ config SPI_DESIGNWARE
help
  general driver for SPI controller core from DesignWare
 
+config SPI_DW_MRST_DMA
+   bool DMA support for DW SPI controller on Intel Moorestown platform
+   depends on SPI_DESGINWARE  MRST_DMA
+
 config SPI_DW_PCI
tristate PCI interface driver for DW SPI core
depends on SPI_DESIGNWARE  PCI
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 3fd90a6..e9d3db4 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -29,6 +29,10 @@
 #include linux/debugfs.h
 #endif
 
+#ifdef CONFIG_SPI_MRST_DMA
+#include linux/lnw_dma.h
+#endif
+
 #define START_STATE((void *)0)
 #define RUNNING_STATE  ((void *)1)
 #define DONE_STATE ((void *)2)
@@ -62,6 +66,166 @@ struct chip_data {
void (*cs_control)(u32 command);
 };
 
+#ifdef CONFIG_SPI_MRST_DMA
+static void dw_spi_dma_init(struct dw_spi *dws)
+{
+   struct lnw_dma_slave *rxs, *txs;
+   dma_cap_mask_t mask;
+
+   dws-txchan = NULL;
+   dws-rxchan = NULL;
+
+   /* 1. Init rx channel */
+   rxs = dws-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;
+
+   dma_cap_zero(mask);
+   dma_cap_set(DMA_MEMCPY, mask);
+   dma_cap_set(DMA_SLAVE, mask);
+
+   dws-rxchan = dma_request_channel(mask, NULL, NULL);
+   if (!dws-rxchan)
+   goto err_exit;
+   dws-rxchan-private = rxs;
+
+   /* 2. Init tx channel */
+   txs = dws-dmas_tx;
+
+   txs-dirn = DMA_TO_DEVICE;
+   txs-hs_mode = LNW_DMA_HW_HS;
+   txs-cfg_mode = LNW_DMA_MEM_TO_PER;
+   txs-src_width = LNW_DMA_WIDTH_32BIT;
+   txs-dst_width = LNW_DMA_WIDTH_16BIT;
+   txs-src_msize = LNW_DMA_MSIZE_16;
+   txs-dst_msize = LNW_DMA_MSIZE_16;
+
+   dma_cap_set(DMA_SLAVE, mask);
+   dma_cap_set(DMA_MEMCPY, mask);
+
+   dws-txchan = dma_request_channel(mask, NULL, NULL);
+   if (!dws-txchan)
+   goto free_rxchan;
+   dws-txchan-private = txs;
+
+   /* Set the dma done bit to 1 */
+   dws-dma_inited = 1;
+   dws-txdma_done = 1;
+   dws-rxdma_done = 1;
+
+   dws-tx_param = ((u64)(unsigned long)dws  32)
+   | (unsigned long)(dws-txdma_done);
+   dws-rx_param = ((u64)(unsigned long)dws  32)
+   | (unsigned long)(dws-rxdma_done);
+   return;
+
+free_rxchan:
+   dma_release_channel(dws-rxchan);
+err_exit:
+   return;
+}
+
+static void dw_spi_dma_exit(struct dw_spi *dws)
+{
+   dma_release_channel(dws-txchan);
+   dma_release_channel(dws-rxchan);
+}
+
+static void transfer_complete(struct dw_spi *dws);
+
+static void dw_spi_dma_done(void *arg)
+{
+   u64 *param = arg;
+   struct dw_spi *dws;
+   int *done;
+
+   dws = (struct dw_spi *)(unsigned long)(*param  32);
+   done = (int *)(unsigned long)(*param  0x);
+
+   *done = 1;
+   /* wait till both tx/rx channels are done */
+   if (!dws-txdma_done || !dws-rxdma_done)
+   return;
+
+   transfer_complete(dws);
+}
+
+static void dma_transfer(struct dw_spi *dws, int cs_change)
+{
+   struct dma_async_tx_descriptor *txdesc = NULL, *rxdesc = NULL;
+   struct dma_chan *txchan, *rxchan;
+   enum dma_ctrl_flags flag;
+   u16 dma_ctrl = 0;
+
+   /* 1. setup DMA related registers */
+   if (cs_change) {
+   spi_enable_chip(dws, 0);
+   dw_writew(dws, dmardlr, 0xf);
+   dw_writew(dws, dmatdlr, 0x10);
+   if (dws-tx_dma)
+   dma_ctrl |= 0x2;
+   if (dws-rx_dma)
+   dma_ctrl |= 0x1;
+   dw_writew(dws, dmacr, dma_ctrl);
+   spi_enable_chip(dws, 1);
+   }
+
+   if (dws-tx_dma)
+   dws-txdma_done = 0;
+   if (dws-rx_dma)
+   dws-rxdma_done = 0;
+
+   /* 2. start the TX dma transfer */
+   txchan

Re: [spi-devel-general] [PATCH 0/3 v3] spi: controller driver for Designware SPI core and PCI interface

2009-10-12 Thread Feng Tang
On Tue, 13 Oct 2009 06:25:53 +0800
Andrew Morton a...@linux-foundation.org wrote:

 On Mon, 12 Oct 2009 14:17:16 +0800
 Feng Tang feng.t...@intel.com wrote:
 
  This patch series adds driver for Designware SPI core + PCI
  interface, and they are generated against kernel 2.6.32-rc4
  
  0001: driver for the DW SPI core
  0002: driver for PCI interface
  0003: add DMA support
  
  This driver has been verified on Intel Moorestown platform, with
  Maxim's Max3110 UART device and Option's 3G modem GTM501L, both PIO
  and DMA works fine, and these 2 slave devcies can work
  simultaneously.
  
  0003 is RFC only, as it has dependency over DMA controller driver's
  acceptance to mainline.
 
 What is DMA controller driver?  Some other patch?  What is the
 status of that patch and where is it?
 
Yes, it's another driver patch for DMA controller of Moorestown, which
is developed by another guy. I don't know if he has submitted the patch
to community (I guess not), though we did test the SPIC+DMAC+3G-Modem.

Thanks,
Feng

--
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


Re: [spi-devel-general] [PATCH 0/3 v3] spi: controller driver for Designware SPI core and PCI interface

2009-10-12 Thread Feng Tang
On Tue, 13 Oct 2009 09:53:27 +0800
Andrew Morton a...@linux-foundation.org wrote:


0003 is RFC only, as it has dependency over DMA controller
driver's acceptance to mainline.
   
   What is DMA controller driver?  Some other patch?  What is the
   status of that patch and where is it?
   
  Yes, it's another driver patch for DMA controller of Moorestown,
  which is developed by another guy. I don't know if he has submitted
  the patch to community (I guess not), though we did test the
  SPIC+DMAC+3G-Modem.
 
 So am I correct in believing that your 0003: add DMA support doesn't
 actually work?  That it depends on some other patch which is
 unavailable to testers and reviewers and patch integrators?

Yes, it's fair enough to not trust the 0003 patch and remove it from mm
tree :) That's why I added a [RFC] for it.

Also many thanks for reviewing the patches, they have been not receiving
any comments for a while.

Thanks,
Feng

 
 Strange.

--
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [PATCH 0/3 v2] [RESEND]spi: controller driver for Designware SPI core and PCI interface

2009-09-21 Thread Feng Tang
Hi all,

This patch series adds driver for Designware SPI core + PCI interface, and
they are generated against kernel 2.6.31

0001: driver for the DW SPI core
0002: driver for PCI interface
0003: add DMA support

This driver has been verified on Intel Moorestown platform, with Maxim's
Max3110 UART device and Option's 3G modem GTM501L, both PIO and DMA works
fine, and these 2 slave devcies can work simultaneously.

User can use dw_apb_ssi_db.pdf from Synopsys as HW datasheet

please help to review them.

Thanks,
Feng



--
Come build with us! The BlackBerryreg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9#45;12, 2009. Register now#33;
http://p.sf.net/sfu/devconf
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [PATCH 1/3 v2] [RESEND]spi: controller driver for Designware SPI core

2009-09-21 Thread Feng Tang
From 5d87c87105aba522468cabb6fe206a4515dc85e8 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Tue, 4 Aug 2009 16:23:47 +0800
Subject: [PATCH 1/3] spi: controller driver for Designware SPI core

Driver for the Designware SPI core, it supports multipul interfaces
like PCI/APB etc. User can use dw_apb_ssi_db.pdf from Synopsys as
HW datasheet.

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/Kconfig|6 +
 drivers/spi/Makefile   |1 +
 drivers/spi/dw_spi.c   |  941 
 include/linux/spi/dw_spi.h |  212 ++
 4 files changed, 1160 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/dw_spi.c
 create mode 100644 include/linux/spi/dw_spi.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 2c733c2..80b1017 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -227,6 +227,12 @@ config SPI_XILINX
  See the OPB Serial Peripheral Interface (SPI) (v1.00e)
  Product Specification document (DS464) for hardware details.

+config SPI_DESIGNWARE
+   bool DesignWare SPI controller core support
+   depends on SPI_MASTER
+   help
+ general driver for SPI controller core from DesignWare
+
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 3de408d..f3f36e0 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
 obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)   += xilinx_spi.o
 obj-$(CONFIG_SPI_SH_SCI)   += spi_sh_sci.o
+obj-$(CONFIG_SPI_DESIGNWARE)   += dw_spi.o
 #  ... add above this line ...

 # SPI protocol drivers (device/link on bus)
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
new file mode 100644
index 000..261c27c
--- /dev/null
+++ b/drivers/spi/dw_spi.c
@@ -0,0 +1,941 @@
+/*
+ * dw_spi.c - Designware SPI core controller driver (refer pxa2xx_spi.c)
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include linux/dma-mapping.h
+#include linux/interrupt.h
+#include linux/highmem.h
+#include linux/delay.h
+
+#include linux/spi/dw_spi.h
+#include linux/spi/spi.h
+
+#ifdef CONFIG_DEBUG_FS
+#include linux/debugfs.h
+#endif
+
+#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
+
+#define MRST_SPI_DEASSERT  0
+#define MRST_SPI_ASSERT1
+
+/* Slave spi_dev related */
+struct chip_data {
+   u16 cr0;
+   u8 cs;  /* chip select pin */
+   u8 n_bytes; /* current is a 1/2/4 byte op */
+   u8 tmode;   /* TR/TO/RO/EEPROM */
+   u8 type;/* SPI/SSP/MicroWire */
+
+   u8 poll_mode;   /* 1 means use poll mode */
+
+   u32 dma_width;
+   u32 rx_threshold;
+   u32 tx_threshold;
+   u8 enable_dma;
+   u8 bits_per_word;
+   u16 clk_div;/* baud rate divider */
+   u32 speed_hz;   /* baud rate */
+   int (*write)(struct dw_spi *dws);
+   int (*read)(struct dw_spi *dws);
+   void (*cs_control)(u32 command);
+};
+
+#ifdef CONFIG_DEBUG_FS
+static int spi_show_regs_open(struct inode *inode, struct file *file)
+{
+   file-private_data = inode-i_private;
+   return 0;
+}
+
+#define SPI_REGS_BUFSIZE   1024
+static ssize_t  spi_show_regs(struct file *file, char __user *user_buf,
+   size_t count, loff_t *ppos)
+{
+   struct dw_spi *dws;
+   char *buf;
+   u32 len = 0;
+   ssize_t ret;
+
+   dws = (struct dw_spi *)file-private_data;
+
+   buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);
+   if (!buf)
+   return 0;
+
+   len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+   MRST SPI0 registers:\n);
+   len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+   =\n);
+   len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+   CTRL0: \t\t0x%08x\n, dw_readl(dws, ctrl0));
+   len += snprintf

[spi-devel-general] [PATCH 1/2] spi: driver for SPI controller of Intel Moorestown platform

2009-06-15 Thread Feng Tang
From 5aeff10330cef37792857c5f6977503607deb3b0 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Mon, 15 Jun 2009 16:50:44 +0800
Subject: [PATCH 1/2] spi: driver for SPI controller of Intel Moorestown platform

The controller is a PCI device, and supports both PIO and DMA mode.

This driver has been tested with Maxim's Max3110 UART device and
Option's 3G modem GTM501L, both PIO and DMA works fine, and these
2 slave devcies can work simultaneously

User can use dw_apb_ssi_db.pdf from Synopsys as HW datasheet

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/Kconfig  |9 +
 drivers/spi/Makefile |1 +
 drivers/spi/mrst_spi.c   | 1153 ++
 include/linux/spi/mrst_spi.h |  143 ++
 4 files changed, 1306 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/mrst_spi.c
 create mode 100644 include/linux/spi/mrst_spi.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 83a185d..e1cba00 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -220,6 +220,15 @@ config SPI_XILINX
  See the OPB Serial Peripheral Interface (SPI) (v1.00e)
  Product Specification document (DS464) for hardware details.
 
+config SPI_MRST
+   tristate SPI controller driver for Intel Moorestown platform 
+   depends on SPI_MASTER  PCI
+   help
+ Driver for SPI controller on Intel Moorestown platform.
+
+ The controller is a PCI device, and its core is a Synopsis
+ DesignWare SPI controller.
+
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 5d04519..d07825d 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
 obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)   += xilinx_spi.o
 obj-$(CONFIG_SPI_SH_SCI)   += spi_sh_sci.o
+obj-$(CONFIG_SPI_MRST) += mrst_spi.o
 #  ... add above this line ...
 
 # SPI protocol drivers (device/link on bus)
diff --git a/drivers/spi/mrst_spi.c b/drivers/spi/mrst_spi.c
new file mode 100644
index 000..99a1129
--- /dev/null
+++ b/drivers/spi/mrst_spi.c
@@ -0,0 +1,1153 @@
+/*
+ *  mrst_spi.c
+ *
+ *  SPI controller driver for Intel Moorestown platform (refer pxa2xx_spi.c)
+ *
+ *  Copyright (C) Intel 2008 Feng Tang feng.t...@intel.com
+ *
+ * ~~
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * ~~
+ *
+ */
+
+#include linux/delay.h
+#include linux/highmem.h
+#include linux/pci.h
+#include linux/dma-mapping.h
+#include linux/interrupt.h
+
+#include linux/spi/spi.h
+#include linux/spi/mrst_spi.h
+
+#ifdef CONFIG_DEBUG_FS
+#include linux/debugfs.h
+#endif
+
+#define DRIVER_NAME mrst_spi
+
+#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
+
+#define MRST_SPI_DEASSERT  0
+#define MRST_SPI_ASSERT1
+
+#define MRST_SPIC_MAX_FREQ 2500
+
+/* per controller struct */
+struct driver_data {
+   /* Driver model hookup */
+   struct pci_dev *pdev;
+   struct spi_master *master;
+
+   struct spi_device *devices;
+   struct spi_device *cur_dev;
+   enum mrst_ssi_type type;
+
+   /* phy and virtual register addresses */
+   void *paddr;
+   void *vaddr;
+   u32 iolen;
+   int irq;
+
+   /* 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;
+   struct chip_data *prev_chip;
+   size_t len;
+   void *tx;
+   void *tx_end;
+   void *rx;
+   void *rx_end

[spi-devel-general] [PATCH 0/2] spi: add driver for SPI controller of Intel Moorestown platform

2009-06-15 Thread Feng Tang
Hi David,

This patch series adds driver for SPI controller of Intel Moorestown platform.

This driver has been tested with Maxim's Max3110 UART device and
Option's 3G modem GTM501L, both PIO and DMA works fine, and these
2 slave devcies can work simultaneously

User can use dw_apb_ssi_db.pdf from Synopsys as HW datasheet

please help to review them.

I haven't seen your mail on this list for a while, so I cc' Andrew and Alan
for their reviews as well.

Thanks,
Feng


--
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing 
server and web deployment.
http://p.sf.net/sfu/businessobjects
___
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general


[spi-devel-general] [PATCH 2/2] spi: add DMA support for Intel Moorestown SPI controller

2009-06-15 Thread Feng Tang
From 6dbcddf7fefbef8b8828ecb358dc177f37685c46 Mon Sep 17 00:00:00 2001
From: Feng Tang feng.t...@intel.com
Date: Mon, 15 Jun 2009 17:00:11 +0800
Subject: [PATCH 2/2] spi: add DMA support for Intel Moorestown SPI controller

The DMA has been only tested with the DMA controller 2 on the
Moorestown platform

Signed-off-by: Feng Tang feng.t...@intel.com
---
 drivers/spi/Kconfig|7 ++
 drivers/spi/mrst_spi.c |  208 
 2 files changed, 215 insertions(+), 0 deletions(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index e1cba00..f7d82ea 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -229,6 +229,13 @@ config SPI_MRST
  The controller is a PCI device, and its core is a Synopsis
  DesignWare SPI controller.
 
+config SPI_MRST_DMA
+   boolean Enable DMA for MRST SPI0 controller
+   default y
+   depends on SPI_MRST  INTEL_LNW_DMAC2
+   help
+ This has to be enabled after Moorestown DMAC2 driver is enabled
+
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
diff --git a/drivers/spi/mrst_spi.c b/drivers/spi/mrst_spi.c
index 99a1129..11fae26 100644
--- a/drivers/spi/mrst_spi.c
+++ b/drivers/spi/mrst_spi.c
@@ -34,6 +34,10 @@
 #include linux/spi/spi.h
 #include linux/spi/mrst_spi.h
 
+#ifdef CONFIG_SPI_MRST_DMA
+#include linux/lnw_dma.h
+#endif
+
 #ifdef CONFIG_DEBUG_FS
 #include linux/debugfs.h
 #endif
@@ -109,6 +113,19 @@ struct driver_data {
 #endif
 
int dma_inited;
+
+#ifdef CONFIG_SPI_MRST_DMA
+   struct lnw_dma_slavedmas_tx;
+   struct lnw_dma_slavedmas_rx;
+   struct dma_chan *txchan;
+   struct dma_chan *rxchan;
+   int txdma_done;
+   int rxdma_done;
+
+   u64 tx_param;
+   u64 rx_param;
+   struct pci_dev *dma_dev;
+#endif
 };
 
 /* slave spi_dev related */
@@ -136,6 +153,128 @@ struct chip_data {
void (*cs_control)(u32 command);
 };
 
+#ifdef CONFIG_SPI_MRST_DMA
+static bool chan_filter(struct dma_chan *chan, void *param)
+{
+   struct driver_data *drv_data = param;
+   bool ret = false;
+
+   if (chan-device-dev == drv_data-dma_dev-dev)
+   ret = true;
+   return ret;
+}
+
+static void mrst_spi_dma_init(struct driver_data *drv_data)
+{
+   struct lnw_dma_slave *rxs, *txs;
+   dma_cap_mask_t mask;
+   struct pci_dev *dmac2;
+
+   drv_data-txchan = NULL;
+   drv_data-rxchan = NULL;
+
+   /* mrst spi0 controller only work with mrst dma contrller 2 */
+   dmac2 = pci_get_device(PCI_VENDOR_ID_INTEL, 0x0813, NULL);
+   if (!dmac2) {
+   printk(KERN_WARNING
+   MRST SPI0: can't find DMAC2, dma init failed\n);
+   return;
+   } else
+   drv_data-dma_dev = dmac2;
+
+   /* 1. init rx channel */
+   rxs = drv_data-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;
+
+   rxs-rx_reg = (dma_addr_t)(drv_data-paddr + 0x60);
+   rxs-tx_reg = (dma_addr_t)0;
+   dma_cap_zero(mask);
+   dma_cap_set(DMA_MEMCPY, mask);
+   dma_cap_set(DMA_SLAVE, mask);
+
+   drv_data-rxchan = dma_request_channel(mask, chan_filter,
+   drv_data);
+   if (!drv_data-rxchan)
+   goto err_exit;
+   drv_data-rxchan-private = rxs;
+
+   /* 2. init tx channel */
+   txs = drv_data-dmas_tx;
+
+   txs-dirn = DMA_TO_DEVICE;
+   txs-hs_mode = LNW_DMA_HW_HS;
+   txs-cfg_mode = LNW_DMA_MEM_TO_PER;
+   txs-src_width = LNW_DMA_WIDTH_32BIT;
+   txs-dst_width = LNW_DMA_WIDTH_16BIT;
+   txs-src_msize = LNW_DMA_MSIZE_16;
+   txs-dst_msize = LNW_DMA_MSIZE_16;
+
+   txs-tx_reg = (dma_addr_t)(drv_data-paddr + 0x60);
+   txs-rx_reg = (dma_addr_t)0;
+   dma_cap_set(DMA_SLAVE, mask);
+   dma_cap_set(DMA_MEMCPY, mask);
+
+   drv_data-txchan = dma_request_channel(mask, chan_filter,
+   drv_data);
+   if (!drv_data-txchan)
+   goto free_rxchan;
+   drv_data-txchan-private = txs;
+
+   /* set the dma done bit to 1 */
+   drv_data-dma_inited = 1;
+   drv_data-txdma_done = 1;
+   drv_data-rxdma_done = 1;
+
+   drv_data-tx_param = ((u64)(u32)drv_data  32)
+   | (u32)(drv_data-txdma_done);
+   drv_data-rx_param = ((u64)(u32)drv_data  32)
+   | (u32)(drv_data-rxdma_done);
+   return;
+
+free_rxchan:
+   dma_release_channel(drv_data-rxchan);
+err_exit:
+   pci_dev_put(dmac2);
+   return;
+}
+
+static void mrst_spi_dma_exit(struct driver_data *drv_data)
+{
+   dma_release_channel(drv_data