101ebea1bSChristian Daudt /* 201ebea1bSChristian Daudt * Copyright (C) 2013 Broadcom Corporation 301ebea1bSChristian Daudt * 401ebea1bSChristian Daudt * This program is free software; you can redistribute it and/or 501ebea1bSChristian Daudt * modify it under the terms of the GNU General Public License as 601ebea1bSChristian Daudt * published by the Free Software Foundation version 2. 701ebea1bSChristian Daudt * 801ebea1bSChristian Daudt * This program is distributed "as is" WITHOUT ANY WARRANTY of any 901ebea1bSChristian Daudt * kind, whether express or implied; without even the implied warranty 1001ebea1bSChristian Daudt * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1101ebea1bSChristian Daudt * GNU General Public License for more details. 1201ebea1bSChristian Daudt */ 1301ebea1bSChristian Daudt 1401ebea1bSChristian Daudt #include <linux/kernel.h> 1501ebea1bSChristian Daudt #include <linux/module.h> 1601ebea1bSChristian Daudt #include <linux/delay.h> 1701ebea1bSChristian Daudt #include <linux/highmem.h> 1801ebea1bSChristian Daudt #include <linux/platform_device.h> 1901ebea1bSChristian Daudt #include <linux/mmc/host.h> 2001ebea1bSChristian Daudt #include <linux/io.h> 2101ebea1bSChristian Daudt #include <linux/gpio.h> 2201ebea1bSChristian Daudt #include <linux/clk.h> 2301ebea1bSChristian Daudt #include <linux/regulator/consumer.h> 2401ebea1bSChristian Daudt #include <linux/of.h> 2501ebea1bSChristian Daudt #include <linux/of_device.h> 2601ebea1bSChristian Daudt #include <linux/of_gpio.h> 2701ebea1bSChristian Daudt #include <linux/mmc/slot-gpio.h> 2801ebea1bSChristian Daudt 2901ebea1bSChristian Daudt #include "sdhci-pltfm.h" 3001ebea1bSChristian Daudt #include "sdhci.h" 3101ebea1bSChristian Daudt 3201ebea1bSChristian Daudt #define SDHCI_SOFT_RESET 0x01000000 3301ebea1bSChristian Daudt #define KONA_SDHOST_CORECTRL 0x8000 3401ebea1bSChristian Daudt #define KONA_SDHOST_CD_PINCTRL 0x00000008 3501ebea1bSChristian Daudt #define KONA_SDHOST_STOP_HCLK 0x00000004 3601ebea1bSChristian Daudt #define KONA_SDHOST_RESET 0x00000002 3701ebea1bSChristian Daudt #define KONA_SDHOST_EN 0x00000001 3801ebea1bSChristian Daudt 3901ebea1bSChristian Daudt #define KONA_SDHOST_CORESTAT 0x8004 4001ebea1bSChristian Daudt #define KONA_SDHOST_WP 0x00000002 4101ebea1bSChristian Daudt #define KONA_SDHOST_CD_SW 0x00000001 4201ebea1bSChristian Daudt 4301ebea1bSChristian Daudt #define KONA_SDHOST_COREIMR 0x8008 4401ebea1bSChristian Daudt #define KONA_SDHOST_IP 0x00000001 4501ebea1bSChristian Daudt 4601ebea1bSChristian Daudt #define KONA_SDHOST_COREISR 0x800C 4701ebea1bSChristian Daudt #define KONA_SDHOST_COREIMSR 0x8010 4801ebea1bSChristian Daudt #define KONA_SDHOST_COREDBG1 0x8014 4901ebea1bSChristian Daudt #define KONA_SDHOST_COREGPO_MASK 0x8018 5001ebea1bSChristian Daudt 5101ebea1bSChristian Daudt #define SD_DETECT_GPIO_DEBOUNCE_128MS 128 5201ebea1bSChristian Daudt 5301ebea1bSChristian Daudt #define KONA_MMC_AUTOSUSPEND_DELAY (50) 5401ebea1bSChristian Daudt 5501ebea1bSChristian Daudt struct sdhci_bcm_kona_dev { 5601ebea1bSChristian Daudt struct mutex write_lock; /* protect back to back writes */ 57a6492c02STim Kryger struct clk *external_clk; 5801ebea1bSChristian Daudt }; 5901ebea1bSChristian Daudt 6001ebea1bSChristian Daudt 6101ebea1bSChristian Daudt static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host) 6201ebea1bSChristian Daudt { 6301ebea1bSChristian Daudt unsigned int val; 6401ebea1bSChristian Daudt unsigned long timeout; 6501ebea1bSChristian Daudt 6601ebea1bSChristian Daudt /* This timeout should be sufficent for core to reset */ 6701ebea1bSChristian Daudt timeout = jiffies + msecs_to_jiffies(100); 6801ebea1bSChristian Daudt 6901ebea1bSChristian Daudt /* reset the host using the top level reset */ 7001ebea1bSChristian Daudt val = sdhci_readl(host, KONA_SDHOST_CORECTRL); 7101ebea1bSChristian Daudt val |= KONA_SDHOST_RESET; 7201ebea1bSChristian Daudt sdhci_writel(host, val, KONA_SDHOST_CORECTRL); 7301ebea1bSChristian Daudt 7401ebea1bSChristian Daudt while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) { 7501ebea1bSChristian Daudt if (time_is_before_jiffies(timeout)) { 7601ebea1bSChristian Daudt pr_err("Error: sd host is stuck in reset!!!\n"); 7701ebea1bSChristian Daudt return -EFAULT; 7801ebea1bSChristian Daudt } 7901ebea1bSChristian Daudt } 8001ebea1bSChristian Daudt 8101ebea1bSChristian Daudt /* bring the host out of reset */ 8201ebea1bSChristian Daudt val = sdhci_readl(host, KONA_SDHOST_CORECTRL); 8301ebea1bSChristian Daudt val &= ~KONA_SDHOST_RESET; 8401ebea1bSChristian Daudt 8501ebea1bSChristian Daudt /* 8601ebea1bSChristian Daudt * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS) 8701ebea1bSChristian Daudt * Back-to-Back writes to same register needs delay when SD bus clock 8801ebea1bSChristian Daudt * is very low w.r.t AHB clock, mainly during boot-time and during card 8901ebea1bSChristian Daudt * insert-removal. 9001ebea1bSChristian Daudt */ 9101ebea1bSChristian Daudt usleep_range(1000, 5000); 9201ebea1bSChristian Daudt sdhci_writel(host, val, KONA_SDHOST_CORECTRL); 9301ebea1bSChristian Daudt 9401ebea1bSChristian Daudt return 0; 9501ebea1bSChristian Daudt } 9601ebea1bSChristian Daudt 9701ebea1bSChristian Daudt static void sdhci_bcm_kona_sd_init(struct sdhci_host *host) 9801ebea1bSChristian Daudt { 9901ebea1bSChristian Daudt unsigned int val; 10001ebea1bSChristian Daudt 10101ebea1bSChristian Daudt /* enable the interrupt from the IP core */ 10201ebea1bSChristian Daudt val = sdhci_readl(host, KONA_SDHOST_COREIMR); 10301ebea1bSChristian Daudt val |= KONA_SDHOST_IP; 10401ebea1bSChristian Daudt sdhci_writel(host, val, KONA_SDHOST_COREIMR); 10501ebea1bSChristian Daudt 10601ebea1bSChristian Daudt /* Enable the AHB clock gating module to the host */ 10701ebea1bSChristian Daudt val = sdhci_readl(host, KONA_SDHOST_CORECTRL); 10801ebea1bSChristian Daudt val |= KONA_SDHOST_EN; 10901ebea1bSChristian Daudt 11001ebea1bSChristian Daudt /* 11101ebea1bSChristian Daudt * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS) 11201ebea1bSChristian Daudt * Back-to-Back writes to same register needs delay when SD bus clock 11301ebea1bSChristian Daudt * is very low w.r.t AHB clock, mainly during boot-time and during card 11401ebea1bSChristian Daudt * insert-removal. 11501ebea1bSChristian Daudt */ 11601ebea1bSChristian Daudt usleep_range(1000, 5000); 11701ebea1bSChristian Daudt sdhci_writel(host, val, KONA_SDHOST_CORECTRL); 11801ebea1bSChristian Daudt } 11901ebea1bSChristian Daudt 12001ebea1bSChristian Daudt /* 12101ebea1bSChristian Daudt * Software emulation of the SD card insertion/removal. Set insert=1 for insert 12201ebea1bSChristian Daudt * and insert=0 for removal. The card detection is done by GPIO. For Broadcom 12301ebea1bSChristian Daudt * IP to function properly the bit 0 of CORESTAT register needs to be set/reset 12401ebea1bSChristian Daudt * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet. 12501ebea1bSChristian Daudt */ 12601ebea1bSChristian Daudt static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert) 12701ebea1bSChristian Daudt { 12801ebea1bSChristian Daudt struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); 12901ebea1bSChristian Daudt struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv); 13001ebea1bSChristian Daudt u32 val; 13101ebea1bSChristian Daudt 13201ebea1bSChristian Daudt /* 13301ebea1bSChristian Daudt * Back-to-Back register write needs a delay of min 10uS. 13401ebea1bSChristian Daudt * Back-to-Back writes to same register needs delay when SD bus clock 13501ebea1bSChristian Daudt * is very low w.r.t AHB clock, mainly during boot-time and during card 13601ebea1bSChristian Daudt * insert-removal. 13701ebea1bSChristian Daudt * We keep 20uS 13801ebea1bSChristian Daudt */ 13901ebea1bSChristian Daudt mutex_lock(&kona_dev->write_lock); 14001ebea1bSChristian Daudt udelay(20); 14101ebea1bSChristian Daudt val = sdhci_readl(host, KONA_SDHOST_CORESTAT); 14201ebea1bSChristian Daudt 14301ebea1bSChristian Daudt if (insert) { 14401ebea1bSChristian Daudt int ret; 14501ebea1bSChristian Daudt 14601ebea1bSChristian Daudt ret = mmc_gpio_get_ro(host->mmc); 14701ebea1bSChristian Daudt if (ret >= 0) 14801ebea1bSChristian Daudt val = (val & ~KONA_SDHOST_WP) | 14901ebea1bSChristian Daudt ((ret) ? KONA_SDHOST_WP : 0); 15001ebea1bSChristian Daudt 15101ebea1bSChristian Daudt val |= KONA_SDHOST_CD_SW; 15201ebea1bSChristian Daudt sdhci_writel(host, val, KONA_SDHOST_CORESTAT); 15301ebea1bSChristian Daudt } else { 15401ebea1bSChristian Daudt val &= ~KONA_SDHOST_CD_SW; 15501ebea1bSChristian Daudt sdhci_writel(host, val, KONA_SDHOST_CORESTAT); 15601ebea1bSChristian Daudt } 15701ebea1bSChristian Daudt mutex_unlock(&kona_dev->write_lock); 15801ebea1bSChristian Daudt 15901ebea1bSChristian Daudt return 0; 16001ebea1bSChristian Daudt } 16101ebea1bSChristian Daudt 16201ebea1bSChristian Daudt /* 16301ebea1bSChristian Daudt * SD card interrupt event callback 16401ebea1bSChristian Daudt */ 165ceb2ea19SSachin Kamat static void sdhci_bcm_kona_card_event(struct sdhci_host *host) 16601ebea1bSChristian Daudt { 16701ebea1bSChristian Daudt if (mmc_gpio_get_cd(host->mmc) > 0) { 16801ebea1bSChristian Daudt dev_dbg(mmc_dev(host->mmc), 16901ebea1bSChristian Daudt "card inserted\n"); 17001ebea1bSChristian Daudt sdhci_bcm_kona_sd_card_emulate(host, 1); 17101ebea1bSChristian Daudt } else { 17201ebea1bSChristian Daudt dev_dbg(mmc_dev(host->mmc), 17301ebea1bSChristian Daudt "card removed\n"); 17401ebea1bSChristian Daudt sdhci_bcm_kona_sd_card_emulate(host, 0); 17501ebea1bSChristian Daudt } 17601ebea1bSChristian Daudt } 17701ebea1bSChristian Daudt 17801ebea1bSChristian Daudt /* 17901ebea1bSChristian Daudt * Get the base clock. Use central clock source for now. Not sure if different 18001ebea1bSChristian Daudt * clock speed to each dev is allowed 18101ebea1bSChristian Daudt */ 18201ebea1bSChristian Daudt static unsigned int sdhci_bcm_kona_get_max_clk(struct sdhci_host *host) 18301ebea1bSChristian Daudt { 18401ebea1bSChristian Daudt struct sdhci_bcm_kona_dev *kona_dev; 18501ebea1bSChristian Daudt struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); 18601ebea1bSChristian Daudt kona_dev = sdhci_pltfm_priv(pltfm_priv); 18701ebea1bSChristian Daudt 18801ebea1bSChristian Daudt return host->mmc->f_max; 18901ebea1bSChristian Daudt } 19001ebea1bSChristian Daudt 19101ebea1bSChristian Daudt static unsigned int sdhci_bcm_kona_get_timeout_clock(struct sdhci_host *host) 19201ebea1bSChristian Daudt { 19301ebea1bSChristian Daudt return sdhci_bcm_kona_get_max_clk(host); 19401ebea1bSChristian Daudt } 19501ebea1bSChristian Daudt 19601ebea1bSChristian Daudt static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host, 19701ebea1bSChristian Daudt u8 power_mode) 19801ebea1bSChristian Daudt { 19901ebea1bSChristian Daudt /* 20001ebea1bSChristian Daudt * JEDEC and SD spec specify supplying 74 continuous clocks to 20101ebea1bSChristian Daudt * device after power up. With minimum bus (100KHz) that 20201ebea1bSChristian Daudt * that translates to 740us 20301ebea1bSChristian Daudt */ 20401ebea1bSChristian Daudt if (power_mode != MMC_POWER_OFF) 20501ebea1bSChristian Daudt udelay(740); 20601ebea1bSChristian Daudt } 20701ebea1bSChristian Daudt 20801ebea1bSChristian Daudt static struct sdhci_ops sdhci_bcm_kona_ops = { 2091771059cSRussell King .set_clock = sdhci_set_clock, 21001ebea1bSChristian Daudt .get_max_clock = sdhci_bcm_kona_get_max_clk, 21101ebea1bSChristian Daudt .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock, 21201ebea1bSChristian Daudt .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, 2132317f56cSRussell King .set_bus_width = sdhci_set_bus_width, 21403231f9bSRussell King .reset = sdhci_reset, 21596d7b78cSRussell King .set_uhs_signaling = sdhci_set_uhs_signaling, 21601ebea1bSChristian Daudt .card_event = sdhci_bcm_kona_card_event, 21701ebea1bSChristian Daudt }; 21801ebea1bSChristian Daudt 21901ebea1bSChristian Daudt static struct sdhci_pltfm_data sdhci_pltfm_data_kona = { 22001ebea1bSChristian Daudt .ops = &sdhci_bcm_kona_ops, 22101ebea1bSChristian Daudt .quirks = SDHCI_QUIRK_NO_CARD_NO_RESET | 22201ebea1bSChristian Daudt SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_32BIT_DMA_ADDR | 22301ebea1bSChristian Daudt SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE | 22401ebea1bSChristian Daudt SDHCI_QUIRK_FORCE_BLK_SZ_2048 | 22501ebea1bSChristian Daudt SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 22601ebea1bSChristian Daudt }; 22701ebea1bSChristian Daudt 228058feb53SMarkus Mayer static struct __initconst of_device_id sdhci_bcm_kona_of_match[] = { 229aea237bfSChristian Daudt { .compatible = "brcm,kona-sdhci"}, 230aea237bfSChristian Daudt { .compatible = "bcm,kona-sdhci"}, /* deprecated name */ 23101ebea1bSChristian Daudt {} 23201ebea1bSChristian Daudt }; 23301ebea1bSChristian Daudt MODULE_DEVICE_TABLE(of, sdhci_bcm_kona_of_match); 23401ebea1bSChristian Daudt 235058feb53SMarkus Mayer static int sdhci_bcm_kona_probe(struct platform_device *pdev) 23601ebea1bSChristian Daudt { 23701ebea1bSChristian Daudt struct sdhci_bcm_kona_dev *kona_dev = NULL; 23801ebea1bSChristian Daudt struct sdhci_pltfm_host *pltfm_priv; 23901ebea1bSChristian Daudt struct device *dev = &pdev->dev; 24001ebea1bSChristian Daudt struct sdhci_host *host; 24101ebea1bSChristian Daudt int ret; 24201ebea1bSChristian Daudt 24301ebea1bSChristian Daudt ret = 0; 24401ebea1bSChristian Daudt 24501ebea1bSChristian Daudt host = sdhci_pltfm_init(pdev, &sdhci_pltfm_data_kona, 24601ebea1bSChristian Daudt sizeof(*kona_dev)); 24701ebea1bSChristian Daudt if (IS_ERR(host)) 24801ebea1bSChristian Daudt return PTR_ERR(host); 24901ebea1bSChristian Daudt 25001ebea1bSChristian Daudt dev_dbg(dev, "%s: inited. IOADDR=%p\n", __func__, host->ioaddr); 25101ebea1bSChristian Daudt 25201ebea1bSChristian Daudt pltfm_priv = sdhci_priv(host); 25301ebea1bSChristian Daudt 25401ebea1bSChristian Daudt kona_dev = sdhci_pltfm_priv(pltfm_priv); 25501ebea1bSChristian Daudt mutex_init(&kona_dev->write_lock); 25601ebea1bSChristian Daudt 25701ebea1bSChristian Daudt mmc_of_parse(host->mmc); 25801ebea1bSChristian Daudt 25901ebea1bSChristian Daudt if (!host->mmc->f_max) { 26001ebea1bSChristian Daudt dev_err(&pdev->dev, "Missing max-freq for SDHCI cfg\n"); 26101ebea1bSChristian Daudt ret = -ENXIO; 26201ebea1bSChristian Daudt goto err_pltfm_free; 26301ebea1bSChristian Daudt } 26401ebea1bSChristian Daudt 265a6492c02STim Kryger /* Get and enable the external clock */ 266a6492c02STim Kryger kona_dev->external_clk = devm_clk_get(dev, NULL); 267a6492c02STim Kryger if (IS_ERR(kona_dev->external_clk)) { 268a6492c02STim Kryger dev_err(dev, "Failed to get external clock\n"); 269a6492c02STim Kryger ret = PTR_ERR(kona_dev->external_clk); 270a6492c02STim Kryger goto err_pltfm_free; 271a6492c02STim Kryger } 272a6492c02STim Kryger 273a6492c02STim Kryger if (clk_set_rate(kona_dev->external_clk, host->mmc->f_max) != 0) { 274a6492c02STim Kryger dev_err(dev, "Failed to set rate external clock\n"); 275a6492c02STim Kryger goto err_pltfm_free; 276a6492c02STim Kryger } 277a6492c02STim Kryger 278a6492c02STim Kryger if (clk_prepare_enable(kona_dev->external_clk) != 0) { 279a6492c02STim Kryger dev_err(dev, "Failed to enable external clock\n"); 280a6492c02STim Kryger goto err_pltfm_free; 281a6492c02STim Kryger } 282a6492c02STim Kryger 28301ebea1bSChristian Daudt dev_dbg(dev, "non-removable=%c\n", 28401ebea1bSChristian Daudt (host->mmc->caps & MMC_CAP_NONREMOVABLE) ? 'Y' : 'N'); 28501ebea1bSChristian Daudt dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n", 28601ebea1bSChristian Daudt (mmc_gpio_get_cd(host->mmc) != -ENOSYS) ? 'Y' : 'N', 28701ebea1bSChristian Daudt (mmc_gpio_get_ro(host->mmc) != -ENOSYS) ? 'Y' : 'N'); 28801ebea1bSChristian Daudt 289cf68b629SChristian Daudt if (host->mmc->caps & MMC_CAP_NONREMOVABLE) 29001ebea1bSChristian Daudt host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; 29101ebea1bSChristian Daudt 29201ebea1bSChristian Daudt dev_dbg(dev, "is_8bit=%c\n", 29301ebea1bSChristian Daudt (host->mmc->caps | MMC_CAP_8_BIT_DATA) ? 'Y' : 'N'); 29401ebea1bSChristian Daudt 29501ebea1bSChristian Daudt ret = sdhci_bcm_kona_sd_reset(host); 29601ebea1bSChristian Daudt if (ret) 297a6492c02STim Kryger goto err_clk_disable; 29801ebea1bSChristian Daudt 29901ebea1bSChristian Daudt sdhci_bcm_kona_sd_init(host); 30001ebea1bSChristian Daudt 30101ebea1bSChristian Daudt ret = sdhci_add_host(host); 30201ebea1bSChristian Daudt if (ret) { 30301ebea1bSChristian Daudt dev_err(dev, "Failed sdhci_add_host\n"); 30401ebea1bSChristian Daudt goto err_reset; 30501ebea1bSChristian Daudt } 30601ebea1bSChristian Daudt 30701ebea1bSChristian Daudt /* if device is eMMC, emulate card insert right here */ 308cf68b629SChristian Daudt if (host->mmc->caps & MMC_CAP_NONREMOVABLE) { 30901ebea1bSChristian Daudt ret = sdhci_bcm_kona_sd_card_emulate(host, 1); 31001ebea1bSChristian Daudt if (ret) { 31101ebea1bSChristian Daudt dev_err(dev, 31201ebea1bSChristian Daudt "unable to emulate card insertion\n"); 31301ebea1bSChristian Daudt goto err_remove_host; 31401ebea1bSChristian Daudt } 31501ebea1bSChristian Daudt } 31601ebea1bSChristian Daudt /* 31701ebea1bSChristian Daudt * Since the card detection GPIO interrupt is configured to be 31801ebea1bSChristian Daudt * edge sensitive, check the initial GPIO value here, emulate 31901ebea1bSChristian Daudt * only if the card is present 32001ebea1bSChristian Daudt */ 32101ebea1bSChristian Daudt if (mmc_gpio_get_cd(host->mmc) > 0) 32201ebea1bSChristian Daudt sdhci_bcm_kona_sd_card_emulate(host, 1); 32301ebea1bSChristian Daudt 32401ebea1bSChristian Daudt dev_dbg(dev, "initialized properly\n"); 32501ebea1bSChristian Daudt return 0; 32601ebea1bSChristian Daudt 32701ebea1bSChristian Daudt err_remove_host: 32801ebea1bSChristian Daudt sdhci_remove_host(host, 0); 32901ebea1bSChristian Daudt 33001ebea1bSChristian Daudt err_reset: 33101ebea1bSChristian Daudt sdhci_bcm_kona_sd_reset(host); 33201ebea1bSChristian Daudt 333a6492c02STim Kryger err_clk_disable: 334a6492c02STim Kryger clk_disable_unprepare(kona_dev->external_clk); 335a6492c02STim Kryger 33601ebea1bSChristian Daudt err_pltfm_free: 33701ebea1bSChristian Daudt sdhci_pltfm_free(pdev); 33801ebea1bSChristian Daudt 33901ebea1bSChristian Daudt dev_err(dev, "Probing of sdhci-pltfm failed: %d\n", ret); 34001ebea1bSChristian Daudt return ret; 34101ebea1bSChristian Daudt } 34201ebea1bSChristian Daudt 3434025ce24SRussell King static int sdhci_bcm_kona_remove(struct platform_device *pdev) 34401ebea1bSChristian Daudt { 345a6492c02STim Kryger struct sdhci_host *host = platform_get_drvdata(pdev); 346a6492c02STim Kryger struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); 347a6492c02STim Kryger struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv); 348a6492c02STim Kryger int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); 349a6492c02STim Kryger 350a6492c02STim Kryger sdhci_remove_host(host, dead); 351a6492c02STim Kryger 352a6492c02STim Kryger clk_disable_unprepare(kona_dev->external_clk); 353a6492c02STim Kryger 354a6492c02STim Kryger sdhci_pltfm_free(pdev); 355a6492c02STim Kryger 356a6492c02STim Kryger return 0; 35701ebea1bSChristian Daudt } 35801ebea1bSChristian Daudt 35901ebea1bSChristian Daudt static struct platform_driver sdhci_bcm_kona_driver = { 36001ebea1bSChristian Daudt .driver = { 36101ebea1bSChristian Daudt .name = "sdhci-kona", 36201ebea1bSChristian Daudt .owner = THIS_MODULE, 36301ebea1bSChristian Daudt .pm = SDHCI_PLTFM_PMOPS, 364058feb53SMarkus Mayer .of_match_table = sdhci_bcm_kona_of_match, 36501ebea1bSChristian Daudt }, 36601ebea1bSChristian Daudt .probe = sdhci_bcm_kona_probe, 367058feb53SMarkus Mayer .remove = sdhci_bcm_kona_remove, 36801ebea1bSChristian Daudt }; 36901ebea1bSChristian Daudt module_platform_driver(sdhci_bcm_kona_driver); 37001ebea1bSChristian Daudt 37101ebea1bSChristian Daudt MODULE_DESCRIPTION("SDHCI driver for Broadcom Kona platform"); 37201ebea1bSChristian Daudt MODULE_AUTHOR("Broadcom"); 37301ebea1bSChristian Daudt MODULE_LICENSE("GPL v2"); 374