[RFC] OpenFirmware bindings for the MMC-over-SPI driver

14 messages, 7 authors, 2008-05-26 · open the first message on its own page

[RFC] OpenFirmware bindings for the MMC-over-SPI driver

From: Anton Vorontsov <hidden>
Date: 2008-05-23 18:28:05

Hi all,

This is second attempt to write the OpenFirmware bindings for the
MMC-over-SPI (and SPI bindings in general). First attempt[1] was discussed
in the linuxppc-dev list only, since I tried to do the bindings without
touching the drivers them self. That attempt got a cool welcome, so here
is an alternative.

Grant, I'm somewhat sure you'll like it now... :-) As a plus, these
bindings doesn't require changes to the spi_of core...

[1] http://ozlabs.org/pipermail/linuxppc-dev/2008-May/056727.html

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

[RFC PATCH 1/2] mmc_spi: export probe and remove functions

From: Anton Vorontsov <hidden>
Date: 2008-05-23 18:28:46

...so we'll able to write bindings for the OpenFirmware without
messing with #ifdefs in the driver itself.

Signed-off-by: Anton Vorontsov <redacted>
---
 drivers/mmc/host/mmc_spi.c |    6 ++++--
 drivers/mmc/host/mmc_spi.h |    7 +++++++
 2 files changed, 11 insertions(+), 2 deletions(-)
 create mode 100644 drivers/mmc/host/mmc_spi.h
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 85d9853..f2c4fc2 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1184,7 +1184,7 @@ static int maybe_count_child(struct device *dev, void *c)
 	return 0;
 }
 
-static int mmc_spi_probe(struct spi_device *spi)
+int mmc_spi_probe(struct spi_device *spi)
 {
 	void			*ones;
 	struct mmc_host		*mmc;
@@ -1366,9 +1366,10 @@ nomem:
 	kfree(ones);
 	return status;
 }
+EXPORT_SYMBOL(mmc_spi_probe);
 
 
-static int __devexit mmc_spi_remove(struct spi_device *spi)
+int __devexit mmc_spi_remove(struct spi_device *spi)
 {
 	struct mmc_host		*mmc = dev_get_drvdata(&spi->dev);
 	struct mmc_spi_host	*host;
@@ -1398,6 +1399,7 @@ static int __devexit mmc_spi_remove(struct spi_device *spi)
 	}
 	return 0;
 }
+EXPORT_SYMBOL(mmc_spi_remove);
 
 
 static struct spi_driver mmc_spi_driver = {
diff --git a/drivers/mmc/host/mmc_spi.h b/drivers/mmc/host/mmc_spi.h
new file mode 100644
index 0000000..d4fcd91
--- /dev/null
+++ b/drivers/mmc/host/mmc_spi.h
@@ -0,0 +1,7 @@
+#ifndef __DRIVERS_MMC_HOST_MMC_SPI_H
+#define __DRIVERS_MMC_HOST_MMC_SPI_H
+
+extern int mmc_spi_probe(struct spi_device *spi);
+extern int __devexit mmc_spi_remove(struct spi_device *spi);
+
+#endif
-- 
1.5.5.1

[RFC PATCH 2/2] mmc: add OpenFirmware bindings for the mmc_spi driver

From: Anton Vorontsov <hidden>
Date: 2008-05-23 18:29:01

This patch depends on the Grant Likely's SPI patches, so this is
for RFC only.

Also, later we'll able to remove OF_GPIO dependency.

Signed-off-by: Anton Vorontsov <redacted>
---
 Documentation/powerpc/booting-without-of.txt |   24 ++++
 drivers/mmc/host/Kconfig                     |    7 ++
 drivers/mmc/host/Makefile                    |    2 +-
 drivers/mmc/host/of_mmc_spi.c                |  151 ++++++++++++++++++++++++++
 4 files changed, 183 insertions(+), 1 deletions(-)
 create mode 100644 drivers/mmc/host/of_mmc_spi.c
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 423cb2b..7d0ef80 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -3151,7 +3151,31 @@ platforms are moved over to use the flattened-device-tree model.
 			};
 		};
 
