linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/5] SPI OF bindings and mpc5200-spi driver
@ 2008-07-03  1:02 Grant Likely
       [not found] ` <20080703005749.26187.71719.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
  0 siblings, 1 reply; 14+ messages in thread
From: Grant Likely @ 2008-07-03  1:02 UTC (permalink / raw)
  To: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	jonsmirl-Re5JQEeQqe8AvxtiuMwx3w

I think I've addressed all the comments I've received.  This series
adds OpenFirmware device tree bindings for SPI devices.  SPI master
drivers which make use of of_spi.c can retrieve the set of spi
devices from the device tree and automatically create them.

This series depends on previously posted patch:
"spi: Change modalias from a pointer to a character array"

 Documentation/powerpc/booting-without-of.txt |   60 +++
 drivers/of/Kconfig                           |    6 +
 drivers/of/Makefile                          |    1 +
 drivers/of/of_spi.c                          |   88 ++++
 drivers/spi/Kconfig                          |    8 +
 drivers/spi/Makefile                         |    1 +
 drivers/spi/mpc52xx_spi.c                    |  595 ++++++++++++++++++++++++++
 drivers/spi/spi.c                            |  141 +++++--
 include/linux/of_spi.h                       |   18 +
 include/linux/spi/mpc52xx_spi.h              |   10 +
 include/linux/spi/spi.h                      |   12 +-
 11 files changed, 895 insertions(+), 45 deletions(-)

--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.

-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* [PATCH v2 1/5] spi: Change modalias from a pointer to a character array
       [not found] ` <20080703005749.26187.71719.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
@ 2008-07-03  1:02   ` Grant Likely
  2008-07-03  1:03   ` [PATCH v2 2/5] spi: split up spi_new_device() to allow two stage registration Grant Likely
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 14+ messages in thread
From: Grant Likely @ 2008-07-03  1:02 UTC (permalink / raw)
  To: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	jonsmirl-Re5JQEeQqe8AvxtiuMwx3w

From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>

Currently, 'modalias' in the spi_device structure is a 'const char *'.
The spi_new_device() function fills in the modalias value from a passed
in spi_board_info data block.  Since it is a pointer copy, the new
spi_device remains dependent on the spi_board_info structure after the
new spi_device is registered (no other fields in spi_device directly
depend on the spi_board_info structure; all of the other data is copied).

This causes a problem when dynamically propulating the list of attached
SPI devices.  For example, in arch/powerpc, the list of SPI devices can
be populated from data in the device tree.  With the current code, the
device tree adapter must kmalloc() a new spi_board_info structure for
each new SPI device it finds in the device tree, and there is no simple
mechanism in place for keeping track of these allocations.

This patch changes modalias from a 'const char *' to a fixed char array.
By copying the modalias string instead of referencing it, the dependency
on the spi_board_info structure is eliminated and an outside caller does
not need to maintain a separate spi_board_info allocation for each device.

