was interested in the 9xx code. On Dec 7, 2010, at 7:38 AM, zhangfei gao wrote: > 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 >> >> ?韬{.n?????%??檩??w?{.n???{炳i?)?骅w*jg????????G??⒏⒎?:+v????????????"??????