linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support
@ 2012-12-04  7:53 Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 01/14] of: add dma-mask binding Wenyou Yang
                   ` (13 more replies)
  0 siblings, 14 replies; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang

Hi All, 

This set of patches is to add dmaengine and device tree support for atmel spi.
The work is based on Jean-Christophe, Nicolas and Richard's work.
I tested it on at91sam9x5ek, at91sam9m10g45ek.

It is based on v3.7-rc8.

Changelog:
v2: 
   1./ Remove the patch :PATCH]mtd: m25p80: change the m25p80_read to reading page to page
	which purpose to fix the BUG: when run "flashcp /bin/busybox /dev/mtdX" in 
	the at91sam9g25ek with DMA mode, it arises a OOPS. 
	Now fix it in this patch:
	[PATHC] spi/atmel_spi: add dmaengine support changing to fix the [BUG].

   2./ Remove two patches:
   	which purpose to read dts property to select SPI IP version and DMA mode
	Now they will be gat from device tree different compatile.

   3./ Fix DMA: when enable both spi0 AND spi1, the spi0 doesn't work BUG.

   4./ Rebase v3.7-rc8.

Best Regards,
Wenyou Yang.


Jean-Christophe PLAGNIOL-VILLARD (3):
  of: add dma-mask binding
  of_spi: add generic binding support to specify cs gpio
  spi/atmel_spi: add DT support

Nicolas Ferre (5):
  spi/atmel_spi: add physical base address
  spi/atmel_spi: call unmapping on transfers buffers
  spi/atmel_spi: status information passed through controller data
  spi/atmel_spi: add flag to controller data for lock operations
  spi/atmel_spi: add dmaengine support

Richard Genoud (6):
  spi/atmel_spi: Fix spi-atmel driver to adapt to slave_config changes
  spi/atmel_spi: correct 16 bits transfers using PIO
  spi/atmel_spi: correct 16 bits transfer with DMA
  ARM: at91: add clocks for spi DT entries
  ARM: dts: add spi nodes for atmel SoC
  ARM: dts: add spi nodes for atmel boards

 Documentation/devicetree/bindings/spi/spi-bus.txt  |    6 +
 .../devicetree/bindings/spi/spi_atmel.txt          |   23 +
 arch/arm/boot/dts/at91sam9260.dtsi                 |   30 +
 arch/arm/boot/dts/at91sam9263.dtsi                 |   30 +
 arch/arm/boot/dts/at91sam9263ek.dts                |    9 +
 arch/arm/boot/dts/at91sam9g20ek_common.dtsi        |    9 +
 arch/arm/boot/dts/at91sam9g25ek.dts                |    9 +
 arch/arm/boot/dts/at91sam9g45.dtsi                 |   30 +
 arch/arm/boot/dts/at91sam9m10g45ek.dts             |    9 +
 arch/arm/boot/dts/at91sam9n12.dtsi                 |   30 +
 arch/arm/boot/dts/at91sam9n12ek.dts                |    9 +
 arch/arm/boot/dts/at91sam9x5.dtsi                  |   30 +
 arch/arm/mach-at91/at91sam9260.c                   |    2 +
 arch/arm/mach-at91/at91sam9g45.c                   |    2 +
 arch/arm/mach-at91/at91sam9n12.c                   |    2 +
 arch/arm/mach-at91/at91sam9x5.c                    |    2 +
 drivers/of/platform.c                              |   23 +-
 drivers/spi/spi-atmel.c                            |  793 ++++++++++++++++++--
 drivers/spi/spi.c                                  |   55 +-
 include/linux/spi/spi.h                            |    3 +
 20 files changed, 1033 insertions(+), 73 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/spi/spi_atmel.txt

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [v2 PATCH 01/14] of: add dma-mask binding
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-04 13:16   ` Rob Herring
  2012-12-04  7:53 ` [v2 PATCH 02/14] of_spi: add generic binding support to specify cs gpio Wenyou Yang
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, grant.likely, rob.herring, devicetree-discuss

From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>

This will allow each device to specify its dma-mask for this we use the
coherent_dma_mask as pointer. By default the dma-mask will be set to
DMA_BIT_MASK(32).
The microblaze architecture hook is drop

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: grant.likely@secretlab.ca
Cc: rob.herring@calxeda.com
Cc: devicetree-discuss@lists.ozlabs.org
---
 drivers/of/platform.c |   23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index b80891b..31ed405 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -130,6 +130,21 @@ void of_device_make_bus_id(struct device *dev)
 	dev_set_name(dev, "%s.%d", node->name, magic - 1);
 }
 
+static void of_get_dma_mask(struct device *dev, struct device_node *np)
+{
+	const __be32 *prop;
+	int len;
+
+	prop = of_get_property(np, "dma-mask", &len);
+
+	dev->dma_mask = &dev->coherent_dma_mask;
+
+	if (!prop)
+		dev->coherent_dma_mask = DMA_BIT_MASK(32);
+	else
+		dev->coherent_dma_mask = of_read_number(prop, len / 4);
+}
+
 /**
  * of_device_alloc - Allocate and initialize an of_device
  * @np: device node to assign to device
@@ -171,10 +186,8 @@ struct platform_device *of_device_alloc(struct device_node *np,
 		WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
 	}
 
+	of_get_dma_mask(&dev->dev, np);
 	dev->dev.of_node = of_node_get(np);
-#if defined(CONFIG_MICROBLAZE)
-	dev->dev.dma_mask = &dev->archdata.dma_mask;
-#endif
 	dev->dev.parent = parent;
 
 	if (bus_id)
@@ -211,10 +224,6 @@ struct platform_device *of_platform_device_create_pdata(
 	if (!dev)
 		return NULL;
 
-#if defined(CONFIG_MICROBLAZE)
-	dev->archdata.dma_mask = 0xffffffffUL;
-#endif
-	dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 	dev->dev.bus = &platform_bus_type;
 	dev->dev.platform_data = platform_data;
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 02/14] of_spi: add generic binding support to specify cs gpio
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 01/14] of: add dma-mask binding Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-05 23:28   ` Grant Likely
  2012-12-04  7:53 ` [v2 PATCH 03/14] spi/atmel_spi: add physical base address Wenyou Yang
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, devicetree-discuss, spi-devel-general, grant.likely,
	rob.herring, rob

From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>

This will allow to use gpio for chip select with no modification in the
driver binding

When use the cs-gpios, the gpio number will be passed via the cs_gpio field
and the number of chip select will automatically increased.

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: spi-devel-general@lists.sourceforge.net
Cc: grant.likely@secretlab.ca
Cc: rob.herring@calxeda.com
Cc: rob@landley.net
Cc: richard.genoud@gmail.com
---
Hi, Richard,

This patch based on the original patch from Jean-Christophe, 
 	[PATCH] of_spi: add generic binding support to specify cs gpio
and merge the patch from Richard Genoud,
	[PATCH] [BUG] SPI: array out of bound => no CS

Could you sign your signature in this patch?

Best Regards,
Wenyou Yang

 Documentation/devicetree/bindings/spi/spi-bus.txt |    6 +++
 drivers/spi/spi.c                                 |   55 +++++++++++++++++++--
 include/linux/spi/spi.h                           |    3 ++
 3 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt
index d2c33d0..7f59ae30 100644
--- a/Documentation/devicetree/bindings/spi/spi-bus.txt
+++ b/Documentation/devicetree/bindings/spi/spi-bus.txt
@@ -12,6 +12,7 @@ The SPI master node requires the following properties:
 - #size-cells     - should be zero.
 - compatible      - name of SPI bus controller following generic names
     		recommended practice.
+- cs-gpios	  - (optional) gpios chip select.
 No other properties are required in the SPI bus node.  It is assumed
 that a driver for an SPI bus device will understand that it is an SPI bus.
 However, the binding does not attempt to define the specific method for
@@ -21,6 +22,8 @@ assumption that board specific platform code will be used to manage
 chip selects.  Individual drivers can define additional properties to
 support describing the chip select layout.
 
+If cs-gpios is used the number of chip select will automatically increased.
+
 Optional property:
 - num-cs : total number of chipselects
 
@@ -37,6 +40,9 @@ contain the following properties.
 - spi-cs-high     - (optional) Empty property indicating device requires
     		chip select active high
 
+If a gpio chipselect is used for the SPI slave the gpio number will be passed
+via the controller_data
+
 SPI example for an MPC5200 SPI bus:
 	spi@f00 {
 		#address-cells = <1>;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 84c2861..74e6577 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 #include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
+#include <linux/of_gpio.h>
 #include <linux/pm_runtime.h>
 #include <linux/export.h>
 #include <linux/sched.h>
@@ -327,6 +328,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
 	spi->dev.parent = &master->dev;
 	spi->dev.bus = &spi_bus_type;
 	spi->dev.release = spidev_release;
+	spi->cs_gpio = -EINVAL;
 	device_initialize(&spi->dev);
 	return spi;
 }
@@ -344,15 +346,16 @@ EXPORT_SYMBOL_GPL(spi_alloc_device);
 int spi_add_device(struct spi_device *spi)
 {
 	static DEFINE_MUTEX(spi_add_lock);
-	struct device *dev = spi->master->dev.parent;
+	struct spi_master *master = spi->master;
+	struct device *dev = master->dev.parent;
 	struct device *d;
 	int status;
 
 	/* Chipselects are numbered 0..max; validate. */
-	if (spi->chip_select >= spi->master->num_chipselect) {
+	if (spi->chip_select >= master->num_chipselect) {
 		dev_err(dev, "cs%d >= max %d\n",
 			spi->chip_select,
-			spi->master->num_chipselect);
+			master->num_chipselect);
 		return -EINVAL;
 	}
 
@@ -376,6 +379,9 @@ int spi_add_device(struct spi_device *spi)
 		goto done;
 	}
 
+	if (master->cs_gpios)
+		spi->cs_gpio = master->cs_gpios[spi->chip_select];
+
 	/* Drivers may modify this initial i/o setup, but will
 	 * normally rely on the device being setup.  Devices
 	 * using SPI_CS_HIGH can't coexist well otherwise...
@@ -946,6 +952,45 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
 }
 EXPORT_SYMBOL_GPL(spi_alloc_master);
 
+#ifdef CONFIG_OF
+static int of_spi_register_master(struct spi_master *master)
+{
+	int nb, i;
+	int *cs;
+	struct device_node *np = master->dev.of_node;
+
+	if (!np)
+		return 0;
+
+	nb = of_gpio_named_count(np, "cs-gpios");
+
+	if (nb < 1)
+		return 0;
+
+	cs = devm_kzalloc(&master->dev,
+			  sizeof(int) * (master->num_chipselect + nb),
+			  GFP_KERNEL);
+	master->cs_gpios = cs;
+
+	if (!master->cs_gpios)
+		return -ENOMEM;
+
+	memset(cs, -EINVAL, master->num_chipselect);
+	cs += master->num_chipselect;
+	master->num_chipselect += nb;
+
+	for (i = 0; i < nb; i++)
+		cs[i] = of_get_named_gpio(np, "cs-gpios", i);
+
+	return 0;
+}
+#else
+static int of_spi_register_master(struct spi_master *master)
+{
+	return 0;
+}
+#endif
+
 /**
  * spi_register_master - register SPI master controller
  * @master: initialized master, originally from spi_alloc_master()
@@ -977,6 +1022,10 @@ int spi_register_master(struct spi_master *master)
 	if (!dev)
 		return -ENODEV;
 
+	status = of_spi_register_master(master);
+	if (status)
+		return status;
+
 	/* even if it's just one always-selected device, there must
 	 * be at least one chipselect
 	 */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index fa702ae..f629189 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -90,6 +90,7 @@ struct spi_device {
 	void			*controller_state;
 	void			*controller_data;
 	char			modalias[SPI_NAME_SIZE];
+	int			cs_gpio;	/* chip select gpio */
 
 	/*
 	 * likely need more hooks for more protocol options affecting how
@@ -362,6 +363,8 @@ struct spi_master {
 	int (*transfer_one_message)(struct spi_master *master,
 				    struct spi_message *mesg);
 	int (*unprepare_transfer_hardware)(struct spi_master *master);
+	/* gpio chip select */
+	int			*cs_gpios;
 };
 
 static inline void *spi_master_get_devdata(struct spi_master *master)
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 03/14] spi/atmel_spi: add physical base address
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 01/14] of: add dma-mask binding Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 02/14] of_spi: add generic binding support to specify cs gpio Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 04/14] spi/atmel_spi: call unmapping on transfers buffers Wenyou Yang
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, grant.likely, spi-devel-general

From: Nicolas Ferre <nicolas.ferre@atmel.com>

Needed for future use with dmaengine enabled driver.

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: grant.likely@secretlab.ca
Cc: spi-devel-general@lists.sourceforge.net
---
 drivers/spi/spi-atmel.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 16d6a83..2e040be 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -188,6 +188,7 @@
 struct atmel_spi {
 	spinlock_t		lock;
 
+	resource_size_t		phybase;
 	void __iomem		*regs;
 	int			irq;
 	struct clk		*clk;
@@ -961,6 +962,7 @@ static int __devinit atmel_spi_probe(struct platform_device *pdev)
 	as->regs = ioremap(regs->start, resource_size(regs));
 	if (!as->regs)
 		goto out_free_buffer;
+	as->phybase = regs->start;
 	as->irq = irq;
 	as->clk = clk;
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 04/14] spi/atmel_spi: call unmapping on transfers buffers
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
                   ` (2 preceding siblings ...)
  2012-12-04  7:53 ` [v2 PATCH 03/14] spi/atmel_spi: add physical base address Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 05/14] spi/atmel_spi: status information passed through controller data Wenyou Yang
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, grant.likely, spi-devel-general

From: Nicolas Ferre <nicolas.ferre@atmel.com>

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: grant.likely@secretlab.ca
Cc: spi-devel-general@lists.sourceforge.net
---
 drivers/spi/spi-atmel.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 2e040be..fc1222a 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -1010,6 +1010,7 @@ static int __devexit atmel_spi_remove(struct platform_device *pdev)
 	struct spi_master	*master = platform_get_drvdata(pdev);
 	struct atmel_spi	*as = spi_master_get_devdata(master);
 	struct spi_message	*msg;
+	struct spi_transfer	*xfer;
 
 	/* reset the hardware and block queue progress */
 	spin_lock_irq(&as->lock);
@@ -1021,9 +1022,10 @@ static int __devexit atmel_spi_remove(struct platform_device *pdev)
 
 	/* Terminate remaining queued transfers */
 	list_for_each_entry(msg, &as->queue, queue) {
-		/* REVISIT unmapping the dma is a NOP on ARM and AVR32
-		 * but we shouldn't depend on that...
-		 */
+		list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+			if (!msg->is_dma_mapped)
+				atmel_spi_dma_unmap_xfer(master, xfer);
+		}
 		msg->status = -ESHUTDOWN;
 		msg->complete(msg->context);
 	}
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 05/14] spi/atmel_spi: status information passed through controller data
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
                   ` (3 preceding siblings ...)
  2012-12-04  7:53 ` [v2 PATCH 04/14] spi/atmel_spi: call unmapping on transfers buffers Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 06/14] spi/atmel_spi: add flag to controller data for lock operations Wenyou Yang
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, grant.likely, spi-devel-general

From: Nicolas Ferre <nicolas.ferre@atmel.com>

The status of transfer is stored in controller data structure
so that it can be used not only by atmel_spi_msg_done() function.
This will be useful for upcoming dmaengine enabled driver.

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: grant.likely@secretlab.ca
Cc: spi-devel-general@lists.sourceforge.net
---
 drivers/spi/spi-atmel.c |   13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index fc1222a..76a1baf 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -201,6 +201,7 @@ struct atmel_spi {
 	unsigned long		current_remaining_bytes;
 	struct spi_transfer	*next_transfer;
 	unsigned long		next_remaining_bytes;
+	int			done_status;
 
 	void			*buffer;
 	dma_addr_t		buffer_dma;
@@ -544,15 +545,15 @@ static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
 
 static void
 atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
-		struct spi_message *msg, int status, int stay)
+		struct spi_message *msg, int stay)
 {
-	if (!stay || status < 0)
+	if (!stay || as->done_status < 0)
 		cs_deactivate(as, msg->spi);
 	else
 		as->stay = msg->spi;
 
 	list_del(&msg->queue);
-	msg->status = status;
+	msg->status = as->done_status;
 
 	dev_dbg(master->dev.parent,
 		"xfer complete: %u bytes transferred\n",
@@ -564,6 +565,7 @@ atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
 
 	as->current_transfer = NULL;
 	as->next_transfer = NULL;
+	as->done_status = 0;
 
 	/* continue if needed */
 	if (list_empty(&as->queue) || as->stopping)
@@ -641,7 +643,8 @@ atmel_spi_interrupt(int irq, void *dev_id)
 		/* Clear any overrun happening while cleaning up */
 		spi_readl(as, SR);
 
-		atmel_spi_msg_done(master, as, msg, -EIO, 0);
+		as->done_status = -EIO;
+		atmel_spi_msg_done(master, as, msg, 0);
 	} else if (pending & (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX))) {
 		ret = IRQ_HANDLED;
 
@@ -659,7 +662,7 @@ atmel_spi_interrupt(int irq, void *dev_id)
 
 			if (atmel_spi_xfer_is_last(msg, xfer)) {
 				/* report completed message */
-				atmel_spi_msg_done(master, as, msg, 0,
+				atmel_spi_msg_done(master, as, msg,
 						xfer->cs_change);
 			} else {
 				if (xfer->cs_change) {
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 06/14] spi/atmel_spi: add flag to controller data for lock operations
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
                   ` (4 preceding siblings ...)
  2012-12-04  7:53 ` [v2 PATCH 05/14] spi/atmel_spi: status information passed through controller data Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 07/14] spi/atmel_spi: add DT support Wenyou Yang
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, grant.likely, spi-devel-general

From: Nicolas Ferre <nicolas.ferre@atmel.com>

Will allow to drop the lock during DMA operations.

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: grant.likely@secretlab.ca
Cc: spi-devel-general@lists.sourceforge.net
---
 drivers/spi/spi-atmel.c |   31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 76a1baf..37f54c3 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -187,6 +187,7 @@
  */
 struct atmel_spi {
 	spinlock_t		lock;
+	unsigned long		flags;
 
 	resource_size_t		phybase;
 	void __iomem		*regs;
@@ -323,6 +324,16 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
 		gpio_set_value(asd->npcs_pin, !active);
 }
 
+static void atmel_spi_lock(struct atmel_spi *as)
+{
+		spin_lock_irqsave(&as->lock, as->flags);
+}
+
+static void atmel_spi_unlock(struct atmel_spi *as)
+{
+		spin_unlock_irqrestore(&as->lock, as->flags);
+}
+
 static inline int atmel_spi_xfer_is_last(struct spi_message *msg,
 					struct spi_transfer *xfer)
 {
@@ -559,9 +570,9 @@ atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
 		"xfer complete: %u bytes transferred\n",
 		msg->actual_length);
 
-	spin_unlock(&as->lock);
+	atmel_spi_unlock(as);
 	msg->complete(msg->context);
-	spin_lock(&as->lock);
+	atmel_spi_lock(as);
 
 	as->current_transfer = NULL;
 	as->next_transfer = NULL;
@@ -788,13 +799,11 @@ static int atmel_spi_setup(struct spi_device *spi)
 		spi->controller_state = asd;
 		gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
 	} else {
-		unsigned long		flags;
-
-		spin_lock_irqsave(&as->lock, flags);
+		atmel_spi_lock(as);
 		if (as->stay == spi)
 			as->stay = NULL;
 		cs_deactivate(as, spi);
-		spin_unlock_irqrestore(&as->lock, flags);
+		atmel_spi_unlock(as);
 	}
 
 	asd->csr = csr;
@@ -813,7 +822,6 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
 {
 	struct atmel_spi	*as;
 	struct spi_transfer	*xfer;
-	unsigned long		flags;
 	struct device		*controller = spi->master->dev.parent;
 	u8			bits;
 	struct atmel_spi_device	*asd;
@@ -878,11 +886,11 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
 	msg->status = -EINPROGRESS;
 	msg->actual_length = 0;
 
-	spin_lock_irqsave(&as->lock, flags);
+	atmel_spi_lock(as);
 	list_add_tail(&msg->queue, &as->queue);
 	if (!as->current_transfer)
 		atmel_spi_next_message(spi->master);
-	spin_unlock_irqrestore(&as->lock, flags);
+	atmel_spi_unlock(as);
 
 	return 0;
 }
@@ -892,17 +900,16 @@ static void atmel_spi_cleanup(struct spi_device *spi)
 	struct atmel_spi	*as = spi_master_get_devdata(spi->master);
 	struct atmel_spi_device	*asd = spi->controller_state;
 	unsigned		gpio = (unsigned) spi->controller_data;
-	unsigned long		flags;
 
 	if (!asd)
 		return;
 
-	spin_lock_irqsave(&as->lock, flags);
+	atmel_spi_lock(as);
 	if (as->stay == spi) {
 		as->stay = NULL;
 		cs_deactivate(as, spi);
 	}
-	spin_unlock_irqrestore(&as->lock, flags);
+	atmel_spi_unlock(as);
 
 	spi->controller_state = NULL;
 	gpio_free(gpio);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 07/14] spi/atmel_spi: add DT support
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
                   ` (5 preceding siblings ...)
  2012-12-04  7:53 ` [v2 PATCH 06/14] spi/atmel_spi: add flag to controller data for lock operations Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-07  6:58   ` Jean-Christophe PLAGNIOL-VILLARD
  2012-12-04  7:53 ` [v2 PATCH 08/14] spi/atmel_spi: add dmaengine support Wenyou Yang
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, devicetree-discuss, spi-devel-general, grant.likely,
	rob.herring, rob, linux-doc

From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>

The atmel_spi use only gpio for chip select.

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
[wenyou.yang@atmel.com: Add driver data and compatible "atmel,at91sam9260-spi", "atmel,at91sam9x5-spi"]
Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: spi-devel-general@lists.sourceforge.net
Cc: grant.likely@secretlab.ca
Cc: rob.herring@calxeda.com
Cc: rob@landley.net
Cc: linux-doc@vger.kernel.org
Cc: richard.genoud@gmail.com
---
Hi, Richard,

This patches is based on the original patch from Jean-Christophe
	[PATCH] spi/atmel: add DT support
and merge the patch from Richard Genoud
	[PATCH] spi-atmel OF: complete documentation
ane wenyou yang add more compatible "atmel,at91sam9260-spi", "atmel,at91sam9x5-spi", 
	add driver data to get IP version and dma support.

Could you sign your signature in this patch?

Best Regards,
Wenyou Yang

 .../devicetree/bindings/spi/spi_atmel.txt          |   23 +++++
 drivers/spi/spi-atmel.c                            |  102 +++++++++++++++++---
 2 files changed, 113 insertions(+), 12 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/spi/spi_atmel.txt

diff --git a/Documentation/devicetree/bindings/spi/spi_atmel.txt b/Documentation/devicetree/bindings/spi/spi_atmel.txt
new file mode 100644
index 0000000..20cdc91
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi_atmel.txt
@@ -0,0 +1,23 @@
+Atmel SPI device
+
+Required properties:
+- compatible : should be "atmel,at91rm9200-spi".
+- reg: Address and length of the register set for the device
+- interrupts: Should contain macb interrupt
+- cs-gpio: Should contain the GPIOs used for chipselect.
+- dma-mask: device coherent dma mask.
+
+spi0: spi@f0000000 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	compatible = "atmel,at91rm9200-spi";
+	reg = <0xf0000000 0x100>;
+	interrupts = <13 4>;
+	cs-gpios = <&pioA 14 0
+		    &pioA 7 0 /* conflicts with TXD2 */
+		    &pioA 1 0 /* conflicts with RXD0 */
+		    &pioB 3 0 /* conflicts with ERXDV */
+		   >;
+	dma-mask = <0xffffffff>;
+	status = "disabled";
+};
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 37f54c3..e032e3d 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #include <asm/io.h>
 #include <mach/board.h>
@@ -185,6 +186,10 @@
  * DMA transfers; transfer queue progress is driven by IRQs.  The clock
  * framework provides the base clock, subdivided for each spi_device.
  */
+struct atmel_spi_pdata {
+	u8			version;
+};
+
 struct atmel_spi {
 	spinlock_t		lock;
 	unsigned long		flags;
@@ -203,6 +208,7 @@ struct atmel_spi {
 	struct spi_transfer	*next_transfer;
 	unsigned long		next_remaining_bytes;
 	int			done_status;
+	struct atmel_spi_pdata	*pdata;
 
 	void			*buffer;
 	dma_addr_t		buffer_dma;
@@ -217,6 +223,51 @@ struct atmel_spi_device {
 #define BUFFER_SIZE		PAGE_SIZE
 #define INVALID_DMA_ADDRESS	0xffffffff
 
+static struct atmel_spi_pdata at91rm9200_config = {
+	.version = 1,
+};
+
+static struct atmel_spi_pdata at91sam9260_config = {
+	.version = 2,
+};
+
+static struct atmel_spi_pdata at91sam9x5_config = {
+	.version = 2,
+};
+
+static const struct platform_device_id atmel_spi_devtypes[] = {
+	{
+		.name = "spi-at91rm9200",
+		.driver_data = (unsigned long) &at91rm9200_config,
+	}, {
+		.name = "spi-at91sam9260",
+		.driver_data = (unsigned long) &at91sam9260_config,
+	}, {
+		.name = "spi-at91sam9x5",
+		.driver_data = (unsigned long) &at91sam9x5_config,
+	}, {
+		/* sentinel */
+	}
+};
+
+#if defined(CONFIG_OF)
+static const struct of_device_id atmel_spi_dt_ids[] = {
+	{
+		.compatible = "atmel,at91rm9200-spi",
+		.data = &at91rm9200_config,
+	} , {
+		.compatible = "atmel,at91sam9260-spi",
+		.data = &at91sam9260_config,
+	} , {
+		.compatible = "atmel,at91sam9x5-spi",
+		.data = &at91sam9x5_config,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(of, atmel_spi_dt_ids);
+#endif
+
 /*
  * Version 2 of the SPI controller has
  *  - CR.LASTXFER
@@ -229,11 +280,15 @@ struct atmel_spi_device {
  * register, but I haven't checked that it exists on all chips, and
  * this is cheaper anyway.
  */
-static bool atmel_spi_is_v2(void)
+static bool atmel_spi_is_v2(struct atmel_spi *as)
 {
-	return !cpu_is_at91rm9200();
+	if (as->pdata->version == 2)
+		return true;
+	else
+		return false;
 }
 
+
 /*
  * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
  * they assume that spi slave device state will not change on deselect, so
@@ -265,7 +320,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
 	unsigned active = spi->mode & SPI_CS_HIGH;
 	u32 mr;
 
-	if (atmel_spi_is_v2()) {
+	if (atmel_spi_is_v2(as)) {
 		/*
 		 * Always use CSR0. This ensures that the clock
 		 * switches to the correct idle polarity before we
@@ -320,7 +375,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
 			asd->npcs_pin, active ? " (low)" : "",
 			mr);
 
-	if (atmel_spi_is_v2() || spi->chip_select != 0)
+	if (atmel_spi_is_v2(as) || spi->chip_select != 0)
 		gpio_set_value(asd->npcs_pin, !active);
 }
 
@@ -710,7 +765,7 @@ static int atmel_spi_setup(struct spi_device *spi)
 	u32			scbr, csr;
 	unsigned int		bits = spi->bits_per_word;
 	unsigned long		bus_hz;
-	unsigned int		npcs_pin;
+	int			npcs_pin;
 	int			ret;
 
 	as = spi_master_get_devdata(spi->master);
@@ -733,7 +788,7 @@ static int atmel_spi_setup(struct spi_device *spi)
 	}
 
 	/* see notes above re chipselect */
-	if (!atmel_spi_is_v2()
+	if (!atmel_spi_is_v2(as)
 			&& spi->chip_select == 0
 			&& (spi->mode & SPI_CS_HIGH)) {
 		dev_dbg(&spi->dev, "setup: can't be active-high\n");
@@ -742,7 +797,7 @@ static int atmel_spi_setup(struct spi_device *spi)
 
 	/* v1 chips start out at half the peripheral bus speed. */
 	bus_hz = clk_get_rate(as->clk);
-	if (!atmel_spi_is_v2())
+	if (!atmel_spi_is_v2(as))
 		bus_hz /= 2;
 
 	if (spi->max_speed_hz) {
@@ -782,7 +837,9 @@ static int atmel_spi_setup(struct spi_device *spi)
 	csr |= SPI_BF(DLYBCT, 0);
 
 	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
-	npcs_pin = (unsigned int)spi->controller_data;
+	if (!gpio_is_valid(spi->cs_gpio))
+		spi->cs_gpio = (int)spi->controller_data;
+	npcs_pin = spi->cs_gpio;
 	asd = spi->controller_state;
 	if (!asd) {
 		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
@@ -812,7 +869,7 @@ static int atmel_spi_setup(struct spi_device *spi)
 		"setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
 		bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
 
-	if (!atmel_spi_is_v2())
+	if (!atmel_spi_is_v2(as))
 		spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
 
 	return 0;
@@ -899,7 +956,7 @@ static void atmel_spi_cleanup(struct spi_device *spi)
 {
 	struct atmel_spi	*as = spi_master_get_devdata(spi->master);
 	struct atmel_spi_device	*asd = spi->controller_state;
-	unsigned		gpio = (unsigned) spi->controller_data;
+	unsigned		gpio = spi->cs_gpio;
 
 	if (!asd)
 		return;
@@ -916,6 +973,21 @@ static void atmel_spi_cleanup(struct spi_device *spi)
 	kfree(asd);
 }
 
+static struct atmel_spi_pdata * __devinit atmel_spi_get_driver_data(
+					struct platform_device *pdev)
+{
+	if (pdev->dev.of_node) {
+		const struct of_device_id *match;
+		match = of_match_node(atmel_spi_dt_ids, pdev->dev.of_node);
+		if (!match)
+			return NULL;
+		return (struct atmel_spi_pdata *) match->data;
+	}
+
+	return (struct atmel_spi_pdata *)
+			platform_get_device_id(pdev)->driver_data;
+}
+
 /*-------------------------------------------------------------------------*/
 
 static int __devinit atmel_spi_probe(struct platform_device *pdev)
@@ -949,7 +1021,8 @@ static int __devinit atmel_spi_probe(struct platform_device *pdev)
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
 	master->bus_num = pdev->id;
-	master->num_chipselect = 4;
+	master->dev.of_node = pdev->dev.of_node;
+	master->num_chipselect = master->dev.of_node ? 0 : 4;
 	master->setup = atmel_spi_setup;
 	master->transfer = atmel_spi_transfer;
 	master->cleanup = atmel_spi_cleanup;
@@ -981,6 +1054,10 @@ static int __devinit atmel_spi_probe(struct platform_device *pdev)
 	if (ret)
 		goto out_unmap_regs;
 
+	as->pdata = atmel_spi_get_driver_data(pdev);
+	if (!as->pdata)
+		goto out_unmap_regs;
+
 	/* Initialize the hardware */
 	clk_enable(clk);
 	spi_writel(as, CR, SPI_BIT(SWRST));
@@ -1078,12 +1155,13 @@ static int atmel_spi_resume(struct platform_device *pdev)
 #define	atmel_spi_resume	NULL
 #endif
 
-
 static struct platform_driver atmel_spi_driver = {
 	.driver		= {
 		.name	= "atmel_spi",
 		.owner	= THIS_MODULE,
+		.of_match_table	= of_match_ptr(atmel_spi_dt_ids),
 	},
+	.id_table	= atmel_spi_devtypes,
 	.suspend	= atmel_spi_suspend,
 	.resume		= atmel_spi_resume,
 	.probe		= atmel_spi_probe,
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 08/14] spi/atmel_spi: add dmaengine support
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
                   ` (6 preceding siblings ...)
  2012-12-04  7:53 ` [v2 PATCH 07/14] spi/atmel_spi: add DT support Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 09/14] spi/atmel_spi: Fix spi-atmel driver to adapt to slave_config changes Wenyou Yang
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, grant.likely, spi-devel-general

From: Nicolas Ferre <nicolas.ferre@atmel.com>

Add dmaengine support.
The has_dma_support to select DMA as the SPI xfer mode.

Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
[wenyou.yang@atmel.com: add has_dma_support to select DMA as the SPI xfer mode]
[wenyou.yang@atmel.com: add support NPCS1,2,3 chip select other than NPCS0]
[wenyou.yang@atmel.com: fix DMA: OOPS if buffer > 4096 bytes]
Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Cc: grant.likely@secretlab.ca
Cc: spi-devel-general@lists.sourceforge.net
Cc: richard.genoud@gmail.com
---
Hi, Richard,

This patch is based on the original patch from Nicolas
	[PATCH] spi/atmel_spi: add dmaengine support
and merge the patches from Richard Genoud,
	[PATCH] spi-atmel: update with dmaengine interface
	[PATCH] spi-atmel: fix __init/__devinit sections mismatch
and Wenyou Yang add the code to support DTS section for selecting the SPI xfer mode,
	add support NPCS1,2,3 chip select other than NPCS0.
	fix DMA: OOPS if buffer > 4096 bytes.

Could you sign your signature in this patch?

Best Regards,
Wenyou Yang

 drivers/spi/spi-atmel.c |  564 ++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 532 insertions(+), 32 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index e032e3d..1de45c2 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/spi/spi.h>
@@ -25,6 +26,7 @@
 #include <mach/board.h>
 #include <asm/gpio.h>
 #include <mach/cpu.h>
+#include <linux/platform_data/dma-atmel.h>
 
 /* SPI register offsets */
 #define SPI_CR					0x0000
@@ -180,6 +182,19 @@
 #define spi_writel(port,reg,value) \
 	__raw_writel((value), (port)->regs + SPI_##reg)
 
+/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
+ * cache operations; better heuristics consider wordsize and bitrate.
+ */
+#define DMA_MIN_BYTES	16
+
+struct atmel_spi_dma {
+	struct dma_chan			*chan_rx;
+	struct dma_chan			*chan_tx;
+	struct scatterlist		sgrx;
+	struct scatterlist		sgtx;
+	struct dma_async_tx_descriptor	*data_desc_rx;
+	struct dma_async_tx_descriptor	*data_desc_tx;
+};
 
 /*
  * The core SPI transfer engine just talks to a register bank to set up
@@ -188,6 +203,8 @@
  */
 struct atmel_spi_pdata {
 	u8			version;
+	bool			has_dma_support;
+	struct at_dma_slave	dma_slave;
 };
 
 struct atmel_spi {
@@ -203,6 +220,7 @@ struct atmel_spi {
 
 	u8			stopping;
 	struct list_head	queue;
+	struct tasklet_struct	tasklet;
 	struct spi_transfer	*current_transfer;
 	unsigned long		current_remaining_bytes;
 	struct spi_transfer	*next_transfer;
@@ -210,8 +228,15 @@ struct atmel_spi {
 	int			done_status;
 	struct atmel_spi_pdata	*pdata;
 
+	bool			use_dma;
+	bool			use_pdc;
+
+	/* scratch buffer */
 	void			*buffer;
 	dma_addr_t		buffer_dma;
+
+	/* dmaengine data */
+	struct atmel_spi_dma	dma;
 };
 
 /* Controller-specific per-slave state */
@@ -225,14 +250,17 @@ struct atmel_spi_device {
 
 static struct atmel_spi_pdata at91rm9200_config = {
 	.version = 1,
+	.has_dma_support = false,
 };
 
 static struct atmel_spi_pdata at91sam9260_config = {
 	.version = 2,
+	.has_dma_support = false,
 };
 
 static struct atmel_spi_pdata at91sam9x5_config = {
 	.version = 2,
+	.has_dma_support = true,
 };
 
 static const struct platform_device_id atmel_spi_devtypes[] = {
@@ -309,9 +337,7 @@ static bool atmel_spi_is_v2(struct atmel_spi *as)
  * and (c) will trigger that first erratum in some cases.
  *
  * TODO: Test if the atmel_spi_is_v2() branch below works on
- * AT91RM9200 if we use some other register than CSR0. However, don't
- * do this unconditionally since AP7000 has an errata where the BITS
- * field in CSR0 overrides all other CSRs.
+ * AT91RM9200 if we use some other register than CSR0.
  */
 
 static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
@@ -321,14 +347,9 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
 	u32 mr;
 
 	if (atmel_spi_is_v2(as)) {
-		/*
-		 * Always use CSR0. This ensures that the clock
-		 * switches to the correct idle polarity before we
-		 * toggle the CS.
-		 */
-		spi_writel(as, CSR0, asd->csr);
-		spi_writel(as, MR, SPI_BF(PCS, 0x0e) | SPI_BIT(MODFDIS)
-				| SPI_BIT(MSTR));
+		spi_writel(as, CSR0 + 4 * spi->chip_select, asd->csr);
+		spi_writel(as, MR, SPI_BF(PCS, ~(0x01 << spi->chip_select))
+				| SPI_BIT(MODFDIS) | SPI_BIT(MSTR));
 		mr = spi_readl(as, MR);
 		gpio_set_value(asd->npcs_pin, active);
 	} else {
@@ -389,6 +410,23 @@ static void atmel_spi_unlock(struct atmel_spi *as)
 		spin_unlock_irqrestore(&as->lock, as->flags);
 }
 
+static inline bool atmel_spi_use_dma(struct atmel_spi *as,
+				struct spi_transfer *xfer)
+{
+	if ((as->use_dma) && (xfer->len >= DMA_MIN_BYTES))
+		return true;
+	else
+		return false;
+}
+
+static inline bool atmel_spi_use_pdc(struct atmel_spi *as)
+{
+	if (as->use_pdc)
+		return true;
+	else
+		return false;
+}
+
 static inline int atmel_spi_xfer_is_last(struct spi_message *msg,
 					struct spi_transfer *xfer)
 {
@@ -400,6 +438,220 @@ static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer)
 	return xfer->delay_usecs == 0 && !xfer->cs_change;
 }
 
+static bool filter(struct dma_chan *chan, void *slave)
+{
+	struct	at_dma_slave *sl = slave;
+
+	if (sl->dma_dev == chan->device->dev) {
+		chan->private = sl;
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static int __devinit atmel_spi_configure_dma(struct atmel_spi *as)
+{
+	struct at_dma_slave *sdata
+			= (struct at_dma_slave *)&as->pdata->dma_slave;
+
+	if (sdata && sdata->dma_dev) {
+		dma_cap_mask_t mask;
+
+		/* setup DMA addresses */
+		sdata->rx_reg = (dma_addr_t)as->phybase + SPI_RDR;
+		sdata->tx_reg = (dma_addr_t)as->phybase + SPI_TDR;
+
+		/* Try to grab two DMA channels */
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+		as->dma.chan_tx = dma_request_channel(mask, filter, sdata);
+		if (as->dma.chan_tx)
+			as->dma.chan_rx =
+				dma_request_channel(mask, filter, sdata);
+	}
+	if (!as->dma.chan_rx || !as->dma.chan_tx) {
+		if (as->dma.chan_rx)
+			dma_release_channel(as->dma.chan_rx);
+		if (as->dma.chan_tx)
+			dma_release_channel(as->dma.chan_tx);
+		dev_err(&as->pdev->dev, "DMA channel not available, " \
+					"unable to use SPI\n");
+		return -EBUSY;
+	}
+
+	dev_info(&as->pdev->dev, "Using %s (tx) and " \
+				" %s (rx) for DMA transfers\n",
+				dma_chan_name(as->dma.chan_tx),
+				dma_chan_name(as->dma.chan_rx));
+
+	return 0;
+}
+
+static void atmel_spi_stop_dma(struct atmel_spi *as)
+{
+	if (as->dma.chan_rx)
+		as->dma.chan_rx->device->device_control(as->dma.chan_rx,
+							DMA_TERMINATE_ALL, 0);
+	if (as->dma.chan_tx)
+		as->dma.chan_tx->device->device_control(as->dma.chan_tx,
+							DMA_TERMINATE_ALL, 0);
+}
+
+static void atmel_spi_release_dma(struct atmel_spi *as)
+{
+	if (as->dma.chan_rx)
+		dma_release_channel(as->dma.chan_rx);
+	if (as->dma.chan_tx)
+		dma_release_channel(as->dma.chan_tx);
+}
+
+/* This function is called by the DMA driver from tasklet context */
+static void dma_callback(void *data)
+{
+	struct spi_master	*master = data;
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+
+	/* trigger SPI tasklet */
+	tasklet_schedule(&as->tasklet);
+}
+
+/*
+ * Next transfer using PIO.
+ * lock is held, spi tasklet is blocked
+ */
+static void atmel_spi_next_xfer_pio(struct spi_master *master,
+				struct spi_transfer *xfer)
+{
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+
+	dev_vdbg(master->dev.parent, "atmel_spi_next_xfer_pio\n");
+
+	as->current_remaining_bytes = xfer->len;
+
+	/* Make sure data is not remaining in RDR */
+	spi_readl(as, RDR);
+	while (spi_readl(as, SR) & SPI_BIT(RDRF)) {
+		spi_readl(as, RDR);
+		cpu_relax();
+	}
+
+	if (xfer->tx_buf)
+		spi_writel(as, TDR, *(u8 *)(xfer->tx_buf));
+	else
+		spi_writel(as, TDR, 0);
+
+	dev_dbg(master->dev.parent,
+		"  start pio xfer %p: len %u tx %p rx %p\n",
+		xfer, xfer->len, xfer->tx_buf, xfer->rx_buf);
+
+	/* Enable relevant interrupts */
+	spi_writel(as, IER, SPI_BIT(RDRF) | SPI_BIT(OVRES));
+}
+
+/*
+ * Submit next transfer for DMA.
+ * lock is held, spi tasklet is blocked
+ */
+static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
+				struct spi_transfer *xfer,
+				u32 *plen)
+{
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	struct dma_chan		*rxchan = as->dma.chan_rx;
+	struct dma_chan		*txchan = as->dma.chan_tx;
+	struct dma_async_tx_descriptor *rxdesc;
+	struct dma_async_tx_descriptor *txdesc;
+	dma_cookie_t		cookie;
+	u32	len = *plen;
+
+	dev_vdbg(master->dev.parent, "atmel_spi_next_xfer_dma_submit\n");
+
+	/* Check that the channels are available */
+	if (!rxchan || !txchan)
+		return -ENODEV;
+
+	/* release lock for DMA operations */
+	atmel_spi_unlock(as);
+
+	/* prepare the RX dma transfer */
+	sg_init_table(&as->dma.sgrx, 1);
+	if (xfer->rx_buf)
+		as->dma.sgrx.dma_address = xfer->rx_dma + xfer->len - *plen;
+	else {
+		as->dma.sgrx.dma_address = as->buffer_dma;
+		if (len > BUFFER_SIZE)
+			len = BUFFER_SIZE;
+	}
+
+	/* prepare the TX dma transfer */
+	sg_init_table(&as->dma.sgtx, 1);
+	if (xfer->tx_buf) {
+		as->dma.sgtx.dma_address = xfer->tx_dma + xfer->len - *plen;
+	} else {
+		as->dma.sgtx.dma_address = as->buffer_dma;
+		if (len > BUFFER_SIZE)
+			len = BUFFER_SIZE;
+		memset(as->buffer, 0, len);
+	}
+
+	sg_dma_len(&as->dma.sgtx) = len;
+	sg_dma_len(&as->dma.sgrx) = len;
+
+	*plen = len;
+
+	/* Send both scatterlists */
+	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
+					&as->dma.sgrx,
+					1,
+					DMA_FROM_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK,
+					NULL);
+	if (!rxdesc)
+		goto err_dma;
+
+	txdesc = txchan->device->device_prep_slave_sg(txchan,
+					&as->dma.sgtx,
+					1,
+					DMA_TO_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK,
+					NULL);
+	if (!txdesc)
+		goto err_dma;
+
+	dev_dbg(master->dev.parent,
+		"  start dma xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+		xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
+		xfer->rx_buf, xfer->rx_dma);
+
+	/* Enable relevant interrupts */
+	spi_writel(as, IER, SPI_BIT(OVRES));
+
+	/* Put the callback on the RX transfer only, that should finish last */
+	rxdesc->callback = dma_callback;
+	rxdesc->callback_param = master;
+
+	/* Submit and fire RX and TX with TX last so we're ready to read! */
+	cookie = rxdesc->tx_submit(rxdesc);
+	if (dma_submit_error(cookie))
+		goto err_dma;
+	cookie = txdesc->tx_submit(txdesc);
+	if (dma_submit_error(cookie))
+		goto err_dma;
+	rxchan->device->device_issue_pending(rxchan);
+	txchan->device->device_issue_pending(txchan);
+
+	/* take back lock */
+	atmel_spi_lock(as);
+	return 0;
+
+err_dma:
+	spi_writel(as, IDR, SPI_BIT(OVRES));
+	atmel_spi_stop_dma(as);
+	atmel_spi_lock(as);
+	return -ENOMEM;
+}
+
 static void atmel_spi_next_xfer_data(struct spi_master *master,
 				struct spi_transfer *xfer,
 				dma_addr_t *tx_dma,
@@ -432,10 +684,10 @@ static void atmel_spi_next_xfer_data(struct spi_master *master,
 }
 
 /*
- * Submit next transfer for DMA.
+ * Submit next transfer for PDC.
  * lock is held, spi irq is blocked
  */
-static void atmel_spi_next_xfer(struct spi_master *master,
+static void atmel_spi_next_xfer_pdc(struct spi_master *master,
 				struct spi_message *msg)
 {
 	struct atmel_spi	*as = spi_master_get_devdata(master);
@@ -532,6 +784,49 @@ static void atmel_spi_next_xfer(struct spi_master *master,
 	spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
 }
 
+/*
+ * Choose way to submit next transfer and start it.
+ * lock is held, spi tasklet is blocked
+ */
+static void atmel_spi_next_xfer_dma(struct spi_master *master,
+				struct spi_message *msg)
+{
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	struct spi_transfer	*xfer;
+	u32	remaining, len;
+
+	dev_vdbg(&msg->spi->dev, "atmel_spi_next_xfer\n");
+
+	remaining = as->current_remaining_bytes;
+	if (remaining) {
+		xfer = as->current_transfer;
+		len = remaining;
+	} else {
+		if (!as->current_transfer)
+			xfer = list_entry(msg->transfers.next,
+				struct spi_transfer, transfer_list);
+		else
+			xfer = list_entry(
+				as->current_transfer->transfer_list.next,
+					struct spi_transfer, transfer_list);
+
+		as->current_transfer = xfer;
+		len = xfer->len;
+	}
+
+	if (atmel_spi_use_dma(as, xfer)) {
+		u32 total = len;
+		if (!atmel_spi_next_xfer_dma_submit(master, xfer, &len)) {
+			as->current_remaining_bytes = total - len;
+			return;
+		} else
+			dev_err(&msg->spi->dev, "unable to use DMA, fallback to PIO\n");
+	}
+
+	/* use PIO if error appened using DMA */
+	atmel_spi_next_xfer_pio(master, xfer);
+}
+
 static void atmel_spi_next_message(struct spi_master *master)
 {
 	struct atmel_spi	*as = spi_master_get_devdata(master);
@@ -556,7 +851,10 @@ static void atmel_spi_next_message(struct spi_master *master)
 	} else
 		cs_activate(as, spi);
 
-	atmel_spi_next_xfer(master, msg);
+	if (atmel_spi_use_pdc(as))
+		atmel_spi_next_xfer_pdc(master, msg);
+	else
+		atmel_spi_next_xfer_dma(master, msg);
 }
 
 /*
@@ -609,6 +907,11 @@ static void atmel_spi_dma_unmap_xfer(struct spi_master *master,
 				 xfer->len, DMA_FROM_DEVICE);
 }
 
+static void atmel_spi_disable_pdc_transfer(struct atmel_spi *as)
+{
+	spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+}
+
 static void
 atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
 		struct spi_message *msg, int stay)
@@ -634,19 +937,175 @@ atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as,
 	as->done_status = 0;
 
 	/* continue if needed */
-	if (list_empty(&as->queue) || as->stopping)
-		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
-	else
+	if (list_empty(&as->queue) || as->stopping) {
+		if (atmel_spi_use_pdc(as))
+			atmel_spi_disable_pdc_transfer(as);
+	} else
 		atmel_spi_next_message(master);
 }
 
-static irqreturn_t
-atmel_spi_interrupt(int irq, void *dev_id)
+/* Called from IRQ
+ * lock is held
+ *
+ * Must update "current_remaining_bytes" to keep track of data
+ * to transfer.
+ */
+static void
+atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)
 {
-	struct spi_master	*master = dev_id;
+	u8		*txp;
+	u8		*rxp;
+	unsigned long	xfer_pos = xfer->len - as->current_remaining_bytes;
+
+	if (xfer->rx_buf) {
+		rxp = ((u8 *)xfer->rx_buf) + xfer_pos;
+		*rxp = spi_readl(as, RDR);
+	} else {
+		spi_readl(as, RDR);
+	}
+
+	as->current_remaining_bytes--;
+
+	if (as->current_remaining_bytes) {
+		if (xfer->tx_buf) {
+			txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1;
+			spi_writel(as, TDR, *txp);
+		} else {
+			spi_writel(as, TDR, 0);
+		}
+	}
+}
+
+/* Tasklet
+ * Called from DMA callback + pio transfer and overrun IRQ.
+ */
+static void atmel_spi_tasklet_func(unsigned long data)
+{
+	struct spi_master	*master = (struct spi_master *)data;
 	struct atmel_spi	*as = spi_master_get_devdata(master);
 	struct spi_message	*msg;
 	struct spi_transfer	*xfer;
+
+	dev_vdbg(master->dev.parent, "atmel_spi_tasklet_func\n");
+
+	atmel_spi_lock(as);
+
+	xfer = as->current_transfer;
+
+	if (xfer == NULL)
+		/* already been there */
+		goto tasklet_out;
+
+	msg = list_entry(as->queue.next, struct spi_message, queue);
+
+	if (as->current_remaining_bytes == 0) {
+		if (as->done_status < 0) {
+			/* error happened (overrun) */
+			if (atmel_spi_use_dma(as, xfer))
+				atmel_spi_stop_dma(as);
+		} else
+			/* only update length if no error */
+			msg->actual_length += xfer->len;
+
+		if (atmel_spi_use_dma(as, xfer))
+			if (!msg->is_dma_mapped)
+				atmel_spi_dma_unmap_xfer(master, xfer);
+
+		if (xfer->delay_usecs)
+			udelay(xfer->delay_usecs);
+
+		if (atmel_spi_xfer_is_last(msg, xfer) || as->done_status < 0)
+			/* report completed (or erroneous) message */
+			atmel_spi_msg_done(master, as, msg, xfer->cs_change);
+		else {
+			if (xfer->cs_change) {
+				cs_deactivate(as, msg->spi);
+				udelay(1);
+				cs_activate(as, msg->spi);
+			}
+
+			/*
+			 * Not done yet. Submit the next transfer.
+			 *
+			 * FIXME handle protocol options for xfer
+			 */
+			atmel_spi_next_xfer_dma(master, msg);
+		}
+	} else
+		/*
+		 * Keep going, we still have data to send in
+		 * the current transfer.
+		 */
+		atmel_spi_next_xfer_dma(master, msg);
+
+tasklet_out:
+	atmel_spi_unlock(as);
+}
+
+static int atmel_spi_interrupt_dma(struct atmel_spi *as,
+				struct spi_master *master)
+{
+	u32			status, pending, imr;
+	struct spi_transfer	*xfer;
+	int			ret = IRQ_NONE;
+
+	imr = spi_readl(as, IMR);
+	status = spi_readl(as, SR);
+	pending = status & imr;
+
+	if (pending & SPI_BIT(OVRES)) {
+		ret = IRQ_HANDLED;
+		spi_writel(as, IDR, SPI_BIT(OVRES));
+		dev_warn(master->dev.parent, "overrun\n");
+
+		/*
+		 * When we get an overrun, we disregard the current
+		 * transfer. Data will not be copied back from any
+		 * bounce buffer and msg->actual_len will not be
+		 * updated with the last xfer.
+		 *
+		 * We will also not process any remaning transfers in
+		 * the message.
+		 *
+		 * All actions are done in tasklet with done_status indication
+		 */
+		as->done_status = -EIO;
+		smp_wmb();
+
+		/* Clear any overrun happening while cleaning up */
+		spi_readl(as, SR);
+
+		tasklet_schedule(&as->tasklet);
+
+	} else if (pending & SPI_BIT(RDRF)) {
+		atmel_spi_lock(as);
+
+		if (as->current_remaining_bytes) {
+			ret = IRQ_HANDLED;
+			xfer = as->current_transfer;
+			atmel_spi_pump_pio_data(as, xfer);
+			if (!as->current_remaining_bytes) {
+				/* no more data to xfer, kick tasklet */
+				spi_writel(as, IDR, pending);
+				tasklet_schedule(&as->tasklet);
+			}
+		}
+
+		atmel_spi_unlock(as);
+	} else {
+		WARN_ONCE(pending, "IRQ not handled, pending = %x\n", pending);
+		ret = IRQ_HANDLED;
+		spi_writel(as, IDR, pending);
+	}
+
+	return ret;
+}
+
+static int atmel_spi_interrupt_pdc(struct atmel_spi *as,
+				struct spi_master *master)
+{
+	struct spi_message	*msg;
+	struct spi_transfer	*xfer;
 	u32			status, pending, imr;
 	int			ret = IRQ_NONE;
 
@@ -742,14 +1201,14 @@ atmel_spi_interrupt(int irq, void *dev_id)
 				 *
 				 * FIXME handle protocol options for xfer
 				 */
-				atmel_spi_next_xfer(master, msg);
+				atmel_spi_next_xfer_pdc(master, msg);
 			}
 		} else {
 			/*
 			 * Keep going, we still have data to send in
 			 * the current transfer.
 			 */
-			atmel_spi_next_xfer(master, msg);
+			atmel_spi_next_xfer_pdc(master, msg);
 		}
 	}
 
@@ -758,6 +1217,27 @@ atmel_spi_interrupt(int irq, void *dev_id)
 	return ret;
 }
 
+/* Interrupt
+ *
+ * No need for locking in this Interrupt handler: done_status is the
+ * only information modified. What we need is the update of this field
+ * before tasklet runs. This is ensured by using barrier.
+ */
+static irqreturn_t
+atmel_spi_interrupt(int irq, void *dev_id)
+{
+	struct spi_master	*master = dev_id;
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	int ret;
+
+	if (atmel_spi_use_pdc(as))
+		ret = atmel_spi_interrupt_pdc(as, master);
+	else
+		ret = atmel_spi_interrupt_dma(as, master);
+
+	return ret;
+}
+
 static int atmel_spi_setup(struct spi_device *spi)
 {
 	struct atmel_spi	*as;
@@ -918,13 +1398,10 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
 
 		/*
 		 * DMA map early, for performance (empties dcache ASAP) and
-		 * better fault reporting.  This is a DMA-only driver.
-		 *
-		 * NOTE that if dma_unmap_single() ever starts to do work on
-		 * platforms supported by this driver, we would need to clean
-		 * up mappings for previously-mapped transfers.
+		 * better fault reporting.
 		 */
-		if (!msg->is_dma_mapped) {
+		if ((!msg->is_dma_mapped) && (atmel_spi_use_dma(as, xfer)
+			|| atmel_spi_use_pdc(as))) {
 			if (atmel_spi_dma_map_xfer(as, xfer) < 0)
 				return -ENOMEM;
 		}
@@ -1041,6 +1518,8 @@ static int __devinit atmel_spi_probe(struct platform_device *pdev)
 
 	spin_lock_init(&as->lock);
 	INIT_LIST_HEAD(&as->queue);
+	tasklet_init(&as->tasklet, atmel_spi_tasklet_func,
+					(unsigned long)master);
 	as->pdev = pdev;
 	as->regs = ioremap(regs->start, resource_size(regs));
 	if (!as->regs)
@@ -1063,7 +1542,16 @@ static int __devinit atmel_spi_probe(struct platform_device *pdev)
 	spi_writel(as, CR, SPI_BIT(SWRST));
 	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
 	spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
-	spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
+
+	as->use_dma = false;
+	as->use_pdc = false;
+
+	if (as->pdata->has_dma_support) {
+		if (atmel_spi_configure_dma(as) == 0)
+			as->use_dma = true;
+	} else
+		as->use_pdc = true;
+
 	spi_writel(as, CR, SPI_BIT(SPIEN));
 
 	/* go! */
@@ -1072,11 +1560,14 @@ static int __devinit atmel_spi_probe(struct platform_device *pdev)
 
 	ret = spi_register_master(master);
 	if (ret)
-		goto out_reset_hw;
+		goto out_free_dma;
 
 	return 0;
 
-out_reset_hw:
+out_free_dma:
+	if (as->use_dma)
+		atmel_spi_release_dma(as);
+
 	spi_writel(as, CR, SPI_BIT(SWRST));
 	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
 	clk_disable(clk);
@@ -1084,6 +1575,7 @@ out_reset_hw:
 out_unmap_regs:
 	iounmap(as->regs);
 out_free_buffer:
+	tasklet_kill(&as->tasklet);
 	dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
 			as->buffer_dma);
 out_free:
@@ -1102,6 +1594,11 @@ static int __devexit atmel_spi_remove(struct platform_device *pdev)
 	/* reset the hardware and block queue progress */
 	spin_lock_irq(&as->lock);
 	as->stopping = 1;
+	if (as->use_dma) {
+		atmel_spi_stop_dma(as);
+		atmel_spi_release_dma(as);
+	}
+
 	spi_writel(as, CR, SPI_BIT(SWRST));
 	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
 	spi_readl(as, SR);
@@ -1110,13 +1607,16 @@ static int __devexit atmel_spi_remove(struct platform_device *pdev)
 	/* Terminate remaining queued transfers */
 	list_for_each_entry(msg, &as->queue, queue) {
 		list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-			if (!msg->is_dma_mapped)
+			if (!msg->is_dma_mapped
+				&& (atmel_spi_use_dma(as, xfer)
+					|| atmel_spi_use_pdc(as)))
 				atmel_spi_dma_unmap_xfer(master, xfer);
 		}
 		msg->status = -ESHUTDOWN;
 		msg->complete(msg->context);
 	}
 
+	tasklet_kill(&as->tasklet);
 	dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
 			as->buffer_dma);
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 09/14] spi/atmel_spi: Fix spi-atmel driver to adapt to slave_config changes
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
                   ` (7 preceding siblings ...)
  2012-12-04  7:53 ` [v2 PATCH 08/14] spi/atmel_spi: add dmaengine support Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 10/14] spi/atmel_spi: correct 16 bits transfers using PIO Wenyou Yang
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, grant.likely, spi-devel-general

From: Richard Genoud <richard.genoud@gmail.com>

This is the following of the patch e2b35f3dbfc080f15b72834d08f04f0269dbe9be

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
[wenyou.yang@atmel.com: fix DMA: when enable both spi0 and spi1, spi0 doesn't work]
Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Cc: grant.likely@secretlab.ca
Cc: spi-devel-general@lists.sourceforge.net
---
 drivers/spi/spi-atmel.c |   60 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 51 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 1de45c2..7f624b6 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -438,6 +438,37 @@ static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer)
 	return xfer->delay_usecs == 0 && !xfer->cs_change;
 }
 
+static int atmel_spi_dma_slave_config(struct atmel_spi *as,
+				struct dma_slave_config *slave_config)
+{
+	int err = 0;
+
+	slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+
+	slave_config->dst_addr = (dma_addr_t)as->phybase + SPI_TDR;
+	slave_config->src_addr = (dma_addr_t)as->phybase + SPI_RDR;
+	slave_config->src_maxburst = 1;
+	slave_config->dst_maxburst = 1;
+	slave_config->device_fc = false;
+
+	slave_config->direction = DMA_MEM_TO_DEV;
+	if (dmaengine_slave_config(as->dma.chan_tx, slave_config)) {
+		dev_err(&as->pdev->dev,
+			"failed to configure tx dma channel\n");
+		err = -EINVAL;
+	}
+
+	slave_config->direction = DMA_DEV_TO_MEM;
+	if (dmaengine_slave_config(as->dma.chan_rx, slave_config)) {
+		dev_err(&as->pdev->dev,
+			"failed to configure rx dma channel\n");
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
 static bool filter(struct dma_chan *chan, void *slave)
 {
 	struct	at_dma_slave *sl = slave;
@@ -454,14 +485,12 @@ static int __devinit atmel_spi_configure_dma(struct atmel_spi *as)
 {
 	struct at_dma_slave *sdata
 			= (struct at_dma_slave *)&as->pdata->dma_slave;
+	struct dma_slave_config	slave_config;
+	int err;
 
 	if (sdata && sdata->dma_dev) {
 		dma_cap_mask_t mask;
 
-		/* setup DMA addresses */
-		sdata->rx_reg = (dma_addr_t)as->phybase + SPI_RDR;
-		sdata->tx_reg = (dma_addr_t)as->phybase + SPI_TDR;
-
 		/* Try to grab two DMA channels */
 		dma_cap_zero(mask);
 		dma_cap_set(DMA_SLAVE, mask);
@@ -471,21 +500,28 @@ static int __devinit atmel_spi_configure_dma(struct atmel_spi *as)
 				dma_request_channel(mask, filter, sdata);
 	}
 	if (!as->dma.chan_rx || !as->dma.chan_tx) {
-		if (as->dma.chan_rx)
-			dma_release_channel(as->dma.chan_rx);
-		if (as->dma.chan_tx)
-			dma_release_channel(as->dma.chan_tx);
 		dev_err(&as->pdev->dev, "DMA channel not available, " \
 					"unable to use SPI\n");
-		return -EBUSY;
+		err = -EBUSY;
+		goto error;
 	}
 
+	err = atmel_spi_dma_slave_config(as, &slave_config);
+	if (err)
+		goto error;
+
 	dev_info(&as->pdev->dev, "Using %s (tx) and " \
 				" %s (rx) for DMA transfers\n",
 				dma_chan_name(as->dma.chan_tx),
 				dma_chan_name(as->dma.chan_rx));
 
 	return 0;
+error:
+	if (as->dma.chan_rx)
+		dma_release_channel(as->dma.chan_rx);
+	if (as->dma.chan_tx)
+		dma_release_channel(as->dma.chan_tx);
+	return err;
 }
 
 static void atmel_spi_stop_dma(struct atmel_spi *as)
@@ -562,6 +598,7 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
 	struct dma_chan		*txchan = as->dma.chan_tx;
 	struct dma_async_tx_descriptor *rxdesc;
 	struct dma_async_tx_descriptor *txdesc;
+	struct dma_slave_config	slave_config;
 	dma_cookie_t		cookie;
 	u32	len = *plen;
 
@@ -600,6 +637,10 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
 
 	*plen = len;
 
+	if (atmel_spi_dma_slave_config(as, &slave_config))
+		goto err_exit;
+
+
 	/* Send both scatterlists */
 	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
 					&as->dma.sgrx,
@@ -648,6 +689,7 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
 err_dma:
 	spi_writel(as, IDR, SPI_BIT(OVRES));
 	atmel_spi_stop_dma(as);
+err_exit:
 	atmel_spi_lock(as);
 	return -ENOMEM;
 }
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 10/14] spi/atmel_spi: correct 16 bits transfers using PIO
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
                   ` (8 preceding siblings ...)
  2012-12-04  7:53 ` [v2 PATCH 09/14] spi/atmel_spi: Fix spi-atmel driver to adapt to slave_config changes Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 11/14] spi/atmel_spi: correct 16 bits transfer with DMA Wenyou Yang
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, grant.likely, spi-devel-general

From: Richard Genoud <richard.genoud@gmail.com>

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
Cc: grant.likely@secretlab.ca
Cc: spi-devel-general@lists.sourceforge.net
---
 drivers/spi/spi-atmel.c |   46 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 7f624b6..9616fab 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -573,13 +573,17 @@ static void atmel_spi_next_xfer_pio(struct spi_master *master,
 	}
 
 	if (xfer->tx_buf)
-		spi_writel(as, TDR, *(u8 *)(xfer->tx_buf));
+		if (xfer->bits_per_word > 8)
+			spi_writel(as, TDR, *(u16 *)(xfer->tx_buf));
+		else
+			spi_writel(as, TDR, *(u8 *)(xfer->tx_buf));
 	else
 		spi_writel(as, TDR, 0);
 
 	dev_dbg(master->dev.parent,
-		"  start pio xfer %p: len %u tx %p rx %p\n",
-		xfer, xfer->len, xfer->tx_buf, xfer->rx_buf);
+		"  start pio xfer %p: len %u tx %p rx %p bitpw %d\n",
+		xfer, xfer->len, xfer->tx_buf, xfer->rx_buf,
+		xfer->bits_per_word);
 
 	/* Enable relevant interrupts */
 	spi_writel(as, IER, SPI_BIT(RDRF) | SPI_BIT(OVRES));
@@ -997,21 +1001,39 @@ atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)
 {
 	u8		*txp;
 	u8		*rxp;
+	u16		*txp16;
+	u16		*rxp16;
 	unsigned long	xfer_pos = xfer->len - as->current_remaining_bytes;
 
 	if (xfer->rx_buf) {
-		rxp = ((u8 *)xfer->rx_buf) + xfer_pos;
-		*rxp = spi_readl(as, RDR);
+		if (xfer->bits_per_word > 8) {
+			rxp16 = (u16 *)(((u8 *)xfer->rx_buf) + xfer_pos);
+			*rxp16 = spi_readl(as, RDR);
+		} else {
+			rxp = ((u8 *)xfer->rx_buf) + xfer_pos;
+			*rxp = spi_readl(as, RDR);
+		}
 	} else {
 		spi_readl(as, RDR);
 	}
-
-	as->current_remaining_bytes--;
+	if (xfer->bits_per_word > 8) {
+		as->current_remaining_bytes -= 2;
+		if (as->current_remaining_bytes < 0)
+			as->current_remaining_bytes = 0;
+	} else {
+		as->current_remaining_bytes--;
+	}
 
 	if (as->current_remaining_bytes) {
 		if (xfer->tx_buf) {
-			txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1;
-			spi_writel(as, TDR, *txp);
+			if (xfer->bits_per_word > 8) {
+				txp16 = (u16 *)(((u8 *)xfer->tx_buf)
+							+ xfer_pos + 2);
+				spi_writel(as, TDR, *txp16);
+			} else {
+				txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1;
+				spi_writel(as, TDR, *txp);
+			}
 		} else {
 			spi_writel(as, TDR, 0);
 		}
@@ -1431,6 +1453,12 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
 				return -ENOPROTOOPT;
 			}
 		}
+		if (xfer->bits_per_word > 8) {
+			if (xfer->len % 2) {
+				dev_dbg(&spi->dev, "buffer len should be 16 bits aligned\n");
+				return -EINVAL;
+			}
+		}
 
 		/* FIXME implement these protocol options!! */
 		if (xfer->speed_hz) {
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 11/14] spi/atmel_spi: correct 16 bits transfer with DMA
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
                   ` (9 preceding siblings ...)
  2012-12-04  7:53 ` [v2 PATCH 10/14] spi/atmel_spi: correct 16 bits transfers using PIO Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 12/14] ARM: at91: add clocks for spi DT entries Wenyou Yang
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, grant.likely, spi-devel-general

From: Richard Genoud <richard.genoud@gmail.com>

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
Cc: grant.likely@secretlab.ca
Cc: spi-devel-general@lists.sourceforge.net
---
 drivers/spi/spi-atmel.c |   17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 9616fab..61452a5 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -439,12 +439,18 @@ static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer)
 }
 
 static int atmel_spi_dma_slave_config(struct atmel_spi *as,
-				struct dma_slave_config *slave_config)
+				struct dma_slave_config *slave_config,
+				u8 bits_per_word)
 {
 	int err = 0;
 
-	slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-	slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	if (bits_per_word > 8) {
+		slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+		slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	} else {
+		slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+		slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	}
 
 	slave_config->dst_addr = (dma_addr_t)as->phybase + SPI_TDR;
 	slave_config->src_addr = (dma_addr_t)as->phybase + SPI_RDR;
@@ -506,7 +512,7 @@ static int __devinit atmel_spi_configure_dma(struct atmel_spi *as)
 		goto error;
 	}
 
-	err = atmel_spi_dma_slave_config(as, &slave_config);
+	err = atmel_spi_dma_slave_config(as, &slave_config, 8);
 	if (err)
 		goto error;
 
@@ -641,10 +647,9 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
 
 	*plen = len;
 
-	if (atmel_spi_dma_slave_config(as, &slave_config))
+	if (atmel_spi_dma_slave_config(as, &slave_config, 8))
 		goto err_exit;
 
-
 	/* Send both scatterlists */
 	rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
 					&as->dma.sgrx,
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 12/14] ARM: at91: add clocks for spi DT entries
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
                   ` (10 preceding siblings ...)
  2012-12-04  7:53 ` [v2 PATCH 11/14] spi/atmel_spi: correct 16 bits transfer with DMA Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
  2012-12-04  7:53 ` [v2 PATCH 13/14] ARM: dts: add spi nodes for atmel SoC Wenyou Yang
  2012-12-04  7:54 ` [v2 PATCH 14/14] ARM: dts: add spi nodes for atmel boards Wenyou Yang
  13 siblings, 0 replies; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, linux, linux

From: Richard Genoud <richard.genoud@gmail.com>

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
[<wenyou.yang@atmel.com: declare the spi clocks for other at91 SoC]
Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Cc: linux@arm.linux.org.uk
Cc: plagnioj@jcrosoft.com
Cc: linux@maxim.org.za
---
 arch/arm/mach-at91/at91sam9260.c |    2 ++
 arch/arm/mach-at91/at91sam9g45.c |    2 ++
 arch/arm/mach-at91/at91sam9n12.c |    2 ++
 arch/arm/mach-at91/at91sam9x5.c  |    2 ++
 4 files changed, 8 insertions(+)

diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index f820261..6c217eb 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -230,6 +230,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t1_clk", "fffdc000.timer", &tc4_clk),
 	CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk),
 	CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &ohci_clk),
+	CLKDEV_CON_DEV_ID("spi_clk", "fffc8000.spi", &spi0_clk),
+	CLKDEV_CON_DEV_ID("spi_clk", "fffcc000.spi", &spi1_clk),
 	/* fake hclk clock */
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 84af1b5..cfe93af 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -258,6 +258,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk),
 	CLKDEV_CON_DEV_ID(NULL, "fff84000.i2c", &twi0_clk),
 	CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi1_clk),
+	CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
+	CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
 	/* fake hclk clock */
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c
index 732d3d3..1e6ebcf 100644
--- a/arch/arm/mach-at91/at91sam9n12.c
+++ b/arch/arm/mach-at91/at91sam9n12.c
@@ -171,6 +171,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
 	CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
 	CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
+	CLKDEV_CON_DEV_ID("spi_clk", "f0000000.spi", &spi0_clk),
+	CLKDEV_CON_DEV_ID("spi_clk", "f0004000.spi", &spi1_clk),
 	CLKDEV_CON_ID("pioA", &pioAB_clk),
 	CLKDEV_CON_ID("pioB", &pioAB_clk),
 	CLKDEV_CON_ID("pioC", &pioCD_clk),
diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
index e503538..ede940c 100644
--- a/arch/arm/mach-at91/at91sam9x5.c
+++ b/arch/arm/mach-at91/at91sam9x5.c
@@ -234,6 +234,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
 	CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
 	CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
+	CLKDEV_CON_DEV_ID("spi_clk", "f0000000.spi", &spi0_clk),
+	CLKDEV_CON_DEV_ID("spi_clk", "f0004000.spi", &spi1_clk),
 	CLKDEV_CON_ID("pioA", &pioAB_clk),
 	CLKDEV_CON_ID("pioB", &pioAB_clk),
 	CLKDEV_CON_ID("pioC", &pioCD_clk),
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 13/14] ARM: dts: add spi nodes for atmel SoC
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
                   ` (11 preceding siblings ...)
  2012-12-04  7:53 ` [v2 PATCH 12/14] ARM: at91: add clocks for spi DT entries Wenyou Yang
@ 2012-12-04  7:53 ` Wenyou Yang
       [not found]   ` <50C0C9C9.9000108@atmel.com>
  2012-12-04  7:54 ` [v2 PATCH 14/14] ARM: dts: add spi nodes for atmel boards Wenyou Yang
  13 siblings, 1 reply; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, linux