+    ...) MMC-over-SPI
 
+      Required properties:
+      - #address-cells : should be 0.
+      - #size-cells : should be 0.
+      - compatible : should be "linux,mmc-spi".
+      - linux,modalias  - should be "of_mmc_spi".
+      - reg : should specify SPI address (chip-select number).
+      - max-speed : (optional) maximum frequency for this device (Hz).
+      - linux,mmc-ocr-mask : (optional) Linux-specific MMC OCR mask
+        (slot voltage).
+      - gpios : (optional) may specify GPIOs in this order: Write-Protect GPIO,
+        Card-Detect GPIO.
+
+      Example:
+
+	mmc-slot@0 {
+		compatible = "linux,mmc-spi";
+		linux,modalias = "of_mmc_spi";
+		reg = <0>;
+		max-speed = <50000000>;
+		linux,mmc-ocr-mask = <0x00200000>;
+		gpios = <&sdcsr_pio 6 0   /*  WP */
+			 &sdcsr_pio 7 1>; /* nCD */
+	};
 
 VII - Marvell Discovery mv64[345]6x System Controller chips
 ===========================================================
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index dead617..f468544 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -130,3 +130,10 @@ config MMC_SPI
 
 	  If unsure, or if your system has no SPI master driver, say N.
 
+config OF_MMC_SPI
+	tristate "MMC/SD over SPI OpenFirmware bindings"
+	depends on MMC_SPI && SPI_MASTER_OF && OF_GPIO
+	default y
+	help
+	  Say Y here to enable OpenFirmware bindings for the MMC/SD over SPI
+	  driver.
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 3877c87..d77f880 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -17,4 +17,4 @@ obj-$(CONFIG_MMC_OMAP)		+= omap.o
 obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
 obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
 obj-$(CONFIG_MMC_SPI)		+= mmc_spi.o
