diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-dove.c')
-rw-r--r-- | drivers/mmc/host/sdhci-dove.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 177f697b5835..a6e53a1ebb08 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c | |||
@@ -20,11 +20,17 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/clk.h> | ||
24 | #include <linux/err.h> | ||
23 | #include <linux/module.h> | 25 | #include <linux/module.h> |
24 | #include <linux/mmc/host.h> | 26 | #include <linux/mmc/host.h> |
25 | 27 | ||
26 | #include "sdhci-pltfm.h" | 28 | #include "sdhci-pltfm.h" |
27 | 29 | ||
30 | struct sdhci_dove_priv { | ||
31 | struct clk *clk; | ||
32 | }; | ||
33 | |||
28 | static u16 sdhci_dove_readw(struct sdhci_host *host, int reg) | 34 | static u16 sdhci_dove_readw(struct sdhci_host *host, int reg) |
29 | { | 35 | { |
30 | u16 ret; | 36 | u16 ret; |
@@ -66,16 +72,57 @@ static struct sdhci_pltfm_data sdhci_dove_pdata = { | |||
66 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | | 72 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | |
67 | SDHCI_QUIRK_NO_BUSY_IRQ | | 73 | SDHCI_QUIRK_NO_BUSY_IRQ | |
68 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | | 74 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | |
69 | SDHCI_QUIRK_FORCE_DMA, | 75 | SDHCI_QUIRK_FORCE_DMA | |
76 | SDHCI_QUIRK_NO_HISPD_BIT, | ||
70 | }; | 77 | }; |
71 | 78 | ||
72 | static int __devinit sdhci_dove_probe(struct platform_device *pdev) | 79 | static int __devinit sdhci_dove_probe(struct platform_device *pdev) |
73 | { | 80 | { |
74 | return sdhci_pltfm_register(pdev, &sdhci_dove_pdata); | 81 | struct sdhci_host *host; |
82 | struct sdhci_pltfm_host *pltfm_host; | ||
83 | struct sdhci_dove_priv *priv; | ||
84 | int ret; | ||
85 | |||
86 | ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); | ||
87 | if (ret) | ||
88 | goto sdhci_dove_register_fail; | ||
89 | |||
90 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv), | ||
91 | GFP_KERNEL); | ||
92 | if (!priv) { | ||
93 | dev_err(&pdev->dev, "unable to allocate private data"); | ||
94 | ret = -ENOMEM; | ||
95 | goto sdhci_dove_allocate_fail; | ||
96 | } | ||
97 | |||
98 | host = platform_get_drvdata(pdev); | ||
99 | pltfm_host = sdhci_priv(host); | ||
100 | pltfm_host->priv = priv; | ||
101 | |||
102 | priv->clk = clk_get(&pdev->dev, NULL); | ||
103 | if (!IS_ERR(priv->clk)) | ||
104 | clk_prepare_enable(priv->clk); | ||
105 | return 0; | ||
106 | |||
107 | sdhci_dove_allocate_fail: | ||
108 | sdhci_pltfm_unregister(pdev); | ||
109 | sdhci_dove_register_fail: | ||
110 | return ret; | ||
75 | } | 111 | } |
76 | 112 | ||
77 | static int __devexit sdhci_dove_remove(struct platform_device *pdev) | 113 | static int __devexit sdhci_dove_remove(struct platform_device *pdev) |
78 | { | 114 | { |
115 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
116 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
117 | struct sdhci_dove_priv *priv = pltfm_host->priv; | ||
118 | |||
119 | if (priv->clk) { | ||
120 | if (!IS_ERR(priv->clk)) { | ||
121 | clk_disable_unprepare(priv->clk); | ||
122 | clk_put(priv->clk); | ||
123 | } | ||
124 | devm_kfree(&pdev->dev, priv->clk); | ||
125 | } | ||
79 | return sdhci_pltfm_unregister(pdev); | 126 | return sdhci_pltfm_unregister(pdev); |
80 | } | 127 | } |
81 | 128 | ||