9
9
#include <linux/dma-mapping.h>
10
10
#include <linux/highmem.h>
11
11
#include <linux/iopoll.h>
12
+ #include <linux/mmc/host.h>
13
+ #include <linux/mmc/mmc.h>
12
14
#include <linux/module.h>
13
15
#include <linux/of.h>
14
16
#include <linux/of_gpio.h>
72
74
#define SDHCI_SPRD_CLK_DEF_RATE 26000000
73
75
#define SDHCI_SPRD_PHY_DLL_CLK 52000000
74
76
77
+ #define SDHCI_SPRD_MAX_RANGE 0xff
78
+ #define SDHCI_SPRD_CMD_DLY_MASK GENMASK(15, 8)
79
+ #define SDHCI_SPRD_POSRD_DLY_MASK GENMASK(23, 16)
80
+ #define SDHCI_SPRD_CPST_EN GENMASK(27, 24)
81
+
75
82
struct sdhci_sprd_host {
76
83
u32 version ;
77
84
struct clk * clk_sdio ;
@@ -85,6 +92,11 @@ struct sdhci_sprd_host {
85
92
u32 phy_delay [MMC_TIMING_MMC_HS400 + 2 ];
86
93
};
87
94
95
+ enum sdhci_sprd_tuning_type {
96
+ SDHCI_SPRD_TUNING_SD_HS_CMD ,
97
+ SDHCI_SPRD_TUNING_SD_HS_DATA ,
98
+ };
99
+
88
100
struct sdhci_sprd_phy_cfg {
89
101
const char * property ;
90
102
u8 timing ;
@@ -532,6 +544,138 @@ static void sdhci_sprd_hs400_enhanced_strobe(struct mmc_host *mmc,
532
544
SDHCI_SPRD_REG_32_DLL_DLY );
533
545
}
534
546
547
+ static int mmc_send_tuning_cmd (struct mmc_card * card )
548
+ {
549
+ return mmc_send_status (card , NULL );
550
+ }
551
+
552
+ static int mmc_send_tuning_data (struct mmc_card * card )
553
+ {
554
+ u8 * status ;
555
+ int ret ;
556
+
557
+ status = kmalloc (64 , GFP_KERNEL );
558
+ if (!status )
559
+ return - ENOMEM ;
560
+
561
+ ret = mmc_sd_switch (card , 0 , 0 , 0 , status );
562
+
563
+ kfree (status );
564
+
565
+ return ret ;
566
+ }
567
+
568
+ static int sdhci_sprd_get_best_clk_sample (struct mmc_host * mmc , u8 * value )
569
+ {
570
+ int range_end = SDHCI_SPRD_MAX_RANGE ;
571
+ int range_length = 0 ;
572
+ int middle_range = 0 ;
573
+ int count = 0 ;
574
+ int i ;
575
+
576
+ for (i = 0 ; i <= SDHCI_SPRD_MAX_RANGE ; i ++ ) {
577
+ if (value [i ]) {
578
+ pr_debug ("%s: tuning ok: %d\n" , mmc_hostname (mmc ), i );
579
+ count ++ ;
580
+ } else {
581
+ pr_debug ("%s: tuning fail: %d\n" , mmc_hostname (mmc ), i );
582
+ if (range_length < count ) {
583
+ range_length = count ;
584
+ range_end = i - 1 ;
585
+ count = 0 ;
586
+ }
587
+ }
588
+ }
589
+
590
+ if (!count )
591
+ return - EIO ;
592
+
593
+ if (count > range_length ) {
594
+ range_length = count ;
595
+ range_end = i - 1 ;
596
+ }
597
+
598
+ middle_range = range_end - (range_length - 1 ) / 2 ;
599
+
600
+ return middle_range ;
601
+ }
602
+
603
+ static int sdhci_sprd_tuning (struct mmc_host * mmc , struct mmc_card * card ,
604
+ enum sdhci_sprd_tuning_type type )
605
+ {
606
+ struct sdhci_host * host = mmc_priv (mmc );
607
+ struct sdhci_sprd_host * sprd_host = TO_SPRD_HOST (host );
608
+ u32 * p = sprd_host -> phy_delay ;
609
+ u32 dll_cfg , dll_dly ;
610
+ int best_clk_sample ;
611
+ int err = 0 ;
612
+ u8 * value ;
613
+ int i ;
614
+
615
+ value = kmalloc (SDHCI_SPRD_MAX_RANGE + 1 , GFP_KERNEL );
616
+ if (!value )
617
+ return - ENOMEM ;
618
+
619
+ sdhci_reset (host , SDHCI_RESET_CMD | SDHCI_RESET_DATA );
620
+
621
+ dll_cfg = sdhci_readl (host , SDHCI_SPRD_REG_32_DLL_CFG );
622
+ dll_cfg &= ~SDHCI_SPRD_CPST_EN ;
623
+ sdhci_writel (host , dll_cfg , SDHCI_SPRD_REG_32_DLL_CFG );
624
+
625
+ dll_dly = p [mmc -> ios .timing ];
626
+
627
+ for (i = 0 ; i <= SDHCI_SPRD_MAX_RANGE ; i ++ ) {
628
+ if (type == SDHCI_SPRD_TUNING_SD_HS_CMD ) {
629
+ dll_dly &= ~SDHCI_SPRD_CMD_DLY_MASK ;
630
+ dll_dly |= ((i << 8 ) & SDHCI_SPRD_CMD_DLY_MASK );
631
+ } else {
632
+ dll_dly &= ~SDHCI_SPRD_POSRD_DLY_MASK ;
633
+ dll_dly |= ((i << 16 ) & SDHCI_SPRD_POSRD_DLY_MASK );
634
+ }
635
+
636
+ sdhci_writel (host , dll_dly , SDHCI_SPRD_REG_32_DLL_DLY );
637
+
638
+ if (type == SDHCI_SPRD_TUNING_SD_HS_CMD )
639
+ value [i ] = !mmc_send_tuning_cmd (card );
640
+ else
641
+ value [i ] = !mmc_send_tuning_data (card );
642
+ }
643
+
644
+ best_clk_sample = sdhci_sprd_get_best_clk_sample (mmc , value );
645
+ if (best_clk_sample < 0 ) {
646
+ dev_err (mmc_dev (host -> mmc ), "all tuning phase fail!\n" );
647
+ goto out ;
648
+ }
649
+
650
+ if (type == SDHCI_SPRD_TUNING_SD_HS_CMD ) {
651
+ p [mmc -> ios .timing ] &= ~SDHCI_SPRD_CMD_DLY_MASK ;
652
+ p [mmc -> ios .timing ] |= ((best_clk_sample << 8 ) & SDHCI_SPRD_CMD_DLY_MASK );
653
+ } else {
654
+ p [mmc -> ios .timing ] &= ~(SDHCI_SPRD_POSRD_DLY_MASK );
655
+ p [mmc -> ios .timing ] |= ((best_clk_sample << 16 ) & SDHCI_SPRD_POSRD_DLY_MASK );
656
+ }
657
+
658
+ pr_debug ("%s: the best clk sample %d, delay value 0x%08x\n" ,
659
+ mmc_hostname (host -> mmc ), best_clk_sample , p [mmc -> ios .timing ]);
660
+
661
+ out :
662
+ sdhci_writel (host , p [mmc -> ios .timing ], SDHCI_SPRD_REG_32_DLL_DLY );
663
+
664
+ kfree (value );
665
+
666
+ return err ;
667
+ }
668
+
669
+ static int sdhci_sprd_prepare_sd_hs_cmd_tuning (struct mmc_host * mmc , struct mmc_card * card )
670
+ {
671
+ return sdhci_sprd_tuning (mmc , card , SDHCI_SPRD_TUNING_SD_HS_CMD );
672
+ }
673
+
674
+ static int sdhci_sprd_execute_sd_hs_data_tuning (struct mmc_host * mmc , struct mmc_card * card )
675
+ {
676
+ return sdhci_sprd_tuning (mmc , card , SDHCI_SPRD_TUNING_SD_HS_DATA );
677
+ }
678
+
535
679
static void sdhci_sprd_phy_param_parse (struct sdhci_sprd_host * sprd_host ,
536
680
struct device_node * np )
537
681
{
@@ -576,6 +720,11 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
576
720
host -> mmc_host_ops .request = sdhci_sprd_request ;
577
721
host -> mmc_host_ops .hs400_enhanced_strobe =
578
722
sdhci_sprd_hs400_enhanced_strobe ;
723
+ host -> mmc_host_ops .prepare_sd_hs_tuning =
724
+ sdhci_sprd_prepare_sd_hs_cmd_tuning ;
725
+ host -> mmc_host_ops .execute_sd_hs_tuning =
726
+ sdhci_sprd_execute_sd_hs_data_tuning ;
727
+
579
728
/*
580
729
* We can not use the standard ops to change and detect the voltage
581
730
* signal for Spreadtrum SD host controller, since our voltage regulator
0 commit comments