* [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