Re: [PATCH v6 2/4] ARM: pxa168: Add SDHCI support
On 3/17/13 8:13 PM, Haojian Zhuang wrote: On Mon, Mar 18, 2013 at 2:18 AM, Tanmay Upadhyay wrote: v2 - clock register for SDHCI are not common across all MMP SoCs. So, move PXA168 implementation to pxa168.c v3 - sdhci-pxav1 driver code is merged with sdhci-pxav2. So, change the device name accordingly - start sdhci device numbering from 1 as other PXA168 devices does that v4 - Use different names for SD clock registers for PXA168 instead of redefining them in pxa168.c. Suggested by Haojian Zhuang v5 - Have two different clock enable functions for clock block 1 & 2 & don't change indentation in regs-apmu.h as suggested by Haojian Zhuang - Use device name while adding clock as suggested by Russell King v6 - Rebase for Linux v3.8; de-select COMMON_CLK for PXA168 as its SDHCI clocks should be handled differently than others --- arch/arm/mach-mmp/Kconfig |1 - arch/arm/mach-mmp/clock-pxa168.c| 47 +++ arch/arm/mach-mmp/include/mach/pxa168.h | 20 + arch/arm/mach-mmp/pxa168.c |4 +++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig index ebdda83..530245c 100644 --- a/arch/arm/mach-mmp/Kconfig +++ b/arch/arm/mach-mmp/Kconfig @@ -111,7 +111,6 @@ endmenu config CPU_PXA168 bool - select COMMON_CLK select CPU_MOHAWK help Select code specific to PXA168 diff --git a/arch/arm/mach-mmp/clock-pxa168.c b/arch/arm/mach-mmp/clock-pxa168.c index 5e6c18c..65ea00e 100644 --- a/arch/arm/mach-mmp/clock-pxa168.c +++ b/arch/arm/mach-mmp/clock-pxa168.c @@ -31,11 +31,49 @@ #define APBC_SSP4 APBC_REG(0x858) #define APBC_SSP5 APBC_REG(0x85c) +#define APMU_SDH0 APMU_REG(0x054) +#define APMU_SDH1 APMU_REG(0x058) #define APMU_NAND APMU_REG(0x060) #define APMU_LCD APMU_REG(0x04c) +#define APMU_SDH2 APMU_REG(0x0e0) +#define APMU_SDH3 APMU_REG(0x0e4) #define APMU_ETH APMU_REG(0x0fc) #define APMU_USB APMU_REG(0x05c) +static void sdh1_clk_enable(struct clk *clk) +{ + /* Bits 3 & 0 in registers for host 0 should be set for host 1 also */ + __raw_writel(__raw_readl(APMU_SDH0) | 0x9, APMU_SDH0); + + __raw_writel(__raw_readl(clk->clk_rst) | clk->enable_val, clk->clk_rst); +} + +static void sdh2_clk_enable(struct clk *clk) +{ + /* Bits 3 & 0 in registers for host 2 should be set for host 3 also */ + __raw_writel(__raw_readl(APMU_SDH2) | 0x9, APMU_SDH2); + + __raw_writel(__raw_readl(clk->clk_rst) | clk->enable_val, clk->clk_rst); +} + +static void sdh_clk_disable(struct clk *clk) +{ + __raw_writel(__raw_readl(clk->clk_rst) & ~clk->enable_val, + clk->clk_rst); +} + +/* Block 1 for controller 0 & 1 */ +struct clkops sdh1_clk_ops = { + .enable = sdh1_clk_enable, + .disable= sdh_clk_disable, +}; + +/* Block 2 for controller 2 & 3 */ +struct clkops sdh2_clk_ops = { + .enable = sdh2_clk_enable, + .disable= sdh_clk_disable, +}; + /* APB peripheral clocks */ static APBC_CLK(uart1, UART1, 1, 14745600); static APBC_CLK(uart2, UART2, 1, 14745600); @@ -60,6 +98,11 @@ static APMU_CLK(lcd, LCD, 0x7f, 31200); static APMU_CLK(eth, ETH, 0x09, 0); static APMU_CLK(usb, USB, 0x12, 0); +static APMU_CLK_OPS(sdh1, SDH0, 0x12, 4800, &sdh1_clk_ops); +static APMU_CLK_OPS(sdh2, SDH1, 0x12, 4800, &sdh1_clk_ops); +static APMU_CLK_OPS(sdh3, SDH2, 0x12, 4800, &sdh2_clk_ops); +static APMU_CLK_OPS(sdh4, SDH3, 0x12, 4800, &sdh2_clk_ops); + /* device and clock bindings */ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL), @@ -83,6 +126,10 @@ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"), INIT_CLKREG(&clk_usb, NULL, "PXA168-USBCLK"), INIT_CLKREG(&clk_rtc, "sa1100-rtc", NULL), + INIT_CLKREG(&clk_sdh1, "sdhci-pxav2.0", "PXA-SDHCLK"), + INIT_CLKREG(&clk_sdh2, "sdhci-pxav2.1", "PXA-SDHCLK"), + INIT_CLKREG(&clk_sdh3, "sdhci-pxav2.2", "PXA-SDHCLK"), + INIT_CLKREG(&clk_sdh4, "sdhci-pxav2.3", "PXA-SDHCLK"), }; void __init pxa168_clk_init(void) diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 37632d9..805117e 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -17,6 +17,7 @@ extern void pxa168_clear_keypad_wakeup(void); #include #include #include +#include extern struct pxa_device_desc pxa168_device_uart1; e
[PATCH v2 4/4] ARM: pxa168/gplugd: Add support for SD port 1
v2 - after sdhci-pxav1 driver is merged with sdhci-pxav2, pass pxav1_controller = 1 - as sdhci device numbering now starts from 1, call pxa168_add_sdh accordingly Signed-off-by: Tanmay Upadhyay Reviewed-by: Philip Rakity --- arch/arm/mach-mmp/gplugd.c |6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c index 5c3d61e..d821368 100644 --- a/arch/arm/mach-mmp/gplugd.c +++ b/arch/arm/mach-mmp/gplugd.c @@ -155,6 +155,11 @@ struct pxa168_eth_platform_data gplugd_eth_platform_data = { .init= gplugd_eth_init, }; +struct sdhci_pxa_platdata gplugd_sdh_platdata = { + .delay_in_ms = 5, + .pxav1_controller = 1, +}; + static void __init select_disp_freq(void) { /* set GPIO 35 & clear GPIO 85 to set LCD External Clock to 74.25 MHz */ @@ -188,6 +193,7 @@ static void __init gplugd_init(void) platform_device_register(&pxa168_device_gpio); pxa168_add_eth(&gplugd_eth_platform_data); + pxa168_add_sdh(1, &gplugd_sdh_platdata); } MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform") -- 1.7.9.5 * eInfochips Business Disclaimer : This e-mail message and all attachments transmitted with it are intended solely for the use of the addressee and may contain legally privileged and confidential information. If the reader of this message is not the intended recipient, or an employee or agent responsible for delivering this message to the intended recipient, you are hereby notified that any dissemination, distribution, copying, or other use of this message or its attachments is strictly prohibited. If you have received this message in error, please notify the sender immediately by replying to this message and please delete it from your computer. Any views expressed in this message are those of the individual sender unless otherwise stated. Company has taken enough precautions to prevent the spread of viruses. However the company accepts no liability for any damage caused by any virus transmitted by this email. * - Notice: This message has been scanned by Trend Micro Mail Security scanner and is believed to be clean -N§˛ćěr¸yúčŘb˛XŹśÇ§vŘ^)Ţş{.nÇ+ˇĽ{ąg"Ř^nrĄöŚzËëh¨čÚ&˘řŽGŤéhŽ(éݢj"úśm§˙ďęäzšŢŕţfŁ˘ˇh§~m
[PATCH v2 3/4] mmc: sdhci-pxa: Add SDHCI driver for PXA16x
PXA16x devices uses SDHCI controller v1. As it's not much different than v2 controller, v1 driver is merged with sdhci-pxav2 driver v2 - instead of having separate file sdhci-pxav1, merge code with sdhci-pxav2 driver code as suggested by Chris Ball Signed-off-by: Philip Rakity Signed-off-by: Tanmay Upadhyay --- drivers/mmc/host/Kconfig|7 --- drivers/mmc/host/sdhci-pxav2.c | 30 +- drivers/mmc/host/sdhci.c|3 +++ drivers/mmc/host/sdhci.h|1 + include/linux/platform_data/pxa_sdhci.h |2 ++ 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index e5faed8..875e2475 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -207,14 +207,15 @@ config MMC_SDHCI_PXAV3 If unsure, say N. config MMC_SDHCI_PXAV2 - tristate "Marvell PXA9XX SD Host Controller support (PXAV2)" + tristate "Marvell PXA16X/PXA9XX SD Host Controller support (PXAV1/V2)" depends on CLKDEV_LOOKUP select MMC_SDHCI select MMC_SDHCI_PLTFM default y if CPU_PXA910 + default y if CPU_PXA168 help - This selects the Marvell(R) PXAV2 SD Host Controller. - If you have a PXA9XX platform with SD Host Controller + This selects the Marvell(R) PXAV1/V2 SD Host Controller. + If you have a PXA16X or PXA9XX platform with SD Host Controller and a card slot, say Y or M here. If unsure, say N. diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index ac854aa..5af7d46 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "sdhci.h" #include "sdhci-pltfm.h" @@ -75,7 +76,13 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask) writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP); } - if (pdata && (pdata->flags & PXA_FLAG_ENABLE_CLOCK_GATING)) { + if (pdata && pdata->pxav1_controller) { + /* no clock gating */ + tmp = readw(host->ioaddr + SD_FIFO_PARAM); + tmp |= DIS_PAD_SD_CLK_GATE; + writew(tmp, host->ioaddr + SD_FIFO_PARAM); + } else if (pdata && (pdata->flags + & PXA_FLAG_ENABLE_CLOCK_GATING)) { tmp = readw(host->ioaddr + SD_FIFO_PARAM); tmp &= ~CLK_GATE_SETTING_BITS; writew(tmp, host->ioaddr + SD_FIFO_PARAM); @@ -118,6 +125,20 @@ static u32 pxav2_get_max_clock(struct sdhci_host *host) return clk_get_rate(pltfm_host->clk); } +/* + * we cannot talk to controller for 8 bus cycles according to sdio spec + * at lowest speed this is 100,000 HZ per cycle or 800,000 cycles + * which is quite a LONG TIME on a fast cpu -- so delay if needed + */ +static void platform_specific_completion(struct sdhci_host *host) +{ + struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; + + if (host->clock < 320 && pdata && pdata->delay_in_ms) + mdelay(pdata->delay_in_ms); +} + static struct sdhci_ops pxav2_sdhci_ops = { .get_max_clock = pxav2_get_max_clock, .platform_reset_exit = pxav2_set_private_registers, @@ -218,6 +239,13 @@ static int sdhci_pxav2_probe(struct platform_device *pdev) if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT) host->mmc->caps |= MMC_CAP_8_BIT_DATA; + if (pdata->pxav1_controller) { + host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ + | SDHCI_QUIRK_32BIT_DMA_SIZE; + pxav2_sdhci_ops.platform_specific_completion + = platform_specific_completion; + } + if (pdata->quirks) host->quirks |= pdata->quirks; if (pdata->host_caps) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6f0bfc0..430eabd 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1001,6 +1001,9 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) mdelay(1); } + if (host->ops->platform_specific_completion) + host->ops->platform_specific_completion(host); + mod_timer(&host->timer, jiffies + 10 * HZ); host->cmd = cmd; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sd
[PATCH 0/4] Add SD support for PXA168 & gplugD
This patch series adds support for on-chip SD controller on PXA168 Tanmay Upadhyay (4): mmc: sdhci-pxa: Trivial fix in Kconfig ARM: pxa168: Add SDHCI support mmc: sdhci-pxa: Add SDHCI driver for PXA16x ARM: pxa168/gplugd: Add support for SD port 1 arch/arm/mach-mmp/Kconfig |1 - arch/arm/mach-mmp/clock-pxa168.c| 47 +++ arch/arm/mach-mmp/gplugd.c |6 arch/arm/mach-mmp/include/mach/pxa168.h | 20 + arch/arm/mach-mmp/pxa168.c |4 +++ drivers/mmc/host/Kconfig| 11 drivers/mmc/host/sdhci-pxav2.c | 30 +++- drivers/mmc/host/sdhci.c|3 ++ drivers/mmc/host/sdhci.h|1 + include/linux/platform_data/pxa_sdhci.h |2 ++ 10 files changed, 118 insertions(+), 7 deletions(-) -- 1.7.9.5 * eInfochips Business Disclaimer : This e-mail message and all attachments transmitted with it are intended solely for the use of the addressee and may contain legally privileged and confidential information. If the reader of this message is not the intended recipient, or an employee or agent responsible for delivering this message to the intended recipient, you are hereby notified that any dissemination, distribution, copying, or other use of this message or its attachments is strictly prohibited. If you have received this message in error, please notify the sender immediately by replying to this message and please delete it from your computer. Any views expressed in this message are those of the individual sender unless otherwise stated. Company has taken enough precautions to prevent the spread of viruses. However the company accepts no liability for any damage caused by any virus transmitted by this email. * - Notice: This message has been scanned by Trend Micro Mail Security scanner and is believed to be clean -
[PATCH 1/4] mmc: sdhci-pxa: Trivial fix in Kconfig
Select MMC_SDHCI_PXAV3 by default if CPU is MMP2 Select MMC_SDHCI_PXAV2 by default if CPU is PXA910 Signed-off-by: Tanmay Upadhyay Reviewed-by: Philip Rakity --- drivers/mmc/host/Kconfig |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 8d13c65..e5faed8 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -198,7 +198,7 @@ config MMC_SDHCI_PXAV3 depends on CLKDEV_LOOKUP select MMC_SDHCI select MMC_SDHCI_PLTFM - default CPU_MMP2 + default y if CPU_MMP2 help This selects the Marvell(R) PXAV3 SD Host Controller. If you have a MMP2 platform with SD Host Controller @@ -211,7 +211,7 @@ config MMC_SDHCI_PXAV2 depends on CLKDEV_LOOKUP select MMC_SDHCI select MMC_SDHCI_PLTFM - default CPU_PXA910 + default y if CPU_PXA910 help This selects the Marvell(R) PXAV2 SD Host Controller. If you have a PXA9XX platform with SD Host Controller -- 1.7.9.5 * eInfochips Business Disclaimer : This e-mail message and all attachments transmitted with it are intended solely for the use of the addressee and may contain legally privileged and confidential information. If the reader of this message is not the intended recipient, or an employee or agent responsible for delivering this message to the intended recipient, you are hereby notified that any dissemination, distribution, copying, or other use of this message or its attachments is strictly prohibited. If you have received this message in error, please notify the sender immediately by replying to this message and please delete it from your computer. Any views expressed in this message are those of the individual sender unless otherwise stated. Company has taken enough precautions to prevent the spread of viruses. However the company accepts no liability for any damage caused by any virus transmitted by this email. * - Notice: This message has been scanned by Trend Micro Mail Security scanner and is believed to be clean -
[PATCH v6 2/4] ARM: pxa168: Add SDHCI support
v2 - clock register for SDHCI are not common across all MMP SoCs. So, move PXA168 implementation to pxa168.c v3 - sdhci-pxav1 driver code is merged with sdhci-pxav2. So, change the device name accordingly - start sdhci device numbering from 1 as other PXA168 devices does that v4 - Use different names for SD clock registers for PXA168 instead of redefining them in pxa168.c. Suggested by Haojian Zhuang v5 - Have two different clock enable functions for clock block 1 & 2 & don't change indentation in regs-apmu.h as suggested by Haojian Zhuang - Use device name while adding clock as suggested by Russell King v6 - Rebase for Linux v3.8; de-select COMMON_CLK for PXA168 as its SDHCI clocks should be handled differently than others --- arch/arm/mach-mmp/Kconfig |1 - arch/arm/mach-mmp/clock-pxa168.c| 47 +++ arch/arm/mach-mmp/include/mach/pxa168.h | 20 + arch/arm/mach-mmp/pxa168.c |4 +++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig index ebdda83..530245c 100644 --- a/arch/arm/mach-mmp/Kconfig +++ b/arch/arm/mach-mmp/Kconfig @@ -111,7 +111,6 @@ endmenu config CPU_PXA168 bool - select COMMON_CLK select CPU_MOHAWK help Select code specific to PXA168 diff --git a/arch/arm/mach-mmp/clock-pxa168.c b/arch/arm/mach-mmp/clock-pxa168.c index 5e6c18c..65ea00e 100644 --- a/arch/arm/mach-mmp/clock-pxa168.c +++ b/arch/arm/mach-mmp/clock-pxa168.c @@ -31,11 +31,49 @@ #define APBC_SSP4 APBC_REG(0x858) #define APBC_SSP5 APBC_REG(0x85c) +#define APMU_SDH0 APMU_REG(0x054) +#define APMU_SDH1 APMU_REG(0x058) #define APMU_NAND APMU_REG(0x060) #define APMU_LCD APMU_REG(0x04c) +#define APMU_SDH2 APMU_REG(0x0e0) +#define APMU_SDH3 APMU_REG(0x0e4) #define APMU_ETH APMU_REG(0x0fc) #define APMU_USB APMU_REG(0x05c) +static void sdh1_clk_enable(struct clk *clk) +{ + /* Bits 3 & 0 in registers for host 0 should be set for host 1 also */ + __raw_writel(__raw_readl(APMU_SDH0) | 0x9, APMU_SDH0); + + __raw_writel(__raw_readl(clk->clk_rst) | clk->enable_val, clk->clk_rst); +} + +static void sdh2_clk_enable(struct clk *clk) +{ + /* Bits 3 & 0 in registers for host 2 should be set for host 3 also */ + __raw_writel(__raw_readl(APMU_SDH2) | 0x9, APMU_SDH2); + + __raw_writel(__raw_readl(clk->clk_rst) | clk->enable_val, clk->clk_rst); +} + +static void sdh_clk_disable(struct clk *clk) +{ + __raw_writel(__raw_readl(clk->clk_rst) & ~clk->enable_val, + clk->clk_rst); +} + +/* Block 1 for controller 0 & 1 */ +struct clkops sdh1_clk_ops = { + .enable = sdh1_clk_enable, + .disable= sdh_clk_disable, +}; + +/* Block 2 for controller 2 & 3 */ +struct clkops sdh2_clk_ops = { + .enable = sdh2_clk_enable, + .disable= sdh_clk_disable, +}; + /* APB peripheral clocks */ static APBC_CLK(uart1, UART1, 1, 14745600); static APBC_CLK(uart2, UART2, 1, 14745600); @@ -60,6 +98,11 @@ static APMU_CLK(lcd, LCD, 0x7f, 31200); static APMU_CLK(eth, ETH, 0x09, 0); static APMU_CLK(usb, USB, 0x12, 0); +static APMU_CLK_OPS(sdh1, SDH0, 0x12, 4800, &sdh1_clk_ops); +static APMU_CLK_OPS(sdh2, SDH1, 0x12, 4800, &sdh1_clk_ops); +static APMU_CLK_OPS(sdh3, SDH2, 0x12, 4800, &sdh2_clk_ops); +static APMU_CLK_OPS(sdh4, SDH3, 0x12, 4800, &sdh2_clk_ops); + /* device and clock bindings */ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL), @@ -83,6 +126,10 @@ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"), INIT_CLKREG(&clk_usb, NULL, "PXA168-USBCLK"), INIT_CLKREG(&clk_rtc, "sa1100-rtc", NULL), + INIT_CLKREG(&clk_sdh1, "sdhci-pxav2.0", "PXA-SDHCLK"), + INIT_CLKREG(&clk_sdh2, "sdhci-pxav2.1", "PXA-SDHCLK"), + INIT_CLKREG(&clk_sdh3, "sdhci-pxav2.2", "PXA-SDHCLK"), + INIT_CLKREG(&clk_sdh4, "sdhci-pxav2.3", "PXA-SDHCLK"), }; void __init pxa168_clk_init(void) diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 37632d9..805117e 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -17,6 +17,7 @@ extern void pxa168_clear_keypad_wakeup(void); #include #include #include +#include extern struct pxa_device_desc pxa168_device_uart1; extern struct pxa_device_desc pxa168_device_uart2; @@ -36,6 +37,10 @@ extern struct pxa_device_desc pxa168_device_nand; extern struct pxa_device_desc pxa168_device_fb; extern struct pxa_device_desc pxa168_device_keypad; extern struct pxa_device_desc pxa168_device_eth; +extern struct pxa_device_desc pxa168_device_sdh1; +extern struct pxa_device_desc pxa168_device_sdh2; +extern str
Re: [PATCH 2/4] ARM: pxa168: Add SDHCI support
On Thursday 29 December 2011 06:36 PM, Haojian Zhuang wrote: On Thu, Dec 29, 2011 at 9:43 PM, Tanmay Upadhyay wrote: v2 - clock register for SDHCI are not common across all MMP SoCs. So, move PXA168 implementation to pxa168.c v3 - sdhci-pxav1 driver code is merged with sdhci-pxav2. So, change the device name accordingly - start sdhci device numbering from 1 as other PXA168 devices does that v4 - Use different names for SD clock registers for PXA168 instead of redefining them in pxa168.c. Suggested by Haojian Zhuang v5 - Have two different clock enable functions for clock block 1& 2 & don't change indentation in regs-apmu.h as suggested by Haojian Zhuang - Use device name while adding clock as suggested by Russell King Signed-off-by: Tanmay Upadhyay Reviewed-by: Philip Rakity --- Acked-by: Haojian Zhuang Hi Eric, Jason, Does this look good to you? Thanks, Tanmay -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/4] ARM: pxa168: Add SDHCI support
v2 - clock register for SDHCI are not common across all MMP SoCs. So, move PXA168 implementation to pxa168.c v3 - sdhci-pxav1 driver code is merged with sdhci-pxav2. So, change the device name accordingly - start sdhci device numbering from 1 as other PXA168 devices does that v4 - Use different names for SD clock registers for PXA168 instead of redefining them in pxa168.c. Suggested by Haojian Zhuang v5 - Have two different clock enable functions for clock block 1 & 2 & don't change indentation in regs-apmu.h as suggested by Haojian Zhuang - Use device name while adding clock as suggested by Russell King Signed-off-by: Tanmay Upadhyay Reviewed-by: Philip Rakity --- arch/arm/mach-mmp/include/mach/pxa168.h| 20 arch/arm/mach-mmp/include/mach/regs-apmu.h |2 + arch/arm/mach-mmp/pxa168.c | 47 3 files changed, 69 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 7fb568d..a181608 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -15,6 +15,7 @@ extern void pxa168_clear_keypad_wakeup(void); #include #include #include +#include extern struct pxa_device_desc pxa168_device_uart1; extern struct pxa_device_desc pxa168_device_uart2; @@ -34,6 +35,10 @@ extern struct pxa_device_desc pxa168_device_nand; extern struct pxa_device_desc pxa168_device_fb; extern struct pxa_device_desc pxa168_device_keypad; extern struct pxa_device_desc pxa168_device_eth; +extern struct pxa_device_desc pxa168_device_sdh1; +extern struct pxa_device_desc pxa168_device_sdh2; +extern struct pxa_device_desc pxa168_device_sdh3; +extern struct pxa_device_desc pxa168_device_sdh4; struct pxa168_usb_pdata { /* If NULL, default phy init routine for PXA168 would be called */ @@ -132,4 +137,19 @@ static inline int pxa168_add_eth(struct pxa168_eth_platform_data *data) { return pxa_register_device(&pxa168_device_eth, data, sizeof(*data)); } + +static inline int pxa168_add_sdh(int id, struct sdhci_pxa_platdata *data) +{ + struct pxa_device_desc *d = NULL; + + switch (id) { + case 1: d = &pxa168_device_sdh1; break; + case 2: d = &pxa168_device_sdh2; break; + case 3: d = &pxa168_device_sdh3; break; + case 4: d = &pxa168_device_sdh4; break; + default: + return -EINVAL; + } + return pxa_register_device(d, data, sizeof(*data)); +} #endif /* __ASM_MACH_PXA168_H */ diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h index 8447ac6..db55618 100644 --- a/arch/arm/mach-mmp/include/mach/regs-apmu.h +++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h @@ -27,6 +27,8 @@ #define APMU_DMA APMU_REG(0x064) #define APMU_GEU APMU_REG(0x068) #define APMU_BUS APMU_REG(0x06c) +#define APMU_PXA168_SDH2 APMU_REG(0x0e0) +#define APMU_PXA168_SDH3 APMU_REG(0x0e4) #define APMU_SDH2 APMU_REG(0x0e8) #define APMU_SDH3 APMU_REG(0x0ec) #define APMU_ETH APMU_REG(0x0fc) diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 76ca15c..d7d7143 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -65,6 +65,40 @@ void __init pxa168_init_irq(void) pxa168_init_gpio(); } +static void sdh1_clk_enable(struct clk *clk) +{ + /* Bits 3 & 0 in registers for host 0 should be set for host 1 also */ + __raw_writel(__raw_readl(APMU_SDH0) | 0x9, APMU_SDH0); + + __raw_writel(__raw_readl(clk->clk_rst) | clk->enable_val, clk->clk_rst); +} + +static void sdh2_clk_enable(struct clk *clk) +{ + /* Bits 3 & 0 in registers for host 2 should be set for host 3 also */ + __raw_writel(__raw_readl(APMU_PXA168_SDH2) | 0x9, APMU_PXA168_SDH2); + + __raw_writel(__raw_readl(clk->clk_rst) | clk->enable_val, clk->clk_rst); +} + +static void sdh_clk_disable(struct clk *clk) +{ + __raw_writel(__raw_readl(clk->clk_rst) & ~clk->enable_val, + clk->clk_rst); +} + +/* Block 1 for controller 0 & 1 */ +struct clkops sdh1_clk_ops = { + .enable = sdh1_clk_enable, + .disable= sdh_clk_disable, +}; + +/* Block 2 for controller 2 & 3 */ +struct clkops sdh2_clk_ops = { + .enable = sdh2_clk_enable, + .disable= sdh_clk_disable, +}; + /* APB peripheral clocks */ static APBC_CLK(uart1, PXA168_UART1, 1, 14745600); static APBC_CLK(uart2, PXA168_UART2, 1, 14745600); @@ -87,6 +121,11 @@ static APMU_CLK(lcd, LCD, 0x7f, 31200); static APMU_CLK(eth, ETH, 0x09, 0); static APMU_CLK(usb, USB, 0x12, 0); +static APMU_CLK_OPS(sdh1, SDH0, 0x12, 4800, &sdh1_clk_ops); +static APMU_CLK_OPS(sdh2, SDH1, 0x12, 4800, &sdh1_clk_ops); +static APMU_CLK_OPS(s
Re: [PATCH v4 2/4] ARM: pxa168: Add SDHCI support
On Tuesday 20 December 2011 07:08 PM, Haojian Zhuang wrote: On Tue, Dec 20, 2011 at 9:25 PM, Haojian Zhuang wrote: On Tue, Dec 20, 2011 at 9:13 PM, Tanmay Upadhyay wrote: v2 - clock register for SDHCI are not common across all MMP SoCs. So, move PXA168 implementation to pxa168.c v3 - sdhci-pxav1 driver code is merged with sdhci-pxav2. So, change the device name accordingly - start sdhci device numbering from 1 as other PXA168 devices does that v4 - Use different names for SD clock registers for PXA168 instead of redefining them in pxa168.c. Suggested by Haojian Zhuang Signed-off-by: Tanmay Upadhyay Reviewed-by: Philip Rakity --- arch/arm/mach-mmp/include/mach/pxa168.h| 20 ++ arch/arm/mach-mmp/include/mach/regs-apmu.h | 40 ++- arch/arm/mach-mmp/pxa168.c | 39 +++ 3 files changed, 80 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 7fb568d..a181608 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -15,6 +15,7 @@ extern void pxa168_clear_keypad_wakeup(void); #include #include #include +#include extern struct pxa_device_desc pxa168_device_uart1; extern struct pxa_device_desc pxa168_device_uart2; @@ -34,6 +35,10 @@ extern struct pxa_device_desc pxa168_device_nand; extern struct pxa_device_desc pxa168_device_fb; extern struct pxa_device_desc pxa168_device_keypad; extern struct pxa_device_desc pxa168_device_eth; +extern struct pxa_device_desc pxa168_device_sdh1; +extern struct pxa_device_desc pxa168_device_sdh2; +extern struct pxa_device_desc pxa168_device_sdh3; +extern struct pxa_device_desc pxa168_device_sdh4; struct pxa168_usb_pdata { /* If NULL, default phy init routine for PXA168 would be called */ @@ -132,4 +137,19 @@ static inline int pxa168_add_eth(struct pxa168_eth_platform_data *data) { return pxa_register_device(&pxa168_device_eth, data, sizeof(*data)); } + +static inline int pxa168_add_sdh(int id, struct sdhci_pxa_platdata *data) +{ + struct pxa_device_desc *d = NULL; + + switch (id) { + case 1: d =&pxa168_device_sdh1; break; + case 2: d =&pxa168_device_sdh2; break; + case 3: d =&pxa168_device_sdh3; break; + case 4: d =&pxa168_device_sdh4; break; + default: + return -EINVAL; + } + return pxa_register_device(d, data, sizeof(*data)); +} #endif /* __ASM_MACH_PXA168_H */ diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h index 8447ac6..a84de77 100644 --- a/arch/arm/mach-mmp/include/mach/regs-apmu.h +++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h @@ -17,27 +17,29 @@ #define APMU_REG(x)(APMU_VIRT_BASE + (x)) /* Clock Reset Control */ -#define APMU_IRE APMU_REG(0x048) -#define APMU_LCD APMU_REG(0x04c) -#define APMU_CCIC APMU_REG(0x050) -#define APMU_SDH0 APMU_REG(0x054) -#define APMU_SDH1 APMU_REG(0x058) -#define APMU_USB APMU_REG(0x05c) -#define APMU_NAND APMU_REG(0x060) -#define APMU_DMA APMU_REG(0x064) -#define APMU_GEU APMU_REG(0x068) -#define APMU_BUS APMU_REG(0x06c) -#define APMU_SDH2 APMU_REG(0x0e8) -#define APMU_SDH3 APMU_REG(0x0ec) -#define APMU_ETH APMU_REG(0x0fc) - -#define APMU_FNCLK_EN (1<< 4) -#define APMU_AXICLK_EN (1<< 3) -#define APMU_FNRST_DIS (1<< 1) -#define APMU_AXIRST_DIS(1<< 0) +#define APMU_IRE APMU_REG(0x048) +#define APMU_LCD APMU_REG(0x04c) +#define APMU_CCIC APMU_REG(0x050) +#define APMU_SDH0 APMU_REG(0x054) +#define APMU_SDH1 APMU_REG(0x058) +#define APMU_USB APMU_REG(0x05c) +#define APMU_NAND APMU_REG(0x060) +#define APMU_DMA APMU_REG(0x064) +#define APMU_GEU APMU_REG(0x068) +#define APMU_BUS APMU_REG(0x06c) +#define APMU_PXA168_SDH2 APMU_REG(0x0e0) +#define APMU_PXA168_SDH3 APMU_REG(0x0e4) +#define APMU_SDH2 APMU_REG(0x0e8) +#define APMU_SDH3 APMU_REG(0x0ec) +#define APMU_ETH APMU_REG(0x0fc) Since you only append APMU_PXA168_SDH2& APMU_PXA168_SDH3, you'd better not touch other registers. If you want to clean the code, you can submit another patch to handle it. Ok. -- Tanmay + +#define APMU_FNCLK_EN (1<< 4) +#define APMU_AXICLK_EN (1<< 3) +#define APMU_FNRST_DIS (1<< 1) +#define APMU_AXIRST_DIS(1<< 0) /* Wake Clear Register */ -#define APMU_WAKE_CLR APMU_REG(0x07c) +#define APMU_WAKE_CLR APMU_REG(0x07c) #define APMU_PXA168_KP_WAKE_CLR(1<< 7) #define APMU_PXA168_CFI_WAKE_CLR (1<< 6) diff --git a/ar
Re: [PATCH v4 2/4] ARM: pxa168: Add SDHCI support
On Tuesday 20 December 2011 06:55 PM, Haojian Zhuang wrote: On Tue, Dec 20, 2011 at 9:13 PM, Tanmay Upadhyay wrote: v2 - clock register for SDHCI are not common across all MMP SoCs. So, move PXA168 implementation to pxa168.c v3 - sdhci-pxav1 driver code is merged with sdhci-pxav2. So, change the device name accordingly - start sdhci device numbering from 1 as other PXA168 devices does that v4 - Use different names for SD clock registers for PXA168 instead of redefining them in pxa168.c. Suggested by Haojian Zhuang Signed-off-by: Tanmay Upadhyay Reviewed-by: Philip Rakity --- arch/arm/mach-mmp/include/mach/pxa168.h| 20 ++ arch/arm/mach-mmp/include/mach/regs-apmu.h | 40 ++- arch/arm/mach-mmp/pxa168.c | 39 +++ 3 files changed, 80 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 7fb568d..a181608 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -15,6 +15,7 @@ extern void pxa168_clear_keypad_wakeup(void); #include #include #include +#include extern struct pxa_device_desc pxa168_device_uart1; extern struct pxa_device_desc pxa168_device_uart2; @@ -34,6 +35,10 @@ extern struct pxa_device_desc pxa168_device_nand; extern struct pxa_device_desc pxa168_device_fb; extern struct pxa_device_desc pxa168_device_keypad; extern struct pxa_device_desc pxa168_device_eth; +extern struct pxa_device_desc pxa168_device_sdh1; +extern struct pxa_device_desc pxa168_device_sdh2; +extern struct pxa_device_desc pxa168_device_sdh3; +extern struct pxa_device_desc pxa168_device_sdh4; struct pxa168_usb_pdata { /* If NULL, default phy init routine for PXA168 would be called */ @@ -132,4 +137,19 @@ static inline int pxa168_add_eth(struct pxa168_eth_platform_data *data) { return pxa_register_device(&pxa168_device_eth, data, sizeof(*data)); } + +static inline int pxa168_add_sdh(int id, struct sdhci_pxa_platdata *data) +{ + struct pxa_device_desc *d = NULL; + + switch (id) { + case 1: d =&pxa168_device_sdh1; break; + case 2: d =&pxa168_device_sdh2; break; + case 3: d =&pxa168_device_sdh3; break; + case 4: d =&pxa168_device_sdh4; break; + default: + return -EINVAL; + } + return pxa_register_device(d, data, sizeof(*data)); +} #endif /* __ASM_MACH_PXA168_H */ diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h index 8447ac6..a84de77 100644 --- a/arch/arm/mach-mmp/include/mach/regs-apmu.h +++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h @@ -17,27 +17,29 @@ #define APMU_REG(x)(APMU_VIRT_BASE + (x)) /* Clock Reset Control */ -#define APMU_IRE APMU_REG(0x048) -#define APMU_LCD APMU_REG(0x04c) -#define APMU_CCIC APMU_REG(0x050) -#define APMU_SDH0 APMU_REG(0x054) -#define APMU_SDH1 APMU_REG(0x058) -#define APMU_USB APMU_REG(0x05c) -#define APMU_NAND APMU_REG(0x060) -#define APMU_DMA APMU_REG(0x064) -#define APMU_GEU APMU_REG(0x068) -#define APMU_BUS APMU_REG(0x06c) -#define APMU_SDH2 APMU_REG(0x0e8) -#define APMU_SDH3 APMU_REG(0x0ec) -#define APMU_ETH APMU_REG(0x0fc) - -#define APMU_FNCLK_EN (1<< 4) -#define APMU_AXICLK_EN (1<< 3) -#define APMU_FNRST_DIS (1<< 1) -#define APMU_AXIRST_DIS(1<< 0) +#define APMU_IRE APMU_REG(0x048) +#define APMU_LCD APMU_REG(0x04c) +#define APMU_CCIC APMU_REG(0x050) +#define APMU_SDH0 APMU_REG(0x054) +#define APMU_SDH1 APMU_REG(0x058) +#define APMU_USB APMU_REG(0x05c) +#define APMU_NAND APMU_REG(0x060) +#define APMU_DMA APMU_REG(0x064) +#define APMU_GEU APMU_REG(0x068) +#define APMU_BUS APMU_REG(0x06c) +#define APMU_PXA168_SDH2 APMU_REG(0x0e0) +#define APMU_PXA168_SDH3 APMU_REG(0x0e4) +#define APMU_SDH2 APMU_REG(0x0e8) +#define APMU_SDH3 APMU_REG(0x0ec) +#define APMU_ETH APMU_REG(0x0fc) + +#define APMU_FNCLK_EN (1<< 4) +#define APMU_AXICLK_EN (1<< 3) +#define APMU_FNRST_DIS (1<< 1) +#define APMU_AXIRST_DIS(1<< 0) /* Wake Clear Register */ -#define APMU_WAKE_CLR APMU_REG(0x07c) +#define APMU_WAKE_CLR APMU_REG(0x07c) #define APMU_PXA168_KP_WAKE_CLR(1<< 7) #define APMU_PXA168_CFI_WAKE_CLR (1<< 6) diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 76ca15c..023659b 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -65,6 +65,32 @@ void __init pxa168_init_irq(void) pxa168_init_gpio(); } +static void sd
[PATCH v4 2/4] ARM: pxa168: Add SDHCI support
v2 - clock register for SDHCI are not common across all MMP SoCs. So, move PXA168 implementation to pxa168.c v3 - sdhci-pxav1 driver code is merged with sdhci-pxav2. So, change the device name accordingly - start sdhci device numbering from 1 as other PXA168 devices does that v4 - Use different names for SD clock registers for PXA168 instead of redefining them in pxa168.c. Suggested by Haojian Zhuang Signed-off-by: Tanmay Upadhyay Reviewed-by: Philip Rakity --- arch/arm/mach-mmp/include/mach/pxa168.h| 20 ++ arch/arm/mach-mmp/include/mach/regs-apmu.h | 40 ++- arch/arm/mach-mmp/pxa168.c | 39 +++ 3 files changed, 80 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 7fb568d..a181608 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -15,6 +15,7 @@ extern void pxa168_clear_keypad_wakeup(void); #include #include #include +#include extern struct pxa_device_desc pxa168_device_uart1; extern struct pxa_device_desc pxa168_device_uart2; @@ -34,6 +35,10 @@ extern struct pxa_device_desc pxa168_device_nand; extern struct pxa_device_desc pxa168_device_fb; extern struct pxa_device_desc pxa168_device_keypad; extern struct pxa_device_desc pxa168_device_eth; +extern struct pxa_device_desc pxa168_device_sdh1; +extern struct pxa_device_desc pxa168_device_sdh2; +extern struct pxa_device_desc pxa168_device_sdh3; +extern struct pxa_device_desc pxa168_device_sdh4; struct pxa168_usb_pdata { /* If NULL, default phy init routine for PXA168 would be called */ @@ -132,4 +137,19 @@ static inline int pxa168_add_eth(struct pxa168_eth_platform_data *data) { return pxa_register_device(&pxa168_device_eth, data, sizeof(*data)); } + +static inline int pxa168_add_sdh(int id, struct sdhci_pxa_platdata *data) +{ + struct pxa_device_desc *d = NULL; + + switch (id) { + case 1: d = &pxa168_device_sdh1; break; + case 2: d = &pxa168_device_sdh2; break; + case 3: d = &pxa168_device_sdh3; break; + case 4: d = &pxa168_device_sdh4; break; + default: + return -EINVAL; + } + return pxa_register_device(d, data, sizeof(*data)); +} #endif /* __ASM_MACH_PXA168_H */ diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h index 8447ac6..a84de77 100644 --- a/arch/arm/mach-mmp/include/mach/regs-apmu.h +++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h @@ -17,27 +17,29 @@ #define APMU_REG(x)(APMU_VIRT_BASE + (x)) /* Clock Reset Control */ -#define APMU_IRE APMU_REG(0x048) -#define APMU_LCD APMU_REG(0x04c) -#define APMU_CCIC APMU_REG(0x050) -#define APMU_SDH0 APMU_REG(0x054) -#define APMU_SDH1 APMU_REG(0x058) -#define APMU_USB APMU_REG(0x05c) -#define APMU_NAND APMU_REG(0x060) -#define APMU_DMA APMU_REG(0x064) -#define APMU_GEU APMU_REG(0x068) -#define APMU_BUS APMU_REG(0x06c) -#define APMU_SDH2 APMU_REG(0x0e8) -#define APMU_SDH3 APMU_REG(0x0ec) -#define APMU_ETH APMU_REG(0x0fc) - -#define APMU_FNCLK_EN (1 << 4) -#define APMU_AXICLK_EN (1 << 3) -#define APMU_FNRST_DIS (1 << 1) -#define APMU_AXIRST_DIS(1 << 0) +#define APMU_IRE APMU_REG(0x048) +#define APMU_LCD APMU_REG(0x04c) +#define APMU_CCIC APMU_REG(0x050) +#define APMU_SDH0 APMU_REG(0x054) +#define APMU_SDH1 APMU_REG(0x058) +#define APMU_USB APMU_REG(0x05c) +#define APMU_NAND APMU_REG(0x060) +#define APMU_DMA APMU_REG(0x064) +#define APMU_GEU APMU_REG(0x068) +#define APMU_BUS APMU_REG(0x06c) +#define APMU_PXA168_SDH2 APMU_REG(0x0e0) +#define APMU_PXA168_SDH3 APMU_REG(0x0e4) +#define APMU_SDH2 APMU_REG(0x0e8) +#define APMU_SDH3 APMU_REG(0x0ec) +#define APMU_ETH APMU_REG(0x0fc) + +#define APMU_FNCLK_EN (1 << 4) +#define APMU_AXICLK_EN (1 << 3) +#define APMU_FNRST_DIS (1 << 1) +#define APMU_AXIRST_DIS(1 << 0) /* Wake Clear Register */ -#define APMU_WAKE_CLR APMU_REG(0x07c) +#define APMU_WAKE_CLR APMU_REG(0x07c) #define APMU_PXA168_KP_WAKE_CLR(1 << 7) #define APMU_PXA168_CFI_WAKE_CLR (1 << 6) diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 76ca15c..023659b 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -65,6 +65,32 @@ void __init pxa168_init_irq(void) pxa168_init_gpio(); } +static void sdh_clk_enable(struct clk *clk) +{ + void __iomem *reg_offset = clk->clk_rst; + + /* Can't see any clean way to do t
Re: [PATCH v3 2/4] ARM: pxa168: Add SDHCI support
On Monday 19 December 2011 10:32 AM, Haojian Zhuang wrote: On Mon, Dec 19, 2011 at 12:55 PM, Tanmay Upadhyay wrote: On Monday 19 December 2011 10:15 AM, Haojian Zhuang wrote: On Fri, Dec 16, 2011 at 7:15 AM, Chris Ballwrote: Hi Eric and Jason, On Thu, Dec 01 2011, Chris Ball wrote: Hi Eric, Jason, Please could you ACK this patch if you agree with it, and I'll take it and the rest of the series via the MMC tree? Thanks. Ping? Thanks, - Chris. NACK. +/* Offset defined in arch/arm/mach-mmp/include/mach/regs-apmu.h are for MMP2 + * PXA168 has different offset */ +#undef APMU_SDH2 +#undef APMU_SDH3 + +#define APMU_SDH2 APMU_REG(0xe0) +#define APMU_SDH3 APMU_REG(0xe4) + Please don't use #undef at here. If the register setting is different, I prefer to use two different clk operations. Sorry I couldn't get you. Could you please elaborate? Here regs-apmu.h defines clock register offsets. They are correct for MMP2, but not for PXA168. So I thought to correct them in a PXA168 specific file. Could you please point me a better way? Thanks, Tanmay APMU_PXA168_SDH2 APMU_MMP2_SDH2 I think this is better. Thanks for the suggestion. This looks a better option. However, I would like add here that not only the register offset, but also the register bits are different for MMP2 & PXA168. So, the code that would control SD/MMC clock will be architecture specific & hence in different architecture specific files. Hope this solution looks good to all of you in that case as well. Thanks, Tanmay -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 2/4] ARM: pxa168: Add SDHCI support
On Monday 19 December 2011 10:15 AM, Haojian Zhuang wrote: On Fri, Dec 16, 2011 at 7:15 AM, Chris Ball wrote: Hi Eric and Jason, On Thu, Dec 01 2011, Chris Ball wrote: Hi Eric, Jason, Please could you ACK this patch if you agree with it, and I'll take it and the rest of the series via the MMC tree? Thanks. Ping? Thanks, - Chris. NACK. +/* Offset defined in arch/arm/mach-mmp/include/mach/regs-apmu.h are for MMP2 + * PXA168 has different offset */ +#undef APMU_SDH2 +#undef APMU_SDH3 + +#define APMU_SDH2 APMU_REG(0xe0) +#define APMU_SDH3 APMU_REG(0xe4) + Please don't use #undef at here. If the register setting is different, I prefer to use two different clk operations. Sorry I couldn't get you. Could you please elaborate? Here regs-apmu.h defines clock register offsets. They are correct for MMP2, but not for PXA168. So I thought to correct them in a PXA168 specific file. Could you please point me a better way? Thanks, Tanmay -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 4/4] ARM: pxa168/gplugd: Add support for SD port 1
v2 - after sdhci-pxav1 driver is merged with sdhci-pxav2, pass pxav1_controller = 1 - as sdhci device numbering now starts from 1, call pxa168_add_sdh accordingly Signed-off-by: Tanmay Upadhyay Reviewed-by: Philip Rakity --- arch/arm/mach-mmp/gplugd.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c index 6915656..d7947e7 100644 --- a/arch/arm/mach-mmp/gplugd.c +++ b/arch/arm/mach-mmp/gplugd.c @@ -154,6 +154,11 @@ struct pxa168_eth_platform_data gplugd_eth_platform_data = { .init= gplugd_eth_init, }; +struct sdhci_pxa_platdata gplugd_sdh_platdata = { + .delay_in_ms = 5, + .pxav1_controller = 1, +}; + static void __init select_disp_freq(void) { /* set GPIO 35 & clear GPIO 85 to set LCD External Clock to 74.25 MHz */ @@ -186,6 +191,7 @@ static void __init gplugd_init(void) pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info)); pxa168_add_eth(&gplugd_eth_platform_data); + pxa168_add_sdh(1, &gplugd_sdh_platdata); } MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform") -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 3/4] mmc: sdhci-pxa: Add SDHCI driver for PXA16x
PXA16x devices uses SDHCI controller v1. As it's not much different than v2 controller, v1 driver is merged with sdhci-pxav2 driver v2 - instead of having separate file sdhci-pxav1, merge code with sdhci-pxav2 driver code as suggested by Chris Ball Signed-off-by: Philip Rakity Signed-off-by: Tanmay Upadhyay --- drivers/mmc/host/Kconfig|7 --- drivers/mmc/host/sdhci-pxav2.c | 30 +- drivers/mmc/host/sdhci.c|3 +++ drivers/mmc/host/sdhci.h|1 + include/linux/platform_data/pxa_sdhci.h |2 ++ 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 21b4149..77541f5 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -195,14 +195,15 @@ config MMC_SDHCI_PXAV3 If unsure, say N. config MMC_SDHCI_PXAV2 - tristate "Marvell PXA9XX SD Host Controller support (PXAV2)" + tristate "Marvell PXA16X/PXA9XX SD Host Controller support (PXAV1/V2)" depends on CLKDEV_LOOKUP select MMC_SDHCI select MMC_SDHCI_PLTFM default y if CPU_PXA910 + default y if CPU_PXA168 help - This selects the Marvell(R) PXAV2 SD Host Controller. - If you have a PXA9XX platform with SD Host Controller + This selects the Marvell(R) PXAV1/V2 SD Host Controller. + If you have a PXA16X or PXA9XX platform with SD Host Controller and a card slot, say Y or M here. If unsure, say N. diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index d4bf6d3..633cc77 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "sdhci.h" #include "sdhci-pltfm.h" @@ -72,7 +73,13 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask) writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP); } - if (pdata && (pdata->flags & PXA_FLAG_ENABLE_CLOCK_GATING)) { + if (pdata && pdata->pxav1_controller) { + /* no clock gating */ + tmp = readw(host->ioaddr + SD_FIFO_PARAM); + tmp |= DIS_PAD_SD_CLK_GATE; + writew(tmp, host->ioaddr + SD_FIFO_PARAM); + } else if (pdata && (pdata->flags + & PXA_FLAG_ENABLE_CLOCK_GATING)) { tmp = readw(host->ioaddr + SD_FIFO_PARAM); tmp &= ~CLK_GATE_SETTING_BITS; writew(tmp, host->ioaddr + SD_FIFO_PARAM); @@ -115,6 +122,20 @@ static u32 pxav2_get_max_clock(struct sdhci_host *host) return clk_get_rate(pltfm_host->clk); } +/* + * we cannot talk to controller for 8 bus cycles according to sdio spec + * at lowest speed this is 100,000 HZ per cycle or 800,000 cycles + * which is quite a LONG TIME on a fast cpu -- so delay if needed + */ +static void platform_specific_completion(struct sdhci_host *host) +{ + struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; + + if (host->clock < 320 && pdata && pdata->delay_in_ms) + mdelay(pdata->delay_in_ms); +} + static struct sdhci_ops pxav2_sdhci_ops = { .get_max_clock = pxav2_get_max_clock, .platform_reset_exit = pxav2_set_private_registers, @@ -167,6 +188,13 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT) host->mmc->caps |= MMC_CAP_8_BIT_DATA; + if (pdata->pxav1_controller) { + host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ + | SDHCI_QUIRK_32BIT_DMA_SIZE; + pxav2_sdhci_ops.platform_specific_completion + = platform_specific_completion; + } + if (pdata->quirks) host->quirks |= pdata->quirks; if (pdata->host_caps) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6d8eea3..c6b52b8 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -983,6 +983,9 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) mdelay(1); } + if (host->ops->platform_specific_completion) + host->ops->platform_specific_completion(host); + mod_timer(&host->timer, jiffies + 10 * HZ); host->cmd = cmd; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.
[PATCH v3 2/4] ARM: pxa168: Add SDHCI support
v2 - clock register for SDHCI are not common across all MMP SoCs. So, move PXA168 implementation to pxa168.c v3 - sdhci-pxav1 driver code is merged with sdhci-pxav2. So, change the device name accordingly - start sdhci device numbering from 1 as other PXA168 devices does that Signed-off-by: Tanmay Upadhyay Reviewed-by: Philip Rakity --- arch/arm/mach-mmp/include/mach/pxa168.h | 20 + arch/arm/mach-mmp/pxa168.c | 46 +++ 2 files changed, 66 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 7fb568d..a181608 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -15,6 +15,7 @@ extern void pxa168_clear_keypad_wakeup(void); #include #include #include +#include extern struct pxa_device_desc pxa168_device_uart1; extern struct pxa_device_desc pxa168_device_uart2; @@ -34,6 +35,10 @@ extern struct pxa_device_desc pxa168_device_nand; extern struct pxa_device_desc pxa168_device_fb; extern struct pxa_device_desc pxa168_device_keypad; extern struct pxa_device_desc pxa168_device_eth; +extern struct pxa_device_desc pxa168_device_sdh1; +extern struct pxa_device_desc pxa168_device_sdh2; +extern struct pxa_device_desc pxa168_device_sdh3; +extern struct pxa_device_desc pxa168_device_sdh4; struct pxa168_usb_pdata { /* If NULL, default phy init routine for PXA168 would be called */ @@ -132,4 +137,19 @@ static inline int pxa168_add_eth(struct pxa168_eth_platform_data *data) { return pxa_register_device(&pxa168_device_eth, data, sizeof(*data)); } + +static inline int pxa168_add_sdh(int id, struct sdhci_pxa_platdata *data) +{ + struct pxa_device_desc *d = NULL; + + switch (id) { + case 1: d = &pxa168_device_sdh1; break; + case 2: d = &pxa168_device_sdh2; break; + case 3: d = &pxa168_device_sdh3; break; + case 4: d = &pxa168_device_sdh4; break; + default: + return -EINVAL; + } + return pxa_register_device(d, data, sizeof(*data)); +} #endif /* __ASM_MACH_PXA168_H */ diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 76ca15c..102f65f 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -45,6 +45,14 @@ static struct mfp_addr_map pxa168_mfp_addr_map[] __initdata = #define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c) +/* Offset defined in arch/arm/mach-mmp/include/mach/regs-apmu.h are for MMP2 + * PXA168 has different offset */ +#undef APMU_SDH2 +#undef APMU_SDH3 + +#define APMU_SDH2 APMU_REG(0xe0) +#define APMU_SDH3 APMU_REG(0xe4) + static void __init pxa168_init_gpio(void) { int i; @@ -65,6 +73,31 @@ void __init pxa168_init_irq(void) pxa168_init_gpio(); } +static void sdh_clk_enable(struct clk *clk) +{ + void __iomem *clk_reg_offset = clk->clk_rst; + + /* Can't see any clean way to do this: Bits 3 & 0 in registers +* for host 0 & 2 should be set for host 1 & 3 also */ + if (clk_reg_offset == APMU_SDH0 || clk_reg_offset == APMU_SDH1) + __raw_writel(__raw_readl(APMU_SDH0) | 0x9, APMU_SDH0); + if (clk_reg_offset == APMU_SDH2 || clk_reg_offset == APMU_SDH3) + __raw_writel(__raw_readl(APMU_SDH2) | 0x9, APMU_SDH2); + + __raw_writel(__raw_readl(clk->clk_rst) | clk->enable_val, clk->clk_rst); +} + +static void sdh_clk_disable(struct clk *clk) +{ + __raw_writel(__raw_readl(clk->clk_rst) & ~(clk->enable_val), + clk->clk_rst); +} + +struct clkops sdh_clk_ops = { + .enable = sdh_clk_enable, + .disable= sdh_clk_disable, +}; + /* APB peripheral clocks */ static APBC_CLK(uart1, PXA168_UART1, 1, 14745600); static APBC_CLK(uart2, PXA168_UART2, 1, 14745600); @@ -87,6 +120,11 @@ static APMU_CLK(lcd, LCD, 0x7f, 31200); static APMU_CLK(eth, ETH, 0x09, 0); static APMU_CLK(usb, USB, 0x12, 0); +static APMU_CLK_OPS(sdh1, SDH0, 0x12, 4800, &sdh_clk_ops); +static APMU_CLK_OPS(sdh2, SDH1, 0x12, 4800, &sdh_clk_ops); +static APMU_CLK_OPS(sdh3, SDH2, 0x12, 4800, &sdh_clk_ops); +static APMU_CLK_OPS(sdh4, SDH3, 0x12, 4800, &sdh_clk_ops); + /* device and clock bindings */ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL), @@ -108,6 +146,10 @@ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL), INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"), INIT_CLKREG(&clk_usb, "pxa168-ehci", "PXA168-USBCLK"), + INIT_CLKREG(&clk_sdh1, NULL, "PXA-SDHCLK"), + INIT_CLKREG(&clk_sdh2, NULL, "PXA-SDHCLK"), + INIT_CLKREG(&cl
[PATCH 1/4] mmc: sdhci-pxa: Trivial fix in Kconfig
Select MMC_SDHCI_PXAV3 by default if CPU is MMP2 Select MMC_SDHCI_PXAV2 by default if CPU is PXA910 Signed-off-by: Tanmay Upadhyay Reviewed-by: Philip Rakity --- drivers/mmc/host/Kconfig |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index cf444b0..21b4149 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -186,7 +186,7 @@ config MMC_SDHCI_PXAV3 depends on CLKDEV_LOOKUP select MMC_SDHCI select MMC_SDHCI_PLTFM - default CPU_MMP2 + default y if CPU_MMP2 help This selects the Marvell(R) PXAV3 SD Host Controller. If you have a MMP2 platform with SD Host Controller @@ -199,7 +199,7 @@ config MMC_SDHCI_PXAV2 depends on CLKDEV_LOOKUP select MMC_SDHCI select MMC_SDHCI_PLTFM - default CPU_PXA910 + default y if CPU_PXA910 help This selects the Marvell(R) PXAV2 SD Host Controller. If you have a PXA9XX platform with SD Host Controller -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/3] ARM: pxa168: Add SDHCI support
v2 - clock register for SDHCI are not common across all MMP SoCs. So, move PXA168 implementation to pxa168.c Signed-off-by: Tanmay Upadhyay --- arch/arm/mach-mmp/clock.c |1 + arch/arm/mach-mmp/clock.h |1 + arch/arm/mach-mmp/include/mach/pxa168.h | 20 + arch/arm/mach-mmp/pxa168.c | 46 +++ 4 files changed, 68 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-mmp/clock.c b/arch/arm/mach-mmp/clock.c index 7c6f95f..eefefea 100644 --- a/arch/arm/mach-mmp/clock.c +++ b/arch/arm/mach-mmp/clock.c @@ -14,6 +14,7 @@ #include #include +#include #include "clock.h" static void apbc_clk_enable(struct clk *clk) diff --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h index 3143e99..1243e4d 100644 --- a/arch/arm/mach-mmp/clock.h +++ b/arch/arm/mach-mmp/clock.h @@ -27,6 +27,7 @@ struct clk { extern struct clkops apbc_clk_ops; extern struct clkops apmu_clk_ops; +extern struct clkops sdh_clk_ops; #define APBC_CLK(_name, _reg, _fnclksel, _rate)\ struct clk clk_##_name = { \ diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 7f00584..390a550 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -15,6 +15,7 @@ extern void pxa168_clear_keypad_wakeup(void); #include #include #include +#include extern struct pxa_device_desc pxa168_device_uart1; extern struct pxa_device_desc pxa168_device_uart2; @@ -34,6 +35,10 @@ extern struct pxa_device_desc pxa168_device_nand; extern struct pxa_device_desc pxa168_device_fb; extern struct pxa_device_desc pxa168_device_keypad; extern struct pxa_device_desc pxa168_device_eth; +extern struct pxa_device_desc pxa168_device_sdh0; +extern struct pxa_device_desc pxa168_device_sdh1; +extern struct pxa_device_desc pxa168_device_sdh2; +extern struct pxa_device_desc pxa168_device_sdh3; static inline int pxa168_add_uart(int id) { @@ -125,4 +130,19 @@ static inline int pxa168_add_eth(struct pxa168_eth_platform_data *data) { return pxa_register_device(&pxa168_device_eth, data, sizeof(*data)); } + +static inline int pxa168_add_sdh(int id, struct sdhci_pxa_platdata *data) +{ + struct pxa_device_desc *d = NULL; + + switch (id) { + case 0: d = &pxa168_device_sdh0; break; + case 1: d = &pxa168_device_sdh1; break; + case 2: d = &pxa168_device_sdh2; break; + case 3: d = &pxa168_device_sdh3; break; + default: + return -EINVAL; + } + return pxa_register_device(d, data, sizeof(*data)); +} #endif /* __ASM_MACH_PXA168_H */ diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 0156f53..868605d 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -43,6 +43,14 @@ static struct mfp_addr_map pxa168_mfp_addr_map[] __initdata = #define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c) +/* Offset defined in arch/arm/mach-mmp/include/mach/regs-apmu.h are for MMP2 + * PXA168 has different offset */ +#undef APMU_SDH2 +#undef APMU_SDH3 + +#define APMU_SDH2 APMU_REG(0xe0) +#define APMU_SDH3 APMU_REG(0xe4) + static void __init pxa168_init_gpio(void) { int i; @@ -63,6 +71,31 @@ void __init pxa168_init_irq(void) pxa168_init_gpio(); } +static void sdh_clk_enable(struct clk *clk) +{ + unsigned long clk_reg_offset = (unsigned long) clk->clk_rst; + + /* Can't see any clean way to do this: Bits 3 & 0 in registers +* for host 0 & 2 should be set for host 1 & 3 also */ + if (clk_reg_offset == APMU_SDH0 || clk_reg_offset == APMU_SDH1) + __raw_writel(__raw_readl(APMU_SDH0) | 0x9, APMU_SDH0); + if (clk_reg_offset == APMU_SDH2 || clk_reg_offset == APMU_SDH3) + __raw_writel(__raw_readl(APMU_SDH2) | 0x9, APMU_SDH2); + + __raw_writel(__raw_readl(clk->clk_rst) | clk->enable_val, clk->clk_rst); +} + +static void sdh_clk_disable(struct clk *clk) +{ + __raw_writel(__raw_readl(clk->clk_rst) & ~(clk->enable_val), + clk->clk_rst); +} + +struct clkops sdh_clk_ops = { + .enable = sdh_clk_enable, + .disable= sdh_clk_disable, +}; + /* APB peripheral clocks */ static APBC_CLK(uart1, PXA168_UART1, 1, 14745600); static APBC_CLK(uart2, PXA168_UART2, 1, 14745600); @@ -84,6 +117,11 @@ static APMU_CLK(nand, NAND, 0x19b, 15600); static APMU_CLK(lcd, LCD, 0x7f, 31200); static APMU_CLK(eth, ETH, 0x09, 0); +static APMU_CLK_OPS(sdh0, SDH0, 0x12, 4800, &sdh_clk_ops); +static APMU_CLK_OPS(sdh1, SDH1, 0x12, 4800, &sdh_clk_ops); +static APMU_CLK_OPS(sdh2, SDH2, 0x12, 4800, &sdh_clk_ops); +static APMU_CLK_OPS(sdh3, SDH3, 0x12, 4800, &sdh_clk_ops); + /* device and clock b
[PATCH 2/3] mmc: sdhci-pxa: Add SDHCI driver for PXA16x
Signed-off-by: Philip Rakity Signed-off-by: Tanmay Upadhyay --- drivers/mmc/host/Kconfig| 13 ++ drivers/mmc/host/Makefile |1 + drivers/mmc/host/sdhci-pxav1.c | 256 +++ drivers/mmc/host/sdhci.c|3 + drivers/mmc/host/sdhci.h|1 + include/linux/platform_data/pxa_sdhci.h |1 + 6 files changed, 275 insertions(+), 0 deletions(-) create mode 100644 drivers/mmc/host/sdhci-pxav1.c diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 8c87096..9c9b73a 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -207,6 +207,19 @@ config MMC_SDHCI_PXAV2 If unsure, say N. +config MMC_SDHCI_PXAV1 + tristate "Marvell PXA16X SD Host Controller support (PXAV1)" + depends on CLKDEV_LOOKUP + select MMC_SDHCI + select MMC_SDHCI_PLTFM + default CPU_PXA168 + help + This selects the Marvell(R) PXAV1 SD Host Controller. + If you have a PXA16X 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 b4b83f3..5094af8 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_SDHCI_PCI)+= sdhci-pci.o obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o +obj-$(CONFIG_MMC_SDHCI_PXAV1) += sdhci-pxav1.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-pxav1.c b/drivers/mmc/host/sdhci-pxav1.c new file mode 100644 index 000..a0f6285 --- /dev/null +++ b/drivers/mmc/host/sdhci-pxav1.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2011 Marvell International Ltd. + * Zhangfei Gao + * Kevin Wang + * Jun Nie + * Qiming Wu + * Philip Rakity + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sdhci.h" +#include "sdhci-pltfm.h" + +#define SD_FIFO_PARAM 0xe0 +#define DIS_PAD_SD_CLK_GATE0x0400 /* Turn on/off Dynamic SD Clock Gating */ +#define CLK_GATE_SETTING_BITS DIS_PAD_SD_CLK_GATE + +#define SD_CLOCK_BURST_SIZE_SETUP 0xe6 +#define SDCLK_SEL_SHIFT8 +#define SDCLK_SEL_MASK 0x3 +#define SDCLK_DELAY_SHIFT 10 +#define SDCLK_DELAY_MASK 0x3c + +#define SD_CE_ATA_20xea +#define MMC_CARD 0x1000 +#define MMC_WIDTH 0x0100 + + +static void pxav1_set_private_registers(struct sdhci_host *host, u8 mask) +{ + struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); + struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; + + if (mask == SDHCI_RESET_ALL) { + u16 tmp = 0; + + /* +* tune timing of read data/command when crc error happen +* no performance impact +*/ + if (pdata && pdata->clk_delay_sel) { + tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP); + + tmp &= ~(SDCLK_DELAY_MASK << SDCLK_DELAY_SHIFT); + tmp |= (pdata->clk_delay_cycles & SDCLK_DELAY_MASK) + << SDCLK_DELAY_SHIFT; + tmp &= ~(SDCLK_SEL_MASK << SDCLK_SEL_SHIFT); + tmp |= (pdata->clk_delay_sel & SDCLK_SEL_MASK) + << SDCLK_SEL_SHIFT; + + writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP); + } + + /* no clock gating */ + tmp = readw(host->ioaddr + SD_FIFO_PARAM); + tmp |= DIS_PAD_SD_CLK_GATE; + writew(tmp, host->ioaddr + SD_FIFO_PARAM); + } +} + +static int pxav1_mmc_set_width(struct sdhci_host *host, int width) +{ + u8 ctrl; + u16 tmp; + + ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); + tmp = readw(host->ioaddr + SD_CE_ATA_2);
[PATCH 3/3] ARM: pxa168/gplugd: Add support for SD port 1
Signed-off-by: Tanmay Upadhyay --- arch/arm/mach-mmp/gplugd.c |7 +++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c index 98e25d9..f453561 100644 --- a/arch/arm/mach-mmp/gplugd.c +++ b/arch/arm/mach-mmp/gplugd.c @@ -17,6 +17,8 @@ #include #include +#include + #include "common.h" static unsigned long gplugd_pin_config[] __initdata = { @@ -154,6 +156,10 @@ struct pxa168_eth_platform_data gplugd_eth_platform_data = { .init= gplugd_eth_init, }; +struct sdhci_pxa_platdata gplugd_sdh_platdata = { + .delay_in_ms = 4, +}; + static void __init select_disp_freq(void) { /* set GPIO 35 & clear GPIO 85 to set LCD External Clock to 74.25 MHz */ @@ -186,6 +192,7 @@ static void __init gplugd_init(void) pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info)); pxa168_add_eth(&gplugd_eth_platform_data); + pxa168_add_sdh(0, &gplugd_sdh_platdata); } MACHINE_START(SHEEVAD, "PXA168-based GuruPlug Display (gplugD) Platform") -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] ARM: pxa168: Add SDHCI support
Signed-off-by: Tanmay Upadhyay --- arch/arm/mach-mmp/clock.c | 26 ++ arch/arm/mach-mmp/clock.h |1 + arch/arm/mach-mmp/include/mach/pxa168.h | 20 arch/arm/mach-mmp/pxa168.c | 13 + 4 files changed, 60 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-mmp/clock.c b/arch/arm/mach-mmp/clock.c index 7c6f95f..6e615cc 100644 --- a/arch/arm/mach-mmp/clock.c +++ b/arch/arm/mach-mmp/clock.c @@ -14,6 +14,7 @@ #include #include +#include #include "clock.h" static void apbc_clk_enable(struct clk *clk) @@ -49,6 +50,31 @@ struct clkops apmu_clk_ops = { .disable= apmu_clk_disable, }; +static void sdh_clk_enable(struct clk *clk) +{ + unsigned long clk_reg_offset = (unsigned long) clk->clk_rst; + + /* Can't see any clean way to do this: Bits 3 & 0 in registers +* for host 0 & 2 should be set for host 1 & 3 also */ + if (clk_reg_offset == APMU_SDH0 || clk_reg_offset == APMU_SDH1) + __raw_writel(__raw_readl(APMU_SDH0) | 0x9, APMU_SDH0); + if (clk_reg_offset == APMU_SDH2 || clk_reg_offset == APMU_SDH3) + __raw_writel(__raw_readl(APMU_SDH2) | 0x9, APMU_SDH2); + + __raw_writel(__raw_readl(clk->clk_rst) | clk->enable_val, clk->clk_rst); +} + +static void sdh_clk_disable(struct clk *clk) +{ + __raw_writel(__raw_readl(clk->clk_rst) & ~(clk->enable_val), + clk->clk_rst); +} + +struct clkops sdh_clk_ops = { + .enable = sdh_clk_enable, + .disable= sdh_clk_disable, +}; + static DEFINE_SPINLOCK(clocks_lock); int clk_enable(struct clk *clk) diff --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h index 3143e99..1243e4d 100644 --- a/arch/arm/mach-mmp/clock.h +++ b/arch/arm/mach-mmp/clock.h @@ -27,6 +27,7 @@ struct clk { extern struct clkops apbc_clk_ops; extern struct clkops apmu_clk_ops; +extern struct clkops sdh_clk_ops; #define APBC_CLK(_name, _reg, _fnclksel, _rate)\ struct clk clk_##_name = { \ diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 7f00584..390a550 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -15,6 +15,7 @@ extern void pxa168_clear_keypad_wakeup(void); #include #include #include +#include extern struct pxa_device_desc pxa168_device_uart1; extern struct pxa_device_desc pxa168_device_uart2; @@ -34,6 +35,10 @@ extern struct pxa_device_desc pxa168_device_nand; extern struct pxa_device_desc pxa168_device_fb; extern struct pxa_device_desc pxa168_device_keypad; extern struct pxa_device_desc pxa168_device_eth; +extern struct pxa_device_desc pxa168_device_sdh0; +extern struct pxa_device_desc pxa168_device_sdh1; +extern struct pxa_device_desc pxa168_device_sdh2; +extern struct pxa_device_desc pxa168_device_sdh3; static inline int pxa168_add_uart(int id) { @@ -125,4 +130,19 @@ static inline int pxa168_add_eth(struct pxa168_eth_platform_data *data) { return pxa_register_device(&pxa168_device_eth, data, sizeof(*data)); } + +static inline int pxa168_add_sdh(int id, struct sdhci_pxa_platdata *data) +{ + struct pxa_device_desc *d = NULL; + + switch (id) { + case 0: d = &pxa168_device_sdh0; break; + case 1: d = &pxa168_device_sdh1; break; + case 2: d = &pxa168_device_sdh2; break; + case 3: d = &pxa168_device_sdh3; break; + default: + return -EINVAL; + } + return pxa_register_device(d, data, sizeof(*data)); +} #endif /* __ASM_MACH_PXA168_H */ diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 0156f53..9da21fd 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -84,6 +84,11 @@ static APMU_CLK(nand, NAND, 0x19b, 15600); static APMU_CLK(lcd, LCD, 0x7f, 31200); static APMU_CLK(eth, ETH, 0x09, 0); +static APMU_CLK_OPS(sdh0, SDH0, 0x12, 4800, &sdh_clk_ops); +static APMU_CLK_OPS(sdh1, SDH1, 0x12, 4800, &sdh_clk_ops); +static APMU_CLK_OPS(sdh2, SDH2, 0x12, 4800, &sdh_clk_ops); +static APMU_CLK_OPS(sdh3, SDH3, 0x12, 4800, &sdh_clk_ops); + /* device and clock bindings */ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL), @@ -104,6 +109,10 @@ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL), INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL), INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"), + INIT_CLKREG(&clk_sdh0, "sdhci-pxav1.0", "PXA-SDHCLK"), + INIT_CLKREG(&clk_sdh1, "sdhci-pxav1.1", "PXA-SDHCLK"),
[PATCH] mmc: sdhci-pxa: Check pdata before using its members
Signed-off-by: Tanmay Upadhyay --- drivers/mmc/host/sdhci-pxav2.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index 38f5899..1114fe2 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -59,7 +59,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask) * tune timing of read data/command when crc error happen * no performance impact */ - if (pdata->clk_delay_sel == 1) { + if (pdata && pdata->clk_delay_sel == 1) { tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP); tmp &= ~(SDCLK_DELAY_MASK << SDCLK_DELAY_SHIFT); @@ -71,7 +71,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask) writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP); } - if (pdata->flags & PXA_FLAG_ENABLE_CLOCK_GATING) { + if (pdata && (pdata->flags & PXA_FLAG_ENABLE_CLOCK_GATING)) { tmp = readw(host->ioaddr + SD_FIFO_PARAM); tmp &= ~CLK_GATE_SETTING_BITS; writew(tmp, host->ioaddr + SD_FIFO_PARAM); -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html