If searched through the code to the best of my ability for any references
to modalias which may be affected by this change and haven't found anything.
It has been tested with the lite5200b platform in arch/powerpc.

Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---

 drivers/spi/spi.c       |    4 +++-
 include/linux/spi/spi.h |    2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 1ad12af..32b7a42 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -218,6 +218,8 @@ struct spi_device *spi_new_device(struct spi_master *master,
 	if (!spi_master_get(master))
 		return NULL;
 
+	WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
+
 	proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
 	if (!proxy) {
 		dev_err(dev, "can't alloc dev for cs%d\n",
@@ -229,7 +231,7 @@ struct spi_device *spi_new_device(struct spi_master *master,
 	proxy->max_speed_hz = chip->max_speed_hz;
 	proxy->mode = chip->mode;
 	proxy->irq = chip->irq;
-	proxy->modalias = chip->modalias;
+	strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
 
 	snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
 			"%s.%u", master->dev.bus_id,
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 387e428..b55910b 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -82,7 +82,7 @@ struct spi_device {
 	int			irq;
 	void			*controller_state;
 	void			*controller_data;
-	const char		*modalias;
+	char			modalias[32];
 
 	/*
 	 * likely need more hooks for more protocol options affecting how


-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* [PATCH v2 2/5] spi: split up spi_new_device() to allow two stage registration.
       [not found] ` <20080703005749.26187.71719.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
  2008-07-03  1:02   ` [PATCH v2 1/5] spi: Change modalias from a pointer to a character array Grant Likely
@ 2008-07-03  1:03   ` Grant Likely
  2008-07-03  1:03   ` [PATCH v2 3/5] of-bindings: Add binding documentation for SPI busses and devices Grant Likely
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 14+ messages in thread
From: Grant Likely @ 2008-07-03  1:03 UTC (permalink / raw)
  To: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	jonsmirl-Re5JQEeQqe8AvxtiuMwx3w

From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>

spi_new_device() allocates and registers an spi device all in one swoop.
If the driver needs to add extra data to the spi_device before it is
registered, then this causes problems.

This patch splits the allocation and registration portions of code out
of spi_new_device() and creates three new functions; spi_alloc_device(),
spi_register_device(), and spi_device_release().  spi_new_device() is
modified to use the new functions for allocation and registration.
None of the existing users of spi_new_device() should be affected by
this change.

Drivers using the new API can forego the use of an spi_board_info
structure to describe the device layout and populate data into the
spi_device structure directly.

This change is in preparation for adding an OF device tree parser to
generate spi_devices based on data in the device tree.

Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---

 drivers/spi/spi.c       |  139 ++++++++++++++++++++++++++++++++---------------
 include/linux/spi/spi.h |   10 +++
 2 files changed, 105 insertions(+), 44 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 32b7a42..e64add0 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -178,6 +178,96 @@ struct boardinfo {
 static LIST_HEAD(board_list);
 static DEFINE_MUTEX(board_lock);
 
+/**
+ * spi_alloc_device - Allocate a new SPI device
+ * @master: Controller to which device is connected
+ * Context: can sleep
+ *
+ * Allows a driver to allocate and initialize and spi_device without
+ * registering it immediately.  This allows a driver to directly
+ * fill the spi_device with device parameters before calling
+ * spi_add_device() on it.
+ *
+ * Caller is responsible to call spi_add_device() on the returned
+ * spi_device structure to add it to the SPI master.  If the caller
+ * needs to discard the spi_device without adding it, then it should
+ * call spi_dev_put() on it.
+ *
+ * Returns a pointer to the new device, or NULL.
+ */
+struct spi_device *spi_alloc_device(struct spi_master *master)
+{
+	struct spi_device	*spi;
+	struct device		*dev = master->dev.parent;
+
+	if (!spi_master_get(master))
+		return NULL;
+
+	spi = kzalloc(sizeof *spi, GFP_KERNEL);
+	if (!spi) {
+		dev_err(dev, "cannot alloc spi_device\n");
+		spi_master_put(master);
+		return NULL;
+	}
+
+	spi->master = master;
+	spi->dev.parent = dev;
+	spi->dev.bus = &spi_bus_type;
+	spi->dev.release = spidev_release;
+	device_initialize(&spi->dev);
+	return spi;
+}
+EXPORT_SYMBOL_GPL(spi_alloc_device);
+
+/**
+ * spi_add_device - Add an spi_device allocated with spi_alloc_device
+ * @spi: spi_device to register
+ *
+ * Companion function to spi_alloc_device.  Devices allocated with
+ * spi_alloc_device can be added onto the spi bus with this function.
+ *
+ * Returns 0 on success; non-zero on failure
+ */
+int spi_add_device(struct spi_device *spi)
+{
+	struct device *dev = spi->master->dev.parent;
+	int status;
+
+	/* Chipselects are numbered 0..max; validate. */
+	if (spi->chip_select >= spi->master->num_chipselect) {
+		dev_err(dev, "cs%d > max %d\n",
+			spi->chip_select,
+			spi->master->num_chipselect);
+		return -EINVAL;
+	}
+
+	/* Set the bus ID string */
+	snprintf(spi->dev.bus_id, sizeof spi->dev.bus_id,
+			"%s.%u", spi->master->dev.bus_id,
+			spi->chip_select);
+
+	/* drivers may modify this initial i/o setup */
+	status = spi->master->setup(spi);
+	if (status < 0) {
+		dev_err(dev, "can't %s %s, status %d\n",
+				"setup", spi->dev.bus_id, status);
+		return status;
+	}
+
+	/* driver core catches callers that misbehave by defining
+	 * devices that already exist.
+	 */
+	status = device_add(&spi->dev);
+	if (status < 0) {
+		dev_err(dev, "can't %s %s, status %d\n",
+				"add", spi->dev.bus_id, status);
+		return status;
+	}
+
+	dev_dbg(dev, "registered child %s\n", spi->dev.bus_id);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(spi_add_device);
 
 /**
  * spi_new_device - instantiate one new SPI device
@@ -197,7 +287,6 @@ struct spi_device *spi_new_device(struct spi_master *master,
 				  struct spi_board_info *chip)
 {
 	struct spi_device	*proxy;
-	struct device		*dev = master->dev.parent;
 	int			status;
 
 	/* NOTE:  caller did any chip->bus_num checks necessary.
@@ -207,66 +296,28 @@ struct spi_device *spi_new_device(struct spi_master *master,
 	 * suggests syslogged diagnostics are best here (ugh).
 	 */
 
-	/* Chipselects are numbered 0..max; validate. */
-	if (chip->chip_select >= master->num_chipselect) {
-		dev_err(dev, "cs%d > max %d\n",
-			chip->chip_select,
-			master->num_chipselect);
-		return NULL;
-	}
-
-	if (!spi_master_get(master))
+	proxy = spi_alloc_device(master);
+	if (!proxy)
 		return NULL;
 
 	WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
 
-	proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
-	if (!proxy) {
-		dev_err(dev, "can't alloc dev for cs%d\n",
-			chip->chip_select);
-		goto fail;
-	}
-	proxy->master = master;
 	proxy->chip_select = chip->chip_select;
 	proxy->max_speed_hz = chip->max_speed_hz;
 	proxy->mode = chip->mode;
 	proxy->irq = chip->irq;
 	strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
-
-	snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
-			"%s.%u", master->dev.bus_id,
-			chip->chip_select);
-	proxy->dev.parent = dev;
-	proxy->dev.bus = &spi_bus_type;
 	proxy->dev.platform_data = (void *) chip->platform_data;
 	proxy->controller_data = chip->controller_data;
 	proxy->controller_state = NULL;
-	proxy->dev.release = spidev_release;
 
-	/* drivers may modify this initial i/o setup */
-	status = master->setup(proxy);
+	status = spi_add_device(proxy);
 	if (status < 0) {
-		dev_err(dev, "can't %s %s, status %d\n",
-				"setup", proxy->dev.bus_id, status);
-		goto fail;
+		spi_dev_put(proxy);
+		return NULL;
 	}
 
-	/* driver core catches callers that misbehave by defining
-	 * devices that already exist.
-	 */
-	status = device_register(&proxy->dev);
-	if (status < 0) {
-		dev_err(dev, "can't %s %s, status %d\n",
-				"add", proxy->dev.bus_id, status);
-		goto fail;
-	}
-	dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id);
 	return proxy;
-
-fail:
-	spi_master_put(master);
-	kfree(proxy);
-	return NULL;
 }
 EXPORT_SYMBOL_GPL(spi_new_device);
 
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index b55910b..d45967e 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -778,8 +778,18 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
  * use spi_new_device() to describe each device.  You can also call
  * spi_unregister_device() to start making that device vanish, but
  * normally that would be handled by spi_unregister_master().
+ *
+ * You can also use spi_alloc_device() and spi_add_device() to
+ * for a two stage registration of an SPI device.  This gives the caller
+ * some more control over the spi_device structure before it is registered
  */
 extern struct spi_device *
+spi_alloc_device(struct spi_master *master);
+
+extern int
+spi_add_device(struct spi_device *spi);
+
+extern struct spi_device *
 spi_new_device(struct spi_master *, struct spi_board_info *);
 
 static inline void


-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* [PATCH v2 3/5] of-bindings: Add binding documentation for SPI busses and devices
       [not found] ` <20080703005749.26187.71719.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
  2008-07-03  1:02   ` [PATCH v2 1/5] spi: Change modalias from a pointer to a character array Grant Likely
  2008-07-03  1:03   ` [PATCH v2 2/5] spi: split up spi_new_device() to allow two stage registration Grant Likely
@ 2008-07-03  1:03   ` Grant Likely
       [not found]     ` <20080703010308.26187.23037.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
  2008-07-03  1:03   ` [PATCH v2 4/5] spi: Add OF binding support for SPI busses Grant Likely
  2008-07-03  1:03   ` [PATCH v2 5/5] powerpc/mpc5200: Add mpc5200-spi (non-PSC) device driver Grant Likely
  4 siblings, 1 reply; 14+ messages in thread
From: Grant Likely @ 2008-07-03  1:03 UTC (permalink / raw)
  To: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	jonsmirl-Re5JQEeQqe8AvxtiuMwx3w

From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>

Add documentation about how to describe SPI busses in the device tree.

Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---

 Documentation/powerpc/booting-without-of.txt |   60 ++++++++++++++++++++++++++
 1 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 1d2a772..7d3564f 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -58,6 +58,7 @@ Table of Contents
       o) Xilinx IP cores
       p) Freescale Synchronous Serial Interface
 	  q) USB EHCI controllers
+      t) SPI busses
 
   VII - Marvell Discovery mv64[345]6x System Controller chips
     1) The /system-controller node
@@ -2870,6 +2871,65 @@ platforms are moved over to use the flattened-device-tree model.
 		reg = <0xe8000000 32>;
 	};
 
+    t) SPI (Serial Peripheral Interface) busses
+
+    SPI busses can be described with a node for the SPI master device
+    and a set of child nodes for each SPI slave on the bus.  For this
+    discussion, it is assumed that the system's SPI controller is in
+    SPI master mode.  This binding does not describe SPI controllers
+    in slave mode.
+
+    The SPI master node requires the following properties:
+    - #address-cells  - number of cells required to define a chip select
+			address on the SPI bus.
+    - #size-cells     - should be zero.
+    - compatible      - name of SPI bus controller following generic names
+			recommended practice.
+    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
+    assigning chip select numbers.  Since SPI chip select configuration is
+    flexible and non-standardized, it is left out of this binding with the
+    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.
+
+    SPI slave nodes must be children of the SPI master node and can
+    contain the following properties.
+    - reg             - (required) chip select address of device.
+    - compatible      - (required) name of SPI device following generic names
+			recommended practice
+    - max-speed       - (required) Maximum SPI clocking speed of device in Hz
+    - spi,cpol        - (optional) Device requires inverse clock polarity
+    - spi,cpha        - (optional) Device requires shifted clock phase
+    - linux,modalias  - (optional, Linux specific) Force binding of SPI device
+			to a particular spi_device driver.  Useful for changing
+			driver binding between spidev and a kernel SPI driver.
+
+    SPI example for an MPC5200 SPI bus:
+		spi@f00 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+			reg = <0xf00 0x20>;
+			interrupts = <2 13 0 2 14 0>;
+			interrupt-parent = <&mpc5200_pic>;
+
+			ethernet-switch@0 {
+				compatible = "micrel,ks8995m";
+				linux,modalias = "ks8995";
+				max-speed = <1000000>;
+				reg = <0>;
+			};
+
+			codec@1 {
+				compatible = "ti,tlv320aic26";
+				max-speed = <100000>;
+				reg = <1>;
+			};
+		};
+
+
 VII - Marvell Discovery mv64[345]6x System Controller chips
 ===========================================================
 


-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* [PATCH v2 4/5] spi: Add OF binding support for SPI busses
       [not found] ` <20080703005749.26187.71719.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
                     ` (2 preceding siblings ...)
  2008-07-03  1:03   ` [PATCH v2 3/5] of-bindings: Add binding documentation for SPI busses and devices Grant Likely
@ 2008-07-03  1:03   ` Grant Likely
       [not found]     ` <20080703010313.26187.99119.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
  2008-07-03  1:03   ` [PATCH v2 5/5] powerpc/mpc5200: Add mpc5200-spi (non-PSC) device driver Grant Likely
  4 siblings, 1 reply; 14+ messages in thread
From: Grant Likely @ 2008-07-03  1:03 UTC (permalink / raw)
  To: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	jonsmirl-Re5JQEeQqe8AvxtiuMwx3w

From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>

This patch adds support for populating an SPI bus based on data in the
OF device tree.  This is useful for powerpc platforms which use the
device tree instead of discrete code for describing platform layout.

Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---

 drivers/of/Kconfig     |    6 +++
 drivers/of/Makefile    |    1 +
 drivers/of/of_spi.c    |   88 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_spi.h |   18 ++++++++++
 4 files changed, 113 insertions(+), 0 deletions(-)

diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 3a7a11a..edd6e92 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -13,3 +13,9 @@ config OF_I2C
 	depends on PPC_OF && I2C
 	help
 	  OpenFirmware I2C accessors
+
+config OF_SPI
+	def_tristate SPI
+	depends on OF && PPC_OF && SPI
+	help
+	  OpenFirmware SPI accessors
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 548772e..4c3c6f8 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -2,3 +2,4 @@ obj-y = base.o
 obj-$(CONFIG_OF_DEVICE) += device.o platform.o
 obj-$(CONFIG_OF_GPIO)   += gpio.o
 obj-$(CONFIG_OF_I2C)	+= of_i2c.o
+obj-$(CONFIG_OF_SPI)	+= of_spi.o
diff --git a/drivers/of/of_spi.c b/drivers/of/of_spi.c
new file mode 100644
index 0000000..ed0c807
--- /dev/null
+++ b/drivers/of/of_spi.c
@@ -0,0 +1,88 @@
+/*
+ * SPI OF support routines
+ * Copyright (C) 2008 Secret Lab Technologies Ltd.
+ *
+ * Support routines for deriving SPI device attachments from the device
+ * tree.
+ */
+
+#include <linux/of.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/of_spi.h>
+
+/**
+ * of_register_spi_devices - Register child devices onto the SPI bus
+ * @master:	Pointer to spi_master device
+ * @np:		parent node of SPI device nodes
+ *
+ * Registers an spi_device for each child node of 'np' which has a 'reg'
+ * property.
+ */
+void of_register_spi_devices(struct spi_master *master, struct device_node *np)
+{
+	struct spi_device *spi;
+	struct device_node *nc;
+	const u32 *prop;
+	const char *sprop;
+	int rc;
+	int len;
+
+	for_each_child_of_node(np, nc) {
+		/* Alloc an spi_device */
+		spi = spi_alloc_device(master);
+		if (!spi) {
+			dev_err(&master->dev, "spi_device alloc error for %s\n",
+				nc->full_name);
+			continue;
+		}
+
+		/* Device address */
+		prop = of_get_property(nc, "reg", &len);
+		if (!prop || len < sizeof(*prop)) {
+			dev_err(&master->dev, "%s has no 'reg' property\n",
+				nc->full_name);
+			continue;
+		}
+		spi->chip_select = *prop;
+
+		/* Mode (clock phase/polarity/etc.) */
+		if (of_find_property(nc, "spi,cpha", NULL))
+			spi->mode |= SPI_CPHA;
+		if (of_find_property(nc, "spi,cpol", NULL))
+			spi->mode |= SPI_CPOL;
+
+		/* Device speed */
+		prop = of_get_property(nc, "max-speed", &len);
+		if (!prop || len < sizeof(*prop)) {
+			dev_err(&master->dev, "%s has no 'max-speed' property\n",
+				nc->full_name);
+			continue;
+		}
+		spi->max_speed_hz = *prop;
+
+		/* IRQ */
+		spi->irq = irq_of_parse_and_map(nc, 0);
+
+		/* Select device driver */
+		sprop = of_get_property(nc, "linux,modalias", &len);
+		if (sprop && len > 0)
+			strncpy(spi->modalias, sprop, KOBJ_NAME_LEN);
+		else
+			strncpy(spi->modalias, "spidev", KOBJ_NAME_LEN);
+
+		/* Store a pointer to the node in the device structure */
+		of_node_get(nc);
+		spi->dev.archdata.of_node = nc;
+
+		/* Register the new device */
+		rc = spi_add_device(spi);
+		if (rc) {
+			dev_err(&master->dev, "spi_device register error %s\n",
+				nc->full_name);
+			spi_dev_put(spi);
+		}
+
+	}
+}
+EXPORT_SYMBOL(of_register_spi_devices);
diff --git a/include/linux/of_spi.h b/include/linux/of_spi.h
new file mode 100644
index 0000000..5f71ee8
--- /dev/null
+++ b/include/linux/of_spi.h
@@ -0,0 +1,18 @@
+/*
+ * OpenFirmware SPI support routines
+ * Copyright (C) 2008 Secret Lab Technologies Ltd.
+ *
+ * Support routines for deriving SPI device attachments from the device
+ * tree.
+ */
+
+#ifndef __LINUX_OF_SPI_H
+#define __LINUX_OF_SPI_H
+
+#include <linux/of.h>
+#include <linux/spi/spi.h>
+
+extern void of_register_spi_devices(struct spi_master *master,
+				    struct device_node *np);
+
+#endif /* __LINUX_OF_SPI */


-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* [PATCH v2 5/5] powerpc/mpc5200: Add mpc5200-spi (non-PSC) device driver
       [not found] ` <20080703005749.26187.71719.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
                     ` (3 preceding siblings ...)
  2008-07-03  1:03   ` [PATCH v2 4/5] spi: Add OF binding support for SPI busses Grant Likely
@ 2008-07-03  1:03   ` Grant Likely
  4 siblings, 0 replies; 14+ messages in thread
From: Grant Likely @ 2008-07-03  1:03 UTC (permalink / raw)
  To: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	jonsmirl-Re5JQEeQqe8AvxtiuMwx3w

From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>

Adds support for the dedicated SPI device on the Freescale MPC5200(b)
SoC.

Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---

 drivers/spi/Kconfig             |    8 +
 drivers/spi/Makefile            |    1 
 drivers/spi/mpc52xx_spi.c       |  595 +++++++++++++++++++++++++++++++++++++++
 include/linux/spi/mpc52xx_spi.h |   10 +
 4 files changed, 614 insertions(+), 0 deletions(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 66ec5d8..01860ac 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -116,6 +116,14 @@ config SPI_LM70_LLP
 	  which interfaces to an LM70 temperature sensor using
 	  a parallel port.
 
+config SPI_MPC52xx
+	tristate "Freescale MPC52xx SPI (non-PSC) controller support"
+	depends on PPC_MPC52xx && SPI
+	select SPI_MASTER_OF
+	help
+	  This drivers supports the MPC52xx SPI controller in master SPI
+	  mode.
+
 config SPI_MPC52xx_PSC
 	tristate "Freescale MPC52xx PSC SPI controller"
 	depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 7fca043..340b878 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
 obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
+obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
 obj-$(CONFIG_SPI_MPC83xx)		+= spi_mpc83xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx.o
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c
new file mode 100644
index 0000000..453690f
--- /dev/null
+++ b/drivers/spi/mpc52xx_spi.c
@@ -0,0 +1,595 @@
+/*
+ * MPC52xx SPI master driver.
+ * Copyright (C) 2008 Secret Lab Technologies Ltd.
+ *
+ * This is the driver for the MPC5200's dedicated SPI device (not for a
+ * PSC in SPI mode)
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/of_platform.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mpc52xx_spi.h>
+#include <linux/of_spi.h>
+#include <linux/io.h>
+#include <asm/time.h>
+#include <asm/mpc52xx.h>
+
+MODULE_AUTHOR("Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>");
+MODULE_DESCRIPTION("MPC52xx SPI (non-PSC) Driver");
+MODULE_LICENSE("GPL");
+
+/* Register offsets */
+#define SPI_CTRL1	0x00
+#define SPI_CTRL1_SPIE		(1 << 7)
+#define SPI_CTRL1_SPE		(1 << 6)
+#define SPI_CTRL1_MSTR		(1 << 4)
+#define SPI_CTRL1_CPOL		(1 << 3)
+#define SPI_CTRL1_CPHA		(1 << 2)
+#define SPI_CTRL1_SSOE		(1 << 1)
+#define SPI_CTRL1_LSBFE		(1 << 0)
+
+#define SPI_CTRL2	0x01
+#define SPI_BRR		0x04
+
+#define SPI_STATUS	0x05
+#define SPI_STATUS_SPIF		(1 << 7)
+#define SPI_STATUS_WCOL		(1 << 6)
+#define SPI_STATUS_MODF		(1 << 4)
+
+#define SPI_DATA	0x09
+#define SPI_PORTDATA	0x0d
+#define SPI_DATADIR	0x10
+
+/* FSM state return values */
+#define FSM_STOP	0
+#define FSM_POLL	1
+#define FSM_CONTINUE	2
+
+/* Driver internal data */
+struct mpc52xx_spi {
+	struct spi_master *master;
+	u32 sysclk;
+	void __iomem *regs;
+	int irq0;	/* MODF irq */
+	int irq1;	/* SPIF irq */
+	int ipb_freq;
+
+	/* Statistics */
+	int msg_count;
+	int wcol_count;
+	int wcol_ticks;
+	u32 wcol_tx_timestamp;
+	int modf_count;
+	int byte_count;
+
+	/* Hooks for platform modification of behaviour */
+	void (*premessage)(struct spi_message *m, void *context);
+	void *premessage_context;
+
+	struct list_head queue;		/* queue of pending messages */
+	spinlock_t lock;
+	struct work_struct work;
+
+
+	/* Details of current transfer (length, and buffer pointers) */
+	struct spi_message *message;	/* current message */
+	struct spi_transfer *transfer;	/* current transfer */
+	int (*state)(int irq, struct mpc52xx_spi *ms, u8 status, u8 data);
+	int len;
+	int timestamp;
+	u8 *rx_buf;
+	const u8 *tx_buf;
+	int cs_change;
+};
+
+/*
+ * CS control function
+ */
+static void mpc52xx_spi_chipsel(struct mpc52xx_spi *ms, int value)
+{
+	if (value)
+		writeb(0, ms->regs + SPI_PORTDATA); /* Assert SS pin */
+	else
+		writeb(0x08, ms->regs + SPI_PORTDATA); /* Deassert SS pin */
+}
+
+/*
+ * Start a new transfer.  This is called both by the idle state
+ * for the first transfer in a message, and by the wait state when the
+ * previous transfer in a message is complete.
+ */
+static void mpc52xx_spi_start_transfer(struct mpc52xx_spi *ms)
+{
+	ms->rx_buf = ms->transfer->rx_buf;
+	ms->tx_buf = ms->transfer->tx_buf;
+	ms->len = ms->transfer->len;
+
+	/* Activate the chip select */
+	if (ms->cs_change)
+		mpc52xx_spi_chipsel(ms, 1);
+	ms->cs_change = ms->transfer->cs_change;
+
+	/* Write out the first byte */
+	ms->wcol_tx_timestamp = get_tbl();
+	if (ms->tx_buf)
+		writeb(*ms->tx_buf++, ms->regs + SPI_DATA);
+	else
+		writeb(0, ms->regs + SPI_DATA);
+}
+
+/* Forward declaration of state handlers */
+static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms,
+					 u8 status, u8 data);
+static int mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms,
+				     u8 status, u8 data);
+
+/*
+ * IDLE state
+ *
+ * No transfers are in progress; if another transfer is pending then retrieve
+ * it and kick it off.  Otherwise, stop processing the state machine
+ */
+static int
+mpc52xx_spi_fsmstate_idle(int irq, struct mpc52xx_spi *ms, u8 status, u8 data)
+{
+	struct spi_message *m;
+	struct spi_device *spi;
+	int spr, sppr;
+	u8 ctrl1;
+
+	if (status && (irq != NO_IRQ))
+		dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n",
+			status);
+
+	/* Check if there is another transfer waiting */
+	if (list_empty(&ms->queue))
+		return FSM_STOP;
+
+	/* Get the next message */
+	spin_lock(&ms->lock);
+
+	/* Call the pre-message hook with a pointer to the next
+	 * message.  The pre-message hook may enqueue a new message for
+	 * changing the chip select value to the head of the queue */
+	m = list_first_entry(&ms->queue, struct spi_message, queue);
+	if (ms->premessage)
+		ms->premessage(m, ms->premessage_context);
+
+	/* reget the head of the queue (the premessage hook may have enqueued
+	 * something before it.) and drop the spinlock */
+	ms->message = list_first_entry(&ms->queue, struct spi_message, queue);
+	list_del_init(&ms->message->queue);
+	spin_unlock(&ms->lock);
+
+	/* Setup the controller parameters */
+	ctrl1 = SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR;
+	spi = ms->message->spi;
+	if (spi->mode & SPI_CPHA)
+		ctrl1 |= SPI_CTRL1_CPHA;
+	if (spi->mode & SPI_CPOL)
+		ctrl1 |= SPI_CTRL1_CPOL;
+	if (spi->mode & SPI_LSB_FIRST)
+		ctrl1 |= SPI_CTRL1_LSBFE;
+	writeb(ctrl1, ms->regs + SPI_CTRL1);
+
+	/* Setup the controller speed */
+	/* minimum divider is '2'.  Also, add '1' to force rounding up. */
+	sppr = ((ms->ipb_freq / ms->message->spi->max_speed_hz) + 1) >> 1;
+	spr = 0;
+	if (sppr < 1)
+		sppr = 1;
+	while (((sppr - 1) & ~0x7) != 0) {
+		sppr = (sppr + 1) >> 1; /* add '1' to force rounding up */
+		spr++;
+	}
+	sppr--;		/* sppr quantity in register is offset by 1 */
+	if (spr > 7) {
+		/* Don't overrun limits of SPI baudrate register */
+		spr = 7;
+		sppr = 7;
+	}
+	writeb(sppr << 4 | spr, ms->regs + SPI_BRR); /* Set speed */
+
+	ms->cs_change = 1;
+	ms->transfer = container_of(ms->message->transfers.next,
+				    struct spi_transfer, transfer_list);
+
+	mpc52xx_spi_start_transfer(ms);
+	ms->state = mpc52xx_spi_fsmstate_transfer;
+
+#if defined(VERBOSE_DEBUG)
+	dev_info(&ms->master->dev, "msg:%p, max_speed:%i, brr:%.2x\n",
+		 ms->message, ms->message->spi->max_speed_hz,
+		 readb(ms->regs + SPI_BRR));
+#endif
+
+	return FSM_CONTINUE;
+}
+
+/*
+ * TRANSFER state
+ *
+ * In the middle of a transfer.  If the SPI core has completed processing
+ * a byte, then read out the received data and write out the next byte
+ * (unless this transfer is finished; in which case go on to the wait
+ * state)
+ */
+static int mpc52xx_spi_fsmstate_transfer(int irq, struct mpc52xx_spi *ms,
+					 u8 status, u8 data)
+{
+	if (!status)
+		return ms->irq0 == NO_IRQ ? FSM_POLL : FSM_STOP;
+
+	if (status & SPI_STATUS_WCOL) {
+		/* The SPI device is stoopid.  At slower speeds, it may raise
+		 * the SPIF flag before the state machine is actually finished.
+		 * which causes a collision (internal to the state machine
+		 * only).  The manual recommends inserting a delay between
+		 * receving the interrupt and sending the next byte, but
+		 * it can also be worked around simply by retrying the
+		 * transfer which is what we do here. */
+		ms->wcol_count++;
+		ms->wcol_ticks += get_tbl() - ms->wcol_tx_timestamp;
+		ms->wcol_tx_timestamp = get_tbl();
+		data = 0;
+		if (ms->tx_buf)
+			data = *(ms->tx_buf-1);
+		writeb(data, ms->regs + SPI_DATA); /* try again */
+		return FSM_CONTINUE;
+	} else if (status & SPI_STATUS_MODF) {
+		ms->modf_count++;
+		dev_err(&ms->master->dev, "mod fault\n");
+		mpc52xx_spi_chipsel(ms, 0);
+		ms->message->status = -EIO;
+		if (ms->message->complete)
+			ms->message->complete(ms->message->context);
+		ms->state = mpc52xx_spi_fsmstate_idle;
+		return FSM_CONTINUE;
+	}
+
+	/* Read data out of the spi device */
+	ms->byte_count++;
+	if (ms->rx_buf)
+		*ms->rx_buf++ = data;
+
+	/* Is the transfer complete? */
+	ms->len--;
+	if (ms->len == 0) {
+		ms->timestamp = get_tbl();
+		ms->timestamp += ms->transfer->delay_usecs * tb_ticks_per_usec;
+		ms->state = mpc52xx_spi_fsmstate_wait;
+		return FSM_CONTINUE;
+	}
+
+	/* Write out the next byte */
+	ms->wcol_tx_timestamp = get_tbl();
+	if (ms->tx_buf)
+		writeb(*ms->tx_buf++, ms->regs + SPI_DATA);
+	else
+		writeb(0, ms->regs + SPI_DATA);
+
+	return FSM_CONTINUE;
+}
+
+/*
+ * WAIT state
+ *
+ * A transfer has completed; need to wait for the delay period to complete
+ * before starting the next transfer
+ */
+static int
+mpc52xx_spi_fsmstate_wait(int irq, struct mpc52xx_spi *ms, u8 status, u8 data)
+{
+	if (status && irq != NO_IRQ)
+		dev_err(&ms->master->dev, "spurious irq, status=0x%.2x\n",
+			status);
+
+	if (((int)get_tbl()) - ms->timestamp < 0)
+		return FSM_POLL;
+
+	ms->message->actual_length += ms->transfer->len;
+
+	/* Check if there is another transfer in this message.  If there
+	 * aren't then deactivate CS, notify sender, and drop back to idle
+	 * to start the next message. */
+	if (ms->transfer->transfer_list.next == &ms->message->transfers) {
+		ms->msg_count++;
+		mpc52xx_spi_chipsel(ms, 0);
+		ms->message->status = 0;
+		if (ms->message->complete)
+			ms->message->complete(ms->message->context);
+		ms->state = mpc52xx_spi_fsmstate_idle;
+		return FSM_CONTINUE;
+	}
+
+	/* There is another transfer; kick it off */
+
+	if (ms->cs_change)
+		mpc52xx_spi_chipsel(ms, 0);
+
+	ms->transfer = container_of(ms->transfer->transfer_list.next,
+				    struct spi_transfer, transfer_list);
+	mpc52xx_spi_start_transfer(ms);
+	ms->state = mpc52xx_spi_fsmstate_transfer;
+	return FSM_CONTINUE;
+}
+
+/*
+ * IRQ handler
+ */
+static irqreturn_t mpc52xx_spi_irq(int irq, void *_ms)
+{
+	struct mpc52xx_spi *ms = _ms;
+	int rc = FSM_CONTINUE;
+	u8 status, data;
+
+	while (rc == FSM_CONTINUE) {
+		/* Interrupt cleared by read of STATUS followed by
+		 * read of DATA registers*/
+		status = readb(ms->regs + SPI_STATUS);
+		data = readb(ms->regs + SPI_DATA); /* clear status */
+		rc = ms->state(irq, ms, status, data);
+	}
+
+	if (rc == FSM_POLL)
+		schedule_work(&ms->work);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Workqueue method of running the state machine
+ */
+static void mpc52xx_spi_wq(struct work_struct *work)
+{
+	struct mpc52xx_spi *ms = container_of(work, struct mpc52xx_spi, work);
+	mpc52xx_spi_irq(NO_IRQ, ms);
+}
+
+/*
+ * spi_master callbacks
+ */
+
+static int mpc52xx_spi_setup(struct spi_device *spi)
+{
+	return 0;
+}
+
+static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct mpc52xx_spi *ms = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	spin_lock_irqsave(&ms->lock, flags);
+	list_add_tail(&m->queue, &ms->queue);
+	spin_unlock_irqrestore(&ms->lock, flags);
+	schedule_work(&ms->work);
+
+	return 0;
+}
+
+/*
+ * Hook to modify premessage hook
+ */
+void mpc52xx_spi_set_premessage_hook(struct spi_master *master,
+				     void (*hook)(struct spi_message *m,
+						  void *context),
+				     void *hook_context)
+{
+	struct mpc52xx_spi *ms = spi_master_get_devdata(master);
+	ms->premessage = hook;
+	ms->premessage_context = hook_context;
+}
+EXPORT_SYMBOL(mpc52xx_spi_set_premessage_hook);
+
+/*
+ * SysFS files
+ */
+static int
+*mpc52xx_spi_sysfs_get_counter(struct mpc52xx_spi *ms, const char *name)
+{
+	if (strcmp(name, "msg_count") == 0)
+		return &ms->msg_count;
+	if (strcmp(name, "byte_count") == 0)
+		return &ms->byte_count;
+	if (strcmp(name, "wcol_count") == 0)
+		return &ms->wcol_count;
+	if (strcmp(name, "wcol_ticks") == 0)
+		return &ms->wcol_ticks;
+	if (strcmp(name, "modf_count") == 0)
+		return &ms->modf_count;
+	return NULL;
+}
+
+static ssize_t mpc52xx_spi_show_count(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buf)
+{
+	struct spi_master *master = container_of(dev, struct spi_master, dev);
+	struct mpc52xx_spi *ms = spi_master_get_devdata(master);
+	int *counter;
+
+	counter = mpc52xx_spi_sysfs_get_counter(ms, attr->attr.name);
+	if (!counter)
+		return sprintf(buf, "error\n");
+	return sprintf(buf, "%d\n", *counter);
+}
+
+static ssize_t mpc52xx_spi_set_count(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct spi_master *master = container_of(dev, struct spi_master, dev);
+	struct mpc52xx_spi *ms = spi_master_get_devdata(master);
+	int *counter;
+	int value = simple_strtoul(buf, NULL, 0);
+
+	counter = mpc52xx_spi_sysfs_get_counter(ms, attr->attr.name);
+	if (counter)
+		*counter = value;
+	return count;
+}
+
+DEVICE_ATTR(msg_count, 0644, mpc52xx_spi_show_count, mpc52xx_spi_set_count);
+DEVICE_ATTR(byte_count, 0644, mpc52xx_spi_show_count, mpc52xx_spi_set_count);
+DEVICE_ATTR(wcol_count, 0644, mpc52xx_spi_show_count, mpc52xx_spi_set_count);
+DEVICE_ATTR(wcol_ticks, 0644, mpc52xx_spi_show_count, mpc52xx_spi_set_count);
+DEVICE_ATTR(modf_count, 0644, mpc52xx_spi_show_count, mpc52xx_spi_set_count);
+
+/*
+ * OF Platform Bus Binding
+ */
+static int __devinit mpc52xx_spi_of_probe(struct of_device *op,
+					  const struct of_device_id *match)
+{
+	struct spi_master *master;
+	struct mpc52xx_spi *ms;
+	void __iomem *regs;
+	const u32 *prop;
+	int rc, len;
+
+	/* MMIO registers */
+	dev_dbg(&op->dev, "probing mpc5200 SPI device\n");
+	regs = of_iomap(op->node, 0);
+	if (!regs)
+		return -ENODEV;
+
+	/* initialize the device */
+	writeb(SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR, regs+SPI_CTRL1);
+	writeb(0x0, regs + SPI_CTRL2);
+	writeb(0xe, regs + SPI_DATADIR);	/* Set output pins */
+	writeb(0x8, regs + SPI_PORTDATA);	/* Deassert /SS signal */
+
+	/* Clear the status register and re-read it to check for a MODF
+	 * failure.  This driver cannot currently handle multiple masters
+	 * on the SPI bus.  This fault will also occur if the SPI signals
+	 * are not connected to any pins (port_config setting) */
+	readb(regs + SPI_STATUS);
+	readb(regs + SPI_DATA);
+	if (readb(regs + SPI_STATUS) & SPI_STATUS_MODF) {
+		dev_err(&op->dev, "mode fault; is port_config correct?\n");
+		return -EIO;
+	}
+
+	dev_dbg(&op->dev, "allocating spi_master struct\n");
+	master = spi_alloc_master(&op->dev, sizeof *ms);
+	if (!master)
+		return -ENOMEM;
+	master->bus_num = -1;
+	master->num_chipselect = 1;
+	prop = of_get_property(op->node, "num-slaves", &len);
+	if (prop && len >= sizeof(*prop))
+		master->num_chipselect = *prop;
+
+	master->setup = mpc52xx_spi_setup;
+	master->transfer = mpc52xx_spi_transfer;
+	dev_set_drvdata(&op->dev, master);
+
+	ms = spi_master_get_devdata(master);
+	ms->master = master;
+	ms->regs = regs;
+	ms->irq0 = irq_of_parse_and_map(op->node, 0);
+	ms->irq1 = irq_of_parse_and_map(op->node, 1);
+	ms->state = mpc52xx_spi_fsmstate_idle;
+	ms->ipb_freq = mpc52xx_find_ipb_freq(op->node);
+	spin_lock_init(&ms->lock);
+	INIT_LIST_HEAD(&ms->queue);
+	INIT_WORK(&ms->work, mpc52xx_spi_wq);
+
+	dev_dbg(&op->dev, "registering spi_master struct\n");
+	rc = spi_register_master(master);
+	if (rc < 0)
+		goto err_register;
+
+	/* Decide if interrupts can be used */
+	if ((ms->irq0 != NO_IRQ) && (ms->irq1 != NO_IRQ)) {
+		rc = request_irq(ms->irq0, mpc52xx_spi_irq, IRQF_SAMPLE_RANDOM,
+				  "mpc5200-spi-modf", ms);
+		rc |= request_irq(ms->irq1, mpc52xx_spi_irq, IRQF_SAMPLE_RANDOM,
+				  "mpc5200-spi-spiF", ms);
+		if (rc) {
+			free_irq(ms->irq0, ms);
+			free_irq(ms->irq1, ms);
+			ms->irq0 = ms->irq1 = NO_IRQ;
+			dev_info(&op->dev, "using polled mode\n");
+		}
+	} else {
+		/* operate in polled mode */
+		ms->irq0 = ms->irq1 = NO_IRQ;
+		dev_info(&op->dev, "using polled mode\n");
+	}
+
+	/* Create SysFS files */
+	rc = device_create_file(&ms->master->dev, &dev_attr_msg_count);
+	rc |= device_create_file(&ms->master->dev, &dev_attr_byte_count);
+	rc |= device_create_file(&ms->master->dev, &dev_attr_wcol_count);
+	rc |= device_create_file(&ms->master->dev, &dev_attr_wcol_ticks);
+	rc |= device_create_file(&ms->master->dev, &dev_attr_modf_count);
+	if (rc)
+		dev_info(&ms->master->dev, "error creating sysfs files\n");
+
+	dev_info(&ms->master->dev, "registered MPC5200 SPI bus\n");
+
+	of_register_spi_devices(master, op->node);
+
+	return rc;
+
+ err_register:
+	dev_err(&ms->master->dev, "initialization failed\n");
+	spi_master_put(master);
+	return rc;
+}
+
+static void __devexit mpc52xx_spi_of_remove(struct of_device *op)
+{
+	struct spi_master *master = dev_get_drvdata(&op->dev);
+	struct mpc52xx_spi *ms = spi_master_get_devdata(master);
+
+	device_remove_file(&ms->master->dev, &dev_attr_msg_count);
+	device_remove_file(&ms->master->dev, &dev_attr_byte_count);
+	device_remove_file(&ms->master->dev, &dev_attr_wcol_count);
+	device_remove_file(&ms->master->dev, &dev_attr_wcol_ticks);
+	device_remove_file(&ms->master->dev, &dev_attr_modf_count);
+
+	free_irq(ms->irq0, ms);
+	free_irq(ms->irq1, ms);
+
+	spi_unregister_master(master);
+	spi_master_put(master);
+	iounmap(ms->regs);
+}
+
+static struct of_device_id mpc52xx_spi_of_match[] __devinitdata = {
+	{ .compatible = "fsl,mpc5200-spi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
+
+static struct of_platform_driver mpc52xx_spi_of_driver = {
+	.owner = THIS_MODULE,
+	.name = "mpc52xx-spi",
+	.match_table = mpc52xx_spi_of_match,
+	.probe = mpc52xx_spi_of_probe,
+	.remove = __exit_p(mpc52xx_spi_of_remove),
+};
+
+static int __init mpc52xx_spi_init(void)
+{
+	return of_register_platform_driver(&mpc52xx_spi_of_driver);
+}
+module_init(mpc52xx_spi_init);
+
+static void __exit mpc52xx_spi_exit(void)
+{
+	of_unregister_platform_driver(&mpc52xx_spi_of_driver);
+}
+module_exit(mpc52xx_spi_exit);
+
diff --git a/include/linux/spi/mpc52xx_spi.h b/include/linux/spi/mpc52xx_spi.h
new file mode 100644
index 0000000..d1004cf
--- /dev/null
+++ b/include/linux/spi/mpc52xx_spi.h
@@ -0,0 +1,10 @@
+
+#ifndef INCLUDE_MPC5200_SPI_H
+#define INCLUDE_MPC5200_SPI_H
+
+extern void mpc52xx_spi_set_premessage_hook(struct spi_master *master,
+					    void (*hook)(struct spi_message *m,
+							 void *context),
+					    void *hook_context);
+
+#endif


-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* Re: [PATCH v2 4/5] spi: Add OF binding support for SPI busses
       [not found]     ` <20080703010313.26187.99119.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
@ 2008-07-03  3:02       ` Jon Smirl
       [not found]         ` <9e4733910807022002n3c739c7cs8ed642e4a6027bb6-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2008-07-04  3:54       ` Chen Gong
  1 sibling, 1 reply; 14+ messages in thread
From: Jon Smirl @ 2008-07-03  3:02 UTC (permalink / raw)
  To: Grant Likely
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

On 7/2/08, Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
> From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
>
>  This patch adds support for populating an SPI bus based on data in the
>  OF device tree.  This is useful for powerpc platforms which use the
>  device tree instead of discrete code for describing platform layout.
>
>  Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
>  ---
>
>   drivers/of/Kconfig     |    6 +++
>   drivers/of/Makefile    |    1 +
>   drivers/of/of_spi.c    |   88 ++++++++++++++++++++++++++++++++++++++++++++++++
>   include/linux/of_spi.h |   18 ++++++++++
>   4 files changed, 113 insertions(+), 0 deletions(-)
>
>  diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
>  index 3a7a11a..edd6e92 100644
>  --- a/drivers/of/Kconfig
>  +++ b/drivers/of/Kconfig
>  @@ -13,3 +13,9 @@ config OF_I2C
>         depends on PPC_OF && I2C
>         help
>           OpenFirmware I2C accessors
>  +
>  +config OF_SPI
>  +       def_tristate SPI
>  +       depends on OF && PPC_OF && SPI
>  +       help
>  +         OpenFirmware SPI accessors
>  diff --git a/drivers/of/Makefile b/drivers/of/Makefile
>  index 548772e..4c3c6f8 100644
>  --- a/drivers/of/Makefile
>  +++ b/drivers/of/Makefile
>  @@ -2,3 +2,4 @@ obj-y = base.o
>   obj-$(CONFIG_OF_DEVICE) += device.o platform.o
>   obj-$(CONFIG_OF_GPIO)   += gpio.o
>   obj-$(CONFIG_OF_I2C)   += of_i2c.o
>  +obj-$(CONFIG_OF_SPI)   += of_spi.o
>  diff --git a/drivers/of/of_spi.c b/drivers/of/of_spi.c
>  new file mode 100644
>  index 0000000..ed0c807
>  --- /dev/null
>  +++ b/drivers/of/of_spi.c
>  @@ -0,0 +1,88 @@
>  +/*
>  + * SPI OF support routines
>  + * Copyright (C) 2008 Secret Lab Technologies Ltd.
>  + *
>  + * Support routines for deriving SPI device attachments from the device
>  + * tree.
>  + */
>  +
>  +#include <linux/of.h>
>  +#include <linux/device.h>
>  +#include <linux/spi/spi.h>
>  +#include <linux/of_spi.h>
>  +
>  +/**
>  + * of_register_spi_devices - Register child devices onto the SPI bus
>  + * @master:    Pointer to spi_master device
>  + * @np:                parent node of SPI device nodes
>  + *
>  + * Registers an spi_device for each child node of 'np' which has a 'reg'
>  + * property.
>  + */
>  +void of_register_spi_devices(struct spi_master *master, struct device_node *np)
>  +{
>  +       struct spi_device *spi;
>  +       struct device_node *nc;
>  +       const u32 *prop;
>  +       const char *sprop;
>  +       int rc;
>  +       int len;
>  +
>  +       for_each_child_of_node(np, nc) {
>  +               /* Alloc an spi_device */
>  +               spi = spi_alloc_device(master);
>  +               if (!spi) {
>  +                       dev_err(&master->dev, "spi_device alloc error for %s\n",
>  +                               nc->full_name);
>  +                       continue;
>  +               }
>  +
>  +               /* Device address */
>  +               prop = of_get_property(nc, "reg", &len);
>  +               if (!prop || len < sizeof(*prop)) {
>  +                       dev_err(&master->dev, "%s has no 'reg' property\n",
>  +                               nc->full_name);
>  +                       continue;
>  +               }
>  +               spi->chip_select = *prop;
>  +
>  +               /* Mode (clock phase/polarity/etc.) */
>  +               if (of_find_property(nc, "spi,cpha", NULL))
>  +                       spi->mode |= SPI_CPHA;
>  +               if (of_find_property(nc, "spi,cpol", NULL))
>  +                       spi->mode |= SPI_CPOL;
>  +
>  +               /* Device speed */
>  +               prop = of_get_property(nc, "max-speed", &len);
>  +               if (!prop || len < sizeof(*prop)) {
>  +                       dev_err(&master->dev, "%s has no 'max-speed' property\n",
>  +                               nc->full_name);
>  +                       continue;
>  +               }
>  +               spi->max_speed_hz = *prop;
>  +
>  +               /* IRQ */
>  +               spi->irq = irq_of_parse_and_map(nc, 0);
>  +
>  +               /* Select device driver */
>  +               sprop = of_get_property(nc, "linux,modalias", &len);
>  +               if (sprop && len > 0)
>  +                       strncpy(spi->modalias, sprop, KOBJ_NAME_LEN);
>  +               else
>  +                       strncpy(spi->modalias, "spidev", KOBJ_NAME_LEN);

You're missing a request_module("%s", info.type) to make sure the
module is loaded.

It might make sense to share code with of_find_i2c_driver() so we have
a common way of guessing module names.

>  +
>  +               /* Store a pointer to the node in the device structure */
>  +               of_node_get(nc);
>  +               spi->dev.archdata.of_node = nc;
>  +
>  +               /* Register the new device */
>  +               rc = spi_add_device(spi);
>  +               if (rc) {
>  +                       dev_err(&master->dev, "spi_device register error %s\n",
>  +                               nc->full_name);
>  +                       spi_dev_put(spi);
>  +               }
>  +
>  +       }
>  +}
>  +EXPORT_SYMBOL(of_register_spi_devices);
>  diff --git a/include/linux/of_spi.h b/include/linux/of_spi.h
>  new file mode 100644
>  index 0000000..5f71ee8
>  --- /dev/null
>  +++ b/include/linux/of_spi.h
>  @@ -0,0 +1,18 @@
>  +/*
>  + * OpenFirmware SPI support routines
>  + * Copyright (C) 2008 Secret Lab Technologies Ltd.
>  + *
>  + * Support routines for deriving SPI device attachments from the device
>  + * tree.
>  + */
>  +
>  +#ifndef __LINUX_OF_SPI_H
>  +#define __LINUX_OF_SPI_H
>  +
>  +#include <linux/of.h>
>  +#include <linux/spi/spi.h>
>  +
>  +extern void of_register_spi_devices(struct spi_master *master,
>  +                                   struct device_node *np);
>  +
>  +#endif /* __LINUX_OF_SPI */
>
>


-- 
Jon Smirl
jonsmirl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* Re: [PATCH v2 4/5] spi: Add OF binding support for SPI busses
       [not found]     ` <20080703010313.26187.99119.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
  2008-07-03  3:02       ` Jon Smirl
@ 2008-07-04  3:54       ` Chen Gong
       [not found]         ` <58A20A281BAF1047B4EAE68DE5C0BDC2010121B7-bKEhWGtIRULiD3AT8lUqWFjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
  1 sibling, 1 reply; 14+ messages in thread
From: Chen Gong @ 2008-07-04  3:54 UTC (permalink / raw)
  To: Grant Likely
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

 

> -----Original Message-----
> From: linuxppc-dev-bounces+b11801=freescale.com-mnsaURCQ41sdnm+yROfE0A@public.gmane.org 
> [mailto:linuxppc-dev-bounces+b11801=freescale.com-mnsaURCQ41sdnm+yROfE0A@public.gmane.org] 
> On Behalf Of Grant Likely
> Sent: 2008?7?3? 9:03
> To: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A@public.gmane.org; 
> spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org; fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
> Subject: [PATCH v2 4/5] spi: Add OF binding support for SPI busses
> 
> From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> 
> This patch adds support for populating an SPI bus based on data in the
> OF device tree.  This is useful for powerpc platforms which use the
> device tree instead of discrete code for describing platform layout.
> 
> Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> ---
> 
>  drivers/of/Kconfig     |    6 +++
>  drivers/of/Makefile    |    1 +
>  drivers/of/of_spi.c    |   88 
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of_spi.h |   18 ++++++++++
>  4 files changed, 113 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
> index 3a7a11a..edd6e92 100644
> --- a/drivers/of/Kconfig
> +++ b/drivers/of/Kconfig
> @@ -13,3 +13,9 @@ config OF_I2C
>  	depends on PPC_OF && I2C
>  	help
>  	  OpenFirmware I2C accessors
> +
> +config OF_SPI
> +	def_tristate SPI
> +	depends on OF && PPC_OF && SPI
> +	help
> +	  OpenFirmware SPI accessors
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index 548772e..4c3c6f8 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -2,3 +2,4 @@ obj-y = base.o
>  obj-$(CONFIG_OF_DEVICE) += device.o platform.o
>  obj-$(CONFIG_OF_GPIO)   += gpio.o
>  obj-$(CONFIG_OF_I2C)	+= of_i2c.o
> +obj-$(CONFIG_OF_SPI)	+= of_spi.o
> diff --git a/drivers/of/of_spi.c b/drivers/of/of_spi.c
> new file mode 100644
> index 0000000..ed0c807
> --- /dev/null
> +++ b/drivers/of/of_spi.c
> @@ -0,0 +1,88 @@
> +/*
> + * SPI OF support routines
> + * Copyright (C) 2008 Secret Lab Technologies Ltd.
> + *
> + * Support routines for deriving SPI device attachments from 
> the device
> + * tree.
> + */
> +
> +#include <linux/of.h>
> +#include <linux/device.h>
> +#include <linux/spi/spi.h>
> +#include <linux/of_spi.h>
> +
> +/**
> + * of_register_spi_devices - Register child devices onto the SPI bus
> + * @master:	Pointer to spi_master device
> + * @np:		parent node of SPI device nodes
> + *
> + * Registers an spi_device for each child node of 'np' which 
> has a 'reg'
> + * property.
> + */
> +void of_register_spi_devices(struct spi_master *master, 
> struct device_node *np)
> +{
> +	struct spi_device *spi;
> +	struct device_node *nc;
> +	const u32 *prop;
> +	const char *sprop;
> +	int rc;
> +	int len;
> +
> +	for_each_child_of_node(np, nc) {
> +		/* Alloc an spi_device */
> +		spi = spi_alloc_device(master);
> +		if (!spi) {
> +			dev_err(&master->dev, "spi_device alloc 
> error for %s\n",
> +				nc->full_name);
> +			continue;
> +		}
> +
> +		/* Device address */
> +		prop = of_get_property(nc, "reg", &len);
> +		if (!prop || len < sizeof(*prop)) {
> +			dev_err(&master->dev, "%s has no 'reg' 
> property\n",
> +				nc->full_name);
> +			continue;
> +		}
> +		spi->chip_select = *prop;
> +
> +		/* Mode (clock phase/polarity/etc.) */
> +		if (of_find_property(nc, "spi,cpha", NULL))
> +			spi->mode |= SPI_CPHA;
> +		if (of_find_property(nc, "spi,cpol", NULL))
> +			spi->mode |= SPI_CPOL;

so becuase in function spi_alloc_deive, spi is allocated by kzalloc,
how about writing as follows:
		/* Mode (clock phase/polarity/etc.) */
		prop = of_get_property(nc, "spi,cpha", NULL))
                        if (prop)
			spi->mode |= *prop;
		prop = of_get_property(nc, "spi,cpol", NULL))
                        if (prop)
			spi->mode |= *prop;

> +
> +		/* Device speed */
> +		prop = of_get_property(nc, "max-speed", &len);
> +		if (!prop || len < sizeof(*prop)) {
> +			dev_err(&master->dev, "%s has no 
> 'max-speed' property\n",
> +				nc->full_name);
> +			continue;
> +		}
> +		spi->max_speed_hz = *prop;
> +
> +		/* IRQ */
> +		spi->irq = irq_of_parse_and_map(nc, 0);
> +
> +		/* Select device driver */
> +		sprop = of_get_property(nc, "linux,modalias", &len);
> +		if (sprop && len > 0)
> +			strncpy(spi->modalias, sprop, KOBJ_NAME_LEN);
> +		else
> +			strncpy(spi->modalias, "spidev", KOBJ_NAME_LEN);
> +
 how about writing as follows:

		if (sprop && len > 0)
			strncpy(spi->modalias, sprop, KOBJ_NAME_LEN -
1);
		else
			strncpy(spi->modalias, "spidev", KOBJ_NAME_LEN -
1);

-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* Re: [PATCH v2 3/5] of-bindings: Add binding documentation for SPI bussesand devices
       [not found]     ` <20080703010308.26187.23037.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
@ 2008-07-04  3:59       ` Chen Gong
       [not found]         ` <58A20A281BAF1047B4EAE68DE5C0BDC2010121B9-bKEhWGtIRULiD3AT8lUqWFjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
  2008-07-04 23:36       ` [PATCH v2 3/5] of-bindings: Add binding documentation for SPI busses and devices Segher Boessenkool
  1 sibling, 1 reply; 14+ messages in thread
From: Chen Gong @ 2008-07-04  3:59 UTC (permalink / raw)
  To: Grant Likely, linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: david-b-yBeKhBN/0LDR7s880joybQ, fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w

 

> -----Original Message-----
> From: linuxppc-dev-bounces+b11801=freescale.com-mnsaURCQ41sdnm+yROfE0A@public.gmane.org 
> [mailto:linuxppc-dev-bounces+b11801=freescale.com-mnsaURCQ41sdnm+yROfE0A@public.gmane.org] 
> On Behalf Of Grant Likely
> Sent: 2008?7?3? 9:03
> To: linuxppc-dev-mnsaURCQ41sdnm+yROfE0A@public.gmane.org; 
> spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org; fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
> Subject: [PATCH v2 3/5] of-bindings: Add binding 
> documentation for SPI bussesand devices
> 
> From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> 
> Add documentation about how to describe SPI busses in the device tree.
> 
> Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> ---
> 
>  Documentation/powerpc/booting-without-of.txt |   60 
> ++++++++++++++++++++++++++
>  1 files changed, 60 insertions(+), 0 deletions(-)
> 
> diff --git a/Documentation/powerpc/booting-without-of.txt 
> b/Documentation/powerpc/booting-without-of.txt
> index 1d2a772..7d3564f 100644
> --- a/Documentation/powerpc/booting-without-of.txt
> +++ b/Documentation/powerpc/booting-without-of.txt
> @@ -58,6 +58,7 @@ Table of Contents
>        o) Xilinx IP cores
>        p) Freescale Synchronous Serial Interface
>  	  q) USB EHCI controllers
> +      t) SPI busses
>  
>    VII - Marvell Discovery mv64[345]6x System Controller chips
>      1) The /system-controller node
> @@ -2870,6 +2871,65 @@ platforms are moved over to use the 
> flattened-device-tree model.
>  		reg = <0xe8000000 32>;
>  	};
>  
> +    t) SPI (Serial Peripheral Interface) busses
> +
> +    SPI busses can be described with a node for the SPI master device
> +    and a set of child nodes for each SPI slave on the bus.  For this
> +    discussion, it is assumed that the system's SPI controller is in
> +    SPI master mode.  This binding does not describe SPI controllers
> +    in slave mode.
> +
> +    The SPI master node requires the following properties:
> +    - #address-cells  - number of cells required to define a 
> chip select
> +			address on the SPI bus.
> +    - #size-cells     - should be zero.
> +    - compatible      - name of SPI bus controller following 
> generic names
> +			recommended practice.
> +    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
> +    assigning chip select numbers.  Since SPI chip select 
> configuration is
> +    flexible and non-standardized, it is left out of this 
> binding with the
> +    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.
> +
> +    SPI slave nodes must be children of the SPI master node and can
> +    contain the following properties.
> +    - reg             - (required) chip select address of device.
> +    - compatible      - (required) name of SPI device 
> following generic names
> +			recommended practice
> +    - max-speed       - (required) Maximum SPI clocking 
> speed of device in Hz
> +    - spi,cpol        - (optional) Device requires inverse 
> clock polarity
> +    - spi,cpha        - (optional) Device requires shifted 
> clock phase
> +    - linux,modalias  - (optional, Linux specific) Force 
> binding of SPI device
> +			to a particular spi_device driver.  
> Useful for changing
> +			driver binding between spidev and a 
> kernel SPI driver.
> +

How about adding a "model" property to describe actual devie type.
Such as using a "sst25vf040b" device with spi-interface, we can
use model="sst25vf040b" to describe it.

-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* Re: [PATCH v2 3/5] of-bindings: Add binding documentation for SPI bussesand devices
       [not found]         ` <58A20A281BAF1047B4EAE68DE5C0BDC2010121B9-bKEhWGtIRULiD3AT8lUqWFjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
@ 2008-07-04  4:05           ` Grant Likely
  0 siblings, 0 replies; 14+ messages in thread
From: Grant Likely @ 2008-07-04  4:05 UTC (permalink / raw)
  To: Chen Gong
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

On Fri, Jul 04, 2008 at 11:59:07AM +0800, Chen Gong wrote:
> > +    - reg             - (required) chip select address of device.
> > +    - compatible      - (required) name of SPI device 
> > following generic names
> > +			recommended practice
> > +    - max-speed       - (required) Maximum SPI clocking 
> > speed of device in Hz
> > +    - spi,cpol        - (optional) Device requires inverse 
> > clock polarity
> > +    - spi,cpha        - (optional) Device requires shifted 
> > clock phase
> > +    - linux,modalias  - (optional, Linux specific) Force 
> > binding of SPI device
> > +			to a particular spi_device driver.  
> > Useful for changing
> > +			driver binding between spidev and a 
> > kernel SPI driver.
> > +
> 
> How about adding a "model" property to describe actual devie type.
> Such as using a "sst25vf040b" device with spi-interface, we can
> use model="sst25vf040b" to describe it.

That's what "compatible" is for.  First value in the compatible list is
the actual device, followed by devices it is compatible with.  In
your particular example, the value would be "sst,sst25vf040b" so that it
follows device tree conventions.

g.

-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* Re: [PATCH v2 4/5] spi: Add OF binding support for SPI busses
       [not found]         ` <58A20A281BAF1047B4EAE68DE5C0BDC2010121B7-bKEhWGtIRULiD3AT8lUqWFjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
@ 2008-07-04  4:17           ` Grant Likely
  0 siblings, 0 replies; 14+ messages in thread
From: Grant Likely @ 2008-07-04  4:17 UTC (permalink / raw)
  To: Chen Gong
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

On Fri, Jul 04, 2008 at 11:54:57AM +0800, Chen Gong wrote:
> Grant Likely wrote:
> > +		/* Mode (clock phase/polarity/etc.) */
> > +		if (of_find_property(nc, "spi,cpha", NULL))
> > +			spi->mode |= SPI_CPHA;
> > +		if (of_find_property(nc, "spi,cpol", NULL))
> > +			spi->mode |= SPI_CPOL;
> 
> so becuase in function spi_alloc_deive, spi is allocated by kzalloc,
> how about writing as follows:
> 		/* Mode (clock phase/polarity/etc.) */
> 		prop = of_get_property(nc, "spi,cpha", NULL))
>                         if (prop)
> 			spi->mode |= *prop;
> 		prop = of_get_property(nc, "spi,cpol", NULL))
>                         if (prop)
> 			spi->mode |= *prop;

spi,cpha and spi,cpol are defined as empty properties.  The presence of
the property in the node means I need to set the flag in the spi_device.

> > +		/* Select device driver */
> > +		sprop = of_get_property(nc, "linux,modalias", &len);
> > +		if (sprop && len > 0)
> > +			strncpy(spi->modalias, sprop, KOBJ_NAME_LEN);
> > +		else
> > +			strncpy(spi->modalias, "spidev", KOBJ_NAME_LEN);
> > +
>  how about writing as follows:
> 
> 		if (sprop && len > 0)
> 			strncpy(spi->modalias, sprop, KOBJ_NAME_LEN -
> 1);
> 		else
> 			strncpy(spi->modalias, "spidev", KOBJ_NAME_LEN -
> 1);

Actually, neither are very good.  What it should really be is:

	if (sprop && len > 0)
		strlcpy(spi->modalias, sprop, sizeof (spi->modalias));
	else
		strlcpy(spi->modalias, "spidev", sizeof (spi->modalias));

This ensures that the string is always null terminated and always the
right size.

... But the whole argument is a bit moot.  The fact that I even defined
a "linux,modalias" property is a great big hairy hack that I would
never want my mother to see.  Instead, I need a method to bind to an SPI
driver based on the compatible list.  Jon Smirl has done some work
in this regard for i2c, but I haven't looked at it very deeply, and so
do not at all understand it (yet).

Thanks for the comments.
g.

-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* Re: [PATCH v2 3/5] of-bindings: Add binding documentation for SPI busses and devices
       [not found]     ` <20080703010308.26187.23037.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
  2008-07-04  3:59       ` [PATCH v2 3/5] of-bindings: Add binding documentation for SPI bussesand devices Chen Gong
@ 2008-07-04 23:36       ` Segher Boessenkool
       [not found]         ` <1694b01b1b41f244e565298b430f021c-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
  1 sibling, 1 reply; 14+ messages in thread
From: Segher Boessenkool @ 2008-07-04 23:36 UTC (permalink / raw)
  To: Grant Likely
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxppc-dev-mnsaURCQ41sdnm+yROfE0A

> +    The SPI master node requires the following properties:
> +    - #address-cells  - number of cells required to define a chip 
> select
> +			address on the SPI bus.

Hrm.  Should this (and "reg" in the child node) be required for SPI
masters that have only one chip select?

> +    - max-speed       - (required) Maximum SPI clocking speed of 
> device in Hz

The property name should include something "SPI", it's way too generic
otherwise.

> +    - spi,cpol        - (optional) Device requires inverse clock 
> polarity
> +    - spi,cpha        - (optional) Device requires shifted clock phase

Don't abbr the property names, there's nothing wrong with longer names.
The names shouldn't start with "spi," either, "spi" isn't a vendor;
how about "spi-inverse-clock-polarity" or similar?

> +    - linux,modalias  - (optional, Linux specific) Force binding of 
> SPI device
> +			to a particular spi_device driver.  Useful for changing
> +			driver binding between spidev and a kernel SPI driver.

This is a temporary workaround I hope?


Segher


-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* Re: [PATCH v2 3/5] of-bindings: Add binding documentation for SPI busses and devices
       [not found]         ` <1694b01b1b41f244e565298b430f021c-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
@ 2008-07-04 23:42           ` Grant Likely
  0 siblings, 0 replies; 14+ messages in thread
From: Grant Likely @ 2008-07-04 23:42 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linuxppc-dev-mnsaURCQ41sdnm+yROfE0A

On Fri, Jul 4, 2008 at 5:36 PM, Segher Boessenkool
<segher-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org> wrote:
>> +    The SPI master node requires the following properties:
>> +    - #address-cells  - number of cells required to define a chip select
>> +                       address on the SPI bus.
>
> Hrm.  Should this (and "reg" in the child node) be required for SPI
> masters that have only one chip select?

I suppose it could be skipped, but I'd rather have it there for consistency

>
>> +    - max-speed       - (required) Maximum SPI clocking speed of device
>> in Hz
>
> The property name should include something "SPI", it's way too generic
> otherwise.

Good point; I'll change this to 'spi-max-speed'

>> +    - spi,cpol        - (optional) Device requires inverse clock polarity
>> +    - spi,cpha        - (optional) Device requires shifted clock phase
>
> Don't abbr the property names, there's nothing wrong with longer names.
> The names shouldn't start with "spi," either, "spi" isn't a vendor;
> how about "spi-inverse-clock-polarity" or similar?

Okay, but cpol and cpha are common abbreviations w.r.t. SPI devices.

>> +    - linux,modalias  - (optional, Linux specific) Force binding of SPI
>> device
>> +                       to a particular spi_device driver.  Useful for
>> changing
>> +                       driver binding between spidev and a kernel SPI
>> driver.
>
> This is a temporary workaround I hope?

Yeah, I'm kind of ashamed of this one.  I'll drop it.

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

* Re: [PATCH v2 4/5] spi: Add OF binding support for SPI busses
       [not found]         ` <9e4733910807022002n3c739c7cs8ed642e4a6027bb6-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2008-07-12  5:21           ` Grant Likely
  0 siblings, 0 replies; 14+ messages in thread
From: Grant Likely @ 2008-07-12  5:21 UTC (permalink / raw)
  To: Jon Smirl
  Cc: david-b-yBeKhBN/0LDR7s880joybQ,
	linuxppc-dev-mnsaURCQ41sdnm+yROfE0A,
	fabrizio.garetto-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

On Wed, Jul 02, 2008 at 11:02:23PM -0400, Jon Smirl wrote:
> On 7/2/08, Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
> > From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> >
> >  This patch adds support for populating an SPI bus based on data in the
> >  OF device tree.  This is useful for powerpc platforms which use the
> >  device tree instead of discrete code for describing platform layout.
> >
> >  Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> >  ---
> >  +               /* Select device driver */
> >  +               sprop = of_get_property(nc, "linux,modalias", &len);
> >  +               if (sprop && len > 0)
> >  +                       strncpy(spi->modalias, sprop, KOBJ_NAME_LEN);
> >  +               else
> >  +                       strncpy(spi->modalias, "spidev", KOBJ_NAME_LEN);
> 
> You're missing a request_module("%s", info.type) to make sure the
> module is loaded.
> 
> It might make sense to share code with of_find_i2c_driver() so we have
> a common way of guessing module names.

You're right.  I've refactored the i2c code to make it usable by SPI
also.  I'll post the new patch series this evening.

g.

-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08

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

end of thread, other threads:[~2008-07-12  5:21 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-07-03  1:02 [PATCH v2 0/5] SPI OF bindings and mpc5200-spi driver Grant Likely
     [not found] ` <20080703005749.26187.71719.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
2008-07-03  1:02   ` [PATCH v2 1/5] spi: Change modalias from a pointer to a character array Grant Likely
2008-07-03  1:03   ` [PATCH v2 2/5] spi: split up spi_new_device() to allow two stage registration Grant Likely
2008-07-03  1:03   ` [PATCH v2 3/5] of-bindings: Add binding documentation for SPI busses and devices Grant Likely
     [not found]     ` <20080703010308.26187.23037.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
2008-07-04  3:59       ` [PATCH v2 3/5] of-bindings: Add binding documentation for SPI bussesand devices Chen Gong
     [not found]         ` <58A20A281BAF1047B4EAE68DE5C0BDC2010121B9-bKEhWGtIRULiD3AT8lUqWFjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
2008-07-04  4:05           ` Grant Likely
2008-07-04 23:36       ` [PATCH v2 3/5] of-bindings: Add binding documentation for SPI busses and devices Segher Boessenkool
     [not found]         ` <1694b01b1b41f244e565298b430f021c-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
2008-07-04 23:42           ` Grant Likely
2008-07-03  1:03   ` [PATCH v2 4/5] spi: Add OF binding support for SPI busses Grant Likely
     [not found]     ` <20080703010313.26187.99119.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
2008-07-03  3:02       ` Jon Smirl
     [not found]         ` <9e4733910807022002n3c739c7cs8ed642e4a6027bb6-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-07-12  5:21           ` Grant Likely
2008-07-04  3:54       ` Chen Gong
     [not found]         ` <58A20A281BAF1047B4EAE68DE5C0BDC2010121B7-bKEhWGtIRULiD3AT8lUqWFjVikpgYyvb5NbjCUgZEJk@public.gmane.org>
2008-07-04  4:17           ` Grant Likely
2008-07-03  1:03   ` [PATCH v2 5/5] powerpc/mpc5200: Add mpc5200-spi (non-PSC) device driver Grant Likely

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).