-
+obj-$(CONFIG_OF_MMC_SPI)	+= of_mmc_spi.o
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
new file mode 100644
index 0000000..b8211ce
--- /dev/null
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -0,0 +1,151 @@
+/*
+ * OpenFirmware bindings for the MMC-over-SPI driver
+ *
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_of.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/mmc/host.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include "mmc_spi.h"
+
+struct of_mmc_spi {
+	int wp_gpio;
+	int cd_gpio;
+	struct mmc_spi_platform_data mmc_pdata;
+};
+
+static int mmc_get_ro(struct device *dev)
+{
+	struct of_mmc_spi *oms = dev->archdata.of_node->data;
+
+	return gpio_get_value(oms->wp_gpio);
+}
+
+static int mmc_get_cd(struct device *dev)
+{
+	struct of_mmc_spi *oms = dev->archdata.of_node->data;
+
+	return gpio_get_value(oms->cd_gpio);
+}
+
+static int of_mmc_spi_probe(struct spi_device *spi)
+{
+	int ret = -EINVAL;
+	struct device_node *np = spi->dev.archdata.of_node;
+	struct device *dev = &spi->dev;
+	struct of_mmc_spi *oms = kzalloc(sizeof(*oms), GFP_KERNEL);
+	const u32 *ocr_mask;
+	int size;
+
+	if (!oms)
+		return -ENOMEM;
+
+	/* Somebody occupied node's data? */
+	WARN_ON(spi->dev.archdata.of_node->data);
+
+	/*
+	 * mmc_spi_probe will use drvdata, so we can't use it. Use node's
+	 * data instead.
+	 */
+	spi->dev.archdata.of_node->data = oms;
+
+	/* We don't support interrupts yet, let's poll. */
+	oms->mmc_pdata.caps |= MMC_CAP_NEEDS_POLL;
+
+	ocr_mask = of_get_property(np, "linux,mmc-ocr-mask", &size);
+	if (ocr_mask && size >= sizeof(ocr_mask))
+		oms->mmc_pdata.ocr_mask = *ocr_mask;
+
+	oms->wp_gpio = of_get_gpio(np, 0);
+	if (gpio_is_valid(oms->wp_gpio)) {
+		ret = gpio_request(oms->wp_gpio, dev->bus_id);
+		if (ret < 0)
+			goto err_wp_gpio;
+		oms->mmc_pdata.get_ro = &mmc_get_ro;
+	}
+
+	oms->cd_gpio = of_get_gpio(np, 1);
+	if (gpio_is_valid(oms->cd_gpio)) {
+		ret = gpio_request(oms->cd_gpio, dev->bus_id);
+		if (ret < 0)
+			goto err_cd_gpio;
+		oms->mmc_pdata.get_cd = &mmc_get_cd;
+	}
+
+	spi->dev.platform_data = &oms->mmc_pdata;
+
+	ret = mmc_spi_probe(spi);
+	if (ret)
+		goto err_mmc_spi;
+
+	return 0;
+err_mmc_spi:
+	if (gpio_is_valid(oms->cd_gpio))
+		gpio_free(oms->cd_gpio);
+err_cd_gpio:
+	if (gpio_is_valid(oms->wp_gpio))
+		gpio_free(oms->wp_gpio);
+err_wp_gpio:
+	spi->dev.archdata.of_node->data = NULL;
+	kfree(oms);
+	return ret;
+}
+
+int __devexit of_mmc_spi_remove(struct spi_device *spi)
+{
+	struct of_mmc_spi *oms = spi->dev.archdata.of_node->data;
+	int ret;
+
+	ret = mmc_spi_remove(spi);
+	if (ret)
+		return ret;
+
+	if (gpio_is_valid(oms->cd_gpio))
+		gpio_free(oms->cd_gpio);
+	if (gpio_is_valid(oms->wp_gpio))
+		gpio_free(oms->wp_gpio);
+
+	spi->dev.archdata.of_node->data = NULL;
+	kfree(oms);
+	return 0;
+}
+
+static struct spi_driver of_mmc_spi_driver = {
+	.driver = {
+		.name = "of_mmc_spi",
+		.bus = &spi_bus_type,
+		.owner = THIS_MODULE,
+	},
+	.probe = of_mmc_spi_probe,
+	.remove = __devexit_p(of_mmc_spi_remove),
+};
+
+static int __init of_mmc_spi_init(void)
+{
+	return spi_register_driver(&of_mmc_spi_driver);
+}
+module_init(of_mmc_spi_init);
+
+static void __exit of_mmc_spi_exit(void)
+{
+	spi_unregister_driver(&of_mmc_spi_driver);
+}
+module_exit(of_mmc_spi_exit);
+
+MODULE_DESCRIPTION("OpenFirmware bindings for the MMC-over-SPI driver");
+MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL");
-- 
1.5.5.1

Re: [RFC PATCH 2/2] mmc: add OpenFirmware bindings for the mmc_spi driver

From: Stephen Rothwell <hidden>
Date: 2008-05-24 02:35:49

Hi Anton,

