* [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
@ 2010-10-18 12:32 zhangfei gao
2010-10-18 14:58 ` Wolfram Sang
2010-10-21 14:13 ` Chris Ball
0 siblings, 2 replies; 20+ messages in thread
From: zhangfei gao @ 2010-10-18 12:32 UTC (permalink / raw)
To: linux-mmc; +Cc: Chris Ball, eric.y.miao, Matt Fleming, Haojian Zhuang
[-- Attachment #1: Type: text/plain, Size: 10087 bytes --]
Update with comments from Matt and Eric.
Test with sd and emmc.
>From e5dd554ed4d3488a83d9a4888d68d1d85482f747 Mon Sep 17 00:00:00 2001
From: Zhangfei Gao <zhangfei.gao@marvell.com>
Date: Mon, 20 Sep 2010 10:51:28 -0400
Subject: [PATCH] mmc: add support of sdhci-pxa driver
Support Marvell PXA168/PXA910/MMP2 SD Host Controller
Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
---
arch/arm/plat-pxa/include/plat/sdhci.h | 32 ++++
drivers/mmc/host/Kconfig | 12 ++
drivers/mmc/host/Makefile | 1 +
drivers/mmc/host/sdhci-pxa.c | 259 ++++++++++++++++++++++++++++++++
4 files changed, 304 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/plat-pxa/include/plat/sdhci.h
create mode 100644 drivers/mmc/host/sdhci-pxa.c
diff --git a/arch/arm/plat-pxa/include/plat/sdhci.h
b/arch/arm/plat-pxa/include/plat/sdhci.h
new file mode 100644
index 0000000..38e86ad
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/sdhci.h
@@ -0,0 +1,32 @@
+/* linux/arch/arm/plat-pxa/include/plat/sdhci.h
+ *
+ * Copyright 2010 Marvell
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ *
+ * PXA Platform - SDHCI platform data definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_PXA_SDHCI_H
+#define __PLAT_PXA_SDHCI_H
+
+/* pxa specific flag */
+/* Require clock free running */
+#define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)
+
+/**
+ * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
+ * @max_speed: The maximum speed supported.
+ * @quirks: quirks of specific device
+ * @flags: flags for platfrom requirement
+*/
+struct sdhci_pxa_platdata {
+ unsigned int max_speed;
+ unsigned int quirks;
+ unsigned int flags;
+};
+
+#endif /* __PLAT_PXA_SDHCI_H */
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index c9c2520..c387402 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -155,6 +155,18 @@ config MMC_SDHCI_S3C
If unsure, say N.
+config MMC_SDHCI_PXA
+ tristate "Marvell PXA168/PXA910/MMP2 SD Host Controller support"
+ depends on ARCH_PXA || ARCH_MMP
+ select MMC_SDHCI
+ select MMC_SDHCI_IO_ACCESSORS
+ help
+ This selects the Marvell(R) PXA168/PXA910/MMP2 SD Host Controller.
+ If you have a PXA168/PXA910/MMP2 platform with SD Host Controller and a
+ card slot,say Y or M here.
+
+ If unsure, say N.
+
config MMC_SDHCI_SPEAR
tristate "SDHCI support on ST SPEAr platform"
depends on MMC_SDHCI && PLAT_SPEAR
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 6c4ac67..7b645ff 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_MMC_IMX) += imxmmc.o
obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
+obj-$(CONFIG_MMC_SDHCI_PXA) += sdhci-pxa.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c
new file mode 100644
index 0000000..93b9237
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pxa.c
@@ -0,0 +1,259 @@
+/* linux/drivers/mmc/host/sdhci-pxa.c
+ *
+ * Copyright (C) 2010 Marvell International Ltd.
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ * Kevin Wang <dwang4@marvell.com>
+ * Mingwei Wang <mwwang@marvell.com>
+ * Philip Rakity <prakity@marvell.com>
+ * Mark Brown <markb@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Supports:
+ * SDHCI support for MMP2/PXA910/PXA168
+ *
+ * Refer sdhci-s3c.c
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <plat/sdhci.h>
+#include "sdhci.h"
+
+#define DRIVER_NAME "sdhci-pxa"
+
+#define SD_FIFO_PARAM 0x104
+#define DIS_PAD_SD_CLK_GATE 0x400
+
+struct sdhci_pxa {
+ struct sdhci_host *host;
+ struct sdhci_pxa_platdata *pdata;
+ struct clk *clk;
+ struct resource *res;
+
+ u8 clk_enable;
+};
+
+/*****************************************************************************\
+ * *
+ * SDHCI core callbacks *
+ * *
+\*****************************************************************************/
+static void set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ struct sdhci_pxa *pxa = sdhci_priv(host);
+ u32 tmp = 0;
+
+ if (clock == 0) {
+ if (pxa->clk_enable) {
+ clk_disable(pxa->clk);
+ pxa->clk_enable = 0;
+ }
+ } else {
+ if (0 == pxa->clk_enable) {
+ if (pxa->pdata->flags
+ & PXA_FLAG_DISABLE_CLOCK_GATING) {
+ tmp = readl(host->ioaddr + SD_FIFO_PARAM);
+ tmp |= DIS_PAD_SD_CLK_GATE;
+ writel(tmp, host->ioaddr + SD_FIFO_PARAM);
+ }
+ clk_enable(pxa->clk);
+ pxa->clk_enable = 1;
+ }
+ }
+}
+
+static struct sdhci_ops sdhci_pxa_ops = {
+ .set_clock = set_clock,
+};
+
+/*****************************************************************************\
+ * *
+ * Device probing/removal *
+ * *
+\*****************************************************************************/
+
+static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
+{
+ struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct sdhci_host *host = NULL;
+ struct resource *iomem = NULL;
+ struct sdhci_pxa *pxa = NULL;
+ int ret, irq;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no irq specified\n");
+ return irq;
+ }
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem) {
+ dev_err(dev, "no memory specified\n");
+ return -ENOENT;
+ }
+
+ host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
+ if (IS_ERR(host)) {
+ dev_err(dev, "failed to alloc host\n");
+ return PTR_ERR(host);
+ }
+
+ pxa = sdhci_priv(host);
+ pxa->host = host;
+ pxa->pdata = pdata;
+ pxa->clk_enable = 0;
+
+ pxa->clk = clk_get(dev, "PXA-SDHCLK");
+ if (IS_ERR(pxa->clk)) {
+ dev_err(dev, "failed to get io clock\n");
+ ret = PTR_ERR(pxa->clk);
+ goto out;
+ }
+
+ pxa->res = request_mem_region(iomem->start, resource_size(iomem),
+ mmc_hostname(host->mmc));
+ if (!pxa->res) {
+ dev_err(&pdev->dev, "cannot request region\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ host->ioaddr = ioremap(iomem->start, resource_size(iomem));
+ if (!host->ioaddr) {
+ dev_err(&pdev->dev, "failed to remap registers\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ host->hw_name = "MMC";
+ host->ops = &sdhci_pxa_ops;
+ host->irq = irq;
+ host->quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
+ if (pdata->quirks)
+ host->quirks |= pdata->quirks;
+
+ ret = sdhci_add_host(host);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add host\n");
+ goto out;
+ }
+
+ if (pxa->pdata->max_speed)
+ host->mmc->f_max = pxa->pdata->max_speed;
+
+ platform_set_drvdata(pdev, host);
+
+ return 0;
+out:
+ if (host) {
+ clk_put(pxa->clk);
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ if (pxa->res)
+ release_mem_region(pxa->res->start,
+ resource_size(pxa->res));
+ sdhci_free_host(host);
+ }
+
+ return ret;
+}
+
+static int __devexit sdhci_pxa_remove(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pxa *pxa = sdhci_priv(host);
+ int dead = 0;
+ u32 scratch;
+
+ if (host) {
+ scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
+ if (scratch == (u32)-1)
+ dead = 1;
+
+ sdhci_remove_host(host, dead);
+
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ if (pxa->res)
+ release_mem_region(pxa->res->start,
+ resource_size(pxa->res));
+ if (pxa->clk_enable) {
+ clk_disable(pxa->clk);
+ pxa->clk_enable = 0;
+ }
+ clk_put(pxa->clk);
+
+ sdhci_free_host(host);
+ platform_set_drvdata(pdev, NULL);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int sdhci_pxa_suspend(struct platform_device *dev)
+{
+ struct sdhci_host *host = platform_get_drvdata(to_platform_device(dev));
+
+ return sdhci_suspend_host(host, state);
+}
+
+static int sdhci_pxa_resume(struct platform_device *dev)
+{
+ struct sdhci_host *host = platform_get_drvdata(to_platform_device(dev));
+
+ return sdhci_resume_host(host);
+}
+#else
+#define sdhci_pxa_suspend NULL
+#define sdhci_pxa_resume NULL
+#endif
+
+static const struct dev_pm_ops sdhci_pxa_pm_ops = {
+ .suspend = sdhci_pxa_suspend,
+ .resume = sdhci_pxa_resume,
+};
+
+
+static struct platform_driver sdhci_pxa_driver = {
+ .probe = sdhci_pxa_probe,
+ .remove = __devexit_p(sdhci_pxa_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &sdhci_pxa_pm_ops,
+ },
+};
+
+/*****************************************************************************\
+ * *
+ * Driver init/exit *
+ * *
+\*****************************************************************************/
+
+static int __init sdhci_pxa_init(void)
+{
+ return platform_driver_register(&sdhci_pxa_driver);
+}
+
+static void __exit sdhci_pxa_exit(void)
+{
+ platform_driver_unregister(&sdhci_pxa_driver);
+}
+
+module_init(sdhci_pxa_init);
+module_exit(sdhci_pxa_exit);
+
+MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2");
+MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>");
+MODULE_LICENSE("GPL v2");
--
1.7.0.4
[-- Attachment #2: 0001-mmc-add-support-of-sdhci-pxa-driver.patch --]
[-- Type: text/x-patch, Size: 10024 bytes --]
From e5dd554ed4d3488a83d9a4888d68d1d85482f747 Mon Sep 17 00:00:00 2001
From: Zhangfei Gao <zhangfei.gao@marvell.com>
Date: Mon, 20 Sep 2010 10:51:28 -0400
Subject: [PATCH] mmc: add support of sdhci-pxa driver
Support Marvell PXA168/PXA910/MMP2 SD Host Controller
Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
---
arch/arm/plat-pxa/include/plat/sdhci.h | 32 ++++
drivers/mmc/host/Kconfig | 12 ++
drivers/mmc/host/Makefile | 1 +
drivers/mmc/host/sdhci-pxa.c | 259 ++++++++++++++++++++++++++++++++
4 files changed, 304 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/plat-pxa/include/plat/sdhci.h
create mode 100644 drivers/mmc/host/sdhci-pxa.c
diff --git a/arch/arm/plat-pxa/include/plat/sdhci.h b/arch/arm/plat-pxa/include/plat/sdhci.h
new file mode 100644
index 0000000..38e86ad
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/sdhci.h
@@ -0,0 +1,32 @@
+/* linux/arch/arm/plat-pxa/include/plat/sdhci.h
+ *
+ * Copyright 2010 Marvell
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ *
+ * PXA Platform - SDHCI platform data definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_PXA_SDHCI_H
+#define __PLAT_PXA_SDHCI_H
+
+/* pxa specific flag */
+/* Require clock free running */
+#define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)
+
+/**
+ * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
+ * @max_speed: The maximum speed supported.
+ * @quirks: quirks of specific device
+ * @flags: flags for platfrom requirement
+*/
+struct sdhci_pxa_platdata {
+ unsigned int max_speed;
+ unsigned int quirks;
+ unsigned int flags;
+};
+
+#endif /* __PLAT_PXA_SDHCI_H */
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index c9c2520..c387402 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -155,6 +155,18 @@ config MMC_SDHCI_S3C
If unsure, say N.
+config MMC_SDHCI_PXA
+ tristate "Marvell PXA168/PXA910/MMP2 SD Host Controller support"
+ depends on ARCH_PXA || ARCH_MMP
+ select MMC_SDHCI
+ select MMC_SDHCI_IO_ACCESSORS
+ help
+ This selects the Marvell(R) PXA168/PXA910/MMP2 SD Host Controller.
+ If you have a PXA168/PXA910/MMP2 platform with SD Host Controller and a
+ card slot,say Y or M here.
+
+ If unsure, say N.
+
config MMC_SDHCI_SPEAR
tristate "SDHCI support on ST SPEAr platform"
depends on MMC_SDHCI && PLAT_SPEAR
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 6c4ac67..7b645ff 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_MMC_IMX) += imxmmc.o
obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
+obj-$(CONFIG_MMC_SDHCI_PXA) += sdhci-pxa.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c
new file mode 100644
index 0000000..93b9237
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pxa.c
@@ -0,0 +1,259 @@
+/* linux/drivers/mmc/host/sdhci-pxa.c
+ *
+ * Copyright (C) 2010 Marvell International Ltd.
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ * Kevin Wang <dwang4@marvell.com>
+ * Mingwei Wang <mwwang@marvell.com>
+ * Philip Rakity <prakity@marvell.com>
+ * Mark Brown <markb@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Supports:
+ * SDHCI support for MMP2/PXA910/PXA168
+ *
+ * Refer sdhci-s3c.c
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <plat/sdhci.h>
+#include "sdhci.h"
+
+#define DRIVER_NAME "sdhci-pxa"
+
+#define SD_FIFO_PARAM 0x104
+#define DIS_PAD_SD_CLK_GATE 0x400
+
+struct sdhci_pxa {
+ struct sdhci_host *host;
+ struct sdhci_pxa_platdata *pdata;
+ struct clk *clk;
+ struct resource *res;
+
+ u8 clk_enable;
+};
+
+/*****************************************************************************\
+ * *
+ * SDHCI core callbacks *
+ * *
+\*****************************************************************************/
+static void set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ struct sdhci_pxa *pxa = sdhci_priv(host);
+ u32 tmp = 0;
+
+ if (clock == 0) {
+ if (pxa->clk_enable) {
+ clk_disable(pxa->clk);
+ pxa->clk_enable = 0;
+ }
+ } else {
+ if (0 == pxa->clk_enable) {
+ if (pxa->pdata->flags
+ & PXA_FLAG_DISABLE_CLOCK_GATING) {
+ tmp = readl(host->ioaddr + SD_FIFO_PARAM);
+ tmp |= DIS_PAD_SD_CLK_GATE;
+ writel(tmp, host->ioaddr + SD_FIFO_PARAM);
+ }
+ clk_enable(pxa->clk);
+ pxa->clk_enable = 1;
+ }
+ }
+}
+
+static struct sdhci_ops sdhci_pxa_ops = {
+ .set_clock = set_clock,
+};
+
+/*****************************************************************************\
+ * *
+ * Device probing/removal *
+ * *
+\*****************************************************************************/
+
+static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
+{
+ struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct sdhci_host *host = NULL;
+ struct resource *iomem = NULL;
+ struct sdhci_pxa *pxa = NULL;
+ int ret, irq;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no irq specified\n");
+ return irq;
+ }
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem) {
+ dev_err(dev, "no memory specified\n");
+ return -ENOENT;
+ }
+
+ host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
+ if (IS_ERR(host)) {
+ dev_err(dev, "failed to alloc host\n");
+ return PTR_ERR(host);
+ }
+
+ pxa = sdhci_priv(host);
+ pxa->host = host;
+ pxa->pdata = pdata;
+ pxa->clk_enable = 0;
+
+ pxa->clk = clk_get(dev, "PXA-SDHCLK");
+ if (IS_ERR(pxa->clk)) {
+ dev_err(dev, "failed to get io clock\n");
+ ret = PTR_ERR(pxa->clk);
+ goto out;
+ }
+
+ pxa->res = request_mem_region(iomem->start, resource_size(iomem),
+ mmc_hostname(host->mmc));
+ if (!pxa->res) {
+ dev_err(&pdev->dev, "cannot request region\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ host->ioaddr = ioremap(iomem->start, resource_size(iomem));
+ if (!host->ioaddr) {
+ dev_err(&pdev->dev, "failed to remap registers\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ host->hw_name = "MMC";
+ host->ops = &sdhci_pxa_ops;
+ host->irq = irq;
+ host->quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
+ if (pdata->quirks)
+ host->quirks |= pdata->quirks;
+
+ ret = sdhci_add_host(host);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add host\n");
+ goto out;
+ }
+
+ if (pxa->pdata->max_speed)
+ host->mmc->f_max = pxa->pdata->max_speed;
+
+ platform_set_drvdata(pdev, host);
+
+ return 0;
+out:
+ if (host) {
+ clk_put(pxa->clk);
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ if (pxa->res)
+ release_mem_region(pxa->res->start,
+ resource_size(pxa->res));
+ sdhci_free_host(host);
+ }
+
+ return ret;
+}
+
+static int __devexit sdhci_pxa_remove(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pxa *pxa = sdhci_priv(host);
+ int dead = 0;
+ u32 scratch;
+
+ if (host) {
+ scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
+ if (scratch == (u32)-1)
+ dead = 1;
+
+ sdhci_remove_host(host, dead);
+
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ if (pxa->res)
+ release_mem_region(pxa->res->start,
+ resource_size(pxa->res));
+ if (pxa->clk_enable) {
+ clk_disable(pxa->clk);
+ pxa->clk_enable = 0;
+ }
+ clk_put(pxa->clk);
+
+ sdhci_free_host(host);
+ platform_set_drvdata(pdev, NULL);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int sdhci_pxa_suspend(struct platform_device *dev)
+{
+ struct sdhci_host *host = platform_get_drvdata(to_platform_device(dev));
+
+ return sdhci_suspend_host(host, state);
+}
+
+static int sdhci_pxa_resume(struct platform_device *dev)
+{
+ struct sdhci_host *host = platform_get_drvdata(to_platform_device(dev));
+
+ return sdhci_resume_host(host);
+}
+#else
+#define sdhci_pxa_suspend NULL
+#define sdhci_pxa_resume NULL
+#endif
+
+static const struct dev_pm_ops sdhci_pxa_pm_ops = {
+ .suspend = sdhci_pxa_suspend,
+ .resume = sdhci_pxa_resume,
+};
+
+
+static struct platform_driver sdhci_pxa_driver = {
+ .probe = sdhci_pxa_probe,
+ .remove = __devexit_p(sdhci_pxa_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &sdhci_pxa_pm_ops,
+ },
+};
+
+/*****************************************************************************\
+ * *
+ * Driver init/exit *
+ * *
+\*****************************************************************************/
+
+static int __init sdhci_pxa_init(void)
+{
+ return platform_driver_register(&sdhci_pxa_driver);
+}
+
+static void __exit sdhci_pxa_exit(void)
+{
+ platform_driver_unregister(&sdhci_pxa_driver);
+}
+
+module_init(sdhci_pxa_init);
+module_exit(sdhci_pxa_exit);
+
+MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2");
+MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>");
+MODULE_LICENSE("GPL v2");
--
1.7.0.4
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-18 12:32 [PATCH V3 1/1]MMC: add support of sdhci-pxa driver zhangfei gao
@ 2010-10-18 14:58 ` Wolfram Sang
2010-10-18 15:25 ` zhangfei gao
2010-10-21 14:13 ` Chris Ball
1 sibling, 1 reply; 20+ messages in thread
From: Wolfram Sang @ 2010-10-18 14:58 UTC (permalink / raw)
To: zhangfei gao
Cc: linux-mmc, Chris Ball, eric.y.miao, Matt Fleming, Haojian Zhuang
[-- Attachment #1: Type: text/plain, Size: 375 bytes --]
On Mon, Oct 18, 2010 at 08:32:46AM -0400, zhangfei gao wrote:
> Update with comments from Matt and Eric.
> Test with sd and emmc.
Sorry if I am blind, but why again can't you use the (updated) platform driver?
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-18 14:58 ` Wolfram Sang
@ 2010-10-18 15:25 ` zhangfei gao
2010-10-19 2:03 ` Wolfram Sang
0 siblings, 1 reply; 20+ messages in thread
From: zhangfei gao @ 2010-10-18 15:25 UTC (permalink / raw)
To: Wolfram Sang
Cc: linux-mmc, Chris Ball, eric.y.miao, Matt Fleming, Haojian Zhuang
On Mon, Oct 18, 2010 at 10:58 PM, Wolfram Sang <w.sang@pengutronix.de> wrote:
> On Mon, Oct 18, 2010 at 08:32:46AM -0400, zhangfei gao wrote:
>> Update with comments from Matt and Eric.
>> Test with sd and emmc.
>
> Sorry if I am blind, but why again can't you use the (updated) platform driver?
Currently platform driver can not support well of the requirement for
several device sharing one driver, each one has different quirk,
different max_speed, and each device need some specific vectors.
We prefer using independent driver first.
>
> --
> Pengutronix e.K. | Wolfram Sang |
> Industrial Linux Solutions | http://www.pengutronix.de/ |
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAky8YJkACgkQD27XaX1/VRtQqACfUOXAYcCu0ui25S/2pXIaQdWK
> hJEAn3ZW7tKsIn7cSg8gkehIzPS8im4p
> =04el
> -----END PGP SIGNATURE-----
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-18 15:25 ` zhangfei gao
@ 2010-10-19 2:03 ` Wolfram Sang
2010-10-19 9:44 ` zhangfei gao
0 siblings, 1 reply; 20+ messages in thread
From: Wolfram Sang @ 2010-10-19 2:03 UTC (permalink / raw)
To: zhangfei gao
Cc: linux-mmc, Chris Ball, eric.y.miao, Matt Fleming, Haojian Zhuang
[-- Attachment #1: Type: text/plain, Size: 478 bytes --]
> Currently platform driver can not support well of the requirement for
> several device sharing one driver, each one has different quirk,
> different max_speed, and each device need some specific vectors.
> We prefer using independent driver first.
What about a custom init-call reading out the platform_data?
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-19 2:03 ` Wolfram Sang
@ 2010-10-19 9:44 ` zhangfei gao
0 siblings, 0 replies; 20+ messages in thread
From: zhangfei gao @ 2010-10-19 9:44 UTC (permalink / raw)
To: Wolfram Sang
Cc: linux-mmc, Chris Ball, eric.y.miao, Matt Fleming, Haojian Zhuang
On Mon, Oct 18, 2010 at 10:03 PM, Wolfram Sang <w.sang@pengutronix.de> wrote:
>> Currently platform driver can not support well of the requirement for
>> several device sharing one driver, each one has different quirk,
>> different max_speed, and each device need some specific vectors.
>> We prefer using independent driver first.
>
> What about a custom init-call reading out the platform_data?
Which one are you talking?
For the different quirk, we have already discussed before, the quirk
in sdhci_pltfm_data is shared in different device, which may impact
each other.
We don't want to be blocked in using what manner.
>
> --
> Pengutronix e.K. | Wolfram Sang |
> Industrial Linux Solutions | http://www.pengutronix.de/ |
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAky8/IQACgkQD27XaX1/VRuYkQCfaPUOLkDwZ+mCW9ztlGJnAy85
> S4oAn1MEL5UhA7bTi8+H5fcMSEEPmZwC
> =6MTu
> -----END PGP SIGNATURE-----
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-18 12:32 [PATCH V3 1/1]MMC: add support of sdhci-pxa driver zhangfei gao
2010-10-18 14:58 ` Wolfram Sang
@ 2010-10-21 14:13 ` Chris Ball
2010-10-21 14:20 ` zhangfei gao
2010-10-21 14:52 ` Chris Ball
1 sibling, 2 replies; 20+ messages in thread
From: Chris Ball @ 2010-10-21 14:13 UTC (permalink / raw)
To: zhangfei gao
Cc: linux-mmc, Wolfram Sang, eric.y.miao, Matt Fleming,
Haojian Zhuang
Hi Zhangfei,
On Mon, Oct 18, 2010 at 08:32:46AM -0400, zhangfei gao wrote:
> Update with comments from Matt and Eric.
> Test with sd and emmc.
>
> >From e5dd554ed4d3488a83d9a4888d68d1d85482f747 Mon Sep 17 00:00:00 2001
> From: Zhangfei Gao <zhangfei.gao@marvell.com>
> Date: Mon, 20 Sep 2010 10:51:28 -0400
> Subject: [PATCH] mmc: add support of sdhci-pxa driver
>
> Support Marvell PXA168/PXA910/MMP2 SD Host Controller
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
> ---
> arch/arm/plat-pxa/include/plat/sdhci.h | 32 ++++
> drivers/mmc/host/Kconfig | 12 ++
> drivers/mmc/host/Makefile | 1 +
> drivers/mmc/host/sdhci-pxa.c | 259 ++++++++++++++++++++++++++++++++
> 4 files changed, 304 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/plat-pxa/include/plat/sdhci.h
> create mode 100644 drivers/mmc/host/sdhci-pxa.c
I'll take the drivers/mmc/ hunks, but you should send the plat-pxa/
patch through the ARM tree.
Thanks,
--
Chris Ball <cjb@laptop.org> <http://printf.net/>
One Laptop Per Child
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-21 14:13 ` Chris Ball
@ 2010-10-21 14:20 ` zhangfei gao
2010-10-21 14:52 ` Chris Ball
1 sibling, 0 replies; 20+ messages in thread
From: zhangfei gao @ 2010-10-21 14:20 UTC (permalink / raw)
To: Chris Ball
Cc: linux-mmc, Wolfram Sang, eric.y.miao, Matt Fleming,
Haojian Zhuang
On Thu, Oct 21, 2010 at 10:13 PM, Chris Ball <cjb@laptop.org> wrote:
> Hi Zhangfei,
>
> On Mon, Oct 18, 2010 at 08:32:46AM -0400, zhangfei gao wrote:
>> Update with comments from Matt and Eric.
>> Test with sd and emmc.
>>
>> >From e5dd554ed4d3488a83d9a4888d68d1d85482f747 Mon Sep 17 00:00:00 2001
>> From: Zhangfei Gao <zhangfei.gao@marvell.com>
>> Date: Mon, 20 Sep 2010 10:51:28 -0400
>> Subject: [PATCH] mmc: add support of sdhci-pxa driver
>>
>> Support Marvell PXA168/PXA910/MMP2 SD Host Controller
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
>> ---
>> arch/arm/plat-pxa/include/plat/sdhci.h | 32 ++++
>> drivers/mmc/host/Kconfig | 12 ++
>> drivers/mmc/host/Makefile | 1 +
>> drivers/mmc/host/sdhci-pxa.c | 259 ++++++++++++++++++++++++++++++++
>> 4 files changed, 304 insertions(+), 0 deletions(-)
>> create mode 100644 arch/arm/plat-pxa/include/plat/sdhci.h
>> create mode 100644 drivers/mmc/host/sdhci-pxa.c
>
> I'll take the drivers/mmc/ hunks, but you should send the plat-pxa/
> patch through the ARM tree.
Thanks a lot, what a relief :)
>
> Thanks,
>
> --
> Chris Ball <cjb@laptop.org> <http://printf.net/>
> One Laptop Per Child
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-21 14:13 ` Chris Ball
2010-10-21 14:20 ` zhangfei gao
@ 2010-10-21 14:52 ` Chris Ball
2010-10-22 0:20 ` Marek Vasut
2010-10-22 8:44 ` Haojian Zhuang
1 sibling, 2 replies; 20+ messages in thread
From: Chris Ball @ 2010-10-21 14:52 UTC (permalink / raw)
To: zhangfei gao
Cc: Matt Fleming, eric.y.miao, linux-mmc, Wolfram Sang,
Haojian Zhuang, linux-arm-kernel
Hi,
On Thu, Oct 21, 2010 at 03:13:02PM +0100, Chris Ball wrote:
> On Mon, Oct 18, 2010 at 08:32:46AM -0400, zhangfei gao wrote:
> > Update with comments from Matt and Eric.
> > Test with sd and emmc.
> >
> > >From e5dd554ed4d3488a83d9a4888d68d1d85482f747 Mon Sep 17 00:00:00 2001
> > From: Zhangfei Gao <zhangfei.gao@marvell.com>
> > Date: Mon, 20 Sep 2010 10:51:28 -0400
> > Subject: [PATCH] mmc: add support of sdhci-pxa driver
> >
> > Support Marvell PXA168/PXA910/MMP2 SD Host Controller
> >
> > Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
> > ---
> > arch/arm/plat-pxa/include/plat/sdhci.h | 32 ++++
> > drivers/mmc/host/Kconfig | 12 ++
> > drivers/mmc/host/Makefile | 1 +
> > drivers/mmc/host/sdhci-pxa.c | 259 ++++++++++++++++++++++++++++++++
> > 4 files changed, 304 insertions(+), 0 deletions(-)
> > create mode 100644 arch/arm/plat-pxa/include/plat/sdhci.h
> > create mode 100644 drivers/mmc/host/sdhci-pxa.c
>
> I'll take the drivers/mmc/ hunks, but you should send the plat-pxa/
> patch through the ARM tree.
Oh. If we do that then the driver won't compile until everything's
together, because it #includes <plat/sdhci.h>. Haojian/Eric, what do
you prefer here? Should I take the arch/arm/ hunk via the MMC tree?
(If so, please provide ACKs.)
Thanks,
--
Chris Ball <cjb@laptop.org> <http://printf.net/>
One Laptop Per Child
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-21 14:52 ` Chris Ball
@ 2010-10-22 0:20 ` Marek Vasut
2010-10-22 0:27 ` Chris Ball
2010-10-22 8:44 ` Haojian Zhuang
1 sibling, 1 reply; 20+ messages in thread
From: Marek Vasut @ 2010-10-22 0:20 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Chris Ball, zhangfei gao, Matt Fleming, eric.y.miao, linux-mmc,
Wolfram Sang, Haojian Zhuang
Dne Čt 21. října 2010 16:52:49 Chris Ball napsal(a):
> Hi,
>
> On Thu, Oct 21, 2010 at 03:13:02PM +0100, Chris Ball wrote:
> > On Mon, Oct 18, 2010 at 08:32:46AM -0400, zhangfei gao wrote:
> > > Update with comments from Matt and Eric.
> > > Test with sd and emmc.
> > >
> > > >From e5dd554ed4d3488a83d9a4888d68d1d85482f747 Mon Sep 17 00:00:00 2001
> > >
> > > From: Zhangfei Gao <zhangfei.gao@marvell.com>
> > > Date: Mon, 20 Sep 2010 10:51:28 -0400
> > > Subject: [PATCH] mmc: add support of sdhci-pxa driver
> > >
> > > Support Marvell PXA168/PXA910/MMP2 SD Host Controller
> > >
> > > Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
> > > ---
> > >
> > > arch/arm/plat-pxa/include/plat/sdhci.h | 32 ++++
> > > drivers/mmc/host/Kconfig | 12 ++
> > > drivers/mmc/host/Makefile | 1 +
> > > drivers/mmc/host/sdhci-pxa.c | 259
> > > ++++++++++++++++++++++++++++++++ 4 files changed, 304 insertions(+),
> > > 0 deletions(-)
> > > create mode 100644 arch/arm/plat-pxa/include/plat/sdhci.h
> > > create mode 100644 drivers/mmc/host/sdhci-pxa.c
> >
> > I'll take the drivers/mmc/ hunks, but you should send the plat-pxa/
> > patch through the ARM tree.
>
> Oh. If we do that then the driver won't compile until everything's
> together, because it #includes <plat/sdhci.h>. Haojian/Eric, what do
> you prefer here? Should I take the arch/arm/ hunk via the MMC tree?
> (If so, please provide ACKs.)
>
> Thanks,
Hi, where can I find the whole driver so I can take a look? It didn't crash into
linux-arm-kernel for some reason.
Thanks
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-22 0:20 ` Marek Vasut
@ 2010-10-22 0:27 ` Chris Ball
0 siblings, 0 replies; 20+ messages in thread
From: Chris Ball @ 2010-10-22 0:27 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-arm-kernel, zhangfei gao, Matt Fleming, eric.y.miao,
linux-mmc, Wolfram Sang, Haojian Zhuang
Hi Marek,
On Fri, Oct 22, 2010 at 02:20:10AM +0200, Marek Vasut wrote:
> > > I'll take the drivers/mmc/ hunks, but you should send the plat-pxa/
> > > patch through the ARM tree.
> >
> > Oh. If we do that then the driver won't compile until everything's
> > together, because it #includes <plat/sdhci.h>. Haojian/Eric, what do
> > you prefer here? Should I take the arch/arm/ hunk via the MMC tree?
> > (If so, please provide ACKs.)
>
> Hi, where can I find the whole driver so I can take a look? It didn't
> crash into linux-arm-kernel for some reason.
Here it is:
http://thread.gmane.org/gmane.linux.kernel.mmc/4190
--
Chris Ball <cjb@laptop.org> <http://printf.net/>
One Laptop Per Child
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-21 14:52 ` Chris Ball
2010-10-22 0:20 ` Marek Vasut
@ 2010-10-22 8:44 ` Haojian Zhuang
2010-10-22 9:58 ` Chris Ball
1 sibling, 1 reply; 20+ messages in thread
From: Haojian Zhuang @ 2010-10-22 8:44 UTC (permalink / raw)
To: Chris Ball
Cc: zhangfei gao, linux-mmc, linux-arm-kernel, Wolfram Sang,
eric.y.miao, Matt Fleming
On Thu, Oct 21, 2010 at 10:52 PM, Chris Ball <cjb@laptop.org> wrote:
> Hi,
>
> On Thu, Oct 21, 2010 at 03:13:02PM +0100, Chris Ball wrote:
>> On Mon, Oct 18, 2010 at 08:32:46AM -0400, zhangfei gao wrote:
>> > Update with comments from Matt and Eric.
>> > Test with sd and emmc.
>> >
>> > >From e5dd554ed4d3488a83d9a4888d68d1d85482f747 Mon Sep 17 00:00:00 2001
>> > From: Zhangfei Gao <zhangfei.gao@marvell.com>
>> > Date: Mon, 20 Sep 2010 10:51:28 -0400
>> > Subject: [PATCH] mmc: add support of sdhci-pxa driver
>> >
>> > Support Marvell PXA168/PXA910/MMP2 SD Host Controller
>> >
>> > Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
>> > ---
>> > arch/arm/plat-pxa/include/plat/sdhci.h | 32 ++++
>> > drivers/mmc/host/Kconfig | 12 ++
>> > drivers/mmc/host/Makefile | 1 +
>> > drivers/mmc/host/sdhci-pxa.c | 259 ++++++++++++++++++++++++++++++++
>> > 4 files changed, 304 insertions(+), 0 deletions(-)
>> > create mode 100644 arch/arm/plat-pxa/include/plat/sdhci.h
>> > create mode 100644 drivers/mmc/host/sdhci-pxa.c
>>
>> I'll take the drivers/mmc/ hunks, but you should send the plat-pxa/
>> patch through the ARM tree.
>
> Oh. If we do that then the driver won't compile until everything's
> together, because it #includes <plat/sdhci.h>. Haojian/Eric, what do
> you prefer here? Should I take the arch/arm/ hunk via the MMC tree?
> (If so, please provide ACKs.)
>
Acked-by: Haojian Zhuang.
I'm fine on this. Please merge it via the MMC tree.
Thanks
Haojian
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-22 8:44 ` Haojian Zhuang
@ 2010-10-22 9:58 ` Chris Ball
2010-10-22 11:04 ` Chris Ball
0 siblings, 1 reply; 20+ messages in thread
From: Chris Ball @ 2010-10-22 9:58 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Haojian Zhuang, zhangfei gao, linux-mmc, linux-arm-kernel,
Wolfram Sang, eric.y.miao, Matt Fleming
Hi Russell,
On Fri, Oct 22, 2010 at 04:44:07PM +0800, Haojian Zhuang wrote:
> I'm fine on this. Please merge it via the MMC tree.
I'm planning on merging this patch via the MMC tree, please let me know
if you object. Thanks.
From: Zhangfei Gao <zhangfei.gao@marvell.com>
Date: Mon, 20 Sep 2010 10:51:28 -0400
Subject: [PATCH] mmc: add new sdhci-pxa driver for Marvell SoCs
Support Marvell PXA168/PXA910/MMP2 SD Host Controller.
Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
Acked-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
---
arch/arm/plat-pxa/include/plat/sdhci.h | 32 ++++
drivers/mmc/host/Kconfig | 12 ++
drivers/mmc/host/Makefile | 1 +
drivers/mmc/host/sdhci-pxa.c | 258 ++++++++++++++++++++++++++++++++
4 files changed, 303 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/plat-pxa/include/plat/sdhci.h
create mode 100644 drivers/mmc/host/sdhci-pxa.c
diff --git a/arch/arm/plat-pxa/include/plat/sdhci.h b/arch/arm/plat-pxa/include/plat/sdhci.h
new file mode 100644
index 0000000..3e3c728
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/sdhci.h
@@ -0,0 +1,32 @@
+/* linux/arch/arm/plat-pxa/include/plat/sdhci.h
+ *
+ * Copyright 2010 Marvell
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ *
+ * PXA Platform - SDHCI platform data definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_PXA_SDHCI_H
+#define __PLAT_PXA_SDHCI_H
+
+/* pxa specific flag */
+/* Require clock free running */
+#define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)
+
+/**
+ * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
+ * @max_speed: the maximum speed supported
+ * @quirks: quirks of specific device
+ * @flags: flags for platform requirement
+*/
+struct sdhci_pxa_platdata {
+ unsigned int max_speed;
+ unsigned int quirks;
+ unsigned int flags;
+};
+
+#endif /* __PLAT_PXA_SDHCI_H */
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index c9c2520..40b0fb9 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -155,6 +155,18 @@ config MMC_SDHCI_S3C
If unsure, say N.
+config MMC_SDHCI_PXA
+ tristate "Marvell PXA168/PXA910/MMP2 SD Host Controller support"
+ depends on ARCH_PXA || ARCH_MMP
+ select MMC_SDHCI
+ select MMC_SDHCI_IO_ACCESSORS
+ help
+ This selects the Marvell(R) PXA168/PXA910/MMP2 SD Host Controller.
+ If you have a PXA168/PXA910/MMP2 platform with SD Host Controller
+ and a card slot, say Y or M here.
+
+ If unsure, say N.
+
config MMC_SDHCI_SPEAR
tristate "SDHCI support on ST SPEAr platform"
depends on MMC_SDHCI && PLAT_SPEAR
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 6c4ac67..7b645ff 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_MMC_IMX) += imxmmc.o
obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
+obj-$(CONFIG_MMC_SDHCI_PXA) += sdhci-pxa.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c
new file mode 100644
index 0000000..aeba3e3
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pxa.c
@@ -0,0 +1,258 @@
+/* linux/drivers/mmc/host/sdhci-pxa.c
+ *
+ * Copyright (C) 2010 Marvell International Ltd.
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ * Kevin Wang <dwang4@marvell.com>
+ * Mingwei Wang <mwwang@marvell.com>
+ * Philip Rakity <prakity@marvell.com>
+ * Mark Brown <markb@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Supports:
+ * SDHCI support for MMP2/PXA910/PXA168
+ *
+ * Refer to sdhci-s3c.c.
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <plat/sdhci.h>
+#include "sdhci.h"
+
+#define DRIVER_NAME "sdhci-pxa"
+
+#define SD_FIFO_PARAM 0x104
+#define DIS_PAD_SD_CLK_GATE 0x400
+
+struct sdhci_pxa {
+ struct sdhci_host *host;
+ struct sdhci_pxa_platdata *pdata;
+ struct clk *clk;
+ struct resource *res;
+
+ u8 clk_enable;
+};
+
+/*****************************************************************************\
+ * *
+ * SDHCI core callbacks *
+ * *
+\*****************************************************************************/
+static void set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ struct sdhci_pxa *pxa = sdhci_priv(host);
+ u32 tmp = 0;
+
+ if (clock == 0) {
+ if (pxa->clk_enable) {
+ clk_disable(pxa->clk);
+ pxa->clk_enable = 0;
+ }
+ } else {
+ if (0 == pxa->clk_enable) {
+ if (pxa->pdata->flags & PXA_FLAG_DISABLE_CLOCK_GATING) {
+ tmp = readl(host->ioaddr + SD_FIFO_PARAM);
+ tmp |= DIS_PAD_SD_CLK_GATE;
+ writel(tmp, host->ioaddr + SD_FIFO_PARAM);
+ }
+ clk_enable(pxa->clk);
+ pxa->clk_enable = 1;
+ }
+ }
+}
+
+static struct sdhci_ops sdhci_pxa_ops = {
+ .set_clock = set_clock,
+};
+
+/*****************************************************************************\
+ * *
+ * Device probing/removal *
+ * *
+\*****************************************************************************/
+
+static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
+{
+ struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct sdhci_host *host = NULL;
+ struct resource *iomem = NULL;
+ struct sdhci_pxa *pxa = NULL;
+ int ret, irq;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no irq specified\n");
+ return irq;
+ }
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem) {
+ dev_err(dev, "no memory specified\n");
+ return -ENOENT;
+ }
+
+ host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
+ if (IS_ERR(host)) {
+ dev_err(dev, "failed to alloc host\n");
+ return PTR_ERR(host);
+ }
+
+ pxa = sdhci_priv(host);
+ pxa->host = host;
+ pxa->pdata = pdata;
+ pxa->clk_enable = 0;
+
+ pxa->clk = clk_get(dev, "PXA-SDHCLK");
+ if (IS_ERR(pxa->clk)) {
+ dev_err(dev, "failed to get io clock\n");
+ ret = PTR_ERR(pxa->clk);
+ goto out;
+ }
+
+ pxa->res = request_mem_region(iomem->start, resource_size(iomem),
+ mmc_hostname(host->mmc));
+ if (!pxa->res) {
+ dev_err(&pdev->dev, "cannot request region\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ host->ioaddr = ioremap(iomem->start, resource_size(iomem));
+ if (!host->ioaddr) {
+ dev_err(&pdev->dev, "failed to remap registers\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ host->hw_name = "MMC";
+ host->ops = &sdhci_pxa_ops;
+ host->irq = irq;
+ host->quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
+ if (pdata->quirks)
+ host->quirks |= pdata->quirks;
+
+ ret = sdhci_add_host(host);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add host\n");
+ goto out;
+ }
+
+ if (pxa->pdata->max_speed)
+ host->mmc->f_max = pxa->pdata->max_speed;
+
+ platform_set_drvdata(pdev, host);
+
+ return 0;
+out:
+ if (host) {
+ clk_put(pxa->clk);
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ if (pxa->res)
+ release_mem_region(pxa->res->start,
+ resource_size(pxa->res));
+ sdhci_free_host(host);
+ }
+
+ return ret;
+}
+
+static int __devexit sdhci_pxa_remove(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pxa *pxa = sdhci_priv(host);
+ int dead = 0;
+ u32 scratch;
+
+ if (host) {
+ scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
+ if (scratch == (u32)-1)
+ dead = 1;
+
+ sdhci_remove_host(host, dead);
+
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ if (pxa->res)
+ release_mem_region(pxa->res->start,
+ resource_size(pxa->res));
+ if (pxa->clk_enable) {
+ clk_disable(pxa->clk);
+ pxa->clk_enable = 0;
+ }
+ clk_put(pxa->clk);
+
+ sdhci_free_host(host);
+ platform_set_drvdata(pdev, NULL);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int sdhci_pxa_suspend(struct platform_device *dev)
+{
+ struct sdhci_host *host = platform_get_drvdata(to_platform_device(dev));
+
+ return sdhci_suspend_host(host, state);
+}
+
+static int sdhci_pxa_resume(struct platform_device *dev)
+{
+ struct sdhci_host *host = platform_get_drvdata(to_platform_device(dev));
+
+ return sdhci_resume_host(host);
+}
+#else
+#define sdhci_pxa_suspend NULL
+#define sdhci_pxa_resume NULL
+#endif
+
+static const struct dev_pm_ops sdhci_pxa_pm_ops = {
+ .suspend = sdhci_pxa_suspend,
+ .resume = sdhci_pxa_resume,
+};
+
+
+static struct platform_driver sdhci_pxa_driver = {
+ .probe = sdhci_pxa_probe,
+ .remove = __devexit_p(sdhci_pxa_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &sdhci_pxa_pm_ops,
+ },
+};
+
+/*****************************************************************************\
+ * *
+ * Driver init/exit *
+ * *
+\*****************************************************************************/
+
+static int __init sdhci_pxa_init(void)
+{
+ return platform_driver_register(&sdhci_pxa_driver);
+}
+
+static void __exit sdhci_pxa_exit(void)
+{
+ platform_driver_unregister(&sdhci_pxa_driver);
+}
+
+module_init(sdhci_pxa_init);
+module_exit(sdhci_pxa_exit);
+
+MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2");
+MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>");
+MODULE_LICENSE("GPL v2");
--
Chris Ball <cjb@laptop.org> <http://printf.net/>
One Laptop Per Child
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-22 9:58 ` Chris Ball
@ 2010-10-22 11:04 ` Chris Ball
2010-10-22 14:09 ` zhangfei gao
0 siblings, 1 reply; 20+ messages in thread
From: Chris Ball @ 2010-10-22 11:04 UTC (permalink / raw)
To: zhangfei gao
Cc: Haojian Zhuang, linux-mmc, linux-arm-kernel, Wolfram Sang,
eric.y.miao, Matt Fleming
Hi,
On Fri, Oct 22, 2010 at 10:58:14AM +0100, Chris Ball wrote:
[...]
> +#ifdef CONFIG_PM
> +static int sdhci_pxa_suspend(struct platform_device *dev)
> +{
> + struct sdhci_host *host = platform_get_drvdata(to_platform_device(dev));
> +
> + return sdhci_suspend_host(host, state);
> +}
> +
> +static int sdhci_pxa_resume(struct platform_device *dev)
> +{
These prototypes are not correct, leading to:
CC [M] drivers/mmc/host/sdhci-pxa.o
drivers/mmc/host/sdhci-pxa.c: In function ‘sdhci_pxa_suspend’:
drivers/mmc/host/sdhci-pxa.c:205: warning: initialization from incompatible pointer type
drivers/mmc/host/sdhci-pxa.c:207: error: ‘state’ undeclared (first use in this function)
drivers/mmc/host/sdhci-pxa.c:207: error: (Each undeclared identifier is reported only once
drivers/mmc/host/sdhci-pxa.c:207: error: for each function it appears in.)
drivers/mmc/host/sdhci-pxa.c: In function ‘sdhci_pxa_resume’:
drivers/mmc/host/sdhci-pxa.c:212: warning: initialization from incompatible pointer type
drivers/mmc/host/sdhci-pxa.c: At top level:
drivers/mmc/host/sdhci-pxa.c:222: warning: initialization from incompatible pointer type
drivers/mmc/host/sdhci-pxa.c:223: warning: initialization from incompatible pointer type
when compiled with CONFIG_PM=y.
--
Chris Ball <cjb@laptop.org> <http://printf.net/>
One Laptop Per Child
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-22 11:04 ` Chris Ball
@ 2010-10-22 14:09 ` zhangfei gao
2010-10-23 14:24 ` Marek Vasut
0 siblings, 1 reply; 20+ messages in thread
From: zhangfei gao @ 2010-10-22 14:09 UTC (permalink / raw)
To: Chris Ball
Cc: Matt Fleming, eric.y.miao, linux-mmc, Wolfram Sang,
Haojian Zhuang, linux-arm-kernel
[-- Attachment #1: Type: text/plain, Size: 11879 bytes --]
On Fri, Oct 22, 2010 at 7:04 AM, Chris Ball <cjb@laptop.org> wrote:
> Hi,
>
> On Fri, Oct 22, 2010 at 10:58:14AM +0100, Chris Ball wrote:
> [...]
>> +#ifdef CONFIG_PM
>> +static int sdhci_pxa_suspend(struct platform_device *dev)
>> +{
>> + struct sdhci_host *host = platform_get_drvdata(to_platform_device(dev));
>> +
>> + return sdhci_suspend_host(host, state);
>> +}
>> +
>> +static int sdhci_pxa_resume(struct platform_device *dev)
>> +{
>
> These prototypes are not correct, leading to:
>
> CC [M] drivers/mmc/host/sdhci-pxa.o
> drivers/mmc/host/sdhci-pxa.c: In function ‘sdhci_pxa_suspend’:
> drivers/mmc/host/sdhci-pxa.c:205: warning: initialization from incompatible pointer type
> drivers/mmc/host/sdhci-pxa.c:207: error: ‘state’ undeclared (first use in this function)
> drivers/mmc/host/sdhci-pxa.c:207: error: (Each undeclared identifier is reported only once
> drivers/mmc/host/sdhci-pxa.c:207: error: for each function it appears in.)
> drivers/mmc/host/sdhci-pxa.c: In function ‘sdhci_pxa_resume’:
> drivers/mmc/host/sdhci-pxa.c:212: warning: initialization from incompatible pointer type
> drivers/mmc/host/sdhci-pxa.c: At top level:
> drivers/mmc/host/sdhci-pxa.c:222: warning: initialization from incompatible pointer type
> drivers/mmc/host/sdhci-pxa.c:223: warning: initialization from incompatible pointer type
>
> when compiled with CONFIG_PM=y.
>
> --
> Chris Ball <cjb@laptop.org> <http://printf.net/>
> One Laptop Per Child
>
Sorry, forgot open CONFIG_PM.
Updated patch, thanks
>From 88e7f028433fe87b211bf3d75b54261979d0d176 Mon Sep 17 00:00:00 2001
From: Zhangfei Gao <zhangfei.gao@marvell.com>
Date: Mon, 20 Sep 2010 10:51:28 -0400
Subject: [PATCH] mmc: add support of sdhci-pxa driver
Support Marvell PXA168/PXA910/MMP2 SD Host Controller
Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
Acked-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
arch/arm/plat-pxa/include/plat/sdhci.h | 32 ++++
drivers/mmc/host/Kconfig | 12 ++
drivers/mmc/host/Makefile | 1 +
drivers/mmc/host/sdhci-pxa.c | 254 ++++++++++++++++++++++++++++++++
4 files changed, 299 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/plat-pxa/include/plat/sdhci.h
create mode 100644 drivers/mmc/host/sdhci-pxa.c
diff --git a/arch/arm/plat-pxa/include/plat/sdhci.h
b/arch/arm/plat-pxa/include/plat/sdhci.h
new file mode 100644
index 0000000..38e86ad
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/sdhci.h
@@ -0,0 +1,32 @@
+/* linux/arch/arm/plat-pxa/include/plat/sdhci.h
+ *
+ * Copyright 2010 Marvell
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ *
+ * PXA Platform - SDHCI platform data definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_PXA_SDHCI_H
+#define __PLAT_PXA_SDHCI_H
+
+/* pxa specific flag */
+/* Require clock free running */
+#define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)
+
+/**
+ * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
+ * @max_speed: The maximum speed supported.
+ * @quirks: quirks of specific device
+ * @flags: flags for platfrom requirement
+*/
+struct sdhci_pxa_platdata {
+ unsigned int max_speed;
+ unsigned int quirks;
+ unsigned int flags;
+};
+
+#endif /* __PLAT_PXA_SDHCI_H */
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index c9c2520..c387402 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -155,6 +155,18 @@ config MMC_SDHCI_S3C
If unsure, say N.
+config MMC_SDHCI_PXA
+ tristate "Marvell PXA168/PXA910/MMP2 SD Host Controller support"
+ depends on ARCH_PXA || ARCH_MMP
+ select MMC_SDHCI
+ select MMC_SDHCI_IO_ACCESSORS
+ help
+ This selects the Marvell(R) PXA168/PXA910/MMP2 SD Host Controller.
+ If you have a PXA168/PXA910/MMP2 platform with SD Host Controller and a
+ card slot,say Y or M here.
+
+ If unsure, say N.
+
config MMC_SDHCI_SPEAR
tristate "SDHCI support on ST SPEAr platform"
depends on MMC_SDHCI && PLAT_SPEAR
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 6c4ac67..7b645ff 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_MMC_IMX) += imxmmc.o
obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
+obj-$(CONFIG_MMC_SDHCI_PXA) += sdhci-pxa.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c
new file mode 100644
index 0000000..abf208c
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pxa.c
@@ -0,0 +1,254 @@
+/* linux/drivers/mmc/host/sdhci-pxa.c
+ *
+ * Copyright (C) 2010 Marvell International Ltd.
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ * Kevin Wang <dwang4@marvell.com>
+ * Mingwei Wang <mwwang@marvell.com>
+ * Philip Rakity <prakity@marvell.com>
+ * Mark Brown <markb@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Supports:
+ * SDHCI support for MMP2/PXA910/PXA168
+ *
+ * Refer sdhci-s3c.c
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <plat/sdhci.h>
+#include "sdhci.h"
+
+#define DRIVER_NAME "sdhci-pxa"
+
+#define SD_FIFO_PARAM 0x104
+#define DIS_PAD_SD_CLK_GATE 0x400
+
+struct sdhci_pxa {
+ struct sdhci_host *host;
+ struct sdhci_pxa_platdata *pdata;
+ struct clk *clk;
+ struct resource *res;
+
+ u8 clk_enable;
+};
+
+/*****************************************************************************\
+ * *
+ * SDHCI core callbacks *
+ * *
+\*****************************************************************************/
+static void set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ struct sdhci_pxa *pxa = sdhci_priv(host);
+ u32 tmp = 0;
+
+ if (clock == 0) {
+ if (pxa->clk_enable) {
+ clk_disable(pxa->clk);
+ pxa->clk_enable = 0;
+ }
+ } else {
+ if (0 == pxa->clk_enable) {
+ if (pxa->pdata->flags
+ & PXA_FLAG_DISABLE_CLOCK_GATING) {
+ tmp = readl(host->ioaddr + SD_FIFO_PARAM);
+ tmp |= DIS_PAD_SD_CLK_GATE;
+ writel(tmp, host->ioaddr + SD_FIFO_PARAM);
+ }
+ clk_enable(pxa->clk);
+ pxa->clk_enable = 1;
+ }
+ }
+}
+
+static struct sdhci_ops sdhci_pxa_ops = {
+ .set_clock = set_clock,
+};
+
+/*****************************************************************************\
+ * *
+ * Device probing/removal *
+ * *
+\*****************************************************************************/
+
+static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
+{
+ struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct sdhci_host *host = NULL;
+ struct resource *iomem = NULL;
+ struct sdhci_pxa *pxa = NULL;
+ int ret, irq;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no irq specified\n");
+ return irq;
+ }
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem) {
+ dev_err(dev, "no memory specified\n");
+ return -ENOENT;
+ }
+
+ host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
+ if (IS_ERR(host)) {
+ dev_err(dev, "failed to alloc host\n");
+ return PTR_ERR(host);
+ }
+
+ pxa = sdhci_priv(host);
+ pxa->host = host;
+ pxa->pdata = pdata;
+ pxa->clk_enable = 0;
+
+ pxa->clk = clk_get(dev, "PXA-SDHCLK");
+ if (IS_ERR(pxa->clk)) {
+ dev_err(dev, "failed to get io clock\n");
+ ret = PTR_ERR(pxa->clk);
+ goto out;
+ }
+
+ pxa->res = request_mem_region(iomem->start, resource_size(iomem),
+ mmc_hostname(host->mmc));
+ if (!pxa->res) {
+ dev_err(&pdev->dev, "cannot request region\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ host->ioaddr = ioremap(iomem->start, resource_size(iomem));
+ if (!host->ioaddr) {
+ dev_err(&pdev->dev, "failed to remap registers\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ host->hw_name = "MMC";
+ host->ops = &sdhci_pxa_ops;
+ host->irq = irq;
+ host->quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
+ if (pdata->quirks)
+ host->quirks |= pdata->quirks;
+
+ ret = sdhci_add_host(host);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add host\n");
+ goto out;
+ }
+
+ if (pxa->pdata->max_speed)
+ host->mmc->f_max = pxa->pdata->max_speed;
+
+ platform_set_drvdata(pdev, host);
+
+ return 0;
+out:
+ if (host) {
+ clk_put(pxa->clk);
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ if (pxa->res)
+ release_mem_region(pxa->res->start,
+ resource_size(pxa->res));
+ sdhci_free_host(host);
+ }
+
+ return ret;
+}
+
+static int __devexit sdhci_pxa_remove(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pxa *pxa = sdhci_priv(host);
+ int dead = 0;
+ u32 scratch;
+
+ if (host) {
+ scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
+ if (scratch == (u32)-1)
+ dead = 1;
+
+ sdhci_remove_host(host, dead);
+
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ if (pxa->res)
+ release_mem_region(pxa->res->start,
+ resource_size(pxa->res));
+ if (pxa->clk_enable) {
+ clk_disable(pxa->clk);
+ pxa->clk_enable = 0;
+ }
+ clk_put(pxa->clk);
+
+ sdhci_free_host(host);
+ platform_set_drvdata(pdev, NULL);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int sdhci_pxa_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_pxa_resume(struct platform_device *dev)
+{
+ struct sdhci_host *host = platform_get_drvdata(dev);
+
+ return sdhci_resume_host(host);
+}
+#else
+#define sdhci_pxa_suspend NULL
+#define sdhci_pxa_resume NULL
+#endif
+
+static struct platform_driver sdhci_pxa_driver = {
+ .probe = sdhci_pxa_probe,
+ .remove = __devexit_p(sdhci_pxa_remove),
+ .suspend = sdhci_pxa_suspend,
+ .resume = sdhci_pxa_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+/*****************************************************************************\
+ * *
+ * Driver init/exit *
+ * *
+\*****************************************************************************/
+
+static int __init sdhci_pxa_init(void)
+{
+ return platform_driver_register(&sdhci_pxa_driver);
+}
+
+static void __exit sdhci_pxa_exit(void)
+{
+ platform_driver_unregister(&sdhci_pxa_driver);
+}
+
+module_init(sdhci_pxa_init);
+module_exit(sdhci_pxa_exit);
+
+MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2");
+MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>");
+MODULE_LICENSE("GPL v2");
--
1.7.0.4
[-- Attachment #2: 0001-mmc-add-support-of-sdhci-pxa-driver.patch --]
[-- Type: text/x-patch, Size: 9969 bytes --]
From 88e7f028433fe87b211bf3d75b54261979d0d176 Mon Sep 17 00:00:00 2001
From: Zhangfei Gao <zhangfei.gao@marvell.com>
Date: Mon, 20 Sep 2010 10:51:28 -0400
Subject: [PATCH] mmc: add support of sdhci-pxa driver
Support Marvell PXA168/PXA910/MMP2 SD Host Controller
Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
Acked-by: Haojian Zhuang <haojian.zhuang@marvell.com>
---
arch/arm/plat-pxa/include/plat/sdhci.h | 32 ++++
drivers/mmc/host/Kconfig | 12 ++
drivers/mmc/host/Makefile | 1 +
drivers/mmc/host/sdhci-pxa.c | 254 ++++++++++++++++++++++++++++++++
4 files changed, 299 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/plat-pxa/include/plat/sdhci.h
create mode 100644 drivers/mmc/host/sdhci-pxa.c
diff --git a/arch/arm/plat-pxa/include/plat/sdhci.h b/arch/arm/plat-pxa/include/plat/sdhci.h
new file mode 100644
index 0000000..38e86ad
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/sdhci.h
@@ -0,0 +1,32 @@
+/* linux/arch/arm/plat-pxa/include/plat/sdhci.h
+ *
+ * Copyright 2010 Marvell
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ *
+ * PXA Platform - SDHCI platform data definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_PXA_SDHCI_H
+#define __PLAT_PXA_SDHCI_H
+
+/* pxa specific flag */
+/* Require clock free running */
+#define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)
+
+/**
+ * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
+ * @max_speed: The maximum speed supported.
+ * @quirks: quirks of specific device
+ * @flags: flags for platfrom requirement
+*/
+struct sdhci_pxa_platdata {
+ unsigned int max_speed;
+ unsigned int quirks;
+ unsigned int flags;
+};
+
+#endif /* __PLAT_PXA_SDHCI_H */
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index c9c2520..c387402 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -155,6 +155,18 @@ config MMC_SDHCI_S3C
If unsure, say N.
+config MMC_SDHCI_PXA
+ tristate "Marvell PXA168/PXA910/MMP2 SD Host Controller support"
+ depends on ARCH_PXA || ARCH_MMP
+ select MMC_SDHCI
+ select MMC_SDHCI_IO_ACCESSORS
+ help
+ This selects the Marvell(R) PXA168/PXA910/MMP2 SD Host Controller.
+ If you have a PXA168/PXA910/MMP2 platform with SD Host Controller and a
+ card slot,say Y or M here.
+
+ If unsure, say N.
+
config MMC_SDHCI_SPEAR
tristate "SDHCI support on ST SPEAr platform"
depends on MMC_SDHCI && PLAT_SPEAR
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 6c4ac67..7b645ff 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_MMC_IMX) += imxmmc.o
obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
+obj-$(CONFIG_MMC_SDHCI_PXA) += sdhci-pxa.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c
new file mode 100644
index 0000000..abf208c
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pxa.c
@@ -0,0 +1,254 @@
+/* linux/drivers/mmc/host/sdhci-pxa.c
+ *
+ * Copyright (C) 2010 Marvell International Ltd.
+ * Zhangfei Gao <zhangfei.gao@marvell.com>
+ * Kevin Wang <dwang4@marvell.com>
+ * Mingwei Wang <mwwang@marvell.com>
+ * Philip Rakity <prakity@marvell.com>
+ * Mark Brown <markb@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Supports:
+ * SDHCI support for MMP2/PXA910/PXA168
+ *
+ * Refer sdhci-s3c.c
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <plat/sdhci.h>
+#include "sdhci.h"
+
+#define DRIVER_NAME "sdhci-pxa"
+
+#define SD_FIFO_PARAM 0x104
+#define DIS_PAD_SD_CLK_GATE 0x400
+
+struct sdhci_pxa {
+ struct sdhci_host *host;
+ struct sdhci_pxa_platdata *pdata;
+ struct clk *clk;
+ struct resource *res;
+
+ u8 clk_enable;
+};
+
+/*****************************************************************************\
+ * *
+ * SDHCI core callbacks *
+ * *
+\*****************************************************************************/
+static void set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ struct sdhci_pxa *pxa = sdhci_priv(host);
+ u32 tmp = 0;
+
+ if (clock == 0) {
+ if (pxa->clk_enable) {
+ clk_disable(pxa->clk);
+ pxa->clk_enable = 0;
+ }
+ } else {
+ if (0 == pxa->clk_enable) {
+ if (pxa->pdata->flags
+ & PXA_FLAG_DISABLE_CLOCK_GATING) {
+ tmp = readl(host->ioaddr + SD_FIFO_PARAM);
+ tmp |= DIS_PAD_SD_CLK_GATE;
+ writel(tmp, host->ioaddr + SD_FIFO_PARAM);
+ }
+ clk_enable(pxa->clk);
+ pxa->clk_enable = 1;
+ }
+ }
+}
+
+static struct sdhci_ops sdhci_pxa_ops = {
+ .set_clock = set_clock,
+};
+
+/*****************************************************************************\
+ * *
+ * Device probing/removal *
+ * *
+\*****************************************************************************/
+
+static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
+{
+ struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct sdhci_host *host = NULL;
+ struct resource *iomem = NULL;
+ struct sdhci_pxa *pxa = NULL;
+ int ret, irq;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "no irq specified\n");
+ return irq;
+ }
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem) {
+ dev_err(dev, "no memory specified\n");
+ return -ENOENT;
+ }
+
+ host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
+ if (IS_ERR(host)) {
+ dev_err(dev, "failed to alloc host\n");
+ return PTR_ERR(host);
+ }
+
+ pxa = sdhci_priv(host);
+ pxa->host = host;
+ pxa->pdata = pdata;
+ pxa->clk_enable = 0;
+
+ pxa->clk = clk_get(dev, "PXA-SDHCLK");
+ if (IS_ERR(pxa->clk)) {
+ dev_err(dev, "failed to get io clock\n");
+ ret = PTR_ERR(pxa->clk);
+ goto out;
+ }
+
+ pxa->res = request_mem_region(iomem->start, resource_size(iomem),
+ mmc_hostname(host->mmc));
+ if (!pxa->res) {
+ dev_err(&pdev->dev, "cannot request region\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ host->ioaddr = ioremap(iomem->start, resource_size(iomem));
+ if (!host->ioaddr) {
+ dev_err(&pdev->dev, "failed to remap registers\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ host->hw_name = "MMC";
+ host->ops = &sdhci_pxa_ops;
+ host->irq = irq;
+ host->quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
+ if (pdata->quirks)
+ host->quirks |= pdata->quirks;
+
+ ret = sdhci_add_host(host);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add host\n");
+ goto out;
+ }
+
+ if (pxa->pdata->max_speed)
+ host->mmc->f_max = pxa->pdata->max_speed;
+
+ platform_set_drvdata(pdev, host);
+
+ return 0;
+out:
+ if (host) {
+ clk_put(pxa->clk);
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ if (pxa->res)
+ release_mem_region(pxa->res->start,
+ resource_size(pxa->res));
+ sdhci_free_host(host);
+ }
+
+ return ret;
+}
+
+static int __devexit sdhci_pxa_remove(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pxa *pxa = sdhci_priv(host);
+ int dead = 0;
+ u32 scratch;
+
+ if (host) {
+ scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
+ if (scratch == (u32)-1)
+ dead = 1;
+
+ sdhci_remove_host(host, dead);
+
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ if (pxa->res)
+ release_mem_region(pxa->res->start,
+ resource_size(pxa->res));
+ if (pxa->clk_enable) {
+ clk_disable(pxa->clk);
+ pxa->clk_enable = 0;
+ }
+ clk_put(pxa->clk);
+
+ sdhci_free_host(host);
+ platform_set_drvdata(pdev, NULL);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int sdhci_pxa_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_pxa_resume(struct platform_device *dev)
+{
+ struct sdhci_host *host = platform_get_drvdata(dev);
+
+ return sdhci_resume_host(host);
+}
+#else
+#define sdhci_pxa_suspend NULL
+#define sdhci_pxa_resume NULL
+#endif
+
+static struct platform_driver sdhci_pxa_driver = {
+ .probe = sdhci_pxa_probe,
+ .remove = __devexit_p(sdhci_pxa_remove),
+ .suspend = sdhci_pxa_suspend,
+ .resume = sdhci_pxa_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+/*****************************************************************************\
+ * *
+ * Driver init/exit *
+ * *
+\*****************************************************************************/
+
+static int __init sdhci_pxa_init(void)
+{
+ return platform_driver_register(&sdhci_pxa_driver);
+}
+
+static void __exit sdhci_pxa_exit(void)
+{
+ platform_driver_unregister(&sdhci_pxa_driver);
+}
+
+module_init(sdhci_pxa_init);
+module_exit(sdhci_pxa_exit);
+
+MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2");
+MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>");
+MODULE_LICENSE("GPL v2");
--
1.7.0.4
[-- Attachment #3: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-22 14:09 ` zhangfei gao
@ 2010-10-23 14:24 ` Marek Vasut
2010-10-23 16:47 ` zhangfei gao
0 siblings, 1 reply; 20+ messages in thread
From: Marek Vasut @ 2010-10-23 14:24 UTC (permalink / raw)
To: linux-arm-kernel
Cc: zhangfei gao, Chris Ball, Matt Fleming, eric.y.miao, linux-mmc,
Wolfram Sang, Haojian Zhuang
Dne Pá 22. října 2010 16:09:03 zhangfei gao napsal(a):
> On Fri, Oct 22, 2010 at 7:04 AM, Chris Ball <cjb@laptop.org> wrote:
> > Hi,
> >
> > On Fri, Oct 22, 2010 at 10:58:14AM +0100, Chris Ball wrote:
> > [...]
> >
> >> +#ifdef CONFIG_PM
> >> +static int sdhci_pxa_suspend(struct platform_device *dev)
> >> +{
> >> + struct sdhci_host *host =
> >> platform_get_drvdata(to_platform_device(dev)); +
> >> + return sdhci_suspend_host(host, state);
> >> +}
> >> +
> >> +static int sdhci_pxa_resume(struct platform_device *dev)
> >> +{
> >
> > These prototypes are not correct, leading to:
> >
> > CC [M] drivers/mmc/host/sdhci-pxa.o
> > drivers/mmc/host/sdhci-pxa.c: In function ‘sdhci_pxa_suspend’:
> > drivers/mmc/host/sdhci-pxa.c:205: warning: initialization from
> > incompatible pointer type drivers/mmc/host/sdhci-pxa.c:207: error:
> > ‘state’ undeclared (first use in this function)
> > drivers/mmc/host/sdhci-pxa.c:207: error: (Each undeclared identifier is
> > reported only once drivers/mmc/host/sdhci-pxa.c:207: error: for each
> > function it appears in.) drivers/mmc/host/sdhci-pxa.c: In function
> > ‘sdhci_pxa_resume’:
> > drivers/mmc/host/sdhci-pxa.c:212: warning: initialization from
> > incompatible pointer type drivers/mmc/host/sdhci-pxa.c: At top level:
> > drivers/mmc/host/sdhci-pxa.c:222: warning: initialization from
> > incompatible pointer type drivers/mmc/host/sdhci-pxa.c:223: warning:
> > initialization from incompatible pointer type
> >
> > when compiled with CONFIG_PM=y.
> >
> > --
> > Chris Ball <cjb@laptop.org> <http://printf.net/>
> > One Laptop Per Child
>
> Sorry, forgot open CONFIG_PM.
> Updated patch, thanks
>
> From 88e7f028433fe87b211bf3d75b54261979d0d176 Mon Sep 17 00:00:00 2001
> From: Zhangfei Gao <zhangfei.gao@marvell.com>
> Date: Mon, 20 Sep 2010 10:51:28 -0400
> Subject: [PATCH] mmc: add support of sdhci-pxa driver
>
> Support Marvell PXA168/PXA910/MMP2 SD Host Controller
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@marvell.com>
> Acked-by: Haojian Zhuang <haojian.zhuang@marvell.com>
> ---
> arch/arm/plat-pxa/include/plat/sdhci.h | 32 ++++
> drivers/mmc/host/Kconfig | 12 ++
> drivers/mmc/host/Makefile | 1 +
> drivers/mmc/host/sdhci-pxa.c | 254
> ++++++++++++++++++++++++++++++++ 4 files changed, 299 insertions(+), 0
> deletions(-)
> create mode 100644 arch/arm/plat-pxa/include/plat/sdhci.h
> create mode 100644 drivers/mmc/host/sdhci-pxa.c
>
> diff --git a/arch/arm/plat-pxa/include/plat/sdhci.h
> b/arch/arm/plat-pxa/include/plat/sdhci.h
> new file mode 100644
> index 0000000..38e86ad
> --- /dev/null
> +++ b/arch/arm/plat-pxa/include/plat/sdhci.h
> @@ -0,0 +1,32 @@
> +/* linux/arch/arm/plat-pxa/include/plat/sdhci.h
> + *
> + * Copyright 2010 Marvell
> + * Zhangfei Gao <zhangfei.gao@marvell.com>
> + *
> + * PXA Platform - SDHCI platform data definitions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> +*/
> +
> +#ifndef __PLAT_PXA_SDHCI_H
> +#define __PLAT_PXA_SDHCI_H
> +
> +/* pxa specific flag */
> +/* Require clock free running */
> +#define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)
> +
> +/**
> + * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
> + * @max_speed: The maximum speed supported.
> + * @quirks: quirks of specific device
> + * @flags: flags for platfrom requirement
> +*/
> +struct sdhci_pxa_platdata {
> + unsigned int max_speed;
> + unsigned int quirks;
> + unsigned int flags;
> +};
> +
> +#endif /* __PLAT_PXA_SDHCI_H */
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index c9c2520..c387402 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -155,6 +155,18 @@ config MMC_SDHCI_S3C
>
> If unsure, say N.
>
> +config MMC_SDHCI_PXA
> + tristate "Marvell PXA168/PXA910/MMP2 SD Host Controller support"
> + depends on ARCH_PXA || ARCH_MMP
> + select MMC_SDHCI
> + select MMC_SDHCI_IO_ACCESSORS
> + help
> + This selects the Marvell(R) PXA168/PXA910/MMP2 SD Host Controller.
> + If you have a PXA168/PXA910/MMP2 platform with SD Host Controller and a
> + card slot,say Y or M here.
> +
> + If unsure, say N.
> +
> config MMC_SDHCI_SPEAR
> tristate "SDHCI support on ST SPEAr platform"
> depends on MMC_SDHCI && PLAT_SPEAR
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index 6c4ac67..7b645ff 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_MMC_IMX) += imxmmc.o
> obj-$(CONFIG_MMC_MXC) += mxcmmc.o
> obj-$(CONFIG_MMC_SDHCI) += sdhci.o
> obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
> +obj-$(CONFIG_MMC_SDHCI_PXA) += sdhci-pxa.o
> obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
> obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
> obj-$(CONFIG_MMC_WBSD) += wbsd.o
> diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c
> new file mode 100644
> index 0000000..abf208c
> --- /dev/null
> +++ b/drivers/mmc/host/sdhci-pxa.c
> @@ -0,0 +1,254 @@
> +/* linux/drivers/mmc/host/sdhci-pxa.c
> + *
> + * Copyright (C) 2010 Marvell International Ltd.
> + * Zhangfei Gao <zhangfei.gao@marvell.com>
> + * Kevin Wang <dwang4@marvell.com>
> + * Mingwei Wang <mwwang@marvell.com>
> + * Philip Rakity <prakity@marvell.com>
> + * Mark Brown <markb@marvell.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +/* Supports:
> + * SDHCI support for MMP2/PXA910/PXA168
> + *
> + * Refer sdhci-s3c.c
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/platform_device.h>
> +#include <linux/mmc/host.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/err.h>
> +#include <plat/sdhci.h>
> +#include "sdhci.h"
> +
> +#define DRIVER_NAME "sdhci-pxa"
> +
> +#define SD_FIFO_PARAM 0x104
> +#define DIS_PAD_SD_CLK_GATE 0x400
> +
> +struct sdhci_pxa {
> + struct sdhci_host *host;
> + struct sdhci_pxa_platdata *pdata;
> + struct clk *clk;
> + struct resource *res;
> +
> + u8 clk_enable;
> +};
> +
> +/*************************************************************************
> ****\ + *
> * + * SDHCI core callbacks
> * + *
> *
> +\************************************************************************
> *****/ +static void set_clock(struct sdhci_host *host, unsigned int clock)
> +{
> + struct sdhci_pxa *pxa = sdhci_priv(host);
> + u32 tmp = 0;
> +
> + if (clock == 0) {
> + if (pxa->clk_enable) {
> + clk_disable(pxa->clk);
> + pxa->clk_enable = 0;
> + }
> + } else {
> + if (0 == pxa->clk_enable) {
> + if (pxa->pdata->flags
> + & PXA_FLAG_DISABLE_CLOCK_GATING) {
> + tmp = readl(host->ioaddr + SD_FIFO_PARAM);
> + tmp |= DIS_PAD_SD_CLK_GATE;
> + writel(tmp, host->ioaddr + SD_FIFO_PARAM);
> + }
> + clk_enable(pxa->clk);
> + pxa->clk_enable = 1;
> + }
> + }
> +}
Doesn't the clock framework have something like clk_is_already_enabled()
function ?
> +
> +static struct sdhci_ops sdhci_pxa_ops = {
> + .set_clock = set_clock,
> +};
> +
> +/*************************************************************************
> ****\ + *
> * + * Device probing/removal
> * + *
> *
> +\************************************************************************
> *****/ +
> +static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
> +{
> + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
> + struct device *dev = &pdev->dev;
> + struct sdhci_host *host = NULL;
> + struct resource *iomem = NULL;
> + struct sdhci_pxa *pxa = NULL;
> + int ret, irq;
> +
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0) {
> + dev_err(dev, "no irq specified\n");
> + return irq;
> + }
> +
> + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!iomem) {
> + dev_err(dev, "no memory specified\n");
> + return -ENOENT;
> + }
> +
> + host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
> + if (IS_ERR(host)) {
> + dev_err(dev, "failed to alloc host\n");
> + return PTR_ERR(host);
> + }
> +
> + pxa = sdhci_priv(host);
> + pxa->host = host;
> + pxa->pdata = pdata;
> + pxa->clk_enable = 0;
> +
> + pxa->clk = clk_get(dev, "PXA-SDHCLK");
> + if (IS_ERR(pxa->clk)) {
> + dev_err(dev, "failed to get io clock\n");
> + ret = PTR_ERR(pxa->clk);
> + goto out;
> + }
> +
> + pxa->res = request_mem_region(iomem->start, resource_size(iomem),
> + mmc_hostname(host->mmc));
> + if (!pxa->res) {
> + dev_err(&pdev->dev, "cannot request region\n");
> + ret = -EBUSY;
> + goto out;
> + }
> +
> + host->ioaddr = ioremap(iomem->start, resource_size(iomem));
> + if (!host->ioaddr) {
> + dev_err(&pdev->dev, "failed to remap registers\n");
> + ret = -ENOMEM;
> + goto out;
> + }
> +
> + host->hw_name = "MMC";
> + host->ops = &sdhci_pxa_ops;
> + host->irq = irq;
> + host->quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
> +
Maybe check if these aren't already set in pdata and warn user ?
> + if (pdata->quirks)
> + host->quirks |= pdata->quirks;
> +
> + ret = sdhci_add_host(host);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to add host\n");
> + goto out;
> + }
> +
> + if (pxa->pdata->max_speed)
> + host->mmc->f_max = pxa->pdata->max_speed;
What happens otherwise ?
> +
> + platform_set_drvdata(pdev, host);
> +
> + return 0;
> +out:
> + if (host) {
> + clk_put(pxa->clk);
> + if (host->ioaddr)
> + iounmap(host->ioaddr);
> + if (pxa->res)
> + release_mem_region(pxa->res->start,
> + resource_size(pxa->res));
> + sdhci_free_host(host);
> + }
> +
> + return ret;
> +}
> +
> +static int __devexit sdhci_pxa_remove(struct platform_device *pdev)
> +{
> + struct sdhci_host *host = platform_get_drvdata(pdev);
> + struct sdhci_pxa *pxa = sdhci_priv(host);
> + int dead = 0;
> + u32 scratch;
> +
> + if (host) {
> + scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
> + if (scratch == (u32)-1)
> + dead = 1;
> +
> + sdhci_remove_host(host, dead);
> +
> + if (host->ioaddr)
> + iounmap(host->ioaddr);
> + if (pxa->res)
> + release_mem_region(pxa->res->start,
> + resource_size(pxa->res));
> + if (pxa->clk_enable) {
> + clk_disable(pxa->clk);
> + pxa->clk_enable = 0;
> + }
> + clk_put(pxa->clk);
> +
> + sdhci_free_host(host);
> + platform_set_drvdata(pdev, NULL);
> + }
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int sdhci_pxa_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_pxa_resume(struct platform_device *dev)
> +{
> + struct sdhci_host *host = platform_get_drvdata(dev);
> +
> + return sdhci_resume_host(host);
> +}
> +#else
> +#define sdhci_pxa_suspend NULL
> +#define sdhci_pxa_resume NULL
> +#endif
> +
> +static struct platform_driver sdhci_pxa_driver = {
> + .probe = sdhci_pxa_probe,
> + .remove = __devexit_p(sdhci_pxa_remove),
> + .suspend = sdhci_pxa_suspend,
> + .resume = sdhci_pxa_resume,
> + .driver = {
> + .name = DRIVER_NAME,
> + .owner = THIS_MODULE,
> + },
> +};
> +
> +/*************************************************************************
> ****\ + *
> * + * Driver init/exit
> * + *
> *
> +\************************************************************************
> *****/ +
> +static int __init sdhci_pxa_init(void)
> +{
> + return platform_driver_register(&sdhci_pxa_driver);
> +}
> +
> +static void __exit sdhci_pxa_exit(void)
> +{
> + platform_driver_unregister(&sdhci_pxa_driver);
> +}
> +
> +module_init(sdhci_pxa_init);
> +module_exit(sdhci_pxa_exit);
> +
> +MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2");
> +MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>");
> +MODULE_LICENSE("GPL v2");
Thanks!
Cheers
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-23 14:24 ` Marek Vasut
@ 2010-10-23 16:47 ` zhangfei gao
2010-10-23 17:50 ` Marek Vasut
0 siblings, 1 reply; 20+ messages in thread
From: zhangfei gao @ 2010-10-23 16:47 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-arm-kernel, Chris Ball, Matt Fleming, eric.y.miao,
linux-mmc, Wolfram Sang, Haojian Zhuang
On Sat, Oct 23, 2010 at 10:24 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
>> +/*************************************************************************
>> ****\ + *
>> * + * Device probing/removal
>> * + *
>> *
>> +\************************************************************************
>> *****/ +
>> +static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
>> +{
>> + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
>> + struct device *dev = &pdev->dev;
>> + struct sdhci_host *host = NULL;
>> + struct resource *iomem = NULL;
>> + struct sdhci_pxa *pxa = NULL;
>> + int ret, irq;
>> +
>> + irq = platform_get_irq(pdev, 0);
>> + if (irq < 0) {
>> + dev_err(dev, "no irq specified\n");
>> + return irq;
>> + }
>> +
>> + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + if (!iomem) {
>> + dev_err(dev, "no memory specified\n");
>> + return -ENOENT;
>> + }
>> +
>> + host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
>> + if (IS_ERR(host)) {
>> + dev_err(dev, "failed to alloc host\n");
>> + return PTR_ERR(host);
>> + }
>> +
>> + pxa = sdhci_priv(host);
>> + pxa->host = host;
>> + pxa->pdata = pdata;
>> + pxa->clk_enable = 0;
>> +
>> + pxa->clk = clk_get(dev, "PXA-SDHCLK");
>> + if (IS_ERR(pxa->clk)) {
>> + dev_err(dev, "failed to get io clock\n");
>> + ret = PTR_ERR(pxa->clk);
>> + goto out;
>> + }
>> +
>> + pxa->res = request_mem_region(iomem->start, resource_size(iomem),
>> + mmc_hostname(host->mmc));
>> + if (!pxa->res) {
>> + dev_err(&pdev->dev, "cannot request region\n");
>> + ret = -EBUSY;
>> + goto out;
>> + }
>> +
>> + host->ioaddr = ioremap(iomem->start, resource_size(iomem));
>> + if (!host->ioaddr) {
>> + dev_err(&pdev->dev, "failed to remap registers\n");
>> + ret = -ENOMEM;
>> + goto out;
>> + }
>> +
>> + host->hw_name = "MMC";
>> + host->ops = &sdhci_pxa_ops;
>> + host->irq = irq;
>> + host->quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
>> +
>
> Maybe check if these aren't already set in pdata and warn user ?
Here pdata->quirks only provide specific quirk like
SDHCI_QUIRK_BROKEN_CARD_DETECTION for on-chip device, the common quirk
is provided above.
In sdhci-s3c, host->quirks is modified here via pdata->cd_type, which
is also a good method.
Here we transfer SDHCI_QUIRK_BROKEN_CARD_DETECTION directly from pdata
since it already move to include folder.
>
>> + if (pdata->quirks)
>> + host->quirks |= pdata->quirks;
>> +
>> + ret = sdhci_add_host(host);
>> + if (ret) {
>> + dev_err(&pdev->dev, "failed to add host\n");
>> + goto out;
>> + }
>> +
>> + if (pxa->pdata->max_speed)
>> + host->mmc->f_max = pxa->pdata->max_speed;
>
> What happens otherwise ?
Otherwise, host->mmc->f_max = host->max_clk set in sdhci_add_host,
host->max_clk is 50M in 2.0 controller, and 200M in 3.0 controller, if
controller does not need to provide get_max_clock.
it's better add defalut value in else condition.
Thanks Marek for review.
>
>> +
>> + platform_set_drvdata(pdev, host);
>> +
>> + return 0;
>> +out:
>> + if (host) {
>> + clk_put(pxa->clk);
>> + if (host->ioaddr)
>> + iounmap(host->ioaddr);
>> + if (pxa->res)
>> + release_mem_region(pxa->res->start,
>> + resource_size(pxa->res));
>> + sdhci_free_host(host);
>> + }
>> +
>> + return ret;
>> +}
>> +
>
> Thanks!
>
> Cheers
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-23 16:47 ` zhangfei gao
@ 2010-10-23 17:50 ` Marek Vasut
2010-10-24 3:26 ` zhangfei gao
0 siblings, 1 reply; 20+ messages in thread
From: Marek Vasut @ 2010-10-23 17:50 UTC (permalink / raw)
To: zhangfei gao
Cc: linux-arm-kernel, Chris Ball, Matt Fleming, eric.y.miao,
linux-mmc, Wolfram Sang, Haojian Zhuang
Dne So 23. října 2010 18:47:10 zhangfei gao napsal(a):
> On Sat, Oct 23, 2010 at 10:24 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
> >> +/**********************************************************************
> >> *** ****\ + *
> >> * + * Device probing/removal
> >> * + *
> >> *
> >> +\**********************************************************************
> >> ** *****/ +
> >> +static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
> >> +{
> >> + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
> >> + struct device *dev = &pdev->dev;
> >> + struct sdhci_host *host = NULL;
> >> + struct resource *iomem = NULL;
> >> + struct sdhci_pxa *pxa = NULL;
> >> + int ret, irq;
> >> +
> >> + irq = platform_get_irq(pdev, 0);
> >> + if (irq < 0) {
> >> + dev_err(dev, "no irq specified\n");
> >> + return irq;
> >> + }
> >> +
> >> + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >> + if (!iomem) {
> >> + dev_err(dev, "no memory specified\n");
> >> + return -ENOENT;
> >> + }
> >> +
> >> + host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
> >> + if (IS_ERR(host)) {
> >> + dev_err(dev, "failed to alloc host\n");
> >> + return PTR_ERR(host);
> >> + }
> >> +
> >> + pxa = sdhci_priv(host);
> >> + pxa->host = host;
> >> + pxa->pdata = pdata;
> >> + pxa->clk_enable = 0;
> >> +
> >> + pxa->clk = clk_get(dev, "PXA-SDHCLK");
> >> + if (IS_ERR(pxa->clk)) {
> >> + dev_err(dev, "failed to get io clock\n");
> >> + ret = PTR_ERR(pxa->clk);
> >> + goto out;
> >> + }
> >> +
> >> + pxa->res = request_mem_region(iomem->start, resource_size(iomem),
> >> + mmc_hostname(host->mmc));
> >> + if (!pxa->res) {
> >> + dev_err(&pdev->dev, "cannot request region\n");
> >> + ret = -EBUSY;
> >> + goto out;
> >> + }
> >> +
> >> + host->ioaddr = ioremap(iomem->start, resource_size(iomem));
> >> + if (!host->ioaddr) {
> >> + dev_err(&pdev->dev, "failed to remap registers\n");
> >> + ret = -ENOMEM;
> >> + goto out;
> >> + }
> >> +
> >> + host->hw_name = "MMC";
> >> + host->ops = &sdhci_pxa_ops;
> >> + host->irq = irq;
> >> + host->quirks = SDHCI_QUIRK_BROKEN_ADMA |
> >> SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; +
> >
> > Maybe check if these aren't already set in pdata and warn user ?
>
> Here pdata->quirks only provide specific quirk like
> SDHCI_QUIRK_BROKEN_CARD_DETECTION for on-chip device, the common quirk
> is provided above.
Right, but what if the user also provides such a quirk? It's unnecessary ... and
in case the quirk was removed from here later, it'd have to be removed from
user's code too ...
> In sdhci-s3c, host->quirks is modified here via pdata->cd_type, which
> is also a good method.
> Here we transfer SDHCI_QUIRK_BROKEN_CARD_DETECTION directly from pdata
> since it already move to include folder.
>
> >> + if (pdata->quirks)
> >> + host->quirks |= pdata->quirks;
> >> +
> >> + ret = sdhci_add_host(host);
> >> + if (ret) {
> >> + dev_err(&pdev->dev, "failed to add host\n");
> >> + goto out;
> >> + }
> >> +
> >> + if (pxa->pdata->max_speed)
> >> + host->mmc->f_max = pxa->pdata->max_speed;
> >
> > What happens otherwise ?
>
> Otherwise, host->mmc->f_max = host->max_clk set in sdhci_add_host,
> host->max_clk is 50M in 2.0 controller, and 200M in 3.0 controller, if
> controller does not need to provide get_max_clock.
> it's better add defalut value in else condition.
Thanks for clearing this
>
> Thanks Marek for review.
>
> >> +
> >> + platform_set_drvdata(pdev, host);
> >> +
> >> + return 0;
> >> +out:
> >> + if (host) {
> >> + clk_put(pxa->clk);
> >> + if (host->ioaddr)
> >> + iounmap(host->ioaddr);
> >> + if (pxa->res)
> >> + release_mem_region(pxa->res->start,
> >> + resource_size(pxa->res));
> >> + sdhci_free_host(host);
> >> + }
> >> +
> >> + return ret;
> >> +}
> >> +
> >
> > Thanks!
> >
> > Cheers
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-23 17:50 ` Marek Vasut
@ 2010-10-24 3:26 ` zhangfei gao
2010-10-24 4:02 ` Marek Vasut
0 siblings, 1 reply; 20+ messages in thread
From: zhangfei gao @ 2010-10-24 3:26 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-arm-kernel, Chris Ball, Matt Fleming, eric.y.miao,
linux-mmc, Wolfram Sang, Haojian Zhuang
On Sun, Oct 24, 2010 at 1:50 AM, Marek Vasut <marek.vasut@gmail.com> wrote:
> Dne So 23. října 2010 18:47:10 zhangfei gao napsal(a):
>> On Sat, Oct 23, 2010 at 10:24 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
>> >> +/**********************************************************************
>> >> *** ****\ + *
>> >> * + * Device probing/removal
>> >> * + *
>> >> *
>> >> +\**********************************************************************
>> >> ** *****/ +
>> >> +static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
>> >> +{
>> >> + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
>> >> + struct device *dev = &pdev->dev;
>> >> + struct sdhci_host *host = NULL;
>> >> + struct resource *iomem = NULL;
>> >> + struct sdhci_pxa *pxa = NULL;
>> >> + int ret, irq;
>> >> +
>> >> + irq = platform_get_irq(pdev, 0);
>> >> + if (irq < 0) {
>> >> + dev_err(dev, "no irq specified\n");
>> >> + return irq;
>> >> + }
>> >> +
>> >> + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> >> + if (!iomem) {
>> >> + dev_err(dev, "no memory specified\n");
>> >> + return -ENOENT;
>> >> + }
>> >> +
>> >> + host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
>> >> + if (IS_ERR(host)) {
>> >> + dev_err(dev, "failed to alloc host\n");
>> >> + return PTR_ERR(host);
>> >> + }
>> >> +
>> >> + pxa = sdhci_priv(host);
>> >> + pxa->host = host;
>> >> + pxa->pdata = pdata;
>> >> + pxa->clk_enable = 0;
>> >> +
>> >> + pxa->clk = clk_get(dev, "PXA-SDHCLK");
>> >> + if (IS_ERR(pxa->clk)) {
>> >> + dev_err(dev, "failed to get io clock\n");
>> >> + ret = PTR_ERR(pxa->clk);
>> >> + goto out;
>> >> + }
>> >> +
>> >> + pxa->res = request_mem_region(iomem->start, resource_size(iomem),
>> >> + mmc_hostname(host->mmc));
>> >> + if (!pxa->res) {
>> >> + dev_err(&pdev->dev, "cannot request region\n");
>> >> + ret = -EBUSY;
>> >> + goto out;
>> >> + }
>> >> +
>> >> + host->ioaddr = ioremap(iomem->start, resource_size(iomem));
>> >> + if (!host->ioaddr) {
>> >> + dev_err(&pdev->dev, "failed to remap registers\n");
>> >> + ret = -ENOMEM;
>> >> + goto out;
>> >> + }
>> >> +
>> >> + host->hw_name = "MMC";
>> >> + host->ops = &sdhci_pxa_ops;
>> >> + host->irq = irq;
>> >> + host->quirks = SDHCI_QUIRK_BROKEN_ADMA |
>> >> SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; +
>> >
>> > Maybe check if these aren't already set in pdata and warn user ?
>>
>> Here pdata->quirks only provide specific quirk like
>> SDHCI_QUIRK_BROKEN_CARD_DETECTION for on-chip device, the common quirk
>> is provided above.
>
> Right, but what if the user also provides such a quirk? It's unnecessary ... and
> in case the quirk was removed from here later, it'd have to be removed from
> user's code too ...
What do you mean 'in case the quirk was removed from here later'.
SDHCI_QUIRK_* is just move from drivers/mmc/host/sdhci.h to
include/linux/mmc/sdhci.h, so code in arch/arm could access them
directly.
We also consider use one flag here, like sdhci-s3c.c.
Code like this,
if (pdata->flags & PXA_FLAG_CARD_PERMENT)
host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
If SDHCI_QUIRK_* not permitted to access, it would be better to use this method.
>
>> In sdhci-s3c, host->quirks is modified here via pdata->cd_type, which
>> is also a good method.
>> Here we transfer SDHCI_QUIRK_BROKEN_CARD_DETECTION directly from pdata
>> since it already move to include folder.
>>
>> >> + if (pdata->quirks)
>> >> + host->quirks |= pdata->quirks;
>> >> +
>> >> + ret = sdhci_add_host(host);
>> >> + if (ret) {
>> >> + dev_err(&pdev->dev, "failed to add host\n");
>> >> + goto out;
>> >> + }
>> >> +
>> >> + if (pxa->pdata->max_speed)
>> >> + host->mmc->f_max = pxa->pdata->max_speed;
>> >
>> > What happens otherwise ?
>>
>> Otherwise, host->mmc->f_max = host->max_clk set in sdhci_add_host,
>> host->max_clk is 50M in 2.0 controller, and 200M in 3.0 controller, if
>> controller does not need to provide get_max_clock.
>> it's better add defalut value in else condition.
>
> Thanks for clearing this
>>
>> Thanks Marek for review.
>>
>> >> +
>> >> + platform_set_drvdata(pdev, host);
>> >> +
>> >> + return 0;
>> >> +out:
>> >> + if (host) {
>> >> + clk_put(pxa->clk);
>> >> + if (host->ioaddr)
>> >> + iounmap(host->ioaddr);
>> >> + if (pxa->res)
>> >> + release_mem_region(pxa->res->start,
>> >> + resource_size(pxa->res));
>> >> + sdhci_free_host(host);
>> >> + }
>> >> +
>> >> + return ret;
>> >> +}
>> >> +
>> >
>> > Thanks!
>> >
>> > Cheers
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-24 3:26 ` zhangfei gao
@ 2010-10-24 4:02 ` Marek Vasut
2010-10-25 5:48 ` zhangfei gao
0 siblings, 1 reply; 20+ messages in thread
From: Marek Vasut @ 2010-10-24 4:02 UTC (permalink / raw)
To: zhangfei gao
Cc: linux-arm-kernel, Chris Ball, Matt Fleming, eric.y.miao,
linux-mmc, Wolfram Sang, Haojian Zhuang
Dne Ne 24. října 2010 05:26:38 zhangfei gao napsal(a):
> On Sun, Oct 24, 2010 at 1:50 AM, Marek Vasut <marek.vasut@gmail.com> wrote:
> > Dne So 23. října 2010 18:47:10 zhangfei gao napsal(a):
> >> On Sat, Oct 23, 2010 at 10:24 PM, Marek Vasut <marek.vasut@gmail.com>
wrote:
> >> >> +/*******************************************************************
> >> >> *** *** ****\ + *
> >> >> * + * Device probing/removal
> >> >> * + *
> >> >> *
> >> >> +\*******************************************************************
> >> >> *** ** *****/ +
> >> >> +static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
> >> >> +{
> >> >> + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
> >> >> + struct device *dev = &pdev->dev;
> >> >> + struct sdhci_host *host = NULL;
> >> >> + struct resource *iomem = NULL;
> >> >> + struct sdhci_pxa *pxa = NULL;
> >> >> + int ret, irq;
> >> >> +
> >> >> + irq = platform_get_irq(pdev, 0);
> >> >> + if (irq < 0) {
> >> >> + dev_err(dev, "no irq specified\n");
> >> >> + return irq;
> >> >> + }
> >> >> +
> >> >> + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >> >> + if (!iomem) {
> >> >> + dev_err(dev, "no memory specified\n");
> >> >> + return -ENOENT;
> >> >> + }
> >> >> +
> >> >> + host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
> >> >> + if (IS_ERR(host)) {
> >> >> + dev_err(dev, "failed to alloc host\n");
> >> >> + return PTR_ERR(host);
> >> >> + }
> >> >> +
> >> >> + pxa = sdhci_priv(host);
> >> >> + pxa->host = host;
> >> >> + pxa->pdata = pdata;
> >> >> + pxa->clk_enable = 0;
> >> >> +
> >> >> + pxa->clk = clk_get(dev, "PXA-SDHCLK");
> >> >> + if (IS_ERR(pxa->clk)) {
> >> >> + dev_err(dev, "failed to get io clock\n");
> >> >> + ret = PTR_ERR(pxa->clk);
> >> >> + goto out;
> >> >> + }
> >> >> +
> >> >> + pxa->res = request_mem_region(iomem->start,
> >> >> resource_size(iomem), + mmc_hostname(host->mmc));
> >> >> + if (!pxa->res) {
> >> >> + dev_err(&pdev->dev, "cannot request region\n");
> >> >> + ret = -EBUSY;
> >> >> + goto out;
> >> >> + }
> >> >> +
> >> >> + host->ioaddr = ioremap(iomem->start, resource_size(iomem));
> >> >> + if (!host->ioaddr) {
> >> >> + dev_err(&pdev->dev, "failed to remap registers\n");
> >> >> + ret = -ENOMEM;
> >> >> + goto out;
> >> >> + }
> >> >> +
> >> >> + host->hw_name = "MMC";
> >> >> + host->ops = &sdhci_pxa_ops;
> >> >> + host->irq = irq;
> >> >> + host->quirks = SDHCI_QUIRK_BROKEN_ADMA |
> >> >> SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; +
> >> >
> >> > Maybe check if these aren't already set in pdata and warn user ?
> >>
> >> Here pdata->quirks only provide specific quirk like
> >> SDHCI_QUIRK_BROKEN_CARD_DETECTION for on-chip device, the common quirk
> >> is provided above.
> >
> > Right, but what if the user also provides such a quirk? It's unnecessary
> > ... and in case the quirk was removed from here later, it'd have to be
> > removed from user's code too ...
>
> What do you mean 'in case the quirk was removed from here later'.
I mean ... if setting the quirk was removed from the driver source, it'd have to
be removed from user code that uses the driver as well -- in case user also set
such a quirk in pdata->quirks. So it might be a good idea to warn user that he's
setting something that's getting set elsewhere (in the driver) anyway.
> SDHCI_QUIRK_* is just move from drivers/mmc/host/sdhci.h to
> include/linux/mmc/sdhci.h, so code in arch/arm could access them
> directly.
>
> We also consider use one flag here, like sdhci-s3c.c.
> Code like this,
> if (pdata->flags & PXA_FLAG_CARD_PERMENT)
> host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
>
> If SDHCI_QUIRK_* not permitted to access, it would be better to use this
> method.
>
> >> In sdhci-s3c, host->quirks is modified here via pdata->cd_type, which
> >> is also a good method.
> >> Here we transfer SDHCI_QUIRK_BROKEN_CARD_DETECTION directly from pdata
> >> since it already move to include folder.
> >>
> >> >> + if (pdata->quirks)
> >> >> + host->quirks |= pdata->quirks;
> >> >> +
> >> >> + ret = sdhci_add_host(host);
> >> >> + if (ret) {
> >> >> + dev_err(&pdev->dev, "failed to add host\n");
> >> >> + goto out;
> >> >> + }
> >> >> +
> >> >> + if (pxa->pdata->max_speed)
> >> >> + host->mmc->f_max = pxa->pdata->max_speed;
> >> >
> >> > What happens otherwise ?
> >>
> >> Otherwise, host->mmc->f_max = host->max_clk set in sdhci_add_host,
> >> host->max_clk is 50M in 2.0 controller, and 200M in 3.0 controller, if
> >> controller does not need to provide get_max_clock.
> >> it's better add defalut value in else condition.
> >
> > Thanks for clearing this
> >
> >> Thanks Marek for review.
> >>
> >> >> +
> >> >> + platform_set_drvdata(pdev, host);
> >> >> +
> >> >> + return 0;
> >> >> +out:
> >> >> + if (host) {
> >> >> + clk_put(pxa->clk);
> >> >> + if (host->ioaddr)
> >> >> + iounmap(host->ioaddr);
> >> >> + if (pxa->res)
> >> >> + release_mem_region(pxa->res->start,
> >> >> + resource_size(pxa->res));
> >> >> + sdhci_free_host(host);
> >> >> + }
> >> >> +
> >> >> + return ret;
> >> >> +}
> >> >> +
> >> >
> >> > Thanks!
> >> >
> >> > Cheers
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3 1/1]MMC: add support of sdhci-pxa driver
2010-10-24 4:02 ` Marek Vasut
@ 2010-10-25 5:48 ` zhangfei gao
0 siblings, 0 replies; 20+ messages in thread
From: zhangfei gao @ 2010-10-25 5:48 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-arm-kernel, Chris Ball, Matt Fleming, eric.y.miao,
linux-mmc, Wolfram Sang, Haojian Zhuang
2010/10/24 Marek Vasut <marek.vasut@gmail.com>:
> Dne Ne 24. října 2010 05:26:38 zhangfei gao napsal(a):
>> On Sun, Oct 24, 2010 at 1:50 AM, Marek Vasut <marek.vasut@gmail.com> wrote:
>> > Dne So 23. října 2010 18:47:10 zhangfei gao napsal(a):
>> >> On Sat, Oct 23, 2010 at 10:24 PM, Marek Vasut <marek.vasut@gmail.com>
> wrote:
>> >> >> +/*******************************************************************
>> >> >> *** *** ****\ + *
>> >> >> * + * Device probing/removal
>> >> >> * + *
>> >> >> *
>> >> >> +\*******************************************************************
>> >> >> *** ** *****/ +
>> >> >> +static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
>> >> >> +{
>> >> >> + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
>> >> >> + struct device *dev = &pdev->dev;
>> >> >> + struct sdhci_host *host = NULL;
>> >> >> + struct resource *iomem = NULL;
>> >> >> + struct sdhci_pxa *pxa = NULL;
>> >> >> + int ret, irq;
>> >> >> +
>> >> >> + irq = platform_get_irq(pdev, 0);
>> >> >> + if (irq < 0) {
>> >> >> + dev_err(dev, "no irq specified\n");
>> >> >> + return irq;
>> >> >> + }
>> >> >> +
>> >> >> + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> >> >> + if (!iomem) {
>> >> >> + dev_err(dev, "no memory specified\n");
>> >> >> + return -ENOENT;
>> >> >> + }
>> >> >> +
>> >> >> + host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pxa));
>> >> >> + if (IS_ERR(host)) {
>> >> >> + dev_err(dev, "failed to alloc host\n");
>> >> >> + return PTR_ERR(host);
>> >> >> + }
>> >> >> +
>> >> >> + pxa = sdhci_priv(host);
>> >> >> + pxa->host = host;
>> >> >> + pxa->pdata = pdata;
>> >> >> + pxa->clk_enable = 0;
>> >> >> +
>> >> >> + pxa->clk = clk_get(dev, "PXA-SDHCLK");
>> >> >> + if (IS_ERR(pxa->clk)) {
>> >> >> + dev_err(dev, "failed to get io clock\n");
>> >> >> + ret = PTR_ERR(pxa->clk);
>> >> >> + goto out;
>> >> >> + }
>> >> >> +
>> >> >> + pxa->res = request_mem_region(iomem->start,
>> >> >> resource_size(iomem), + mmc_hostname(host->mmc));
>> >> >> + if (!pxa->res) {
>> >> >> + dev_err(&pdev->dev, "cannot request region\n");
>> >> >> + ret = -EBUSY;
>> >> >> + goto out;
>> >> >> + }
>> >> >> +
>> >> >> + host->ioaddr = ioremap(iomem->start, resource_size(iomem));
>> >> >> + if (!host->ioaddr) {
>> >> >> + dev_err(&pdev->dev, "failed to remap registers\n");
>> >> >> + ret = -ENOMEM;
>> >> >> + goto out;
>> >> >> + }
>> >> >> +
>> >> >> + host->hw_name = "MMC";
>> >> >> + host->ops = &sdhci_pxa_ops;
>> >> >> + host->irq = irq;
>> >> >> + host->quirks = SDHCI_QUIRK_BROKEN_ADMA |
>> >> >> SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; +
>> >> >
>> >> > Maybe check if these aren't already set in pdata and warn user ?
>> >>
>> >> Here pdata->quirks only provide specific quirk like
>> >> SDHCI_QUIRK_BROKEN_CARD_DETECTION for on-chip device, the common quirk
>> >> is provided above.
>> >
>> > Right, but what if the user also provides such a quirk? It's unnecessary
>> > ... and in case the quirk was removed from here later, it'd have to be
>> > removed from user's code too ...
>>
>> What do you mean 'in case the quirk was removed from here later'.
>
> I mean ... if setting the quirk was removed from the driver source, it'd have to
> be removed from user code that uses the driver as well -- in case user also set
> such a quirk in pdata->quirks. So it might be a good idea to warn user that he's
> setting something that's getting set elsewhere (in the driver) anyway.
Thanks for suggestion, but I think it is OK here.
In our design, driver set common limitation quirk, and pdata set
specific quirk for some device.
>
>> SDHCI_QUIRK_* is just move from drivers/mmc/host/sdhci.h to
>> include/linux/mmc/sdhci.h, so code in arch/arm could access them
>> directly.
>>
>> We also consider use one flag here, like sdhci-s3c.c.
>> Code like this,
>> if (pdata->flags & PXA_FLAG_CARD_PERMENT)
>> host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
>>
>> If SDHCI_QUIRK_* not permitted to access, it would be better to use this
>> method.
>>
>> >> In sdhci-s3c, host->quirks is modified here via pdata->cd_type, which
>> >> is also a good method.
>> >> Here we transfer SDHCI_QUIRK_BROKEN_CARD_DETECTION directly from pdata
>> >> since it already move to include folder.
>> >>
>> >> >> + if (pdata->quirks)
>> >> >> + host->quirks |= pdata->quirks;
>> >> >> +
>> >> >> + ret = sdhci_add_host(host);
>> >> >> + if (ret) {
>> >> >> + dev_err(&pdev->dev, "failed to add host\n");
>> >> >> + goto out;
>> >> >> + }
>> >> >> +
>> >> >> + if (pxa->pdata->max_speed)
>> >> >> + host->mmc->f_max = pxa->pdata->max_speed;
>> >> >
>> >> > What happens otherwise ?
>> >>
>> >> Otherwise, host->mmc->f_max = host->max_clk set in sdhci_add_host,
>> >> host->max_clk is 50M in 2.0 controller, and 200M in 3.0 controller, if
>> >> controller does not need to provide get_max_clock.
>> >> it's better add defalut value in else condition.
>> >
>> > Thanks for clearing this
>> >
>> >> Thanks Marek for review.
>> >>
>> >> >> +
>> >> >> + platform_set_drvdata(pdev, host);
>> >> >> +
>> >> >> + return 0;
>> >> >> +out:
>> >> >> + if (host) {
>> >> >> + clk_put(pxa->clk);
>> >> >> + if (host->ioaddr)
>> >> >> + iounmap(host->ioaddr);
>> >> >> + if (pxa->res)
>> >> >> + release_mem_region(pxa->res->start,
>> >> >> + resource_size(pxa->res));
>> >> >> + sdhci_free_host(host);
>> >> >> + }
>> >> >> +
>> >> >> + return ret;
>> >> >> +}
>> >> >> +
>> >> >
>> >> > Thanks!
>> >> >
>> >> > Cheers
>
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2010-10-25 5:48 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-18 12:32 [PATCH V3 1/1]MMC: add support of sdhci-pxa driver zhangfei gao
2010-10-18 14:58 ` Wolfram Sang
2010-10-18 15:25 ` zhangfei gao
2010-10-19 2:03 ` Wolfram Sang
2010-10-19 9:44 ` zhangfei gao
2010-10-21 14:13 ` Chris Ball
2010-10-21 14:20 ` zhangfei gao
2010-10-21 14:52 ` Chris Ball
2010-10-22 0:20 ` Marek Vasut
2010-10-22 0:27 ` Chris Ball
2010-10-22 8:44 ` Haojian Zhuang
2010-10-22 9:58 ` Chris Ball
2010-10-22 11:04 ` Chris Ball
2010-10-22 14:09 ` zhangfei gao
2010-10-23 14:24 ` Marek Vasut
2010-10-23 16:47 ` zhangfei gao
2010-10-23 17:50 ` Marek Vasut
2010-10-24 3:26 ` zhangfei gao
2010-10-24 4:02 ` Marek Vasut
2010-10-25 5:48 ` zhangfei gao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox