linux-mmc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: saeed bishara <saeed.bishara@gmail.com>
To: linux-mmc@vger.kernel.org
Cc: Saeed Bishara <saeed@marvell.com>
Subject: Re: [PATCH] MMC: add support for the Marvell platform SDHCI controller
Date: Wed, 5 May 2010 16:39:37 +0300	[thread overview]
Message-ID: <s2tc70ff3ad1005050639xf79968ddle48c06d007af043c@mail.gmail.com> (raw)
In-Reply-To: <1272990283-18699-1-git-send-email-saeed@marvell.com>

[-- Attachment #1: Type: text/plain, Size: 10630 bytes --]

Attached v2 of the patch. changes:
1. added missing files (Makefile and Kconfig)
2. added the force dma quirk
3. removed special treatment for DATA register used fro pio mode

please review

saeed
On Tue, May 4, 2010 at 7:24 PM, Saeed Bishara <saeed@marvell.com> wrote:
> This patch implements the driver for the platfrom SDHCI controllers that found on some of Marvell's SoC's.
>
> Signed-off-by: Saeed Bishara <saeed@marvell.com>
> ---
>  drivers/mmc/host/sdhci-mv.c |  266 +++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 266 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mmc/host/sdhci-mv.c
>
> diff --git a/drivers/mmc/host/sdhci-mv.c b/drivers/mmc/host/sdhci-mv.c
> new file mode 100644
> index 0000000..a88cae1
> --- /dev/null
> +++ b/drivers/mmc/host/sdhci-mv.c
> @@ -0,0 +1,266 @@
> +/*
> + * sdhci-mv.c Support for SDHCI platform devices
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +/* Supports:
> + * SDHCI platform devices found on Marvell SoC's
> + *
> + * Based on  sdhci-pltfm.c
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +#include <linux/mmc/host.h>
> +#include "sdhci.h"
> +
> +struct sdhci_mv_host {
> +#if defined(CONFIG_HAVE_CLK)
> +       struct clk              *clk;
> +#endif
> +};
> +
> +/*****************************************************************************\
> + *                                                                           *
> + * SDHCI core callbacks                                                      *
> + *                                                                           *
> +\*****************************************************************************/
> +static u16 mv_readw(struct sdhci_host *host, int reg)
> +{
> +       u16 ret;
> +
> +       switch (reg) {
> +       case SDHCI_HOST_VERSION:
> +       case SDHCI_SLOT_INT_STATUS:
> +               /* those registers don't exist */
> +               return 0;
> +       default:
> +               ret = readw(host->ioaddr + reg);
> +       }
> +       return ret;
> +}
> +
> +static u32 mv_readl(struct sdhci_host *host, int reg)
> +{
> +       u32 ret;
> +
> +       switch (reg) {
> +       case SDHCI_BUFFER:
> +               /*
> +                * This register can't be accessed with 32 bit access, solve
> +                * this issue by breaking it into two 16 bit accesses.
> +                */
> +               ret = readw(host->ioaddr + SDHCI_BUFFER);
> +               ret |= readw(host->ioaddr + SDHCI_BUFFER + 2) << 16;
> +               break;
> +       default:
> +               ret = readl(host->ioaddr + reg);
> +       }
> +       return ret;
> +}
> +
> +static void mv_writel(struct sdhci_host *host, u32 val, int reg)
> +{
> +       switch (reg) {
> +       case SDHCI_BUFFER:
> +       {
> +               /*
> +                * This register can't be accessed with 32 bit access, solve
> +                * this issue by breaking it into two 16 bit accesses.
> +                */
> +               u16 temp = reg & 0xFFFF;
> +               writew(temp, host->ioaddr + SDHCI_BUFFER);
> +               temp = (0xFFFF0000 & reg) >> 16;
> +               writew(temp, host->ioaddr + SDHCI_BUFFER + 2);
> +       }
> +       break;
> +       default:
> +               writel(val, host->ioaddr + reg);
> +       }
> +}
> +
> +static struct sdhci_ops sdhci_mv_ops = {
> +       .read_w = mv_readw,
> +       .read_l = mv_readl,
> +       .write_l = mv_writel,
> +};
> +
> +/*****************************************************************************\
> + *                                                                           *
> + * Device probing/removal                                                    *
> + *                                                                           *
> +\*****************************************************************************/
> +
> +static int __devinit sdhci_mv_probe(struct platform_device *pdev)
> +{
> +       struct sdhci_host *host;
> +       struct sdhci_mv_host *mv_host;
> +       struct resource *iomem;
> +       int ret;
> +
> +       BUG_ON(pdev == NULL);
> +
> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!iomem) {
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       if (resource_size(iomem) != 0x100)
> +               dev_err(&pdev->dev, "Invalid iomem size. You may "
> +                       "experience problems.\n");
> +
> +       if (pdev->dev.parent)
> +               host = sdhci_alloc_host(pdev->dev.parent, sizeof(*mv_host));
> +       else
> +               host = sdhci_alloc_host(&pdev->dev, sizeof(*mv_host));
> +
> +       if (IS_ERR(host)) {
> +               ret = PTR_ERR(host);
> +               goto err;
> +       }
> +
> +       mv_host = sdhci_priv(host);
> +       host->hw_name = "marvell-sdhci";
> +       host->ops = &sdhci_mv_ops;
> +       host->irq = platform_get_irq(pdev, 0);
> +       host->quirks =  SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
> +                       SDHCI_QUIRK_NO_BUSY_IRQ |
> +                       SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
> +
> +       if (!devm_request_mem_region(&pdev->dev, iomem->start,
> +                                    resource_size(iomem),
> +                                    mmc_hostname(host->mmc))) {
> +               dev_err(&pdev->dev, "cannot request region\n");
> +               ret = -EBUSY;
> +               goto err_request;
> +       }
> +
> +       host->ioaddr = devm_ioremap(&pdev->dev, iomem->start,
> +                                   resource_size(iomem));
> +       if (!host->ioaddr) {
> +               dev_err(&pdev->dev, "failed to remap registers\n");
> +               ret = -ENOMEM;
> +               goto err_request;
> +       }
> +
> +#if defined(CONFIG_HAVE_CLK)
> +       mv_host->clk = clk_get(&pdev->dev, NULL);
> +       if (IS_ERR(mv_host->clk))
> +               dev_notice(&pdev->dev, "cannot get clkdev\n");
> +       else
> +               clk_enable(mv_host->clk);
> +#endif
> +
> +       ret = sdhci_add_host(host);
> +       if (ret)
> +               goto err_request;
> +
> +       platform_set_drvdata(pdev, host);
> +
> +       return 0;
> +
> +err_request:
> +       sdhci_free_host(host);
> +err:
> +       printk(KERN_ERR"Probing of sdhci-mv failed: %d\n", ret);
> +       return ret;
> +}
> +
> +static int __devexit sdhci_mv_remove(struct platform_device *pdev)
> +{
> +       struct sdhci_host *host = platform_get_drvdata(pdev);
> +#if defined(CONFIG_HAVE_CLK)
> +       struct sdhci_mv_host *mv_host = sdhci_priv(host);
> +       struct clk *clk = mv_host->clk;
> +#endif
> +       int dead;
> +       u32 scratch;
> +
> +       dead = 0;
> +       scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
> +       if (scratch == (u32)-1)
> +               dead = 1;
> +
> +       sdhci_remove_host(host, dead);
> +       sdhci_free_host(host);
> +       platform_set_drvdata(pdev, NULL);
> +#if defined(CONFIG_HAVE_CLK)
> +       if (!IS_ERR(clk)) {
> +               clk_disable(clk);
> +               clk_put(clk);
> +       }
> +#endif
> +
> +       return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int sdhci_mv_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> +       struct sdhci_host *host = dev_get_drvdata(&pdev->dev);
> +
> +       return sdhci_suspend_host(host, state);
> +}
> +
> +static int sdhci_mv_resume(struct platform_device *pdev)
> +{
> +       struct sdhci_host *host = dev_get_drvdata(&pdev->dev);
> +
> +       return sdhci_resume_host(host);
> +}
> +#else
> +#define sdhci_mv_suspend NULL
> +#define sdhci_mv_resume NULL
> +#endif
> +
> +static struct platform_driver sdhci_mv_driver = {
> +       .driver = {
> +               .name   = "sdhci-mv",
> +               .owner  = THIS_MODULE,
> +       },
> +       .probe          = sdhci_mv_probe,
> +       .remove         = __devexit_p(sdhci_mv_remove),
> +       .suspend        = sdhci_mv_suspend,
> +       .resume         = sdhci_mv_resume,
> +};
> +
> +/*****************************************************************************\
> + *                                                                           *
> + * Driver init/exit                                                          *
> + *                                                                           *
> +\*****************************************************************************/
> +
> +static int __init sdhci_mv_init(void)
> +{
> +       return platform_driver_register(&sdhci_mv_driver);
> +}
> +
> +static void __exit sdhci_mv_exit(void)
> +{
> +       platform_driver_unregister(&sdhci_mv_driver);
> +}
> +
> +module_init(sdhci_mv_init);
> +module_exit(sdhci_mv_exit);
> +
> +MODULE_DESCRIPTION("Marvell SDHCI platform driver");
> +MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:sdhci-mv");
> +
> --
> 1.6.0.4
>
>

[-- Attachment #2: 0001-MMC-add-support-for-the-Marvell-platform-SDHCI-cont.patch --]
[-- Type: application/octet-stream, Size: 8450 bytes --]

From 4d8abec442d94895d3d2c7d7f9d59c5e19d379b2 Mon Sep 17 00:00:00 2001
From: Saeed Bishara <saeed@marvell.com>
Date: Tue, 4 May 2010 19:13:24 +0300
Subject: [PATCHv2] MMC: add support for the Marvell platform SDHCI controller

This patch implements the driver for the platfrom SDHCI controllers that found on some of Marvell's SoC's.

Signed-off-by: Saeed Bishara <saeed@marvell.com>
---
 drivers/mmc/host/Kconfig    |   12 ++
 drivers/mmc/host/Makefile   |    1 +
 drivers/mmc/host/sdhci-mv.c |  243 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 256 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mmc/host/sdhci-mv.c

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 2e13b94..d132256 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -146,6 +146,18 @@ config MMC_SDHCI_S3C_DMA
 
 	  YMMV.
 
+config MMC_SDHCI_MV
+	tristate "SDHCI support on Marvell's soc"
+	depends on MMC_SDHCI
+	select MMC_SDHCI_IO_ACCESSORS
+	help
+	  This selects the Secure Digital Host Controller Interface in
+	  Marvell's SoC controllers.
+
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_OMAP
 	tristate "TI OMAP Multimedia Card Interface support"
 	depends on ARCH_OMAP
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index f480397..3a5519a 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)	+= sdhci-pci.o
 obj-$(CONFIG_MMC_SDHCI_PLTFM)	+= sdhci-pltfm.o
 obj-$(CONFIG_MMC_SDHCI_S3C)	+= sdhci-s3c.o
+obj-$(CONFIG_MMC_SDHCI_MV)	+= sdhci-mv.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
 obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)		+= omap.o