On Fri, 23 May 2008 22:28:42 +0400 Anton Vorontsov [off-list ref] wrote:
quoted hunk
+++ b/drivers/mmc/host/of_mmc_spi.c
+static int of_mmc_spi_probe(struct spi_device *spi)
quoted hunk
+	/*
+	 * mmc_spi_probe will use drvdata, so we can't use it. Use node's
+	 * data instead.
+	 */
+	spi->dev.archdata.of_node->data = oms;
If you delay this assignment, you may not have to clean it up in the
error path.
+	ocr_mask = of_get_property(np, "linux,mmc-ocr-mask", &size);
You should really explicitly include linux/of.h to use of_get_property etc
quoted hunk
+int __devexit of_mmc_spi_remove(struct spi_device *spi)
+{
+	struct of_mmc_spi *oms = spi->dev.archdata.of_node->data;
+	int ret;
+
+	ret = mmc_spi_remove(spi);
+	if (ret)
+		return ret;
Maybe you should do this last so that you don't leak more than necessary
if mmc_spi_remove fails.  (I don't know what state mmc_spi_remove leaves
stuff in if it fails ...)
quoted hunk
+static struct spi_driver of_mmc_spi_driver = {
+	.driver = {
+		.name = "of_mmc_spi",
+		.bus = &spi_bus_type,
This is initialised by spi_register_driver().

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

Re: [RFC PATCH 2/2] mmc: add OpenFirmware bindings for the mmc_spi driver

From: Grant Likely <hidden>
Date: 2008-05-24 05:19:40

Yup, I like this approach better.  I had been thinking about putting
this all in the same file (drivers/mmc/host/mmc_spi.c) instead of
exporting the probe/remove symbols and by using clear comment blocks
to divide the sections, but I've got no issues with this approach.

This is good work.  Some comments below.  (I won't repeat Stephen's comments)

On Fri, May 23, 2008 at 12:28 PM, Anton Vorontsov
[off-list ref] wrote:
quoted hunk
This patch depends on the Grant Likely's SPI patches, so this is
for RFC only.

Also, later we'll able to remove OF_GPIO dependency.

Signed-off-by: Anton Vorontsov <redacted>
---
 Documentation/powerpc/booting-without-of.txt |   24 ++++
 drivers/mmc/host/Kconfig                     |    7 ++
 drivers/mmc/host/Makefile                    |    2 +-
 drivers/mmc/host/of_mmc_spi.c                |  151 ++++++++++++++++++++++++++
 4 files changed, 183 insertions(+), 1 deletions(-)
 create mode 100644 drivers/mmc/host/of_mmc_spi.c
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 423cb2b..7d0ef80 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -3151,7 +3151,31 @@ platforms are moved over to use the flattened-device-tree model.
                       };
               };

+    ...) MMC-over-SPI

+      Required properties:
+      - #address-cells : should be 0.
+      - #size-cells : should be 0.
Are these properties required at all?  Will this node have any children.
+      - compatible : should be "linux,mmc-spi".
+      - linux,modalias  - should be "of_mmc_spi".
I'm not even sure if the whole linux,modalias is even a good idea.  I
had kind of thrown it in there as a convenient way to override
compatible when needed, but I haven't really thought it out very well
and I think it is rather a hack.

The real problem is we don't yet have good method (or place) to apply
a translation table from compatible values to modaliases.  Ideally,
the translations should be part of the drivers themselves, but that
causes a chicken and egg problem of needing to load the driver to get
access to the table to know if it is the correct driver... Of course,
I'm really not very familiar with the whole module autoloading
mechanism.  Regardless; binding should be based on compatible, not on
a hacky and bogus linux,modalias property.
quoted hunk
+      - reg : should specify SPI address (chip-select number).
+      - max-speed : (optional) maximum frequency for this device (Hz).
+      - linux,mmc-ocr-mask : (optional) Linux-specific MMC OCR mask
+        (slot voltage).
Should this property be better defined?
quoted hunk
+      - gpios : (optional) may specify GPIOs in this order: Write-Protect GPIO,
+        Card-Detect GPIO.
+
+      Example:
+
+       mmc-slot@0 {
+               compatible = "linux,mmc-spi";
+               linux,modalias = "of_mmc_spi";
+               reg = <0>;
+               max-speed = <50000000>;
+               linux,mmc-ocr-mask = <0x00200000>;
+               gpios = <&sdcsr_pio 6 0   /*  WP */
+                        &sdcsr_pio 7 1>; /* nCD */
+       };

 VII - Marvell Discovery mv64[345]6x System Controller chips
 ===========================================================
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index dead617..f468544 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -130,3 +130,10 @@ config MMC_SPI

         If unsure, or if your system has no SPI master driver, say N.