From: Richard Genoud <richard.genoud@gmail.com>

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
[wenyou.yang@atmel.com: add spi nodes for other atmel SOC]
Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Cc: linux@arm.linux.org.uk
---
 arch/arm/boot/dts/at91sam9260.dtsi |   30 ++++++++++++++++++++++++++++++
 arch/arm/boot/dts/at91sam9263.dtsi |   30 ++++++++++++++++++++++++++++++
 arch/arm/boot/dts/at91sam9g45.dtsi |   30 ++++++++++++++++++++++++++++++
 arch/arm/boot/dts/at91sam9n12.dtsi |   30 ++++++++++++++++++++++++++++++
 arch/arm/boot/dts/at91sam9x5.dtsi  |   30 ++++++++++++++++++++++++++++++
 5 files changed, 150 insertions(+)

diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index d410581..87254aa 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -212,6 +212,36 @@
 				status = "disabled";
 			};
 
+			spi0: spi@fffc8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9260-spi";
+				reg = <0xfffc8000 0x200>;
+				interrupts = <12 4 3>;
+				cs-gpios = <&pioA 3 0
+					    &pioC 11 0
+					    &pioC 16 0
+					    &pioC 17 0
+					   >;
+				dma-mask = <0xffffffff>;
+				status = "disabled";
+			};
+
+			spi1: spi@fffcc000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9260-spi";
+				reg = <0xfffcc000 0x200>;
+				interrupts = <13 4 3>;
+				cs-gpios = <&pioB 3 0
+					    &pioC 5 0
+					    &pioC 4 0
+					    &pioC 3 0
+					   >;
+				dma-mask = <0xffffffff>;
+				status = "disabled";
+			};
+
 			adc0: adc@fffe0000 {
 				compatible = "atmel,at91sam9260-adc";
 				reg = <0xfffe0000 0x100>;
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
index 3e6e5c1..528395d 100644
--- a/arch/arm/boot/dts/at91sam9263.dtsi
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -195,6 +195,36 @@
 				#size-cells = <0>;
 				status = "disabled";
 			};
