brintos

brintos / linux-shallow public Read only

0
0
Text · 20.3 KiB · a71d56c Raw
792 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* linux/drivers/mmc/host/sdhci-s3c.c3 *4 * Copyright 2008 Openmoko Inc.5 * Copyright 2008 Simtec Electronics6 *      Ben Dooks <ben@simtec.co.uk>7 *      http://armlinux.simtec.co.uk/8 *9 * SDHCI (HSMMC) support for Samsung SoC10 */11 12#include <linux/spinlock.h>13#include <linux/delay.h>14#include <linux/dma-mapping.h>15#include <linux/platform_device.h>16#include <linux/platform_data/mmc-sdhci-s3c.h>17#include <linux/slab.h>18#include <linux/clk.h>19#include <linux/io.h>20#include <linux/module.h>21#include <linux/of.h>22#include <linux/pm.h>23#include <linux/pm_runtime.h>24 25#include <linux/mmc/host.h>26 27#include "sdhci.h"28 29#define MAX_BUS_CLK	(4)30 31#define S3C_SDHCI_CONTROL2			(0x80)32#define S3C_SDHCI_CONTROL3			(0x84)33#define S3C64XX_SDHCI_CONTROL4			(0x8C)34 35#define S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR	BIT(31)36#define S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK		BIT(30)37#define S3C_SDHCI_CTRL2_CDINVRXD3		BIT(29)38#define S3C_SDHCI_CTRL2_SLCARDOUT		BIT(28)39 40#define S3C_SDHCI_CTRL2_FLTCLKSEL_MASK		(0xf << 24)41#define S3C_SDHCI_CTRL2_FLTCLKSEL_SHIFT		(24)42#define S3C_SDHCI_CTRL2_FLTCLKSEL(_x)		((_x) << 24)43 44#define S3C_SDHCI_CTRL2_LVLDAT_MASK		(0xff << 16)45#define S3C_SDHCI_CTRL2_LVLDAT_SHIFT		(16)46#define S3C_SDHCI_CTRL2_LVLDAT(_x)		((_x) << 16)47 48#define S3C_SDHCI_CTRL2_ENFBCLKTX		BIT(15)49#define S3C_SDHCI_CTRL2_ENFBCLKRX		BIT(14)50#define S3C_SDHCI_CTRL2_SDCDSEL			BIT(13)51#define S3C_SDHCI_CTRL2_SDSIGPC			BIT(12)52#define S3C_SDHCI_CTRL2_ENBUSYCHKTXSTART	BIT(11)53 54#define S3C_SDHCI_CTRL2_DFCNT_MASK		(0x3 << 9)55#define S3C_SDHCI_CTRL2_DFCNT_SHIFT		(9)56#define S3C_SDHCI_CTRL2_DFCNT_NONE		(0x0 << 9)57#define S3C_SDHCI_CTRL2_DFCNT_4SDCLK		(0x1 << 9)58#define S3C_SDHCI_CTRL2_DFCNT_16SDCLK		(0x2 << 9)59#define S3C_SDHCI_CTRL2_DFCNT_64SDCLK		(0x3 << 9)60 61#define S3C_SDHCI_CTRL2_ENCLKOUTHOLD		BIT(8)62#define S3C_SDHCI_CTRL2_RWAITMODE		BIT(7)63#define S3C_SDHCI_CTRL2_DISBUFRD		BIT(6)64 65#define S3C_SDHCI_CTRL2_SELBASECLK_MASK		(0x3 << 4)66#define S3C_SDHCI_CTRL2_SELBASECLK_SHIFT	(4)67#define S3C_SDHCI_CTRL2_PWRSYNC			BIT(3)68#define S3C_SDHCI_CTRL2_ENCLKOUTMSKCON		BIT(1)69#define S3C_SDHCI_CTRL2_HWINITFIN		BIT(0)70 71#define S3C_SDHCI_CTRL3_FCSEL3			BIT(31)72#define S3C_SDHCI_CTRL3_FCSEL2			BIT(23)73#define S3C_SDHCI_CTRL3_FCSEL1			BIT(15)74#define S3C_SDHCI_CTRL3_FCSEL0			BIT(7)75 76#define S3C_SDHCI_CTRL3_FIA3_MASK		(0x7f << 24)77#define S3C_SDHCI_CTRL3_FIA3_SHIFT		(24)78#define S3C_SDHCI_CTRL3_FIA3(_x)		((_x) << 24)79 80#define S3C_SDHCI_CTRL3_FIA2_MASK		(0x7f << 16)81#define S3C_SDHCI_CTRL3_FIA2_SHIFT		(16)82#define S3C_SDHCI_CTRL3_FIA2(_x)		((_x) << 16)83 84#define S3C_SDHCI_CTRL3_FIA1_MASK		(0x7f << 8)85#define S3C_SDHCI_CTRL3_FIA1_SHIFT		(8)86#define S3C_SDHCI_CTRL3_FIA1(_x)		((_x) << 8)87 88#define S3C_SDHCI_CTRL3_FIA0_MASK		(0x7f << 0)89#define S3C_SDHCI_CTRL3_FIA0_SHIFT		(0)90#define S3C_SDHCI_CTRL3_FIA0(_x)		((_x) << 0)91 92#define S3C64XX_SDHCI_CONTROL4_DRIVE_MASK	(0x3 << 16)93#define S3C64XX_SDHCI_CONTROL4_DRIVE_SHIFT	(16)94#define S3C64XX_SDHCI_CONTROL4_DRIVE_2mA	(0x0 << 16)95#define S3C64XX_SDHCI_CONTROL4_DRIVE_4mA	(0x1 << 16)96#define S3C64XX_SDHCI_CONTROL4_DRIVE_7mA	(0x2 << 16)97#define S3C64XX_SDHCI_CONTROL4_DRIVE_9mA	(0x3 << 16)98 99#define S3C64XX_SDHCI_CONTROL4_BUSY		(1)100 101/**102 * struct sdhci_s3c - S3C SDHCI instance103 * @host: The SDHCI host created104 * @pdev: The platform device we where created from.105 * @ioarea: The resource created when we claimed the IO area.106 * @pdata: The platform data for this controller.107 * @cur_clk: The index of the current bus clock.108 * @ext_cd_irq: External card detect interrupt.109 * @clk_io: The clock for the internal bus interface.110 * @clk_rates: Clock frequencies.111 * @clk_bus: The clocks that are available for the SD/MMC bus clock.112 * @no_divider: No or non-standard internal clock divider.113 */114struct sdhci_s3c {115	struct sdhci_host	*host;116	struct platform_device	*pdev;117	struct resource		*ioarea;118	struct s3c_sdhci_platdata *pdata;119	int			cur_clk;120	int			ext_cd_irq;121 122	struct clk		*clk_io;123	struct clk		*clk_bus[MAX_BUS_CLK];124	unsigned long		clk_rates[MAX_BUS_CLK];125 126	bool			no_divider;127};128 129/**130 * struct sdhci_s3c_drv_data - S3C SDHCI platform specific driver data131 * @sdhci_quirks: sdhci host specific quirks.132 * @no_divider: no or non-standard internal clock divider.133 * @ops: sdhci_ops to use for this variant134 *135 * Specifies platform specific configuration of sdhci controller.136 * Note: A structure for driver specific platform data is used for future137 * expansion of its usage.138 */139struct sdhci_s3c_drv_data {140	unsigned int		sdhci_quirks;141	bool			no_divider;142	const struct sdhci_ops	*ops;143};144 145static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)146{147	return sdhci_priv(host);148}149 150/**151 * sdhci_s3c_get_max_clk - callback to get maximum clock frequency.152 * @host: The SDHCI host instance.153 *154 * Callback to return the maximum clock rate acheivable by the controller.155*/156static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)157{158	struct sdhci_s3c *ourhost = to_s3c(host);159	unsigned long rate, max = 0;160	int src;161 162	for (src = 0; src < MAX_BUS_CLK; src++) {163		rate = ourhost->clk_rates[src];164		if (rate > max)165			max = rate;166	}167 168	return max;169}170 171/**172 * sdhci_s3c_consider_clock - consider one the bus clocks for current setting173 * @ourhost: Our SDHCI instance.174 * @src: The source clock index.175 * @wanted: The clock frequency wanted.176 */177static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,178					     unsigned int src,179					     unsigned int wanted)180{181	unsigned long rate;182	struct clk *clksrc = ourhost->clk_bus[src];183	int shift;184 185	if (IS_ERR(clksrc))186		return UINT_MAX;187 188	/*189	 * If controller uses a non-standard clock division, find the best clock190	 * speed possible with selected clock source and skip the division.191	 */192	if (ourhost->no_divider) {193		rate = clk_round_rate(clksrc, wanted);194		return wanted - rate;195	}196 197	rate = ourhost->clk_rates[src];198 199	for (shift = 0; shift <= 8; ++shift) {200		if ((rate >> shift) <= wanted)201			break;202	}203 204	if (shift > 8) {205		dev_dbg(&ourhost->pdev->dev,206			"clk %d: rate %ld, min rate %lu > wanted %u\n",207			src, rate, rate / 256, wanted);208		return UINT_MAX;209	}210 211	dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n",212		src, rate, wanted, rate >> shift);213 214	return wanted - (rate >> shift);215}216 217/**218 * sdhci_s3c_set_clock - callback on clock change219 * @host: The SDHCI host being changed220 * @clock: The clock rate being requested.221 *222 * When the card's clock is going to be changed, look at the new frequency223 * and find the best clock source to go with it.224*/225static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)226{227	struct sdhci_s3c *ourhost = to_s3c(host);228	unsigned int best = UINT_MAX;229	unsigned int delta;230	int best_src = 0;231	int src;232	u32 ctrl;233 234	host->mmc->actual_clock = 0;235 236	/* don't bother if the clock is going off. */237	if (clock == 0) {238		sdhci_set_clock(host, clock);239		return;240	}241 242	for (src = 0; src < MAX_BUS_CLK; src++) {243		delta = sdhci_s3c_consider_clock(ourhost, src, clock);244		if (delta < best) {245			best = delta;246			best_src = src;247		}248	}249 250	dev_dbg(&ourhost->pdev->dev,251		"selected source %d, clock %d, delta %d\n",252		 best_src, clock, best);253 254	/* select the new clock source */255	if (ourhost->cur_clk != best_src) {256		struct clk *clk = ourhost->clk_bus[best_src];257 258		clk_prepare_enable(clk);259		if (ourhost->cur_clk >= 0)260			clk_disable_unprepare(261					ourhost->clk_bus[ourhost->cur_clk]);262 263		ourhost->cur_clk = best_src;264		host->max_clk = ourhost->clk_rates[best_src];265	}266 267	/* turn clock off to card before changing clock source */268	writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);269 270	ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);271	ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;272	ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;273	writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);274 275	/* reprogram default hardware configuration */276	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA,277		host->ioaddr + S3C64XX_SDHCI_CONTROL4);278 279	ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);280	ctrl |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |281		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |282		  S3C_SDHCI_CTRL2_ENFBCLKRX |283		  S3C_SDHCI_CTRL2_DFCNT_NONE |284		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);285	writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);286 287	/* reconfigure the controller for new clock rate */288	ctrl = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);289	if (clock < 25 * 1000000)290		ctrl |= (S3C_SDHCI_CTRL3_FCSEL3 | S3C_SDHCI_CTRL3_FCSEL2);291	writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL3);292 293	sdhci_set_clock(host, clock);294}295 296/**297 * sdhci_s3c_get_min_clock - callback to get minimal supported clock value298 * @host: The SDHCI host being queried299 *300 * To init mmc host properly a minimal clock value is needed. For high system301 * bus clock's values the standard formula gives values out of allowed range.302 * The clock still can be set to lower values, if clock source other then303 * system bus is selected.304*/305static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host)306{307	struct sdhci_s3c *ourhost = to_s3c(host);308	unsigned long rate, min = ULONG_MAX;309	int src;310 311	for (src = 0; src < MAX_BUS_CLK; src++) {312		rate = ourhost->clk_rates[src] / 256;313		if (!rate)314			continue;315		if (rate < min)316			min = rate;317	}318 319	return min;320}321 322/* sdhci_cmu_get_max_clk - callback to get maximum clock frequency.*/323static unsigned int sdhci_cmu_get_max_clock(struct sdhci_host *host)324{325	struct sdhci_s3c *ourhost = to_s3c(host);326	unsigned long rate, max = 0;327	int src;328 329	for (src = 0; src < MAX_BUS_CLK; src++) {330		struct clk *clk;331 332		clk = ourhost->clk_bus[src];333		if (IS_ERR(clk))334			continue;335 336		rate = clk_round_rate(clk, ULONG_MAX);337		if (rate > max)338			max = rate;339	}340 341	return max;342}343 344/* sdhci_cmu_get_min_clock - callback to get minimal supported clock value. */345static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)346{347	struct sdhci_s3c *ourhost = to_s3c(host);348	unsigned long rate, min = ULONG_MAX;349	int src;350 351	for (src = 0; src < MAX_BUS_CLK; src++) {352		struct clk *clk;353 354		clk = ourhost->clk_bus[src];355		if (IS_ERR(clk))356			continue;357 358		rate = clk_round_rate(clk, 0);359		if (rate < min)360			min = rate;361	}362 363	return min;364}365 366/* sdhci_cmu_set_clock - callback on clock change.*/367static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)368{369	struct sdhci_s3c *ourhost = to_s3c(host);370	struct device *dev = &ourhost->pdev->dev;371	unsigned long timeout;372	u16 clk = 0;373	int ret;374 375	host->mmc->actual_clock = 0;376 377	/* If the clock is going off, set to 0 at clock control register */378	if (clock == 0) {379		sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);380		return;381	}382 383	sdhci_s3c_set_clock(host, clock);384 385	/* Reset SD Clock Enable */386	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);387	clk &= ~SDHCI_CLOCK_CARD_EN;388	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);389 390	ret = clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);391	if (ret != 0) {392		dev_err(dev, "%s: failed to set clock rate %uHz\n",393			mmc_hostname(host->mmc), clock);394		return;395	}396 397	clk = SDHCI_CLOCK_INT_EN;398	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);399 400	/* Wait max 20 ms */401	timeout = 20;402	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))403		& SDHCI_CLOCK_INT_STABLE)) {404		if (timeout == 0) {405			dev_err(dev, "%s: Internal clock never stabilised.\n",406				mmc_hostname(host->mmc));407			return;408		}409		timeout--;410		mdelay(1);411	}412 413	clk |= SDHCI_CLOCK_CARD_EN;414	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);415}416 417static const struct sdhci_ops sdhci_s3c_ops_s3c6410 = {418	.get_max_clock		= sdhci_s3c_get_max_clk,419	.set_clock		= sdhci_s3c_set_clock,420	.get_min_clock		= sdhci_s3c_get_min_clock,421	.set_bus_width		= sdhci_set_bus_width,422	.reset			= sdhci_reset,423	.set_uhs_signaling	= sdhci_set_uhs_signaling,424};425 426static const struct sdhci_ops sdhci_s3c_ops_exynos4 __maybe_unused = {427	.get_max_clock		= sdhci_cmu_get_max_clock,428	.set_clock		= sdhci_cmu_set_clock,429	.get_min_clock		= sdhci_cmu_get_min_clock,430	.set_bus_width		= sdhci_set_bus_width,431	.reset			= sdhci_reset,432	.set_uhs_signaling	= sdhci_set_uhs_signaling,433};434 435#ifdef CONFIG_OF436static int sdhci_s3c_parse_dt(struct device *dev,437		struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)438{439	struct device_node *node = dev->of_node;440	u32 max_width;441 442	/* if the bus-width property is not specified, assume width as 1 */443	if (of_property_read_u32(node, "bus-width", &max_width))444		max_width = 1;445	pdata->max_width = max_width;446 447	/* get the card detection method */448	if (of_property_read_bool(node, "broken-cd")) {449		pdata->cd_type = S3C_SDHCI_CD_NONE;450		return 0;451	}452 453	if (of_property_read_bool(node, "non-removable")) {454		pdata->cd_type = S3C_SDHCI_CD_PERMANENT;455		return 0;456	}457 458	if (of_property_present(node, "cd-gpios"))459		return 0;460 461	/* assuming internal card detect that will be configured by pinctrl */462	pdata->cd_type = S3C_SDHCI_CD_INTERNAL;463	return 0;464}465#else466static int sdhci_s3c_parse_dt(struct device *dev,467		struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)468{469	return -EINVAL;470}471#endif472 473static inline const struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(474			struct platform_device *pdev)475{476#ifdef CONFIG_OF477	if (pdev->dev.of_node)478		return of_device_get_match_data(&pdev->dev);479#endif480	return (const struct sdhci_s3c_drv_data *)481			platform_get_device_id(pdev)->driver_data;482}483 484static int sdhci_s3c_probe(struct platform_device *pdev)485{486	struct s3c_sdhci_platdata *pdata;487	const struct sdhci_s3c_drv_data *drv_data;488	struct device *dev = &pdev->dev;489	struct sdhci_host *host;490	struct sdhci_s3c *sc;491	int ret, irq, ptr, clks;492 493	if (!pdev->dev.platform_data && !pdev->dev.of_node) {494		dev_err(dev, "no device data specified\n");495		return -ENOENT;496	}497 498	irq = platform_get_irq(pdev, 0);499	if (irq < 0)500		return irq;501 502	host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));503	if (IS_ERR(host)) {504		dev_err(dev, "sdhci_alloc_host() failed\n");505		return PTR_ERR(host);506	}507	sc = sdhci_priv(host);508 509	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);510	if (!pdata) {511		ret = -ENOMEM;512		goto err_pdata_io_clk;513	}514 515	if (pdev->dev.of_node) {516		ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata);517		if (ret)518			goto err_pdata_io_clk;519	} else {520		memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));521	}522 523	drv_data = sdhci_s3c_get_driver_data(pdev);524 525	sc->host = host;526	sc->pdev = pdev;527	sc->pdata = pdata;528	sc->cur_clk = -1;529 530	platform_set_drvdata(pdev, host);531 532	sc->clk_io = devm_clk_get(dev, "hsmmc");533	if (IS_ERR(sc->clk_io)) {534		dev_err(dev, "failed to get io clock\n");535		ret = PTR_ERR(sc->clk_io);536		goto err_pdata_io_clk;537	}538 539	/* enable the local io clock and keep it running for the moment. */540	clk_prepare_enable(sc->clk_io);541 542	for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {543		char name[14];544 545		snprintf(name, 14, "mmc_busclk.%d", ptr);546		sc->clk_bus[ptr] = devm_clk_get(dev, name);547		if (IS_ERR(sc->clk_bus[ptr]))548			continue;549 550		clks++;551		sc->clk_rates[ptr] = clk_get_rate(sc->clk_bus[ptr]);552 553		dev_info(dev, "clock source %d: %s (%ld Hz)\n",554				ptr, name, sc->clk_rates[ptr]);555	}556 557	if (clks == 0) {558		dev_err(dev, "failed to find any bus clocks\n");559		ret = -ENOENT;560		goto err_no_busclks;561	}562 563	host->ioaddr = devm_platform_ioremap_resource(pdev, 0);564	if (IS_ERR(host->ioaddr)) {565		ret = PTR_ERR(host->ioaddr);566		goto err_req_regs;567	}568 569	/* Ensure we have minimal gpio selected CMD/CLK/Detect */570	if (pdata->cfg_gpio)571		pdata->cfg_gpio(pdev, pdata->max_width);572 573	host->hw_name = "samsung-hsmmc";574	host->ops = &sdhci_s3c_ops_s3c6410;575	host->quirks = 0;576	host->quirks2 = 0;577	host->irq = irq;578 579	/* Setup quirks for the controller */580	host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;581	host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;582	if (drv_data) {583		host->quirks |= drv_data->sdhci_quirks;584		host->ops = drv_data->ops;585		sc->no_divider = drv_data->no_divider;586	}587 588#ifndef CONFIG_MMC_SDHCI_S3C_DMA589 590	/* we currently see overruns on errors, so disable the SDMA591	 * support as well. */592	host->quirks |= SDHCI_QUIRK_BROKEN_DMA;593 594#endif /* CONFIG_MMC_SDHCI_S3C_DMA */595 596	/* It seems we do not get an DATA transfer complete on non-busy597	 * transfers, not sure if this is a problem with this specific598	 * SDHCI block, or a missing configuration that needs to be set. */599	host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;600 601	/* This host supports the Auto CMD12 */602	host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;603 604	/* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */605	host->quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC;606 607	if (pdata->cd_type == S3C_SDHCI_CD_NONE ||608	    pdata->cd_type == S3C_SDHCI_CD_PERMANENT)609		host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;610 611	if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT)612		host->mmc->caps = MMC_CAP_NONREMOVABLE;613 614	switch (pdata->max_width) {615	case 8:616		host->mmc->caps |= MMC_CAP_8_BIT_DATA;617		fallthrough;618	case 4:619		host->mmc->caps |= MMC_CAP_4_BIT_DATA;620		break;621	}622 623	if (pdata->pm_caps)624		host->mmc->pm_caps |= pdata->pm_caps;625 626	host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR |627			 SDHCI_QUIRK_32BIT_DMA_SIZE);628 629	/* HSMMC on Samsung SoCs uses SDCLK as timeout clock */630	host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;631 632	/* It supports additional host capabilities if needed */633	if (pdata->host_caps)634		host->mmc->caps |= pdata->host_caps;635 636	if (pdata->host_caps2)637		host->mmc->caps2 |= pdata->host_caps2;638 639	pm_runtime_enable(&pdev->dev);640	pm_runtime_set_autosuspend_delay(&pdev->dev, 50);641	pm_runtime_use_autosuspend(&pdev->dev);642	pm_suspend_ignore_children(&pdev->dev, 1);643 644	ret = mmc_of_parse(host->mmc);645	if (ret)646		goto err_req_regs;647 648	ret = sdhci_add_host(host);649	if (ret)650		goto err_req_regs;651 652#ifdef CONFIG_PM653	if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)654		clk_disable_unprepare(sc->clk_io);655#endif656	return 0;657 658 err_req_regs:659	pm_runtime_disable(&pdev->dev);660 661 err_no_busclks:662	clk_disable_unprepare(sc->clk_io);663 664 err_pdata_io_clk:665	sdhci_free_host(host);666 667	return ret;668}669 670static void sdhci_s3c_remove(struct platform_device *pdev)671{672	struct sdhci_host *host =  platform_get_drvdata(pdev);673	struct sdhci_s3c *sc = sdhci_priv(host);674 675	if (sc->ext_cd_irq)676		free_irq(sc->ext_cd_irq, sc);677 678#ifdef CONFIG_PM679	if (sc->pdata->cd_type != S3C_SDHCI_CD_INTERNAL)680		clk_prepare_enable(sc->clk_io);681#endif682	sdhci_remove_host(host, 1);683 684	pm_runtime_dont_use_autosuspend(&pdev->dev);685	pm_runtime_disable(&pdev->dev);686 687	clk_disable_unprepare(sc->clk_io);688 689	sdhci_free_host(host);690}691 692#ifdef CONFIG_PM_SLEEP693static int sdhci_s3c_suspend(struct device *dev)694{695	struct sdhci_host *host = dev_get_drvdata(dev);696 697	if (host->tuning_mode != SDHCI_TUNING_MODE_3)698		mmc_retune_needed(host->mmc);699 700	return sdhci_suspend_host(host);701}702 703static int sdhci_s3c_resume(struct device *dev)704{705	struct sdhci_host *host = dev_get_drvdata(dev);706 707	return sdhci_resume_host(host);708}709#endif710 711#ifdef CONFIG_PM712static int sdhci_s3c_runtime_suspend(struct device *dev)713{714	struct sdhci_host *host = dev_get_drvdata(dev);715	struct sdhci_s3c *ourhost = to_s3c(host);716	struct clk *busclk = ourhost->clk_io;717	int ret;718 719	ret = sdhci_runtime_suspend_host(host);720 721	if (host->tuning_mode != SDHCI_TUNING_MODE_3)722		mmc_retune_needed(host->mmc);723 724	if (ourhost->cur_clk >= 0)725		clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);726	clk_disable_unprepare(busclk);727	return ret;728}729 730static int sdhci_s3c_runtime_resume(struct device *dev)731{732	struct sdhci_host *host = dev_get_drvdata(dev);733	struct sdhci_s3c *ourhost = to_s3c(host);734	struct clk *busclk = ourhost->clk_io;735	int ret;736 737	clk_prepare_enable(busclk);738	if (ourhost->cur_clk >= 0)739		clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);740	ret = sdhci_runtime_resume_host(host, 0);741	return ret;742}743#endif744 745static const struct dev_pm_ops sdhci_s3c_pmops = {746	SET_SYSTEM_SLEEP_PM_OPS(sdhci_s3c_suspend, sdhci_s3c_resume)747	SET_RUNTIME_PM_OPS(sdhci_s3c_runtime_suspend, sdhci_s3c_runtime_resume,748			   NULL)749};750 751static const struct platform_device_id sdhci_s3c_driver_ids[] = {752	{753		.name		= "s3c-sdhci",754		.driver_data	= (kernel_ulong_t)NULL,755	},756	{ }757};758MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids);759 760#ifdef CONFIG_OF761static const struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {762	.no_divider = true,763	.ops = &sdhci_s3c_ops_exynos4,764};765 766static const struct of_device_id sdhci_s3c_dt_match[] = {767	{ .compatible = "samsung,s3c6410-sdhci", },768	{ .compatible = "samsung,exynos4210-sdhci",769		.data = &exynos4_sdhci_drv_data },770	{},771};772MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match);773#endif774 775static struct platform_driver sdhci_s3c_driver = {776	.probe		= sdhci_s3c_probe,777	.remove_new	= sdhci_s3c_remove,778	.id_table	= sdhci_s3c_driver_ids,779	.driver		= {780		.name	= "s3c-sdhci",781		.probe_type = PROBE_PREFER_ASYNCHRONOUS,782		.of_match_table = of_match_ptr(sdhci_s3c_dt_match),783		.pm	= &sdhci_s3c_pmops,784	},785};786 787module_platform_driver(sdhci_s3c_driver);788 789MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue");790MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");791MODULE_LICENSE("GPL v2");792