+config OF_MMC_SPI
+       tristate "MMC/SD over SPI OpenFirmware bindings"
+       depends on MMC_SPI && SPI_MASTER_OF && OF_GPIO
+       default y
+       help
+         Say Y here to enable OpenFirmware bindings for the MMC/SD over SPI
+         driver.
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 3877c87..d77f880 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -17,4 +17,4 @@ obj-$(CONFIG_MMC_OMAP)                += omap.o
 obj-$(CONFIG_MMC_AT91)         += at91_mci.o
 obj-$(CONFIG_MMC_TIFM_SD)      += tifm_sd.o
 obj-$(CONFIG_MMC_SPI)          += mmc_spi.o

66 more quoted lines

Perhaps bail at this point to avoid corruption?  Would it be better to
use container_of() instead for getting a pointer back to the private
structure from the pdata pointer?
quoted hunk
+
+       /*
+        * mmc_spi_probe will use drvdata, so we can't use it. Use node's
+        * data instead.
+        */
+       spi->dev.archdata.of_node->data = oms;
+
+       /* We don't support interrupts yet, let's poll. */
+       oms->mmc_pdata.caps |= MMC_CAP_NEEDS_POLL;
+
+       ocr_mask = of_get_property(np, "linux,mmc-ocr-mask", &size);
+       if (ocr_mask && size >= sizeof(ocr_mask))
+               oms->mmc_pdata.ocr_mask = *ocr_mask;
+
+       oms->wp_gpio = of_get_gpio(np, 0);
+       if (gpio_is_valid(oms->wp_gpio)) {
+               ret = gpio_request(oms->wp_gpio, dev->bus_id);
+               if (ret < 0)
+                       goto err_wp_gpio;
+               oms->mmc_pdata.get_ro = &mmc_get_ro;
+       }
+
+       oms->cd_gpio = of_get_gpio(np, 1);
+       if (gpio_is_valid(oms->cd_gpio)) {
+               ret = gpio_request(oms->cd_gpio, dev->bus_id);
+               if (ret < 0)
+                       goto err_cd_gpio;
+               oms->mmc_pdata.get_cd = &mmc_get_cd;
+       }
+
+       spi->dev.platform_data = &oms->mmc_pdata;
+
+       ret = mmc_spi_probe(spi);
+       if (ret)
+               goto err_mmc_spi;
+
+       return 0;
+err_mmc_spi:
+       if (gpio_is_valid(oms->cd_gpio))
+               gpio_free(oms->cd_gpio);

56 more quoted lines



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

Re: [RFC PATCH 2/2] mmc: add OpenFirmware bindings for the mmc_spi driver

From: Jochen Friedrich <jochen@scram.de>
Date: 2008-05-24 14:33:03

Hi Grant,
quoted
+      - compatible : should be "linux,mmc-spi".
+      - linux,modalias  - should be "of_mmc_spi".
I'm not even sure if the whole linux,modalias is even a good idea.  I
had kind of thrown it in there as a convenient way to override
compatible when needed, but I haven't really thought it out very well
and I think it is rather a hack.

The real problem is we don't yet have good method (or place) to apply
a translation table from compatible values to modaliases.  Ideally,
the translations should be part of the drivers themselves, but that
causes a chicken and egg problem of needing to load the driver to get
access to the table to know if it is the correct driver... Of course,
I'm really not very familiar with the whole module autoloading
mechanism.  Regardless; binding should be based on compatible, not on
a hacky and bogus linux,modalias property.
i2c exactly has the same problem. Here the compatible entry is used
in drivers/of/of_i2c.c and mangled into a name to be used as modalias.
It's still sort of hackish, but it seems to be a compromise acceptable
by both OF and i2c folks.

Thanks,
Jochen

Re: [RFC] OpenFirmware bindings for the MMC-over-SPI driver

From: David Brownell <hidden>
Date: 2008-05-24 21:11:39

On Friday 23 May 2008, Anton Vorontsov wrote:
This is second attempt to write the OpenFirmware bindings for the
MMC-over-SPI (and SPI bindings in general).
Summary:  an OF-specific wrapper around the mmc_spi platform code.