diff --git a/drivers/mmc/host/sdhci-mv.c b/drivers/mmc/host/sdhci-mv.c
new file mode 100644
index 0000000..93adf2a
--- /dev/null
+++ b/drivers/mmc/host/sdhci-mv.c
@@ -0,0 +1,243 @@
+/*
+ * sdhci-mv.c Support for SDHCI platform devices
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * SDHCI platform devices found on Marvell SoC's
+ *
+ * Based on  sdhci-pltfm.c
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/mmc/host.h>
+#include "sdhci.h"
+
+struct sdhci_mv_host {
+#if defined(CONFIG_HAVE_CLK)
+	struct clk		*clk;
+#endif
+};
+
+/*****************************************************************************\
+ *                                                                           *
+ * SDHCI core callbacks                                                      *
+ *                                                                           *
+\*****************************************************************************/
+static u16 mv_readw(struct sdhci_host *host, int reg)
+{
+	u16 ret;
+
+	switch (reg) {
+	case SDHCI_HOST_VERSION:
+	case SDHCI_SLOT_INT_STATUS:
+		/* those registers don't exist */
+		return 0;
+	default:
+		ret = readw(host->ioaddr + reg);
+	}
+	return ret;
+}
+
+static u32 mv_readl(struct sdhci_host *host, int reg)
+{
+	u32 ret;
+
+	switch (reg) {
+	case SDHCI_CAPABILITIES:
+		ret = readl(host->ioaddr + reg);
+		/* Mask the support for 3.0V */
+		ret &= ~SDHCI_CAN_VDD_300;
+		break;
+	default:
+		ret = readl(host->ioaddr + reg);
+	}
+	return ret;
+}
+
+static struct sdhci_ops sdhci_mv_ops = {
+	.read_w = mv_readw,
+	.read_l = mv_readl,
+};
+
+/*****************************************************************************\
+ *                                                                           *
+ * Device probing/removal                                                    *
+ *                                                                           *
+\*****************************************************************************/
+
+static int __devinit sdhci_mv_probe(struct platform_device *pdev)
+{
+	struct sdhci_host *host;
+	struct sdhci_mv_host *mv_host;
+	struct resource *iomem;
+	int ret;
+
+	BUG_ON(pdev == NULL);
+
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iomem) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (resource_size(iomem) != 0x100)
+		dev_err(&pdev->dev, "Invalid iomem size. You may "
+			"experience problems.\n");
+
+	if (pdev->dev.parent)
+		host = sdhci_alloc_host(pdev->dev.parent, sizeof(*mv_host));
+	else
+		host = sdhci_alloc_host(&pdev->dev, sizeof(*mv_host));
+
+	if (IS_ERR(host)) {
+		ret = PTR_ERR(host);
+		goto err;
+	}
+
+	mv_host = sdhci_priv(host);
+	host->hw_name = "marvell-sdhci";
+	host->ops = &sdhci_mv_ops;
+	host->irq = platform_get_irq(pdev, 0);
+	host->quirks =  SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
+			SDHCI_QUIRK_NO_BUSY_IRQ |
+			SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+			SDHCI_QUIRK_FORCE_DMA;
+
+	if (!devm_request_mem_region(&pdev->dev, iomem->start,
+				     resource_size(iomem),
+				     mmc_hostname(host->mmc))) {
+		dev_err(&pdev->dev, "cannot request region\n");
+		ret = -EBUSY;
+		goto err_request;
+	}
+
+	host->ioaddr = devm_ioremap(&pdev->dev, iomem->start,
+				    resource_size(iomem));
+	if (!host->ioaddr) {
+		dev_err(&pdev->dev, "failed to remap registers\n");
+		ret = -ENOMEM;
+		goto err_request;
+	}
+
+#if defined(CONFIG_HAVE_CLK)
+	mv_host->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mv_host->clk))
+		dev_notice(&pdev->dev, "cannot get clkdev\n");
+	else
+		clk_enable(mv_host->clk);
+#endif
+
+	ret = sdhci_add_host(host);
+	if (ret)
+		goto err_request;
+
+	platform_set_drvdata(pdev, host);
+
+	return 0;
+
+err_request:
+	sdhci_free_host(host);
+err:
+	printk(KERN_ERR"Probing of sdhci-mv failed: %d\n", ret);
+	return ret;
+}
+
+static int __devexit sdhci_mv_remove(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+#if defined(CONFIG_HAVE_CLK)
+	struct sdhci_mv_host *mv_host = sdhci_priv(host);
+	struct clk *clk = mv_host->clk;
+#endif
+	int dead;
+	u32 scratch;
+
+	dead = 0;
+	scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
+	if (scratch == (u32)-1)
+		dead = 1;
+
+	sdhci_remove_host(host, dead);
+	sdhci_free_host(host);
+	platform_set_drvdata(pdev, NULL);
+#if defined(CONFIG_HAVE_CLK)
+	if (!IS_ERR(clk)) {
+		clk_disable(clk);
+		clk_put(clk);
+	}
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int sdhci_mv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct sdhci_host *host = dev_get_drvdata(&pdev->dev);
+
+	return sdhci_suspend_host(host, state);
+}
+
+static int sdhci_mv_resume(struct platform_device *pdev)
+{
+	struct sdhci_host *host = dev_get_drvdata(&pdev->dev);
+
+	return sdhci_resume_host(host);
+}
+#else
+#define sdhci_mv_suspend NULL
+#define sdhci_mv_resume NULL
+#endif
+
+static struct platform_driver sdhci_mv_driver = {
+	.driver = {
+		.name	= "sdhci-mv",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sdhci_mv_probe,
+	.remove		= __devexit_p(sdhci_mv_remove),
+	.suspend	= sdhci_mv_suspend,
+	.resume		= sdhci_mv_resume,
+};
+
+/*****************************************************************************\
+ *                                                                           *
+ * Driver init/exit                                                          *
+ *                                                                           *
+\*****************************************************************************/
+
+static int __init sdhci_mv_init(void)
+{
+	return platform_driver_register(&sdhci_mv_driver);
+}
+
+static void __exit sdhci_mv_exit(void)
+{
+	platform_driver_unregister(&sdhci_mv_driver);
+}
+
+module_init(sdhci_mv_init);
+module_exit(sdhci_mv_exit);
+
+MODULE_DESCRIPTION("Marvell SDHCI platform driver");
+MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sdhci-mv");
+
-- 
1.6.0.4


  reply	other threads:[~2010-05-05 13:39 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-05-04 16:24 [PATCH] MMC: add support for the Marvell platform SDHCI controller Saeed Bishara
2010-05-05 13:39 ` saeed bishara [this message]
2010-05-25  7:21   ` saeed bishara
  -- strict thread matches above, loose matches on Subject: below --
2010-06-22 14:09 Saeed Bishara
2010-06-23 11:52 ` Matt Fleming
2010-06-23 12:11   ` saeed bishara
2010-06-23 14:06     ` Matt Fleming
2010-08-25 22:39 ` Matt Fleming
2010-08-25 23:16   ` Andrew Morton
2010-09-10 20:16 ` Chris Ball
2010-10-27  8:07 Mike Rapoport
2010-10-27  8:46 ` Saeed Bishara
2010-10-27  9:17   ` Mike Rapoport
2010-10-27  9:10 ` Chris Ball

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=s2tc70ff3ad1005050639xf79968ddle48c06d007af043c@mail.gmail.com \
    --to=saeed.bishara@gmail.com \
    --cc=linux-mmc@vger.kernel.org \
    --cc=saeed@marvell.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).