+
+			spi0: spi@fffa4000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9260-spi";
+				reg = <0xfffa4000 0x200>;
+				interrupts = <14 4 3>;
+				cs-gpios = <&pioA 5 0
+					    &pioA 3 0
+					    &pioA 4 0
+					    &pioB 11 0
+					   >;
+				dma-mask = <0xffffffff>;
+				status = "disabled";
+			};
+
+			spi1: spi@fffa8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9260-spi";
+				reg = <0xfffa8000 0x200>;
+				interrupts = <15 4 3>;
+				cs-gpios = <&pioB 15 0
+					    &pioB 16 0
+					    &pioB 17 0
+					    &pioB 18 0
+					   >;
+				dma-mask = <0xffffffff>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index 3add030..8a6aae92 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -262,6 +262,36 @@
 					trigger-value = <0x6>;
 				};
 			};
+
+			spi0: spi@fffa4000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9260-spi";
+				reg = <0xfffa4000 0x200>;
+				interrupts = <14 4 3>;
+				cs-gpios = <&pioB 3 0
+					    &pioB 18 0
+					    &pioB 19 0
+					    &pioD 27 0
+					   >;
+				dma-mask = <0xffffffff>;
+				status = "disabled";
+			};
+
+			spi1: spi@fffa8000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9260-spi";
+				reg = <0xfffa8000 0x200>;
+				interrupts = <15 4 3>;
+				cs-gpios = <&pioB 17 0
+					    &pioD 28 0
+					    &pioD 18 0
+					    &pioD 19 0
+					   >;
+				dma-mask = <0xffffffff>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
index 82508d6..183cacf 100644
--- a/arch/arm/boot/dts/at91sam9n12.dtsi
+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
@@ -202,6 +202,36 @@
 				#size-cells = <0>;
 				status = "disabled";
 			};
