2 * Rockchip Specific Extensions for Synopsys DW Multimedia Card Interface driver
4 * Copyright (C) 2014, Rockchip Electronics Co., Ltd.
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.
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>
19 #include <linux/of_gpio.h>
20 #include <linux/slab.h>
21 #include <linux/rockchip/cpu.h>
24 #include "dw_mmc-pltfm.h"
25 #include "../../clk/rockchip/clk-ops.h"
27 #include "rk_sdmmc_of.h"
31 * sdmmc,sdio0,sdio1,emmc id=0~3
32 * cclk_in_drv, cclk_in_sample i=0,1
34 #define CRU_SDMMC_CON(id, tuning_type) (0x200 + ((id) * 8) + ((tuning_type) * 4))
36 #define MAX_DELAY_LINE (0xff)
37 #define FREQ_REF_150MHZ (150000000)
38 #define PRECISE_ADJUST (0)
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)
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,
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",
62 USE_CLK_AFTER_PHASE = 0,
63 USE_CLK_AFTER_PHASE_AND_DELAY_LINE = 1,
66 /* Variations in Rockchip specific dw-mshc controller */
67 enum dw_mci_rockchip_type {
72 /* Rockchip implementation specific driver private data */
73 struct dw_mci_rockchip_priv_data {
74 enum dw_mci_rockchip_type ctrl_type;
81 static struct dw_mci_rockchip_compatible {
83 enum dw_mci_rockchip_type ctrl_type;
84 } rockchip_compat[] = {
86 .compatible = "rockchip,rk31xx-sdmmc",
87 .ctrl_type = DW_MCI_TYPE_RK3188,
89 .compatible = "rockchip,rk32xx-sdmmc",
90 .ctrl_type = DW_MCI_TYPE_RK3288,
94 static int dw_mci_rockchip_priv_init(struct dw_mci *host)
96 struct dw_mci_rockchip_priv_data *priv;
99 priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
101 dev_err(host->dev, "mem alloc failed for private data\n");
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;
115 static int dw_mci_rockchip_setup_clock(struct dw_mci *host)
117 struct dw_mci_rockchip_priv_data *priv = host->priv;
119 if (priv->ctrl_type == DW_MCI_TYPE_RK3288)
120 host->bus_hz /= (priv->ciu_div + 1);
125 static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
127 // if (SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL)))
128 // *cmdr |= SDMMC_CMD_USE_HOLD_REG;
131 static void dw_mci_rockchip_set_ios(struct dw_mci *host, struct mmc_ios *ios)
136 static int dw_mci_rockchip_parse_dt(struct dw_mci *host)
140 static inline u8 dw_mci_rockchip_get_delaynum(struct dw_mci *host, u8 con_id, u8 tuning_type)
145 regs = cru_readl(CRU_SDMMC_CON(con_id, tuning_type));
146 delaynum = ((regs>>SDMMC_TUNING_DELAYNUM(tuning_type)) & 0xff);
151 static inline void dw_mci_rockchip_set_delaynum(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 delaynum)
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));
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));
162 cru_writel(regs, CRU_SDMMC_CON(con_id, tuning_type));
165 static inline void dw_mci_rockchip_set_degree(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 phase)
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));
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));
177 cru_writel(regs, CRU_SDMMC_CON(con_id, tuning_type));
180 static inline void dw_mci_rockchip_turning_sel(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 mode)
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));
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));
191 cru_writel(regs, CRU_SDMMC_CON(con_id, tuning_type));
195 static inline u8 dw_mci_rockchip_get_phase(struct dw_mci *host, u8 con_id, u8 tuning_type)
200 static inline u8 dw_mci_rockchip_move_next_clksmpl(struct dw_mci *host, u8 con_id, u8 tuning_type, u8 val)
204 regs = cru_readl(CRU_SDMMC_CON(con_id, tuning_type)) ;
207 val = ((regs>>SDMMC_TUNING_DELAYNUM(tuning_type)) & 0xff);
214 static u8 dw_mci_rockchip_get_best_clksmpl(u8 *candiates)
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))
231 static int inline __dw_mci_rockchip_execute_tuning(struct dw_mci_slot *slot, u32 opcode,
232 u8 *blk_test, unsigned int blksz)
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;
244 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
245 stop.opcode = MMC_STOP_TRANSMISSION;
247 stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
250 data.flags = MMC_DATA_READ;
254 sg_init_one(&sg, blk_test, blksz);
259 mci_writel(host, TMOUT, ~0);
261 mmc_wait_for_req(mmc, &mrq);
262 if(!cmd.error && !data.error){
266 "Tuning error: cmd.error:%d, data.error:%d\n",cmd.error, data.error);
273 static int dw_mci_rockchip_execute_tuning(struct dw_mci_slot *slot, u32 opcode,
274 struct dw_mci_tuning_data *tuning_data)
277 struct dw_mci *host = slot->host;
279 u8 candidates_delayline[MAX_DELAY_LINE] = {0};
280 u8 candidates_degree[SDMMC_SHIFT_DEGREE_INVALID] = {4,4,4,4};
283 u32 start_delayline = 0;
284 u8 *blk_pattern = tuning_data->blk_pattern;
288 unsigned int blksz = tuning_data->blksz;
290 MMC_DBG_INFO_FUNC(host->mmc,"execute tuning: [%s]", mmc_hostname(host->mmc));
292 blk_test = kmalloc(blksz, GFP_KERNEL);
295 MMC_DBG_ERR_FUNC(host->mmc,"execute tuning: blk_test kmalloc failed[%s]",
296 mmc_hostname(host->mmc));
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);
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
310 ref = ((FREQ_REF_150MHZ + host->bus_hz - 1) / host->bus_hz);
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));
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));
323 step = (15 * ((FREQ_REF_150MHZ / host->bus_hz) * 100)) / 100;
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));
330 MMC_DBG_INFO_FUNC(host->mmc,
331 "execute tuning: SOC is UNKNOWN, step = %d[%s]",
332 step, mmc_hostname(host->mmc));
335 /* Loop degree from 0 ~ 270 */
336 for(start_degree = SDMMC_SHIFT_DEGREE_0; start_degree < SDMMC_SHIFT_DEGREE_270; start_degree++){
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;
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));
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)){
359 MMC_DBG_INFO_FUNC(host->mmc,
360 "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_90 [%s]",
361 mmc_hostname(host->mmc));
363 dw_mci_rockchip_set_degree(host, tuning_data->con_id,
364 tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_90);
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);
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)){
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));
385 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_0);
389 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
393 }else if((candidates_degree[0]==SDMMC_SHIFT_DEGREE_0)
394 && (candidates_degree[1]==SDMMC_SHIFT_DEGREE_180)){
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));
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);
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)){
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));
411 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_90);
415 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
419 }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_180)
420 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_270)){
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));
426 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_180);
430 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
434 }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_180)
435 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_INVALID)){
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));
441 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_90);
445 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
449 }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_90)
450 && (candidates_degree[1] == SDMMC_SHIFT_DEGREE_INVALID)){
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));
456 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_0);
460 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
464 }else if((candidates_degree[0] == SDMMC_SHIFT_DEGREE_270)){
466 MMC_DBG_INFO_FUNC(host->mmc,
467 "execute tuning: candidates_degree = SDMMC_SHIFT_DEGREE_270 [%s]",
468 mmc_hostname(host->mmc));
470 /*FixME: so urgly signal indicator, HW engineer help!*/
472 dw_mci_rockchip_set_degree(host, tuning_data->con_id, tuning_data->tuning_type, SDMMC_SHIFT_DEGREE_180);
476 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id, tuning_data->tuning_type, step);
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)
491 for(start_delayline = 0; start_delayline <= MAX_DELAY_LINE; start_delayline += step){
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;
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));
508 /* Make step smaller, and re-calculate */
512 }else if(index >= 2){
514 MMC_DBG_INFO_FUNC(host->mmc,
515 "execute tuning: candidates_delayline calculate successfully [%s]",
516 mmc_hostname(host->mmc));
518 dw_mci_rockchip_set_delaynum(host, tuning_data->con_id,
519 tuning_data->tuning_type, candidates_delayline[index/2]);
531 /* Common capabilities of RK32XX SoC */
532 static unsigned long rockchip_dwmmc_caps[4] = {
539 unsigned int rockchip_dwmmc_hold_reg[4] = {1,0,0,0};
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,
552 static const struct of_device_id dw_mci_rockchip_match[] = {
553 { .compatible = "rockchip,rk_mmc",
554 .data = &rockchip_drv_data, },
557 MODULE_DEVICE_TABLE(of, dw_mci_rockchip_match);
560 extern void rockchip_mmc_of_probe(struct device_node *np,struct rk_sdmmc_of *mmc_property);
563 static int dw_mci_rockchip_probe(struct platform_device *pdev)
565 const struct dw_mci_drv_data *drv_data;
566 const struct of_device_id *match;
569 struct device_node *np = pdev->dev.of_node;
570 struct rk_sdmmc_of *rk_mmc_property = NULL;
572 rk_mmc_property = (struct rk_sdmmc_of *)kmalloc(sizeof(struct rk_sdmmc_of),GFP_KERNEL);
573 if(NULL == rk_mmc_property)
575 kfree(rk_mmc_property);
576 rk_mmc_property = NULL;
577 printk("rk_mmc_property malloc space failed!\n");
581 rockchip_mmc_of_probe(np,rk_mmc_property);
582 #endif /*DW_MMC_OF_PROBE*/
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);
590 static struct platform_driver dw_mci_rockchip_pltfm_driver = {
591 .probe = dw_mci_rockchip_probe,
592 .remove = __exit_p(dw_mci_pltfm_remove),
594 .name = "dwmmc_rockchip",
595 .of_match_table = dw_mci_rockchip_match,
596 .pm = &dw_mci_pltfm_pmops,
600 module_platform_driver(dw_mci_rockchip_pltfm_driver);
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");