2 * SDHCI support for SiRF primaII and marco SoCs
4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
6 * Licensed under GPLv2 or later.
9 #include <linux/delay.h>
10 #include <linux/device.h>
11 #include <linux/mmc/host.h>
12 #include <linux/module.h>
14 #include <linux/of_gpio.h>
15 #include <linux/mmc/slot-gpio.h>
16 #include "sdhci-pltfm.h"
18 struct sdhci_sirf_priv
{
23 static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host
*host
)
25 struct sdhci_pltfm_host
*pltfm_host
= sdhci_priv(host
);
26 struct sdhci_sirf_priv
*priv
= sdhci_pltfm_priv(pltfm_host
);
27 return clk_get_rate(priv
->clk
);
30 static struct sdhci_ops sdhci_sirf_ops
= {
31 .get_max_clock
= sdhci_sirf_get_max_clk
,
34 static struct sdhci_pltfm_data sdhci_sirf_pdata
= {
35 .ops
= &sdhci_sirf_ops
,
36 .quirks
= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
|
37 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK
|
38 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN
|
39 SDHCI_QUIRK_INVERTED_WRITE_PROTECT
|
40 SDHCI_QUIRK_DELAY_AFTER_POWER
,
43 static int sdhci_sirf_probe(struct platform_device
*pdev
)
45 struct sdhci_host
*host
;
46 struct sdhci_pltfm_host
*pltfm_host
;
47 struct sdhci_sirf_priv
*priv
;
52 clk
= devm_clk_get(&pdev
->dev
, NULL
);
54 dev_err(&pdev
->dev
, "unable to get clock");
58 if (pdev
->dev
.of_node
)
59 gpio_cd
= of_get_named_gpio(pdev
->dev
.of_node
, "cd-gpios", 0);
63 host
= sdhci_pltfm_init(pdev
, &sdhci_sirf_pdata
, sizeof(struct sdhci_sirf_priv
));
67 pltfm_host
= sdhci_priv(host
);
68 priv
= sdhci_pltfm_priv(pltfm_host
);
70 priv
->gpio_cd
= gpio_cd
;
72 sdhci_get_of_property(pdev
);
74 ret
= clk_prepare_enable(priv
->clk
);
78 ret
= sdhci_add_host(host
);
83 * We must request the IRQ after sdhci_add_host(), as the tasklet only
84 * gets setup in sdhci_add_host() and we oops.
86 if (gpio_is_valid(priv
->gpio_cd
)) {
87 ret
= mmc_gpio_request_cd(host
->mmc
, priv
->gpio_cd
);
89 dev_err(&pdev
->dev
, "card detect irq request failed: %d\n",
98 sdhci_remove_host(host
, 0);
100 clk_disable_unprepare(priv
->clk
);
102 sdhci_pltfm_free(pdev
);
106 static int sdhci_sirf_remove(struct platform_device
*pdev
)
108 struct sdhci_host
*host
= platform_get_drvdata(pdev
);
109 struct sdhci_pltfm_host
*pltfm_host
= sdhci_priv(host
);
110 struct sdhci_sirf_priv
*priv
= sdhci_pltfm_priv(pltfm_host
);
112 sdhci_pltfm_unregister(pdev
);
114 if (gpio_is_valid(priv
->gpio_cd
))
115 mmc_gpio_free_cd(host
->mmc
);
117 clk_disable_unprepare(priv
->clk
);
121 #ifdef CONFIG_PM_SLEEP
122 static int sdhci_sirf_suspend(struct device
*dev
)
124 struct sdhci_host
*host
= dev_get_drvdata(dev
);
125 struct sdhci_pltfm_host
*pltfm_host
= sdhci_priv(host
);
126 struct sdhci_sirf_priv
*priv
= sdhci_pltfm_priv(pltfm_host
);
129 ret
= sdhci_suspend_host(host
);
133 clk_disable(priv
->clk
);
138 static int sdhci_sirf_resume(struct device
*dev
)
140 struct sdhci_host
*host
= dev_get_drvdata(dev
);
141 struct sdhci_pltfm_host
*pltfm_host
= sdhci_priv(host
);
142 struct sdhci_sirf_priv
*priv
= sdhci_pltfm_priv(pltfm_host
);
145 ret
= clk_enable(priv
->clk
);
147 dev_dbg(dev
, "Resume: Error enabling clock\n");
151 return sdhci_resume_host(host
);
154 static SIMPLE_DEV_PM_OPS(sdhci_sirf_pm_ops
, sdhci_sirf_suspend
, sdhci_sirf_resume
);
157 static const struct of_device_id sdhci_sirf_of_match
[] = {
158 { .compatible
= "sirf,prima2-sdhc" },
161 MODULE_DEVICE_TABLE(of
, sdhci_sirf_of_match
);
163 static struct platform_driver sdhci_sirf_driver
= {
165 .name
= "sdhci-sirf",
166 .owner
= THIS_MODULE
,
167 .of_match_table
= sdhci_sirf_of_match
,
168 #ifdef CONFIG_PM_SLEEP
169 .pm
= &sdhci_sirf_pm_ops
,
172 .probe
= sdhci_sirf_probe
,
173 .remove
= sdhci_sirf_remove
,
176 module_platform_driver(sdhci_sirf_driver
);
178 MODULE_DESCRIPTION("SDHCI driver for SiRFprimaII/SiRFmarco");
179 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
180 MODULE_LICENSE("GPL v2");