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