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