2010/12/7 Philip Rakity <prakity@xxxxxxxxxxx>: > > Where is the code that implements > >> + unsigned int clk_delay_cycles; >> + unsigned int clk_delay_sel; The code is located under arch/arm/, it is used differently depends on different platfrom. For example, aspen could realize under arch/arm/mach-pxa/pxa168.c. Could you refer the code for mmp2. > > > > > On Dec 6, 2010, at 9:56 PM, Raymond Wu wrote: > >> Hi, >> >> This patch is verified by: Raymond Wu(xywu@xxxxxxxxxxx) on pxa955 SAARB platform. >> >> Thanks, >> Raymond >> >> >> -----Original Message----- >> From: zhangfei gao [mailto:zhangfei.gao@xxxxxxxxx] >> Sent: 2010年12月3日 14:31 >> To: linux-mmc@xxxxxxxxxxxxxxx >> Cc: Chris Ball; Eric Miao; Haojian Zhuang; niej0001@xxxxxxxxx; Philip Rakity; Mark Brown; Raymond Wu; Jun Nie >> Subject: [PATCH 2/2] sdhci-pxa add call back interface to share sdhci-pxa >> >> From fb5927afac7cbb44805093816bea51dde33da1e5 Mon Sep 17 00:00:00 2001 >> From: Zhangfei Gao <zhangfei.gao@xxxxxxxxxxx> >> Date: Tue, 30 Nov 2010 05:43:29 -0500 >> Subject: [PATCH 2/2] sdhci-pxa: add call back interface to share sdhci-pxa >> >> Call back functions is added to support mmp2, pxa910, pxa168 and pxa955 >> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@xxxxxxxxxxx> >> CC: RaymondWu <xywu@xxxxxxxxxxx> >> CC: Jun Nie <njun@xxxxxxxxxxx> >> CC: Philip Rakity <prakity@xxxxxxxxxxx> >> --- >> arch/arm/plat-pxa/include/plat/sdhci.h | 44 +++++++++++++++++ >> drivers/mmc/host/sdhci-pxa.c | 83 +++++++++++++++++++++----------- >> 2 files changed, 98 insertions(+), 29 deletions(-) >> >> diff --git a/arch/arm/plat-pxa/include/plat/sdhci.h >> b/arch/arm/plat-pxa/include/plat/sdhci.h >> index 1ab332e..4ce3b05 100644 >> --- a/arch/arm/plat-pxa/include/plat/sdhci.h >> +++ b/arch/arm/plat-pxa/include/plat/sdhci.h >> @@ -13,9 +13,14 @@ >> #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) @@ -25,11 +30,50 @@ >> * @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 & pxa168: each step is 1ns, 4bits width >> + * @clk_delay_enable: enable clk_delay or not, used on pxa910 & pxa168 >> + * @clk_delay_sel: select clk_delay, used on pxa910 & pxa168 >> + * 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 >> + * @soc_set_timing: set timing for specific soc >> + * @ext_cd_init: Initialize external card detect subsystem >> + * @ext_cd_cleanup: Cleanup external card detect subsystem >> + * @soc_set_ops: overwrite host ops with soc specific ops >> */ >> +struct sdhci_pxa; >> struct sdhci_pxa_platdata { >> unsigned int max_speed; >> unsigned int quirks; >> 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; >> + >> + void (*soc_set_timing)(struct sdhci_host *host, >> + struct sdhci_pxa_platdata *pdata); >> + int (*ext_cd_init)(void (*notify_func)(struct platform_device *dev, >> + int state), void *data); >> + int (*ext_cd_cleanup)(void (*notify_func)(struct platform_device *dev, >> + int state), void *data); >> + void (*soc_set_ops)(struct sdhci_pxa *pxa); }; >> + >> +struct sdhci_pxa { >> + struct sdhci_host *host; >> + struct sdhci_pxa_platdata *pdata; >> + struct clk *clk; >> + struct resource *res; >> + struct sdhci_ops *ops; >> + >> + u8 clk_enable; >> + u8 power_mode; >> }; >> >> #endif /* __PLAT_PXA_SDHCI_H */ >> diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c index 5a61208..f79dccf 100644 >> --- a/drivers/mmc/host/sdhci-pxa.c >> +++ b/drivers/mmc/host/sdhci-pxa.c >> @@ -24,32 +24,22 @@ >> #include <linux/clk.h> >> #include <linux/io.h> >> #include <linux/err.h> >> +#include <linux/slab.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; >> + struct sdhci_pxa_platdata *pdata = pxa->pdata; >> >> if (clock == 0) { >> if (pxa->clk_enable) { >> @@ -57,21 +47,31 @@ static void set_clock(struct sdhci_host *host, unsigned int clock) >> 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; >> - } >> + if (pdata && pdata->soc_set_timing) >> + pdata->soc_set_timing(host, pdata); >> + clk_enable(pxa->clk); >> + pxa->clk_enable = 1; >> } >> } >> >> -static struct sdhci_ops sdhci_pxa_ops = { >> - .set_clock = set_clock, >> -}; >> +static void sdhci_pxa_notify_change(struct platform_device *dev, int >> +state) { >> + struct sdhci_host *host = platform_get_drvdata(dev); >> + unsigned long flags; >> + >> + if (host) { >> + spin_lock_irqsave(&host->lock, flags); >> + if (state) { >> + dev_dbg(&dev->dev, "card inserted.\n"); >> + host->flags &= ~SDHCI_DEVICE_DEAD; >> + } else { >> + dev_dbg(&dev->dev, "card removed.\n"); >> + host->flags |= SDHCI_DEVICE_DEAD; >> + } >> + tasklet_schedule(&host->card_tasklet); >> + spin_unlock_irqrestore(&host->lock, flags); >> + } >> +} >> >> /*****************************************************************************\ >> * * >> @@ -111,6 +111,12 @@ static int __devinit sdhci_pxa_probe(struct platform_device *pdev) >> pxa->pdata = pdata; >> pxa->clk_enable = 0; >> >> + pxa->ops = kzalloc(sizeof(struct sdhci_ops), GFP_KERNEL); >> + if (!pxa->ops) { >> + ret = -ENOMEM; >> + goto out; >> + } >> + >> pxa->clk = clk_get(dev, "PXA-SDHCLK"); >> if (IS_ERR(pxa->clk)) { >> dev_err(dev, "failed to get io clock\n"); @@ -134,32 +140,46 @@ static int __devinit sdhci_pxa_probe(struct platform_device *pdev) >> } >> >> 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) >> + 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 (pdata && pdata->quirks) >> host->quirks |= pdata->quirks; >> >> /* 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->soc_set_ops) >> + pdata->soc_set_ops(pxa); >> + >> + pxa->ops->set_clock = set_clock; >> + host->ops = pxa->ops; >> + >> 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; >> + if (pdata && pdata->max_speed) >> + host->mmc->f_max = pdata->max_speed; >> >> + if (pdata && pdata->ext_cd_init) >> + pdata->ext_cd_init(&sdhci_pxa_notify_change, pdata); >> platform_set_drvdata(pdev, host); >> >> return 0; >> out: >> if (host) { >> clk_put(pxa->clk); >> + kfree(pxa->ops); >> if (host->ioaddr) >> iounmap(host->ioaddr); >> if (pxa->res) >> @@ -173,18 +193,23 @@ out: >> >> static int __devexit sdhci_pxa_remove(struct platform_device *pdev) { >> + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; >> struct sdhci_host *host = platform_get_drvdata(pdev); >> struct sdhci_pxa *pxa = sdhci_priv(host); >> int dead = 0; >> u32 scratch; >> >> if (host) { >> + if (pdata && pdata->ext_cd_cleanup) >> + pdata->ext_cd_cleanup(&sdhci_pxa_notify_change, pdata); >> + >> scratch = readl(host->ioaddr + SDHCI_INT_STATUS); >> if (scratch == (u32)-1) >> dead = 1; >> >> sdhci_remove_host(host, dead); >> >> + kfree(pxa->ops); >> if (host->ioaddr) >> iounmap(host->ioaddr); >> if (pxa->res) >> -- >> 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