[RFC] OpenFirmware bindings for the MMC-over-SPI driver
From: Anton Vorontsov <hidden>
Date: 2008-05-23 18:28:05
14 messages, 7 authors, 2008-05-26 · open the first message on its own page
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
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
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
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:
+++ b/drivers/mmc/host/of_mmc_spi.c
+static int of_mmc_spi_probe(struct spi_device *spi)
+ /* + * 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
+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 ...)
+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/
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:
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.cdiff --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.
+ - 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?
+ - 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
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?
+ + /* + * 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);
-- Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
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
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
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
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
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.
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.cdiff --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
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.cquoted
+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
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?
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