I think a wrapper to encapsulate all the OF-specific knowledge makes
much sense here.

The only thing that looks odd to me about this is that the wrapper
is a spi_device rather than an of_device.  To me it makes more sense
to just have an of_device setting up the right spi_device.  (Though
maybe I missed some discussion about why that can't work.)

Example:  drivers/usb/host/sl811_cs.c does that for PCMCIA card
that just wraps an sl811 chip that's more often used standalone.
The PCMCIA descriptors being analagous to OF device table entries.

- Dave

Re: [RFC PATCH 2/2] mmc: add OpenFirmware bindings for the mmc_spi driver

From: Segher Boessenkool <hidden>
Date: 2008-05-24 23:07:29

quoted
+      Required properties:
+      - #address-cells : should be 0.
+      - #size-cells : should be 0.
Are these properties required at all?  Will this node have any children.
You mean, "does this node define a bus".  If it doesn't, there
shouldn't be #a and #s; if it does, the binding should describe
what the addressing is.  #a = #s = 0 describes a bus without any
addressing; pretty unusual :-)
quoted
+      - linux,mmc-ocr-mask : (optional) Linux-specific MMC OCR mask
+        (slot voltage).
Should this property be better defined?
Yes please.  There's a good chance that it doesn't turn out to be
Linux-specific at all (after some modification, perhaps).


Segher

Re: [RFC PATCH 2/2] mmc: add OpenFirmware bindings for the mmc_spi driver

From: Segher Boessenkool <hidden>
Date: 2008-05-24 23:17:20

quoted
The real problem is we don't yet have good method (or place) to apply
a translation table from compatible values to modaliases.  Ideally,
the translations should be part of the drivers themselves, but that
causes a chicken and egg problem of needing to load the driver to get
access to the table to know if it is the correct driver... Of course,
I'm really not very familiar with the whole module autoloading
mechanism.  Regardless; binding should be based on compatible, not on
a hacky and bogus linux,modalias property.
i2c exactly has the same problem. Here the compatible entry is used
in drivers/of/of_i2c.c and mangled into a name to be used as modalias.
It's still sort of hackish, but it seems to be a compromise acceptable
by both OF and i2c folks.
It's perfectly acceptable.  The sole purpose of "compatible" is for
a client (i.e., the kernel) to decide what to do with this device;
most often, to decide what driver to use.

It would be nice to have a completely generic thing that matches device
tree nodes to drivers, and it sounds perfectly reasonable to me to go
via modalias for that (i.e., just translate from device tree namespace
to the kernel driver namespace).

As a bonus, it would make driver matching more correct in some places:
currently, whatever driver matches first wins (i.e., which "compatible"
value is tried first), but the ordering of different values in "compatible"
is supposed to be significant (whatever is mentioned there first should
win).


Segher

Re: [RFC] OpenFirmware bindings for the MMC-over-SPI driver

From: Grant Likely <hidden>
Date: 2008-05-25 04:47:22

On Sat, May 24, 2008 at 1:56 PM, David Brownell [off-list ref] wrote:
On Friday 23 May 2008, Anton Vorontsov wrote:
quoted
This is second attempt to write the OpenFirmware bindings for the
MMC-over-SPI (and SPI bindings in general).
Summary:  an OF-specific wrapper around the mmc_spi platform code.

I think a wrapper to encapsulate all the OF-specific knowledge makes
much sense here.

