mmc: add support for rk3036
[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
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 /* Variations in Rockchip specific dw-mshc controller */
71 enum dw_mci_rockchip_type {
72         DW_MCI_TYPE_RK3188,
73         DW_MCI_TYPE_RK3288,
74         DW_MCI_TYPE_RK3036,
75 };
76
77 /* Rockchip implementation specific driver private data */
78 struct dw_mci_rockchip_priv_data {
79         enum dw_mci_rockchip_type               ctrl_type;
80         u8                              ciu_div;
81         u32                             sdr_timing;
82         u32                             ddr_timing;
83         u32                             cur_speed;
84 };
85
86 static struct dw_mci_rockchip_compatible {
87         char                            *compatible;
88         enum dw_mci_rockchip_type               ctrl_type;
89 } rockchip_compat[] = {
90         {
91                 .compatible     = "rockchip,rk31xx-sdmmc",
92                 .ctrl_type      = DW_MCI_TYPE_RK3188,
93         },{
94                 .compatible     = "rockchip,rk32xx-sdmmc",
95                 .ctrl_type      = DW_MCI_TYPE_RK3288,
96         },{
97                 .compatible     = "rockchip,rk3036-sdmmc",
98                 .ctrl_type      = DW_MCI_TYPE_RK3036,
99         },
100 };
101
102 static int dw_mci_rockchip_priv_init(struct dw_mci *host)
103 {
104         struct dw_mci_rockchip_priv_data *priv;
105         int idx;
106
107         priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
108         if(!priv){
109                 dev_err(host->dev, "mem alloc failed for private data\n");
110                 return -ENOMEM;
111         }
112
113         for(idx = 0; idx < ARRAY_SIZE(rockchip_compat); idx++){
114                 if(of_device_is_compatible(host->dev->of_node,
115                                 rockchip_compat[idx].compatible))
116                         priv->ctrl_type = rockchip_compat[idx].ctrl_type;
117         }
118
119         host->priv = priv;
120         return 0;
121 }
122
123 static int dw_mci_rockchip_setup_clock(struct dw_mci *host)
124 {
125         struct dw_mci_rockchip_priv_data *priv = host->priv;
126
127         if ((priv->ctrl_type == DW_MCI_TYPE_RK3288) ||
128                 (priv->ctrl_type == DW_MCI_TYPE_RK3036))
129                 host->bus_hz /= (priv->ciu_div + 1);
130
131         return 0;
132 }
133
134 static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
135 {
136
137 }
138
139 static void dw_mci_rockchip_set_ios(struct dw_mci *host, struct mmc_ios *ios)
140 {
141
142 }
143
144 static int dw_mci_rockchip_parse_dt(struct dw_mci *host)
145 {
146         return 0;
147 }
148 static inline u8 dw_mci_rockchip_get_delaynum(struct dw_mci *host, u8 con_id, u8 tuning_type)
149 {
150         u32 regs;
151         u8 delaynum;
152
153         regs =  cru_readl(CRU_SDMMC_CON(con_id, tuning_type));
154         delaynum = ((regs>>SDMMC_TUNING_DELAYNUM(tuning_type)) & 0xff);
155
156         return delaynum;
157 }
158
159 static inline void dw_mci_rockchip_set_delaynum(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 delaynum)
160 {
161         u32 regs;
162         regs = cru_readl(CRU_SDMMC_CON(con_id, tuning_type));
163         regs &= ~( 0xff << SDMMC_TUNING_DELAYNUM(tuning_type));
164         regs |= (delaynum  << SDMMC_TUNING_DELAYNUM(tuning_type));
165         regs |= (0xff  << (SDMMC_TUNING_DELAYNUM(tuning_type)+16));
166
167         MMC_DBG_INFO_FUNC(host->mmc,"tuning_result[delayline]: con_id = %d, tuning_type = %d, CRU_CON = 0x%x. [%s]",
168                 con_id, tuning_type, regs, mmc_hostname(host->mmc));
169
170         cru_writel(regs, CRU_SDMMC_CON(con_id, tuning_type));
171 }
172
173 static inline void dw_mci_rockchip_set_degree(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 phase)
174 {
175         u32 regs;
176         
177         regs = cru_readl(CRU_SDMMC_CON(con_id, tuning_type));
178         regs &= ~( 0x3 << SDMMC_TUNING_DEGREE(tuning_type));
179         regs |= (phase  << SDMMC_TUNING_DEGREE(tuning_type));
180         regs |= (0x3  << (SDMMC_TUNING_DEGREE(tuning_type)+16));
181
182         MMC_DBG_INFO_FUNC(host->mmc,"tuning_result[phase]: con_id = %d, tuning_type= %d, CRU_CON = 0x%x. [%s]",
183                 con_id, tuning_type, regs, mmc_hostname(host->mmc));
184         
185         cru_writel(regs, CRU_SDMMC_CON(con_id, tuning_type));
186 }
187
188 static inline void dw_mci_rockchip_turning_sel(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 mode)
189 {
190         u32 regs;
191         regs = cru_readl(CRU_SDMMC_CON(con_id, tuning_type)) ;
192         regs &= ~( 0x1 << SDMMC_TUNING_SEL(tuning_type));
193         regs |= (mode  << SDMMC_TUNING_SEL(tuning_type));
194         regs |= (0x1  << (SDMMC_TUNING_SEL(tuning_type)+16));
195
196         MMC_DBG_INFO_FUNC(host->mmc,"tuning_sel: con_id = %d, tuning_type = %d, CRU_CON = 0x%x. [%s]",
197                 con_id, tuning_type, regs, mmc_hostname(host->mmc));
198                 
199         cru_writel(regs, CRU_SDMMC_CON(con_id, tuning_type));       
200 }
201
202
203 static inline u8 dw_mci_rockchip_get_phase(struct dw_mci *host, u8 con_id, u8 tuning_type)
204 {
205         return 0;
206 }
207
208 static inline u8 dw_mci_rockchip_move_next_clksmpl(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 val)
209 {
210         u32 regs;
211         
212         regs = cru_readl(CRU_SDMMC_CON(con_id, tuning_type)) ;
213
214         if(tuning_type) {
215             val = ((regs>>SDMMC_TUNING_DELAYNUM(tuning_type)) & 0xff);
216         }
217
218         return val;
219 }
220
221 static void dw_mci_rockchip_load_tuning_base(void)
222 {
223         if(cpu_is_rk3288())
224                 cru_tuning_base =  RK3288_CRU_SDMMC_CON0;
225
226      /* Fixme: 3036
227         else if(cpu_is_rk3036())
228                 cru_tuning_base =  RK3036_CRU_SDMMC_CON0;
229      */
230 }
231
232 static int inline __dw_mci_rockchip_execute_tuning(struct dw_mci_slot *slot, u32 opcode,
233                                         u8 *blk_test, unsigned int blksz)
234 {
235         struct dw_mci *host = slot->host;
236         struct mmc_host *mmc = slot->mmc;       
237         struct mmc_request mrq = {NULL};
238         struct mmc_command cmd = {0};
239         struct mmc_command stop = {0};
240         struct mmc_data data = {0};
241         struct scatterlist sg;
242
243         cmd.opcode = opcode;
244         cmd.arg = 0;
245         cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
246         stop.opcode = MMC_STOP_TRANSMISSION;
247         stop.arg = 0;
248         stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
249         data.blksz = blksz;
250         data.blocks = 1;
251         data.flags = MMC_DATA_READ;
252         data.sg = &sg;
253         data.sg_len = 1;
254
255         sg_init_one(&sg, blk_test, blksz);
256         mrq.cmd = &cmd;
257         mrq.stop = &stop;
258         mrq.data = &data;
259         host->mrq = &mrq;
260         mci_writel(host, TMOUT, ~0);
261
262         mmc_wait_for_req(mmc, &mrq);
263         if(!cmd.error && !data.error){
264                 return 0;
265         }else{
266                 dev_dbg(host->dev,
267                         "Tuning error: cmd.error:%d, data.error:%d\n",cmd.error, data.error);
268                 return -EIO;
269         }
270         
271 }
272
273
274 static int dw_mci_rockchip_execute_tuning(struct dw_mci_slot *slot, u32 opcode,
275                                         struct dw_mci_tuning_data *tuning_data)
276 {
277         
278         struct dw_mci *host = slot->host;
279         u8 step;
280         u8 candidates_delayline[MAX_DELAY_LINE] = {0};
281         u8 candidates_degree[SDMMC_SHIFT_DEGREE_INVALID] = {4,4,4,4};
282         u8 index = 0;
283         u8 start_degree = 0;
284         u32 start_delayline = 0;
285         const u8 *blk_pattern = tuning_data->blk_pattern;
286         u8 *blk_test;
287         int ret = -1;
288         int ref = 0;
289         unsigned int blksz = tuning_data->blksz;
290
291         MMC_DBG_INFO_FUNC(host->mmc,"execute tuning:  [%s]", mmc_hostname(host->mmc));
292
293         dw_mci_rockchip_load_tuning_base();
294        
295         blk_test = kmalloc(blksz, GFP_KERNEL);
296         if (!blk_test)
297         {
298                 MMC_DBG_ERR_FUNC(host->mmc,"execute tuning:  blk_test kmalloc failed[%s]",
299                         mmc_hostname(host->mmc));
300                 return -ENOMEM;
301         }
302         
303         /* Select use delay line*/
304         dw_mci_rockchip_turning_sel(host, tuning_data->con_id, tuning_data->tuning_type,
305                                     USE_CLK_AFTER_PHASE_AND_DELAY_LINE);
306                                     
307         /* For RK32XX signoff 150M clk, 1 cycle = 6.66ns , and 1/4 phase = 1.66ns. 
308            Netlist level sample LT:  10.531ns / 42.126ps   WC: 19.695ns / 76.936ps.
309            So we take average --- 60ps, (1.66ns/ 2) = 0.83(middle-value),TAKE 0.9
310            0.9 / 60ps = 15 delayline
311          */
312         if(cpu_is_rk3288()){
313                 /* Fixme: 3036:  dose it compatitable? */
314                  ref = ((FREQ_REF_150MHZ + host->bus_hz - 1) / host->bus_hz);
315                  step = (15 * ref);
316
317                  if(step > MAX_DELAY_LINE){
318                         step = MAX_DELAY_LINE;       
319                         MMC_DBG_WARN_FUNC(host->mmc,
320                                         "execute tuning: TOO LARGE STEP![%s]", mmc_hostname(host->mmc));
321                  }              
322                  MMC_DBG_INFO_FUNC(host->mmc,
323                                 "execute tuning: SOC is RK3288, ref = %d, step = %d[%s]",
324                                 ref, step, mmc_hostname(host->mmc));
325                  
326         }else{              
327                  step = (15 * ((FREQ_REF_150MHZ / host->bus_hz) * 100)) / 100;
328
329                  if(step > MAX_DELAY_LINE){
330                         step = MAX_DELAY_LINE;
331                         MMC_DBG_WARN_FUNC(host->mmc,
332                                         "execute tuning: TOO LARGE STEP![%s]", mmc_hostname(host->mmc));
333                  }              
334                  MMC_DBG_INFO_FUNC(host->mmc,
335                                 "execute tuning: SOC is UNKNOWN, step = %d[%s]",
336                                 step, mmc_hostname(host->mmc));
337         }
338           
339         /* Loop degree from 0 ~ 270 */
340         for(start_degree = SDMMC_SHIFT_DEGREE_0; start_degree < SDMMC_SHIFT_DEGREE_270; start_degree++){
341
342                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, start_degree);
343                 if(0 == __dw_mci_rockchip_execute_tuning(slot, opcode, blk_test, blksz)){
344                         if(!memcmp(blk_pattern, blk_test, blksz)){
345                                 /* Successfully tuning in this condition*/                      
346                                 candidates_degree[index] = start_degree;
347                                 index++;
348                          }
349                }              
350                 
351         }
352         
353         MMC_DBG_INFO_FUNC(host->mmc,"\n execute tuning: candidates_degree = %s \t%s \t%s \t%s[%s]",
354                 phase_desc[candidates_degree[0]], phase_desc[candidates_degree[1]],
355                 phase_desc[candidates_degree[2]], phase_desc[candidates_degree[3]],
356                 mmc_hostname(host->mmc));
357
358         
359         if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_0)
360                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_90)
361                 && (candidates_degree[2] == SDMMC_SHIFT_DEGREE_180)){
362            
363                 MMC_DBG_INFO_FUNC(host->mmc,
364                                 "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_90 [%s]",
365                                 mmc_hostname(host->mmc));
366                                 
367                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, 
368                         tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_90);
369                 ret = 0;
370                 goto done;
371         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_90) 
372                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_180) 
373                 && (candidates_degree[2] == SDMMC_SHIFT_DEGREE_270)){
374                 MMC_DBG_INFO_FUNC(host->mmc,
375                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_180 [%s]",
376                         mmc_hostname(host->mmc));
377                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, 
378                         tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_180);
379                 ret = 0;
380                 goto done;
381         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_0) 
382                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_90) 
383                 && (candidates_degree[2] == SDMMC_SHIFT_DEGREE_INVALID)){
384
385                 MMC_DBG_INFO_FUNC(host->mmc,
386                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_0 ~  SDMMC_SHIFT_DEGREE_90[%s]",
387                         mmc_hostname(host->mmc));
388                 
389                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_0);
390                 #if PRECISE_ADJUST
391                 goto delayline; 
392                 #else              
393                 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
394                 ret = 0;
395                 goto done;  
396                 #endif       
397         }else if((candidates_degree[0]==SDMMC_SHIFT_DEGREE_0) 
398                 && (candidates_degree[1]==SDMMC_SHIFT_DEGREE_180)){
399
400                 MMC_DBG_INFO_FUNC(host->mmc,
401                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_0 AND SDMMC_SHIFT_DEGREE_180[%s]",
402                         mmc_hostname(host->mmc));
403
404                 /* FixMe: NO sense any signal indicator make this case happen*/
405                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_0);
406                 goto delayline;
407         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_90) 
408                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_180) 
409                 && (candidates_degree[2] == SDMMC_SHIFT_DEGREE_INVALID)){
410
411                 MMC_DBG_INFO_FUNC(host->mmc,
412                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_90 ~  SDMMC_SHIFT_DEGREE_180[%s]",
413                         mmc_hostname(host->mmc));
414                
415                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_90);
416                 #if PRECISE_ADJUST
417                 goto delayline; 
418                 #else              
419                 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
420                 ret = 0;
421                 goto done;  
422                 #endif                              
423         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_180) 
424                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_270)){
425
426                 MMC_DBG_INFO_FUNC(host->mmc,
427                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_180 ~  SDMMC_SHIFT_DEGREE_270[%s]",
428                         mmc_hostname(host->mmc));
429                         
430                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_180);
431                 #if PRECISE_ADJUST
432                 goto delayline; 
433                 #else              
434                 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
435                 ret = 0;
436                 goto done;  
437                 #endif                            
438         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_180) 
439                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_INVALID)){
440
441                 MMC_DBG_INFO_FUNC(host->mmc,
442                         "execute tuning: candidates_degree = [SDMMC_SHIFT_DEGREE_90 + n ~  SDMMC_SHIFT_DEGREE_180][%s]",
443                         mmc_hostname(host->mmc));             
444                 
445                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_90);
446                 #if PRECISE_ADJUST
447                 goto delayline; 
448                 #else
449                 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
450                 ret = 0;
451                 goto done;  
452                 #endif
453         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_90) 
454                 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_INVALID)){
455
456                 MMC_DBG_INFO_FUNC(host->mmc,
457                         "execute tuning: candidates_degree = [SDMMC_SHIFT_DEGREE_0 + n ~  SDMMC_SHIFT_DEGREE_90][%s]",
458                         mmc_hostname(host->mmc));             
459                 
460                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_0);
461                 #if PRECISE_ADJUST
462                 goto delayline; 
463                 #else
464                 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
465                 ret = 0;
466                 goto done;  
467                 #endif
468         }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_270)){
469
470                 MMC_DBG_INFO_FUNC(host->mmc,
471                         "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_270 [%s]",
472                         mmc_hostname(host->mmc));         
473
474                 /*FixME: so urgly signal indicator, HW engineer help!*/
475
476                 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_180);             
477                 #if PRECISE_ADJUST
478                 goto delayline; 
479                 #else
480                 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
481                 ret = 0;
482                 goto done;  
483                 #endif            
484         }else{
485                 MMC_DBG_ERR_FUNC(host->mmc,
486                                 "execute tuning: candidates_degree beyong limited case! [%s]",
487                                 mmc_hostname(host->mmc));
488                 if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC)
489                         BUG();
490                 return -EAGAIN;
491         }
492
493 delayline:
494                 index = 0;
495                 for(start_delayline = 0; start_delayline <= MAX_DELAY_LINE; start_delayline += step){
496                 
497                         dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, 
498                                 tuning_data->tuning_type, start_delayline);
499                         if(0 == __dw_mci_rockchip_execute_tuning(slot, opcode, blk_test, blksz)){
500                                 if(!memcmp(blk_pattern, blk_test, blksz)){
501                                         /* Successfully tuning in this condition*/                                        
502                                         candidates_delayline[index] = start_delayline;
503                                         index++; 
504                                 }
505                         }                    
506                 }
507                 if((index < 2) && (index != 0)) {
508                         MMC_DBG_INFO_FUNC(host->mmc,
509                                 "execute tuning: candidates_delayline failed for only one element [%s]",
510                                 mmc_hostname(host->mmc));
511
512                         /* Make step smaller, and re-calculate */
513                         step = step >> 1;
514                         index = 0;
515                         goto delayline;
516                 }else if(index >= 2){
517                         /* Find it! */
518                         MMC_DBG_INFO_FUNC(host->mmc,
519                                 "execute tuning: candidates_delayline calculate successfully  [%s]",
520                                 mmc_hostname(host->mmc));
521
522                         dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, 
523                                 tuning_data->tuning_type, candidates_delayline[index/2]); 
524                         ret = 0; 
525                         goto done;
526                 }
527         
528 done:
529         kfree(blk_test);
530         blk_test = NULL;
531         return ret;
532         
533 }
534
535 /* Common capabilities of RK32XX SoC */
536 static unsigned long rockchip_dwmmc_caps[4] = {
537         MMC_CAP_CMD23,
538         MMC_CAP_CMD23,
539         MMC_CAP_CMD23,
540         MMC_CAP_CMD23,
541 };
542
543 unsigned int  rockchip_dwmmc_hold_reg[4] = {1,0,0,0};
544
545 static const struct dw_mci_drv_data rockchip_drv_data = {
546         .caps                   = rockchip_dwmmc_caps,
547         .hold_reg_flag  = rockchip_dwmmc_hold_reg,
548         .init                   = dw_mci_rockchip_priv_init,
549         .setup_clock            = dw_mci_rockchip_setup_clock,
550         .prepare_command        = dw_mci_rockchip_prepare_command,
551         .set_ios                = dw_mci_rockchip_set_ios,
552         .parse_dt               = dw_mci_rockchip_parse_dt,
553         .execute_tuning         = dw_mci_rockchip_execute_tuning,
554 };
555
556 static const struct of_device_id dw_mci_rockchip_match[] = {
557         { .compatible = "rockchip,rk_mmc",
558                         .data = &rockchip_drv_data, },
559         { /* Sentinel */},
560 };
561 MODULE_DEVICE_TABLE(of, dw_mci_rockchip_match);
562
563 static int dw_mci_rockchip_probe(struct platform_device *pdev)
564 {
565         const struct dw_mci_drv_data *drv_data;
566         const struct of_device_id *match;
567         
568         match = of_match_node(dw_mci_rockchip_match, pdev->dev.of_node);
569         drv_data = match->data;
570         return dw_mci_pltfm_register(pdev, drv_data);
571 }
572
573 static struct platform_driver dw_mci_rockchip_pltfm_driver = {
574         .probe          = dw_mci_rockchip_probe,
575         .remove         = __exit_p(dw_mci_pltfm_remove),
576         .driver         = {
577                 .name           = "dwmmc_rockchip",
578                 .of_match_table = dw_mci_rockchip_match,
579                 .pm             = &dw_mci_pltfm_pmops,
580         },
581 };
582
583 module_platform_driver(dw_mci_rockchip_pltfm_driver);
584
585 MODULE_DESCRIPTION("Rockchip Specific DW-SDMMC Driver Extension");
586 MODULE_AUTHOR("Shawn Lin <lintao@rock-chips.com>");
587 MODULE_AUTHOR("Bangwang Xie <xbw@rock-chips.com>");
588 MODULE_LICENSE("GPL v2");
589 MODULE_ALIAS("platform:dwmmc-rockchip");