diff options
-rw-r--r-- | drivers/mmc/host/sdhci-bcm-kona.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index 7a190fe4dff1..923eefabf801 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c | |||
@@ -54,6 +54,7 @@ | |||
54 | 54 | ||
55 | struct sdhci_bcm_kona_dev { | 55 | struct sdhci_bcm_kona_dev { |
56 | struct mutex write_lock; /* protect back to back writes */ | 56 | struct mutex write_lock; /* protect back to back writes */ |
57 | struct clk *external_clk; | ||
57 | }; | 58 | }; |
58 | 59 | ||
59 | 60 | ||
@@ -257,6 +258,24 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev) | |||
257 | goto err_pltfm_free; | 258 | goto err_pltfm_free; |
258 | } | 259 | } |
259 | 260 | ||
261 | /* Get and enable the external clock */ | ||
262 | kona_dev->external_clk = devm_clk_get(dev, NULL); | ||
263 | if (IS_ERR(kona_dev->external_clk)) { | ||
264 | dev_err(dev, "Failed to get external clock\n"); | ||
265 | ret = PTR_ERR(kona_dev->external_clk); | ||
266 | goto err_pltfm_free; | ||
267 | } | ||
268 | |||
269 | if (clk_set_rate(kona_dev->external_clk, host->mmc->f_max) != 0) { | ||
270 | dev_err(dev, "Failed to set rate external clock\n"); | ||
271 | goto err_pltfm_free; | ||
272 | } | ||
273 | |||
274 | if (clk_prepare_enable(kona_dev->external_clk) != 0) { | ||
275 | dev_err(dev, "Failed to enable external clock\n"); | ||
276 | goto err_pltfm_free; | ||
277 | } | ||
278 | |||
260 | dev_dbg(dev, "non-removable=%c\n", | 279 | dev_dbg(dev, "non-removable=%c\n", |
261 | (host->mmc->caps & MMC_CAP_NONREMOVABLE) ? 'Y' : 'N'); | 280 | (host->mmc->caps & MMC_CAP_NONREMOVABLE) ? 'Y' : 'N'); |
262 | dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n", | 281 | dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n", |
@@ -271,7 +290,7 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev) | |||
271 | 290 | ||
272 | ret = sdhci_bcm_kona_sd_reset(host); | 291 | ret = sdhci_bcm_kona_sd_reset(host); |
273 | if (ret) | 292 | if (ret) |
274 | goto err_pltfm_free; | 293 | goto err_clk_disable; |
275 | 294 | ||
276 | sdhci_bcm_kona_sd_init(host); | 295 | sdhci_bcm_kona_sd_init(host); |
277 | 296 | ||
@@ -307,6 +326,9 @@ err_remove_host: | |||
307 | err_reset: | 326 | err_reset: |
308 | sdhci_bcm_kona_sd_reset(host); | 327 | sdhci_bcm_kona_sd_reset(host); |
309 | 328 | ||
329 | err_clk_disable: | ||
330 | clk_disable_unprepare(kona_dev->external_clk); | ||
331 | |||
310 | err_pltfm_free: | 332 | err_pltfm_free: |
311 | sdhci_pltfm_free(pdev); | 333 | sdhci_pltfm_free(pdev); |
312 | 334 | ||
@@ -316,7 +338,18 @@ err_pltfm_free: | |||
316 | 338 | ||
317 | static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev) | 339 | static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev) |
318 | { | 340 | { |
319 | return sdhci_pltfm_unregister(pdev); | 341 | struct sdhci_host *host = platform_get_drvdata(pdev); |
342 | struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); | ||
343 | struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv); | ||
344 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); | ||
345 | |||
346 | sdhci_remove_host(host, dead); | ||
347 | |||
348 | clk_disable_unprepare(kona_dev->external_clk); | ||
349 | |||
350 | sdhci_pltfm_free(pdev); | ||
351 | |||
352 | return 0; | ||
320 | } | 353 | } |
321 | 354 | ||
322 | static struct platform_driver sdhci_bcm_kona_driver = { | 355 | static struct platform_driver sdhci_bcm_kona_driver = { |