xref: /openbmc/linux/drivers/mmc/host/sdhci-msm.c (revision 951b8c87)
10eb0d9f4SGeorgi Djakov /*
20eb0d9f4SGeorgi Djakov  * drivers/mmc/host/sdhci-msm.c - Qualcomm SDHCI Platform driver
30eb0d9f4SGeorgi Djakov  *
40eb0d9f4SGeorgi Djakov  * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
50eb0d9f4SGeorgi Djakov  *
60eb0d9f4SGeorgi Djakov  * This program is free software; you can redistribute it and/or modify
70eb0d9f4SGeorgi Djakov  * it under the terms of the GNU General Public License version 2 and
80eb0d9f4SGeorgi Djakov  * only version 2 as published by the Free Software Foundation.
90eb0d9f4SGeorgi Djakov  *
100eb0d9f4SGeorgi Djakov  * This program is distributed in the hope that it will be useful,
110eb0d9f4SGeorgi Djakov  * but WITHOUT ANY WARRANTY; without even the implied warranty of
120eb0d9f4SGeorgi Djakov  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
130eb0d9f4SGeorgi Djakov  * GNU General Public License for more details.
140eb0d9f4SGeorgi Djakov  *
150eb0d9f4SGeorgi Djakov  */
160eb0d9f4SGeorgi Djakov 
170eb0d9f4SGeorgi Djakov #include <linux/module.h>
180eb0d9f4SGeorgi Djakov #include <linux/of_device.h>
190eb0d9f4SGeorgi Djakov #include <linux/delay.h>
20415b5a75SGeorgi Djakov #include <linux/mmc/mmc.h>
21415b5a75SGeorgi Djakov #include <linux/slab.h>
220eb0d9f4SGeorgi Djakov 
230eb0d9f4SGeorgi Djakov #include "sdhci-pltfm.h"
240eb0d9f4SGeorgi Djakov 
253a3ad3e9SGeorgi Djakov #define CORE_MCI_VERSION		0x50
263a3ad3e9SGeorgi Djakov #define CORE_VERSION_MAJOR_SHIFT	28
273a3ad3e9SGeorgi Djakov #define CORE_VERSION_MAJOR_MASK		(0xf << CORE_VERSION_MAJOR_SHIFT)
283a3ad3e9SGeorgi Djakov #define CORE_VERSION_MINOR_MASK		0xff
293a3ad3e9SGeorgi Djakov 
300eb0d9f4SGeorgi Djakov #define CORE_HC_MODE		0x78
310eb0d9f4SGeorgi Djakov #define HC_MODE_EN		0x1
320eb0d9f4SGeorgi Djakov #define CORE_POWER		0x0
330eb0d9f4SGeorgi Djakov #define CORE_SW_RST		BIT(7)
340eb0d9f4SGeorgi Djakov 
35415b5a75SGeorgi Djakov #define MAX_PHASES		16
36415b5a75SGeorgi Djakov #define CORE_DLL_LOCK		BIT(7)
37415b5a75SGeorgi Djakov #define CORE_DLL_EN		BIT(16)
38415b5a75SGeorgi Djakov #define CORE_CDR_EN		BIT(17)
39415b5a75SGeorgi Djakov #define CORE_CK_OUT_EN		BIT(18)
40415b5a75SGeorgi Djakov #define CORE_CDR_EXT_EN		BIT(19)
41415b5a75SGeorgi Djakov #define CORE_DLL_PDN		BIT(29)
42415b5a75SGeorgi Djakov #define CORE_DLL_RST		BIT(30)
43415b5a75SGeorgi Djakov #define CORE_DLL_CONFIG		0x100
44415b5a75SGeorgi Djakov #define CORE_DLL_STATUS		0x108
45415b5a75SGeorgi Djakov 
46415b5a75SGeorgi Djakov #define CORE_VENDOR_SPEC	0x10c
47415b5a75SGeorgi Djakov #define CORE_CLK_PWRSAVE	BIT(1)
48415b5a75SGeorgi Djakov 
493a3ad3e9SGeorgi Djakov #define CORE_VENDOR_SPEC_CAPABILITIES0	0x11c
503a3ad3e9SGeorgi Djakov 
51415b5a75SGeorgi Djakov #define CDR_SELEXT_SHIFT	20
52415b5a75SGeorgi Djakov #define CDR_SELEXT_MASK		(0xf << CDR_SELEXT_SHIFT)
53415b5a75SGeorgi Djakov #define CMUX_SHIFT_PHASE_SHIFT	24
54415b5a75SGeorgi Djakov #define CMUX_SHIFT_PHASE_MASK	(7 << CMUX_SHIFT_PHASE_SHIFT)
55415b5a75SGeorgi Djakov 
560eb0d9f4SGeorgi Djakov struct sdhci_msm_host {
570eb0d9f4SGeorgi Djakov 	struct platform_device *pdev;
580eb0d9f4SGeorgi Djakov 	void __iomem *core_mem;	/* MSM SDCC mapped address */
590eb0d9f4SGeorgi Djakov 	struct clk *clk;	/* main SD/MMC bus clock */
600eb0d9f4SGeorgi Djakov 	struct clk *pclk;	/* SDHC peripheral bus clock */
610eb0d9f4SGeorgi Djakov 	struct clk *bus_clk;	/* SDHC bus voter clock */
620eb0d9f4SGeorgi Djakov 	struct mmc_host *mmc;
630eb0d9f4SGeorgi Djakov 	struct sdhci_pltfm_data sdhci_msm_pdata;
640eb0d9f4SGeorgi Djakov };
650eb0d9f4SGeorgi Djakov 
660eb0d9f4SGeorgi Djakov /* Platform specific tuning */
67415b5a75SGeorgi Djakov static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll)
68415b5a75SGeorgi Djakov {
69415b5a75SGeorgi Djakov 	u32 wait_cnt = 50;
70415b5a75SGeorgi Djakov 	u8 ck_out_en;
71415b5a75SGeorgi Djakov 	struct mmc_host *mmc = host->mmc;
72415b5a75SGeorgi Djakov 
73415b5a75SGeorgi Djakov 	/* Poll for CK_OUT_EN bit.  max. poll time = 50us */
74415b5a75SGeorgi Djakov 	ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
75415b5a75SGeorgi Djakov 			CORE_CK_OUT_EN);
76415b5a75SGeorgi Djakov 
77415b5a75SGeorgi Djakov 	while (ck_out_en != poll) {
78415b5a75SGeorgi Djakov 		if (--wait_cnt == 0) {
79415b5a75SGeorgi Djakov 			dev_err(mmc_dev(mmc), "%s: CK_OUT_EN bit is not %d\n",
80415b5a75SGeorgi Djakov 			       mmc_hostname(mmc), poll);
81415b5a75SGeorgi Djakov 			return -ETIMEDOUT;
82415b5a75SGeorgi Djakov 		}
83415b5a75SGeorgi Djakov 		udelay(1);
84415b5a75SGeorgi Djakov 
85415b5a75SGeorgi Djakov 		ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
86415b5a75SGeorgi Djakov 				CORE_CK_OUT_EN);
87415b5a75SGeorgi Djakov 	}
88415b5a75SGeorgi Djakov 
89415b5a75SGeorgi Djakov 	return 0;
90415b5a75SGeorgi Djakov }
91415b5a75SGeorgi Djakov 
92415b5a75SGeorgi Djakov static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
93415b5a75SGeorgi Djakov {
94415b5a75SGeorgi Djakov 	int rc;
95415b5a75SGeorgi Djakov 	static const u8 grey_coded_phase_table[] = {
96415b5a75SGeorgi Djakov 		0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4,
97415b5a75SGeorgi Djakov 		0xc, 0xd, 0xf, 0xe, 0xa, 0xb, 0x9, 0x8
98415b5a75SGeorgi Djakov 	};
99415b5a75SGeorgi Djakov 	unsigned long flags;
100415b5a75SGeorgi Djakov 	u32 config;
101415b5a75SGeorgi Djakov 	struct mmc_host *mmc = host->mmc;
102415b5a75SGeorgi Djakov 
103415b5a75SGeorgi Djakov 	spin_lock_irqsave(&host->lock, flags);
104415b5a75SGeorgi Djakov 
105415b5a75SGeorgi Djakov 	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
106415b5a75SGeorgi Djakov 	config &= ~(CORE_CDR_EN | CORE_CK_OUT_EN);
107415b5a75SGeorgi Djakov 	config |= (CORE_CDR_EXT_EN | CORE_DLL_EN);
108415b5a75SGeorgi Djakov 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
109415b5a75SGeorgi Djakov 
110415b5a75SGeorgi Djakov 	/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '0' */
111415b5a75SGeorgi Djakov 	rc = msm_dll_poll_ck_out_en(host, 0);
112415b5a75SGeorgi Djakov 	if (rc)
113415b5a75SGeorgi Djakov 		goto err_out;
114415b5a75SGeorgi Djakov 
115415b5a75SGeorgi Djakov 	/*
116415b5a75SGeorgi Djakov 	 * Write the selected DLL clock output phase (0 ... 15)
117415b5a75SGeorgi Djakov 	 * to CDR_SELEXT bit field of DLL_CONFIG register.
118415b5a75SGeorgi Djakov 	 */
119415b5a75SGeorgi Djakov 	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
120415b5a75SGeorgi Djakov 	config &= ~CDR_SELEXT_MASK;
121415b5a75SGeorgi Djakov 	config |= grey_coded_phase_table[phase] << CDR_SELEXT_SHIFT;
122415b5a75SGeorgi Djakov 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
123415b5a75SGeorgi Djakov 
124415b5a75SGeorgi Djakov 	/* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */
125415b5a75SGeorgi Djakov 	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
126415b5a75SGeorgi Djakov 			| CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
127415b5a75SGeorgi Djakov 
128415b5a75SGeorgi Djakov 	/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */
129415b5a75SGeorgi Djakov 	rc = msm_dll_poll_ck_out_en(host, 1);
130415b5a75SGeorgi Djakov 	if (rc)
131415b5a75SGeorgi Djakov 		goto err_out;
132415b5a75SGeorgi Djakov 
133415b5a75SGeorgi Djakov 	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
134415b5a75SGeorgi Djakov 	config |= CORE_CDR_EN;
135415b5a75SGeorgi Djakov 	config &= ~CORE_CDR_EXT_EN;
136415b5a75SGeorgi Djakov 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
137415b5a75SGeorgi Djakov 	goto out;
138415b5a75SGeorgi Djakov 
139415b5a75SGeorgi Djakov err_out:
140415b5a75SGeorgi Djakov 	dev_err(mmc_dev(mmc), "%s: Failed to set DLL phase: %d\n",
141415b5a75SGeorgi Djakov 	       mmc_hostname(mmc), phase);
142415b5a75SGeorgi Djakov out:
143415b5a75SGeorgi Djakov 	spin_unlock_irqrestore(&host->lock, flags);
144415b5a75SGeorgi Djakov 	return rc;
145415b5a75SGeorgi Djakov }
146415b5a75SGeorgi Djakov 
147415b5a75SGeorgi Djakov /*
148415b5a75SGeorgi Djakov  * Find out the greatest range of consecuitive selected
149415b5a75SGeorgi Djakov  * DLL clock output phases that can be used as sampling
150415b5a75SGeorgi Djakov  * setting for SD3.0 UHS-I card read operation (in SDR104
151415b5a75SGeorgi Djakov  * timing mode) or for eMMC4.5 card read operation (in HS200
152415b5a75SGeorgi Djakov  * timing mode).
153415b5a75SGeorgi Djakov  * Select the 3/4 of the range and configure the DLL with the
154415b5a75SGeorgi Djakov  * selected DLL clock output phase.
155415b5a75SGeorgi Djakov  */
156415b5a75SGeorgi Djakov 
157415b5a75SGeorgi Djakov static int msm_find_most_appropriate_phase(struct sdhci_host *host,
158415b5a75SGeorgi Djakov 					   u8 *phase_table, u8 total_phases)
159415b5a75SGeorgi Djakov {
160415b5a75SGeorgi Djakov 	int ret;
161415b5a75SGeorgi Djakov 	u8 ranges[MAX_PHASES][MAX_PHASES] = { {0}, {0} };
162415b5a75SGeorgi Djakov 	u8 phases_per_row[MAX_PHASES] = { 0 };
163415b5a75SGeorgi Djakov 	int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0;
164415b5a75SGeorgi Djakov 	int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0;
165415b5a75SGeorgi Djakov 	bool phase_0_found = false, phase_15_found = false;
166415b5a75SGeorgi Djakov 	struct mmc_host *mmc = host->mmc;
167415b5a75SGeorgi Djakov 
168415b5a75SGeorgi Djakov 	if (!total_phases || (total_phases > MAX_PHASES)) {
169415b5a75SGeorgi Djakov 		dev_err(mmc_dev(mmc), "%s: Invalid argument: total_phases=%d\n",
170415b5a75SGeorgi Djakov 		       mmc_hostname(mmc), total_phases);
171415b5a75SGeorgi Djakov 		return -EINVAL;
172415b5a75SGeorgi Djakov 	}
173415b5a75SGeorgi Djakov 
174415b5a75SGeorgi Djakov 	for (cnt = 0; cnt < total_phases; cnt++) {
175415b5a75SGeorgi Djakov 		ranges[row_index][col_index] = phase_table[cnt];
176415b5a75SGeorgi Djakov 		phases_per_row[row_index] += 1;
177415b5a75SGeorgi Djakov 		col_index++;
178415b5a75SGeorgi Djakov 
179415b5a75SGeorgi Djakov 		if ((cnt + 1) == total_phases) {
180415b5a75SGeorgi Djakov 			continue;
181415b5a75SGeorgi Djakov 		/* check if next phase in phase_table is consecutive or not */
182415b5a75SGeorgi Djakov 		} else if ((phase_table[cnt] + 1) != phase_table[cnt + 1]) {
183415b5a75SGeorgi Djakov 			row_index++;
184415b5a75SGeorgi Djakov 			col_index = 0;
185415b5a75SGeorgi Djakov 		}
186415b5a75SGeorgi Djakov 	}
187415b5a75SGeorgi Djakov 
188415b5a75SGeorgi Djakov 	if (row_index >= MAX_PHASES)
189415b5a75SGeorgi Djakov 		return -EINVAL;
190415b5a75SGeorgi Djakov 
191415b5a75SGeorgi Djakov 	/* Check if phase-0 is present in first valid window? */
192415b5a75SGeorgi Djakov 	if (!ranges[0][0]) {
193415b5a75SGeorgi Djakov 		phase_0_found = true;
194415b5a75SGeorgi Djakov 		phase_0_raw_index = 0;
195415b5a75SGeorgi Djakov 		/* Check if cycle exist between 2 valid windows */
196415b5a75SGeorgi Djakov 		for (cnt = 1; cnt <= row_index; cnt++) {
197415b5a75SGeorgi Djakov 			if (phases_per_row[cnt]) {
198415b5a75SGeorgi Djakov 				for (i = 0; i < phases_per_row[cnt]; i++) {
199415b5a75SGeorgi Djakov 					if (ranges[cnt][i] == 15) {
200415b5a75SGeorgi Djakov 						phase_15_found = true;
201415b5a75SGeorgi Djakov 						phase_15_raw_index = cnt;
202415b5a75SGeorgi Djakov 						break;
203415b5a75SGeorgi Djakov 					}
204415b5a75SGeorgi Djakov 				}
205415b5a75SGeorgi Djakov 			}
206415b5a75SGeorgi Djakov 		}
207415b5a75SGeorgi Djakov 	}
208415b5a75SGeorgi Djakov 
209415b5a75SGeorgi Djakov 	/* If 2 valid windows form cycle then merge them as single window */
210415b5a75SGeorgi Djakov 	if (phase_0_found && phase_15_found) {
211415b5a75SGeorgi Djakov 		/* number of phases in raw where phase 0 is present */
212415b5a75SGeorgi Djakov 		u8 phases_0 = phases_per_row[phase_0_raw_index];
213415b5a75SGeorgi Djakov 		/* number of phases in raw where phase 15 is present */
214415b5a75SGeorgi Djakov 		u8 phases_15 = phases_per_row[phase_15_raw_index];
215415b5a75SGeorgi Djakov 
216415b5a75SGeorgi Djakov 		if (phases_0 + phases_15 >= MAX_PHASES)
217415b5a75SGeorgi Djakov 			/*
218415b5a75SGeorgi Djakov 			 * If there are more than 1 phase windows then total
219415b5a75SGeorgi Djakov 			 * number of phases in both the windows should not be
220415b5a75SGeorgi Djakov 			 * more than or equal to MAX_PHASES.
221415b5a75SGeorgi Djakov 			 */
222415b5a75SGeorgi Djakov 			return -EINVAL;
223415b5a75SGeorgi Djakov 
224415b5a75SGeorgi Djakov 		/* Merge 2 cyclic windows */
225415b5a75SGeorgi Djakov 		i = phases_15;
226415b5a75SGeorgi Djakov 		for (cnt = 0; cnt < phases_0; cnt++) {
227415b5a75SGeorgi Djakov 			ranges[phase_15_raw_index][i] =
228415b5a75SGeorgi Djakov 			    ranges[phase_0_raw_index][cnt];
229415b5a75SGeorgi Djakov 			if (++i >= MAX_PHASES)
230415b5a75SGeorgi Djakov 				break;
231415b5a75SGeorgi Djakov 		}
232415b5a75SGeorgi Djakov 
233415b5a75SGeorgi Djakov 		phases_per_row[phase_0_raw_index] = 0;
234415b5a75SGeorgi Djakov 		phases_per_row[phase_15_raw_index] = phases_15 + phases_0;
235415b5a75SGeorgi Djakov 	}
236415b5a75SGeorgi Djakov 
237415b5a75SGeorgi Djakov 	for (cnt = 0; cnt <= row_index; cnt++) {
238415b5a75SGeorgi Djakov 		if (phases_per_row[cnt] > curr_max) {
239415b5a75SGeorgi Djakov 			curr_max = phases_per_row[cnt];
240415b5a75SGeorgi Djakov 			selected_row_index = cnt;
241415b5a75SGeorgi Djakov 		}
242415b5a75SGeorgi Djakov 	}
243415b5a75SGeorgi Djakov 
244415b5a75SGeorgi Djakov 	i = (curr_max * 3) / 4;
245415b5a75SGeorgi Djakov 	if (i)
246415b5a75SGeorgi Djakov 		i--;
247415b5a75SGeorgi Djakov 
248415b5a75SGeorgi Djakov 	ret = ranges[selected_row_index][i];
249415b5a75SGeorgi Djakov 
250415b5a75SGeorgi Djakov 	if (ret >= MAX_PHASES) {
251415b5a75SGeorgi Djakov 		ret = -EINVAL;
252415b5a75SGeorgi Djakov 		dev_err(mmc_dev(mmc), "%s: Invalid phase selected=%d\n",
253415b5a75SGeorgi Djakov 		       mmc_hostname(mmc), ret);
254415b5a75SGeorgi Djakov 	}
255415b5a75SGeorgi Djakov 
256415b5a75SGeorgi Djakov 	return ret;
257415b5a75SGeorgi Djakov }
258415b5a75SGeorgi Djakov 
259415b5a75SGeorgi Djakov static inline void msm_cm_dll_set_freq(struct sdhci_host *host)
260415b5a75SGeorgi Djakov {
261415b5a75SGeorgi Djakov 	u32 mclk_freq = 0, config;
262415b5a75SGeorgi Djakov 
263415b5a75SGeorgi Djakov 	/* Program the MCLK value to MCLK_FREQ bit field */
264415b5a75SGeorgi Djakov 	if (host->clock <= 112000000)
265415b5a75SGeorgi Djakov 		mclk_freq = 0;
266415b5a75SGeorgi Djakov 	else if (host->clock <= 125000000)
267415b5a75SGeorgi Djakov 		mclk_freq = 1;
268415b5a75SGeorgi Djakov 	else if (host->clock <= 137000000)
269415b5a75SGeorgi Djakov 		mclk_freq = 2;
270415b5a75SGeorgi Djakov 	else if (host->clock <= 150000000)
271415b5a75SGeorgi Djakov 		mclk_freq = 3;
272415b5a75SGeorgi Djakov 	else if (host->clock <= 162000000)
273415b5a75SGeorgi Djakov 		mclk_freq = 4;
274415b5a75SGeorgi Djakov 	else if (host->clock <= 175000000)
275415b5a75SGeorgi Djakov 		mclk_freq = 5;
276415b5a75SGeorgi Djakov 	else if (host->clock <= 187000000)
277415b5a75SGeorgi Djakov 		mclk_freq = 6;
278415b5a75SGeorgi Djakov 	else if (host->clock <= 200000000)
279415b5a75SGeorgi Djakov 		mclk_freq = 7;
280415b5a75SGeorgi Djakov 
281415b5a75SGeorgi Djakov 	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
282415b5a75SGeorgi Djakov 	config &= ~CMUX_SHIFT_PHASE_MASK;
283415b5a75SGeorgi Djakov 	config |= mclk_freq << CMUX_SHIFT_PHASE_SHIFT;
284415b5a75SGeorgi Djakov 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
285415b5a75SGeorgi Djakov }
286415b5a75SGeorgi Djakov 
287415b5a75SGeorgi Djakov /* Initialize the DLL (Programmable Delay Line) */
288415b5a75SGeorgi Djakov static int msm_init_cm_dll(struct sdhci_host *host)
289415b5a75SGeorgi Djakov {
290415b5a75SGeorgi Djakov 	struct mmc_host *mmc = host->mmc;
291415b5a75SGeorgi Djakov 	int wait_cnt = 50;
292415b5a75SGeorgi Djakov 	unsigned long flags;
293415b5a75SGeorgi Djakov 
294415b5a75SGeorgi Djakov 	spin_lock_irqsave(&host->lock, flags);
295415b5a75SGeorgi Djakov 
296415b5a75SGeorgi Djakov 	/*
297415b5a75SGeorgi Djakov 	 * Make sure that clock is always enabled when DLL
298415b5a75SGeorgi Djakov 	 * tuning is in progress. Keeping PWRSAVE ON may
299415b5a75SGeorgi Djakov 	 * turn off the clock.
300415b5a75SGeorgi Djakov 	 */
301415b5a75SGeorgi Djakov 	writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
302415b5a75SGeorgi Djakov 			& ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC);
303415b5a75SGeorgi Djakov 
304415b5a75SGeorgi Djakov 	/* Write 1 to DLL_RST bit of DLL_CONFIG register */
305415b5a75SGeorgi Djakov 	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
306415b5a75SGeorgi Djakov 			| CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
307415b5a75SGeorgi Djakov 
308415b5a75SGeorgi Djakov 	/* Write 1 to DLL_PDN bit of DLL_CONFIG register */
309415b5a75SGeorgi Djakov 	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
310415b5a75SGeorgi Djakov 			| CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
311415b5a75SGeorgi Djakov 	msm_cm_dll_set_freq(host);
312415b5a75SGeorgi Djakov 
313415b5a75SGeorgi Djakov 	/* Write 0 to DLL_RST bit of DLL_CONFIG register */
314415b5a75SGeorgi Djakov 	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
315415b5a75SGeorgi Djakov 			& ~CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
316415b5a75SGeorgi Djakov 
317415b5a75SGeorgi Djakov 	/* Write 0 to DLL_PDN bit of DLL_CONFIG register */
318415b5a75SGeorgi Djakov 	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
319415b5a75SGeorgi Djakov 			& ~CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
320415b5a75SGeorgi Djakov 
321415b5a75SGeorgi Djakov 	/* Set DLL_EN bit to 1. */
322415b5a75SGeorgi Djakov 	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
323415b5a75SGeorgi Djakov 			| CORE_DLL_EN), host->ioaddr + CORE_DLL_CONFIG);
324415b5a75SGeorgi Djakov 
325415b5a75SGeorgi Djakov 	/* Set CK_OUT_EN bit to 1. */
326415b5a75SGeorgi Djakov 	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
327415b5a75SGeorgi Djakov 			| CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
328415b5a75SGeorgi Djakov 
329415b5a75SGeorgi Djakov 	/* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */
330415b5a75SGeorgi Djakov 	while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) &
331415b5a75SGeorgi Djakov 		 CORE_DLL_LOCK)) {
332415b5a75SGeorgi Djakov 		/* max. wait for 50us sec for LOCK bit to be set */
333415b5a75SGeorgi Djakov 		if (--wait_cnt == 0) {
334415b5a75SGeorgi Djakov 			dev_err(mmc_dev(mmc), "%s: DLL failed to LOCK\n",
335415b5a75SGeorgi Djakov 			       mmc_hostname(mmc));
336415b5a75SGeorgi Djakov 			spin_unlock_irqrestore(&host->lock, flags);
337415b5a75SGeorgi Djakov 			return -ETIMEDOUT;
338415b5a75SGeorgi Djakov 		}
339415b5a75SGeorgi Djakov 		udelay(1);
340415b5a75SGeorgi Djakov 	}
341415b5a75SGeorgi Djakov 
342415b5a75SGeorgi Djakov 	spin_unlock_irqrestore(&host->lock, flags);
343415b5a75SGeorgi Djakov 	return 0;
344415b5a75SGeorgi Djakov }
345415b5a75SGeorgi Djakov 
3460eb0d9f4SGeorgi Djakov static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
3470eb0d9f4SGeorgi Djakov {
348415b5a75SGeorgi Djakov 	int tuning_seq_cnt = 3;
34933d73935SUlf Hansson 	u8 phase, tuned_phases[16], tuned_phase_cnt = 0;
350415b5a75SGeorgi Djakov 	int rc;
351415b5a75SGeorgi Djakov 	struct mmc_host *mmc = host->mmc;
352415b5a75SGeorgi Djakov 	struct mmc_ios ios = host->mmc->ios;
353415b5a75SGeorgi Djakov 
3540eb0d9f4SGeorgi Djakov 	/*
355415b5a75SGeorgi Djakov 	 * Tuning is required for SDR104, HS200 and HS400 cards and
356415b5a75SGeorgi Djakov 	 * if clock frequency is greater than 100MHz in these modes.
3570eb0d9f4SGeorgi Djakov 	 */
358415b5a75SGeorgi Djakov 	if (host->clock <= 100 * 1000 * 1000 ||
359415b5a75SGeorgi Djakov 	    !((ios.timing == MMC_TIMING_MMC_HS200) ||
360415b5a75SGeorgi Djakov 	      (ios.timing == MMC_TIMING_UHS_SDR104)))
3610eb0d9f4SGeorgi Djakov 		return 0;
362415b5a75SGeorgi Djakov 
363415b5a75SGeorgi Djakov retry:
364415b5a75SGeorgi Djakov 	/* First of all reset the tuning block */
365415b5a75SGeorgi Djakov 	rc = msm_init_cm_dll(host);
366415b5a75SGeorgi Djakov 	if (rc)
36733d73935SUlf Hansson 		return rc;
368415b5a75SGeorgi Djakov 
369415b5a75SGeorgi Djakov 	phase = 0;
370415b5a75SGeorgi Djakov 	do {
371415b5a75SGeorgi Djakov 		/* Set the phase in delay line hw block */
372415b5a75SGeorgi Djakov 		rc = msm_config_cm_dll_phase(host, phase);
373415b5a75SGeorgi Djakov 		if (rc)
37433d73935SUlf Hansson 			return rc;
375415b5a75SGeorgi Djakov 
37633d73935SUlf Hansson 		rc = mmc_send_tuning(mmc);
37733d73935SUlf Hansson 		if (!rc) {
378415b5a75SGeorgi Djakov 			/* Tuning is successful at this tuning point */
379415b5a75SGeorgi Djakov 			tuned_phases[tuned_phase_cnt++] = phase;
380415b5a75SGeorgi Djakov 			dev_dbg(mmc_dev(mmc), "%s: Found good phase = %d\n",
381415b5a75SGeorgi Djakov 				 mmc_hostname(mmc), phase);
382415b5a75SGeorgi Djakov 		}
383415b5a75SGeorgi Djakov 	} while (++phase < ARRAY_SIZE(tuned_phases));
384415b5a75SGeorgi Djakov 
385415b5a75SGeorgi Djakov 	if (tuned_phase_cnt) {
386415b5a75SGeorgi Djakov 		rc = msm_find_most_appropriate_phase(host, tuned_phases,
387415b5a75SGeorgi Djakov 						     tuned_phase_cnt);
388415b5a75SGeorgi Djakov 		if (rc < 0)
38933d73935SUlf Hansson 			return rc;
390415b5a75SGeorgi Djakov 		else
391415b5a75SGeorgi Djakov 			phase = rc;
392415b5a75SGeorgi Djakov 
393415b5a75SGeorgi Djakov 		/*
394415b5a75SGeorgi Djakov 		 * Finally set the selected phase in delay
395415b5a75SGeorgi Djakov 		 * line hw block.
396415b5a75SGeorgi Djakov 		 */
397415b5a75SGeorgi Djakov 		rc = msm_config_cm_dll_phase(host, phase);
398415b5a75SGeorgi Djakov 		if (rc)
39933d73935SUlf Hansson 			return rc;
400415b5a75SGeorgi Djakov 		dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n",
401415b5a75SGeorgi Djakov 			 mmc_hostname(mmc), phase);
402415b5a75SGeorgi Djakov 	} else {
403415b5a75SGeorgi Djakov 		if (--tuning_seq_cnt)
404415b5a75SGeorgi Djakov 			goto retry;
405415b5a75SGeorgi Djakov 		/* Tuning failed */
406415b5a75SGeorgi Djakov 		dev_dbg(mmc_dev(mmc), "%s: No tuning point found\n",
407415b5a75SGeorgi Djakov 		       mmc_hostname(mmc));
408415b5a75SGeorgi Djakov 		rc = -EIO;
409415b5a75SGeorgi Djakov 	}
410415b5a75SGeorgi Djakov 
411415b5a75SGeorgi Djakov 	return rc;
4120eb0d9f4SGeorgi Djakov }
4130eb0d9f4SGeorgi Djakov 
4140eb0d9f4SGeorgi Djakov static const struct of_device_id sdhci_msm_dt_match[] = {
4150eb0d9f4SGeorgi Djakov 	{ .compatible = "qcom,sdhci-msm-v4" },
4160eb0d9f4SGeorgi Djakov 	{},
4170eb0d9f4SGeorgi Djakov };
4180eb0d9f4SGeorgi Djakov 
4190eb0d9f4SGeorgi Djakov MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match);
4200eb0d9f4SGeorgi Djakov 
4210eb0d9f4SGeorgi Djakov static struct sdhci_ops sdhci_msm_ops = {
4220eb0d9f4SGeorgi Djakov 	.platform_execute_tuning = sdhci_msm_execute_tuning,
423ed1761d7SStephen Boyd 	.reset = sdhci_reset,
424ed1761d7SStephen Boyd 	.set_clock = sdhci_set_clock,
425ed1761d7SStephen Boyd 	.set_bus_width = sdhci_set_bus_width,
426ed1761d7SStephen Boyd 	.set_uhs_signaling = sdhci_set_uhs_signaling,
4270eb0d9f4SGeorgi Djakov };
4280eb0d9f4SGeorgi Djakov 
4290eb0d9f4SGeorgi Djakov static int sdhci_msm_probe(struct platform_device *pdev)
4300eb0d9f4SGeorgi Djakov {
4310eb0d9f4SGeorgi Djakov 	struct sdhci_host *host;
4320eb0d9f4SGeorgi Djakov 	struct sdhci_pltfm_host *pltfm_host;
4330eb0d9f4SGeorgi Djakov 	struct sdhci_msm_host *msm_host;
4340eb0d9f4SGeorgi Djakov 	struct resource *core_memres;
4350eb0d9f4SGeorgi Djakov 	int ret;
4363a3ad3e9SGeorgi Djakov 	u16 host_version, core_minor;
4373a3ad3e9SGeorgi Djakov 	u32 core_version, caps;
4383a3ad3e9SGeorgi Djakov 	u8 core_major;
4390eb0d9f4SGeorgi Djakov 
4400eb0d9f4SGeorgi Djakov 	msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL);
4410eb0d9f4SGeorgi Djakov 	if (!msm_host)
4420eb0d9f4SGeorgi Djakov 		return -ENOMEM;
4430eb0d9f4SGeorgi Djakov 
4440eb0d9f4SGeorgi Djakov 	msm_host->sdhci_msm_pdata.ops = &sdhci_msm_ops;
4450eb0d9f4SGeorgi Djakov 	host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0);
4460eb0d9f4SGeorgi Djakov 	if (IS_ERR(host))
4470eb0d9f4SGeorgi Djakov 		return PTR_ERR(host);
4480eb0d9f4SGeorgi Djakov 
4490eb0d9f4SGeorgi Djakov 	pltfm_host = sdhci_priv(host);
4500eb0d9f4SGeorgi Djakov 	pltfm_host->priv = msm_host;
4510eb0d9f4SGeorgi Djakov 	msm_host->mmc = host->mmc;
4520eb0d9f4SGeorgi Djakov 	msm_host->pdev = pdev;
4530eb0d9f4SGeorgi Djakov 
4540eb0d9f4SGeorgi Djakov 	ret = mmc_of_parse(host->mmc);
4550eb0d9f4SGeorgi Djakov 	if (ret)
4560eb0d9f4SGeorgi Djakov 		goto pltfm_free;
4570eb0d9f4SGeorgi Djakov 
4580eb0d9f4SGeorgi Djakov 	sdhci_get_of_property(pdev);
4590eb0d9f4SGeorgi Djakov 
4600eb0d9f4SGeorgi Djakov 	/* Setup SDCC bus voter clock. */
4610eb0d9f4SGeorgi Djakov 	msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus");
4620eb0d9f4SGeorgi Djakov 	if (!IS_ERR(msm_host->bus_clk)) {
4630eb0d9f4SGeorgi Djakov 		/* Vote for max. clk rate for max. performance */
4640eb0d9f4SGeorgi Djakov 		ret = clk_set_rate(msm_host->bus_clk, INT_MAX);
4650eb0d9f4SGeorgi Djakov 		if (ret)
4660eb0d9f4SGeorgi Djakov 			goto pltfm_free;
4670eb0d9f4SGeorgi Djakov 		ret = clk_prepare_enable(msm_host->bus_clk);
4680eb0d9f4SGeorgi Djakov 		if (ret)
4690eb0d9f4SGeorgi Djakov 			goto pltfm_free;
4700eb0d9f4SGeorgi Djakov 	}
4710eb0d9f4SGeorgi Djakov 
4720eb0d9f4SGeorgi Djakov 	/* Setup main peripheral bus clock */
4730eb0d9f4SGeorgi Djakov 	msm_host->pclk = devm_clk_get(&pdev->dev, "iface");
4740eb0d9f4SGeorgi Djakov 	if (IS_ERR(msm_host->pclk)) {
4750eb0d9f4SGeorgi Djakov 		ret = PTR_ERR(msm_host->pclk);
4760eb0d9f4SGeorgi Djakov 		dev_err(&pdev->dev, "Perpheral clk setup failed (%d)\n", ret);
4770eb0d9f4SGeorgi Djakov 		goto bus_clk_disable;
4780eb0d9f4SGeorgi Djakov 	}
4790eb0d9f4SGeorgi Djakov 
4800eb0d9f4SGeorgi Djakov 	ret = clk_prepare_enable(msm_host->pclk);
4810eb0d9f4SGeorgi Djakov 	if (ret)
4820eb0d9f4SGeorgi Djakov 		goto bus_clk_disable;
4830eb0d9f4SGeorgi Djakov 
4840eb0d9f4SGeorgi Djakov 	/* Setup SDC MMC clock */
4850eb0d9f4SGeorgi Djakov 	msm_host->clk = devm_clk_get(&pdev->dev, "core");
4860eb0d9f4SGeorgi Djakov 	if (IS_ERR(msm_host->clk)) {
4870eb0d9f4SGeorgi Djakov 		ret = PTR_ERR(msm_host->clk);
4880eb0d9f4SGeorgi Djakov 		dev_err(&pdev->dev, "SDC MMC clk setup failed (%d)\n", ret);
4890eb0d9f4SGeorgi Djakov 		goto pclk_disable;
4900eb0d9f4SGeorgi Djakov 	}
4910eb0d9f4SGeorgi Djakov 
492951b8c87SIvan T. Ivanov 	/* Vote for maximum clock rate for maximum performance */
493951b8c87SIvan T. Ivanov 	ret = clk_set_rate(msm_host->clk, INT_MAX);
494951b8c87SIvan T. Ivanov 	if (ret)
495951b8c87SIvan T. Ivanov 		dev_warn(&pdev->dev, "core clock boost failed\n");
496951b8c87SIvan T. Ivanov 
4970eb0d9f4SGeorgi Djakov 	ret = clk_prepare_enable(msm_host->clk);
4980eb0d9f4SGeorgi Djakov 	if (ret)
4990eb0d9f4SGeorgi Djakov 		goto pclk_disable;
5000eb0d9f4SGeorgi Djakov 
5010eb0d9f4SGeorgi Djakov 	core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
5020eb0d9f4SGeorgi Djakov 	msm_host->core_mem = devm_ioremap_resource(&pdev->dev, core_memres);
5030eb0d9f4SGeorgi Djakov 
5040eb0d9f4SGeorgi Djakov 	if (IS_ERR(msm_host->core_mem)) {
5050eb0d9f4SGeorgi Djakov 		dev_err(&pdev->dev, "Failed to remap registers\n");
5060eb0d9f4SGeorgi Djakov 		ret = PTR_ERR(msm_host->core_mem);
5070eb0d9f4SGeorgi Djakov 		goto clk_disable;
5080eb0d9f4SGeorgi Djakov 	}
5090eb0d9f4SGeorgi Djakov 
5100eb0d9f4SGeorgi Djakov 	/* Reset the core and Enable SDHC mode */
5110eb0d9f4SGeorgi Djakov 	writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) |
5120eb0d9f4SGeorgi Djakov 		       CORE_SW_RST, msm_host->core_mem + CORE_POWER);
5130eb0d9f4SGeorgi Djakov 
5140eb0d9f4SGeorgi Djakov 	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
5150eb0d9f4SGeorgi Djakov 	usleep_range(1000, 5000);
5160eb0d9f4SGeorgi Djakov 	if (readl(msm_host->core_mem + CORE_POWER) & CORE_SW_RST) {
5170eb0d9f4SGeorgi Djakov 		dev_err(&pdev->dev, "Stuck in reset\n");
5180eb0d9f4SGeorgi Djakov 		ret = -ETIMEDOUT;
5190eb0d9f4SGeorgi Djakov 		goto clk_disable;
5200eb0d9f4SGeorgi Djakov 	}
5210eb0d9f4SGeorgi Djakov 
5220eb0d9f4SGeorgi Djakov 	/* Set HC_MODE_EN bit in HC_MODE register */
5230eb0d9f4SGeorgi Djakov 	writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
5240eb0d9f4SGeorgi Djakov 
5250eb0d9f4SGeorgi Djakov 	host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
5260eb0d9f4SGeorgi Djakov 	host->quirks |= SDHCI_QUIRK_SINGLE_POWER_WRITE;
5270eb0d9f4SGeorgi Djakov 
5280eb0d9f4SGeorgi Djakov 	host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
5290eb0d9f4SGeorgi Djakov 	dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
5300eb0d9f4SGeorgi Djakov 		host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >>
5310eb0d9f4SGeorgi Djakov 			       SDHCI_VENDOR_VER_SHIFT));
5320eb0d9f4SGeorgi Djakov 
5333a3ad3e9SGeorgi Djakov 	core_version = readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION);
5343a3ad3e9SGeorgi Djakov 	core_major = (core_version & CORE_VERSION_MAJOR_MASK) >>
5353a3ad3e9SGeorgi Djakov 		      CORE_VERSION_MAJOR_SHIFT;
5363a3ad3e9SGeorgi Djakov 	core_minor = core_version & CORE_VERSION_MINOR_MASK;
5373a3ad3e9SGeorgi Djakov 	dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n",
5383a3ad3e9SGeorgi Djakov 		core_version, core_major, core_minor);
5393a3ad3e9SGeorgi Djakov 
5403a3ad3e9SGeorgi Djakov 	/*
5413a3ad3e9SGeorgi Djakov 	 * Support for some capabilities is not advertised by newer
5423a3ad3e9SGeorgi Djakov 	 * controller versions and must be explicitly enabled.
5433a3ad3e9SGeorgi Djakov 	 */
5443a3ad3e9SGeorgi Djakov 	if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) {
5453a3ad3e9SGeorgi Djakov 		caps = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES);
5463a3ad3e9SGeorgi Djakov 		caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
5473a3ad3e9SGeorgi Djakov 		writel_relaxed(caps, host->ioaddr +
5483a3ad3e9SGeorgi Djakov 			       CORE_VENDOR_SPEC_CAPABILITIES0);
5493a3ad3e9SGeorgi Djakov 	}
5503a3ad3e9SGeorgi Djakov 
5510eb0d9f4SGeorgi Djakov 	ret = sdhci_add_host(host);
5520eb0d9f4SGeorgi Djakov 	if (ret)
5530eb0d9f4SGeorgi Djakov 		goto clk_disable;
5540eb0d9f4SGeorgi Djakov 
5550eb0d9f4SGeorgi Djakov 	return 0;
5560eb0d9f4SGeorgi Djakov 
5570eb0d9f4SGeorgi Djakov clk_disable:
5580eb0d9f4SGeorgi Djakov 	clk_disable_unprepare(msm_host->clk);
5590eb0d9f4SGeorgi Djakov pclk_disable:
5600eb0d9f4SGeorgi Djakov 	clk_disable_unprepare(msm_host->pclk);
5610eb0d9f4SGeorgi Djakov bus_clk_disable:
5620eb0d9f4SGeorgi Djakov 	if (!IS_ERR(msm_host->bus_clk))
5630eb0d9f4SGeorgi Djakov 		clk_disable_unprepare(msm_host->bus_clk);
5640eb0d9f4SGeorgi Djakov pltfm_free:
5650eb0d9f4SGeorgi Djakov 	sdhci_pltfm_free(pdev);
5660eb0d9f4SGeorgi Djakov 	return ret;
5670eb0d9f4SGeorgi Djakov }
5680eb0d9f4SGeorgi Djakov 
5690eb0d9f4SGeorgi Djakov static int sdhci_msm_remove(struct platform_device *pdev)
5700eb0d9f4SGeorgi Djakov {
5710eb0d9f4SGeorgi Djakov 	struct sdhci_host *host = platform_get_drvdata(pdev);
5720eb0d9f4SGeorgi Djakov 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
5730eb0d9f4SGeorgi Djakov 	struct sdhci_msm_host *msm_host = pltfm_host->priv;
5740eb0d9f4SGeorgi Djakov 	int dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) ==
5750eb0d9f4SGeorgi Djakov 		    0xffffffff);
5760eb0d9f4SGeorgi Djakov 
5770eb0d9f4SGeorgi Djakov 	sdhci_remove_host(host, dead);
5780eb0d9f4SGeorgi Djakov 	sdhci_pltfm_free(pdev);
5790eb0d9f4SGeorgi Djakov 	clk_disable_unprepare(msm_host->clk);
5800eb0d9f4SGeorgi Djakov 	clk_disable_unprepare(msm_host->pclk);
5810eb0d9f4SGeorgi Djakov 	if (!IS_ERR(msm_host->bus_clk))
5820eb0d9f4SGeorgi Djakov 		clk_disable_unprepare(msm_host->bus_clk);
5830eb0d9f4SGeorgi Djakov 	return 0;
5840eb0d9f4SGeorgi Djakov }
5850eb0d9f4SGeorgi Djakov 
5860eb0d9f4SGeorgi Djakov static struct platform_driver sdhci_msm_driver = {
5870eb0d9f4SGeorgi Djakov 	.probe = sdhci_msm_probe,
5880eb0d9f4SGeorgi Djakov 	.remove = sdhci_msm_remove,
5890eb0d9f4SGeorgi Djakov 	.driver = {
5900eb0d9f4SGeorgi Djakov 		   .name = "sdhci_msm",
5910eb0d9f4SGeorgi Djakov 		   .of_match_table = sdhci_msm_dt_match,
5920eb0d9f4SGeorgi Djakov 	},
5930eb0d9f4SGeorgi Djakov };
5940eb0d9f4SGeorgi Djakov 
5950eb0d9f4SGeorgi Djakov module_platform_driver(sdhci_msm_driver);
5960eb0d9f4SGeorgi Djakov 
5970eb0d9f4SGeorgi Djakov MODULE_DESCRIPTION("Qualcomm Secure Digital Host Controller Interface driver");
5980eb0d9f4SGeorgi Djakov MODULE_LICENSE("GPL v2");
599