bacca5ea0a9c814c015e5b3e21940285055e23d4
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / host / dw_mmc-rockchip.c
1 /*
2  * Rockchip Specific Extensions for Synopsys DW Multimedia Card Interface driver
3  *
4  * Copyright (C) 2014, Rockchip Electronics Co., Ltd.
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 as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/clk.h>
15 #include <linux/mmc/host.h>
16 #include <linux/mmc/mmc.h>
17 #include <linux/mmc/rk_mmc.h>
18 #include <linux/of.h>
19 #include <linux/of_gpio.h>
20 #include <linux/slab.h>
21 #include <linux/rockchip/cpu.h>
22 #include <linux/rockchip/cru.h>
23 #include <linux/delay.h>
24 #include "rk_sdmmc.h"
25 #include "dw_mmc-pltfm.h"
26 #include "../../clk/rockchip/clk-ops.h"
27
28 #include "rk_sdmmc_dbg.h"
29
30 /*CRU SDMMC TUNING*/
31 /*
32 *   sdmmc,sdio0,sdio1,emmc id=0~3
33 *   cclk_in_drv, cclk_in_sample  i=0,1
34 */
35
36 static  u32 cru_tuning_base = 0;
37
38 #define CRU_SDMMC_CON(id, tuning_type)  (cru_tuning_base + ((id) * 8) + ((tuning_type) * 4))
39
40 #define MAX_DELAY_LINE  (0xff)
41 #define FREQ_REF_150MHZ (150000000)
42 #define PRECISE_ADJUST  (0)
43
44 #define SDMMC_TUNING_SEL(tuning_type)           ( tuning_type? 10:11 )
45 #define SDMMC_TUNING_DELAYNUM(tuning_type)      ( tuning_type? 2:3 )
46 #define SDMMC_TUNING_DEGREE(tuning_type)        ( tuning_type? 0:1 )
47 #define SDMMC_TUNING_INIT_STATE                 (0)
48
49 enum{
50        SDMMC_SHIFT_DEGREE_0 = 0,
51        SDMMC_SHIFT_DEGREE_90,
52        SDMMC_SHIFT_DEGREE_180,
53        SDMMC_SHIFT_DEGREE_270,
54        SDMMC_SHIFT_DEGREE_INVALID,
55 };
56
57 const char *phase_desc[SDMMC_SHIFT_DEGREE_INVALID + 1] = {
58         "SDMMC_SHIFT_DEGREE_0",
59         "SDMMC_SHIFT_DEGREE_90",
60         "SDMMC_SHIFT_DEGREE_180",
61         "SDMMC_SHIFT_DEGREE_270",
62         "SDMMC_SHIFT_DEGREE_INVALID",
63 };
64
65 enum{
66         USE_CLK_AFTER_PHASE = 0,
67         USE_CLK_AFTER_PHASE_AND_DELAY_LINE = 1,
68 };
69
70 enum{
71         IO_DRV_2MA  = 0x0,
72         IO_DRV_4MA  = 0x1,
73         IO_DRV_8MA  = 0x2,
74         IO_DRV_12MA = 0x3,
75 };
76
77 enum{
78         SLEW_RATE_SLOW = 0,
79         SLEW_RATE_FAST = 1,
80 };
81
82 /* Variations in Rockchip specific dw-mshc controller */
83 enum dw_mci_rockchip_type {
84         DW_MCI_TYPE_RK3188,
85         DW_MCI_TYPE_RK3288,
86         DW_MCI_TYPE_RK3036,
87         DW_MCI_TYPE_RK312X,
88 };
89
90 /* Rockchip implementation specific driver private data */
91 struct dw_mci_rockchip_priv_data {
92         enum dw_mci_rockchip_type               ctrl_type;
93         u8                              ciu_div;
94         u32                             sdr_timing;
95         u32                             ddr_timing;
96         u32                             cur_speed;
97 };
98
99 static struct dw_mci_rockchip_compatible {
100         char                            *compatible;
101         enum dw_mci_rockchip_type               ctrl_type;
102 } rockchip_compat[] = {
103         {
104                 .compatible     = "rockchip,rk31xx-sdmmc",
105                 .ctrl_type      = DW_MCI_TYPE_RK3188,
106         },{
107                 .compatible     = "rockchip,rk32xx-sdmmc",
108                 .ctrl_type      = DW_MCI_TYPE_RK3288,
109         },{
110                 .compatible     = "rockchip,rk3036-sdmmc",
111                 .ctrl_type      = DW_MCI_TYPE_RK3036,
112         },{
113                 .compatible     = "rockchip,rk312x-sdmmc",
114                 .ctrl_type      = DW_MCI_TYPE_RK312X,
115         },
116 };
117
118 static int dw_mci_rockchip_priv_init(struct dw_mci *host)
119 {
120         struct dw_mci_rockchip_priv_data *priv;
121         int idx;
122
123         priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
124         if(!priv){
125                 dev_err(host->dev, "mem alloc failed for private data\n");
126                 return -ENOMEM;
127         }
128
129         for(idx = 0; idx < ARRAY_SIZE(rockchip_compat); idx++){
130                 if(of_device_is_compatible(host->dev->of_node,
131                                 rockchip_compat[idx].compatible))
132                         priv->ctrl_type = rockchip_compat[idx].ctrl_type;
133         }
134
135         host->priv = priv;
136         return 0;
137 }
138
139 static int dw_mci_rockchip_setup_clock(struct dw_mci *host)
140 {
141         struct dw_mci_rockchip_priv_data *priv = host->priv;
142
143         if ((priv->ctrl_type == DW_MCI_TYPE_RK3288) ||
144                 (priv->ctrl_type == DW_MCI_TYPE_RK3036) ||
145                 (priv->ctrl_type == DW_MCI_TYPE_RK312X))
146                 host->bus_hz /= (priv->ciu_div + 1);
147
148         return 0;
149 }
150
151 static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
152 {
153
154 }
155
156 static void dw_mci_rockchip_set_ios(struct dw_mci *host, struct mmc_ios *ios)
157 {
158
159 }
160
161 static int dw_mci_rockchip_parse_dt(struct dw_mci *host)
162 {
163         return 0;
164 }
165 static inline u8 dw_mci_rockchip_get_delaynum(struct dw_mci *host, u8 con_id, u8 tuning_type)
166 {
167         u32 regs;
168         u8 delaynum;
169
170         regs =  cru_readl(CRU_SDMMC_CON(con_id, tuning_type));
171         delaynum = ((regs>>SDMMC_TUNING_DELAYNUM(tuning_type)) & 0xff);
172
173         return delaynum;
174 }
175
176 static inline void dw_mci_rockchip_set_delaynum(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 delaynum)
177 {
178         u32 regs;
179         regs = cru_readl(CRU_SDMMC_CON(con_id, tuning_type));
180         regs &= ~( 0xff << SDMMC_TUNING_DELAYNUM(tuning_type));
181         regs |= (delaynum  << SDMMC_TUNING_DELAYNUM(tuning_type));
182         regs |= (0xff  << (SDMMC_TUNING_DELAYNUM(tuning_type)+16));
183
184         MMC_DBG_INFO_FUNC(host->mmc,"tuning_result[delayline]: con_id = %d, tuning_type = %d, CRU_CON = 0x%x. [%s]",
185                 con_id, tuning_type, regs, mmc_hostname(host->mmc));
186
187         cru_writel(regs, CRU_SDMMC_CON(con_id, tuning_type));
188 }
189
190 static inline void dw_mci_rockchip_set_degree(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 phase)
191 {
192         u32 regs;
193         
194         regs = cru_readl(CRU_SDMMC_CON(con_id, tuning_type));
195         regs &= ~( 0x3 << SDMMC_TUNING_DEGREE(tuning_type));
196         regs |= (phase  << SDMMC_TUNING_DEGREE(tuning_type));
197         regs |= (0x3  << (SDMMC_TUNING_DEGREE(tuning_type)+16));
198
199         MMC_DBG_INFO_FUNC(host->mmc,"tuning_result[phase]: con_id = %d, tuning_type= %d, CRU_CON = 0x%x. [%s]",
200                 con_id, tuning_type, regs, mmc_hostname(host->mmc));
201         
202         cru_writel(regs, CRU_SDMMC_CON(con_id, tuning_type));
203 }
204
205 static inline void dw_mci_rockchip_turning_sel(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 mode)
206 {
207         u32 regs;
208         regs = cru_readl(CRU_SDMMC_CON(con_id, tuning_type)) ;
209         regs &= ~( 0x1 << SDMMC_TUNING_SEL(tuning_type));
210         regs |= (mode  << SDMMC_TUNING_SEL(tuning_type));
211         regs |= (0x1  << (SDMMC_TUNING_SEL(tuning_type)+16));
212
213         MMC_DBG_INFO_FUNC(host->mmc,"tuning_sel: con_id = %d, tuning_type = %d, CRU_CON = 0x%x. [%s]",
214                 con_id, tuning_type, regs, mmc_hostname(host->mmc));
215                 
216         cru_writel(regs, CRU_SDMMC_CON(con_id, tuning_type));       
217 }
218
219
220 static inline u8 dw_mci_rockchip_get_phase(struct dw_mci *host, u8 con_id, u8 tuning_type)
221 {
222         return 0;
223 }
224
225 static inline u8 dw_mci_rockchip_move_next_clksmpl(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 val)
226 {
227         u32 regs;
228         
229         regs = cru_readl(CRU_SDMMC_CON(con_id, tuning_type)) ;
230
231         if(tuning_type) {
232             val = ((regs>>SDMMC_TUNING_DELAYNUM(tuning_type)) & 0xff);
233         }
234
235         return val;
236 }
237
238 static void dw_mci_rockchip_load_signal_integrity(struct dw_mci *host, u32 sr, u32 drv)
239 {
240         if (unlikely((drv > IO_DRV_12MA) || (sr > SLEW_RATE_FAST))) {
241                 MMC_DBG_ERR_FUNC(host->mmc,"wrong signal integrity setting: drv = %d, sr = %d ![%s]",
242                         drv, sr, mmc_hostname(host->mmc));
243                 return;
244         }
245
246         if(cpu_is_rk3288()){
247                 /*Note 00: 2ma 01:4ma 10:8ma 11:12ma
248                 For consider line loading and IP's slew rate,
249                 we should match these by every board depends for signal integrity.
250                 slew rate >= 2*pi*f*Vpeak = max(|d'(Vpeak)/dt|)
251                 */
252                 if (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO) {
253                         grf_writel(0xff005500 | (drv << 14) | (drv << 12) |
254                                                  (drv << 10) | (drv << 8), 0x01f8); /* GPIO4C4-C7 */
255                         grf_writel(0x000f0000 | (drv << 0) | (drv << 2), 0x01fc); /* GPIO4D0-D1 */
256                         grf_writel(0x03f00000 | (sr << 4) | (sr << 5) | (sr << 6) |
257                                                 (sr << 7) | (sr << 8) | (sr << 9) , 0x011c); /* slew rate*/
258                 }else if (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) {
259                         grf_writel(0x3fff0000 | (drv << 0) | (drv << 2) | (drv << 4) |
260                                                  (drv << 6) | (drv << 8) | (drv << 10) |
261                                                  (drv << 12), 0x0218); /* GPIO6C0-C6 */
262                         grf_writel(0x003f0000 | (sr << 0) | (sr << 1) | (sr << 2) |
263                                                 (sr << 3) | (sr << 4) | (sr << 5), 0x012c); /* slew rate */
264                 }else if (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC) {
265                         /* emmc hardware relative addr match requirement, assume 4ma not slow slew rate */
266                         grf_writel(0xffff5555, 0x01e0); /* GPIO3A0-A7 */
267                         grf_writel(0x000c0006, 0x01e4); /* GPIO3B1 */
268                         grf_writel(0x003f0015, 0x01e8); /* GPIO3C2-C0 */
269                 }
270         }
271
272 }
273 static void dw_mci_rockchip_load_tuning_base(void)
274 {
275         /* load tuning base */
276         if(cpu_is_rk3288())
277                 cru_tuning_base =  RK3288_CRU_SDMMC_CON0;
278 }
279
280 static int inline __dw_mci_rockchip_execute_tuning(struct dw_mci_slot *slot, u32 opcode,
281                                         u8 *blk_test, unsigned int blksz)
282 {
283         struct dw_mci *host = slot->host;
284         struct mmc_host *mmc = slot->mmc;       
285         struct mmc_request mrq = {NULL};
286         struct mmc_command cmd = {0};
287         struct mmc_command stop = {0};
288         struct mmc_data data = {0};
289         struct scatterlist sg;
290
291         cmd.opcode = opcode;
292         cmd.arg = 0;
293         cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
294         stop.opcode = MMC_STOP_TRANSMISSION;
295         stop.arg = 0;
296         stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
297         data.blksz = blksz;
298         data.blocks = 1;
299         data.flags = MMC_DATA_READ;
300         data.sg = &sg;
301         data.sg_len = 1;
302
303         sg_init_one(&sg, blk_test, blksz);
304         mrq.cmd = &cmd;
305         mrq.stop = &stop;
306         mrq.data = &data;
307         host->mrq = &mrq;
308         mci_writel(host, TMOUT, ~0);
309
310         mmc_wait_for_req(mmc, &mrq);
311         if(!cmd.error && !data.error){
312                 return 0;
313         }else{
314                 dev_dbg(host->dev,
315                         "Tuning error: cmd.error:%d, data.error:%d\n",cmd.error, data.error);
316                 return -EIO;
317         }
318         
319 }
320
321
322 static int dw_mci_rockchip_execute_tuning(struct dw_mci_slot *slot, u32 opcode,
323                                         struct dw_mci_tuning_data *tuning_data)
324 {
325         
326         struct dw_mci *host = slot->host;
327         u8 step;
328         u8 candidates_delayline[MAX_DELAY_LINE] = {0};
329         u8 candidates_degree[SDMMC_SHIFT_DEGREE_INVALID] = {4,4,4,4};
330         u8 default_drv;
331         u8 index = 0;
332         u8 start_degree = 0;
333         u32 start_delayline = 0;
334         const u8 *blk_pattern = tuning_data->blk_pattern;
335         u8 *blk_test;
336         int ret = -1;
337         int ref = 0;
338         unsigned int blksz = tuning_data->blksz;
339
340         MMC_DBG_INFO_FUNC(host->mmc,"execute tuning:  [%s]", mmc_hostname(host->mmc));
341
342         dw_mci_rockchip_load_tuning_base();
343
344         blk_test = kmalloc(blksz, GFP_KERNEL);
345         if (!blk_test)
346         {
347                 MMC_DBG_ERR_FUNC(host->mmc,"execute tuning:  blk_test kmalloc failed[%s]",
348                         mmc_hostname(host->mmc));
349                 return -ENOMEM;
350         }
351         
352         /* Select use delay line*/
353         dw_mci_rockchip_turning_sel(host, tuning_data->con_id, tuning_data->tuning_type,
354                                     USE_CLK_AFTER_PHASE_AND_DELAY_LINE);
355                                     
356         /* For RK32XX signoff 150M clk, 1 cycle = 6.66ns , and 1/4 phase = 1.66ns. 
357            Netlist level sample LT:  10.531ns / 42.126ps   WC: 19.695ns / 76.936ps.
358            So we take average --- 60ps, (1.66ns/ 2) = 0.83(middle-value),TAKE 0.9
359            0.9 / 60ps = 15 delayline
360          */
361         if (cpu_is_rk3288() && !(rockchip_get_cpu_version() > 0)) {
362                 /* RK3288, non-eco */
363                 ref = DIV_ROUND_UP(FREQ_REF_150MHZ, host->bus_hz);
364                 step = (15 * ref);
365
366                 if (step > MAX_DELAY_LINE) {
367                         step = MAX_DELAY_LINE;       
368                         MMC_DBG_WARN_FUNC(host->mmc,
369                                         "execute tuning: TOO LARGE STEP![%s]", mmc_hostname(host->mmc));
370                 }
371                 MMC_DBG_INFO_FUNC(host->mmc,
372                                 "execute tuning: SOC is RK3288, ref = %d, step = %d[%s]",
373                                 ref, step, mmc_hostname(host->mmc));
374                  
375         } else {
376                 step = (15 * ((FREQ_REF_150MHZ / host->bus_hz) * 100)) / 100;
377
378                 if (step > MAX_DELAY_LINE) {
379                         step = MAX_DELAY_LINE;
380                         MMC_DBG_WARN_FUNC(host->mmc,
381                                         "execute tuning: TOO LARGE STEP![%s]", mmc_hostname(host->mmc));
382                 }
383                 MMC_DBG_INFO_FUNC(host->mmc,
384                                 "execute tuning: SOC is UNKNOWN, step = %d[%s]",
385                                 step, mmc_hostname(host->mmc));
386         }
387
388 re_phase:
389         /* calcute slew rate & drv strength in timing tuning */
390         if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)
391                 default_drv = IO_DRV_4MA;
392         else
393                 default_drv = IO_DRV_8MA;
394
395         dw_mci_rockchip_load_signal_integrity(host, SLEW_RATE_SLOW, default_drv);
396         /* Loop degree from 0 ~ 270 */
397         for(start_degree = SDMMC_SHIFT_DEGREE_0; start_degree < SDMMC_SHIFT_DEGREE_270; start_degree++){
398                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, start_degree);
399                 if(0 == __dw_mci_rockchip_execute_tuning(slot, opcode, blk_test, blksz)){
400                         if(!memcmp(blk_pattern, blk_test, blksz)){
401                                 /* Successfully tuning in this condition*/                      
402                                 candidates_degree[index] = start_degree;
403                                 index++;
404                          }
405                 }
406                 /* eMMC spec does not require a delay between tuning cycles
407                  * but eMMC should be guaranteed to complete a sequence of 40 times CMD21
408                  * withnin 150ms, some eMMC may limit 4ms gap between any two sequential CMD21
409                  */
410                 if (opcode == MMC_SEND_TUNING_BLOCK)
411                         mdelay(1);
412                 else
413                         /* MMC_SEND_TUNING_BLOCK_HS200 */
414                         mdelay(5);
415         }
416         
417         MMC_DBG_BOOT_FUNC(host->mmc,"\n execute tuning: candidates_degree = %s \t%s \t%s \t%s[%s]",
418                 phase_desc[candidates_degree[0]], phase_desc[candidates_degree[1]],
419                 phase_desc[candidates_degree[2]], phase_desc[candidates_degree[3]],
420                 mmc_hostname(host->mmc));
421
422         
423         if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_0)
424                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_90)
425                 && (candidates_degree[2] == SDMMC_SHIFT_DEGREE_180)){
426            
427                 MMC_DBG_INFO_FUNC(host->mmc,
428                                 "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_90 [%s]",
429                                 mmc_hostname(host->mmc));
430                                 
431                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, 
432                         tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_90);
433                 ret = 0;
434                 goto done;
435         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_90) 
436                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_180) 
437                 && (candidates_degree[2] == SDMMC_SHIFT_DEGREE_270)){
438                 MMC_DBG_INFO_FUNC(host->mmc,
439                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_180 [%s]",
440                         mmc_hostname(host->mmc));
441                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, 
442                         tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_180);
443                 ret = 0;
444                 goto done;
445         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_0) 
446                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_90) 
447                 && (candidates_degree[2] == SDMMC_SHIFT_DEGREE_INVALID)){
448
449                 MMC_DBG_INFO_FUNC(host->mmc,
450                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_0 ~  SDMMC_SHIFT_DEGREE_90[%s]",
451                         mmc_hostname(host->mmc));
452                 
453                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_0);
454                 #if PRECISE_ADJUST
455                 goto delayline; 
456                 #else              
457                 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
458                 ret = 0;
459                 goto done;  
460                 #endif       
461         }else if((candidates_degree[0]==SDMMC_SHIFT_DEGREE_0) 
462                 && (candidates_degree[1]==SDMMC_SHIFT_DEGREE_180)){
463
464                 MMC_DBG_INFO_FUNC(host->mmc,
465                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_0 AND SDMMC_SHIFT_DEGREE_180[%s]",
466                         mmc_hostname(host->mmc));
467
468                 /* FixMe: NO sense any signal indicator make this case happen*/
469                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_0);
470                 goto delayline;
471         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_90) 
472                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_180) 
473                 && (candidates_degree[2] == SDMMC_SHIFT_DEGREE_INVALID)){
474
475                 MMC_DBG_INFO_FUNC(host->mmc,
476                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_90 ~  SDMMC_SHIFT_DEGREE_180[%s]",
477                         mmc_hostname(host->mmc));
478                
479                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_90);
480                 #if PRECISE_ADJUST
481                 goto delayline; 
482                 #else              
483                 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
484                 ret = 0;
485                 goto done;  
486                 #endif                              
487         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_180) 
488                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_270)){
489
490                 MMC_DBG_INFO_FUNC(host->mmc,
491                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_180 ~  SDMMC_SHIFT_DEGREE_270[%s]",
492                         mmc_hostname(host->mmc));
493                         
494                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_180);
495                 #if PRECISE_ADJUST
496                 goto delayline; 
497                 #else              
498                 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
499                 ret = 0;
500                 goto done;
501                 #endif
502         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_180) 
503                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_INVALID)){
504
505                 MMC_DBG_INFO_FUNC(host->mmc,
506                         "execute tuning: candidates_degree = [SDMMC_SHIFT_DEGREE_90 + n ~  SDMMC_SHIFT_DEGREE_180][%s]",
507                         mmc_hostname(host->mmc));             
508                 
509                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_90);
510                 #if PRECISE_ADJUST
511                 goto delayline;
512                 #else
513                 default_drv++;
514                 goto re_phase;
515                 //dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
516                 //ret = 0;
517                 //goto done;
518                 #endif
519         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_90) 
520                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_INVALID)){
521
522                 MMC_DBG_INFO_FUNC(host->mmc,
523                         "execute tuning: candidates_degree = [SDMMC_SHIFT_DEGREE_0 + n ~  SDMMC_SHIFT_DEGREE_90][%s]",
524                         mmc_hostname(host->mmc));             
525                 
526                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_0);
527                 #if PRECISE_ADJUST
528                 goto delayline; 
529                 #else
530                 default_drv++;
531                 goto re_phase;
532                 //dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
533                 //ret = 0;
534                 //goto done;
535                 #endif
536         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_270)){
537
538                 MMC_DBG_INFO_FUNC(host->mmc,
539                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_270 [%s]",
540                         mmc_hostname(host->mmc));         
541
542                 /*FixME: so urgly signal indicator, HW engineer help!*/
543
544                 //dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_180);
545                 #if PRECISE_ADJUST
546                 goto delayline; 
547                 #else
548                 default_drv++;
549                 goto re_phase;
550                 //dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
551                 //ret = 0;
552                 //goto done;
553                 #endif            
554         }else{
555                 MMC_DBG_ERR_FUNC(host->mmc,
556                                 "execute tuning: candidates_degree beyong limited case! [%s]",
557                                 mmc_hostname(host->mmc));
558                 default_drv++;
559                 goto re_phase;
560                 if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC)
561                         BUG();
562                 return -EAGAIN;
563         }
564
565 delayline:
566                 index = 0;
567                 for(start_delayline = 0; start_delayline <= MAX_DELAY_LINE; start_delayline += step){
568                 
569                         dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, 
570                                 tuning_data->tuning_type, start_delayline);
571                         if(0 == __dw_mci_rockchip_execute_tuning(slot, opcode, blk_test, blksz)){
572                                 if(!memcmp(blk_pattern, blk_test, blksz)){
573                                         /* Successfully tuning in this condition*/                                        
574                                         candidates_delayline[index] = start_delayline;
575                                         index++; 
576                                 }
577                         }                    
578                 }
579                 if((index < 2) && (index != 0)) {
580                         /* setup 400ps, consider line loading, at least 600ps wc.
581                            for 150M, 15 steps =900ps ,too larger scale, should step smaller in principle
582                          */
583                         MMC_DBG_INFO_FUNC(host->mmc,
584                                 "execute tuning: candidates_delayline failed for no enough elements [%s]",
585                                 mmc_hostname(host->mmc));
586
587                         /* Make step smaller, and re-calculate */
588                         step = step >> 1;
589                         index = 0;
590                         goto delayline;
591                 }else if(index >= 2){
592                         /* Find it! */
593                         MMC_DBG_INFO_FUNC(host->mmc,
594                                 "execute tuning: candidates_delayline calculate successfully  [%s]",
595                                 mmc_hostname(host->mmc));
596
597                         dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, 
598                                 tuning_data->tuning_type, candidates_delayline[index/2]); 
599                         ret = 0; 
600                         goto done;
601                 }
602         
603 done:
604         kfree(blk_test);
605         blk_test = NULL;
606         return ret;
607         
608 }
609
610 /* Common capabilities of RK32XX SoC */
611 static unsigned long rockchip_dwmmc_caps[4] = {
612         MMC_CAP_CMD23,
613         MMC_CAP_CMD23,
614         MMC_CAP_CMD23,
615         MMC_CAP_CMD23,
616 };
617
618 unsigned int  rockchip_dwmmc_hold_reg[4] = {1,0,0,0};
619
620 static const struct dw_mci_drv_data rockchip_drv_data = {
621         .caps                   = rockchip_dwmmc_caps,
622         .hold_reg_flag  = rockchip_dwmmc_hold_reg,
623         .init                   = dw_mci_rockchip_priv_init,
624         .setup_clock            = dw_mci_rockchip_setup_clock,
625         .prepare_command        = dw_mci_rockchip_prepare_command,
626         .set_ios                = dw_mci_rockchip_set_ios,
627         .parse_dt               = dw_mci_rockchip_parse_dt,
628         .execute_tuning         = dw_mci_rockchip_execute_tuning,
629 };
630
631 static const struct of_device_id dw_mci_rockchip_match[] = {
632         { .compatible = "rockchip,rk_mmc",
633                         .data = &rockchip_drv_data, },
634         { /* Sentinel */},
635 };
636 MODULE_DEVICE_TABLE(of, dw_mci_rockchip_match);
637
638 static int dw_mci_rockchip_probe(struct platform_device *pdev)
639 {
640         const struct dw_mci_drv_data *drv_data;
641         const struct of_device_id *match;
642         
643         match = of_match_node(dw_mci_rockchip_match, pdev->dev.of_node);
644         drv_data = match->data;
645         return dw_mci_pltfm_register(pdev, drv_data);
646 }
647
648 static struct platform_driver dw_mci_rockchip_pltfm_driver = {
649         .probe          = dw_mci_rockchip_probe,
650         .remove         = __exit_p(dw_mci_pltfm_remove),
651         .driver         = {
652                 .name           = "dwmmc_rockchip",
653                 .of_match_table = dw_mci_rockchip_match,
654                 .pm             = &dw_mci_pltfm_pmops,
655         },
656 };
657
658 module_platform_driver(dw_mci_rockchip_pltfm_driver);
659
660 MODULE_DESCRIPTION("Rockchip Specific DW-SDMMC Driver Extension");
661 MODULE_AUTHOR("Shawn Lin <lintao@rock-chips.com>");
662 MODULE_AUTHOR("Bangwang Xie <xbw@rock-chips.com>");
663 MODULE_LICENSE("GPL v2");
664 MODULE_ALIAS("platform:dwmmc-rockchip");