code is missing hooks for 74 clock generation. On May 23, 2011, at 6:21 AM, Zhangfei Gao wrote: > Delete sdhci-pxa.c and replace with sdhci-mmp2.c specificlly for mmp2 > > Signed-off-by: Zhangfei Gao <zhangfei.gao@xxxxxxxxxxx> > --- > arch/arm/plat-pxa/include/plat/sdhci.h | 43 ++++- > drivers/mmc/host/Kconfig | 9 +- > drivers/mmc/host/Makefile | 2 +- > drivers/mmc/host/sdhci-mmp2.c | 304 ++++++++++++++++++++++++++++++++ > drivers/mmc/host/sdhci-pxa.c | 303 ------------------------------- > 5 files changed, 349 insertions(+), 312 deletions(-) > create mode 100644 drivers/mmc/host/sdhci-mmp2.c > delete 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 > index 1ab332e..92becc0 100644 > --- a/arch/arm/plat-pxa/include/plat/sdhci.h > +++ b/arch/arm/plat-pxa/include/plat/sdhci.h > @@ -13,23 +13,58 @@ > #ifndef __PLAT_PXA_SDHCI_H > #define __PLAT_PXA_SDHCI_H > > +#include <linux/mmc/sdhci.h> > +#include <linux/platform_device.h> > + > /* pxa specific flag */ > /* Require clock free running */ > #define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0) > - > +/* card alwayes wired to host, like on-chip emmc */ > +#define PXA_FLAG_CARD_PERMANENT (1<<1) > /* Board design supports 8-bit data on SD/SDIO BUS */ > #define PXA_FLAG_SD_8_BIT_CAPABLE_SLOT (1<<2) > +/* card not use wp, such as micro sd card */ > +#define PXA_FLAG_CARD_NO_WP (3<<1) > > +struct sdhci_pxa; > /* > * 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 > + * @clk_delay_cycles: > + * mmp2: each step is roughly 100ps, 5bits width > + * pxa910: each step is 1ns, 4bits width > + * @clk_delay_sel: select clk_delay, used on pxa910 > + * 0: choose feedback clk > + * 1: choose feedback clk + delay value > + * 2: choose internal clk > + * @ext_cd_gpio: gpio pin used for external CD line > + * @ext_cd_gpio_invert: invert values for external CD gpio line > + * @clk_delay_enable: enable clk_delay or not, used on pxa910 > + * @max_speed: the maximum speed supported > + * @host_caps: Standard MMC host capabilities bit field. > + * @quirks: quirks of platfrom > + * @pm_caps: pm_caps of platfrom > */ > struct sdhci_pxa_platdata { > + unsigned int flags; > + unsigned int clk_delay_cycles; > + unsigned int clk_delay_sel; > + unsigned int ext_cd_gpio; > + bool ext_cd_gpio_invert; > + bool clk_delay_enable; > unsigned int max_speed; > + unsigned int host_caps; > unsigned int quirks; > - unsigned int flags; > + unsigned int pm_caps; > +}; > + > +struct sdhci_pxa { > + struct sdhci_pxa_platdata *pdata; > + struct clk *clk; > + struct sdhci_ops *ops; > + > + u8 clk_enable; > + u8 power_mode; > }; > > #endif /* __PLAT_PXA_SDHCI_H */ > diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig > index 862235e..1e520e3 100644 > --- a/drivers/mmc/host/Kconfig > +++ b/drivers/mmc/host/Kconfig > @@ -181,14 +181,15 @@ config MMC_SDHCI_S3C > > If unsure, say N. > > -config MMC_SDHCI_PXA > - tristate "Marvell PXA168/PXA910/MMP2 SD Host Controller support" > +config MMC_SDHCI_MMP2 > + tristate "Marvell MMP2 SD Host Controller support" > depends on ARCH_PXA || ARCH_MMP > select MMC_SDHCI > + select MMC_SDHCI_PLTFM > 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 > + This selects the Marvell(R) MMP2 SD Host Controller. > + If you have a MMP2 platform with SD Host Controller > and a card slot, say Y or M here. > > If unsure, say N. > diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile > index 4933004..f8650e0 100644 > --- a/drivers/mmc/host/Makefile > +++ b/drivers/mmc/host/Makefile > @@ -9,7 +9,7 @@ obj-$(CONFIG_MMC_MXC) += mxcmmc.o > obj-$(CONFIG_MMC_MXS) += mxs-mmc.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_MMP2) += sdhci-mmp2.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-mmp2.c b/drivers/mmc/host/sdhci-mmp2.c > new file mode 100644 > index 0000000..566d525 > --- /dev/null > +++ b/drivers/mmc/host/sdhci-mmp2.c > @@ -0,0 +1,304 @@ > +/* > + * Copyright (C) 2010 Marvell International Ltd. > + * > + * This software is licensed under the terms of the GNU General Public > + * License version 2, as published by the Free Software Foundation, and > + * may be copied, distributed, and modified under those terms. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > + > +#include <linux/err.h> > +#include <linux/init.h> > +#include <linux/platform_device.h> > +#include <linux/clk.h> > +#include <linux/io.h> > +#include <linux/gpio.h> > +#include <linux/mmc/card.h> > +#include <linux/mmc/host.h> > +#include <plat/sdhci.h> > +#include <linux/slab.h> > +#include "sdhci.h" > +#include "sdhci-pltfm.h" > + > +#define MMP2_SD_FIFO_PARAM 0x104 > +#define MMP2_DIS_PAD_SD_CLK_GATE 0x400 > + > +#define MMP2_SD_CLOCK_AND_BURST_SIZE_SETUP 0x10A > +#define MMP2_SDCLK_SEL 0x100 > +#define MMP2_SDCLK_DELAY_SHIFT 9 > +#define MMP2_SDCLK_DELAY_MASK 0x1f > + > +#define SD_CFG_FIFO_PARAM 0x100 > +#define SDCFG_GEN_PAD_CLK_ON (1<<6) > +#define SDCFG_GEN_PAD_CLK_CNT_MASK 0xFF > +#define SDCFG_GEN_PAD_CLK_CNT_SHIFT 24 > + > +#define SD_SPI_MODE 0x108 > +#define SD_CE_ATA_1 0x10C > + > +#define SD_CE_ATA_2 0x10E > +#define SDCE_MISC_INT (1<<2) > +#define SDCE_MISC_INT_EN (1<<1) > + > +static void mmp2_soc_set_timing(struct sdhci_host *host, > + struct sdhci_pxa_platdata *pdata) > +{ > + /* > + * tune timing of read data/command when crc error happen > + * no performance impact > + */ > + if (pdata && 0 != pdata->clk_delay_cycles) { > + u16 tmp; > + > + tmp = readw(host->ioaddr + MMP2_SD_CLOCK_AND_BURST_SIZE_SETUP); > + tmp |= (pdata->clk_delay_cycles & MMP2_SDCLK_DELAY_MASK) > + << MMP2_SDCLK_DELAY_SHIFT; > + tmp |= MMP2_SDCLK_SEL; > + writew(tmp, host->ioaddr + MMP2_SD_CLOCK_AND_BURST_SIZE_SETUP); > + } > + > + /* > + * disable clock gating per some cards requirement > + */ > + > + if (pdata && pdata->flags & PXA_FLAG_DISABLE_CLOCK_GATING) { > + u32 tmp = 0; > + > + tmp = readl(host->ioaddr + MMP2_SD_FIFO_PARAM); > + tmp |= MMP2_DIS_PAD_SD_CLK_GATE; > + writel(tmp, host->ioaddr + MMP2_SD_FIFO_PARAM); > + } > +} > + > +static unsigned int mmp2_get_ro(struct sdhci_host *host) > +{ > + /* Micro SD does not support write-protect feature */ > + return 0; > +} > + > +static void mmp2_set_clock(struct sdhci_host *host, unsigned int clock) > +{ > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct sdhci_pxa *pxa = pltfm_host->priv; > + > + if (clock) > + mmp2_soc_set_timing(host, pxa->pdata); > +} > + > +static int mmp2_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) > +{ > + u16 ctrl_2; > + > + /* > + * Set V18_EN -- UHS modes do not work without this. > + * does not change signaling voltage > + */ > + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); > + > + /* Select Bus Speed Mode for host */ > + ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; > + switch (uhs) { > + case MMC_TIMING_UHS_SDR12: > + ctrl_2 |= SDHCI_CTRL_UHS_SDR12; > + break; > + case MMC_TIMING_UHS_SDR25: > + ctrl_2 |= SDHCI_CTRL_UHS_SDR25; > + break; > + case MMC_TIMING_UHS_SDR50: > + ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180; > + break; > + case MMC_TIMING_UHS_SDR104: > + ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180; > + break; > + case MMC_TIMING_UHS_DDR50: > + ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180; > + break; > + } > + > + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); > + dev_dbg(mmc_dev(host->mmc), > + "%s:%s uhs = %d, ctrl_2 = %04X\n", > + __func__, mmc_hostname(host->mmc), uhs, ctrl_2); > + > + return 0; > +} > + > +static int __devinit sdhci_mmp2_probe(struct platform_device *pdev) > +{ > + struct sdhci_pltfm_host *pltfm_host; > + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; > + struct device *dev = &pdev->dev; > + struct sdhci_host *host = NULL; > + struct sdhci_pxa *pxa = NULL; > + int ret; > + struct clk *clk; > + > + pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL); > + if (!pxa) { > + ret = -ENOMEM; > + goto out; > + } > + pxa->ops = kzalloc(sizeof(struct sdhci_ops), GFP_KERNEL); > + if (!pxa->ops) { > + ret = -ENOMEM; > + goto out; > + } > + pxa->pdata = pdata; > + > + clk = clk_get(dev, "PXA-SDHCLK"); > + if (IS_ERR(clk)) { > + dev_err(dev, "failed to get io clock\n"); > + ret = PTR_ERR(clk); > + goto out; > + } > + pxa->clk = clk; > + clk_enable(clk); > + > + host = sdhci_pltfm_init(pdev, NULL); > + if (IS_ERR(host)) > + return PTR_ERR(host); > + > + pltfm_host = sdhci_priv(host); > + pltfm_host->priv = pxa; > + > + host->quirks = SDHCI_QUIRK_BROKEN_ADMA > + | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL > + | SDHCI_QUIRK_32BIT_DMA_ADDR > + | SDHCI_QUIRK_32BIT_DMA_SIZE > + | SDHCI_QUIRK_32BIT_ADMA_SIZE > + | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; > + > + /* enable 1/8V DDR capable */ > + host->mmc->caps |= MMC_CAP_1_8V_DDR; > + > + if (pdata && pdata->flags & PXA_FLAG_CARD_PERMANENT) { > + /* on-chip device */ > + host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; > + host->mmc->caps |= MMC_CAP_NONREMOVABLE; > + } > + > + /* If slot design supports 8 bit data, indicate this to MMC. */ > + if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT) > + host->mmc->caps |= MMC_CAP_8_BIT_DATA; > + > + if (pdata && pdata->quirks) > + host->quirks |= pdata->quirks; > + if (pdata && pdata->host_caps) > + host->mmc->caps |= pdata->host_caps; > + if (pdata && pdata->pm_caps) > + host->mmc->pm_caps |= pdata->pm_caps; > + > + pxa->ops->set_clock = mmp2_set_clock; > + pxa->ops->set_uhs_signaling = mmp2_set_uhs_signaling; > + if (pdata && pdata->flags & PXA_FLAG_CARD_NO_WP) > + pxa->ops->get_ro = mmp2_get_ro; > + > + host->ops = pxa->ops; > + > + ret = sdhci_add_host(host); > + if (ret) { > + dev_err(&pdev->dev, "failed to add host\n"); > + goto out; > + } > + > + platform_set_drvdata(pdev, host); > + > + return 0; > +out: > + if (host) { > + clk_disable(pltfm_host->clk); > + clk_put(pltfm_host->clk); > + sdhci_pltfm_free(pdev); > + } > + > + if (pxa) > + kfree(pxa->ops); > + kfree(pxa); > + > + return ret; > +} > + > +static int __devexit sdhci_mmp2_remove(struct platform_device *pdev) > +{ > + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; > + struct sdhci_host *host = platform_get_drvdata(pdev); > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct sdhci_pxa *pxa = pltfm_host->priv; > + 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); > + > + clk_disable(pxa->clk); > + clk_put(pxa->clk); > + sdhci_pltfm_free(pdev); > + > + platform_set_drvdata(pdev, NULL); > + } > + > + if (pxa) > + kfree(pxa->ops); > + kfree(pxa); > + > + return 0; > +} > + > +#ifdef CONFIG_PM > +static int sdhci_mmp2_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_mmp2_resume(struct platform_device *dev) > +{ > + struct sdhci_host *host = platform_get_drvdata(dev); > + > + return sdhci_resume_host(host); > +} > +#else > +#define sdhci_mmp2_suspend NULL > +#define sdhci_mmp2_resume NULL > +#endif > + > + > +static struct platform_driver sdhci_mmp2_driver = { > + .driver = { > + .name = "sdhci-mmp2", > + .owner = THIS_MODULE, > + }, > + .probe = sdhci_mmp2_probe, > + .remove = __devexit_p(sdhci_mmp2_remove), > +#ifdef CONFIG_PM > + .suspend = sdhci_mmp2_suspend, > + .resume = sdhci_mmp2_resume, > +#endif > +}; > +static int __init sdhci_mmp2_init(void) > +{ > + return platform_driver_register(&sdhci_mmp2_driver); > +} > + > +static void __exit sdhci_mmp2_exit(void) > +{ > + platform_driver_unregister(&sdhci_mmp2_driver); > +} > + > +module_init(sdhci_mmp2_init); > +module_exit(sdhci_mmp2_exit); > + > +MODULE_DESCRIPTION("SDHCI driver for mmp2"); > +MODULE_AUTHOR("Marvell International Ltd."); > +MODULE_LICENSE("GPL v2"); > + > diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c > deleted file mode 100644 > index 089c9a6..0000000 > --- a/drivers/mmc/host/sdhci-pxa.c > +++ /dev/null > @@ -1,303 +0,0 @@ > -/* linux/drivers/mmc/host/sdhci-pxa.c > - * > - * Copyright (C) 2010 Marvell International Ltd. > - * Zhangfei Gao <zhangfei.gao@xxxxxxxxxxx> > - * Kevin Wang <dwang4@xxxxxxxxxxx> > - * Mingwei Wang <mwwang@xxxxxxxxxxx> > - * Philip Rakity <prakity@xxxxxxxxxxx> > - * Mark Brown <markb@xxxxxxxxxxx> > - * > - * 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 int set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) > -{ > - u16 ctrl_2; > - > - /* > - * Set V18_EN -- UHS modes do not work without this. > - * does not change signaling voltage > - */ > - ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); > - > - /* Select Bus Speed Mode for host */ > - ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; > - switch (uhs) { > - case MMC_TIMING_UHS_SDR12: > - ctrl_2 |= SDHCI_CTRL_UHS_SDR12; > - break; > - case MMC_TIMING_UHS_SDR25: > - ctrl_2 |= SDHCI_CTRL_UHS_SDR25; > - break; > - case MMC_TIMING_UHS_SDR50: > - ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180; > - break; > - case MMC_TIMING_UHS_SDR104: > - ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180; > - break; > - case MMC_TIMING_UHS_DDR50: > - ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180; > - break; > - } > - > - sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); > - pr_debug("%s:%s uhs = %d, ctrl_2 = %04X\n", > - __func__, mmc_hostname(host->mmc), uhs, ctrl_2); > - > - return 0; > -} > - > -static struct sdhci_ops sdhci_pxa_ops = { > - .set_uhs_signaling = set_uhs_signaling, > - .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 > - | SDHCI_QUIRK_32BIT_DMA_ADDR > - | SDHCI_QUIRK_32BIT_DMA_SIZE > - | SDHCI_QUIRK_32BIT_ADMA_SIZE > - | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; > - > - if (pdata->quirks) > - host->quirks |= pdata->quirks; > - > - /* enable 1/8V DDR capable */ > - host->mmc->caps |= MMC_CAP_1_8V_DDR; > - > - /* If slot design supports 8 bit data, indicate this to MMC. */ > - if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT) > - host->mmc->caps |= MMC_CAP_8_BIT_DATA; > - > - 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@xxxxxxxxxxx>"); > -MODULE_LICENSE("GPL v2"); > -- > 1.7.0.4 > -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html