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/version.h>
2801ebea1bSChristian Daudt #include <linux/mmc/slot-gpio.h>
2901ebea1bSChristian Daudt 
3001ebea1bSChristian Daudt #include "sdhci-pltfm.h"
3101ebea1bSChristian Daudt #include "sdhci.h"
3201ebea1bSChristian Daudt 
3301ebea1bSChristian Daudt #define SDHCI_SOFT_RESET			0x01000000
3401ebea1bSChristian Daudt #define KONA_SDHOST_CORECTRL			0x8000
3501ebea1bSChristian Daudt #define KONA_SDHOST_CD_PINCTRL			0x00000008
3601ebea1bSChristian Daudt #define KONA_SDHOST_STOP_HCLK			0x00000004
3701ebea1bSChristian Daudt #define KONA_SDHOST_RESET			0x00000002
3801ebea1bSChristian Daudt #define KONA_SDHOST_EN				0x00000001
3901ebea1bSChristian Daudt 
4001ebea1bSChristian Daudt #define KONA_SDHOST_CORESTAT			0x8004
4101ebea1bSChristian Daudt #define KONA_SDHOST_WP				0x00000002
4201ebea1bSChristian Daudt #define KONA_SDHOST_CD_SW			0x00000001
4301ebea1bSChristian Daudt 
4401ebea1bSChristian Daudt #define KONA_SDHOST_COREIMR			0x8008
4501ebea1bSChristian Daudt #define KONA_SDHOST_IP				0x00000001
4601ebea1bSChristian Daudt 
4701ebea1bSChristian Daudt #define KONA_SDHOST_COREISR			0x800C
4801ebea1bSChristian Daudt #define KONA_SDHOST_COREIMSR			0x8010
4901ebea1bSChristian Daudt #define KONA_SDHOST_COREDBG1			0x8014
5001ebea1bSChristian Daudt #define KONA_SDHOST_COREGPO_MASK		0x8018
5101ebea1bSChristian Daudt 
5201ebea1bSChristian Daudt #define SD_DETECT_GPIO_DEBOUNCE_128MS		128
5301ebea1bSChristian Daudt 
5401ebea1bSChristian Daudt #define KONA_MMC_AUTOSUSPEND_DELAY		(50)
5501ebea1bSChristian Daudt 
5601ebea1bSChristian Daudt struct sdhci_bcm_kona_dev {
5701ebea1bSChristian Daudt 	struct mutex	write_lock; /* protect back to back writes */
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  */
16501ebea1bSChristian Daudt 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 = {
20901ebea1bSChristian Daudt 	.get_max_clock = sdhci_bcm_kona_get_max_clk,
21001ebea1bSChristian Daudt 	.get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
21101ebea1bSChristian Daudt 	.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
21201ebea1bSChristian Daudt 	.card_event = sdhci_bcm_kona_card_event,
21301ebea1bSChristian Daudt };
21401ebea1bSChristian Daudt 
21501ebea1bSChristian Daudt static struct sdhci_pltfm_data sdhci_pltfm_data_kona = {
21601ebea1bSChristian Daudt 	.ops    = &sdhci_bcm_kona_ops,
21701ebea1bSChristian Daudt 	.quirks = SDHCI_QUIRK_NO_CARD_NO_RESET |
21801ebea1bSChristian Daudt 		SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_32BIT_DMA_ADDR |
21901ebea1bSChristian Daudt 		SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE |
22001ebea1bSChristian Daudt 		SDHCI_QUIRK_FORCE_BLK_SZ_2048 |
22101ebea1bSChristian Daudt 		SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
22201ebea1bSChristian Daudt };
22301ebea1bSChristian Daudt 
22401ebea1bSChristian Daudt static const struct of_device_id sdhci_bcm_kona_of_match[] __initdata = {
22501ebea1bSChristian Daudt 	{ .compatible = "bcm,kona-sdhci"},
22601ebea1bSChristian Daudt 	{}
22701ebea1bSChristian Daudt };
22801ebea1bSChristian Daudt MODULE_DEVICE_TABLE(of, sdhci_bcm_kona_of_match);
22901ebea1bSChristian Daudt 
23001ebea1bSChristian Daudt static int __init sdhci_bcm_kona_probe(struct platform_device *pdev)
23101ebea1bSChristian Daudt {
23201ebea1bSChristian Daudt 	struct sdhci_bcm_kona_dev *kona_dev = NULL;
23301ebea1bSChristian Daudt 	struct sdhci_pltfm_host *pltfm_priv;
23401ebea1bSChristian Daudt 	struct device *dev = &pdev->dev;
23501ebea1bSChristian Daudt 	struct sdhci_host *host;
23601ebea1bSChristian Daudt 	int ret;
23701ebea1bSChristian Daudt 
23801ebea1bSChristian Daudt 	ret = 0;
23901ebea1bSChristian Daudt 
24001ebea1bSChristian Daudt 	host = sdhci_pltfm_init(pdev, &sdhci_pltfm_data_kona,
24101ebea1bSChristian Daudt 			sizeof(*kona_dev));
24201ebea1bSChristian Daudt 	if (IS_ERR(host))
24301ebea1bSChristian Daudt 		return PTR_ERR(host);
24401ebea1bSChristian Daudt 
24501ebea1bSChristian Daudt 	dev_dbg(dev, "%s: inited. IOADDR=%p\n", __func__, host->ioaddr);
24601ebea1bSChristian Daudt 
24701ebea1bSChristian Daudt 	pltfm_priv = sdhci_priv(host);
24801ebea1bSChristian Daudt 
24901ebea1bSChristian Daudt 	kona_dev = sdhci_pltfm_priv(pltfm_priv);
25001ebea1bSChristian Daudt 	mutex_init(&kona_dev->write_lock);
25101ebea1bSChristian Daudt 
25201ebea1bSChristian Daudt 	mmc_of_parse(host->mmc);
25301ebea1bSChristian Daudt 
25401ebea1bSChristian Daudt 	if (!host->mmc->f_max) {
25501ebea1bSChristian Daudt 		dev_err(&pdev->dev, "Missing max-freq for SDHCI cfg\n");
25601ebea1bSChristian Daudt 		ret = -ENXIO;
25701ebea1bSChristian Daudt 		goto err_pltfm_free;
25801ebea1bSChristian Daudt 	}
25901ebea1bSChristian Daudt 
26001ebea1bSChristian Daudt 	dev_dbg(dev, "non-removable=%c\n",
26101ebea1bSChristian Daudt 		(host->mmc->caps & MMC_CAP_NONREMOVABLE) ? 'Y' : 'N');
26201ebea1bSChristian Daudt 	dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n",
26301ebea1bSChristian Daudt 		(mmc_gpio_get_cd(host->mmc) != -ENOSYS) ? 'Y' : 'N',
26401ebea1bSChristian Daudt 		(mmc_gpio_get_ro(host->mmc) != -ENOSYS) ? 'Y' : 'N');
26501ebea1bSChristian Daudt 
26601ebea1bSChristian Daudt 	if (host->mmc->caps | MMC_CAP_NONREMOVABLE)
26701ebea1bSChristian Daudt 		host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
26801ebea1bSChristian Daudt 
26901ebea1bSChristian Daudt 	dev_dbg(dev, "is_8bit=%c\n",
27001ebea1bSChristian Daudt 		(host->mmc->caps | MMC_CAP_8_BIT_DATA) ? 'Y' : 'N');
27101ebea1bSChristian Daudt 
27201ebea1bSChristian Daudt 	ret = sdhci_bcm_kona_sd_reset(host);
27301ebea1bSChristian Daudt 	if (ret)
27401ebea1bSChristian Daudt 		goto err_pltfm_free;
27501ebea1bSChristian Daudt 
27601ebea1bSChristian Daudt 	sdhci_bcm_kona_sd_init(host);
27701ebea1bSChristian Daudt 
27801ebea1bSChristian Daudt 	ret = sdhci_add_host(host);
27901ebea1bSChristian Daudt 	if (ret) {
28001ebea1bSChristian Daudt 		dev_err(dev, "Failed sdhci_add_host\n");
28101ebea1bSChristian Daudt 		goto err_reset;
28201ebea1bSChristian Daudt 	}
28301ebea1bSChristian Daudt 
28401ebea1bSChristian Daudt 	/* if device is eMMC, emulate card insert right here */
28501ebea1bSChristian Daudt 	if (host->mmc->caps | MMC_CAP_NONREMOVABLE) {
28601ebea1bSChristian Daudt 		ret = sdhci_bcm_kona_sd_card_emulate(host, 1);
28701ebea1bSChristian Daudt 		if (ret) {
28801ebea1bSChristian Daudt 			dev_err(dev,
28901ebea1bSChristian Daudt 				"unable to emulate card insertion\n");
29001ebea1bSChristian Daudt 			goto err_remove_host;
29101ebea1bSChristian Daudt 		}
29201ebea1bSChristian Daudt 	}
29301ebea1bSChristian Daudt 	/*
29401ebea1bSChristian Daudt 	 * Since the card detection GPIO interrupt is configured to be
29501ebea1bSChristian Daudt 	 * edge sensitive, check the initial GPIO value here, emulate
29601ebea1bSChristian Daudt 	 * only if the card is present
29701ebea1bSChristian Daudt 	 */
29801ebea1bSChristian Daudt 	if (mmc_gpio_get_cd(host->mmc) > 0)
29901ebea1bSChristian Daudt 		sdhci_bcm_kona_sd_card_emulate(host, 1);
30001ebea1bSChristian Daudt 
30101ebea1bSChristian Daudt 	dev_dbg(dev, "initialized properly\n");
30201ebea1bSChristian Daudt 	return 0;
30301ebea1bSChristian Daudt 
30401ebea1bSChristian Daudt err_remove_host:
30501ebea1bSChristian Daudt 	sdhci_remove_host(host, 0);
30601ebea1bSChristian Daudt 
30701ebea1bSChristian Daudt err_reset:
30801ebea1bSChristian Daudt 	sdhci_bcm_kona_sd_reset(host);
30901ebea1bSChristian Daudt 
31001ebea1bSChristian Daudt err_pltfm_free:
31101ebea1bSChristian Daudt 	sdhci_pltfm_free(pdev);
31201ebea1bSChristian Daudt 
31301ebea1bSChristian Daudt 	dev_err(dev, "Probing of sdhci-pltfm failed: %d\n", ret);
31401ebea1bSChristian Daudt 	return ret;
31501ebea1bSChristian Daudt }
31601ebea1bSChristian Daudt 
31701ebea1bSChristian Daudt static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev)
31801ebea1bSChristian Daudt {
31901ebea1bSChristian Daudt 	struct sdhci_host *host = platform_get_drvdata(pdev);
32001ebea1bSChristian Daudt 	int dead;
32101ebea1bSChristian Daudt 	u32 scratch;
32201ebea1bSChristian Daudt 
32301ebea1bSChristian Daudt 	dead = 0;
32401ebea1bSChristian Daudt 	scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
32501ebea1bSChristian Daudt 	if (scratch == (u32)-1)
32601ebea1bSChristian Daudt 		dead = 1;
32701ebea1bSChristian Daudt 	sdhci_remove_host(host, dead);
32801ebea1bSChristian Daudt 
32901ebea1bSChristian Daudt 	sdhci_free_host(host);
33001ebea1bSChristian Daudt 
33101ebea1bSChristian Daudt 	return 0;
33201ebea1bSChristian Daudt }
33301ebea1bSChristian Daudt 
33401ebea1bSChristian Daudt static struct platform_driver sdhci_bcm_kona_driver = {
33501ebea1bSChristian Daudt 	.driver		= {
33601ebea1bSChristian Daudt 		.name	= "sdhci-kona",
33701ebea1bSChristian Daudt 		.owner	= THIS_MODULE,
33801ebea1bSChristian Daudt 		.pm	= SDHCI_PLTFM_PMOPS,
33901ebea1bSChristian Daudt 		.of_match_table = of_match_ptr(sdhci_bcm_kona_of_match),
34001ebea1bSChristian Daudt 	},
34101ebea1bSChristian Daudt 	.probe		= sdhci_bcm_kona_probe,
34201ebea1bSChristian Daudt 	.remove		= __exit_p(sdhci_bcm_kona_remove),
34301ebea1bSChristian Daudt };
34401ebea1bSChristian Daudt module_platform_driver(sdhci_bcm_kona_driver);
34501ebea1bSChristian Daudt 
34601ebea1bSChristian Daudt MODULE_DESCRIPTION("SDHCI driver for Broadcom Kona platform");
34701ebea1bSChristian Daudt MODULE_AUTHOR("Broadcom");
34801ebea1bSChristian Daudt MODULE_LICENSE("GPL v2");
349