+
+			spi0: spi@f0000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9x5-spi";
+				reg = <0xf0000000 0x100>;
+				interrupts = <13 4 3>;
+				cs-gpios = <&pioA 14 0
+					    &pioA 7 0
+					    &pioA 1 0
+					    &pioB 3 0
+					   >;
+				dma-mask = <0xffffffff>;
+				status = "disabled";
+			};
+
+			spi1: spi@f0004000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9x5-spi";
+				reg = <0xf0004000 0x100>;
+				interrupts = <14 4 3>;
+				cs-gpios = <&pioA 8 0
+					    &pioA 0 0
+					    &pioA 31 0
+					    &pioA 30 0
+					   >;
+				dma-mask = <0xffffffff>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 03fc136..95b55fd 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -263,6 +263,36 @@
 					trigger-value = <0x6>;
 				};
 			};
+
+			spi0: spi@f0000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9x5-spi";
+				reg = <0xf0000000 0x100>;
+				interrupts = <13 4 3>;
+				cs-gpios = <&pioA 14 0
+					    &pioA 7 0 /* conflicts with TXD2 */
+					    &pioA 1 0 /* conflicts with RXD0 */
+					    &pioB 3 0 /* conflicts with ERXDV */
+					   >;
+				dma-mask = <0xffffffff>;
+				status = "disabled";
+			};
+
+			spi1: spi@f0004000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "atmel,at91sam9x5-spi";
+				reg = <0xf0004000 0x100>;
+				interrupts = <14 4 3>;
+				cs-gpios = <&pioA 8 0 /* conflitcs with RXD2 */
+					    &pioA 0 0 /* conflitcs with TXD0 */
+					    &pioA 31 0 /* conflitcs with TWCK0 */
+					    &pioA 30 0 /* conflitcs with TWD0 */
+					   >;
+				dma-mask = <0xffffffff>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand@40000000 {
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [v2 PATCH 14/14] ARM: dts: add spi nodes for atmel boards
  2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
                   ` (12 preceding siblings ...)
  2012-12-04  7:53 ` [v2 PATCH 13/14] ARM: dts: add spi nodes for atmel SoC Wenyou Yang
@ 2012-12-04  7:54 ` Wenyou Yang
  13 siblings, 0 replies; 20+ messages in thread
From: Wenyou Yang @ 2012-12-04  7:54 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, linux

From: Richard Genoud <richard.genoud@gmail.com>

Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
[wenyou.yang@atmel.com: added spi nodes for other atmel boards]
[wenyou.yang@atmel.com: remove the cs-gpios property for sam9x5ek boards]
Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Cc: linux@arm.linux.org.uk
---
 arch/arm/boot/dts/at91sam9263ek.dts         |    9 +++++++++
 arch/arm/boot/dts/at91sam9g20ek_common.dtsi |    9 +++++++++
 arch/arm/boot/dts/at91sam9g25ek.dts         |    9 +++++++++
 arch/arm/boot/dts/at91sam9m10g45ek.dts      |    9 +++++++++
 arch/arm/boot/dts/at91sam9n12ek.dts         |    9 +++++++++
 5 files changed, 45 insertions(+)

diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts
index f86ac4b..11e274d 100644
--- a/arch/arm/boot/dts/at91sam9263ek.dts
+++ b/arch/arm/boot/dts/at91sam9263ek.dts
@@ -50,6 +50,15 @@
 				atmel,vbus-gpio = <&pioA 25 0>;
 				status = "okay";
 			};
+
+			spi0: spi@fffa4000 {
+				status = "okay";
+				mtd_dataflash@0 {
+					compatible = "atmel,at45", "atmel,dataflash";
+					spi-max-frequency = <50000000>;
+					reg = <0>;
+				};
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
index e6391a4..3c3b63d 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -51,6 +51,15 @@
 				atmel,vbus-gpio = <&pioC 5 0>;
 				status = "okay";
 			};
+
+			spi0: spi@fffc8000 {
+				status = "okay";
+				mtd_dataflash@0 {
+					compatible = "atmel,at45", "atmel,dataflash";
+					spi-max-frequency = <50000000>;
+					reg = <1>;
+				};
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
index 877c08f..3b84bc9 100644
--- a/arch/arm/boot/dts/at91sam9g25ek.dts
+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
@@ -44,6 +44,15 @@
 			i2c2: i2c@f8018000 {
 				status = "okay";
 			};
+
+			spi0: spi@f0000000 {
+				status = "okay";
+				m25p80@0 {
+					compatible = "atmel,at25df321a";
+					spi-max-frequency = <50000000>;
+					reg = <0>;
+				};
+			};
 		};
 
 		usb0: ohci@00600000 {
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
index 15e1dd4..a23ac6e 100644
--- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -54,6 +54,15 @@
 			i2c1: i2c@fff88000 {
 				status = "okay";
 			};
+
+			spi0: spi@fffa4000{
+				status = "okay";
+				mtd_dataflash@0 {
+					compatible = "atmel,at45", "atmel,dataflash";
+					spi-max-frequency = <13000000>;
+					reg = <0>;
+				};
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
index 912b2c2..706bd00 100644
--- a/arch/arm/boot/dts/at91sam9n12ek.dts
+++ b/arch/arm/boot/dts/at91sam9n12ek.dts
@@ -45,6 +45,15 @@
 			i2c1: i2c@f8014000 {
 				status = "okay";
 			};
+
+			spi0: spi@f0000000 {
+				status = "okay";
+				m25p80@0 {
+					compatible = "atmel,at25df321a";
+					spi-max-frequency = <50000000>;
+					reg = <0>;
+				};
+			};
 		};
 
 		nand0: nand@40000000 {
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [v2 PATCH 01/14] of: add dma-mask binding
  2012-12-04  7:53 ` [v2 PATCH 01/14] of: add dma-mask binding Wenyou Yang
@ 2012-12-04 13:16   ` Rob Herring
  0 siblings, 0 replies; 20+ messages in thread
From: Rob Herring @ 2012-12-04 13:16 UTC (permalink / raw)
  To: Wenyou Yang
  Cc: linux-arm-kernel, JM.Lin, linux-kernel, rob.herring, devicetree-discuss

On 12/04/2012 01:53 AM, Wenyou Yang wrote:
> From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> 
> This will allow each device to specify its dma-mask for this we use the
> coherent_dma_mask as pointer. By default the dma-mask will be set to
> DMA_BIT_MASK(32).
> The microblaze architecture hook is drop
> 
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Cc: grant.likely@secretlab.ca
> Cc: rob.herring@calxeda.com
> Cc: devicetree-discuss@lists.ozlabs.org
> ---

My same comment as the last version applies. Use dma-ranges.

Rob

>  drivers/of/platform.c |   23 ++++++++++++++++-------
>  1 file changed, 16 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index b80891b..31ed405 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -130,6 +130,21 @@ void of_device_make_bus_id(struct device *dev)
>  	dev_set_name(dev, "%s.%d", node->name, magic - 1);
>  }
>  
> +static void of_get_dma_mask(struct device *dev, struct device_node *np)
> +{
> +	const __be32 *prop;
> +	int len;
> +
> +	prop = of_get_property(np, "dma-mask", &len);
> +
> +	dev->dma_mask = &dev->coherent_dma_mask;
> +
> +	if (!prop)
> +		dev->coherent_dma_mask = DMA_BIT_MASK(32);
> +	else
> +		dev->coherent_dma_mask = of_read_number(prop, len / 4);
> +}
> +
>  /**
>   * of_device_alloc - Allocate and initialize an of_device
>   * @np: device node to assign to device
> @@ -171,10 +186,8 @@ struct platform_device *of_device_alloc(struct device_node *np,
>  		WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
>  	}
>  
> +	of_get_dma_mask(&dev->dev, np);
>  	dev->dev.of_node = of_node_get(np);
> -#if defined(CONFIG_MICROBLAZE)
> -	dev->dev.dma_mask = &dev->archdata.dma_mask;
> -#endif
>  	dev->dev.parent = parent;
>  
>  	if (bus_id)
> @@ -211,10 +224,6 @@ struct platform_device *of_platform_device_create_pdata(
>  	if (!dev)
>  		return NULL;
>  
> -#if defined(CONFIG_MICROBLAZE)
> -	dev->archdata.dma_mask = 0xffffffffUL;
> -#endif
> -	dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
>  	dev->dev.bus = &platform_bus_type;
>  	dev->dev.platform_data = platform_data;
>  
> 


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [v2 PATCH 02/14] of_spi: add generic binding support to specify cs gpio
  2012-12-04  7:53 ` [v2 PATCH 02/14] of_spi: add generic binding support to specify cs gpio Wenyou Yang
@ 2012-12-05 23:28   ` Grant Likely
  0 siblings, 0 replies; 20+ messages in thread
From: Grant Likely @ 2012-12-05 23:28 UTC (permalink / raw)
  To: Wenyou Yang, linux-arm-kernel
  Cc: linux-kernel, nicolas.ferre, plagnioj, richard.genoud, JM.Lin,
	wenyou.yang, devicetree-discuss, spi-devel-general, rob.herring,
	rob

On Tue,  4 Dec 2012 15:53:48 +0800, Wenyou Yang <wenyou.yang@atmel.com> wrote:
> From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> 
> This will allow to use gpio for chip select with no modification in the
> driver binding
> 
> When use the cs-gpios, the gpio number will be passed via the cs_gpio field
> and the number of chip select will automatically increased.
> 
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Cc: devicetree-discuss@lists.ozlabs.org
> Cc: spi-devel-general@lists.sourceforge.net
> Cc: grant.likely@secretlab.ca
> Cc: rob.herring@calxeda.com
> Cc: rob@landley.net
> Cc: richard.genoud@gmail.com
> ---
> Hi, Richard,
> 
> This patch based on the original patch from Jean-Christophe, 
>  	[PATCH] of_spi: add generic binding support to specify cs gpio
> and merge the patch from Richard Genoud,
> 	[PATCH] [BUG] SPI: array out of bound => no CS
> 
> Could you sign your signature in this patch?
> 
> Best Regards,
> Wenyou Yang

I've already merged a version of this patch. Please check against the
version that is in linux-next.

g.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: [v2 PATCH 13/14] ARM: dts: add spi nodes for atmel SoC
       [not found]   ` <50C0C9C9.9000108@atmel.com>
@ 2012-12-07  1:34     ` Yang, Wenyou
  2012-12-07  6:56     ` Jean-Christophe PLAGNIOL-VILLARD
  1 sibling, 0 replies; 20+ messages in thread
From: Yang, Wenyou @ 2012-12-07  1:34 UTC (permalink / raw)
  To: Desroches, Ludovic
  Cc: linux-arm-kernel, linux, richard.genoud, Lin, JM, Ferre, Nicolas,
	linux-kernel, plagnioj

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 7844 bytes --]

