sdhci-msm.c revision 2137f5d3b8e8e04cff06194cacd0f6357495ac94
1/*
2 * drivers/mmc/host/sdhci-msm.c - Qualcomm SDHCI Platform driver
3 *
4 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and
8 * only version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/of_device.h>
19#include <linux/delay.h>
20#include <linux/mmc/mmc.h>
21#include <linux/slab.h>
22
23#include "sdhci-pltfm.h"
24
25#define CORE_HC_MODE		0x78
26#define HC_MODE_EN		0x1
27#define CORE_POWER		0x0
28#define CORE_SW_RST		BIT(7)
29
30#define MAX_PHASES		16
31#define CORE_DLL_LOCK		BIT(7)
32#define CORE_DLL_EN		BIT(16)
33#define CORE_CDR_EN		BIT(17)
34#define CORE_CK_OUT_EN		BIT(18)
35#define CORE_CDR_EXT_EN		BIT(19)
36#define CORE_DLL_PDN		BIT(29)
37#define CORE_DLL_RST		BIT(30)
38#define CORE_DLL_CONFIG		0x100
39#define CORE_DLL_STATUS		0x108
40
41#define CORE_VENDOR_SPEC	0x10c
42#define CORE_CLK_PWRSAVE	BIT(1)
43
44#define CDR_SELEXT_SHIFT	20
45#define CDR_SELEXT_MASK		(0xf << CDR_SELEXT_SHIFT)
46#define CMUX_SHIFT_PHASE_SHIFT	24
47#define CMUX_SHIFT_PHASE_MASK	(7 << CMUX_SHIFT_PHASE_SHIFT)
48
49static const u32 tuning_block_64[] = {
50	0x00ff0fff, 0xccc3ccff, 0xffcc3cc3, 0xeffefffe,
51	0xddffdfff, 0xfbfffbff, 0xff7fffbf, 0xefbdf777,
52	0xf0fff0ff, 0x3cccfc0f, 0xcfcc33cc, 0xeeffefff,
53	0xfdfffdff, 0xffbfffdf, 0xfff7ffbb, 0xde7b7ff7
54};
55
56static const u32 tuning_block_128[] = {
57	0xff00ffff, 0x0000ffff, 0xccccffff, 0xcccc33cc,
58	0xcc3333cc, 0xffffcccc, 0xffffeeff, 0xffeeeeff,
59	0xffddffff, 0xddddffff, 0xbbffffff, 0xbbffffff,
60	0xffffffbb, 0xffffff77, 0x77ff7777, 0xffeeddbb,
61	0x00ffffff, 0x00ffffff, 0xccffff00, 0xcc33cccc,
62	0x3333cccc, 0xffcccccc, 0xffeeffff, 0xeeeeffff,
63	0xddffffff, 0xddffffff, 0xffffffdd, 0xffffffbb,
64	0xffffbbbb, 0xffff77ff, 0xff7777ff, 0xeeddbb77
65};
66
67struct sdhci_msm_host {
68	struct platform_device *pdev;
69	void __iomem *core_mem;	/* MSM SDCC mapped address */
70	struct clk *clk;	/* main SD/MMC bus clock */
71	struct clk *pclk;	/* SDHC peripheral bus clock */
72	struct clk *bus_clk;	/* SDHC bus voter clock */
73	struct mmc_host *mmc;
74	struct sdhci_pltfm_data sdhci_msm_pdata;
75};
76
77/* Platform specific tuning */
78static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll)
79{
80	u32 wait_cnt = 50;
81	u8 ck_out_en;
82	struct mmc_host *mmc = host->mmc;
83
84	/* Poll for CK_OUT_EN bit.  max. poll time = 50us */
85	ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
86			CORE_CK_OUT_EN);
87
88	while (ck_out_en != poll) {
89		if (--wait_cnt == 0) {
90			dev_err(mmc_dev(mmc), "%s: CK_OUT_EN bit is not %d\n",
91			       mmc_hostname(mmc), poll);
92			return -ETIMEDOUT;
93		}
94		udelay(1);
95
96		ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
97				CORE_CK_OUT_EN);
98	}
99
100	return 0;
101}
102
103static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
104{
105	int rc;
106	static const u8 grey_coded_phase_table[] = {
107		0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4,
108		0xc, 0xd, 0xf, 0xe, 0xa, 0xb, 0x9, 0x8
109	};
110	unsigned long flags;
111	u32 config;
112	struct mmc_host *mmc = host->mmc;
113
114	spin_lock_irqsave(&host->lock, flags);
115
116	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
117	config &= ~(CORE_CDR_EN | CORE_CK_OUT_EN);
118	config |= (CORE_CDR_EXT_EN | CORE_DLL_EN);
119	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
120
121	/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '0' */
122	rc = msm_dll_poll_ck_out_en(host, 0);
123	if (rc)
124		goto err_out;
125
126	/*
127	 * Write the selected DLL clock output phase (0 ... 15)
128	 * to CDR_SELEXT bit field of DLL_CONFIG register.
129	 */
130	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
131	config &= ~CDR_SELEXT_MASK;
132	config |= grey_coded_phase_table[phase] << CDR_SELEXT_SHIFT;
133	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
134
135	/* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */
136	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
137			| CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
138
139	/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */
140	rc = msm_dll_poll_ck_out_en(host, 1);
141	if (rc)
142		goto err_out;
143
144	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
145	config |= CORE_CDR_EN;
146	config &= ~CORE_CDR_EXT_EN;
147	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
148	goto out;
149
150err_out:
151	dev_err(mmc_dev(mmc), "%s: Failed to set DLL phase: %d\n",
152	       mmc_hostname(mmc), phase);
153out:
154	spin_unlock_irqrestore(&host->lock, flags);
155	return rc;
156}
157
158/*
159 * Find out the greatest range of consecuitive selected
160 * DLL clock output phases that can be used as sampling
161 * setting for SD3.0 UHS-I card read operation (in SDR104
162 * timing mode) or for eMMC4.5 card read operation (in HS200
163 * timing mode).
164 * Select the 3/4 of the range and configure the DLL with the
165 * selected DLL clock output phase.
166 */
167
168static int msm_find_most_appropriate_phase(struct sdhci_host *host,
169					   u8 *phase_table, u8 total_phases)
170{
171	int ret;
172	u8 ranges[MAX_PHASES][MAX_PHASES] = { {0}, {0} };
173	u8 phases_per_row[MAX_PHASES] = { 0 };
174	int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0;
175	int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0;
176	bool phase_0_found = false, phase_15_found = false;
177	struct mmc_host *mmc = host->mmc;
178
179	if (!total_phases || (total_phases > MAX_PHASES)) {
180		dev_err(mmc_dev(mmc), "%s: Invalid argument: total_phases=%d\n",
181		       mmc_hostname(mmc), total_phases);
182		return -EINVAL;
183	}
184
185	for (cnt = 0; cnt < total_phases; cnt++) {
186		ranges[row_index][col_index] = phase_table[cnt];
187		phases_per_row[row_index] += 1;
188		col_index++;
189
190		if ((cnt + 1) == total_phases) {
191			continue;
192		/* check if next phase in phase_table is consecutive or not */
193		} else if ((phase_table[cnt] + 1) != phase_table[cnt + 1]) {
194			row_index++;
195			col_index = 0;
196		}
197	}
198
199	if (row_index >= MAX_PHASES)
200		return -EINVAL;
201
202	/* Check if phase-0 is present in first valid window? */
203	if (!ranges[0][0]) {
204		phase_0_found = true;
205		phase_0_raw_index = 0;
206		/* Check if cycle exist between 2 valid windows */
207		for (cnt = 1; cnt <= row_index; cnt++) {
208			if (phases_per_row[cnt]) {
209				for (i = 0; i < phases_per_row[cnt]; i++) {
210					if (ranges[cnt][i] == 15) {
211						phase_15_found = true;
212						phase_15_raw_index = cnt;
213						break;
214					}
215				}
216			}
217		}
218	}
219
220	/* If 2 valid windows form cycle then merge them as single window */
221	if (phase_0_found && phase_15_found) {
222		/* number of phases in raw where phase 0 is present */
223		u8 phases_0 = phases_per_row[phase_0_raw_index];
224		/* number of phases in raw where phase 15 is present */
225		u8 phases_15 = phases_per_row[phase_15_raw_index];
226
227		if (phases_0 + phases_15 >= MAX_PHASES)
228			/*
229			 * If there are more than 1 phase windows then total
230			 * number of phases in both the windows should not be
231			 * more than or equal to MAX_PHASES.
232			 */
233			return -EINVAL;
234
235		/* Merge 2 cyclic windows */
236		i = phases_15;
237		for (cnt = 0; cnt < phases_0; cnt++) {
238			ranges[phase_15_raw_index][i] =
239			    ranges[phase_0_raw_index][cnt];
240			if (++i >= MAX_PHASES)
241				break;
242		}
243
244		phases_per_row[phase_0_raw_index] = 0;
245		phases_per_row[phase_15_raw_index] = phases_15 + phases_0;
246	}
247
248	for (cnt = 0; cnt <= row_index; cnt++) {
249		if (phases_per_row[cnt] > curr_max) {
250			curr_max = phases_per_row[cnt];
251			selected_row_index = cnt;
252		}
253	}
254
255	i = (curr_max * 3) / 4;
256	if (i)
257		i--;
258
259	ret = ranges[selected_row_index][i];
260
261	if (ret >= MAX_PHASES) {
262		ret = -EINVAL;
263		dev_err(mmc_dev(mmc), "%s: Invalid phase selected=%d\n",
264		       mmc_hostname(mmc), ret);
265	}
266
267	return ret;
268}
269
270static inline void msm_cm_dll_set_freq(struct sdhci_host *host)
271{
272	u32 mclk_freq = 0, config;
273
274	/* Program the MCLK value to MCLK_FREQ bit field */
275	if (host->clock <= 112000000)
276		mclk_freq = 0;
277	else if (host->clock <= 125000000)
278		mclk_freq = 1;
279	else if (host->clock <= 137000000)
280		mclk_freq = 2;
281	else if (host->clock <= 150000000)
282		mclk_freq = 3;
283	else if (host->clock <= 162000000)
284		mclk_freq = 4;
285	else if (host->clock <= 175000000)
286		mclk_freq = 5;
287	else if (host->clock <= 187000000)
288		mclk_freq = 6;
289	else if (host->clock <= 200000000)
290		mclk_freq = 7;
291
292	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
293	config &= ~CMUX_SHIFT_PHASE_MASK;
294	config |= mclk_freq << CMUX_SHIFT_PHASE_SHIFT;
295	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
296}
297
298/* Initialize the DLL (Programmable Delay Line) */
299static int msm_init_cm_dll(struct sdhci_host *host)
300{
301	struct mmc_host *mmc = host->mmc;
302	int wait_cnt = 50;
303	unsigned long flags;
304
305	spin_lock_irqsave(&host->lock, flags);
306
307	/*
308	 * Make sure that clock is always enabled when DLL
309	 * tuning is in progress. Keeping PWRSAVE ON may
310	 * turn off the clock.
311	 */
312	writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
313			& ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC);
314
315	/* Write 1 to DLL_RST bit of DLL_CONFIG register */
316	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
317			| CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
318
319	/* Write 1 to DLL_PDN bit of DLL_CONFIG register */
320	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
321			| CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
322	msm_cm_dll_set_freq(host);
323
324	/* Write 0 to DLL_RST bit of DLL_CONFIG register */
325	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
326			& ~CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
327
328	/* Write 0 to DLL_PDN bit of DLL_CONFIG register */
329	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
330			& ~CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
331
332	/* Set DLL_EN bit to 1. */
333	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
334			| CORE_DLL_EN), host->ioaddr + CORE_DLL_CONFIG);
335
336	/* Set CK_OUT_EN bit to 1. */
337	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
338			| CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
339
340	/* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */
341	while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) &
342		 CORE_DLL_LOCK)) {
343		/* max. wait for 50us sec for LOCK bit to be set */
344		if (--wait_cnt == 0) {
345			dev_err(mmc_dev(mmc), "%s: DLL failed to LOCK\n",
346			       mmc_hostname(mmc));
347			spin_unlock_irqrestore(&host->lock, flags);
348			return -ETIMEDOUT;
349		}
350		udelay(1);
351	}
352
353	spin_unlock_irqrestore(&host->lock, flags);
354	return 0;
355}
356
357static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
358{
359	int tuning_seq_cnt = 3;
360	u8 phase, *data_buf, tuned_phases[16], tuned_phase_cnt = 0;
361	const u32 *tuning_block_pattern = tuning_block_64;
362	int size = sizeof(tuning_block_64);	/* Pattern size in bytes */
363	int rc;
364	struct mmc_host *mmc = host->mmc;
365	struct mmc_ios ios = host->mmc->ios;
366
367	/*
368	 * Tuning is required for SDR104, HS200 and HS400 cards and
369	 * if clock frequency is greater than 100MHz in these modes.
370	 */
371	if (host->clock <= 100 * 1000 * 1000 ||
372	    !((ios.timing == MMC_TIMING_MMC_HS200) ||
373	      (ios.timing == MMC_TIMING_UHS_SDR104)))
374		return 0;
375
376	if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) &&
377	    (mmc->ios.bus_width == MMC_BUS_WIDTH_8)) {
378		tuning_block_pattern = tuning_block_128;
379		size = sizeof(tuning_block_128);
380	}
381
382	data_buf = kmalloc(size, GFP_KERNEL);
383	if (!data_buf)
384		return -ENOMEM;
385
386retry:
387	/* First of all reset the tuning block */
388	rc = msm_init_cm_dll(host);
389	if (rc)
390		goto out;
391
392	phase = 0;
393	do {
394		struct mmc_command cmd = { 0 };
395		struct mmc_data data = { 0 };
396		struct mmc_request mrq = {
397			.cmd = &cmd,
398			.data = &data
399		};
400		struct scatterlist sg;
401
402		/* Set the phase in delay line hw block */
403		rc = msm_config_cm_dll_phase(host, phase);
404		if (rc)
405			goto out;
406
407		cmd.opcode = opcode;
408		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
409
410		data.blksz = size;
411		data.blocks = 1;
412		data.flags = MMC_DATA_READ;
413		data.timeout_ns = NSEC_PER_SEC;	/* 1 second */
414
415		data.sg = &sg;
416		data.sg_len = 1;
417		sg_init_one(&sg, data_buf, size);
418		memset(data_buf, 0, size);
419		mmc_wait_for_req(mmc, &mrq);
420
421		if (!cmd.error && !data.error &&
422		    !memcmp(data_buf, tuning_block_pattern, size)) {
423			/* Tuning is successful at this tuning point */
424			tuned_phases[tuned_phase_cnt++] = phase;
425			dev_dbg(mmc_dev(mmc), "%s: Found good phase = %d\n",
426				 mmc_hostname(mmc), phase);
427		}
428	} while (++phase < ARRAY_SIZE(tuned_phases));
429
430	if (tuned_phase_cnt) {
431		rc = msm_find_most_appropriate_phase(host, tuned_phases,
432						     tuned_phase_cnt);
433		if (rc < 0)
434			goto out;
435		else
436			phase = rc;
437
438		/*
439		 * Finally set the selected phase in delay
440		 * line hw block.
441		 */
442		rc = msm_config_cm_dll_phase(host, phase);
443		if (rc)
444			goto out;
445		dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n",
446			 mmc_hostname(mmc), phase);
447	} else {
448		if (--tuning_seq_cnt)
449			goto retry;
450		/* Tuning failed */
451		dev_dbg(mmc_dev(mmc), "%s: No tuning point found\n",
452		       mmc_hostname(mmc));
453		rc = -EIO;
454	}
455
456out:
457	kfree(data_buf);
458	return rc;
459}
460
461static const struct of_device_id sdhci_msm_dt_match[] = {
462	{ .compatible = "qcom,sdhci-msm-v4" },
463	{},
464};
465
466MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match);
467
468static struct sdhci_ops sdhci_msm_ops = {
469	.platform_execute_tuning = sdhci_msm_execute_tuning,
470	.reset = sdhci_reset,
471	.set_clock = sdhci_set_clock,
472	.set_bus_width = sdhci_set_bus_width,
473	.set_uhs_signaling = sdhci_set_uhs_signaling,
474};
475
476static int sdhci_msm_probe(struct platform_device *pdev)
477{
478	struct sdhci_host *host;
479	struct sdhci_pltfm_host *pltfm_host;
480	struct sdhci_msm_host *msm_host;
481	struct resource *core_memres;
482	int ret;
483	u16 host_version;
484
485	msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL);
486	if (!msm_host)
487		return -ENOMEM;
488
489	msm_host->sdhci_msm_pdata.ops = &sdhci_msm_ops;
490	host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0);
491	if (IS_ERR(host))
492		return PTR_ERR(host);
493
494	pltfm_host = sdhci_priv(host);
495	pltfm_host->priv = msm_host;
496	msm_host->mmc = host->mmc;
497	msm_host->pdev = pdev;
498
499	ret = mmc_of_parse(host->mmc);
500	if (ret)
501		goto pltfm_free;
502
503	sdhci_get_of_property(pdev);
504
505	/* Setup SDCC bus voter clock. */
506	msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus");
507	if (!IS_ERR(msm_host->bus_clk)) {
508		/* Vote for max. clk rate for max. performance */
509		ret = clk_set_rate(msm_host->bus_clk, INT_MAX);
510		if (ret)
511			goto pltfm_free;
512		ret = clk_prepare_enable(msm_host->bus_clk);
513		if (ret)
514			goto pltfm_free;
515	}
516
517	/* Setup main peripheral bus clock */
518	msm_host->pclk = devm_clk_get(&pdev->dev, "iface");
519	if (IS_ERR(msm_host->pclk)) {
520		ret = PTR_ERR(msm_host->pclk);
521		dev_err(&pdev->dev, "Perpheral clk setup failed (%d)\n", ret);
522		goto bus_clk_disable;
523	}
524
525	ret = clk_prepare_enable(msm_host->pclk);
526	if (ret)
527		goto bus_clk_disable;
528
529	/* Setup SDC MMC clock */
530	msm_host->clk = devm_clk_get(&pdev->dev, "core");
531	if (IS_ERR(msm_host->clk)) {
532		ret = PTR_ERR(msm_host->clk);
533		dev_err(&pdev->dev, "SDC MMC clk setup failed (%d)\n", ret);
534		goto pclk_disable;
535	}
536
537	ret = clk_prepare_enable(msm_host->clk);
538	if (ret)
539		goto pclk_disable;
540
541	core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
542	msm_host->core_mem = devm_ioremap_resource(&pdev->dev, core_memres);
543
544	if (IS_ERR(msm_host->core_mem)) {
545		dev_err(&pdev->dev, "Failed to remap registers\n");
546		ret = PTR_ERR(msm_host->core_mem);
547		goto clk_disable;
548	}
549
550	/* Reset the core and Enable SDHC mode */
551	writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) |
552		       CORE_SW_RST, msm_host->core_mem + CORE_POWER);
553
554	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
555	usleep_range(1000, 5000);
556	if (readl(msm_host->core_mem + CORE_POWER) & CORE_SW_RST) {
557		dev_err(&pdev->dev, "Stuck in reset\n");
558		ret = -ETIMEDOUT;
559		goto clk_disable;
560	}
561
562	/* Set HC_MODE_EN bit in HC_MODE register */
563	writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
564
565	host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
566	host->quirks |= SDHCI_QUIRK_SINGLE_POWER_WRITE;
567
568	host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
569	dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
570		host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >>
571			       SDHCI_VENDOR_VER_SHIFT));
572
573	ret = sdhci_add_host(host);
574	if (ret)
575		goto clk_disable;
576
577	return 0;
578
579clk_disable:
580	clk_disable_unprepare(msm_host->clk);
581pclk_disable:
582	clk_disable_unprepare(msm_host->pclk);
583bus_clk_disable:
584	if (!IS_ERR(msm_host->bus_clk))
585		clk_disable_unprepare(msm_host->bus_clk);
586pltfm_free:
587	sdhci_pltfm_free(pdev);
588	return ret;
589}
590
591static int sdhci_msm_remove(struct platform_device *pdev)
592{
593	struct sdhci_host *host = platform_get_drvdata(pdev);
594	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
595	struct sdhci_msm_host *msm_host = pltfm_host->priv;
596	int dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) ==
597		    0xffffffff);
598
599	sdhci_remove_host(host, dead);
600	sdhci_pltfm_free(pdev);
601	clk_disable_unprepare(msm_host->clk);
602	clk_disable_unprepare(msm_host->pclk);
603	if (!IS_ERR(msm_host->bus_clk))
604		clk_disable_unprepare(msm_host->bus_clk);
605	return 0;
606}
607
608static struct platform_driver sdhci_msm_driver = {
609	.probe = sdhci_msm_probe,
610	.remove = sdhci_msm_remove,
611	.driver = {
612		   .name = "sdhci_msm",
613		   .of_match_table = sdhci_msm_dt_match,
614	},
615};
616
617module_platform_driver(sdhci_msm_driver);
618
619MODULE_DESCRIPTION("Qualcomm Secure Digital Host Controller Interface driver");
620MODULE_LICENSE("GPL v2");
621