blob: f4f277b27b96cb22f283f0f589cc99cca4424529 [file] [log] [blame]
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +02001/*
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>
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +020019#include <linux/delay.h>
Georgi Djakov415b5a72014-03-10 17:37:13 +020020#include <linux/mmc/mmc.h>
Pramod Gurav67e6db12016-10-21 12:12:04 +053021#include <linux/pm_runtime.h>
Georgi Djakov415b5a72014-03-10 17:37:13 +020022#include <linux/slab.h>
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +020023
24#include "sdhci-pltfm.h"
25
Georgi Djakov3a3ad3e2015-03-23 18:47:29 +020026#define CORE_MCI_VERSION 0x50
27#define CORE_VERSION_MAJOR_SHIFT 28
28#define CORE_VERSION_MAJOR_MASK (0xf << CORE_VERSION_MAJOR_SHIFT)
29#define CORE_VERSION_MINOR_MASK 0xff
30
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +020031#define CORE_HC_MODE 0x78
32#define HC_MODE_EN 0x1
33#define CORE_POWER 0x0
34#define CORE_SW_RST BIT(7)
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +053035#define FF_CLK_SW_RST_DIS BIT(13)
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +020036
Georgi Djakovad81d382016-06-24 18:07:14 +030037#define CORE_PWRCTL_STATUS 0xdc
38#define CORE_PWRCTL_MASK 0xe0
39#define CORE_PWRCTL_CLEAR 0xe4
40#define CORE_PWRCTL_CTL 0xe8
41#define CORE_PWRCTL_BUS_OFF BIT(0)
42#define CORE_PWRCTL_BUS_ON BIT(1)
43#define CORE_PWRCTL_IO_LOW BIT(2)
44#define CORE_PWRCTL_IO_HIGH BIT(3)
45#define CORE_PWRCTL_BUS_SUCCESS BIT(0)
46#define CORE_PWRCTL_IO_SUCCESS BIT(2)
47#define REQ_BUS_OFF BIT(0)
48#define REQ_BUS_ON BIT(1)
49#define REQ_IO_LOW BIT(2)
50#define REQ_IO_HIGH BIT(3)
51#define INT_MASK 0xf
Georgi Djakov415b5a72014-03-10 17:37:13 +020052#define MAX_PHASES 16
53#define CORE_DLL_LOCK BIT(7)
54#define CORE_DLL_EN BIT(16)
55#define CORE_CDR_EN BIT(17)
56#define CORE_CK_OUT_EN BIT(18)
57#define CORE_CDR_EXT_EN BIT(19)
58#define CORE_DLL_PDN BIT(29)
59#define CORE_DLL_RST BIT(30)
60#define CORE_DLL_CONFIG 0x100
61#define CORE_DLL_STATUS 0x108
62
Venkat Gopalakrishnan83736352016-11-21 12:07:16 +053063#define CORE_DLL_CONFIG_2 0x1b4
64#define CORE_FLL_CYCLE_CNT BIT(18)
65#define CORE_DLL_CLOCK_DISABLE BIT(21)
66
Georgi Djakov415b5a72014-03-10 17:37:13 +020067#define CORE_VENDOR_SPEC 0x10c
68#define CORE_CLK_PWRSAVE BIT(1)
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +053069#define CORE_HC_MCLK_SEL_DFLT (2 << 8)
70#define CORE_HC_MCLK_SEL_HS400 (3 << 8)
71#define CORE_HC_MCLK_SEL_MASK (3 << 8)
72#define CORE_HC_SELECT_IN_EN BIT(18)
73#define CORE_HC_SELECT_IN_HS400 (6 << 19)
74#define CORE_HC_SELECT_IN_MASK (7 << 19)
Georgi Djakov415b5a72014-03-10 17:37:13 +020075
Georgi Djakov3a3ad3e2015-03-23 18:47:29 +020076#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
77
Ritesh Harjaniabf270e2016-11-21 12:07:24 +053078#define INVALID_TUNING_PHASE -1
Ritesh Harjani80031bd2016-11-21 12:07:17 +053079#define SDHCI_MSM_MIN_CLOCK 400000
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +053080#define CORE_FREQ_100MHZ (100 * 1000 * 1000)
Ritesh Harjani80031bd2016-11-21 12:07:17 +053081
Georgi Djakov415b5a72014-03-10 17:37:13 +020082#define CDR_SELEXT_SHIFT 20
83#define CDR_SELEXT_MASK (0xf << CDR_SELEXT_SHIFT)
84#define CMUX_SHIFT_PHASE_SHIFT 24
85#define CMUX_SHIFT_PHASE_MASK (7 << CMUX_SHIFT_PHASE_SHIFT)
86
Pramod Gurav67e6db12016-10-21 12:12:04 +053087#define MSM_MMC_AUTOSUSPEND_DELAY_MS 50
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +020088struct sdhci_msm_host {
89 struct platform_device *pdev;
90 void __iomem *core_mem; /* MSM SDCC mapped address */
Georgi Djakovad81d382016-06-24 18:07:14 +030091 int pwr_irq; /* power irq */
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +020092 struct clk *clk; /* main SD/MMC bus clock */
93 struct clk *pclk; /* SDHC peripheral bus clock */
94 struct clk *bus_clk; /* SDHC bus voter clock */
Venkat Gopalakrishnan83736352016-11-21 12:07:16 +053095 struct clk *xo_clk; /* TCXO clk needed for FLL feature of cm_dll*/
Ritesh Harjaniedc609f2016-11-21 12:07:20 +053096 unsigned long clk_rate;
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +020097 struct mmc_host *mmc;
Venkat Gopalakrishnan83736352016-11-21 12:07:16 +053098 bool use_14lpp_dll_reset;
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +053099 bool tuning_done;
100 bool calibration_done;
Ritesh Harjaniabf270e2016-11-21 12:07:24 +0530101 u8 saved_tuning_phase;
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200102};
103
104/* Platform specific tuning */
Georgi Djakov415b5a72014-03-10 17:37:13 +0200105static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll)
106{
107 u32 wait_cnt = 50;
108 u8 ck_out_en;
109 struct mmc_host *mmc = host->mmc;
110
111 /* Poll for CK_OUT_EN bit. max. poll time = 50us */
112 ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
113 CORE_CK_OUT_EN);
114
115 while (ck_out_en != poll) {
116 if (--wait_cnt == 0) {
117 dev_err(mmc_dev(mmc), "%s: CK_OUT_EN bit is not %d\n",
118 mmc_hostname(mmc), poll);
119 return -ETIMEDOUT;
120 }
121 udelay(1);
122
123 ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
124 CORE_CK_OUT_EN);
125 }
126
127 return 0;
128}
129
130static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
131{
132 int rc;
133 static const u8 grey_coded_phase_table[] = {
134 0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4,
135 0xc, 0xd, 0xf, 0xe, 0xa, 0xb, 0x9, 0x8
136 };
137 unsigned long flags;
138 u32 config;
139 struct mmc_host *mmc = host->mmc;
140
Ritesh Harjaniabf270e2016-11-21 12:07:24 +0530141 if (phase > 0xf)
142 return -EINVAL;
143
Georgi Djakov415b5a72014-03-10 17:37:13 +0200144 spin_lock_irqsave(&host->lock, flags);
145
146 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
147 config &= ~(CORE_CDR_EN | CORE_CK_OUT_EN);
148 config |= (CORE_CDR_EXT_EN | CORE_DLL_EN);
149 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
150
151 /* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '0' */
152 rc = msm_dll_poll_ck_out_en(host, 0);
153 if (rc)
154 goto err_out;
155
156 /*
157 * Write the selected DLL clock output phase (0 ... 15)
158 * to CDR_SELEXT bit field of DLL_CONFIG register.
159 */
160 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
161 config &= ~CDR_SELEXT_MASK;
162 config |= grey_coded_phase_table[phase] << CDR_SELEXT_SHIFT;
163 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
164
Ritesh Harjani29301f42016-11-21 12:07:13 +0530165 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
166 config |= CORE_CK_OUT_EN;
167 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
Georgi Djakov415b5a72014-03-10 17:37:13 +0200168
169 /* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */
170 rc = msm_dll_poll_ck_out_en(host, 1);
171 if (rc)
172 goto err_out;
173
174 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
175 config |= CORE_CDR_EN;
176 config &= ~CORE_CDR_EXT_EN;
177 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
178 goto out;
179
180err_out:
181 dev_err(mmc_dev(mmc), "%s: Failed to set DLL phase: %d\n",
182 mmc_hostname(mmc), phase);
183out:
184 spin_unlock_irqrestore(&host->lock, flags);
185 return rc;
186}
187
188/*
189 * Find out the greatest range of consecuitive selected
190 * DLL clock output phases that can be used as sampling
191 * setting for SD3.0 UHS-I card read operation (in SDR104
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +0530192 * timing mode) or for eMMC4.5 card read operation (in
193 * HS400/HS200 timing mode).
Georgi Djakov415b5a72014-03-10 17:37:13 +0200194 * Select the 3/4 of the range and configure the DLL with the
195 * selected DLL clock output phase.
196 */
197
198static int msm_find_most_appropriate_phase(struct sdhci_host *host,
199 u8 *phase_table, u8 total_phases)
200{
201 int ret;
202 u8 ranges[MAX_PHASES][MAX_PHASES] = { {0}, {0} };
203 u8 phases_per_row[MAX_PHASES] = { 0 };
204 int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0;
205 int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0;
206 bool phase_0_found = false, phase_15_found = false;
207 struct mmc_host *mmc = host->mmc;
208
209 if (!total_phases || (total_phases > MAX_PHASES)) {
210 dev_err(mmc_dev(mmc), "%s: Invalid argument: total_phases=%d\n",
211 mmc_hostname(mmc), total_phases);
212 return -EINVAL;
213 }
214
215 for (cnt = 0; cnt < total_phases; cnt++) {
216 ranges[row_index][col_index] = phase_table[cnt];
217 phases_per_row[row_index] += 1;
218 col_index++;
219
220 if ((cnt + 1) == total_phases) {
221 continue;
222 /* check if next phase in phase_table is consecutive or not */
223 } else if ((phase_table[cnt] + 1) != phase_table[cnt + 1]) {
224 row_index++;
225 col_index = 0;
226 }
227 }
228
229 if (row_index >= MAX_PHASES)
230 return -EINVAL;
231
232 /* Check if phase-0 is present in first valid window? */
233 if (!ranges[0][0]) {
234 phase_0_found = true;
235 phase_0_raw_index = 0;
236 /* Check if cycle exist between 2 valid windows */
237 for (cnt = 1; cnt <= row_index; cnt++) {
238 if (phases_per_row[cnt]) {
239 for (i = 0; i < phases_per_row[cnt]; i++) {
240 if (ranges[cnt][i] == 15) {
241 phase_15_found = true;
242 phase_15_raw_index = cnt;
243 break;
244 }
245 }
246 }
247 }
248 }
249
250 /* If 2 valid windows form cycle then merge them as single window */
251 if (phase_0_found && phase_15_found) {
252 /* number of phases in raw where phase 0 is present */
253 u8 phases_0 = phases_per_row[phase_0_raw_index];
254 /* number of phases in raw where phase 15 is present */
255 u8 phases_15 = phases_per_row[phase_15_raw_index];
256
257 if (phases_0 + phases_15 >= MAX_PHASES)
258 /*
259 * If there are more than 1 phase windows then total
260 * number of phases in both the windows should not be
261 * more than or equal to MAX_PHASES.
262 */
263 return -EINVAL;
264
265 /* Merge 2 cyclic windows */
266 i = phases_15;
267 for (cnt = 0; cnt < phases_0; cnt++) {
268 ranges[phase_15_raw_index][i] =
269 ranges[phase_0_raw_index][cnt];
270 if (++i >= MAX_PHASES)
271 break;
272 }
273
274 phases_per_row[phase_0_raw_index] = 0;
275 phases_per_row[phase_15_raw_index] = phases_15 + phases_0;
276 }
277
278 for (cnt = 0; cnt <= row_index; cnt++) {
279 if (phases_per_row[cnt] > curr_max) {
280 curr_max = phases_per_row[cnt];
281 selected_row_index = cnt;
282 }
283 }
284
285 i = (curr_max * 3) / 4;
286 if (i)
287 i--;
288
289 ret = ranges[selected_row_index][i];
290
291 if (ret >= MAX_PHASES) {
292 ret = -EINVAL;
293 dev_err(mmc_dev(mmc), "%s: Invalid phase selected=%d\n",
294 mmc_hostname(mmc), ret);
295 }
296
297 return ret;
298}
299
300static inline void msm_cm_dll_set_freq(struct sdhci_host *host)
301{
302 u32 mclk_freq = 0, config;
303
304 /* Program the MCLK value to MCLK_FREQ bit field */
305 if (host->clock <= 112000000)
306 mclk_freq = 0;
307 else if (host->clock <= 125000000)
308 mclk_freq = 1;
309 else if (host->clock <= 137000000)
310 mclk_freq = 2;
311 else if (host->clock <= 150000000)
312 mclk_freq = 3;
313 else if (host->clock <= 162000000)
314 mclk_freq = 4;
315 else if (host->clock <= 175000000)
316 mclk_freq = 5;
317 else if (host->clock <= 187000000)
318 mclk_freq = 6;
319 else if (host->clock <= 200000000)
320 mclk_freq = 7;
321
322 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
323 config &= ~CMUX_SHIFT_PHASE_MASK;
324 config |= mclk_freq << CMUX_SHIFT_PHASE_SHIFT;
325 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
326}
327
328/* Initialize the DLL (Programmable Delay Line) */
329static int msm_init_cm_dll(struct sdhci_host *host)
330{
331 struct mmc_host *mmc = host->mmc;
Venkat Gopalakrishnan83736352016-11-21 12:07:16 +0530332 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
333 struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
Georgi Djakov415b5a72014-03-10 17:37:13 +0200334 int wait_cnt = 50;
335 unsigned long flags;
Ritesh Harjani29301f42016-11-21 12:07:13 +0530336 u32 config;
Georgi Djakov415b5a72014-03-10 17:37:13 +0200337
338 spin_lock_irqsave(&host->lock, flags);
339
340 /*
341 * Make sure that clock is always enabled when DLL
342 * tuning is in progress. Keeping PWRSAVE ON may
343 * turn off the clock.
344 */
Ritesh Harjani29301f42016-11-21 12:07:13 +0530345 config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
346 config &= ~CORE_CLK_PWRSAVE;
347 writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
Georgi Djakov415b5a72014-03-10 17:37:13 +0200348
Venkat Gopalakrishnan83736352016-11-21 12:07:16 +0530349 if (msm_host->use_14lpp_dll_reset) {
350 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
351 config &= ~CORE_CK_OUT_EN;
352 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
353
354 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
355 config |= CORE_DLL_CLOCK_DISABLE;
356 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
357 }
358
Ritesh Harjani29301f42016-11-21 12:07:13 +0530359 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
360 config |= CORE_DLL_RST;
361 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
Georgi Djakov415b5a72014-03-10 17:37:13 +0200362
Ritesh Harjani29301f42016-11-21 12:07:13 +0530363 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
364 config |= CORE_DLL_PDN;
365 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
Georgi Djakov415b5a72014-03-10 17:37:13 +0200366 msm_cm_dll_set_freq(host);
367
Venkat Gopalakrishnan83736352016-11-21 12:07:16 +0530368 if (msm_host->use_14lpp_dll_reset &&
369 !IS_ERR_OR_NULL(msm_host->xo_clk)) {
370 u32 mclk_freq = 0;
371
372 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
373 config &= CORE_FLL_CYCLE_CNT;
374 if (config)
375 mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 8),
376 clk_get_rate(msm_host->xo_clk));
377 else
378 mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 4),
379 clk_get_rate(msm_host->xo_clk));
380
381 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
382 config &= ~(0xFF << 10);
383 config |= mclk_freq << 10;
384
385 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
386 /* wait for 5us before enabling DLL clock */
387 udelay(5);
388 }
389
Ritesh Harjani29301f42016-11-21 12:07:13 +0530390 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
391 config &= ~CORE_DLL_RST;
392 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
Georgi Djakov415b5a72014-03-10 17:37:13 +0200393
Ritesh Harjani29301f42016-11-21 12:07:13 +0530394 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
395 config &= ~CORE_DLL_PDN;
396 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
Georgi Djakov415b5a72014-03-10 17:37:13 +0200397
Venkat Gopalakrishnan83736352016-11-21 12:07:16 +0530398 if (msm_host->use_14lpp_dll_reset) {
399 msm_cm_dll_set_freq(host);
400 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
401 config &= ~CORE_DLL_CLOCK_DISABLE;
402 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
403 }
404
Ritesh Harjani29301f42016-11-21 12:07:13 +0530405 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
406 config |= CORE_DLL_EN;
407 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
Georgi Djakov415b5a72014-03-10 17:37:13 +0200408
Ritesh Harjani29301f42016-11-21 12:07:13 +0530409 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
410 config |= CORE_CK_OUT_EN;
411 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
Georgi Djakov415b5a72014-03-10 17:37:13 +0200412
413 /* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */
414 while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) &
415 CORE_DLL_LOCK)) {
416 /* max. wait for 50us sec for LOCK bit to be set */
417 if (--wait_cnt == 0) {
418 dev_err(mmc_dev(mmc), "%s: DLL failed to LOCK\n",
419 mmc_hostname(mmc));
420 spin_unlock_irqrestore(&host->lock, flags);
421 return -ETIMEDOUT;
422 }
423 udelay(1);
424 }
425
426 spin_unlock_irqrestore(&host->lock, flags);
427 return 0;
428}
429
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200430static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
431{
Georgi Djakov415b5a72014-03-10 17:37:13 +0200432 int tuning_seq_cnt = 3;
Ulf Hansson33d73932014-12-05 12:59:41 +0100433 u8 phase, tuned_phases[16], tuned_phase_cnt = 0;
Georgi Djakov415b5a72014-03-10 17:37:13 +0200434 int rc;
435 struct mmc_host *mmc = host->mmc;
436 struct mmc_ios ios = host->mmc->ios;
Ritesh Harjaniabf270e2016-11-21 12:07:24 +0530437 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
438 struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
Georgi Djakov415b5a72014-03-10 17:37:13 +0200439
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200440 /*
Georgi Djakov415b5a72014-03-10 17:37:13 +0200441 * Tuning is required for SDR104, HS200 and HS400 cards and
442 * if clock frequency is greater than 100MHz in these modes.
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200443 */
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +0530444 if (host->clock <= CORE_FREQ_100MHZ ||
445 !(ios.timing == MMC_TIMING_MMC_HS400 ||
446 ios.timing == MMC_TIMING_MMC_HS200 ||
447 ios.timing == MMC_TIMING_UHS_SDR104))
Georgi Djakov415b5a72014-03-10 17:37:13 +0200448 return 0;
449
Georgi Djakov415b5a72014-03-10 17:37:13 +0200450retry:
451 /* First of all reset the tuning block */
452 rc = msm_init_cm_dll(host);
453 if (rc)
Ulf Hansson33d73932014-12-05 12:59:41 +0100454 return rc;
Georgi Djakov415b5a72014-03-10 17:37:13 +0200455
456 phase = 0;
457 do {
Georgi Djakov415b5a72014-03-10 17:37:13 +0200458 /* Set the phase in delay line hw block */
459 rc = msm_config_cm_dll_phase(host, phase);
460 if (rc)
Ulf Hansson33d73932014-12-05 12:59:41 +0100461 return rc;
Georgi Djakov415b5a72014-03-10 17:37:13 +0200462
Ritesh Harjaniabf270e2016-11-21 12:07:24 +0530463 msm_host->saved_tuning_phase = phase;
Chaotian Jing9979dbe2015-10-27 14:24:28 +0800464 rc = mmc_send_tuning(mmc, opcode, NULL);
Ulf Hansson33d73932014-12-05 12:59:41 +0100465 if (!rc) {
Georgi Djakov415b5a72014-03-10 17:37:13 +0200466 /* Tuning is successful at this tuning point */
467 tuned_phases[tuned_phase_cnt++] = phase;
468 dev_dbg(mmc_dev(mmc), "%s: Found good phase = %d\n",
469 mmc_hostname(mmc), phase);
470 }
471 } while (++phase < ARRAY_SIZE(tuned_phases));
472
473 if (tuned_phase_cnt) {
474 rc = msm_find_most_appropriate_phase(host, tuned_phases,
475 tuned_phase_cnt);
476 if (rc < 0)
Ulf Hansson33d73932014-12-05 12:59:41 +0100477 return rc;
Georgi Djakov415b5a72014-03-10 17:37:13 +0200478 else
479 phase = rc;
480
481 /*
482 * Finally set the selected phase in delay
483 * line hw block.
484 */
485 rc = msm_config_cm_dll_phase(host, phase);
486 if (rc)
Ulf Hansson33d73932014-12-05 12:59:41 +0100487 return rc;
Georgi Djakov415b5a72014-03-10 17:37:13 +0200488 dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n",
489 mmc_hostname(mmc), phase);
490 } else {
491 if (--tuning_seq_cnt)
492 goto retry;
493 /* Tuning failed */
494 dev_dbg(mmc_dev(mmc), "%s: No tuning point found\n",
495 mmc_hostname(mmc));
496 rc = -EIO;
497 }
498
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +0530499 if (!rc)
500 msm_host->tuning_done = true;
Georgi Djakov415b5a72014-03-10 17:37:13 +0200501 return rc;
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200502}
503
Ritesh Harjaniee320672016-07-19 17:52:25 +0300504static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
505 unsigned int uhs)
506{
507 struct mmc_host *mmc = host->mmc;
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +0530508 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
509 struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
Ritesh Harjaniee320672016-07-19 17:52:25 +0300510 u16 ctrl_2;
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +0530511 u32 config;
Ritesh Harjaniee320672016-07-19 17:52:25 +0300512
513 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
514 /* Select Bus Speed Mode for host */
515 ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
516 switch (uhs) {
517 case MMC_TIMING_UHS_SDR12:
518 ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
519 break;
520 case MMC_TIMING_UHS_SDR25:
521 ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
522 break;
523 case MMC_TIMING_UHS_SDR50:
524 ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
525 break;
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +0530526 case MMC_TIMING_MMC_HS400:
Ritesh Harjaniee320672016-07-19 17:52:25 +0300527 case MMC_TIMING_MMC_HS200:
528 case MMC_TIMING_UHS_SDR104:
529 ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
530 break;
531 case MMC_TIMING_UHS_DDR50:
532 case MMC_TIMING_MMC_DDR52:
533 ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
534 break;
535 }
536
537 /*
538 * When clock frequency is less than 100MHz, the feedback clock must be
539 * provided and DLL must not be used so that tuning can be skipped. To
540 * provide feedback clock, the mode selection can be any value less
541 * than 3'b011 in bits [2:0] of HOST CONTROL2 register.
542 */
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +0530543 if (host->clock <= CORE_FREQ_100MHZ) {
544 if (uhs == MMC_TIMING_MMC_HS400 ||
545 uhs == MMC_TIMING_MMC_HS200 ||
546 uhs == MMC_TIMING_UHS_SDR104)
547 ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
548 /*
549 * DLL is not required for clock <= 100MHz
550 * Thus, make sure DLL it is disabled when not required
551 */
552 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
553 config |= CORE_DLL_RST;
554 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
555
556 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
557 config |= CORE_DLL_PDN;
558 writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
559
560 /*
561 * The DLL needs to be restored and CDCLP533 recalibrated
562 * when the clock frequency is set back to 400MHz.
563 */
564 msm_host->calibration_done = false;
565 }
Ritesh Harjaniee320672016-07-19 17:52:25 +0300566
567 dev_dbg(mmc_dev(mmc), "%s: clock=%u uhs=%u ctrl_2=0x%x\n",
568 mmc_hostname(host->mmc), host->clock, uhs, ctrl_2);
569 sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
570}
571
Georgi Djakovad81d382016-06-24 18:07:14 +0300572static void sdhci_msm_voltage_switch(struct sdhci_host *host)
573{
574 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
575 struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
576 u32 irq_status, irq_ack = 0;
577
578 irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
579 irq_status &= INT_MASK;
580
581 writel_relaxed(irq_status, msm_host->core_mem + CORE_PWRCTL_CLEAR);
582
583 if (irq_status & (CORE_PWRCTL_BUS_ON | CORE_PWRCTL_BUS_OFF))
584 irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
585 if (irq_status & (CORE_PWRCTL_IO_LOW | CORE_PWRCTL_IO_HIGH))
586 irq_ack |= CORE_PWRCTL_IO_SUCCESS;
587
588 /*
589 * The driver has to acknowledge the interrupt, switch voltages and
590 * report back if it succeded or not to this register. The voltage
591 * switches are handled by the sdhci core, so just report success.
592 */
593 writel_relaxed(irq_ack, msm_host->core_mem + CORE_PWRCTL_CTL);
594}
595
596static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
597{
598 struct sdhci_host *host = (struct sdhci_host *)data;
599
600 sdhci_msm_voltage_switch(host);
601
602 return IRQ_HANDLED;
603}
604
Ritesh Harjani80031bd2016-11-21 12:07:17 +0530605static unsigned int sdhci_msm_get_max_clock(struct sdhci_host *host)
606{
607 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
608 struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
609
610 return clk_round_rate(msm_host->clk, ULONG_MAX);
611}
612
613static unsigned int sdhci_msm_get_min_clock(struct sdhci_host *host)
614{
615 return SDHCI_MSM_MIN_CLOCK;
616}
617
Ritesh Harjaniedc609f2016-11-21 12:07:20 +0530618/**
619 * __sdhci_msm_set_clock - sdhci_msm clock control.
620 *
621 * Description:
622 * MSM controller does not use internal divider and
623 * instead directly control the GCC clock as per
624 * HW recommendation.
625 **/
626void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
627{
628 u16 clk;
629 /*
630 * Keep actual_clock as zero -
631 * - since there is no divider used so no need of having actual_clock.
632 * - MSM controller uses SDCLK for data timeout calculation. If
633 * actual_clock is zero, host->clock is taken for calculation.
634 */
635 host->mmc->actual_clock = 0;
636
637 sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
638
639 if (clock == 0)
640 return;
641
642 /*
643 * MSM controller do not use clock divider.
644 * Thus read SDHCI_CLOCK_CONTROL and only enable
645 * clock with no divider value programmed.
646 */
647 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
648 sdhci_enable_clk(host, clk);
649}
650
651/* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */
652static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
653{
654 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
655 struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
Ritesh Harjanib12d44d2016-11-21 12:07:21 +0530656 struct mmc_ios curr_ios = host->mmc->ios;
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +0530657 u32 config;
Ritesh Harjaniedc609f2016-11-21 12:07:20 +0530658 int rc;
659
660 if (!clock) {
661 msm_host->clk_rate = clock;
662 goto out;
663 }
664
665 spin_unlock_irq(&host->lock);
Ritesh Harjanib12d44d2016-11-21 12:07:21 +0530666 /*
667 * The SDHC requires internal clock frequency to be double the
668 * actual clock that will be set for DDR mode. The controller
669 * uses the faster clock(100/400MHz) for some of its parts and
670 * send the actual required clock (50/200MHz) to the card.
671 */
672 if (curr_ios.timing == MMC_TIMING_UHS_DDR50 ||
673 curr_ios.timing == MMC_TIMING_MMC_DDR52 ||
674 curr_ios.timing == MMC_TIMING_MMC_HS400)
675 clock *= 2;
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +0530676 /*
677 * In general all timing modes are controlled via UHS mode select in
678 * Host Control2 register. eMMC specific HS200/HS400 doesn't have
679 * their respective modes defined here, hence we use these values.
680 *
681 * HS200 - SDR104 (Since they both are equivalent in functionality)
682 * HS400 - This involves multiple configurations
683 * Initially SDR104 - when tuning is required as HS200
684 * Then when switching to DDR @ 400MHz (HS400) we use
685 * the vendor specific HC_SELECT_IN to control the mode.
686 *
687 * In addition to controlling the modes we also need to select the
688 * correct input clock for DLL depending on the mode.
689 *
690 * HS400 - divided clock (free running MCLK/2)
691 * All other modes - default (free running MCLK)
692 */
693 if (curr_ios.timing == MMC_TIMING_MMC_HS400) {
694 /* Select the divided clock (free running MCLK/2) */
695 config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
696 config &= ~CORE_HC_MCLK_SEL_MASK;
697 config |= CORE_HC_MCLK_SEL_HS400;
698
699 writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
700 /*
701 * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
702 * register
703 */
704 if (msm_host->tuning_done && !msm_host->calibration_done) {
705 /*
706 * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN
707 * field in VENDOR_SPEC_FUNC
708 */
709 config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
710 config |= CORE_HC_SELECT_IN_HS400;
711 config |= CORE_HC_SELECT_IN_EN;
712 writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
713 }
714 } else {
715 config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
716 config &= ~CORE_HC_MCLK_SEL_MASK;
717 config |= CORE_HC_MCLK_SEL_DFLT;
718 writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
719
720 /*
721 * Disable HC_SELECT_IN to be able to use the UHS mode select
722 * configuration from Host Control2 register for all other
723 * modes.
724 * Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field
725 * in VENDOR_SPEC_FUNC
726 */
727 config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
728 config &= ~CORE_HC_SELECT_IN_EN;
729 config &= ~CORE_HC_SELECT_IN_MASK;
730 writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
731 }
732
733 /*
734 * Make sure above writes impacting free running MCLK are completed
735 * before changing the clk_rate at GCC.
736 */
737 wmb();
Ritesh Harjaniedc609f2016-11-21 12:07:20 +0530738
739 rc = clk_set_rate(msm_host->clk, clock);
740 if (rc) {
Ritesh Harjanib12d44d2016-11-21 12:07:21 +0530741 pr_err("%s: Failed to set clock at rate %u at timing %d\n",
742 mmc_hostname(host->mmc), clock,
743 curr_ios.timing);
Ritesh Harjaniedc609f2016-11-21 12:07:20 +0530744 goto out_lock;
745 }
746 msm_host->clk_rate = clock;
Ritesh Harjanib12d44d2016-11-21 12:07:21 +0530747 pr_debug("%s: Setting clock at rate %lu at timing %d\n",
748 mmc_hostname(host->mmc), clk_get_rate(msm_host->clk),
749 curr_ios.timing);
Ritesh Harjaniedc609f2016-11-21 12:07:20 +0530750
751out_lock:
752 spin_lock_irq(&host->lock);
753out:
754 __sdhci_msm_set_clock(host, clock);
755}
756
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200757static const struct of_device_id sdhci_msm_dt_match[] = {
758 { .compatible = "qcom,sdhci-msm-v4" },
759 {},
760};
761
762MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match);
763
Jisheng Zhanga50396a2016-02-16 21:08:21 +0800764static const struct sdhci_ops sdhci_msm_ops = {
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200765 .platform_execute_tuning = sdhci_msm_execute_tuning,
Stephen Boyded1761d2014-06-10 11:27:19 -0700766 .reset = sdhci_reset,
Ritesh Harjaniedc609f2016-11-21 12:07:20 +0530767 .set_clock = sdhci_msm_set_clock,
Ritesh Harjani80031bd2016-11-21 12:07:17 +0530768 .get_min_clock = sdhci_msm_get_min_clock,
769 .get_max_clock = sdhci_msm_get_max_clock,
Stephen Boyded1761d2014-06-10 11:27:19 -0700770 .set_bus_width = sdhci_set_bus_width,
Ritesh Harjaniee320672016-07-19 17:52:25 +0300771 .set_uhs_signaling = sdhci_msm_set_uhs_signaling,
Georgi Djakovad81d382016-06-24 18:07:14 +0300772 .voltage_switch = sdhci_msm_voltage_switch,
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200773};
774
Jisheng Zhanga50396a2016-02-16 21:08:21 +0800775static const struct sdhci_pltfm_data sdhci_msm_pdata = {
776 .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
Georgi Djakov9718f842016-06-24 19:24:59 +0300777 SDHCI_QUIRK_NO_CARD_NO_RESET |
Ritesh Harjania0e31422016-11-21 12:07:18 +0530778 SDHCI_QUIRK_SINGLE_POWER_WRITE |
779 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
780 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
Jisheng Zhanga50396a2016-02-16 21:08:21 +0800781 .ops = &sdhci_msm_ops,
782};
783
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200784static int sdhci_msm_probe(struct platform_device *pdev)
785{
786 struct sdhci_host *host;
787 struct sdhci_pltfm_host *pltfm_host;
788 struct sdhci_msm_host *msm_host;
789 struct resource *core_memres;
790 int ret;
Georgi Djakov3a3ad3e2015-03-23 18:47:29 +0200791 u16 host_version, core_minor;
Ritesh Harjani29301f42016-11-21 12:07:13 +0530792 u32 core_version, config;
Georgi Djakov3a3ad3e2015-03-23 18:47:29 +0200793 u8 core_major;
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200794
Jisheng Zhang6f699532016-02-16 21:08:22 +0800795 host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host));
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200796 if (IS_ERR(host))
797 return PTR_ERR(host);
798
799 pltfm_host = sdhci_priv(host);
Jisheng Zhang6f699532016-02-16 21:08:22 +0800800 msm_host = sdhci_pltfm_priv(pltfm_host);
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200801 msm_host->mmc = host->mmc;
802 msm_host->pdev = pdev;
803
804 ret = mmc_of_parse(host->mmc);
805 if (ret)
806 goto pltfm_free;
807
808 sdhci_get_of_property(pdev);
809
Ritesh Harjaniabf270e2016-11-21 12:07:24 +0530810 msm_host->saved_tuning_phase = INVALID_TUNING_PHASE;
811
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200812 /* Setup SDCC bus voter clock. */
813 msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus");
814 if (!IS_ERR(msm_host->bus_clk)) {
815 /* Vote for max. clk rate for max. performance */
816 ret = clk_set_rate(msm_host->bus_clk, INT_MAX);
817 if (ret)
818 goto pltfm_free;
819 ret = clk_prepare_enable(msm_host->bus_clk);
820 if (ret)
821 goto pltfm_free;
822 }
823
824 /* Setup main peripheral bus clock */
825 msm_host->pclk = devm_clk_get(&pdev->dev, "iface");
826 if (IS_ERR(msm_host->pclk)) {
827 ret = PTR_ERR(msm_host->pclk);
Colin Ian King2801b952016-06-23 10:52:05 +0100828 dev_err(&pdev->dev, "Peripheral clk setup failed (%d)\n", ret);
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200829 goto bus_clk_disable;
830 }
831
832 ret = clk_prepare_enable(msm_host->pclk);
833 if (ret)
834 goto bus_clk_disable;
835
836 /* Setup SDC MMC clock */
837 msm_host->clk = devm_clk_get(&pdev->dev, "core");
838 if (IS_ERR(msm_host->clk)) {
839 ret = PTR_ERR(msm_host->clk);
840 dev_err(&pdev->dev, "SDC MMC clk setup failed (%d)\n", ret);
841 goto pclk_disable;
842 }
843
Venkat Gopalakrishnan83736352016-11-21 12:07:16 +0530844 /*
845 * xo clock is needed for FLL feature of cm_dll.
846 * In case if xo clock is not mentioned in DT, warn and proceed.
847 */
848 msm_host->xo_clk = devm_clk_get(&pdev->dev, "xo");
849 if (IS_ERR(msm_host->xo_clk)) {
850 ret = PTR_ERR(msm_host->xo_clk);
851 dev_warn(&pdev->dev, "TCXO clk not present (%d)\n", ret);
852 }
853
Ivan T. Ivanov951b8c82015-07-06 14:53:38 +0300854 /* Vote for maximum clock rate for maximum performance */
855 ret = clk_set_rate(msm_host->clk, INT_MAX);
856 if (ret)
857 dev_warn(&pdev->dev, "core clock boost failed\n");
858
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200859 ret = clk_prepare_enable(msm_host->clk);
860 if (ret)
861 goto pclk_disable;
862
863 core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
864 msm_host->core_mem = devm_ioremap_resource(&pdev->dev, core_memres);
865
866 if (IS_ERR(msm_host->core_mem)) {
867 dev_err(&pdev->dev, "Failed to remap registers\n");
868 ret = PTR_ERR(msm_host->core_mem);
869 goto clk_disable;
870 }
871
Ritesh Harjani29301f42016-11-21 12:07:13 +0530872 config = readl_relaxed(msm_host->core_mem + CORE_POWER);
873 config |= CORE_SW_RST;
874 writel_relaxed(config, msm_host->core_mem + CORE_POWER);
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200875
876 /* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
877 usleep_range(1000, 5000);
878 if (readl(msm_host->core_mem + CORE_POWER) & CORE_SW_RST) {
879 dev_err(&pdev->dev, "Stuck in reset\n");
880 ret = -ETIMEDOUT;
881 goto clk_disable;
882 }
883
884 /* Set HC_MODE_EN bit in HC_MODE register */
885 writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
886
Venkat Gopalakrishnanff06ce42016-11-21 12:07:23 +0530887 config = readl_relaxed(msm_host->core_mem + CORE_HC_MODE);
888 config |= FF_CLK_SW_RST_DIS;
889 writel_relaxed(config, msm_host->core_mem + CORE_HC_MODE);
890
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200891 host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
892 dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
893 host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >>
894 SDHCI_VENDOR_VER_SHIFT));
895
Georgi Djakov3a3ad3e2015-03-23 18:47:29 +0200896 core_version = readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION);
897 core_major = (core_version & CORE_VERSION_MAJOR_MASK) >>
898 CORE_VERSION_MAJOR_SHIFT;
899 core_minor = core_version & CORE_VERSION_MINOR_MASK;
900 dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n",
901 core_version, core_major, core_minor);
902
Venkat Gopalakrishnan83736352016-11-21 12:07:16 +0530903 if (core_major == 1 && core_minor >= 0x42)
904 msm_host->use_14lpp_dll_reset = true;
905
Georgi Djakov3a3ad3e2015-03-23 18:47:29 +0200906 /*
907 * Support for some capabilities is not advertised by newer
908 * controller versions and must be explicitly enabled.
909 */
910 if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) {
Ritesh Harjani29301f42016-11-21 12:07:13 +0530911 config = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES);
912 config |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
913 writel_relaxed(config, host->ioaddr +
Georgi Djakov3a3ad3e2015-03-23 18:47:29 +0200914 CORE_VENDOR_SPEC_CAPABILITIES0);
915 }
916
Georgi Djakovad81d382016-06-24 18:07:14 +0300917 /* Setup IRQ for handling power/voltage tasks with PMIC */
918 msm_host->pwr_irq = platform_get_irq_byname(pdev, "pwr_irq");
919 if (msm_host->pwr_irq < 0) {
920 dev_err(&pdev->dev, "Get pwr_irq failed (%d)\n",
921 msm_host->pwr_irq);
Wei Yongjund1f63f02016-10-26 15:04:41 +0000922 ret = msm_host->pwr_irq;
Georgi Djakovad81d382016-06-24 18:07:14 +0300923 goto clk_disable;
924 }
925
926 ret = devm_request_threaded_irq(&pdev->dev, msm_host->pwr_irq, NULL,
927 sdhci_msm_pwr_irq, IRQF_ONESHOT,
928 dev_name(&pdev->dev), host);
929 if (ret) {
930 dev_err(&pdev->dev, "Request IRQ failed (%d)\n", ret);
931 goto clk_disable;
932 }
933
Pramod Gurav67e6db12016-10-21 12:12:04 +0530934 pm_runtime_get_noresume(&pdev->dev);
935 pm_runtime_set_active(&pdev->dev);
936 pm_runtime_enable(&pdev->dev);
937 pm_runtime_set_autosuspend_delay(&pdev->dev,
938 MSM_MMC_AUTOSUSPEND_DELAY_MS);
939 pm_runtime_use_autosuspend(&pdev->dev);
940
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200941 ret = sdhci_add_host(host);
942 if (ret)
Pramod Gurav67e6db12016-10-21 12:12:04 +0530943 goto pm_runtime_disable;
944
945 pm_runtime_mark_last_busy(&pdev->dev);
946 pm_runtime_put_autosuspend(&pdev->dev);
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200947
948 return 0;
949
Pramod Gurav67e6db12016-10-21 12:12:04 +0530950pm_runtime_disable:
951 pm_runtime_disable(&pdev->dev);
952 pm_runtime_set_suspended(&pdev->dev);
953 pm_runtime_put_noidle(&pdev->dev);
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200954clk_disable:
955 clk_disable_unprepare(msm_host->clk);
956pclk_disable:
957 clk_disable_unprepare(msm_host->pclk);
958bus_clk_disable:
959 if (!IS_ERR(msm_host->bus_clk))
960 clk_disable_unprepare(msm_host->bus_clk);
961pltfm_free:
962 sdhci_pltfm_free(pdev);
963 return ret;
964}
965
966static int sdhci_msm_remove(struct platform_device *pdev)
967{
968 struct sdhci_host *host = platform_get_drvdata(pdev);
969 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
Jisheng Zhang6f699532016-02-16 21:08:22 +0800970 struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200971 int dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) ==
972 0xffffffff);
973
974 sdhci_remove_host(host, dead);
Pramod Gurav67e6db12016-10-21 12:12:04 +0530975
976 pm_runtime_get_sync(&pdev->dev);
977 pm_runtime_disable(&pdev->dev);
978 pm_runtime_put_noidle(&pdev->dev);
979
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200980 clk_disable_unprepare(msm_host->clk);
981 clk_disable_unprepare(msm_host->pclk);
982 if (!IS_ERR(msm_host->bus_clk))
983 clk_disable_unprepare(msm_host->bus_clk);
Jisheng Zhang6f699532016-02-16 21:08:22 +0800984 sdhci_pltfm_free(pdev);
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +0200985 return 0;
986}
987
Pramod Gurav67e6db12016-10-21 12:12:04 +0530988#ifdef CONFIG_PM
989static int sdhci_msm_runtime_suspend(struct device *dev)
990{
991 struct sdhci_host *host = dev_get_drvdata(dev);
992 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
993 struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
994
995 clk_disable_unprepare(msm_host->clk);
996 clk_disable_unprepare(msm_host->pclk);
997
998 return 0;
999}
1000
1001static int sdhci_msm_runtime_resume(struct device *dev)
1002{
1003 struct sdhci_host *host = dev_get_drvdata(dev);
1004 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
1005 struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
1006 int ret;
1007
1008 ret = clk_prepare_enable(msm_host->clk);
1009 if (ret) {
1010 dev_err(dev, "clk_enable failed for core_clk: %d\n", ret);
1011 return ret;
1012 }
1013 ret = clk_prepare_enable(msm_host->pclk);
1014 if (ret) {
1015 dev_err(dev, "clk_enable failed for iface_clk: %d\n", ret);
1016 clk_disable_unprepare(msm_host->clk);
1017 return ret;
1018 }
1019
1020 return 0;
1021}
1022#endif
1023
1024static const struct dev_pm_ops sdhci_msm_pm_ops = {
1025 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1026 pm_runtime_force_resume)
1027 SET_RUNTIME_PM_OPS(sdhci_msm_runtime_suspend,
1028 sdhci_msm_runtime_resume,
1029 NULL)
1030};
1031
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +02001032static struct platform_driver sdhci_msm_driver = {
1033 .probe = sdhci_msm_probe,
1034 .remove = sdhci_msm_remove,
1035 .driver = {
1036 .name = "sdhci_msm",
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +02001037 .of_match_table = sdhci_msm_dt_match,
Pramod Gurav67e6db12016-10-21 12:12:04 +05301038 .pm = &sdhci_msm_pm_ops,
Georgi Djakov0eb0d9f2014-03-10 17:37:12 +02001039 },
1040};
1041
1042module_platform_driver(sdhci_msm_driver);
1043
1044MODULE_DESCRIPTION("Qualcomm Secure Digital Host Controller Interface driver");
1045MODULE_LICENSE("GPL v2");