Hi Ludovic,

> -----Original Message-----
> From: Desroches, Ludovic
> Sent: 2012Äê12ÔÂ7ÈÕ 0:37
> To: Yang, Wenyou
> Cc: linux-arm-kernel@lists.infradead.org; linux@arm.linux.org.uk;
> richard.genoud@gmail.com; Lin, JM; Ferre, Nicolas; linux-kernel@vger.kernel.org;
> plagnioj@jcrosoft.com; Desroches, Ludovic
> Subject: Re: [v2 PATCH 13/14] ARM: dts: add spi nodes for atmel SoC
> 
> Hi,
> 
> On 12/04/2012 08:53 AM, Wenyou Yang wrote:
> > From: Richard Genoud <richard.genoud@gmail.com>
> >
> > Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
> > [wenyou.yang@atmel.com: add spi nodes for other atmel SOC]
> > Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
> > Cc: linux@arm.linux.org.uk
> > ---
> >   arch/arm/boot/dts/at91sam9260.dtsi |   30
> ++++++++++++++++++++++++++++++
> >   arch/arm/boot/dts/at91sam9263.dtsi |   30
> ++++++++++++++++++++++++++++++
> >   arch/arm/boot/dts/at91sam9g45.dtsi |   30
> ++++++++++++++++++++++++++++++
> >   arch/arm/boot/dts/at91sam9n12.dtsi |   30
> ++++++++++++++++++++++++++++++
> >   arch/arm/boot/dts/at91sam9x5.dtsi  |   30
> ++++++++++++++++++++++++++++++
> >   5 files changed, 150 insertions(+)
> >
> > diff --git a/arch/arm/boot/dts/at91sam9260.dtsi
> b/arch/arm/boot/dts/at91sam9260.dtsi
> > index d410581..87254aa 100644
> > --- a/arch/arm/boot/dts/at91sam9260.dtsi
> > +++ b/arch/arm/boot/dts/at91sam9260.dtsi
> > @@ -212,6 +212,36 @@
> >   				status = "disabled";
> >   			};
> >
> > +			spi0: spi@fffc8000 {
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				compatible = "atmel,at91sam9260-spi";
> > +				reg = <0xfffc8000 0x200>;
> > +				interrupts = <12 4 3>;
> > +				cs-gpios = <&pioA 3 0
> > +					    &pioC 11 0
> > +					    &pioC 16 0
> > +					    &pioC 17 0
> > +					   >;
> 
>  From my point of view, the cs-gpios stuff should be in board dts files
> instead of the SoC dtsi file.
> 
> These pios can be shared with other devices. If only one chip select
> gpio is used on the board, it could avoid some useless pin conflicts.
> 
Thanks
These pins are defined as CS0, CS1, CS2 and CS3 for SoC. it is selected for the board.
And it will not be configured unless it is selected. So it doesn't cause pin conficts.

> Regards
> 
> Ludovic
>
Best Regards,
Wenyou Yang
 
> > +				dma-mask = <0xffffffff>;
> > +				status = "disabled";
> > +			};
> > +
> > +			spi1: spi@fffcc000 {
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				compatible = "atmel,at91sam9260-spi";
> > +				reg = <0xfffcc000 0x200>;
> > +				interrupts = <13 4 3>;
> > +				cs-gpios = <&pioB 3 0
> > +					    &pioC 5 0
> > +					    &pioC 4 0
> > +					    &pioC 3 0
> > +					   >;
> > +				dma-mask = <0xffffffff>;
> > +				status = "disabled";
> > +			};
> > +
> >   			adc0: adc@fffe0000 {
> >   				compatible = "atmel,at91sam9260-adc";
> >   				reg = <0xfffe0000 0x100>;
> > diff --git a/arch/arm/boot/dts/at91sam9263.dtsi
> b/arch/arm/boot/dts/at91sam9263.dtsi
> > index 3e6e5c1..528395d 100644
> > --- a/arch/arm/boot/dts/at91sam9263.dtsi
> > +++ b/arch/arm/boot/dts/at91sam9263.dtsi
> > @@ -195,6 +195,36 @@
> >   				#size-cells = <0>;
> >   				status = "disabled";
> >   			};
> > +
> > +			spi0: spi@fffa4000 {
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				compatible = "atmel,at91sam9260-spi";
> > +				reg = <0xfffa4000 0x200>;
> > +				interrupts = <14 4 3>;
> > +				cs-gpios = <&pioA 5 0
> > +					    &pioA 3 0
> > +					    &pioA 4 0
> > +					    &pioB 11 0
> > +					   >;
> > +				dma-mask = <0xffffffff>;
> > +				status = "disabled";
> > +			};
> > +
> > +			spi1: spi@fffa8000 {
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				compatible = "atmel,at91sam9260-spi";
> > +				reg = <0xfffa8000 0x200>;
> > +				interrupts = <15 4 3>;
> > +				cs-gpios = <&pioB 15 0
> > +					    &pioB 16 0
> > +					    &pioB 17 0
> > +					    &pioB 18 0
> > +					   >;
> > +				dma-mask = <0xffffffff>;
> > +				status = "disabled";
> > +			};
> >   		};
> >
> >   		nand0: nand@40000000 {
> > diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi
> b/arch/arm/boot/dts/at91sam9g45.dtsi
> > index 3add030..8a6aae92 100644
> > --- a/arch/arm/boot/dts/at91sam9g45.dtsi
> > +++ b/arch/arm/boot/dts/at91sam9g45.dtsi
> > @@ -262,6 +262,36 @@
> >   					trigger-value = <0x6>;
> >   				};
> >   			};
> > +
> > +			spi0: spi@fffa4000 {
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				compatible = "atmel,at91sam9260-spi";
> > +				reg = <0xfffa4000 0x200>;
> > +				interrupts = <14 4 3>;
> > +				cs-gpios = <&pioB 3 0
> > +					    &pioB 18 0
> > +					    &pioB 19 0
> > +					    &pioD 27 0
> > +					   >;
> > +				dma-mask = <0xffffffff>;
> > +				status = "disabled";
> > +			};
> > +
> > +			spi1: spi@fffa8000 {
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				compatible = "atmel,at91sam9260-spi";
> > +				reg = <0xfffa8000 0x200>;
> > +				interrupts = <15 4 3>;
> > +				cs-gpios = <&pioB 17 0
> > +					    &pioD 28 0
> > +					    &pioD 18 0
> > +					    &pioD 19 0
> > +					   >;
> > +				dma-mask = <0xffffffff>;
> > +				status = "disabled";
> > +			};
> >   		};
> >
> >   		nand0: nand@40000000 {
> > diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi
> b/arch/arm/boot/dts/at91sam9n12.dtsi
> > index 82508d6..183cacf 100644
> > --- a/arch/arm/boot/dts/at91sam9n12.dtsi
> > +++ b/arch/arm/boot/dts/at91sam9n12.dtsi
> > @@ -202,6 +202,36 @@
> >   				#size-cells = <0>;
> >   				status = "disabled";
> >   			};
> > +
> > +			spi0: spi@f0000000 {
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				compatible = "atmel,at91sam9x5-spi";
> > +				reg = <0xf0000000 0x100>;
> > +				interrupts = <13 4 3>;
> > +				cs-gpios = <&pioA 14 0
> > +					    &pioA 7 0
> > +					    &pioA 1 0
> > +					    &pioB 3 0
> > +					   >;
> > +				dma-mask = <0xffffffff>;
> > +				status = "disabled";
> > +			};
> > +
> > +			spi1: spi@f0004000 {
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				compatible = "atmel,at91sam9x5-spi";
> > +				reg = <0xf0004000 0x100>;
> > +				interrupts = <14 4 3>;
> > +				cs-gpios = <&pioA 8 0
> > +					    &pioA 0 0
> > +					    &pioA 31 0
> > +					    &pioA 30 0
> > +					   >;
> > +				dma-mask = <0xffffffff>;
> > +				status = "disabled";
> > +			};
> >   		};
> >
> >   		nand0: nand@40000000 {
> > diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi
> b/arch/arm/boot/dts/at91sam9x5.dtsi
> > index 03fc136..95b55fd 100644
> > --- a/arch/arm/boot/dts/at91sam9x5.dtsi
> > +++ b/arch/arm/boot/dts/at91sam9x5.dtsi
> > @@ -263,6 +263,36 @@
> >   					trigger-value = <0x6>;
> >   				};
> >   			};
> > +
> > +			spi0: spi@f0000000 {
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				compatible = "atmel,at91sam9x5-spi";
> > +				reg = <0xf0000000 0x100>;
> > +				interrupts = <13 4 3>;
> > +				cs-gpios = <&pioA 14 0
> > +					    &pioA 7 0 /* conflicts with TXD2 */
> > +					    &pioA 1 0 /* conflicts with RXD0 */
> > +					    &pioB 3 0 /* conflicts with ERXDV */
> > +					   >;
> > +				dma-mask = <0xffffffff>;
> > +				status = "disabled";
> > +			};
> > +
> > +			spi1: spi@f0004000 {
> > +				#address-cells = <1>;
> > +				#size-cells = <0>;
> > +				compatible = "atmel,at91sam9x5-spi";
> > +				reg = <0xf0004000 0x100>;
> > +				interrupts = <14 4 3>;
> > +				cs-gpios = <&pioA 8 0 /* conflitcs with RXD2 */
> > +					    &pioA 0 0 /* conflitcs with TXD0 */
> > +					    &pioA 31 0 /* conflitcs with TWCK0 */
> > +					    &pioA 30 0 /* conflitcs with TWD0 */
> > +					   >;
> > +				dma-mask = <0xffffffff>;
> > +				status = "disabled";
> > +			};
> >   		};
> >
> >   		nand0: nand@40000000 {
> >

ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [v2 PATCH 13/14] ARM: dts: add spi nodes for atmel SoC
       [not found]   ` <50C0C9C9.9000108@atmel.com>
  2012-12-07  1:34     ` Yang, Wenyou
@ 2012-12-07  6:56     ` Jean-Christophe PLAGNIOL-VILLARD
  1 sibling, 0 replies; 20+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-12-07  6:56 UTC (permalink / raw)
  To: ludovic.desroches
  Cc: Wenyou Yang, linux-arm-kernel, linux, richard.genoud, JM.Lin,
	nicolas.ferre, linux-kernel

On 17:37 Thu 06 Dec     , ludovic.desroches wrote:
> Hi,
> 
> On 12/04/2012 08:53 AM, Wenyou Yang wrote:
> >From: Richard Genoud <richard.genoud@gmail.com>
> >
> >Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
> >[wenyou.yang@atmel.com: add spi nodes for other atmel SOC]
> >Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
> >Cc: linux@arm.linux.org.uk
> >---
> >  arch/arm/boot/dts/at91sam9260.dtsi |   30 ++++++++++++++++++++++++++++++
> >  arch/arm/boot/dts/at91sam9263.dtsi |   30 ++++++++++++++++++++++++++++++
> >  arch/arm/boot/dts/at91sam9g45.dtsi |   30 ++++++++++++++++++++++++++++++
> >  arch/arm/boot/dts/at91sam9n12.dtsi |   30 ++++++++++++++++++++++++++++++
> >  arch/arm/boot/dts/at91sam9x5.dtsi  |   30 ++++++++++++++++++++++++++++++
> >  5 files changed, 150 insertions(+)
> >
> >diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
> >index d410581..87254aa 100644
> >--- a/arch/arm/boot/dts/at91sam9260.dtsi
> >+++ b/arch/arm/boot/dts/at91sam9260.dtsi
> >@@ -212,6 +212,36 @@
> >  				status = "disabled";
> >  			};
> >
> >+			spi0: spi@fffc8000 {
> >+				#address-cells = <1>;
> >+				#size-cells = <0>;
> >+				compatible = "atmel,at91sam9260-spi";
> >+				reg = <0xfffc8000 0x200>;
> >+				interrupts = <12 4 3>;
> >+				cs-gpios = <&pioA 3 0
> >+					    &pioC 11 0
> >+					    &pioC 16 0
> >+					    &pioC 17 0
> >+					   >;
> 
> From my point of view, the cs-gpios stuff should be in board dts
> files instead of the SoC dtsi file.
> 
> These pios can be shared with other devices. If only one chip select
> gpio is used on the board, it could avoid some useless pin
> conflicts.
agree and you MUST based on work on what I send on the ML and Grant applyed

Best Regards,
J.
> 
> Regards
> 
> Ludovic
> 
> >+				dma-mask = <0xffffffff>;
> >+				status = "disabled";
> >+			};
> >+
> >+			spi1: spi@fffcc000 {
> >+				#address-cells = <1>;
> >+				#size-cells = <0>;
> >+				compatible = "atmel,at91sam9260-spi";
> >+				reg = <0xfffcc000 0x200>;
> >+				interrupts = <13 4 3>;
> >+				cs-gpios = <&pioB 3 0
> >+					    &pioC 5 0
> >+					    &pioC 4 0
> >+					    &pioC 3 0
> >+					   >;
> >+				dma-mask = <0xffffffff>;
> >+				status = "disabled";
> >+			};
> >+
> >  			adc0: adc@fffe0000 {
> >  				compatible = "atmel,at91sam9260-adc";
> >  				reg = <0xfffe0000 0x100>;
> >diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
> >index 3e6e5c1..528395d 100644
> >--- a/arch/arm/boot/dts/at91sam9263.dtsi
> >+++ b/arch/arm/boot/dts/at91sam9263.dtsi
> >@@ -195,6 +195,36 @@
> >  				#size-cells = <0>;
> >  				status = "disabled";
> >  			};
> >+
> >+			spi0: spi@fffa4000 {
> >+				#address-cells = <1>;
> >+				#size-cells = <0>;
> >+				compatible = "atmel,at91sam9260-spi";
> >+				reg = <0xfffa4000 0x200>;
> >+				interrupts = <14 4 3>;
> >+				cs-gpios = <&pioA 5 0
> >+					    &pioA 3 0
> >+					    &pioA 4 0
> >+					    &pioB 11 0
> >+					   >;
> >+				dma-mask = <0xffffffff>;
> >+				status = "disabled";
> >+			};
> >+
> >+			spi1: spi@fffa8000 {
> >+				#address-cells = <1>;
> >+				#size-cells = <0>;
> >+				compatible = "atmel,at91sam9260-spi";
> >+				reg = <0xfffa8000 0x200>;
> >+				interrupts = <15 4 3>;
> >+				cs-gpios = <&pioB 15 0
> >+					    &pioB 16 0
> >+					    &pioB 17 0
> >+					    &pioB 18 0
> >+					   >;
> >+				dma-mask = <0xffffffff>;
> >+				status = "disabled";
> >+			};
> >  		};
> >
> >  		nand0: nand@40000000 {
> >diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
> >index 3add030..8a6aae92 100644
> >--- a/arch/arm/boot/dts/at91sam9g45.dtsi
> >+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
> >@@ -262,6 +262,36 @@
> >  					trigger-value = <0x6>;
> >  				};
> >  			};
> >+
> >+			spi0: spi@fffa4000 {
> >+				#address-cells = <1>;
> >+				#size-cells = <0>;
> >+				compatible = "atmel,at91sam9260-spi";
> >+				reg = <0xfffa4000 0x200>;
> >+				interrupts = <14 4 3>;
> >+				cs-gpios = <&pioB 3 0
> >+					    &pioB 18 0
> >+					    &pioB 19 0
> >+					    &pioD 27 0
> >+					   >;
> >+				dma-mask = <0xffffffff>;
> >+				status = "disabled";
> >+			};
> >+
> >+			spi1: spi@fffa8000 {
> >+				#address-cells = <1>;
> >+				#size-cells = <0>;
> >+				compatible = "atmel,at91sam9260-spi";
> >+				reg = <0xfffa8000 0x200>;
> >+				interrupts = <15 4 3>;
> >+				cs-gpios = <&pioB 17 0
> >+					    &pioD 28 0
> >+					    &pioD 18 0
> >+					    &pioD 19 0
> >+					   >;
> >+				dma-mask = <0xffffffff>;
> >+				status = "disabled";
> >+			};
> >  		};
> >
> >  		nand0: nand@40000000 {
> >diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
> >index 82508d6..183cacf 100644
> >--- a/arch/arm/boot/dts/at91sam9n12.dtsi
> >+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
> >@@ -202,6 +202,36 @@
> >  				#size-cells = <0>;
> >  				status = "disabled";
> >  			};
> >+
> >+			spi0: spi@f0000000 {
> >+				#address-cells = <1>;
> >+				#size-cells = <0>;
> >+				compatible = "atmel,at91sam9x5-spi";
> >+				reg = <0xf0000000 0x100>;
> >+				interrupts = <13 4 3>;
> >+				cs-gpios = <&pioA 14 0
> >+					    &pioA 7 0
> >+					    &pioA 1 0
> >+					    &pioB 3 0
> >+					   >;
> >+				dma-mask = <0xffffffff>;
> >+				status = "disabled";
> >+			};
> >+
> >+			spi1: spi@f0004000 {
> >+				#address-cells = <1>;
> >+				#size-cells = <0>;
> >+				compatible = "atmel,at91sam9x5-spi";
> >+				reg = <0xf0004000 0x100>;
> >+				interrupts = <14 4 3>;
> >+				cs-gpios = <&pioA 8 0
> >+					    &pioA 0 0
> >+					    &pioA 31 0
> >+					    &pioA 30 0
> >+					   >;
> >+				dma-mask = <0xffffffff>;
> >+				status = "disabled";
> >+			};
> >  		};
> >
> >  		nand0: nand@40000000 {
> >diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
> >index 03fc136..95b55fd 100644
> >--- a/arch/arm/boot/dts/at91sam9x5.dtsi
> >+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
> >@@ -263,6 +263,36 @@
> >  					trigger-value = <0x6>;
> >  				};
> >  			};
> >+
> >+			spi0: spi@f0000000 {
> >+				#address-cells = <1>;
> >+				#size-cells = <0>;
> >+				compatible = "atmel,at91sam9x5-spi";
> >+				reg = <0xf0000000 0x100>;
> >+				interrupts = <13 4 3>;
> >+				cs-gpios = <&pioA 14 0
> >+					    &pioA 7 0 /* conflicts with TXD2 */
> >+					    &pioA 1 0 /* conflicts with RXD0 */
> >+					    &pioB 3 0 /* conflicts with ERXDV */
> >+					   >;
> >+				dma-mask = <0xffffffff>;
> >+				status = "disabled";
> >+			};
> >+
> >+			spi1: spi@f0004000 {
> >+				#address-cells = <1>;
> >+				#size-cells = <0>;
> >+				compatible = "atmel,at91sam9x5-spi";
> >+				reg = <0xf0004000 0x100>;
> >+				interrupts = <14 4 3>;
> >+				cs-gpios = <&pioA 8 0 /* conflitcs with RXD2 */
> >+					    &pioA 0 0 /* conflitcs with TXD0 */
> >+					    &pioA 31 0 /* conflitcs with TWCK0 */
> >+					    &pioA 30 0 /* conflitcs with TWD0 */
> >+					   >;
> >+				dma-mask = <0xffffffff>;
> >+				status = "disabled";
> >+			};
> >  		};
> >
> >  		nand0: nand@40000000 {
> >
> 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [v2 PATCH 07/14] spi/atmel_spi: add DT support
  2012-12-04  7:53 ` [v2 PATCH 07/14] spi/atmel_spi: add DT support Wenyou Yang
@ 2012-12-07  6:58   ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 0 replies; 20+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-12-07  6:58 UTC (permalink / raw)
  To: Wenyou Yang
  Cc: linux-arm-kernel, linux-kernel, nicolas.ferre, richard.genoud,
	JM.Lin, devicetree-discuss, spi-devel-general, grant.likely,
	rob.herring, rob, linux-doc

On 15:53 Tue 04 Dec     , Wenyou Yang wrote:
> From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> 
> The atmel_spi use only gpio for chip select.
no this patch need go on the TOP of mine

that is plan for 3.8

Best Regards,
J.
> 
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> [wenyou.yang@atmel.com: Add driver data and compatible "atmel,at91sam9260-spi", "atmel,at91sam9x5-spi"]
> Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
> Cc: devicetree-discuss@lists.ozlabs.org
> Cc: spi-devel-general@lists.sourceforge.net
> Cc: grant.likely@secretlab.ca
> Cc: rob.herring@calxeda.com
> Cc: rob@landley.net
> Cc: linux-doc@vger.kernel.org
> Cc: richard.genoud@gmail.com
> ---
> Hi, Richard,
> 
> This patches is based on the original patch from Jean-Christophe
> 	[PATCH] spi/atmel: add DT support
> and merge the patch from Richard Genoud
> 	[PATCH] spi-atmel OF: complete documentation
> ane wenyou yang add more compatible "atmel,at91sam9260-spi", "atmel,at91sam9x5-spi", 
> 	add driver data to get IP version and dma support.
> 
> Could you sign your signature in this patch?
> 
> Best Regards,
> Wenyou Yang
> 
>  .../devicetree/bindings/spi/spi_atmel.txt          |   23 +++++
>  drivers/spi/spi-atmel.c                            |  102 +++++++++++++++++---
>  2 files changed, 113 insertions(+), 12 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/spi/spi_atmel.txt
> 
> diff --git a/Documentation/devicetree/bindings/spi/spi_atmel.txt b/Documentation/devicetree/bindings/spi/spi_atmel.txt
> new file mode 100644
> index 0000000..20cdc91
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/spi/spi_atmel.txt
> @@ -0,0 +1,23 @@
> +Atmel SPI device
> +
> +Required properties:
> +- compatible : should be "atmel,at91rm9200-spi".
> +- reg: Address and length of the register set for the device
> +- interrupts: Should contain macb interrupt
> +- cs-gpio: Should contain the GPIOs used for chipselect.
> +- dma-mask: device coherent dma mask.
> +
> +spi0: spi@f0000000 {
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +	compatible = "atmel,at91rm9200-spi";
> +	reg = <0xf0000000 0x100>;
> +	interrupts = <13 4>;
> +	cs-gpios = <&pioA 14 0
> +		    &pioA 7 0 /* conflicts with TXD2 */
> +		    &pioA 1 0 /* conflicts with RXD0 */
> +		    &pioB 3 0 /* conflicts with ERXDV */
> +		   >;
> +	dma-mask = <0xffffffff>;
> +	status = "disabled";
> +};
> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
> index 37f54c3..e032e3d 100644
> --- a/drivers/spi/spi-atmel.c
> +++ b/drivers/spi/spi-atmel.c
> @@ -19,6 +19,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/spi/spi.h>
>  #include <linux/slab.h>
> +#include <linux/of.h>
>  
>  #include <asm/io.h>
>  #include <mach/board.h>
> @@ -185,6 +186,10 @@
>   * DMA transfers; transfer queue progress is driven by IRQs.  The clock
>   * framework provides the base clock, subdivided for each spi_device.
>   */
> +struct atmel_spi_pdata {
> +	u8			version;
> +};
> +
>  struct atmel_spi {
>  	spinlock_t		lock;
>  	unsigned long		flags;
> @@ -203,6 +208,7 @@ struct atmel_spi {
>  	struct spi_transfer	*next_transfer;
>  	unsigned long		next_remaining_bytes;
>  	int			done_status;
> +	struct atmel_spi_pdata	*pdata;
>  
>  	void			*buffer;
>  	dma_addr_t		buffer_dma;
> @@ -217,6 +223,51 @@ struct atmel_spi_device {
>  #define BUFFER_SIZE		PAGE_SIZE
>  #define INVALID_DMA_ADDRESS	0xffffffff
>  
> +static struct atmel_spi_pdata at91rm9200_config = {
> +	.version = 1,
> +};
> +
> +static struct atmel_spi_pdata at91sam9260_config = {
> +	.version = 2,
> +};
> +
> +static struct atmel_spi_pdata at91sam9x5_config = {
> +	.version = 2,
> +};
> +
> +static const struct platform_device_id atmel_spi_devtypes[] = {
> +	{
> +		.name = "spi-at91rm9200",
> +		.driver_data = (unsigned long) &at91rm9200_config,
> +	}, {
> +		.name = "spi-at91sam9260",
> +		.driver_data = (unsigned long) &at91sam9260_config,
> +	}, {
> +		.name = "spi-at91sam9x5",
> +		.driver_data = (unsigned long) &at91sam9x5_config,
> +	}, {
> +		/* sentinel */
> +	}
> +};
> +
> +#if defined(CONFIG_OF)
> +static const struct of_device_id atmel_spi_dt_ids[] = {
> +	{
> +		.compatible = "atmel,at91rm9200-spi",
> +		.data = &at91rm9200_config,
> +	} , {
> +		.compatible = "atmel,at91sam9260-spi",
> +		.data = &at91sam9260_config,
> +	} , {
> +		.compatible = "atmel,at91sam9x5-spi",
> +		.data = &at91sam9x5_config,
> +	}, {
> +		/* sentinel */
> +	}
> +};
> +MODULE_DEVICE_TABLE(of, atmel_spi_dt_ids);
> +#endif
> +
>  /*
>   * Version 2 of the SPI controller has
>   *  - CR.LASTXFER
> @@ -229,11 +280,15 @@ struct atmel_spi_device {
>   * register, but I haven't checked that it exists on all chips, and
>   * this is cheaper anyway.
>   */
> -static bool atmel_spi_is_v2(void)
> +static bool atmel_spi_is_v2(struct atmel_spi *as)
>  {
> -	return !cpu_is_at91rm9200();
> +	if (as->pdata->version == 2)
> +		return true;
> +	else
> +		return false;
>  }
>  
> +
>  /*
>   * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
>   * they assume that spi slave device state will not change on deselect, so
> @@ -265,7 +320,7 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
>  	unsigned active = spi->mode & SPI_CS_HIGH;
>  	u32 mr;
>  
> -	if (atmel_spi_is_v2()) {
> +	if (atmel_spi_is_v2(as)) {
>  		/*
>  		 * Always use CSR0. This ensures that the clock
>  		 * switches to the correct idle polarity before we
> @@ -320,7 +375,7 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
>  			asd->npcs_pin, active ? " (low)" : "",
>  			mr);
>  
> -	if (atmel_spi_is_v2() || spi->chip_select != 0)
> +	if (atmel_spi_is_v2(as) || spi->chip_select != 0)
>  		gpio_set_value(asd->npcs_pin, !active);
>  }
>  
> @@ -710,7 +765,7 @@ static int atmel_spi_setup(struct spi_device *spi)
>  	u32			scbr, csr;
>  	unsigned int		bits = spi->bits_per_word;
>  	unsigned long		bus_hz;
> -	unsigned int		npcs_pin;
> +	int			npcs_pin;
>  	int			ret;
>  
>  	as = spi_master_get_devdata(spi->master);
> @@ -733,7 +788,7 @@ static int atmel_spi_setup(struct spi_device *spi)
>  	}
>  
>  	/* see notes above re chipselect */
> -	if (!atmel_spi_is_v2()
> +	if (!atmel_spi_is_v2(as)
>  			&& spi->chip_select == 0
>  			&& (spi->mode & SPI_CS_HIGH)) {
>  		dev_dbg(&spi->dev, "setup: can't be active-high\n");
> @@ -742,7 +797,7 @@ static int atmel_spi_setup(struct spi_device *spi)
>  
>  	/* v1 chips start out at half the peripheral bus speed. */
>  	bus_hz = clk_get_rate(as->clk);
> -	if (!atmel_spi_is_v2())
> +	if (!atmel_spi_is_v2(as))
>  		bus_hz /= 2;
>  
>  	if (spi->max_speed_hz) {
> @@ -782,7 +837,9 @@ static int atmel_spi_setup(struct spi_device *spi)
>  	csr |= SPI_BF(DLYBCT, 0);
>  
>  	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
> -	npcs_pin = (unsigned int)spi->controller_data;
> +	if (!gpio_is_valid(spi->cs_gpio))
> +		spi->cs_gpio = (int)spi->controller_data;
> +	npcs_pin = spi->cs_gpio;
>  	asd = spi->controller_state;
>  	if (!asd) {
>  		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
> @@ -812,7 +869,7 @@ static int atmel_spi_setup(struct spi_device *spi)
>  		"setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
>  		bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
>  
> -	if (!atmel_spi_is_v2())
> +	if (!atmel_spi_is_v2(as))
>  		spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
>  
>  	return 0;
> @@ -899,7 +956,7 @@ static void atmel_spi_cleanup(struct spi_device *spi)
>  {
>  	struct atmel_spi	*as = spi_master_get_devdata(spi->master);
>  	struct atmel_spi_device	*asd = spi->controller_state;
> -	unsigned		gpio = (unsigned) spi->controller_data;
> +	unsigned		gpio = spi->cs_gpio;
>  
>  	if (!asd)
>  		return;
> @@ -916,6 +973,21 @@ static void atmel_spi_cleanup(struct spi_device *spi)
>  	kfree(asd);
>  }
>  
> +static struct atmel_spi_pdata * __devinit atmel_spi_get_driver_data(
> +					struct platform_device *pdev)
> +{
> +	if (pdev->dev.of_node) {
> +		const struct of_device_id *match;
> +		match = of_match_node(atmel_spi_dt_ids, pdev->dev.of_node);
> +		if (!match)
> +			return NULL;
> +		return (struct atmel_spi_pdata *) match->data;
> +	}
> +
> +	return (struct atmel_spi_pdata *)
> +			platform_get_device_id(pdev)->driver_data;
> +}
> +
>  /*-------------------------------------------------------------------------*/
>  
>  static int __devinit atmel_spi_probe(struct platform_device *pdev)
> @@ -949,7 +1021,8 @@ static int __devinit atmel_spi_probe(struct platform_device *pdev)
>  	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
>  
>  	master->bus_num = pdev->id;
> -	master->num_chipselect = 4;
> +	master->dev.of_node = pdev->dev.of_node;
> +	master->num_chipselect = master->dev.of_node ? 0 : 4;
>  	master->setup = atmel_spi_setup;
>  	master->transfer = atmel_spi_transfer;
>  	master->cleanup = atmel_spi_cleanup;
> @@ -981,6 +1054,10 @@ static int __devinit atmel_spi_probe(struct platform_device *pdev)
>  	if (ret)
>  		goto out_unmap_regs;
>  
> +	as->pdata = atmel_spi_get_driver_data(pdev);
> +	if (!as->pdata)
> +		goto out_unmap_regs;
> +
>  	/* Initialize the hardware */
>  	clk_enable(clk);
>  	spi_writel(as, CR, SPI_BIT(SWRST));
> @@ -1078,12 +1155,13 @@ static int atmel_spi_resume(struct platform_device *pdev)
>  #define	atmel_spi_resume	NULL
>  #endif
>  
> -
>  static struct platform_driver atmel_spi_driver = {
>  	.driver		= {
>  		.name	= "atmel_spi",
>  		.owner	= THIS_MODULE,
> +		.of_match_table	= of_match_ptr(atmel_spi_dt_ids),
>  	},
> +	.id_table	= atmel_spi_devtypes,
>  	.suspend	= atmel_spi_suspend,
>  	.resume		= atmel_spi_resume,
>  	.probe		= atmel_spi_probe,
> -- 
> 1.7.9.5
> 

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2012-12-07  7:06 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-04  7:53 [v2 PATCH 00/14] atmel SPI controller with dmaengine and device tree support Wenyou Yang
2012-12-04  7:53 ` [v2 PATCH 01/14] of: add dma-mask binding Wenyou Yang
2012-12-04 13:16   ` Rob Herring
2012-12-04  7:53 ` [v2 PATCH 02/14] of_spi: add generic binding support to specify cs gpio Wenyou Yang
2012-12-05 23:28   ` Grant Likely
2012-12-04  7:53 ` [v2 PATCH 03/14] spi/atmel_spi: add physical base address Wenyou Yang
2012-12-04  7:53 ` [v2 PATCH 04/14] spi/atmel_spi: call unmapping on transfers buffers Wenyou Yang
2012-12-04  7:53 ` [v2 PATCH 05/14] spi/atmel_spi: status information passed through controller data Wenyou Yang
2012-12-04  7:53 ` [v2 PATCH 06/14] spi/atmel_spi: add flag to controller data for lock operations Wenyou Yang
2012-12-04  7:53 ` [v2 PATCH 07/14] spi/atmel_spi: add DT support Wenyou Yang
2012-12-07  6:58   ` Jean-Christophe PLAGNIOL-VILLARD
2012-12-04  7:53 ` [v2 PATCH 08/14] spi/atmel_spi: add dmaengine support Wenyou Yang
2012-12-04  7:53 ` [v2 PATCH 09/14] spi/atmel_spi: Fix spi-atmel driver to adapt to slave_config changes Wenyou Yang
2012-12-04  7:53 ` [v2 PATCH 10/14] spi/atmel_spi: correct 16 bits transfers using PIO Wenyou Yang
2012-12-04  7:53 ` [v2 PATCH 11/14] spi/atmel_spi: correct 16 bits transfer with DMA Wenyou Yang
2012-12-04  7:53 ` [v2 PATCH 12/14] ARM: at91: add clocks for spi DT entries Wenyou Yang
2012-12-04  7:53 ` [v2 PATCH 13/14] ARM: dts: add spi nodes for atmel SoC Wenyou Yang
     [not found]   ` <50C0C9C9.9000108@atmel.com>
2012-12-07  1:34     ` Yang, Wenyou
2012-12-07  6:56     ` Jean-Christophe PLAGNIOL-VILLARD
2012-12-04  7:54 ` [v2 PATCH 14/14] ARM: dts: add spi nodes for atmel boards Wenyou Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).