* Re: [RFC][PATCH] powerpc: respect how command line nr_cpus is set
From: Kumar Gala @ 2011-05-05 11:38 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1304562302.2513.418.camel@pasglop>
On May 4, 2011, at 9:25 PM, Benjamin Herrenschmidt wrote:
> On Wed, 2011-05-04 at 15:17 -0500, Kumar Gala wrote:
>> We should utilize nr_cpus as the max # of CPUs that we can have =
present
>> instead of NR_CPUS. This way we actually respect how nr_cpus is set =
on
>> the command line rather than ignoring it.
>>=20
>> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
>> ---
>> I think this is what we should be doing, but would like someone else =
to take
>> a look.
>=20
> The main question I have is should max_cpus absolutely limit the =
number
> of possible CPUs or should it limit the number that get automatically
> onlined at boot, potentially letting us bring the rest online later on =
?
>=20
> Cheers,
> Ben.
=46rom Documentation/kernel-parameters.txt:
nr_cpus=3D [SMP] Maximum number of processors that an SMP =
kernel
could support. nr_cpus=3Dn : n >=3D 1 limits =
the kernel to
supporting 'n' processors. Later in runtime you =
can not
use hotplug cpu feature to put more cpu back to =
online.
just like you compile the kernel NR_CPUS=3Dn
Which makes me think we should have max_cpus be an absolute limit.
- k=
^ permalink raw reply
* [PATCH v2 0/7] Consolidate sdhci pltfm & OF drivers and get them self registered
From: Shawn Guo @ 2011-05-05 13:22 UTC (permalink / raw)
To: linux-mmc
Cc: Chris Ball, sameo, Arnd Bergmann, patches, devicetree-discuss,
Saeed Bishara, Xiaobo Xie, kernel, Mike Rapoport, Olof Johansson,
Anton Vorontsov, linuxppc-dev, Albert Herranz, linux-arm-kernel
Here are what the patch set does.
* Remove .probe and .remove hooks from sdhci-pltfm.c and make it be
a pure common helper function providers.
* Add .probe and .remove hooks for sdhci pltfm drivers sdhci-cns3xxx,
sdhci-dove, sdhci-tegra, and sdhci-esdhc-imx to make them self
registered with calling helper functions created above.
* Migrate the use of sdhci_of_host and sdhci_of_data to
sdhci_pltfm_host and sdhci_pltfm_data, so that OF version host and
data structure works can be saved, and pltfm version works for both
cases.
* Add OF common helper stuff into sdhci-pltfm.c, and make OF version
sdhci drivers sdhci-of-esdhc and sdhci-of-hlwd become self
registered as well, so that sdhci-of-core.c and sdhci-of.h can be
removed.
* Consolidate the OF and pltfm esdhc drivers into one with sharing
the same pair of .probe and .remove hooks.
* Eliminate include/linux/mmc/sdhci-pltfm.h with moving stuff into
drivers/mmc/host/sdhci-pltfm.h.
And the benefits we gain from the changes are:
* Get the sdhci device driver follow the Linux trend that driver
makes the registration by its own.
* sdhci-pltfm.c becomes simple and clean as it only has common helper
stuff there now.
* All sdhci device specific things are going back its own driver.
* The dt and non-dt drivers are consolidated to use the same pair of
.probe and .remove hooks.
* SDHCI driver for Freescale eSDHC controller found on both MPCxxx
and i.MX platforms is consolidated to use the same one .probe
function.
It was only tested on i.mx51 babbage board, all other targets were
build tested. Tested-by, Reviwed-by, and Acked-by are much
appreciated.
I attempt to get patch #1 ~ #6 go through Chris' tree, while the #7
through Sascha's tree.
Regards,
Shawn
Changes since v1:
* Rebase on cjb's mmc-next tree
* Introduce helper function pair sdhci_pltfm_register and
sdhci_pltfm_unregister
* Eliminate variable 'scratch' in .remove hook to make the code
look simple
* Return ERR_PTR in sdhci_pltfm_init and use IS_ERR/PTR_ERR to check
return value in .probe hooks
* Correct MODULE_AUTHOR statement
* Split esdhc conlidation patch to ease reviewing
Shawn Guo (7):
mmc: sdhci: make sdhci-pltfm device drivers self registered
mmc: sdhci: eliminate sdhci_of_host and sdhci_of_data
mmc: sdhci: make sdhci-of device drivers self registered
sdhci: rename sdhci-esdhc-imx.c to sdhci-esdhc.c
mmc: sdhci: consolidate sdhci-of-esdhc and sdhci-esdhc-imx
mmc: sdhci: merge two sdhci-pltfm.h into one
ARM: mxc: remove esdhc.h and use the public one
.../plat-mxc/devices/platform-sdhci-esdhc-imx.c | 1 -
arch/arm/plat-mxc/include/mach/devices-common.h | 2 +-
drivers/mmc/host/Kconfig | 77 ++--
drivers/mmc/host/Makefile | 17 +-
drivers/mmc/host/sdhci-cns3xxx.c | 43 ++-
drivers/mmc/host/sdhci-dove.c | 42 ++-
drivers/mmc/host/sdhci-esdhc-imx.c | 331 -----------
drivers/mmc/host/sdhci-esdhc.c | 580 ++++++++++++++++++++
drivers/mmc/host/sdhci-esdhc.h | 81 ---
drivers/mmc/host/sdhci-of-core.c | 250 ---------
drivers/mmc/host/sdhci-of-esdhc.c | 91 ---
drivers/mmc/host/sdhci-of-hlwd.c | 66 ++-
drivers/mmc/host/sdhci-of.h | 42 --
drivers/mmc/host/sdhci-pltfm.c | 259 +++++----
drivers/mmc/host/sdhci-pltfm.h | 39 ++-
drivers/mmc/host/sdhci-tegra.c | 118 +++--
include/linux/mmc/esdhc.h | 27 +
include/linux/mmc/sdhci-pltfm.h | 35 --
18 files changed, 1048 insertions(+), 1053 deletions(-)
^ permalink raw reply
* [PATCH v2 1/7] mmc: sdhci: make sdhci-pltfm device drivers self registered
From: Shawn Guo @ 2011-05-05 13:22 UTC (permalink / raw)
To: linux-mmc
Cc: Chris Ball, sameo, Arnd Bergmann, patches, Shawn Guo,
devicetree-discuss, Saeed Bishara, Xiaobo Xie, kernel,
Mike Rapoport, Olof Johansson, Anton Vorontsov, linuxppc-dev,
Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-1-git-send-email-shawn.guo@linaro.org>
The patch turns the common stuff in sdhci-pltfm.c into functions, and
add device drivers their own .probe and .remove which in turn call
into the common functions, so that those sdhci-pltfm device drivers
register itself and keep all device specific things away from common
sdhci-pltfm file.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
---
drivers/mmc/host/Kconfig | 32 ++++----
drivers/mmc/host/Makefile | 11 +--
drivers/mmc/host/sdhci-cns3xxx.c | 42 +++++++++-
drivers/mmc/host/sdhci-dove.c | 42 +++++++++-
drivers/mmc/host/sdhci-esdhc-imx.c | 112 ++++++++++++++++++-------
drivers/mmc/host/sdhci-pltfm.c | 157 +++++++++---------------------------
drivers/mmc/host/sdhci-pltfm.h | 17 +++-
drivers/mmc/host/sdhci-tegra.c | 118 +++++++++++++++++++--------
include/linux/mmc/sdhci-pltfm.h | 6 --
9 files changed, 317 insertions(+), 220 deletions(-)
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index b981715..799e935 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -113,28 +113,27 @@ config MMC_SDHCI_OF_HLWD
If unsure, say N.
config MMC_SDHCI_PLTFM
- tristate "SDHCI support on the platform specific bus"
+ bool
depends on MMC_SDHCI
help
- This selects the platform specific bus support for Secure Digital Host
- Controller Interface.
-
- If you have a controller with this interface, say Y or M here.
-
- If unsure, say N.
+ This selects the platform common function support for Secure Digital
+ Host Controller Interface.
config MMC_SDHCI_CNS3XXX
- bool "SDHCI support on the Cavium Networks CNS3xxx SoC"
+ tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
depends on ARCH_CNS3XXX
- depends on MMC_SDHCI_PLTFM
+ depends on MMC_SDHCI
+ select MMC_SDHCI_PLTFM
help
This selects the SDHCI support for CNS3xxx System-on-Chip devices.
If unsure, say N.
config MMC_SDHCI_ESDHC_IMX
- bool "SDHCI platform support for the Freescale eSDHC i.MX controller"
- depends on MMC_SDHCI_PLTFM && (ARCH_MX25 || ARCH_MX35 || ARCH_MX5)
+ tristate "SDHCI platform support for the Freescale eSDHC i.MX controller"
+ depends on ARCH_MX25 || ARCH_MX35 || ARCH_MX5
+ depends on MMC_SDHCI
+ select MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
help
This selects the Freescale eSDHC controller support on the platform
@@ -143,9 +142,10 @@ config MMC_SDHCI_ESDHC_IMX
If unsure, say N.
config MMC_SDHCI_DOVE
- bool "SDHCI support on Marvell's Dove SoC"
+ tristate "SDHCI support on Marvell's Dove SoC"
depends on ARCH_DOVE
- depends on MMC_SDHCI_PLTFM
+ depends on MMC_SDHCI
+ select MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
help
This selects the Secure Digital Host Controller Interface in
@@ -154,8 +154,10 @@ config MMC_SDHCI_DOVE
If unsure, say N.
config MMC_SDHCI_TEGRA
- bool "SDHCI platform support for the Tegra SD/MMC Controller"
- depends on MMC_SDHCI_PLTFM && ARCH_TEGRA
+ tristate "SDHCI platform support for the Tegra SD/MMC Controller"
+ depends on ARCH_TEGRA
+ depends on MMC_SDHCI
+ select MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
help
This selects the Tegra SD/MMC controller. If you have a Tegra
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 4f1df0a..95fddb8 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,12 +43,11 @@ obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o
obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o
obj-$(CONFIG_MMC_USHC) += ushc.o
-obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-platform.o
-sdhci-platform-y := sdhci-pltfm.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o
-sdhci-platform-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o
+obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
+obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
+obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
+obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o
+obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o
obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o
sdhci-of-y := sdhci-of-core.o
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
index 9ebd1d7..ac4b26f 100644
--- a/drivers/mmc/host/sdhci-cns3xxx.c
+++ b/drivers/mmc/host/sdhci-cns3xxx.c
@@ -86,7 +86,7 @@ static struct sdhci_ops sdhci_cns3xxx_ops = {
.set_clock = sdhci_cns3xxx_set_clock,
};
-struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
+static struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
.ops = &sdhci_cns3xxx_ops,
.quirks = SDHCI_QUIRK_BROKEN_DMA |
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
@@ -95,3 +95,43 @@ struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
SDHCI_QUIRK_NONSTANDARD_CLOCK,
};
+
+static int __devinit sdhci_cns3xxx_probe(struct platform_device *pdev)
+{
+ return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata);
+}
+
+static int __devexit sdhci_cns3xxx_remove(struct platform_device *pdev)
+{
+ return sdhci_pltfm_unregister(pdev);
+}
+
+static struct platform_driver sdhci_cns3xxx_driver = {
+ .driver = {
+ .name = "sdhci-cns3xxx",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdhci_cns3xxx_probe,
+ .remove = __devexit_p(sdhci_cns3xxx_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
+};
+
+static int __init sdhci_cns3xxx_init(void)
+{
+ return platform_driver_register(&sdhci_cns3xxx_driver);
+}
+module_init(sdhci_cns3xxx_init);
+
+static void __exit sdhci_cns3xxx_exit(void)
+{
+ platform_driver_unregister(&sdhci_cns3xxx_driver);
+}
+module_exit(sdhci_cns3xxx_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for CNS3xxx");
+MODULE_AUTHOR("Scott Shu, "
+ "Anton Vorontsov <avorontsov@mvista.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
index 2aeef4f..49aa533 100644
--- a/drivers/mmc/host/sdhci-dove.c
+++ b/drivers/mmc/host/sdhci-dove.c
@@ -61,10 +61,50 @@ static struct sdhci_ops sdhci_dove_ops = {
.read_l = sdhci_dove_readl,
};
-struct sdhci_pltfm_data sdhci_dove_pdata = {
+static struct sdhci_pltfm_data sdhci_dove_pdata = {
.ops = &sdhci_dove_ops,
.quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
SDHCI_QUIRK_NO_BUSY_IRQ |
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
SDHCI_QUIRK_FORCE_DMA,
};
+
+static int __devinit sdhci_dove_probe(struct platform_device *pdev)
+{
+ return sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
+}
+
+static int __devexit sdhci_dove_remove(struct platform_device *pdev)
+{
+ return sdhci_pltfm_unregister(pdev);
+}
+
+static struct platform_driver sdhci_dove_driver = {
+ .driver = {
+ .name = "sdhci-dove",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdhci_dove_probe,
+ .remove = __devexit_p(sdhci_dove_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
+};
+
+static int __init sdhci_dove_init(void)
+{
+ return platform_driver_register(&sdhci_dove_driver);
+}
+module_init(sdhci_dove_init);
+
+static void __exit sdhci_dove_exit(void)
+{
+ platform_driver_unregister(&sdhci_dove_driver);
+}
+module_exit(sdhci_dove_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for Dove");
+MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>, "
+ "Mike Rapoport <mike@compulab.co.il>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index a19967d..8da57d4 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -191,16 +191,6 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
return clk_get_rate(pltfm_host->clk) / 256 / 16;
}
-static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
-{
- struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
-
- if (boarddata && gpio_is_valid(boarddata->wp_gpio))
- return gpio_get_value(boarddata->wp_gpio);
- else
- return -ENOSYS;
-}
-
static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl_le,
.read_w = esdhc_readw_le,
@@ -212,6 +202,23 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.get_min_clock = esdhc_pltfm_get_min_clock,
};
+static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
+ .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
+ | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
+ /* ADMA has issues. Might be fixable */
+ .ops = &sdhci_esdhc_ops,
+};
+
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+ if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ return gpio_get_value(boarddata->wp_gpio);
+ else
+ return -ENOSYS;
+}
+
static irqreturn_t cd_irq(int irq, void *data)
{
struct sdhci_host *sdhost = (struct sdhci_host *)data;
@@ -220,30 +227,35 @@ static irqreturn_t cd_irq(int irq, void *data)
return IRQ_HANDLED;
};
-static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
+static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+ struct sdhci_pltfm_host *pltfm_host;
+ struct sdhci_host *host;
+ struct esdhc_platform_data *boarddata;
struct clk *clk;
int err;
struct pltfm_imx_data *imx_data;
+ host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata);
+ if (IS_ERR(host))
+ return PTR_ERR(host);
+
+ pltfm_host = sdhci_priv(host);
+
+ imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
+ if (!imx_data)
+ return -ENOMEM;
+ pltfm_host->priv = imx_data;
+
clk = clk_get(mmc_dev(host->mmc), NULL);
if (IS_ERR(clk)) {
dev_err(mmc_dev(host->mmc), "clk err\n");
- return PTR_ERR(clk);
+ err = PTR_ERR(clk);
+ goto err_clk_get;
}
clk_enable(clk);
pltfm_host->clk = clk;
- imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
- if (!imx_data) {
- clk_disable(pltfm_host->clk);
- clk_put(pltfm_host->clk);
- return -ENOMEM;
- }
- pltfm_host->priv = imx_data;
-
if (!cpu_is_mx25())
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
@@ -257,6 +269,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
+ boarddata = host->mmc->parent->platform_data;
if (boarddata) {
err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
if (err) {
@@ -289,6 +302,10 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
}
+ err = sdhci_add_host(host);
+ if (err)
+ goto err_add_host;
+
return 0;
no_card_detect_irq:
@@ -297,14 +314,23 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
boarddata->cd_gpio = err;
not_supported:
kfree(imx_data);
- return 0;
+ err_add_host:
+ clk_disable(pltfm_host->clk);
+ clk_put(pltfm_host->clk);
+ err_clk_get:
+ sdhci_pltfm_free(pdev);
+ return err;
}
-static void esdhc_pltfm_exit(struct sdhci_host *host)
+static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+ sdhci_remove_host(host, dead);
if (boarddata && gpio_is_valid(boarddata->wp_gpio))
gpio_free(boarddata->wp_gpio);
@@ -319,13 +345,37 @@ static void esdhc_pltfm_exit(struct sdhci_host *host)
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
kfree(imx_data);
+
+ sdhci_pltfm_free(pdev);
+
+ return 0;
}
-struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
- .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
- | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
- /* ADMA has issues. Might be fixable */
- .ops = &sdhci_esdhc_ops,
- .init = esdhc_pltfm_init,
- .exit = esdhc_pltfm_exit,
+static struct platform_driver sdhci_esdhc_imx_driver = {
+ .driver = {
+ .name = "sdhci-esdhc-imx",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdhci_esdhc_imx_probe,
+ .remove = __devexit_p(sdhci_esdhc_imx_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
};
+
+static int __init sdhci_esdhc_imx_init(void)
+{
+ return platform_driver_register(&sdhci_esdhc_imx_driver);
+}
+module_init(sdhci_esdhc_imx_init);
+
+static void __exit sdhci_esdhc_imx_exit(void)
+{
+ platform_driver_unregister(&sdhci_esdhc_imx_driver);
+}
+module_exit(sdhci_esdhc_imx_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index dbab040..8ccf256 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -22,48 +22,22 @@
* Inspired by sdhci-pci.c, by Pierre Ossman
*/
-#include <linux/delay.h>
-#include <linux/highmem.h>
-#include <linux/mod_devicetable.h>
-#include <linux/platform_device.h>
-
-#include <linux/mmc/host.h>
-
-#include <linux/io.h>
-#include <linux/mmc/sdhci-pltfm.h>
+#include <linux/err.h>
#include "sdhci.h"
#include "sdhci-pltfm.h"
-/*****************************************************************************\
- * *
- * SDHCI core callbacks *
- * *
-\*****************************************************************************/
-
static struct sdhci_ops sdhci_pltfm_ops = {
};
-/*****************************************************************************\
- * *
- * Device probing/removal *
- * *
-\*****************************************************************************/
-
-static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
+struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
+ struct sdhci_pltfm_data *pdata)
{
- const struct platform_device_id *platid = platform_get_device_id(pdev);
- struct sdhci_pltfm_data *pdata;
struct sdhci_host *host;
struct sdhci_pltfm_host *pltfm_host;
struct resource *iomem;
int ret;
- if (platid && platid->driver_data)
- pdata = (void *)platid->driver_data;
- else
- pdata = pdev->dev.platform_data;
-
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!iomem) {
ret = -ENOMEM;
@@ -71,8 +45,7 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
}
if (resource_size(iomem) < 0x100)
- dev_err(&pdev->dev, "Invalid iomem size. You may "
- "experience problems.\n");
+ dev_err(&pdev->dev, "Invalid iomem size!\n");
/* Some PCI-based MFD need the parent here */
if (pdev->dev.parent != &platform_bus)
@@ -87,7 +60,7 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(host);
- host->hw_name = "platform";
+ host->hw_name = dev_name(&pdev->dev);
if (pdata && pdata->ops)
host->ops = pdata->ops;
else
@@ -110,126 +83,70 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
goto err_remap;
}
- if (pdata && pdata->init) {
- ret = pdata->init(host, pdata);
- if (ret)
- goto err_plat_init;
- }
-
- ret = sdhci_add_host(host);
- if (ret)
- goto err_add_host;
-
platform_set_drvdata(pdev, host);
- return 0;
+ return host;
-err_add_host:
- if (pdata && pdata->exit)
- pdata->exit(host);
-err_plat_init:
- iounmap(host->ioaddr);
err_remap:
release_mem_region(iomem->start, resource_size(iomem));
err_request:
sdhci_free_host(host);
err:
- printk(KERN_ERR"Probing of sdhci-pltfm failed: %d\n", ret);
- return ret;
+ dev_err(&pdev->dev, "%s failed %d\n", __func__, ret);
+ return ERR_PTR(ret);
}
-static int __devexit sdhci_pltfm_remove(struct platform_device *pdev)
+void sdhci_pltfm_free(struct platform_device *pdev)
{
- struct sdhci_pltfm_data *pdata = pdev->dev.platform_data;
struct sdhci_host *host = platform_get_drvdata(pdev);
struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- int dead;
- u32 scratch;
-
- dead = 0;
- scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
- if (scratch == (u32)-1)
- dead = 1;
- sdhci_remove_host(host, dead);
- if (pdata && pdata->exit)
- pdata->exit(host);
iounmap(host->ioaddr);
release_mem_region(iomem->start, resource_size(iomem));
sdhci_free_host(host);
platform_set_drvdata(pdev, NULL);
+}
- return 0;
+int sdhci_pltfm_register(struct platform_device *pdev,
+ struct sdhci_pltfm_data *pdata)
+{
+ struct sdhci_host *host;
+ int ret = 0;
+
+ host = sdhci_pltfm_init(pdev, pdata);
+ if (IS_ERR(host))
+ return PTR_ERR(host);
+
+ ret = sdhci_add_host(host);
+ if (ret)
+ sdhci_pltfm_free(pdev);
+
+ return ret;
}
-static const struct platform_device_id sdhci_pltfm_ids[] = {
- { "sdhci", },
-#ifdef CONFIG_MMC_SDHCI_CNS3XXX
- { "sdhci-cns3xxx", (kernel_ulong_t)&sdhci_cns3xxx_pdata },
-#endif
-#ifdef CONFIG_MMC_SDHCI_ESDHC_IMX
- { "sdhci-esdhc-imx", (kernel_ulong_t)&sdhci_esdhc_imx_pdata },
-#endif
-#ifdef CONFIG_MMC_SDHCI_DOVE
- { "sdhci-dove", (kernel_ulong_t)&sdhci_dove_pdata },
-#endif
-#ifdef CONFIG_MMC_SDHCI_TEGRA
- { "sdhci-tegra", (kernel_ulong_t)&sdhci_tegra_pdata },
-#endif
- { },
-};
-MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids);
+int sdhci_pltfm_unregister(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+ sdhci_remove_host(host, dead);
+ sdhci_pltfm_free(pdev);
+
+ return 0;
+}
#ifdef CONFIG_PM
-static int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state)
+int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state)
{
struct sdhci_host *host = platform_get_drvdata(dev);
return sdhci_suspend_host(host, state);
}
-static int sdhci_pltfm_resume(struct platform_device *dev)
+int sdhci_pltfm_resume(struct platform_device *dev)
{
struct sdhci_host *host = platform_get_drvdata(dev);
return sdhci_resume_host(host);
}
-#else
-#define sdhci_pltfm_suspend NULL
-#define sdhci_pltfm_resume NULL
#endif /* CONFIG_PM */
-
-static struct platform_driver sdhci_pltfm_driver = {
- .driver = {
- .name = "sdhci",
- .owner = THIS_MODULE,
- },
- .probe = sdhci_pltfm_probe,
- .remove = __devexit_p(sdhci_pltfm_remove),
- .id_table = sdhci_pltfm_ids,
- .suspend = sdhci_pltfm_suspend,
- .resume = sdhci_pltfm_resume,
-};
-
-/*****************************************************************************\
- * *
- * Driver init/exit *
- * *
-\*****************************************************************************/
-
-static int __init sdhci_drv_init(void)
-{
- return platform_driver_register(&sdhci_pltfm_driver);
-}
-
-static void __exit sdhci_drv_exit(void)
-{
- platform_driver_unregister(&sdhci_pltfm_driver);
-}
-
-module_init(sdhci_drv_init);
-module_exit(sdhci_drv_exit);
-
-MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver");
-MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
index 2b37016..ff4b7eb 100644
--- a/drivers/mmc/host/sdhci-pltfm.h
+++ b/drivers/mmc/host/sdhci-pltfm.h
@@ -13,6 +13,7 @@
#include <linux/clk.h>
#include <linux/types.h>
+#include <linux/platform_device.h>
#include <linux/mmc/sdhci-pltfm.h>
struct sdhci_pltfm_host {
@@ -20,9 +21,17 @@ struct sdhci_pltfm_host {
void *priv; /* to handle quirks across io-accessor calls */
};
-extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata;
-extern struct sdhci_pltfm_data sdhci_esdhc_imx_pdata;
-extern struct sdhci_pltfm_data sdhci_dove_pdata;
-extern struct sdhci_pltfm_data sdhci_tegra_pdata;
+extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
+ struct sdhci_pltfm_data *pdata);
+extern void sdhci_pltfm_free(struct platform_device *pdev);
+
+extern int sdhci_pltfm_register(struct platform_device *pdev,
+ struct sdhci_pltfm_data *pdata);
+extern int sdhci_pltfm_unregister(struct platform_device *pdev);
+
+#ifdef CONFIG_PM
+extern int sdhci_pltfm_suspend(struct platform_device *dev, pm_message_t state);
+extern int sdhci_pltfm_resume(struct platform_device *dev);
+#endif
#endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 343c97e..95fce3d 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -116,20 +116,42 @@ static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width)
return 0;
}
+static struct sdhci_ops tegra_sdhci_ops = {
+ .get_ro = tegra_sdhci_get_ro,
+ .read_l = tegra_sdhci_readl,
+ .read_w = tegra_sdhci_readw,
+ .write_l = tegra_sdhci_writel,
+ .platform_8bit_width = tegra_sdhci_8bit,
+};
+
+static struct sdhci_pltfm_data sdhci_tegra_pdata = {
+ .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+ SDHCI_QUIRK_SINGLE_POWER_WRITE |
+ SDHCI_QUIRK_NO_HISPD_BIT |
+ SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
+ .ops = &tegra_sdhci_ops,
+};
-static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
- struct sdhci_pltfm_data *pdata)
+static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+ struct sdhci_pltfm_host *pltfm_host;
struct tegra_sdhci_platform_data *plat;
+ struct sdhci_host *host;
struct clk *clk;
int rc;
+ host = sdhci_pltfm_init(pdev, &sdhci_tegra_pdata);
+ if (IS_ERR(host))
+ return PTR_ERR(host);
+
+ pltfm_host = sdhci_priv(host);
+
plat = pdev->dev.platform_data;
+
if (plat == NULL) {
dev_err(mmc_dev(host->mmc), "missing platform data\n");
- return -ENXIO;
+ rc = -ENXIO;
+ goto err_no_plat;
}
if (gpio_is_valid(plat->power_gpio)) {
@@ -137,7 +159,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (rc) {
dev_err(mmc_dev(host->mmc),
"failed to allocate power gpio\n");
- goto out;
+ goto err_power_req;
}
tegra_gpio_enable(plat->power_gpio);
gpio_direction_output(plat->power_gpio, 1);
@@ -148,7 +170,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (rc) {
dev_err(mmc_dev(host->mmc),
"failed to allocate cd gpio\n");
- goto out_power;
+ goto err_cd_req;
}
tegra_gpio_enable(plat->cd_gpio);
gpio_direction_input(plat->cd_gpio);
@@ -159,7 +181,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (rc) {
dev_err(mmc_dev(host->mmc), "request irq error\n");
- goto out_cd;
+ goto err_cd_irq_req;
}
}
@@ -169,7 +191,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (rc) {
dev_err(mmc_dev(host->mmc),
"failed to allocate wp gpio\n");
- goto out_irq;
+ goto err_wp_req;
}
tegra_gpio_enable(plat->wp_gpio);
gpio_direction_input(plat->wp_gpio);
@@ -179,7 +201,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (IS_ERR(clk)) {
dev_err(mmc_dev(host->mmc), "clk err\n");
rc = PTR_ERR(clk);
- goto out_wp;
+ goto err_clk_get;
}
clk_enable(clk);
pltfm_host->clk = clk;
@@ -189,38 +211,47 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
if (plat->is_8bit)
host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+ rc = sdhci_add_host(host);
+ if (rc)
+ goto err_add_host;
+
return 0;
-out_wp:
+err_add_host:
+ clk_disable(pltfm_host->clk);
+ clk_put(pltfm_host->clk);
+err_clk_get:
if (gpio_is_valid(plat->wp_gpio)) {
tegra_gpio_disable(plat->wp_gpio);
gpio_free(plat->wp_gpio);
}
-
-out_irq:
+err_wp_req:
if (gpio_is_valid(plat->cd_gpio))
free_irq(gpio_to_irq(plat->cd_gpio), host);
-out_cd:
+err_cd_irq_req:
if (gpio_is_valid(plat->cd_gpio)) {
tegra_gpio_disable(plat->cd_gpio);
gpio_free(plat->cd_gpio);
}
-
-out_power:
+err_cd_req:
if (gpio_is_valid(plat->power_gpio)) {
tegra_gpio_disable(plat->power_gpio);
gpio_free(plat->power_gpio);
}
-
-out:
+err_power_req:
+err_no_plat:
+ sdhci_pltfm_free(pdev);
return rc;
}
-static void tegra_sdhci_pltfm_exit(struct sdhci_host *host)
+static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
- struct tegra_sdhci_platform_data *plat;
+ struct tegra_sdhci_platform_data *plat;
+ int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+ sdhci_remove_host(host, dead);
plat = pdev->dev.platform_data;
@@ -242,22 +273,37 @@ static void tegra_sdhci_pltfm_exit(struct sdhci_host *host)
clk_disable(pltfm_host->clk);
clk_put(pltfm_host->clk);
+
+ sdhci_pltfm_free(pdev);
+
+ return 0;
}
-static struct sdhci_ops tegra_sdhci_ops = {
- .get_ro = tegra_sdhci_get_ro,
- .read_l = tegra_sdhci_readl,
- .read_w = tegra_sdhci_readw,
- .write_l = tegra_sdhci_writel,
- .platform_8bit_width = tegra_sdhci_8bit,
+static struct platform_driver sdhci_tegra_driver = {
+ .driver = {
+ .name = "sdhci-tegra",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdhci_tegra_probe,
+ .remove = __devexit_p(sdhci_tegra_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
};
-struct sdhci_pltfm_data sdhci_tegra_pdata = {
- .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
- SDHCI_QUIRK_SINGLE_POWER_WRITE |
- SDHCI_QUIRK_NO_HISPD_BIT |
- SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
- .ops = &tegra_sdhci_ops,
- .init = tegra_sdhci_pltfm_init,
- .exit = tegra_sdhci_pltfm_exit,
-};
+static int __init sdhci_tegra_init(void)
+{
+ return platform_driver_register(&sdhci_tegra_driver);
+}
+module_init(sdhci_tegra_init);
+
+static void __exit sdhci_tegra_exit(void)
+{
+ platform_driver_unregister(&sdhci_tegra_driver);
+}
+module_exit(sdhci_tegra_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for Tegra");
+MODULE_AUTHOR(" Google, Inc.");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mmc/sdhci-pltfm.h b/include/linux/mmc/sdhci-pltfm.h
index 548d59d..f1c2ac3 100644
--- a/include/linux/mmc/sdhci-pltfm.h
+++ b/include/linux/mmc/sdhci-pltfm.h
@@ -15,21 +15,15 @@
#define _SDHCI_PLTFM_H
struct sdhci_ops;
-struct sdhci_host;
/**
* struct sdhci_pltfm_data - SDHCI platform-specific information & hooks
* @ops: optional pointer to the platform-provided SDHCI ops
* @quirks: optional SDHCI quirks
- * @init: optional hook that is called during device probe, before the
- * driver tries to access any SDHCI registers
- * @exit: optional hook that is called during device removal
*/
struct sdhci_pltfm_data {
struct sdhci_ops *ops;
unsigned int quirks;
- int (*init)(struct sdhci_host *host, struct sdhci_pltfm_data *pdata);
- void (*exit)(struct sdhci_host *host);
};
#endif /* _SDHCI_PLTFM_H */
--
1.7.4.1
^ permalink raw reply related
* [PATCH v2 2/7] mmc: sdhci: eliminate sdhci_of_host and sdhci_of_data
From: Shawn Guo @ 2011-05-05 13:22 UTC (permalink / raw)
To: linux-mmc
Cc: Chris Ball, sameo, Arnd Bergmann, patches, Shawn Guo,
devicetree-discuss, Saeed Bishara, Xiaobo Xie, kernel,
Mike Rapoport, Olof Johansson, Anton Vorontsov, linuxppc-dev,
Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-1-git-send-email-shawn.guo@linaro.org>
The patch migrates the use of sdhci_of_host and sdhci_of_data to
sdhci_pltfm_host and sdhci_pltfm_data, so that the former pair can
be eliminated.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
---
drivers/mmc/host/sdhci-of-core.c | 30 +++++++++++++++---------------
drivers/mmc/host/sdhci-of-esdhc.c | 36 +++++++++++++++++++-----------------
drivers/mmc/host/sdhci-of-hlwd.c | 20 +++++++++++---------
drivers/mmc/host/sdhci-of.h | 15 +++------------
drivers/mmc/host/sdhci-pltfm.h | 4 ++++
5 files changed, 52 insertions(+), 53 deletions(-)
diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c
index f9b611f..6b2de9e 100644
--- a/drivers/mmc/host/sdhci-of-core.c
+++ b/drivers/mmc/host/sdhci-of-core.c
@@ -59,7 +59,7 @@ void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg)
void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg)
{
- struct sdhci_of_host *of_host = sdhci_priv(host);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
int base = reg & ~0x3;
int shift = (reg & 0x2) * 8;
@@ -69,10 +69,10 @@ void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg)
* Postpone this write, we must do it together with a
* command write that is down below.
*/
- of_host->xfer_mode_shadow = val;
+ pltfm_host->xfer_mode_shadow = val;
return;
case SDHCI_COMMAND:
- sdhci_be32bs_writel(host, val << 16 | of_host->xfer_mode_shadow,
+ sdhci_be32bs_writel(host, val << 16 | pltfm_host->xfer_mode_shadow,
SDHCI_TRANSFER_MODE);
return;
}
@@ -127,7 +127,7 @@ static bool __devinit sdhci_of_wp_inverted(struct device_node *np)
static int __devinit sdhci_of_probe(struct platform_device *ofdev)
{
struct device_node *np = ofdev->dev.of_node;
- struct sdhci_of_data *sdhci_of_data;
+ struct sdhci_pltfm_data *pdata;
struct sdhci_host *host;
struct sdhci_of_host *of_host;
const __be32 *clk;
@@ -136,16 +136,16 @@ static int __devinit sdhci_of_probe(struct platform_device *ofdev)
if (!ofdev->dev.of_match)
return -EINVAL;
- sdhci_of_data = ofdev->dev.of_match->data;
+ pdata = ofdev->dev.of_match->data;
if (!of_device_is_available(np))
return -ENODEV;
- host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host));
+ host = sdhci_alloc_host(&ofdev->dev, sizeof(*pltfm_host));
if (IS_ERR(host))
return -ENOMEM;
- of_host = sdhci_priv(host);
+ pltfm_host = sdhci_priv(host);
dev_set_drvdata(&ofdev->dev, host);
host->ioaddr = of_iomap(np, 0);
@@ -161,9 +161,9 @@ static int __devinit sdhci_of_probe(struct platform_device *ofdev)
}
host->hw_name = dev_name(&ofdev->dev);
- if (sdhci_of_data) {
- host->quirks = sdhci_of_data->quirks;
- host->ops = &sdhci_of_data->ops;
+ if (pdata) {
+ host->quirks = pdata->quirks;
+ host->ops = &pdata->ops;
}
if (of_get_property(np, "sdhci,auto-cmd12", NULL))
@@ -178,7 +178,7 @@ static int __devinit sdhci_of_probe(struct platform_device *ofdev)
clk = of_get_property(np, "clock-frequency", &size);
if (clk && size == sizeof(*clk) && *clk)
- of_host->clock = be32_to_cpup(clk);
+ pltfm_host->clock = be32_to_cpup(clk);
ret = sdhci_add_host(host);
if (ret)
@@ -208,12 +208,12 @@ static int __devexit sdhci_of_remove(struct platform_device *ofdev)
static const struct of_device_id sdhci_of_match[] = {
#ifdef CONFIG_MMC_SDHCI_OF_ESDHC
- { .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, },
- { .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, },
- { .compatible = "fsl,esdhc", .data = &sdhci_esdhc, },
+ { .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc_pdata, },
+ { .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc_pdata, },
+ { .compatible = "fsl,esdhc", .data = &sdhci_esdhc_pdata, },
#endif
#ifdef CONFIG_MMC_SDHCI_OF_HLWD
- { .compatible = "nintendo,hollywood-sdhci", .data = &sdhci_hlwd, },
+ { .compatible = "nintendo,hollywood-sdhci", .data = &sdhci_hlwd_pdata, },
#endif
{ .compatible = "generic-sdhci", },
{},
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index ba40d6d..492bcd7 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -60,32 +60,34 @@ static int esdhc_of_enable_dma(struct sdhci_host *host)
static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host)
{
- struct sdhci_of_host *of_host = sdhci_priv(host);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- return of_host->clock;
+ return pltfm_host->clock;
}
static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
{
- struct sdhci_of_host *of_host = sdhci_priv(host);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- return of_host->clock / 256 / 16;
+ return pltfm_host->clock / 256 / 16;
}
-struct sdhci_of_data sdhci_esdhc = {
+static struct sdhci_ops sdhci_esdhc_ops = {
+ .read_l = sdhci_be32bs_readl,
+ .read_w = esdhc_readw,
+ .read_b = sdhci_be32bs_readb,
+ .write_l = sdhci_be32bs_writel,
+ .write_w = esdhc_writew,
+ .write_b = esdhc_writeb,
+ .set_clock = esdhc_set_clock,
+ .enable_dma = esdhc_of_enable_dma,
+ .get_max_clock = esdhc_of_get_max_clock,
+ .get_min_clock = esdhc_of_get_min_clock,
+};
+
+struct sdhci_pltfm_data sdhci_esdhc_pdata = {
/* card detection could be handled via GPIO */
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
| SDHCI_QUIRK_NO_CARD_NO_RESET,
- .ops = {
- .read_l = sdhci_be32bs_readl,
- .read_w = esdhc_readw,
- .read_b = sdhci_be32bs_readb,
- .write_l = sdhci_be32bs_writel,
- .write_w = esdhc_writew,
- .write_b = esdhc_writeb,
- .set_clock = esdhc_set_clock,
- .enable_dma = esdhc_of_enable_dma,
- .get_max_clock = esdhc_of_get_max_clock,
- .get_min_clock = esdhc_of_get_min_clock,
- },
+ .ops = &sdhci_esdhc_ops,
};
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
index 68ddb75..380e896 100644
--- a/drivers/mmc/host/sdhci-of-hlwd.c
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -51,15 +51,17 @@ static void sdhci_hlwd_writeb(struct sdhci_host *host, u8 val, int reg)
udelay(SDHCI_HLWD_WRITE_DELAY);
}
-struct sdhci_of_data sdhci_hlwd = {
+static struct sdhci_ops sdhci_hlwd_ops = {
+ .read_l = sdhci_be32bs_readl,
+ .read_w = sdhci_be32bs_readw,
+ .read_b = sdhci_be32bs_readb,
+ .write_l = sdhci_hlwd_writel,
+ .write_w = sdhci_hlwd_writew,
+ .write_b = sdhci_hlwd_writeb,
+};
+
+struct sdhci_pltfm_data sdhci_hlwd_pdata = {
.quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
SDHCI_QUIRK_32BIT_DMA_SIZE,
- .ops = {
- .read_l = sdhci_be32bs_readl,
- .read_w = sdhci_be32bs_readw,
- .read_b = sdhci_be32bs_readb,
- .write_l = sdhci_hlwd_writel,
- .write_w = sdhci_hlwd_writew,
- .write_b = sdhci_hlwd_writeb,
- },
+ .ops = &sdhci_hlwd_ops,
};
diff --git a/drivers/mmc/host/sdhci-of.h b/drivers/mmc/host/sdhci-of.h
index ad09ad9..5bdb5e7 100644
--- a/drivers/mmc/host/sdhci-of.h
+++ b/drivers/mmc/host/sdhci-of.h
@@ -18,16 +18,7 @@
#include <linux/types.h>
#include "sdhci.h"
-
-struct sdhci_of_data {
- unsigned int quirks;
- struct sdhci_ops ops;
-};
-
-struct sdhci_of_host {
- unsigned int clock;
- u16 xfer_mode_shadow;
-};
+#include "sdhci-pltfm.h"
extern u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg);
extern u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg);
@@ -36,7 +27,7 @@ extern void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg);
extern void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg);
extern void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg);
-extern struct sdhci_of_data sdhci_esdhc;
-extern struct sdhci_of_data sdhci_hlwd;
+extern struct sdhci_pltfm_data sdhci_esdhc_pdata;
+extern struct sdhci_pltfm_data sdhci_hlwd_pdata;
#endif /* __SDHCI_OF_H */
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
index ff4b7eb..3cac450 100644
--- a/drivers/mmc/host/sdhci-pltfm.h
+++ b/drivers/mmc/host/sdhci-pltfm.h
@@ -19,6 +19,10 @@
struct sdhci_pltfm_host {
struct clk *clk;
void *priv; /* to handle quirks across io-accessor calls */
+
+ /* migrate from sdhci_of_host */
+ unsigned int clock;
+ u16 xfer_mode_shadow;
};
extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
--
1.7.4.1
^ permalink raw reply related
* [PATCH v2 3/7] mmc: sdhci: make sdhci-of device drivers self registered
From: Shawn Guo @ 2011-05-05 13:22 UTC (permalink / raw)
To: linux-mmc
Cc: Chris Ball, sameo, Arnd Bergmann, patches, Shawn Guo,
devicetree-discuss, Saeed Bishara, Xiaobo Xie, kernel,
Mike Rapoport, Olof Johansson, Anton Vorontsov, linuxppc-dev,
Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-1-git-send-email-shawn.guo@linaro.org>
The patch turns the sdhci-of-core common stuff into helper functions
added into sdhci-pltfm.c, and makes sdhci-of device drviers self
registered using the same pair of .probe and .remove used by
sdhci-pltfm device drivers.
As a result, sdhci-of-core.c and sdhci-of.h can be eliminated with
those common things merged into sdhci-pltfm.c and sdhci-pltfm.h
respectively.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
drivers/mmc/host/Kconfig | 15 +--
drivers/mmc/host/Makefile | 7 +-
drivers/mmc/host/sdhci-of-core.c | 250 -------------------------------------
drivers/mmc/host/sdhci-of-esdhc.c | 53 ++++++++-
drivers/mmc/host/sdhci-of-hlwd.c | 50 +++++++-
drivers/mmc/host/sdhci-of.h | 33 -----
drivers/mmc/host/sdhci-pltfm.c | 104 +++++++++++++++-
drivers/mmc/host/sdhci-pltfm.h | 12 ++
8 files changed, 220 insertions(+), 304 deletions(-)
delete mode 100644 drivers/mmc/host/sdhci-of-core.c
delete mode 100644 drivers/mmc/host/sdhci-of.h
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 799e935..fdd20ad 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -81,19 +81,11 @@ config MMC_RICOH_MMC
If unsure, say Y.
-config MMC_SDHCI_OF
- tristate "SDHCI support on OpenFirmware platforms"
- depends on MMC_SDHCI && OF
- help
- This selects the OF support for Secure Digital Host Controller
- Interfaces.
-
- If unsure, say N.
-
config MMC_SDHCI_OF_ESDHC
bool "SDHCI OF support for the Freescale eSDHC controller"
- depends on MMC_SDHCI_OF
+ depends on MMC_SDHCI
depends on PPC_OF
+ select MMC_SDHCI_PLTFM
select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
help
This selects the Freescale eSDHC controller support.
@@ -102,8 +94,9 @@ config MMC_SDHCI_OF_ESDHC
config MMC_SDHCI_OF_HLWD
bool "SDHCI OF support for the Nintendo Wii SDHCI controllers"
- depends on MMC_SDHCI_OF
+ depends on MMC_SDHCI
depends on PPC_OF
+ select MMC_SDHCI_PLTFM
select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
help
This selects the Secure Digital Host Controller Interface (SDHCI)
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 95fddb8..01d38a1 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -48,11 +48,8 @@ obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o
obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o
-
-obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o
-sdhci-of-y := sdhci-of-core.o
-sdhci-of-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o
-sdhci-of-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o
+obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o
+obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o
ifeq ($(CONFIG_CB710_DEBUG),y)
CFLAGS-cb710-mmc += -DDEBUG
diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c
deleted file mode 100644
index 6b2de9e..0000000
--- a/drivers/mmc/host/sdhci-of-core.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * OpenFirmware bindings for Secure Digital Host Controller Interface.
- *
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
- * Copyright (c) 2009 MontaVista Software, Inc.
- *
- * Authors: Xiaobo Xie <X.Xie@freescale.com>
- * 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/err.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/mmc/host.h>
-#ifdef CONFIG_PPC
-#include <asm/machdep.h>
-#endif
-#include "sdhci-of.h"
-#include "sdhci.h"
-
-#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
-
-/*
- * These accessors are designed for big endian hosts doing I/O to
- * little endian controllers incorporating a 32-bit hardware byte swapper.
- */
-
-u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg)
-{
- return in_be32(host->ioaddr + reg);
-}
-
-u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg)
-{
- return in_be16(host->ioaddr + (reg ^ 0x2));
-}
-
-u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg)
-{
- return in_8(host->ioaddr + (reg ^ 0x3));
-}
-
-void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg)
-{
- out_be32(host->ioaddr + reg, val);
-}
-
-void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- int base = reg & ~0x3;
- int shift = (reg & 0x2) * 8;
-
- switch (reg) {
- case SDHCI_TRANSFER_MODE:
- /*
- * Postpone this write, we must do it together with a
- * command write that is down below.
- */
- pltfm_host->xfer_mode_shadow = val;
- return;
- case SDHCI_COMMAND:
- sdhci_be32bs_writel(host, val << 16 | pltfm_host->xfer_mode_shadow,
- SDHCI_TRANSFER_MODE);
- return;
- }
- clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
-}
-
-void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
-{
- int base = reg & ~0x3;
- int shift = (reg & 0x3) * 8;
-
- clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
-}
-#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */
-
-#ifdef CONFIG_PM
-
-static int sdhci_of_suspend(struct platform_device *ofdev, pm_message_t state)
-{
- struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
- return mmc_suspend_host(host->mmc);
-}
-
-static int sdhci_of_resume(struct platform_device *ofdev)
-{
- struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
- return mmc_resume_host(host->mmc);
-}
-
-#else
-
-#define sdhci_of_suspend NULL
-#define sdhci_of_resume NULL
-
-#endif
-
-static bool __devinit sdhci_of_wp_inverted(struct device_node *np)
-{
- if (of_get_property(np, "sdhci,wp-inverted", NULL))
- return true;
-
- /* Old device trees don't have the wp-inverted property. */
-#ifdef CONFIG_PPC
- return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds);
-#else
- return false;
-#endif
-}
-
-static int __devinit sdhci_of_probe(struct platform_device *ofdev)
-{
- struct device_node *np = ofdev->dev.of_node;
- struct sdhci_pltfm_data *pdata;
- struct sdhci_host *host;
- struct sdhci_of_host *of_host;
- const __be32 *clk;
- int size;
- int ret;
-
- if (!ofdev->dev.of_match)
- return -EINVAL;
- pdata = ofdev->dev.of_match->data;
-
- if (!of_device_is_available(np))
- return -ENODEV;
-
- host = sdhci_alloc_host(&ofdev->dev, sizeof(*pltfm_host));
- if (IS_ERR(host))
- return -ENOMEM;
-
- pltfm_host = sdhci_priv(host);
- dev_set_drvdata(&ofdev->dev, host);
-
- host->ioaddr = of_iomap(np, 0);
- if (!host->ioaddr) {
- ret = -ENOMEM;
- goto err_addr_map;
- }
-
- host->irq = irq_of_parse_and_map(np, 0);
- if (!host->irq) {
- ret = -EINVAL;
- goto err_no_irq;
- }
-
- host->hw_name = dev_name(&ofdev->dev);
- if (pdata) {
- host->quirks = pdata->quirks;
- host->ops = &pdata->ops;
- }
-
- if (of_get_property(np, "sdhci,auto-cmd12", NULL))
- host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
-
-
- if (of_get_property(np, "sdhci,1-bit-only", NULL))
- host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
-
- if (sdhci_of_wp_inverted(np))
- host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
-
- clk = of_get_property(np, "clock-frequency", &size);
- if (clk && size == sizeof(*clk) && *clk)
- pltfm_host->clock = be32_to_cpup(clk);
-
- ret = sdhci_add_host(host);
- if (ret)
- goto err_add_host;
-
- return 0;
-
-err_add_host:
- irq_dispose_mapping(host->irq);
-err_no_irq:
- iounmap(host->ioaddr);
-err_addr_map:
- sdhci_free_host(host);
- return ret;
-}
-
-static int __devexit sdhci_of_remove(struct platform_device *ofdev)
-{
- struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
- sdhci_remove_host(host, 0);
- sdhci_free_host(host);
- irq_dispose_mapping(host->irq);
- iounmap(host->ioaddr);
- return 0;
-}
-
-static const struct of_device_id sdhci_of_match[] = {
-#ifdef CONFIG_MMC_SDHCI_OF_ESDHC
- { .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc_pdata, },
- { .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc_pdata, },
- { .compatible = "fsl,esdhc", .data = &sdhci_esdhc_pdata, },
-#endif
-#ifdef CONFIG_MMC_SDHCI_OF_HLWD
- { .compatible = "nintendo,hollywood-sdhci", .data = &sdhci_hlwd_pdata, },
-#endif
- { .compatible = "generic-sdhci", },
- {},
-};
-MODULE_DEVICE_TABLE(of, sdhci_of_match);
-
-static struct platform_driver sdhci_of_driver = {
- .driver = {
- .name = "sdhci-of",
- .owner = THIS_MODULE,
- .of_match_table = sdhci_of_match,
- },
- .probe = sdhci_of_probe,
- .remove = __devexit_p(sdhci_of_remove),
- .suspend = sdhci_of_suspend,
- .resume = sdhci_of_resume,
-};
-
-static int __init sdhci_of_init(void)
-{
- return platform_driver_register(&sdhci_of_driver);
-}
-module_init(sdhci_of_init);
-
-static void __exit sdhci_of_exit(void)
-{
- platform_driver_unregister(&sdhci_of_driver);
-}
-module_exit(sdhci_of_exit);
-
-MODULE_DESCRIPTION("Secure Digital Host Controller Interface OF driver");
-MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
- "Anton Vorontsov <avorontsov@ru.mvista.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 492bcd7..2db6a45 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -16,7 +16,7 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/mmc/host.h>
-#include "sdhci-of.h"
+#include "sdhci-pltfm.h"
#include "sdhci.h"
#include "sdhci-esdhc.h"
@@ -85,9 +85,58 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.get_min_clock = esdhc_of_get_min_clock,
};
-struct sdhci_pltfm_data sdhci_esdhc_pdata = {
+static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
/* card detection could be handled via GPIO */
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
| SDHCI_QUIRK_NO_CARD_NO_RESET,
.ops = &sdhci_esdhc_ops,
};
+
+static int __devinit sdhci_esdhc_probe(struct platform_device *pdev)
+{
+ return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata);
+}
+
+static int __devexit sdhci_esdhc_remove(struct platform_device *pdev)
+{
+ return sdhci_pltfm_unregister(pdev);
+}
+
+static const struct of_device_id sdhci_esdhc_of_match[] = {
+ { .compatible = "fsl,mpc8379-esdhc" },
+ { .compatible = "fsl,mpc8536-esdhc" },
+ { .compatible = "fsl,esdhc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match);
+
+static struct platform_driver sdhci_esdhc_driver = {
+ .driver = {
+ .name = "sdhci-esdhc",
+ .owner = THIS_MODULE,
+ .of_match_table = sdhci_esdhc_of_match,
+ },
+ .probe = sdhci_esdhc_probe,
+ .remove = __devexit_p(sdhci_esdhc_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
+};
+
+static int __init sdhci_esdhc_init(void)
+{
+ return platform_driver_register(&sdhci_esdhc_driver);
+}
+module_init(sdhci_esdhc_init);
+
+static void __exit sdhci_esdhc_exit(void)
+{
+ platform_driver_unregister(&sdhci_esdhc_driver);
+}
+module_exit(sdhci_esdhc_exit);
+
+MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC");
+MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
+ "Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
index 380e896..faedfce 100644
--- a/drivers/mmc/host/sdhci-of-hlwd.c
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -21,7 +21,7 @@
#include <linux/delay.h>
#include <linux/mmc/host.h>
-#include "sdhci-of.h"
+#include "sdhci-pltfm.h"
#include "sdhci.h"
/*
@@ -60,8 +60,54 @@ static struct sdhci_ops sdhci_hlwd_ops = {
.write_b = sdhci_hlwd_writeb,
};
-struct sdhci_pltfm_data sdhci_hlwd_pdata = {
+static struct sdhci_pltfm_data sdhci_hlwd_pdata = {
.quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
SDHCI_QUIRK_32BIT_DMA_SIZE,
.ops = &sdhci_hlwd_ops,
};
+
+static int __devinit sdhci_hlwd_probe(struct platform_device *pdev)
+{
+ return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata);
+}
+
+static int __devexit sdhci_hlwd_remove(struct platform_device *pdev)
+{
+ return sdhci_pltfm_unregister(pdev);
+}
+
+static const struct of_device_id sdhci_hlwd_of_match[] = {
+ { .compatible = "nintendo,hollywood-sdhci" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sdhci_hlwd_of_match);
+
+static struct platform_driver sdhci_hlwd_driver = {
+ .driver = {
+ .name = "sdhci-hlwd",
+ .owner = THIS_MODULE,
+ .of_match_table = sdhci_hlwd_of_match,
+ },
+ .probe = sdhci_hlwd_probe,
+ .remove = __devexit_p(sdhci_hlwd_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
+};
+
+static int __init sdhci_hlwd_init(void)
+{
+ return platform_driver_register(&sdhci_hlwd_driver);
+}
+module_init(sdhci_hlwd_init);
+
+static void __exit sdhci_hlwd_exit(void)
+{
+ platform_driver_unregister(&sdhci_hlwd_driver);
+}
+module_exit(sdhci_hlwd_exit);
+
+MODULE_DESCRIPTION("Nintendo Wii SDHCI OF driver");
+MODULE_AUTHOR("The GameCube Linux Team, Albert Herranz");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-of.h b/drivers/mmc/host/sdhci-of.h
deleted file mode 100644
index 5bdb5e7..0000000
--- a/drivers/mmc/host/sdhci-of.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * OpenFirmware bindings for Secure Digital Host Controller Interface.
- *
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
- * Copyright (c) 2009 MontaVista Software, Inc.
- *
- * Authors: Xiaobo Xie <X.Xie@freescale.com>
- * 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.
- */
-
-#ifndef __SDHCI_OF_H
-#define __SDHCI_OF_H
-
-#include <linux/types.h>
-#include "sdhci.h"
-#include "sdhci-pltfm.h"
-
-extern u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg);
-extern u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg);
-extern u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg);
-extern void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg);
-extern void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg);
-extern void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg);
-
-extern struct sdhci_pltfm_data sdhci_esdhc_pdata;
-extern struct sdhci_pltfm_data sdhci_hlwd_pdata;
-
-#endif /* __SDHCI_OF_H */
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 8ccf256..4b22db2 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -23,13 +23,113 @@
*/
#include <linux/err.h>
-
+#include <linux/of.h>
+#ifdef CONFIG_PPC
+#include <asm/machdep.h>
+#endif
#include "sdhci.h"
#include "sdhci-pltfm.h"
static struct sdhci_ops sdhci_pltfm_ops = {
};
+#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+/*
+ * These accessors are designed for big endian hosts doing I/O to
+ * little endian controllers incorporating a 32-bit hardware byte swapper.
+ */
+u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg)
+{
+ return in_be32(host->ioaddr + reg);
+}
+
+u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg)
+{
+ return in_be16(host->ioaddr + (reg ^ 0x2));
+}
+
+u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg)
+{
+ return in_8(host->ioaddr + (reg ^ 0x3));
+}
+
+void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg)
+{
+ out_be32(host->ioaddr + reg, val);
+}
+
+void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ int base = reg & ~0x3;
+ int shift = (reg & 0x2) * 8;
+
+ switch (reg) {
+ case SDHCI_TRANSFER_MODE:
+ /*
+ * Postpone this write, we must do it together with a
+ * command write that is down below.
+ */
+ pltfm_host->xfer_mode_shadow = val;
+ return;
+ case SDHCI_COMMAND:
+ sdhci_be32bs_writel(host, val << 16 | pltfm_host->xfer_mode_shadow,
+ SDHCI_TRANSFER_MODE);
+ return;
+ }
+ clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
+}
+
+void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+ int base = reg & ~0x3;
+ int shift = (reg & 0x3) * 8;
+
+ clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
+}
+#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */
+
+#ifdef CONFIG_OF
+static bool sdhci_of_wp_inverted(struct device_node *np)
+{
+ if (of_get_property(np, "sdhci,wp-inverted", NULL))
+ return true;
+
+ /* Old device trees don't have the wp-inverted property. */
+#ifdef CONFIG_PPC
+ return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds);
+#else
+ return false;
+#endif
+}
+
+void sdhci_get_of_property(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ const __be32 *clk;
+ int size;
+
+ if (of_device_is_available(np)) {
+ if (of_get_property(np, "sdhci,auto-cmd12", NULL))
+ host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+
+ if (of_get_property(np, "sdhci,1-bit-only", NULL))
+ host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
+
+ if (sdhci_of_wp_inverted(np))
+ host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
+
+ clk = of_get_property(np, "clock-frequency", &size);
+ if (clk && size == sizeof(*clk) && *clk)
+ pltfm_host->clock = be32_to_cpup(clk);
+ }
+}
+#else
+void sdhci_get_of_property(struct platform_device *pdev) {}
+#endif
+
struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
struct sdhci_pltfm_data *pdata)
{
@@ -117,6 +217,8 @@ int sdhci_pltfm_register(struct platform_device *pdev,
if (IS_ERR(host))
return PTR_ERR(host);
+ sdhci_get_of_property(pdev);
+
ret = sdhci_add_host(host);
if (ret)
sdhci_pltfm_free(pdev);
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
index 3cac450..fe27b83 100644
--- a/drivers/mmc/host/sdhci-pltfm.h
+++ b/drivers/mmc/host/sdhci-pltfm.h
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/mmc/sdhci-pltfm.h>
+#include <linux/mmc/sdhci.h>
struct sdhci_pltfm_host {
struct clk *clk;
@@ -25,6 +26,17 @@ struct sdhci_pltfm_host {
u16 xfer_mode_shadow;
};
+#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+extern u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg);
+extern u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg);
+extern u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg);
+extern void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg);
+extern void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg);
+extern void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg);
+#endif
+
+extern void sdhci_get_of_property(struct platform_device *pdev);
+
extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
struct sdhci_pltfm_data *pdata);
extern void sdhci_pltfm_free(struct platform_device *pdev);
--
1.7.4.1
^ permalink raw reply related
* [PATCH v2 4/7] sdhci: rename sdhci-esdhc-imx.c to sdhci-esdhc.c
From: Shawn Guo @ 2011-05-05 13:22 UTC (permalink / raw)
To: linux-mmc
Cc: Chris Ball, sameo, Arnd Bergmann, patches, Shawn Guo,
devicetree-discuss, Saeed Bishara, Xiaobo Xie, kernel,
Mike Rapoport, Olof Johansson, Anton Vorontsov, linuxppc-dev,
Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-1-git-send-email-shawn.guo@linaro.org>
The patch renames the file to prepare for the consolidation
sdhci-of-esdhc and sdhci-esdhc-imx.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
drivers/mmc/host/Makefile | 2 +-
drivers/mmc/host/sdhci-esdhc-imx.c | 381 ------------------------------------
drivers/mmc/host/sdhci-esdhc.c | 381 ++++++++++++++++++++++++++++++++++++
3 files changed, 382 insertions(+), 382 deletions(-)
delete mode 100644 drivers/mmc/host/sdhci-esdhc-imx.c
create mode 100644 drivers/mmc/host/sdhci-esdhc.c
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 01d38a1..186f0ed 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -45,7 +45,7 @@ obj-$(CONFIG_MMC_USHC) += ushc.o
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
-obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o
+obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc.o
obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o
obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o
obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
deleted file mode 100644
index 8da57d4..0000000
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Freescale eSDHC i.MX controller driver for the platform bus.
- *
- * derived from the OF-version.
- *
- * Copyright (c) 2010 Pengutronix e.K.
- * Author: Wolfram Sang <w.sang@pengutronix.de>
- *
- * 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.
- */
-
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sdhci-pltfm.h>
-#include <linux/mmc/mmc.h>
-#include <linux/mmc/sdio.h>
-#include <mach/hardware.h>
-#include <mach/esdhc.h>
-#include "sdhci.h"
-#include "sdhci-pltfm.h"
-#include "sdhci-esdhc.h"
-
-/* VENDOR SPEC register */
-#define SDHCI_VENDOR_SPEC 0xC0
-#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
-
-#define ESDHC_FLAG_GPIO_FOR_CD_WP (1 << 0)
-/*
- * The CMDTYPE of the CMD register (offset 0xE) should be set to
- * "11" when the STOP CMD12 is issued on imx53 to abort one
- * open ended multi-blk IO. Otherwise the TC INT wouldn't
- * be generated.
- * In exact block transfer, the controller doesn't complete the
- * operations automatically as required at the end of the
- * transfer and remains on hold if the abort command is not sent.
- * As a result, the TC flag is not asserted and SW received timeout
- * exeception. Bit1 of Vendor Spec registor is used to fix it.
- */
-#define ESDHC_FLAG_MULTIBLK_NO_INT (1 << 1)
-
-struct pltfm_imx_data {
- int flags;
- u32 scratchpad;
-};
-
-static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
-{
- void __iomem *base = host->ioaddr + (reg & ~0x3);
- u32 shift = (reg & 0x3) * 8;
-
- writel(((readl(base) & ~(mask << shift)) | (val << shift)), base);
-}
-
-static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct pltfm_imx_data *imx_data = pltfm_host->priv;
-
- /* fake CARD_PRESENT flag on mx25/35 */
- u32 val = readl(host->ioaddr + reg);
-
- if (unlikely((reg == SDHCI_PRESENT_STATE)
- && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) {
- struct esdhc_platform_data *boarddata =
- host->mmc->parent->platform_data;
-
- if (boarddata && gpio_is_valid(boarddata->cd_gpio)
- && gpio_get_value(boarddata->cd_gpio))
- /* no card, if a valid gpio says so... */
- val &= SDHCI_CARD_PRESENT;
- else
- /* ... in all other cases assume card is present */
- val |= SDHCI_CARD_PRESENT;
- }
-
- return val;
-}
-
-static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct pltfm_imx_data *imx_data = pltfm_host->priv;
-
- if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
- && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP)))
- /*
- * these interrupts won't work with a custom card_detect gpio
- * (only applied to mx25/35)
- */
- val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
-
- if (unlikely((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
- && (reg == SDHCI_INT_STATUS)
- && (val & SDHCI_INT_DATA_END))) {
- u32 v;
- v = readl(host->ioaddr + SDHCI_VENDOR_SPEC);
- v &= ~SDHCI_VENDOR_SPEC_SDIO_QUIRK;
- writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
- }
-
- writel(val, host->ioaddr + reg);
-}
-
-static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
-{
- if (unlikely(reg == SDHCI_HOST_VERSION))
- reg ^= 2;
-
- return readw(host->ioaddr + reg);
-}
-
-static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct pltfm_imx_data *imx_data = pltfm_host->priv;
-
- switch (reg) {
- case SDHCI_TRANSFER_MODE:
- /*
- * Postpone this write, we must do it together with a
- * command write that is down below.
- */
- if ((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
- && (host->cmd->opcode == SD_IO_RW_EXTENDED)
- && (host->cmd->data->blocks > 1)
- && (host->cmd->data->flags & MMC_DATA_READ)) {
- u32 v;
- v = readl(host->ioaddr + SDHCI_VENDOR_SPEC);
- v |= SDHCI_VENDOR_SPEC_SDIO_QUIRK;
- writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
- }
- imx_data->scratchpad = val;
- return;
- case SDHCI_COMMAND:
- if ((host->cmd->opcode == MMC_STOP_TRANSMISSION)
- && (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
- val |= SDHCI_CMD_ABORTCMD;
- writel(val << 16 | imx_data->scratchpad,
- host->ioaddr + SDHCI_TRANSFER_MODE);
- return;
- case SDHCI_BLOCK_SIZE:
- val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
- break;
- }
- esdhc_clrset_le(host, 0xffff, val, reg);
-}
-
-static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
-{
- u32 new_val;
-
- switch (reg) {
- case SDHCI_POWER_CONTROL:
- /*
- * FSL put some DMA bits here
- * If your board has a regulator, code should be here
- */
- return;
- case SDHCI_HOST_CONTROL:
- /* FSL messed up here, so we can just keep those two */
- new_val = val & (SDHCI_CTRL_LED | SDHCI_CTRL_4BITBUS);
- /* ensure the endianess */
- new_val |= ESDHC_HOST_CONTROL_LE;
- /* DMA mode bits are shifted */
- new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5;
-
- esdhc_clrset_le(host, 0xffff, new_val, reg);
- return;
- }
- esdhc_clrset_le(host, 0xff, val, reg);
-}
-
-static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-
- return clk_get_rate(pltfm_host->clk);
-}
-
-static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-
- return clk_get_rate(pltfm_host->clk) / 256 / 16;
-}
-
-static struct sdhci_ops sdhci_esdhc_ops = {
- .read_l = esdhc_readl_le,
- .read_w = esdhc_readw_le,
- .write_l = esdhc_writel_le,
- .write_w = esdhc_writew_le,
- .write_b = esdhc_writeb_le,
- .set_clock = esdhc_set_clock,
- .get_max_clock = esdhc_pltfm_get_max_clock,
- .get_min_clock = esdhc_pltfm_get_min_clock,
-};
-
-static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
- .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
- | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
- /* ADMA has issues. Might be fixable */
- .ops = &sdhci_esdhc_ops,
-};
-
-static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
-{
- struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
-
- if (boarddata && gpio_is_valid(boarddata->wp_gpio))
- return gpio_get_value(boarddata->wp_gpio);
- else
- return -ENOSYS;
-}
-
-static irqreturn_t cd_irq(int irq, void *data)
-{
- struct sdhci_host *sdhost = (struct sdhci_host *)data;
-
- tasklet_schedule(&sdhost->card_tasklet);
- return IRQ_HANDLED;
-};
-
-static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
-{
- struct sdhci_pltfm_host *pltfm_host;
- struct sdhci_host *host;
- struct esdhc_platform_data *boarddata;
- struct clk *clk;
- int err;
- struct pltfm_imx_data *imx_data;
-
- host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata);
- if (IS_ERR(host))
- return PTR_ERR(host);
-
- pltfm_host = sdhci_priv(host);
-
- imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
- if (!imx_data)
- return -ENOMEM;
- pltfm_host->priv = imx_data;
-
- clk = clk_get(mmc_dev(host->mmc), NULL);
- if (IS_ERR(clk)) {
- dev_err(mmc_dev(host->mmc), "clk err\n");
- err = PTR_ERR(clk);
- goto err_clk_get;
- }
- clk_enable(clk);
- pltfm_host->clk = clk;
-
- if (!cpu_is_mx25())
- host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
-
- if (cpu_is_mx25() || cpu_is_mx35()) {
- /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
- host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
- /* write_protect can't be routed to controller, use gpio */
- sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
- }
-
- if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
- imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
-
- boarddata = host->mmc->parent->platform_data;
- if (boarddata) {
- err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
- if (err) {
- dev_warn(mmc_dev(host->mmc),
- "no write-protect pin available!\n");
- boarddata->wp_gpio = err;
- }
-
- err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
- if (err) {
- dev_warn(mmc_dev(host->mmc),
- "no card-detect pin available!\n");
- goto no_card_detect_pin;
- }
-
- /* i.MX5x has issues to be researched */
- if (!cpu_is_mx25() && !cpu_is_mx35())
- goto not_supported;
-
- err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- mmc_hostname(host->mmc), host);
- if (err) {
- dev_warn(mmc_dev(host->mmc), "request irq error\n");
- goto no_card_detect_irq;
- }
-
- imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD_WP;
- /* Now we have a working card_detect again */
- host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
- }
-
- err = sdhci_add_host(host);
- if (err)
- goto err_add_host;
-
- return 0;
-
- no_card_detect_irq:
- gpio_free(boarddata->cd_gpio);
- no_card_detect_pin:
- boarddata->cd_gpio = err;
- not_supported:
- kfree(imx_data);
- err_add_host:
- clk_disable(pltfm_host->clk);
- clk_put(pltfm_host->clk);
- err_clk_get:
- sdhci_pltfm_free(pdev);
- return err;
-}
-
-static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
-{
- struct sdhci_host *host = platform_get_drvdata(pdev);
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
- struct pltfm_imx_data *imx_data = pltfm_host->priv;
- int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
-
- sdhci_remove_host(host, dead);
-
- if (boarddata && gpio_is_valid(boarddata->wp_gpio))
- gpio_free(boarddata->wp_gpio);
-
- if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
- gpio_free(boarddata->cd_gpio);
-
- if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
- free_irq(gpio_to_irq(boarddata->cd_gpio), host);
- }
-
- clk_disable(pltfm_host->clk);
- clk_put(pltfm_host->clk);
- kfree(imx_data);
-
- sdhci_pltfm_free(pdev);
-
- return 0;
-}
-
-static struct platform_driver sdhci_esdhc_imx_driver = {
- .driver = {
- .name = "sdhci-esdhc-imx",
- .owner = THIS_MODULE,
- },
- .probe = sdhci_esdhc_imx_probe,
- .remove = __devexit_p(sdhci_esdhc_imx_remove),
-#ifdef CONFIG_PM
- .suspend = sdhci_pltfm_suspend,
- .resume = sdhci_pltfm_resume,
-#endif
-};
-
-static int __init sdhci_esdhc_imx_init(void)
-{
- return platform_driver_register(&sdhci_esdhc_imx_driver);
-}
-module_init(sdhci_esdhc_imx_init);
-
-static void __exit sdhci_esdhc_imx_exit(void)
-{
- platform_driver_unregister(&sdhci_esdhc_imx_driver);
-}
-module_exit(sdhci_esdhc_imx_exit);
-
-MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");
-MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-esdhc.c b/drivers/mmc/host/sdhci-esdhc.c
new file mode 100644
index 0000000..8da57d4
--- /dev/null
+++ b/drivers/mmc/host/sdhci-esdhc.c
@@ -0,0 +1,381 @@
+/*
+ * Freescale eSDHC i.MX controller driver for the platform bus.
+ *
+ * derived from the OF-version.
+ *
+ * Copyright (c) 2010 Pengutronix e.K.
+ * Author: Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdhci-pltfm.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <mach/hardware.h>
+#include <mach/esdhc.h>
+#include "sdhci.h"
+#include "sdhci-pltfm.h"
+#include "sdhci-esdhc.h"
+
+/* VENDOR SPEC register */
+#define SDHCI_VENDOR_SPEC 0xC0
+#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
+
+#define ESDHC_FLAG_GPIO_FOR_CD_WP (1 << 0)
+/*
+ * The CMDTYPE of the CMD register (offset 0xE) should be set to
+ * "11" when the STOP CMD12 is issued on imx53 to abort one
+ * open ended multi-blk IO. Otherwise the TC INT wouldn't
+ * be generated.
+ * In exact block transfer, the controller doesn't complete the
+ * operations automatically as required at the end of the
+ * transfer and remains on hold if the abort command is not sent.
+ * As a result, the TC flag is not asserted and SW received timeout
+ * exeception. Bit1 of Vendor Spec registor is used to fix it.
+ */
+#define ESDHC_FLAG_MULTIBLK_NO_INT (1 << 1)
+
+struct pltfm_imx_data {
+ int flags;
+ u32 scratchpad;
+};
+
+static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
+{
+ void __iomem *base = host->ioaddr + (reg & ~0x3);
+ u32 shift = (reg & 0x3) * 8;
+
+ writel(((readl(base) & ~(mask << shift)) | (val << shift)), base);
+}
+
+static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
+ /* fake CARD_PRESENT flag on mx25/35 */
+ u32 val = readl(host->ioaddr + reg);
+
+ if (unlikely((reg == SDHCI_PRESENT_STATE)
+ && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) {
+ struct esdhc_platform_data *boarddata =
+ host->mmc->parent->platform_data;
+
+ if (boarddata && gpio_is_valid(boarddata->cd_gpio)
+ && gpio_get_value(boarddata->cd_gpio))
+ /* no card, if a valid gpio says so... */
+ val &= SDHCI_CARD_PRESENT;
+ else
+ /* ... in all other cases assume card is present */
+ val |= SDHCI_CARD_PRESENT;
+ }
+
+ return val;
+}
+
+static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
+ if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
+ && (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP)))
+ /*
+ * these interrupts won't work with a custom card_detect gpio
+ * (only applied to mx25/35)
+ */
+ val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
+
+ if (unlikely((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
+ && (reg == SDHCI_INT_STATUS)
+ && (val & SDHCI_INT_DATA_END))) {
+ u32 v;
+ v = readl(host->ioaddr + SDHCI_VENDOR_SPEC);
+ v &= ~SDHCI_VENDOR_SPEC_SDIO_QUIRK;
+ writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
+ }
+
+ writel(val, host->ioaddr + reg);
+}
+
+static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
+{
+ if (unlikely(reg == SDHCI_HOST_VERSION))
+ reg ^= 2;
+
+ return readw(host->ioaddr + reg);
+}
+
+static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
+ switch (reg) {
+ case SDHCI_TRANSFER_MODE:
+ /*
+ * Postpone this write, we must do it together with a
+ * command write that is down below.
+ */
+ if ((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
+ && (host->cmd->opcode == SD_IO_RW_EXTENDED)
+ && (host->cmd->data->blocks > 1)
+ && (host->cmd->data->flags & MMC_DATA_READ)) {
+ u32 v;
+ v = readl(host->ioaddr + SDHCI_VENDOR_SPEC);
+ v |= SDHCI_VENDOR_SPEC_SDIO_QUIRK;
+ writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
+ }
+ imx_data->scratchpad = val;
+ return;
+ case SDHCI_COMMAND:
+ if ((host->cmd->opcode == MMC_STOP_TRANSMISSION)
+ && (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
+ val |= SDHCI_CMD_ABORTCMD;
+ writel(val << 16 | imx_data->scratchpad,
+ host->ioaddr + SDHCI_TRANSFER_MODE);
+ return;
+ case SDHCI_BLOCK_SIZE:
+ val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
+ break;
+ }
+ esdhc_clrset_le(host, 0xffff, val, reg);
+}
+
+static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
+{
+ u32 new_val;
+
+ switch (reg) {
+ case SDHCI_POWER_CONTROL:
+ /*
+ * FSL put some DMA bits here
+ * If your board has a regulator, code should be here
+ */
+ return;
+ case SDHCI_HOST_CONTROL:
+ /* FSL messed up here, so we can just keep those two */
+ new_val = val & (SDHCI_CTRL_LED | SDHCI_CTRL_4BITBUS);
+ /* ensure the endianess */
+ new_val |= ESDHC_HOST_CONTROL_LE;
+ /* DMA mode bits are shifted */
+ new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5;
+
+ esdhc_clrset_le(host, 0xffff, new_val, reg);
+ return;
+ }
+ esdhc_clrset_le(host, 0xff, val, reg);
+}
+
+static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ return clk_get_rate(pltfm_host->clk);
+}
+
+static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ return clk_get_rate(pltfm_host->clk) / 256 / 16;
+}
+
+static struct sdhci_ops sdhci_esdhc_ops = {
+ .read_l = esdhc_readl_le,
+ .read_w = esdhc_readw_le,
+ .write_l = esdhc_writel_le,
+ .write_w = esdhc_writew_le,
+ .write_b = esdhc_writeb_le,
+ .set_clock = esdhc_set_clock,
+ .get_max_clock = esdhc_pltfm_get_max_clock,
+ .get_min_clock = esdhc_pltfm_get_min_clock,
+};
+
+static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
+ .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
+ | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
+ /* ADMA has issues. Might be fixable */
+ .ops = &sdhci_esdhc_ops,
+};
+
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+ if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ return gpio_get_value(boarddata->wp_gpio);
+ else
+ return -ENOSYS;
+}
+
+static irqreturn_t cd_irq(int irq, void *data)
+{
+ struct sdhci_host *sdhost = (struct sdhci_host *)data;
+
+ tasklet_schedule(&sdhost->card_tasklet);
+ return IRQ_HANDLED;
+};
+
+static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
+{
+ struct sdhci_pltfm_host *pltfm_host;
+ struct sdhci_host *host;
+ struct esdhc_platform_data *boarddata;
+ struct clk *clk;
+ int err;
+ struct pltfm_imx_data *imx_data;
+
+ host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata);
+ if (IS_ERR(host))
+ return PTR_ERR(host);
+
+ pltfm_host = sdhci_priv(host);
+
+ imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
+ if (!imx_data)
+ return -ENOMEM;
+ pltfm_host->priv = imx_data;
+
+ clk = clk_get(mmc_dev(host->mmc), NULL);
+ if (IS_ERR(clk)) {
+ dev_err(mmc_dev(host->mmc), "clk err\n");
+ err = PTR_ERR(clk);
+ goto err_clk_get;
+ }
+ clk_enable(clk);
+ pltfm_host->clk = clk;
+
+ if (!cpu_is_mx25())
+ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
+ if (cpu_is_mx25() || cpu_is_mx35()) {
+ /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
+ host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+ /* write_protect can't be routed to controller, use gpio */
+ sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
+ }
+
+ if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
+ imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
+
+ boarddata = host->mmc->parent->platform_data;
+ if (boarddata) {
+ err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
+ if (err) {
+ dev_warn(mmc_dev(host->mmc),
+ "no write-protect pin available!\n");
+ boarddata->wp_gpio = err;
+ }
+
+ err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
+ if (err) {
+ dev_warn(mmc_dev(host->mmc),
+ "no card-detect pin available!\n");
+ goto no_card_detect_pin;
+ }
+
+ /* i.MX5x has issues to be researched */
+ if (!cpu_is_mx25() && !cpu_is_mx35())
+ goto not_supported;
+
+ err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ mmc_hostname(host->mmc), host);
+ if (err) {
+ dev_warn(mmc_dev(host->mmc), "request irq error\n");
+ goto no_card_detect_irq;
+ }
+
+ imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD_WP;
+ /* Now we have a working card_detect again */
+ host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ }
+
+ err = sdhci_add_host(host);
+ if (err)
+ goto err_add_host;
+
+ return 0;
+
+ no_card_detect_irq:
+ gpio_free(boarddata->cd_gpio);
+ no_card_detect_pin:
+ boarddata->cd_gpio = err;
+ not_supported:
+ kfree(imx_data);
+ err_add_host:
+ clk_disable(pltfm_host->clk);
+ clk_put(pltfm_host->clk);
+ err_clk_get:
+ sdhci_pltfm_free(pdev);
+ return err;
+}
+
+static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+ struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+
+ sdhci_remove_host(host, dead);
+
+ if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+ gpio_free(boarddata->wp_gpio);
+
+ if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
+ gpio_free(boarddata->cd_gpio);
+
+ if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
+ free_irq(gpio_to_irq(boarddata->cd_gpio), host);
+ }
+
+ clk_disable(pltfm_host->clk);
+ clk_put(pltfm_host->clk);
+ kfree(imx_data);
+
+ sdhci_pltfm_free(pdev);
+
+ return 0;
+}
+
+static struct platform_driver sdhci_esdhc_imx_driver = {
+ .driver = {
+ .name = "sdhci-esdhc-imx",
+ .owner = THIS_MODULE,
+ },
+ .probe = sdhci_esdhc_imx_probe,
+ .remove = __devexit_p(sdhci_esdhc_imx_remove),
+#ifdef CONFIG_PM
+ .suspend = sdhci_pltfm_suspend,
+ .resume = sdhci_pltfm_resume,
+#endif
+};
+
+static int __init sdhci_esdhc_imx_init(void)
+{
+ return platform_driver_register(&sdhci_esdhc_imx_driver);
+}
+module_init(sdhci_esdhc_imx_init);
+
+static void __exit sdhci_esdhc_imx_exit(void)
+{
+ platform_driver_unregister(&sdhci_esdhc_imx_driver);
+}
+module_exit(sdhci_esdhc_imx_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
--
1.7.4.1
^ permalink raw reply related
* [PATCH v2 5/7] mmc: sdhci: consolidate sdhci-of-esdhc and sdhci-esdhc-imx
From: Shawn Guo @ 2011-05-05 13:22 UTC (permalink / raw)
To: linux-mmc
Cc: Chris Ball, sameo, Arnd Bergmann, patches, Shawn Guo,
devicetree-discuss, Saeed Bishara, Xiaobo Xie, kernel,
Mike Rapoport, Olof Johansson, Anton Vorontsov, linuxppc-dev,
Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-1-git-send-email-shawn.guo@linaro.org>
This patch is to consolidate SDHCI driver for Freescale eSDHC
controller found on both MPCxxx and i.MX platforms. It merges
sdhci-of-esdhc.c into sdhci-esdhc.c, so that the same pair of
.probe/.remove hook works with eSDHC for two platforms.
As the results, sdhci-of-esdhc.c and sdhci-esdhc.h are removed, and
header esdhc.h containing the definition of esdhc_platform_data is
put into the public folder.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
drivers/mmc/host/Kconfig | 38 ++++---
drivers/mmc/host/Makefile | 3 +-
drivers/mmc/host/sdhci-esdhc.c | 244 +++++++++++++++++++++++++++++++++----
drivers/mmc/host/sdhci-esdhc.h | 81 ------------
drivers/mmc/host/sdhci-of-esdhc.c | 142 ---------------------
include/linux/mmc/esdhc.h | 27 ++++
6 files changed, 273 insertions(+), 262 deletions(-)
delete mode 100644 drivers/mmc/host/sdhci-esdhc.h
delete mode 100644 drivers/mmc/host/sdhci-of-esdhc.c
create mode 100644 include/linux/mmc/esdhc.h
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index fdd20ad..e32cb76 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -81,17 +81,6 @@ config MMC_RICOH_MMC
If unsure, say Y.
-config MMC_SDHCI_OF_ESDHC
- bool "SDHCI OF support for the Freescale eSDHC controller"
- depends on MMC_SDHCI
- depends on PPC_OF
- select MMC_SDHCI_PLTFM
- select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
- help
- This selects the Freescale eSDHC controller support.
-
- If unsure, say N.
-
config MMC_SDHCI_OF_HLWD
bool "SDHCI OF support for the Nintendo Wii SDHCI controllers"
depends on MMC_SDHCI
@@ -122,15 +111,34 @@ config MMC_SDHCI_CNS3XXX
If unsure, say N.
+config MMC_SDHCI_ESDHC
+ bool
+ depends on MMC_SDHCI
+ select MMC_SDHCI_PLTFM
+ help
+ This selects SDHCI driver for Freescale eSDHC controller.
+
+config MMC_SDHCI_ESDHC_MPC
+ bool "SDHCI support for the Freescale eSDHC MPC controller"
+ depends on MMC_SDHCI
+ depends on PPC_OF && PPC_CLOCK
+ select MMC_SDHCI_ESDHC
+ select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+ help
+ This selects the Freescale eSDHC controller support on the
+ MPC platforms.
+
+ If unsure, say N.
+
config MMC_SDHCI_ESDHC_IMX
- tristate "SDHCI platform support for the Freescale eSDHC i.MX controller"
+ tristate "SDHCI support for the Freescale eSDHC i.MX controller"
depends on ARCH_MX25 || ARCH_MX35 || ARCH_MX5
depends on MMC_SDHCI
- select MMC_SDHCI_PLTFM
+ select MMC_SDHCI_ESDHC
select MMC_SDHCI_IO_ACCESSORS
help
- This selects the Freescale eSDHC controller support on the platform
- bus, found on platforms like mx35/51.
+ This selects the Freescale eSDHC controller support on platforms
+ like mx25/mx35/mx5x.
If unsure, say N.
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 186f0ed..a3f1df8 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -45,10 +45,9 @@ obj-$(CONFIG_MMC_USHC) += ushc.o
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
-obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc.o
+obj-$(CONFIG_MMC_SDHCI_ESDHC) += sdhci-esdhc.o
obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o
obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o
-obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o
obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o
ifeq ($(CONFIG_CB710_DEBUG),y)
diff --git a/drivers/mmc/host/sdhci-esdhc.c b/drivers/mmc/host/sdhci-esdhc.c
index 8da57d4..f3b4ff5 100644
--- a/drivers/mmc/host/sdhci-esdhc.c
+++ b/drivers/mmc/host/sdhci-esdhc.c
@@ -1,7 +1,11 @@
/*
- * Freescale eSDHC i.MX controller driver for the platform bus.
+ * Freescale eSDHC i.MX controller driver for MPCxxx and i.MX.
*
- * derived from the OF-version.
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Author: Xiaobo Xie <X.Xie@freescale.com>
+ *
+ * Copyright (c) 2009 MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
*
* Copyright (c) 2010 Pengutronix e.K.
* Author: Wolfram Sang <w.sang@pengutronix.de>
@@ -21,11 +25,40 @@
#include <linux/mmc/sdhci-pltfm.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sdio.h>
+#include <linux/mmc/esdhc.h>
+#ifdef CONFIG_MMC_SDHCI_ESDHC_IMX
#include <mach/hardware.h>
-#include <mach/esdhc.h>
+#endif
#include "sdhci.h"
#include "sdhci-pltfm.h"
-#include "sdhci-esdhc.h"
+
+/*
+ * Ops and quirks for the Freescale eSDHC controller.
+ */
+
+#define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
+ SDHCI_QUIRK_NO_BUSY_IRQ | \
+ SDHCI_QUIRK_NONSTANDARD_CLOCK | \
+ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
+ SDHCI_QUIRK_PIO_NEEDS_DELAY | \
+ SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
+
+#define ESDHC_SYSTEM_CONTROL 0x2c
+#define ESDHC_CLOCK_MASK 0x0000fff0
+#define ESDHC_PREDIV_SHIFT 8
+#define ESDHC_DIVIDER_SHIFT 4
+#define ESDHC_CLOCK_PEREN 0x00000004
+#define ESDHC_CLOCK_HCKEN 0x00000002
+#define ESDHC_CLOCK_IPGEN 0x00000001
+
+/* OF-specific */
+#define ESDHC_DMA_SYSCTL 0x40c
+#define ESDHC_DMA_SNOOP 0x00000040
+
+#define ESDHC_HOST_CONTROL_RES 0x05
+
+/* pltfm-specific */
+#define ESDHC_HOST_CONTROL_LE 0x20
/* VENDOR SPEC register */
#define SDHCI_VENDOR_SPEC 0xC0
@@ -50,6 +83,117 @@ struct pltfm_imx_data {
u32 scratchpad;
};
+static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ int pre_div = 2;
+ int div = 1;
+ u32 temp;
+
+ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+ temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
+ | ESDHC_CLOCK_MASK);
+ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+
+ if (clock == 0)
+ goto out;
+
+ while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
+ pre_div *= 2;
+
+ while (host->max_clk / pre_div / div > clock && div < 16)
+ div++;
+
+ dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
+ clock, host->max_clk / pre_div / div);
+
+ pre_div >>= 1;
+ div--;
+
+ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+ temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
+ | (div << ESDHC_DIVIDER_SHIFT)
+ | (pre_div << ESDHC_PREDIV_SHIFT));
+ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+ mdelay(100);
+out:
+ host->clock = clock;
+}
+
+#ifdef CONFIG_MMC_SDHCI_ESDHC_MPC
+static u16 esdhc_readw(struct sdhci_host *host, int reg)
+{
+ u16 ret;
+
+ if (unlikely(reg == SDHCI_HOST_VERSION))
+ ret = in_be16(host->ioaddr + reg);
+ else
+ ret = sdhci_be32bs_readw(host, reg);
+ return ret;
+}
+
+static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
+{
+ if (reg == SDHCI_BLOCK_SIZE) {
+ /*
+ * Two last DMA bits are reserved, and first one is used for
+ * non-standard blksz of 4096 bytes that we don't support
+ * yet. So clear the DMA boundary bits.
+ */
+ val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
+ }
+ sdhci_be32bs_writew(host, val, reg);
+}
+
+static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+ /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
+ if (reg == SDHCI_HOST_CONTROL)
+ val &= ~ESDHC_HOST_CONTROL_RES;
+ sdhci_be32bs_writeb(host, val, reg);
+}
+
+static int esdhc_of_enable_dma(struct sdhci_host *host)
+{
+ setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP);
+ return 0;
+}
+
+static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ return pltfm_host->clock;
+}
+
+static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ return pltfm_host->clock / 256 / 16;
+}
+
+static struct sdhci_ops sdhci_esdhc_mpc_ops = {
+ .read_l = sdhci_be32bs_readl,
+ .read_w = esdhc_readw,
+ .read_b = sdhci_be32bs_readb,
+ .write_l = sdhci_be32bs_writel,
+ .write_w = esdhc_writew,
+ .write_b = esdhc_writeb,
+ .set_clock = esdhc_set_clock,
+ .enable_dma = esdhc_of_enable_dma,
+ .get_max_clock = esdhc_of_get_max_clock,
+ .get_min_clock = esdhc_of_get_min_clock,
+};
+
+static struct sdhci_pltfm_data sdhci_esdhc_mpc_pdata = {
+ /* card detection could be handled via GPIO */
+ .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
+ | SDHCI_QUIRK_NO_CARD_NO_RESET,
+ .ops = &sdhci_esdhc_mpc_ops,
+};
+#endif /* CONFIG_MMC_SDHCI_ESDHC_MPC */
+
+#ifdef CONFIG_MMC_SDHCI_ESDHC_IMX
static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
{
void __iomem *base = host->ioaddr + (reg & ~0x3);
@@ -191,7 +335,7 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
return clk_get_rate(pltfm_host->clk) / 256 / 16;
}
-static struct sdhci_ops sdhci_esdhc_ops = {
+static struct sdhci_ops sdhci_esdhc_imx_ops = {
.read_l = esdhc_readl_le,
.read_w = esdhc_readw_le,
.write_l = esdhc_writel_le,
@@ -206,8 +350,35 @@ static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
| SDHCI_QUIRK_BROKEN_CARD_DETECTION,
/* ADMA has issues. Might be fixable */
- .ops = &sdhci_esdhc_ops,
+ .ops = &sdhci_esdhc_imx_ops,
+};
+#endif /* CONFIG_MMC_SDHCI_ESDHC_IMX */
+
+#ifdef CONFIG_OF
+#include <linux/of_device.h>
+static const struct of_device_id sdhci_esdhc_dt_ids[] = {
+#ifdef CONFIG_MMC_SDHCI_ESDHC_IMX
+ { .compatible = "fsl,imx-esdhc", .data = &sdhci_esdhc_imx_pdata },
+#endif
+#ifdef CONFIG_MMC_SDHCI_ESDHC_MPC
+ { .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc_mpc_pdata },
+ { .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc_mpc_pdata },
+ { .compatible = "fsl,esdhc", .data = &sdhci_esdhc_mpc_pdata },
+#endif
+ { }
};
+MODULE_DEVICE_TABLE(platform, sdhci_esdhc_dt_ids);
+#else
+#define sdhci_esdhc_dt_ids NULL
+#endif
+
+static const struct platform_device_id sdhci_esdhc_pltfm_ids[] = {
+#ifdef CONFIG_MMC_SDHCI_ESDHC_IMX
+ { "sdhci-esdhc-imx", (kernel_ulong_t)&sdhci_esdhc_imx_pdata },
+#endif
+ { }
+};
+MODULE_DEVICE_TABLE(platform, sdhci_esdhc_pltfm_ids);
static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
{
@@ -227,8 +398,20 @@ static irqreturn_t cd_irq(int irq, void *data)
return IRQ_HANDLED;
};
-static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
+#ifndef CONFIG_MMC_SDHCI_ESDHC_IMX
+#define cpu_is_mx25() (0)
+#define cpu_is_mx35() (0)
+#define cpu_is_mx51() (0)
+#define cpu_is_imx() (0)
+#else
+#define cpu_is_imx() (1)
+#endif
+
+static int __devinit sdhci_esdhc_probe(struct platform_device *pdev)
{
+ const struct platform_device_id *platid = platform_get_device_id(pdev);
+ const struct of_device_id *dtid = pdev->dev.of_match;
+ struct sdhci_pltfm_data *pdata;
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_host *host;
struct esdhc_platform_data *boarddata;
@@ -236,12 +419,24 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
int err;
struct pltfm_imx_data *imx_data;
- host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata);
+ if (platid && platid->driver_data)
+ pdata = (void *)platid->driver_data;
+ else if (dtid && dtid->data)
+ pdata = dtid->data;
+ else
+ pdata = pdev->dev.platform_data;
+
+ host = sdhci_pltfm_init(pdev, pdata);
if (IS_ERR(host))
return PTR_ERR(host);
+ sdhci_get_of_property(pdev);
+
pltfm_host = sdhci_priv(host);
+ if (!cpu_is_imx())
+ goto add_host;
+
imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
if (!imx_data)
return -ENOMEM;
@@ -263,7 +458,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
/* write_protect can't be routed to controller, use gpio */
- sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
+ pdata->ops->get_ro = esdhc_pltfm_get_ro;
}
if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
@@ -302,6 +497,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
}
+ add_host:
err = sdhci_add_host(host);
if (err)
goto err_add_host;
@@ -322,7 +518,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
return err;
}
-static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
+static int __devexit sdhci_esdhc_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -351,31 +547,35 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver sdhci_esdhc_imx_driver = {
+static struct platform_driver sdhci_esdhc_driver = {
.driver = {
- .name = "sdhci-esdhc-imx",
+ .name = "sdhci-esdhc",
.owner = THIS_MODULE,
+ .of_match_table = sdhci_esdhc_dt_ids,
},
- .probe = sdhci_esdhc_imx_probe,
- .remove = __devexit_p(sdhci_esdhc_imx_remove),
+ .probe = sdhci_esdhc_probe,
+ .remove = __devexit_p(sdhci_esdhc_remove),
+ .id_table = sdhci_esdhc_pltfm_ids,
#ifdef CONFIG_PM
.suspend = sdhci_pltfm_suspend,
.resume = sdhci_pltfm_resume,
#endif
};
-static int __init sdhci_esdhc_imx_init(void)
+static int __init sdhci_esdhc_init(void)
{
- return platform_driver_register(&sdhci_esdhc_imx_driver);
+ return platform_driver_register(&sdhci_esdhc_driver);
}
-module_init(sdhci_esdhc_imx_init);
+module_init(sdhci_esdhc_init);
-static void __exit sdhci_esdhc_imx_exit(void)
+static void __exit sdhci_esdhc_exit(void)
{
- platform_driver_unregister(&sdhci_esdhc_imx_driver);
+ platform_driver_unregister(&sdhci_esdhc_driver);
}
-module_exit(sdhci_esdhc_imx_exit);
+module_exit(sdhci_esdhc_exit);
-MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");
-MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_DESCRIPTION("SDHCI driver for Freescale eSDHC");
+MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
+ "Anton Vorontsov <avorontsov@ru.mvista.com>, "
+ "Wolfram Sang <w.sang@pengutronix.de>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
deleted file mode 100644
index c3b08f1..0000000
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Freescale eSDHC controller driver generics for OF and pltfm.
- *
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
- * Copyright (c) 2009 MontaVista Software, Inc.
- * Copyright (c) 2010 Pengutronix e.K.
- * Author: Wolfram Sang <w.sang@pengutronix.de>
- *
- * 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.
- */
-
-#ifndef _DRIVERS_MMC_SDHCI_ESDHC_H
-#define _DRIVERS_MMC_SDHCI_ESDHC_H
-
-/*
- * Ops and quirks for the Freescale eSDHC controller.
- */
-
-#define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
- SDHCI_QUIRK_NO_BUSY_IRQ | \
- SDHCI_QUIRK_NONSTANDARD_CLOCK | \
- SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
- SDHCI_QUIRK_PIO_NEEDS_DELAY | \
- SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
-
-#define ESDHC_SYSTEM_CONTROL 0x2c
-#define ESDHC_CLOCK_MASK 0x0000fff0
-#define ESDHC_PREDIV_SHIFT 8
-#define ESDHC_DIVIDER_SHIFT 4
-#define ESDHC_CLOCK_PEREN 0x00000004
-#define ESDHC_CLOCK_HCKEN 0x00000002
-#define ESDHC_CLOCK_IPGEN 0x00000001
-
-/* pltfm-specific */
-#define ESDHC_HOST_CONTROL_LE 0x20
-
-/* OF-specific */
-#define ESDHC_DMA_SYSCTL 0x40c
-#define ESDHC_DMA_SNOOP 0x00000040
-
-#define ESDHC_HOST_CONTROL_RES 0x05
-
-static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
-{
- int pre_div = 2;
- int div = 1;
- u32 temp;
-
- temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
- temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
- | ESDHC_CLOCK_MASK);
- sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
-
- if (clock == 0)
- goto out;
-
- while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
- pre_div *= 2;
-
- while (host->max_clk / pre_div / div > clock && div < 16)
- div++;
-
- dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
- clock, host->max_clk / pre_div / div);
-
- pre_div >>= 1;
- div--;
-
- temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
- temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
- | (div << ESDHC_DIVIDER_SHIFT)
- | (pre_div << ESDHC_PREDIV_SHIFT));
- sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
- mdelay(100);
-out:
- host->clock = clock;
-}
-
-#endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
deleted file mode 100644
index 2db6a45..0000000
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Freescale eSDHC controller driver.
- *
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
- * Copyright (c) 2009 MontaVista Software, Inc.
- *
- * Authors: Xiaobo Xie <X.Xie@freescale.com>
- * 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/io.h>
-#include <linux/delay.h>
-#include <linux/mmc/host.h>
-#include "sdhci-pltfm.h"
-#include "sdhci.h"
-#include "sdhci-esdhc.h"
-
-static u16 esdhc_readw(struct sdhci_host *host, int reg)
-{
- u16 ret;
-
- if (unlikely(reg == SDHCI_HOST_VERSION))
- ret = in_be16(host->ioaddr + reg);
- else
- ret = sdhci_be32bs_readw(host, reg);
- return ret;
-}
-
-static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
-{
- if (reg == SDHCI_BLOCK_SIZE) {
- /*
- * Two last DMA bits are reserved, and first one is used for
- * non-standard blksz of 4096 bytes that we don't support
- * yet. So clear the DMA boundary bits.
- */
- val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
- }
- sdhci_be32bs_writew(host, val, reg);
-}
-
-static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
-{
- /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
- if (reg == SDHCI_HOST_CONTROL)
- val &= ~ESDHC_HOST_CONTROL_RES;
- sdhci_be32bs_writeb(host, val, reg);
-}
-
-static int esdhc_of_enable_dma(struct sdhci_host *host)
-{
- setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP);
- return 0;
-}
-
-static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-
- return pltfm_host->clock;
-}
-
-static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
-{
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-
- return pltfm_host->clock / 256 / 16;
-}
-
-static struct sdhci_ops sdhci_esdhc_ops = {
- .read_l = sdhci_be32bs_readl,
- .read_w = esdhc_readw,
- .read_b = sdhci_be32bs_readb,
- .write_l = sdhci_be32bs_writel,
- .write_w = esdhc_writew,
- .write_b = esdhc_writeb,
- .set_clock = esdhc_set_clock,
- .enable_dma = esdhc_of_enable_dma,
- .get_max_clock = esdhc_of_get_max_clock,
- .get_min_clock = esdhc_of_get_min_clock,
-};
-
-static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
- /* card detection could be handled via GPIO */
- .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
- | SDHCI_QUIRK_NO_CARD_NO_RESET,
- .ops = &sdhci_esdhc_ops,
-};
-
-static int __devinit sdhci_esdhc_probe(struct platform_device *pdev)
-{
- return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata);
-}
-
-static int __devexit sdhci_esdhc_remove(struct platform_device *pdev)
-{
- return sdhci_pltfm_unregister(pdev);
-}
-
-static const struct of_device_id sdhci_esdhc_of_match[] = {
- { .compatible = "fsl,mpc8379-esdhc" },
- { .compatible = "fsl,mpc8536-esdhc" },
- { .compatible = "fsl,esdhc" },
- { }
-};
-MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match);
-
-static struct platform_driver sdhci_esdhc_driver = {
- .driver = {
- .name = "sdhci-esdhc",
- .owner = THIS_MODULE,
- .of_match_table = sdhci_esdhc_of_match,
- },
- .probe = sdhci_esdhc_probe,
- .remove = __devexit_p(sdhci_esdhc_remove),
-#ifdef CONFIG_PM
- .suspend = sdhci_pltfm_suspend,
- .resume = sdhci_pltfm_resume,
-#endif
-};
-
-static int __init sdhci_esdhc_init(void)
-{
- return platform_driver_register(&sdhci_esdhc_driver);
-}
-module_init(sdhci_esdhc_init);
-
-static void __exit sdhci_esdhc_exit(void)
-{
- platform_driver_unregister(&sdhci_esdhc_driver);
-}
-module_exit(sdhci_esdhc_exit);
-
-MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC");
-MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
- "Anton Vorontsov <avorontsov@ru.mvista.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mmc/esdhc.h b/include/linux/mmc/esdhc.h
new file mode 100644
index 0000000..e0f6598
--- /dev/null
+++ b/include/linux/mmc/esdhc.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * 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; version 2
+ * of the License.
+ */
+
+#ifndef __LINUX_MMC_ESDHC_H
+#define __LINUX_MMC_ESDHC_H
+
+/**
+ * struct esdhc_platform_data - optional platform data for esdhc
+ *
+ * strongly recommended for i.MX25/35, not needed for other variants
+ *
+ * @wp_gpio: gpio for write_protect (-EINVAL if unused)
+ * @cd_gpio: gpio for card_detect interrupt (-EINVAL if unused)
+ */
+
+struct esdhc_platform_data {
+ unsigned int wp_gpio;
+ unsigned int cd_gpio;
+};
+
+#endif /* __LINUX_MMC_ESDHC_H */
--
1.7.4.1
^ permalink raw reply related
* [PATCH v2 6/7] mmc: sdhci: merge two sdhci-pltfm.h into one
From: Shawn Guo @ 2011-05-05 13:22 UTC (permalink / raw)
To: linux-mmc
Cc: Chris Ball, sameo, Arnd Bergmann, patches, Shawn Guo,
devicetree-discuss, Saeed Bishara, Xiaobo Xie, kernel,
Mike Rapoport, Olof Johansson, Anton Vorontsov, linuxppc-dev,
Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-1-git-send-email-shawn.guo@linaro.org>
The structure sdhci_pltfm_data is not necessarily to be in a public
header like include/linux/mmc/sdhci-pltfm.h, so the patch moves it
into drivers/mmc/host/sdhci-pltfm.h and eliminates the former one.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
---
drivers/mmc/host/sdhci-cns3xxx.c | 1 -
drivers/mmc/host/sdhci-esdhc.c | 1 -
drivers/mmc/host/sdhci-pltfm.h | 6 +++++-
include/linux/mmc/sdhci-pltfm.h | 29 -----------------------------
4 files changed, 5 insertions(+), 32 deletions(-)
delete mode 100644 include/linux/mmc/sdhci-pltfm.h
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
index ac4b26f..025d1a5 100644
--- a/drivers/mmc/host/sdhci-cns3xxx.c
+++ b/drivers/mmc/host/sdhci-cns3xxx.c
@@ -15,7 +15,6 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/mmc/host.h>
-#include <linux/mmc/sdhci-pltfm.h>
#include <mach/cns3xxx.h>
#include "sdhci.h"
#include "sdhci-pltfm.h"
diff --git a/drivers/mmc/host/sdhci-esdhc.c b/drivers/mmc/host/sdhci-esdhc.c
index f3b4ff5..f005cb8 100644
--- a/drivers/mmc/host/sdhci-esdhc.c
+++ b/drivers/mmc/host/sdhci-esdhc.c
@@ -22,7 +22,6 @@
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/mmc/host.h>
-#include <linux/mmc/sdhci-pltfm.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/esdhc.h>
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h
index fe27b83..fd72694 100644
--- a/drivers/mmc/host/sdhci-pltfm.h
+++ b/drivers/mmc/host/sdhci-pltfm.h
@@ -14,9 +14,13 @@
#include <linux/clk.h>
#include <linux/types.h>
#include <linux/platform_device.h>
-#include <linux/mmc/sdhci-pltfm.h>
#include <linux/mmc/sdhci.h>
+struct sdhci_pltfm_data {
+ struct sdhci_ops *ops;
+ unsigned int quirks;
+};
+
struct sdhci_pltfm_host {
struct clk *clk;
void *priv; /* to handle quirks across io-accessor calls */
diff --git a/include/linux/mmc/sdhci-pltfm.h b/include/linux/mmc/sdhci-pltfm.h
deleted file mode 100644
index f1c2ac3..0000000
--- a/include/linux/mmc/sdhci-pltfm.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Platform data declarations for the sdhci-pltfm driver.
- *
- * Copyright (c) 2010 MontaVista Software, LLC.
- *
- * 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.
- */
-
-#ifndef _SDHCI_PLTFM_H
-#define _SDHCI_PLTFM_H
-
-struct sdhci_ops;
-
-/**
- * struct sdhci_pltfm_data - SDHCI platform-specific information & hooks
- * @ops: optional pointer to the platform-provided SDHCI ops
- * @quirks: optional SDHCI quirks
- */
-struct sdhci_pltfm_data {
- struct sdhci_ops *ops;
- unsigned int quirks;
-};
-
-#endif /* _SDHCI_PLTFM_H */
--
1.7.4.1
^ permalink raw reply related
* [PATCH v2 7/7] ARM: mxc: remove esdhc.h and use the public one
From: Shawn Guo @ 2011-05-05 13:22 UTC (permalink / raw)
To: linux-mmc
Cc: Chris Ball, sameo, Arnd Bergmann, patches, Shawn Guo,
devicetree-discuss, Saeed Bishara, Xiaobo Xie, kernel,
Mike Rapoport, Olof Johansson, Anton Vorontsov, linuxppc-dev,
Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-1-git-send-email-shawn.guo@linaro.org>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
.../plat-mxc/devices/platform-sdhci-esdhc-imx.c | 1 -
arch/arm/plat-mxc/include/mach/devices-common.h | 2 +-
2 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
index 6b2940b..b401689 100644
--- a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
+++ b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
@@ -8,7 +8,6 @@
#include <mach/hardware.h>
#include <mach/devices-common.h>
-#include <mach/esdhc.h>
#define imx_sdhci_esdhc_imx_data_entry_single(soc, _id, hwid) \
{ \
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index 8658c9c..c95ab13 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -243,7 +243,7 @@ struct imx_mxc_w1_data {
struct platform_device *__init imx_add_mxc_w1(
const struct imx_mxc_w1_data *data);
-#include <mach/esdhc.h>
+#include <linux/mmc/esdhc.h>
struct imx_sdhci_esdhc_imx_data {
int id;
resource_size_t iobase;
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH 0/6] General device tree irq domain infrastructure
From: Grant Likely @ 2011-05-05 14:07 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Michal Simek, Sebastian Andrzej Siewior, x86, linux-kernel,
Ralf Baechle, hpa, Dirk Brandewie, linuxppc-dev,
devicetree-discuss
In-Reply-To: <alpine.LFD.2.02.1105051026370.3005@ionos>
On Thu, May 5, 2011 at 2:37 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
> On Thu, 5 May 2011, Benjamin Herrenschmidt wrote:
>> > As for the mapping, I agree that the functionality is generally
>> > useful, I'm just not fond of the current implementation. =A0I think it
>> > is more complex than it needs to be and I'm not excited about bring it
>> > over to the other architectures as-is.
>>
>> Nobody cares about the current implementation. What is important is
>> indeed the functionality. The basic thing I think everybody agrees is
>> that you need to extend the irq_desc (or data, whatever tglx prefers)
>> with two bits of information: Some identifier of the domain and some
>> identifier of the interrupt number within that domain.
>
> irq_data because that's what is handed into the callbacks and you
> probably want to have the HW number there.
Okay, I'll take another hack at it. Unfortunately I've got a great
big unmaskable interrupt in the form of UDS next week, but I'll be
back on it the week after.
g.
^ permalink raw reply
* Re: [PATCH v2 6/7] mmc: sdhci: merge two sdhci-pltfm.h into one
From: Anton Vorontsov @ 2011-05-05 14:13 UTC (permalink / raw)
To: Shawn Guo
Cc: sameo, Arnd Bergmann, patches, devicetree-discuss, linux-mmc,
Saeed Bishara, Xiaobo Xie, kernel, Mike Rapoport, Olof Johansson,
Chris Ball, linuxppc-dev, Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-7-git-send-email-shawn.guo@linaro.org>
On Thu, May 05, 2011 at 09:22:57PM +0800, Shawn Guo wrote:
> The structure sdhci_pltfm_data is not necessarily to be in a public
> header like include/linux/mmc/sdhci-pltfm.h, so the patch moves it
> into drivers/mmc/host/sdhci-pltfm.h and eliminates the former one.
>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
> Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
^ permalink raw reply
* Re: [PATCH 0/6] General device tree irq domain infrastructure
From: Sebastian Andrzej Siewior @ 2011-05-05 14:14 UTC (permalink / raw)
To: Grant Likely
Cc: Michal Simek, devicetree-discuss, x86, linux-kernel, Ralf Baechle,
hpa, Dirk Brandewie, Thomas Gleixner, linuxppc-dev
In-Reply-To: <BANLkTimQ7GsUton3nvJof8YB8k6cnx4rFQ@mail.gmail.com>
Grant Likely wrote:
> Okay, I'll take another hack at it. Unfortunately I've got a great
> big unmaskable interrupt in the form of UDS next week, but I'll be
> back on it the week after.
And I thought you were a NMI.
>
> g.
Sebastian
^ permalink raw reply
* Re: [PATCH v2 5/7] mmc: sdhci: consolidate sdhci-of-esdhc and sdhci-esdhc-imx
From: Anton Vorontsov @ 2011-05-05 14:20 UTC (permalink / raw)
To: Shawn Guo
Cc: sameo, Arnd Bergmann, patches, devicetree-discuss, linux-mmc,
Saeed Bishara, Xiaobo Xie, kernel, Mike Rapoport, Olof Johansson,
Chris Ball, linuxppc-dev, Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-6-git-send-email-shawn.guo@linaro.org>
On Thu, May 05, 2011 at 09:22:56PM +0800, Shawn Guo wrote:
> This patch is to consolidate SDHCI driver for Freescale eSDHC
> controller found on both MPCxxx and i.MX platforms. It merges
> sdhci-of-esdhc.c into sdhci-esdhc.c, so that the same pair of
> .probe/.remove hook works with eSDHC for two platforms.
>
> As the results, sdhci-of-esdhc.c and sdhci-esdhc.h are removed, and
> header esdhc.h containing the definition of esdhc_platform_data is
> put into the public folder.
>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
I'm not sure if that makes sense to merge these two.
I'd rather vote for renaming sdhci-of-esdhc to sdhci-esdhc-mpc. :-)
--
Anton Vorontsov
Email: cbouatmailru@gmail.com
^ permalink raw reply
* Re: [PATCH v2 3/7] mmc: sdhci: make sdhci-of device drivers self registered
From: Anton Vorontsov @ 2011-05-05 14:23 UTC (permalink / raw)
To: Shawn Guo
Cc: sameo, Arnd Bergmann, patches, devicetree-discuss, linux-mmc,
Saeed Bishara, Xiaobo Xie, kernel, Mike Rapoport, Olof Johansson,
Chris Ball, linuxppc-dev, Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-4-git-send-email-shawn.guo@linaro.org>
On Thu, May 05, 2011 at 09:22:54PM +0800, Shawn Guo wrote:
[...]
> - * Copyright (c) 2007 Freescale Semiconductor, Inc.
> - * Copyright (c) 2009 MontaVista Software, Inc.
> - *
> - * Authors: Xiaobo Xie <X.Xie@freescale.com>
> - * Anton Vorontsov <avorontsov@ru.mvista.com>
[...]
> -#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
> -
> -/*
> - * These accessors are designed for big endian hosts doing I/O to
> - * little endian controllers incorporating a 32-bit hardware byte swapper.
> - */
> -
> -u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg)
> -{
> - return in_be32(host->ioaddr + reg);
> -}
> -
> -u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg)
> -{
> - return in_be16(host->ioaddr + (reg ^ 0x2));
> -}
> -
> -u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg)
> -{
> - return in_8(host->ioaddr + (reg ^ 0x3));
> -}
> -
> -void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg)
> -{
> - out_be32(host->ioaddr + reg, val);
> -}
> -
> -void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg)
> -{
> - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> - int base = reg & ~0x3;
> - int shift = (reg & 0x2) * 8;
> -
> - switch (reg) {
> - case SDHCI_TRANSFER_MODE:
> - /*
> - * Postpone this write, we must do it together with a
> - * command write that is down below.
> - */
> - pltfm_host->xfer_mode_shadow = val;
> - return;
> - case SDHCI_COMMAND:
> - sdhci_be32bs_writel(host, val << 16 | pltfm_host->xfer_mode_shadow,
> - SDHCI_TRANSFER_MODE);
> - return;
> - }
> - clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
> -}
> -
> -void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
> -{
> - int base = reg & ~0x3;
> - int shift = (reg & 0x3) * 8;
> -
> - clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
> -}
> -#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */
[...]
> +#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
> +/*
> + * These accessors are designed for big endian hosts doing I/O to
> + * little endian controllers incorporating a 32-bit hardware byte swapper.
> + */
> +u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg)
> +{
> + return in_be32(host->ioaddr + reg);
> +}
> +
> +u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg)
> +{
> + return in_be16(host->ioaddr + (reg ^ 0x2));
> +}
> +
> +u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg)
> +{
> + return in_8(host->ioaddr + (reg ^ 0x3));
> +}
> +
> +void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg)
> +{
> + out_be32(host->ioaddr + reg, val);
> +}
> +
> +void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg)
> +{
> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> + int base = reg & ~0x3;
> + int shift = (reg & 0x2) * 8;
> +
> + switch (reg) {
> + case SDHCI_TRANSFER_MODE:
> + /*
> + * Postpone this write, we must do it together with a
> + * command write that is down below.
> + */
> + pltfm_host->xfer_mode_shadow = val;
> + return;
> + case SDHCI_COMMAND:
> + sdhci_be32bs_writel(host, val << 16 | pltfm_host->xfer_mode_shadow,
> + SDHCI_TRANSFER_MODE);
> + return;
> + }
> + clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
> +}
> +
> +void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
> +{
> + int base = reg & ~0x3;
> + int shift = (reg & 0x3) * 8;
> +
> + clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
> +}
> +#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */
I noticed you're very careful wrt copyright/authorship notices,
except for this case. How about retaining copyright stuff when
you merge these two files?
The patch itself looks great though.
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
^ permalink raw reply
* Re: [PATCH v2 2/7] mmc: sdhci: eliminate sdhci_of_host and sdhci_of_data
From: Anton Vorontsov @ 2011-05-05 14:23 UTC (permalink / raw)
To: Shawn Guo
Cc: sameo, Arnd Bergmann, patches, devicetree-discuss, linux-mmc,
Saeed Bishara, Xiaobo Xie, kernel, Mike Rapoport, Olof Johansson,
Chris Ball, linuxppc-dev, Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-3-git-send-email-shawn.guo@linaro.org>
On Thu, May 05, 2011 at 09:22:53PM +0800, Shawn Guo wrote:
> The patch migrates the use of sdhci_of_host and sdhci_of_data to
> sdhci_pltfm_host and sdhci_pltfm_data, so that the former pair can
> be eliminated.
>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
Thanks!
--
Anton Vorontsov
Email: cbouatmailru@gmail.com
^ permalink raw reply
* Re: [PATCH v2 1/7] mmc: sdhci: make sdhci-pltfm device drivers self registered
From: Anton Vorontsov @ 2011-05-05 14:24 UTC (permalink / raw)
To: Shawn Guo
Cc: sameo, Arnd Bergmann, patches, devicetree-discuss, linux-mmc,
Saeed Bishara, Xiaobo Xie, kernel, Mike Rapoport, Olof Johansson,
Chris Ball, linuxppc-dev, Albert Herranz, linux-arm-kernel
In-Reply-To: <1304601778-13837-2-git-send-email-shawn.guo@linaro.org>
On Thu, May 05, 2011 at 09:22:52PM +0800, Shawn Guo wrote:
[...]
> +static int __devinit sdhci_cns3xxx_probe(struct platform_device *pdev)
> +{
> + return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata);
> +}
> +
> +static int __devexit sdhci_cns3xxx_remove(struct platform_device *pdev)
> +{
> + return sdhci_pltfm_unregister(pdev);
> +}
> +
> +static struct platform_driver sdhci_cns3xxx_driver = {
> + .driver = {
> + .name = "sdhci-cns3xxx",
> + .owner = THIS_MODULE,
> + },
> + .probe = sdhci_cns3xxx_probe,
> + .remove = __devexit_p(sdhci_cns3xxx_remove),
> +#ifdef CONFIG_PM
> + .suspend = sdhci_pltfm_suspend,
> + .resume = sdhci_pltfm_resume,
> +#endif
> +};
> +
> +static int __init sdhci_cns3xxx_init(void)
> +{
> + return platform_driver_register(&sdhci_cns3xxx_driver);
> +}
> +module_init(sdhci_cns3xxx_init);
> +
> +static void __exit sdhci_cns3xxx_exit(void)
> +{
> + platform_driver_unregister(&sdhci_cns3xxx_driver);
> +}
> +module_exit(sdhci_cns3xxx_exit);
I don't think I like this duplicate code for each platform sub-
driver. It's repetitive and annoying. :-/
But considering that ARM will be multiplatform soon, we don't
want to have every mach-* stuff in the single sdhci-pltfm.
So... OK. If that compiles, I'm fine with it. :-D
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
Thanks!
--
Anton Vorontsov
Email: cbouatmailru@gmail.com
^ permalink raw reply
* [PATCH v2] powerpc: Use the deterministic mode of ar
From: Michal Marek @ 2011-05-05 15:22 UTC (permalink / raw)
To: linux-kbuild; +Cc: linuxppc-dev, Paul Mackerras, linux-kernel
In-Reply-To: <1302015561-21047-1-git-send-email-mmarek@suse.cz>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Michal Marek <mmarek@suse.cz>
---
Hi,
this version fixes build with binutils <= 2.19 by first checking if ar(1)
supports the D option. It depends on a previous patch in the kbuild tree,
commit 40df759e (kbuild: Fix build with binutils <= 2.19) in linux-next,
so it will need to go through the kbuild tree. But feedback from the PPC
maintainers would be appreciated.
Thanks
Michal
---
arch/powerpc/boot/Makefile | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 8917816..f0543f8 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -127,7 +127,7 @@ quiet_cmd_bootas = BOOTAS $@
cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
quiet_cmd_bootar = BOOTAR $@
- cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@
+ cmd_bootar = $(CROSS32AR) -cr$(KBUILD_ARFLAGS) $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@
$(obj-libfdt): $(obj)/%.o: $(srctree)/scripts/dtc/libfdt/%.c FORCE
$(call if_changed_dep,bootcc)
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH 0/1] ppc4xx: Fix PCIe scanning for the 460SX
From: Tirumala Marri @ 2011-05-05 16:44 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Ayman El-Khashab, Paul Mackerras
In-Reply-To: <1304487166.2513.351.camel@pasglop>
[-- Attachment #1: Type: text/plain, Size: 593 bytes --]
>
> Also, the patch removes the code for waiting for the link to be up with
> a comment "What DCR has the link status on the 460SX?". Please fix that
> (Tirumala, can you provide the missing information ?)
>
It is not one register. Here is the flow for Gen-1.
1. PECFGn_DLLSTA[3] will be asserted when pci-e link comes up.
2. now progream the UTL buffer configuration registers.
3. SW should assert PEUTLn_PCTL[0] to cause flow control initialization.
This is memory mapped using GPL register REGBH , REBAL and REGMSK
4. Now check for the PEUTLN_PSTA[8] for the flow control init completion.
[-- Attachment #2: Type: text/html, Size: 853 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] powerpc: add support for MPIC message register API
From: Meador Inge @ 2011-05-05 21:41 UTC (permalink / raw)
To: Scott Wood
Cc: Wood Scott-B07421, devicetree-discuss@lists.ozlabs.org,
Hollis Blanchard, Kushwaha Prabhakar-B32579,
openmcapi-dev@googlegroups.com, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20110503101921.45f31d34@schlenkerla.am.freescale.net>
On 05/03/2011 10:19 AM, Scott Wood wrote:
> In the absence of partitioning, no driver should need a specific one. With
> partitioning, let the system designer mark those resources as reserved so
> they don't get allocated. :-)
That seem reasonable. Back to the device tree then. One option is to bring
back the sister-send property 'mpic-msgr-send-mask', which was discussed some
months back. For example, consider:
/* OS 1 */
mpic_msgr_block0: mpic-msgr-block@41400 {
compatible = "fsl,mpic-v3.1-msgr";
reg = <0x41400 0x200>;
interrupts = <0xb0 2 0xb2 2>;
mpic-msgr-receive-mask = <0x5>;
mpic-msgr-send-mask = <0xa>;
};
mpic_msgr_block1: mpic-msgr-block@42400 {
compatible = "fsl,mpic-v3.1-msgr";
reg = <0x42400 0x200>;
interrupts = <0xb4 2 0xb6 2>;
mpic-msgr-receive-mask = <0x5>;
};
/* OS 2 */
mpic_msgr_block0: mpic-msgr-block@41400 {
compatible = "fsl,mpic-v3.1-msgr";
reg = <0x41400 0x200>;
interrupts = <0xb0 2 0xb2 2>;
mpic-msgr-receive-mask = <0xa>;
mpic-msgr-send-mask = <0x5>;
};
mpic_msgr_block1: mpic-msgr-block@42400 {
compatible = "fsl,mpic-v3.1-msgr";
reg = <0x42400 0x200>;
interrupts = <0xb4 2 0xb6 2>;
mpic-msgr-send-mask = <0x5>;
};
In block0 for both OSes, all registers are partitioned and are thus not
available for allocation. In block1 for both OSes, registers 0 and 2 are
reserved and registers 1 and 3 are available for general allocation.
So any register mentioned in one of 'mpic-msgr-receive-mask' or
'mpic-msgr-send-mask' is out of the running for general allocation.
If neither of the properties appear, then all registers are available
for general allocation.
You could get into trouble with this method with cases like:
/* OS 1 */
mpic_msgr_block0: mpic-msgr-block@41400 {
compatible = "fsl,mpic-v3.1-msgr";
reg = <0x41400 0x200>;
interrupts = <0xb0 2 0xb2 2>;
mpic-msgr-send-mask = <0xa>;
};
/* OS 2 */
mpic_msgr_block0: mpic-msgr-block@41400 {
compatible = "fsl,mpic-v3.1-msgr";
reg = <0x41400 0x200>;
interrupts = <0xb0 2 0xb2 2>;
mpic-msgr-receive-mask = <0x5>;
};
Now OS 1 has registers 0 and 2 available for general allocation, which
OS 2 is receiving on. However, we already have that problem if someone
botches the masks. So I am not very worried about that.
Clearly this is just one method, but I think tagging what is available from the
device tree is a must.
Thoughts?
--
Meador Inge | meador_inge AT mentor.com
Mentor Embedded | http://www.mentor.com/embedded-software
^ permalink raw reply
* Re: [RFC][PATCH] powerpc: respect how command line nr_cpus is set
From: Benjamin Herrenschmidt @ 2011-05-05 22:29 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <B122211D-FA1E-4B0D-8399-6EC4F701FCDF@kernel.crashing.org>
> From Documentation/kernel-parameters.txt:
>
> nr_cpus= [SMP] Maximum number of processors that an SMP kernel
> could support. nr_cpus=n : n >= 1 limits the kernel to
> supporting 'n' processors. Later in runtime you can not
> use hotplug cpu feature to put more cpu back to online.
> just like you compile the kernel NR_CPUS=n
>
> Which makes me think we should have max_cpus be an absolute limit.
Ok, looks like I've been confusing nr_cpus= vs. max_cpus= or something
like that.
I'll have a look at your patch later today.
Cheers,
Ben.
^ permalink raw reply
* [PATCH 2/2] powerpc/pseries: Add support for IO event interrupts
From: Tseng-Hui (Frank) Lin @ 2011-05-05 22:32 UTC (permalink / raw)
To: linuxppc-dev; +Cc: tsenglin
From: Tseng-Hui (Frank) Lin <thlin@linux.vnet.ibm.com>
This patch adds support for handling IO Event interrupts which come
through at the /event-sources/ibm,io-events device tree node.
The interrupts come through ibm,io-events device tree node are generated
by the firmware to report IO events. The firmware uses the same interrupt
to report multiple types of events for multiple devices. Each device may
have its own event handler. This patch implements a plateform interrupt
handler that is triggered by the IO event interrupts come through
ibm,io-events device tree node, pull in the IO events from RTAS and call
device event handlers registered in the notifier list.
Device event handlers are expected to use atomic_notifier_chain_register()
and atomic_notifier_chain_unregister() to register/unregister their
event handler in pseries_ioei_notifier_list list with IO event interrupt.
Device event handlers are responsible to identify if the event belongs
to the device event handler. The device event handle should return NOTIFY_OK
after the event is handled if the event belongs to the device event handler,
or NOTIFY_DONE otherwise.
Change log:
- Fixed compilation errors
- Fix comments to be docbook compliant
- Fix some code format
Signed-off-by: Tseng-Hui (Frank) Lin <thlin@us.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/io_event_irq.h | 54 ++++++
arch/powerpc/platforms/pseries/Kconfig | 18 ++
arch/powerpc/platforms/pseries/Makefile | 1 +
arch/powerpc/platforms/pseries/io_event_irq.c | 231 +++++++++++++++++++++++++
4 files changed, 304 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/include/asm/io_event_irq.h b/arch/powerpc/include/asm/io_event_irq.h
new file mode 100644
index 0000000..b1a9a1b
--- /dev/null
+++ b/arch/powerpc/include/asm/io_event_irq.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010, 2011 Mark Nelson and Tseng-Hui (Frank) Lin, IBM Corporation
+ *
+ * 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.
+ */
+
+#ifndef _ASM_POWERPC_IO_EVENT_IRQ_H
+#define _ASM_POWERPC_IO_EVENT_IRQ_H
+
+#include <linux/types.h>
+#include <linux/notifier.h>
+
+#define PSERIES_IOEI_RPC_MAX_LEN 216
+
+#define PSERIES_IOEI_TYPE_ERR_DETECTED 0x01
+#define PSERIES_IOEI_TYPE_ERR_RECOVERED 0x02
+#define PSERIES_IOEI_TYPE_EVENT 0x03
+#define PSERIES_IOEI_TYPE_RPC_PASS_THRU 0x04
+
+#define PSERIES_IOEI_SUBTYPE_NOT_APP 0x00
+#define PSERIES_IOEI_SUBTYPE_REBALANCE_REQ 0x01
+#define PSERIES_IOEI_SUBTYPE_NODE_ONLINE 0x03
+#define PSERIES_IOEI_SUBTYPE_NODE_OFFLINE 0x04
+#define PSERIES_IOEI_SUBTYPE_DUMP_SIZE_CHANGE 0x05
+#define PSERIES_IOEI_SUBTYPE_TORRENT_IRV_UPDATE 0x06
+#define PSERIES_IOEI_SUBTYPE_TORRENT_HFI_CFGED 0x07
+
+#define PSERIES_IOEI_SCOPE_NOT_APP 0x00
+#define PSERIES_IOEI_SCOPE_RIO_HUB 0x36
+#define PSERIES_IOEI_SCOPE_RIO_BRIDGE 0x37
+#define PSERIES_IOEI_SCOPE_PHB 0x38
+#define PSERIES_IOEI_SCOPE_EADS_GLOBAL 0x39
+#define PSERIES_IOEI_SCOPE_EADS_SLOT 0x3A
+#define PSERIES_IOEI_SCOPE_TORRENT_HUB 0x3B
+#define PSERIES_IOEI_SCOPE_SERVICE_PROC 0x51
+
+/* Platform Event Log Format, Version 6, data portition of IO event section */
+struct pseries_io_event {
+ uint8_t event_type; /* 0x00 IO-Event Type */
+ uint8_t rpc_data_len; /* 0x01 RPC data length */
+ uint8_t scope; /* 0x02 Error/Event Scope */
+ uint8_t event_subtype; /* 0x03 I/O-Event Sub-Type */
+ uint32_t drc_index; /* 0x04 DRC Index */
+ uint8_t rpc_data[PSERIES_IOEI_RPC_MAX_LEN];
+ /* 0x08 RPC Data (0-216 bytes, */
+ /* padded to 4 bytes alignment) */
+};
+
+extern struct atomic_notifier_head pseries_ioei_notifier_list;
+
+#endif /* _ASM_POWERPC_IO_EVENT_IRQ_H */
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index b044922..71af4c5 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -50,6 +50,24 @@ config SCANLOG
tristate "Scanlog dump interface"
depends on RTAS_PROC && PPC_PSERIES
+config IO_EVENT_IRQ
+ bool "IO Event Interrupt support"
+ depends on PPC_PSERIES
+ default y
+ help
+ Select this option, if you want to enable support for IO Event
+ interrupts. IO event interrupt is a mechanism provided by RTAS
+ to return information about hardware error and non-error events
+ which may need OS attention. RTAS returns events for multiple
+ event types and scopes. Device drivers can register their handlers
+ to receive events.
+
+ This option will only enable the IO event platform code. You
+ will still need to enable or compile the actual drivers
+ that use this infrastruture to handle IO event interrupts.
+
+ Say Y if you are unsure.
+
config LPARCFG
bool "LPAR Configuration Data"
depends on PPC_PSERIES || PPC_ISERIES
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 4cfefba..3556e40 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
obj-$(CONFIG_CMM) += cmm.o
obj-$(CONFIG_DTL) += dtl.o
+obj-$(CONFIG_IO_EVENT_IRQ) += io_event_irq.o
ifeq ($(CONFIG_PPC_PSERIES),y)
obj-$(CONFIG_SUSPEND) += suspend.o
diff --git a/arch/powerpc/platforms/pseries/io_event_irq.c b/arch/powerpc/platforms/pseries/io_event_irq.c
new file mode 100644
index 0000000..c829e60
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/io_event_irq.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2010 2011 Mark Nelson and Tseng-Hui (Frank) Lin, IBM Corporation
+ *
+ * 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/errno.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+
+#include <asm/machdep.h>
+#include <asm/rtas.h>
+#include <asm/irq.h>
+#include <asm/io_event_irq.h>
+
+#include "pseries.h"
+
+/*
+ * IO event interrupt is a mechanism provided by RTAS to return
+ * information about hardware error and non-error events. Device
+ * drivers can register their event handlers to receive events.
+ * Device drivers are expected to use atomic_notifier_chain_register()
+ * and atomic_notifier_chain_unregister() to register and unregister
+ * their event handlers. Since multiple IO event types and scopes
+ * share an IO event interrupt, the event handlers are called one
+ * by one until the IO event is claimed by one of the handlers.
+ * The event handlers are expected to return NOTIFY_OK if the
+ * event is handled by the event handler or NOTIFY_DONE if the
+ * event does not belong to the handler.
+ *
+ * Usage:
+ *
+ * Notifier function:
+ * #include <asm/io_event_irq.h>
+ * int event_handler(struct notifier_block *nb, unsigned long val, void *data) {
+ * p = (struct pseries_io_event_sect_data *) data;
+ * if (! is_my_event(p->scope, p->event_type)) return NOTIFY_DONE;
+ * :
+ * :
+ * return NOTIFY_OK;
+ * }
+ * struct notifier_block event_nb = {
+ * .notifier_call = event_handler,
+ * }
+ *
+ * Registration:
+ * atomic_notifier_chain_register(&pseries_ioei_notifier_list, &event_nb);
+ *
+ * Unregistration:
+ * atomic_notifier_chain_unregister(&pseries_ioei_notifier_list, &event_nb);
+ */
+
+ATOMIC_NOTIFIER_HEAD(pseries_ioei_notifier_list);
+EXPORT_SYMBOL_GPL(pseries_ioei_notifier_list);
+
+static int ioei_check_exception_token;
+
+/* pSeries event log format */
+
+/* Two bytes ASCII section IDs */
+#define PSERIES_ELOG_SECT_ID_PRIV_HDR (('P' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_USER_HDR (('U' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_PRIMARY_SRC (('P' << 8) | 'S')
+#define PSERIES_ELOG_SECT_ID_EXTENDED_UH (('E' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_FAILING_MTMS (('M' << 8) | 'T')
+#define PSERIES_ELOG_SECT_ID_SECONDARY_SRC (('S' << 8) | 'S')
+#define PSERIES_ELOG_SECT_ID_DUMP_LOCATOR (('D' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_FW_ERROR (('S' << 8) | 'W')
+#define PSERIES_ELOG_SECT_ID_IMPACT_PART_ID (('L' << 8) | 'P')
+#define PSERIES_ELOG_SECT_ID_LOGIC_RESOURCE_ID (('L' << 8) | 'R')
+#define PSERIES_ELOG_SECT_ID_HMC_ID (('H' << 8) | 'M')
+#define PSERIES_ELOG_SECT_ID_EPOW (('E' << 8) | 'P')
+#define PSERIES_ELOG_SECT_ID_IO_EVENT (('I' << 8) | 'E')
+#define PSERIES_ELOG_SECT_ID_MANUFACT_INFO (('M' << 8) | 'I')
+#define PSERIES_ELOG_SECT_ID_CALL_HOME (('C' << 8) | 'H')
+#define PSERIES_ELOG_SECT_ID_USER_DEF (('U' << 8) | 'D')
+
+/* Vendor specific Platform Event Log Format, Version 6, section header */
+struct pseries_elog_section {
+ uint16_t id; /* 0x00 2-byte ASCII section ID */
+ uint16_t length; /* 0x02 Section length in bytes */
+ uint8_t version; /* 0x04 Section version */
+ uint8_t subtype; /* 0x05 Section subtype */
+ uint16_t creator_component; /* 0x06 Creator component ID */
+ uint8_t data[]; /* 0x08 Start of section data */
+};
+
+static char ioei_rtas_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
+
+/**
+ * Find data portion of a specific section in RTAS extended event log.
+ * @elog: RTAS error/event log.
+ * @sect_id: secsion ID.
+ *
+ * Return:
+ * pointer to the section data of the specified section
+ * NULL if not found
+ */
+static struct pseries_elog_section *find_xelog_section(struct rtas_error_log *elog,
+ uint16_t sect_id)
+{
+ struct rtas_ext_event_log_v6 *xelog =
+ (struct rtas_ext_event_log_v6 *) elog->buffer;
+ struct pseries_elog_section *sect;
+ unsigned char *p, *log_end;
+
+ /* Check that we understand the format */
+ if (elog->extended_log_length < sizeof(struct rtas_ext_event_log_v6) ||
+ xelog->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
+ xelog->company_id != RTAS_V6EXT_COMPANY_ID_IBM)
+ return NULL;
+
+ log_end = elog->buffer + elog->extended_log_length;
+ p = xelog->vendor_log;
+ while (p < log_end) {
+ sect = (struct pseries_elog_section *)p;
+ if (sect->id == sect_id)
+ return sect;
+ p += sect->length;
+ }
+ return NULL;
+}
+
+/**
+ * Find the data portion of an IO Event section from event log.
+ * @elog: RTAS error/event log.
+ *
+ * Return:
+ * pointer to a valid IO event section data. NULL if not found.
+ */
+static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog)
+{
+ struct pseries_elog_section *sect;
+
+ /* We should only ever get called for io-event interrupts, but if
+ * we do get called for another type then something went wrong so
+ * make some noise about it.
+ * RTAS_TYPE_IO only exists in extended event log version 6 or later.
+ * No need to check event log version.
+ */
+ if (unlikely(elog->type != RTAS_TYPE_IO)) {
+ printk_once(KERN_WARNING "io_event_irq: Unexpected event type %d",
+ elog->type);
+ return NULL;
+ }
+
+ sect = find_xelog_section(elog, PSERIES_ELOG_SECT_ID_IO_EVENT);
+ if (unlikely(!sect)) {
+ printk_once(KERN_WARNING "io_event_irq: RTAS extended event "
+ "log does not contain an IO Event section. "
+ "Could be a bug in system firmware!\n");
+ return NULL;
+ }
+ return (struct pseries_io_event *) §->data;
+}
+
+/*
+ * PAPR:
+ * - check-exception returns the first found error or event and clear that
+ * error or event so it is reported once.
+ * - Each interrupt returns one event. If a plateform chooses to report
+ * multiple events through a single interrupt, it must ensure that the
+ * interrupt remains asserted until check-exception has been used to
+ * process all out-standing events for that interrupt.
+ *
+ * Implementation notes:
+ * - Events must be processed in the order they are returned. Hence,
+ * sequential in nature.
+ * - The owner of an event is determined by combinations of scope,
+ * event type, and sub-type. There is no easy way to pre-sort clients
+ * by scope or event type alone. For example, Torrent ISR route change
+ * event is reported with scope 0x00 (Not Applicatable) rather than
+ * 0x3B (Torrent-hub). It is better to let the clients to identify
+ * who owns the the event.
+ */
+
+static irqreturn_t ioei_interrupt(int irq, void *dev_id)
+{
+ struct pseries_io_event *event;
+ int rtas_rc;
+
+ for (;;) {
+ rtas_rc = rtas_call(ioei_check_exception_token, 6, 1, NULL,
+ RTAS_VECTOR_EXTERNAL_INTERRUPT,
+ virq_to_hw(irq),
+ RTAS_IO_EVENTS, 1 /* Time Critical */,
+ __pa(ioei_rtas_buf),
+ RTAS_DATA_BUF_SIZE);
+ if (rtas_rc != 0)
+ break;
+
+ event = ioei_find_event((struct rtas_error_log *)ioei_rtas_buf);
+ if (!event)
+ continue;
+
+ atomic_notifier_call_chain(&pseries_ioei_notifier_list,
+ 0, event);
+ }
+ return IRQ_HANDLED;
+}
+
+static int __init ioei_init(void)
+{
+ struct device_node *np;
+
+ ioei_check_exception_token = rtas_token("check-exception");
+ if (ioei_check_exception_token == RTAS_UNKNOWN_SERVICE) {
+ pr_warning("IO Event IRQ not supported on this system !\n");
+ return -ENODEV;
+ }
+ np = of_find_node_by_path("/event-sources/ibm,io-events");
+ if (np) {
+ request_event_sources_irqs(np, ioei_interrupt, "IO_EVENT");
+ of_node_put(np);
+ } else {
+ pr_err("io_event_irq: No ibm,io-events on system! "
+ "IO Event interrupt disabled.\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+machine_subsys_initcall(pseries, ioei_init);
+
^ permalink raw reply related
* [PATCH] powerpc, hw_breakpoints: Fix CONFIG_HAVE_HW_BREAKPOINT off-case in ptrace_set_debugreg
From: Frederic Weisbecker @ 2011-05-05 23:53 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Frederic Weisbecker, LPPC, LKML, Prasad, v2.6.33..
We make use of ptrace_get_breakpoints() / ptrace_put_breakpoints()
to protect ptrace_set_debugreg() even if CONFIG_HAVE_HW_BREAKPOINT
if off. However in this case, these APIs are not implemented.
To fix this, push the protection down inside the relevant ifdef.
Best would be to export the code inside CONFIG_HAVE_HW_BREAKPOINT
into a standalone function to cleanup the ifdefury there and call
the breakpoint ref API inside. But as it is more invasive, this
should be rather made in an -rc1.
Fixes:
arch/powerpc/kernel/ptrace.c:1594: error: implicit declaration of function 'ptrace_get_breakpoints'
make[2]: *** [arch/powerpc/kernel/ptrace.o] Error 1
make[1]: *** [arch/powerpc/kernel] Error 2
make: *** [sub-make] Error 2
Reported-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Prasad <prasad@linux.vnet.ibm.com>
Cc: v2.6.33.. <stable@kernel.org>
---
arch/powerpc/kernel/ptrace.c | 15 +++++++++++----
1 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 4edeeb3..a6ae1cf 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -933,12 +933,16 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
if (data && !(data & DABR_TRANSLATION))
return -EIO;
#ifdef CONFIG_HAVE_HW_BREAKPOINT
+ if (ptrace_get_breakpoints(task) < 0)
+ return -ESRCH;
+
bp = thread->ptrace_bps[0];
if ((!data) || !(data & (DABR_DATA_WRITE | DABR_DATA_READ))) {
if (bp) {
unregister_hw_breakpoint(bp);
thread->ptrace_bps[0] = NULL;
}
+ ptrace_put_breakpoints(task);
return 0;
}
if (bp) {
@@ -948,9 +952,12 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
(DABR_DATA_WRITE | DABR_DATA_READ),
&attr.bp_type);
ret = modify_user_hw_breakpoint(bp, &attr);
- if (ret)
+ if (ret) {
+ ptrace_put_breakpoints(task);
return ret;
+ }
thread->ptrace_bps[0] = bp;
+ ptrace_put_breakpoints(task);
thread->dabr = data;
return 0;
}
@@ -965,9 +972,12 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
ptrace_triggered, task);
if (IS_ERR(bp)) {
thread->ptrace_bps[0] = NULL;
+ ptrace_put_breakpoints(task);
return PTR_ERR(bp);
}
+ ptrace_put_breakpoints(task);
+
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
/* Move contents to the DABR register */
@@ -1591,10 +1601,7 @@ long arch_ptrace(struct task_struct *child, long request,
}
case PTRACE_SET_DEBUGREG:
- if (ptrace_get_breakpoints(child) < 0)
- return -ESRCH;
ret = ptrace_set_debugreg(child, addr, data);
- ptrace_put_breakpoints(child);
break;
#ifdef CONFIG_PPC64
--
1.7.3.2
^ permalink raw reply related
* Re: [PATCH 3/3] [repost] powerpc/eeh: Display eeh error location for bus and device
From: Benjamin Herrenschmidt @ 2011-05-06 0:46 UTC (permalink / raw)
To: Richard A Lary; +Cc: antonb, linuxppc-dev
In-Reply-To: <4DC1D9CE.4050104@linux.vnet.ibm.com>
On Wed, 2011-05-04 at 15:57 -0700, Richard A Lary wrote:
> From: Richard A Lary <rlary@linux.vnet.ibm.com>
>
> For adapters which have devices under a PCIe switch/bridge it is informative
> to display information for both the PCIe switch/bridge and the device on
> which the bus error was detected.
>
> rebased to powerpc-next
>
> Signed-off-by: Richard A Lary <rlary@linux.vnet.ibm.com>
> ---
Not sure what you're doing but it still doesn't apply for me. I think
the patch is whitespace damaged. IE. Some spaces have been added at
the beginning of each line. IE. "context" lines (nor patch lines
that start with - or +) seem to have -two- spaces at the beginning
of each line for some reason.
I suspect whatever you're using for email is corrupting patches.
Cheers,
Ben.
> ---
> arch/powerpc/platforms/pseries/eeh_driver.c | 22 13 + 9 - 0 !
> 1 file changed, 13 insertions(+), 9 deletions(-)
>
> Index: b/arch/powerpc/platforms/pseries/eeh_driver.c
> ===================================================================
> --- a/arch/powerpc/platforms/pseries/eeh_driver.c
> +++ b/arch/powerpc/platforms/pseries/eeh_driver.c
> @@ -328,7 +328,7 @@ struct pci_dn * handle_eeh_events (struc
> struct pci_bus *frozen_bus;
> int rc = 0;
> enum pci_ers_result result = PCI_ERS_RESULT_NONE;
> - const char *location, *pci_str, *drv_str;
> + const char *location, *pci_str, *drv_str, *bus_pci_str, *bus_drv_str;
>
> frozen_dn = find_device_pe(event->dn);
> if (!frozen_dn) {
> @@ -364,13 +364,8 @@ struct pci_dn * handle_eeh_events (struc
> frozen_pdn = PCI_DN(frozen_dn);
> frozen_pdn->eeh_freeze_count++;
>
> - if (frozen_pdn->pcidev) {
> - pci_str = pci_name (frozen_pdn->pcidev);
> - drv_str = pcid_name (frozen_pdn->pcidev);
> - } else {
> - pci_str = eeh_pci_name(event->dev);
> - drv_str = pcid_name (event->dev);
> - }
> + pci_str = eeh_pci_name(event->dev);
> + drv_str = pcid_name(event->dev);
>
> if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
> goto excess_failures;
> @@ -378,8 +373,17 @@ struct pci_dn * handle_eeh_events (struc
> printk(KERN_WARNING
> "EEH: This PCI device has failed %d times in the last hour:\n",
> frozen_pdn->eeh_freeze_count);
> +
> + if (frozen_pdn->pcidev) {
> + bus_pci_str = pci_name(frozen_pdn->pcidev);
> + bus_drv_str = pcid_name(frozen_pdn->pcidev);
> + printk(KERN_WARNING
> + "EEH: Bus location=%s driver=%s pci addr=%s\n",
> + location, bus_drv_str, bus_pci_str);
> + }
> +
> printk(KERN_WARNING
> - "EEH: location=%s driver=%s pci addr=%s\n",
> + "EEH: Device location=%s driver=%s pci addr=%s\n",
> location, drv_str, pci_str);
>
> /* Walk the various device drivers attached to this slot through
^ permalink raw reply
* Re: [PATCH 3/3] [repost] powerpc/eeh: Display eeh error location for bus and device
From: Benjamin Herrenschmidt @ 2011-05-06 0:50 UTC (permalink / raw)
To: Richard A Lary; +Cc: antonb, linuxppc-dev
In-Reply-To: <1304642771.2513.487.camel@pasglop>
On Fri, 2011-05-06 at 10:46 +1000, Benjamin Herrenschmidt wrote:
> On Wed, 2011-05-04 at 15:57 -0700, Richard A Lary wrote:
> > From: Richard A Lary <rlary@linux.vnet.ibm.com>
> >
> > For adapters which have devices under a PCIe switch/bridge it is informative
> > to display information for both the PCIe switch/bridge and the device on
> > which the bus error was detected.
> >
> > rebased to powerpc-next
> >
> > Signed-off-by: Richard A Lary <rlary@linux.vnet.ibm.com>
> > ---
>
> Not sure what you're doing but it still doesn't apply for me. I think
> the patch is whitespace damaged. IE. Some spaces have been added at
> the beginning of each line. IE. "context" lines (nor patch lines
> that start with - or +) seem to have -two- spaces at the beginning
> of each line for some reason.
>
> I suspect whatever you're using for email is corrupting patches.
BTW. I've hand applied it this time.
Cheers,
Ben.
> Cheers,
> Ben.
>
> > ---
> > arch/powerpc/platforms/pseries/eeh_driver.c | 22 13 + 9 - 0 !
> > 1 file changed, 13 insertions(+), 9 deletions(-)
> >
> > Index: b/arch/powerpc/platforms/pseries/eeh_driver.c
> > ===================================================================
> > --- a/arch/powerpc/platforms/pseries/eeh_driver.c
> > +++ b/arch/powerpc/platforms/pseries/eeh_driver.c
> > @@ -328,7 +328,7 @@ struct pci_dn * handle_eeh_events (struc
> > struct pci_bus *frozen_bus;
> > int rc = 0;
> > enum pci_ers_result result = PCI_ERS_RESULT_NONE;
> > - const char *location, *pci_str, *drv_str;
> > + const char *location, *pci_str, *drv_str, *bus_pci_str, *bus_drv_str;
> >
> > frozen_dn = find_device_pe(event->dn);
> > if (!frozen_dn) {
> > @@ -364,13 +364,8 @@ struct pci_dn * handle_eeh_events (struc
> > frozen_pdn = PCI_DN(frozen_dn);
> > frozen_pdn->eeh_freeze_count++;
> >
> > - if (frozen_pdn->pcidev) {
> > - pci_str = pci_name (frozen_pdn->pcidev);
> > - drv_str = pcid_name (frozen_pdn->pcidev);
> > - } else {
> > - pci_str = eeh_pci_name(event->dev);
> > - drv_str = pcid_name (event->dev);
> > - }
> > + pci_str = eeh_pci_name(event->dev);
> > + drv_str = pcid_name(event->dev);
> >
> > if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
> > goto excess_failures;
> > @@ -378,8 +373,17 @@ struct pci_dn * handle_eeh_events (struc
> > printk(KERN_WARNING
> > "EEH: This PCI device has failed %d times in the last hour:\n",
> > frozen_pdn->eeh_freeze_count);
> > +
> > + if (frozen_pdn->pcidev) {
> > + bus_pci_str = pci_name(frozen_pdn->pcidev);
> > + bus_drv_str = pcid_name(frozen_pdn->pcidev);
> > + printk(KERN_WARNING
> > + "EEH: Bus location=%s driver=%s pci addr=%s\n",
> > + location, bus_drv_str, bus_pci_str);
> > + }
> > +
> > printk(KERN_WARNING
> > - "EEH: location=%s driver=%s pci addr=%s\n",
> > + "EEH: Device location=%s driver=%s pci addr=%s\n",
> > location, drv_str, pci_str);
> >
> > /* Walk the various device drivers attached to this slot through
>
^ permalink raw reply
* Re: [PATCH 3/4] powerpc/mpic: parse 4-cell intspec types other than zero
From: Kumar Gala @ 2011-05-06 1:07 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <20110324214354.GB9524@schlenkerla.am.freescale.net>
On Mar 24, 2011, at 4:43 PM, Scott Wood wrote:
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> arch/powerpc/include/asm/mpic.h | 2 ++
> arch/powerpc/sysdev/mpic.c | 37 =
++++++++++++++++++++++++++++++++++++-
> 2 files changed, 38 insertions(+), 1 deletions(-)
Ben,
Did you plan on review and pull this in or expect me to?
- k
>=20
> diff --git a/arch/powerpc/include/asm/mpic.h =
b/arch/powerpc/include/asm/mpic.h
> index 7005ee0..25a0cb3 100644
> --- a/arch/powerpc/include/asm/mpic.h
> +++ b/arch/powerpc/include/asm/mpic.h
> @@ -371,6 +371,8 @@ struct mpic
> * NOTE: This flag trumps MPIC_WANTS_RESET.
> */
> #define MPIC_NO_RESET 0x00004000
> +/* Freescale MPIC (compatible includes "fsl,mpic") */
> +#define MPIC_FSL 0x00008000
>=20
> /* MPIC HW modification ID */
> #define MPIC_REGSET_MASK 0xf0000000
> diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
> index 0f7c671..69f96ec 100644
> --- a/arch/powerpc/sysdev/mpic.c
> +++ b/arch/powerpc/sysdev/mpic.c
> @@ -6,6 +6,7 @@
> * with various broken implementations of this HW.
> *
> * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
> + * Copyright 2010-2011 Freescale Semiconductor, Inc.
> *
> * This file is subject to the terms and conditions of the GNU =
General Public
> * License. See the file COPYING in the main directory of this =
archive
> @@ -1030,6 +1031,7 @@ static int mpic_host_xlate(struct irq_host *h, =
struct device_node *ct,
> irq_hw_number_t *out_hwirq, unsigned int =
*out_flags)
>=20
> {
> + struct mpic *mpic =3D h->host_data;
> static unsigned char map_mpic_senses[4] =3D {
> IRQ_TYPE_EDGE_RISING,
> IRQ_TYPE_LEVEL_LOW,
> @@ -1038,7 +1040,38 @@ static int mpic_host_xlate(struct irq_host *h, =
struct device_node *ct,
> };
>=20
> *out_hwirq =3D intspec[0];
> - if (intsize > 1) {
> + if (intsize >=3D 4 && (mpic->flags & MPIC_FSL)) {
> + /*
> + * Freescale MPIC with extended intspec:
> + * First two cells are as usual. Third specifies
> + * an "interrupt type". Fourth is type-specific data.
> + *
> + * See =
Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
> + */
> + switch (intspec[2]) {
> + case 0:
> + case 1: /* no EISR/EIMR support for now, treat as shared =
IRQ */
> + break;
> + case 2:
> + if (intspec[0] >=3D ARRAY_SIZE(mpic->ipi_vecs))
> + return -EINVAL;
> +
> + *out_hwirq =3D mpic->ipi_vecs[intspec[0]];
> + break;
> + case 3:
> + if (intspec[0] >=3D =
ARRAY_SIZE(mpic->timer_vecs))
> + return -EINVAL;
> +
> + *out_hwirq =3D mpic->timer_vecs[intspec[0]];
> + break;
> + default:
> + pr_debug("%s: unknown irq type %u\n",
> + __func__, intspec[2]);
> + return -EINVAL;
> + }
> +
> + *out_flags =3D map_mpic_senses[intspec[1] & 3];
> + } else if (intsize > 1) {
> u32 mask =3D 0x3;
>=20
> /* Apple invented a new race of encoding on machines =
with
> @@ -1137,6 +1170,8 @@ struct mpic * __init mpic_alloc(struct =
device_node *node,
> /* Check for "big-endian" in device-tree */
> if (node && of_get_property(node, "big-endian", NULL) !=3D NULL)
> mpic->flags |=3D MPIC_BIG_ENDIAN;
> + if (node && of_device_is_compatible(node, "fsl,mpic"))
> + mpic->flags |=3D MPIC_FSL;
>=20
> /* Look for protected sources */
> if (node) {
> --=20
> 1.7.1
>=20
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox