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 #define SDHCI_SIRF_8BITBUS BIT(3)
20 struct sdhci_sirf_priv
{
25 static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host
*host
)
27 struct sdhci_pltfm_host
*pltfm_host
= sdhci_priv(host
);
28 struct sdhci_sirf_priv
*priv
= sdhci_pltfm_priv(pltfm_host
);
29 return clk_get_rate(priv
->clk
);
32 static void sdhci_sirf_set_bus_width(struct sdhci_host
*host
, int width
)
36 ctrl
= sdhci_readb(host
, SDHCI_HOST_CONTROL
);
37 ctrl
&= ~(SDHCI_CTRL_4BITBUS
| SDHCI_SIRF_8BITBUS
);
40 * CSR atlas7 and prima2 SD host version is not 3.0
41 * 8bit-width enable bit of CSR SD hosts is 3,
42 * while stardard hosts use bit 5
44 if (width
== MMC_BUS_WIDTH_8
)
45 ctrl
|= SDHCI_SIRF_8BITBUS
;
46 else if (width
== MMC_BUS_WIDTH_4
)
47 ctrl
|= SDHCI_CTRL_4BITBUS
;
49 sdhci_writeb(host
, ctrl
, SDHCI_HOST_CONTROL
);
52 static struct sdhci_ops sdhci_sirf_ops
= {
53 .set_clock
= sdhci_set_clock
,
54 .get_max_clock
= sdhci_sirf_get_max_clk
,
55 .set_bus_width
= sdhci_sirf_set_bus_width
,
57 .set_uhs_signaling
= sdhci_set_uhs_signaling
,
60 static struct sdhci_pltfm_data sdhci_sirf_pdata
= {
61 .ops
= &sdhci_sirf_ops
,
62 .quirks
= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
|
63 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK
|
64 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN
|
65 SDHCI_QUIRK_INVERTED_WRITE_PROTECT
|
66 SDHCI_QUIRK_DELAY_AFTER_POWER
,
69 static int sdhci_sirf_probe(struct platform_device
*pdev
)
71 struct sdhci_host
*host
;
72 struct sdhci_pltfm_host
*pltfm_host
;
73 struct sdhci_sirf_priv
*priv
;
78 clk
= devm_clk_get(&pdev
->dev
, NULL
);
80 dev_err(&pdev
->dev
, "unable to get clock");
84 if (pdev
->dev
.of_node
)
85 gpio_cd
= of_get_named_gpio(pdev
->dev
.of_node
, "cd-gpios", 0);
89 host
= sdhci_pltfm_init(pdev
, &sdhci_sirf_pdata
, sizeof(struct sdhci_sirf_priv
));
93 pltfm_host
= sdhci_priv(host
);
94 priv
= sdhci_pltfm_priv(pltfm_host
);
96 priv
->gpio_cd
= gpio_cd
;
98 sdhci_get_of_property(pdev
);
100 ret
= clk_prepare_enable(priv
->clk
);
102 goto err_clk_prepare
;
104 ret
= sdhci_add_host(host
);
109 * We must request the IRQ after sdhci_add_host(), as the tasklet only
110 * gets setup in sdhci_add_host() and we oops.
112 if (gpio_is_valid(priv
->gpio_cd
)) {
113 ret
= mmc_gpio_request_cd(host
->mmc
, priv
->gpio_cd
, 0);
115 dev_err(&pdev
->dev
, "card detect irq request failed: %d\n",
119 mmc_gpiod_request_cd_irq(host
->mmc
);
125 sdhci_remove_host(host
, 0);
127 clk_disable_unprepare(priv
->clk
);
129 sdhci_pltfm_free(pdev
);
133 static int sdhci_sirf_remove(struct platform_device
*pdev
)
135 struct sdhci_host
*host
= platform_get_drvdata(pdev
);
136 struct sdhci_pltfm_host
*pltfm_host
= sdhci_priv(host
);
137 struct sdhci_sirf_priv
*priv
= sdhci_pltfm_priv(pltfm_host
);
139 sdhci_pltfm_unregister(pdev
);
141 if (gpio_is_valid(priv
->gpio_cd
))
142 mmc_gpio_free_cd(host
->mmc
);
144 clk_disable_unprepare(priv
->clk
);
148 #ifdef CONFIG_PM_SLEEP
149 static int sdhci_sirf_suspend(struct device
*dev
)
151 struct sdhci_host
*host
= dev_get_drvdata(dev
);
152 struct sdhci_pltfm_host
*pltfm_host
= sdhci_priv(host
);
153 struct sdhci_sirf_priv
*priv
= sdhci_pltfm_priv(pltfm_host
);
156 ret
= sdhci_suspend_host(host
);
160 clk_disable(priv
->clk
);
165 static int sdhci_sirf_resume(struct device
*dev
)
167 struct sdhci_host
*host
= dev_get_drvdata(dev
);
168 struct sdhci_pltfm_host
*pltfm_host
= sdhci_priv(host
);
169 struct sdhci_sirf_priv
*priv
= sdhci_pltfm_priv(pltfm_host
);
172 ret
= clk_enable(priv
->clk
);
174 dev_dbg(dev
, "Resume: Error enabling clock\n");
178 return sdhci_resume_host(host
);
181 static SIMPLE_DEV_PM_OPS(sdhci_sirf_pm_ops
, sdhci_sirf_suspend
, sdhci_sirf_resume
);
184 static const struct of_device_id sdhci_sirf_of_match
[] = {
185 { .compatible
= "sirf,prima2-sdhc" },
188 MODULE_DEVICE_TABLE(of
, sdhci_sirf_of_match
);
190 static struct platform_driver sdhci_sirf_driver
= {
192 .name
= "sdhci-sirf",
193 .of_match_table
= sdhci_sirf_of_match
,
194 #ifdef CONFIG_PM_SLEEP
195 .pm
= &sdhci_sirf_pm_ops
,
198 .probe
= sdhci_sirf_probe
,
199 .remove
= sdhci_sirf_remove
,
202 module_platform_driver(sdhci_sirf_driver
);
204 MODULE_DESCRIPTION("SDHCI driver for SiRFprimaII/SiRFmarco");
205 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
206 MODULE_LICENSE("GPL v2");