The only thing that looks odd to me about this is that the wrapper
is a spi_device rather than an of_device.  To me it makes more sense
to just have an of_device setting up the right spi_device.  (Though
maybe I missed some discussion about why that can't work.)
It's not so much that I can't work; more like it's not necessary.
of_platform bus is by no means the prescribed way to work with the
device tree.  In fact, there is talk about moving away from
of_platform bus entirely and using
platform_device/spi_device/i2c_device/etc directly instead since the
of_platform bus is mostly a clone of the platform bus with different
device binding semantics.

As Anton's patch shows, it is straight forward to add a binding that
can extract the platform data out of the device tree without the
overhead of adding an additional of_platform bus device & driver pair.

Cheers,
g.

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

Re: [RFC PATCH 2/2] mmc: add OpenFirmware bindings for the mmc_spi driver

From: Anton Vorontsov <hidden>
Date: 2008-05-26 11:49:26

On Fri, May 23, 2008 at 11:19:28PM -0600, Grant Likely wrote:
Yup, I like this approach better.  I had been thinking about putting
this all in the same file (drivers/mmc/host/mmc_spi.c) instead of
exporting the probe/remove symbols and by using clear comment blocks
to divide the sections, but I've got no issues with this approach.

This is good work.  Some comments below.  (I won't repeat Stephen's comments)
Thanks!
On Fri, May 23, 2008 at 12:28 PM, Anton Vorontsov
[off-list ref] wrote:
quoted
This patch depends on the Grant Likely's SPI patches, so this is
for RFC only.

Also, later we'll able to remove OF_GPIO dependency.

Signed-off-by: Anton Vorontsov <redacted>
---
 Documentation/powerpc/booting-without-of.txt |   24 ++++
 drivers/mmc/host/Kconfig                     |    7 ++
 drivers/mmc/host/Makefile                    |    2 +-
 drivers/mmc/host/of_mmc_spi.c                |  151 ++++++++++++++++++++++++++
 4 files changed, 183 insertions(+), 1 deletions(-)
 create mode 100644 drivers/mmc/host/of_mmc_spi.c
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 423cb2b..7d0ef80 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -3151,7 +3151,31 @@ platforms are moved over to use the flattened-device-tree model.
                       };
               };

+    ...) MMC-over-SPI

+      Required properties:
+      - #address-cells : should be 0.
+      - #size-cells : should be 0.
Are these properties required at all?  Will this node have any children.
Yeah, my weakness for #a/#s, I always insert it where unnecessary. :-)
Will fix.
quoted
+      - compatible : should be "linux,mmc-spi".
+      - linux,modalias  - should be "of_mmc_spi".
I'm not even sure if the whole linux,modalias is even a good idea.  I
had kind of thrown it in there as a convenient way to override
compatible when needed, but I haven't really thought it out very well
and I think it is rather a hack.

The real problem is we don't yet have good method (or place) to apply
a translation table from compatible values to modaliases.  Ideally,
the translations should be part of the drivers themselves, but that
causes a chicken and egg problem of needing to load the driver to get
access to the table to know if it is the correct driver... Of course,
I'm really not very familiar with the whole module autoloading
mechanism.  Regardless; binding should be based on compatible, not on
a hacky and bogus linux,modalias property.
I fully agree. Though, I just tried to use your spi_of with a belief
that you'll implement compatible->modalias translation in spi_of. :-)
quoted
+      - reg : should specify SPI address (chip-select number).
+      - max-speed : (optional) maximum frequency for this device (Hz).
+      - linux,mmc-ocr-mask : (optional) Linux-specific MMC OCR mask
+        (slot voltage).
Should this property be better defined?
Yes, will do. Was a bit lazy to do this for the RFC.

[...]
quoted
+static int mmc_get_cd(struct device *dev)
+{
+       struct of_mmc_spi *oms = dev->archdata.of_node->data;
+
+       return gpio_get_value(oms->cd_gpio);
+}
+
+static int of_mmc_spi_probe(struct spi_device *spi)
+{
+       int ret = -EINVAL;
+       struct device_node *np = spi->dev.archdata.of_node;
+       struct device *dev = &spi->dev;
+       struct of_mmc_spi *oms = kzalloc(sizeof(*oms), GFP_KERNEL);
+       const u32 *ocr_mask;
+       int size;
+
+       if (!oms)
+               return -ENOMEM;
+
+       /* Somebody occupied node's data? */
+       WARN_ON(spi->dev.archdata.of_node->data);
Perhaps bail at this point to avoid corruption?  Would it be better to
use container_of() instead for getting a pointer back to the private
structure from the pdata pointer?
Using platform_data with container_of isn't always safe (e.g. for
platform bus we can't use it, this is done so that board's platform_data
definitions could be made __initdata).

