99#include <linux/dma-mapping.h>
1010#include <linux/highmem.h>
1111#include <linux/iopoll.h>
12+ #include <linux/mmc/host.h>
13+ #include <linux/mmc/mmc.h>
1214#include <linux/module.h>
1315#include <linux/of.h>
1416#include <linux/of_gpio.h>
7274#define SDHCI_SPRD_CLK_DEF_RATE 26000000
7375#define SDHCI_SPRD_PHY_DLL_CLK 52000000
7476
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+
7582struct sdhci_sprd_host {
7683 u32 version ;
7784 struct clk * clk_sdio ;
@@ -85,6 +92,11 @@ struct sdhci_sprd_host {
8592 u32 phy_delay [MMC_TIMING_MMC_HS400 + 2 ];
8693};
8794
95+ enum sdhci_sprd_tuning_type {
96+ SDHCI_SPRD_TUNING_SD_HS_CMD ,
97+ SDHCI_SPRD_TUNING_SD_HS_DATA ,
98+ };
99+
88100struct sdhci_sprd_phy_cfg {
89101 const char * property ;
90102 u8 timing ;
@@ -532,6 +544,138 @@ static void sdhci_sprd_hs400_enhanced_strobe(struct mmc_host *mmc,
532544 SDHCI_SPRD_REG_32_DLL_DLY );
533545}
534546
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+
535679static void sdhci_sprd_phy_param_parse (struct sdhci_sprd_host * sprd_host ,
536680 struct device_node * np )
537681{
@@ -576,6 +720,11 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
576720 host -> mmc_host_ops .request = sdhci_sprd_request ;
577721 host -> mmc_host_ops .hs400_enhanced_strobe =
578722 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+
579728 /*
580729 * We can not use the standard ops to change and detect the voltage
581730 * signal for Spreadtrum SD host controller, since our voltage regulator
0 commit comments