1 /* linux/drivers/mmc/host/sdhci-pxa.c
3 * Copyright (C) 2010 Marvell International Ltd.
4 * Zhangfei Gao <zhangfei.gao@marvell.com>
5 * Kevin Wang <dwang4@marvell.com>
6 * Mingwei Wang <mwwang@marvell.com>
7 * Philip Rakity <prakity@marvell.com>
8 * Mark Brown <markb@marvell.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
16 * SDHCI support for MMP2/PXA910/PXA168
18 * Refer to sdhci-s3c.c.
21 #include <linux/delay.h>
22 #include <linux/platform_device.h>
23 #include <linux/mmc/host.h>
24 #include <linux/clk.h>
26 #include <linux/err.h>
27 #include <plat/sdhci.h>
30 #define DRIVER_NAME "sdhci-pxa"
32 #define SD_FIFO_PARAM 0x104
33 #define DIS_PAD_SD_CLK_GATE 0x400
36 struct sdhci_host
*host
;
37 struct sdhci_pxa_platdata
*pdata
;
44 /*****************************************************************************\
46 * SDHCI core callbacks *
48 \*****************************************************************************/
49 static void set_clock(struct sdhci_host
*host
, unsigned int clock
)
51 struct sdhci_pxa
*pxa
= sdhci_priv(host
);
55 if (pxa
->clk_enable
) {
56 clk_disable(pxa
->clk
);
60 if (0 == pxa
->clk_enable
) {
61 if (pxa
->pdata
->flags
& PXA_FLAG_DISABLE_CLOCK_GATING
) {
62 tmp
= readl(host
->ioaddr
+ SD_FIFO_PARAM
);
63 tmp
|= DIS_PAD_SD_CLK_GATE
;
64 writel(tmp
, host
->ioaddr
+ SD_FIFO_PARAM
);
72 static int set_uhs_signaling(struct sdhci_host
*host
, unsigned int uhs
)
77 * Set V18_EN -- UHS modes do not work without this.
78 * does not change signaling voltage
80 ctrl_2
= sdhci_readw(host
, SDHCI_HOST_CONTROL2
);
82 /* Select Bus Speed Mode for host */
83 ctrl_2
&= ~SDHCI_CTRL_UHS_MASK
;
85 case MMC_TIMING_UHS_SDR12
:
86 ctrl_2
|= SDHCI_CTRL_UHS_SDR12
;
88 case MMC_TIMING_UHS_SDR25
:
89 ctrl_2
|= SDHCI_CTRL_UHS_SDR25
;
91 case MMC_TIMING_UHS_SDR50
:
92 ctrl_2
|= SDHCI_CTRL_UHS_SDR50
| SDHCI_CTRL_VDD_180
;
94 case MMC_TIMING_UHS_SDR104
:
95 ctrl_2
|= SDHCI_CTRL_UHS_SDR104
| SDHCI_CTRL_VDD_180
;
97 case MMC_TIMING_UHS_DDR50
:
98 ctrl_2
|= SDHCI_CTRL_UHS_DDR50
| SDHCI_CTRL_VDD_180
;
102 sdhci_writew(host
, ctrl_2
, SDHCI_HOST_CONTROL2
);
103 pr_debug("%s:%s uhs = %d, ctrl_2 = %04X\n",
104 __func__
, mmc_hostname(host
->mmc
), uhs
, ctrl_2
);
109 static struct sdhci_ops sdhci_pxa_ops
= {
110 .set_uhs_signaling
= set_uhs_signaling
,
111 .set_clock
= set_clock
,
114 /*****************************************************************************\
116 * Device probing/removal *
118 \*****************************************************************************/
120 static int __devinit
sdhci_pxa_probe(struct platform_device
*pdev
)
122 struct sdhci_pxa_platdata
*pdata
= pdev
->dev
.platform_data
;
123 struct device
*dev
= &pdev
->dev
;
124 struct sdhci_host
*host
= NULL
;
125 struct resource
*iomem
= NULL
;
126 struct sdhci_pxa
*pxa
= NULL
;
129 irq
= platform_get_irq(pdev
, 0);
131 dev_err(dev
, "no irq specified\n");
135 iomem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
137 dev_err(dev
, "no memory specified\n");
141 host
= sdhci_alloc_host(&pdev
->dev
, sizeof(struct sdhci_pxa
));
143 dev_err(dev
, "failed to alloc host\n");
144 return PTR_ERR(host
);
147 pxa
= sdhci_priv(host
);
152 pxa
->clk
= clk_get(dev
, "PXA-SDHCLK");
153 if (IS_ERR(pxa
->clk
)) {
154 dev_err(dev
, "failed to get io clock\n");
155 ret
= PTR_ERR(pxa
->clk
);
159 pxa
->res
= request_mem_region(iomem
->start
, resource_size(iomem
),
160 mmc_hostname(host
->mmc
));
162 dev_err(&pdev
->dev
, "cannot request region\n");
167 host
->ioaddr
= ioremap(iomem
->start
, resource_size(iomem
));
169 dev_err(&pdev
->dev
, "failed to remap registers\n");
174 host
->hw_name
= "MMC";
175 host
->ops
= &sdhci_pxa_ops
;
177 host
->quirks
= SDHCI_QUIRK_BROKEN_ADMA
178 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
179 | SDHCI_QUIRK_32BIT_DMA_ADDR
180 | SDHCI_QUIRK_32BIT_DMA_SIZE
181 | SDHCI_QUIRK_32BIT_ADMA_SIZE
182 | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
;
185 host
->quirks
|= pdata
->quirks
;
187 /* enable 1/8V DDR capable */
188 host
->mmc
->caps
|= MMC_CAP_1_8V_DDR
;
190 /* If slot design supports 8 bit data, indicate this to MMC. */
191 if (pdata
->flags
& PXA_FLAG_SD_8_BIT_CAPABLE_SLOT
)
192 host
->mmc
->caps
|= MMC_CAP_8_BIT_DATA
;
194 ret
= sdhci_add_host(host
);
196 dev_err(&pdev
->dev
, "failed to add host\n");
200 if (pxa
->pdata
->max_speed
)
201 host
->mmc
->f_max
= pxa
->pdata
->max_speed
;
203 platform_set_drvdata(pdev
, host
);
210 iounmap(host
->ioaddr
);
212 release_mem_region(pxa
->res
->start
,
213 resource_size(pxa
->res
));
214 sdhci_free_host(host
);
220 static int __devexit
sdhci_pxa_remove(struct platform_device
*pdev
)
222 struct sdhci_host
*host
= platform_get_drvdata(pdev
);
223 struct sdhci_pxa
*pxa
= sdhci_priv(host
);
228 scratch
= readl(host
->ioaddr
+ SDHCI_INT_STATUS
);
229 if (scratch
== (u32
)-1)
232 sdhci_remove_host(host
, dead
);
235 iounmap(host
->ioaddr
);
237 release_mem_region(pxa
->res
->start
,
238 resource_size(pxa
->res
));
239 if (pxa
->clk_enable
) {
240 clk_disable(pxa
->clk
);
245 sdhci_free_host(host
);
246 platform_set_drvdata(pdev
, NULL
);
253 static int sdhci_pxa_suspend(struct platform_device
*dev
, pm_message_t state
)
255 struct sdhci_host
*host
= platform_get_drvdata(dev
);
257 return sdhci_suspend_host(host
, state
);
260 static int sdhci_pxa_resume(struct platform_device
*dev
)
262 struct sdhci_host
*host
= platform_get_drvdata(dev
);
264 return sdhci_resume_host(host
);
267 #define sdhci_pxa_suspend NULL
268 #define sdhci_pxa_resume NULL
271 static struct platform_driver sdhci_pxa_driver
= {
272 .probe
= sdhci_pxa_probe
,
273 .remove
= __devexit_p(sdhci_pxa_remove
),
274 .suspend
= sdhci_pxa_suspend
,
275 .resume
= sdhci_pxa_resume
,
278 .owner
= THIS_MODULE
,
282 /*****************************************************************************\
286 \*****************************************************************************/
288 static int __init
sdhci_pxa_init(void)
290 return platform_driver_register(&sdhci_pxa_driver
);
293 static void __exit
sdhci_pxa_exit(void)
295 platform_driver_unregister(&sdhci_pxa_driver
);
298 module_init(sdhci_pxa_init
);
299 module_exit(sdhci_pxa_exit
);
301 MODULE_DESCRIPTION("SDH controller driver for PXA168/PXA910/MMP2");
302 MODULE_AUTHOR("Zhangfei Gao <zhangfei.gao@marvell.com>");
303 MODULE_LICENSE("GPL v2");