David, would you [not] suggest us to use platform_data with
container_of, that is, are there any plans to make SPI core copy
the platform_data instead of passing a pointer directly?
quoted
+
+       /*
+        * mmc_spi_probe will use drvdata, so we can't use it. Use node's
+        * data instead.
+        */
+       spi->dev.archdata.of_node->data = oms;
+
[...]

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

Re: [RFC PATCH 2/2] mmc: add OpenFirmware bindings for the mmc_spi driver

From: Anton Vorontsov <hidden>
Date: 2008-05-26 11:58:49

On Sat, May 24, 2008 at 12:35:27PM +1000, Stephen Rothwell wrote:
Hi Anton,

On Fri, 23 May 2008 22:28:42 +0400 Anton Vorontsov [off-list ref] wrote:
quoted
+++ b/drivers/mmc/host/of_mmc_spi.c
quoted
+static int of_mmc_spi_probe(struct spi_device *spi)
quoted
+	/*
+	 * mmc_spi_probe will use drvdata, so we can't use it. Use node's
+	 * data instead.
+	 */
+	spi->dev.archdata.of_node->data = oms;
If you delay this assignment, you may not have to clean it up in the
error path.
No, if I delay it I'll have to clean it up anyway, just a bit later
(after mmc_spi_probe() fail).
quoted
+	ocr_mask = of_get_property(np, "linux,mmc-ocr-mask", &size);
You should really explicitly include linux/of.h to use of_get_property etc
Thanks, will do.
quoted
+int __devexit of_mmc_spi_remove(struct spi_device *spi)
+{
+	struct of_mmc_spi *oms = spi->dev.archdata.of_node->data;
+	int ret;
+
+	ret = mmc_spi_remove(spi);
+	if (ret)
+		return ret;
Maybe you should do this last so that you don't leak more than necessary
if mmc_spi_remove fails. (I don't know what state mmc_spi_remove leaves
stuff in if it fails ...)
If I do this last, then of_mmc_spi_remove() would be not safe to call
multiple times on non-fatal errors (e.g. when mmc_spi_remove() returns
-EBUSY (despite that currently mmc_spi_remove can't fail)).

Also, if I do this last, then there will be a potential use-after-free
in the mmc_spi driver.
quoted
+static struct spi_driver of_mmc_spi_driver = {
+	.driver = {
+		.name = "of_mmc_spi",
+		.bus = &spi_bus_type,
This is initialised by spi_register_driver().
This was straight copy from the mmc_spi.c. Will fix.

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

Re: [RFC PATCH 2/2] mmc: add OpenFirmware bindings for the mmc_spi driver

From: David Brownell <hidden>
Date: 2008-05-26 22:27:18

On Monday 26 May 2008, Anton Vorontsov wrote:
David, would you [not] suggest us to use platform_data with
container_of, that is, are there any plans to make SPI core copy
the platform_data instead of passing a pointer directly?
No such plans.  How could it copy, not knowing the size?

Re: [RFC PATCH 2/2] mmc: add OpenFirmware bindings for the mmc_spi driver

From: Anton Vorontsov <hidden>
Date: 2008-05-26 23:16:20

On Mon, May 26, 2008 at 03:19:01PM -0700, David Brownell wrote:
On Monday 26 May 2008, Anton Vorontsov wrote:
quoted
David, would you [not] suggest us to use platform_data with
container_of, that is, are there any plans to make SPI core copy
the platform_data instead of passing a pointer directly?
No such plans.
Ok, great.
How could it copy, not knowing the size?
Platform bus usually knows the size via platform_device_add_data()...
anyway, we're in safe if there are no plans for this in SPI.

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help