75
75
#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_MASK 0x0000000f
76
76
#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_VREF_SEL_VAL 0x7
77
77
#define SDHCI_TEGRA_SDMEM_COMP_PADCTRL_E_INPUT_E_PWRD BIT(31)
78
+ #define SDHCI_COMP_PADCTRL_DRVUPDN_OFFSET_MASK 0x07FFF000
78
79
79
80
#define SDHCI_TEGRA_AUTO_CAL_STATUS 0x1ec
80
81
#define SDHCI_TEGRA_AUTO_CAL_ACTIVE BIT(31)
@@ -121,6 +122,8 @@ struct sdhci_tegra {
121
122
struct pinctrl * pinctrl_sdmmc ;
122
123
struct pinctrl_state * pinctrl_state_3v3 ;
123
124
struct pinctrl_state * pinctrl_state_1v8 ;
125
+ struct pinctrl_state * pinctrl_state_3v3_drv ;
126
+ struct pinctrl_state * pinctrl_state_1v8_drv ;
124
127
125
128
struct sdhci_tegra_autocal_offsets autocal_offsets ;
126
129
ktime_t last_calib ;
@@ -411,6 +414,76 @@ static void tegra_sdhci_set_pad_autocal_offset(struct sdhci_host *host,
411
414
sdhci_writel (host , reg , SDHCI_TEGRA_AUTO_CAL_CONFIG );
412
415
}
413
416
417
+ static int tegra_sdhci_set_padctrl (struct sdhci_host * host , int voltage ,
418
+ bool state_drvupdn )
419
+ {
420
+ struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
421
+ struct sdhci_tegra * tegra_host = sdhci_pltfm_priv (pltfm_host );
422
+ struct sdhci_tegra_autocal_offsets * offsets =
423
+ & tegra_host -> autocal_offsets ;
424
+ struct pinctrl_state * pinctrl_drvupdn = NULL ;
425
+ int ret = 0 ;
426
+ u8 drvup = 0 , drvdn = 0 ;
427
+ u32 reg ;
428
+
429
+ if (!state_drvupdn ) {
430
+ /* PADS Drive Strength */
431
+ if (voltage == MMC_SIGNAL_VOLTAGE_180 ) {
432
+ if (tegra_host -> pinctrl_state_1v8_drv ) {
433
+ pinctrl_drvupdn =
434
+ tegra_host -> pinctrl_state_1v8_drv ;
435
+ } else {
436
+ drvup = offsets -> pull_up_1v8_timeout ;
437
+ drvdn = offsets -> pull_down_1v8_timeout ;
438
+ }
439
+ } else {
440
+ if (tegra_host -> pinctrl_state_3v3_drv ) {
441
+ pinctrl_drvupdn =
442
+ tegra_host -> pinctrl_state_3v3_drv ;
443
+ } else {
444
+ drvup = offsets -> pull_up_3v3_timeout ;
445
+ drvdn = offsets -> pull_down_3v3_timeout ;
446
+ }
447
+ }
448
+
449
+ if (pinctrl_drvupdn != NULL ) {
450
+ ret = pinctrl_select_state (tegra_host -> pinctrl_sdmmc ,
451
+ pinctrl_drvupdn );
452
+ if (ret < 0 )
453
+ dev_err (mmc_dev (host -> mmc ),
454
+ "failed pads drvupdn, ret: %d\n" , ret );
455
+ } else if ((drvup ) || (drvdn )) {
456
+ reg = sdhci_readl (host ,
457
+ SDHCI_TEGRA_SDMEM_COMP_PADCTRL );
458
+ reg &= ~SDHCI_COMP_PADCTRL_DRVUPDN_OFFSET_MASK ;
459
+ reg |= (drvup << 20 ) | (drvdn << 12 );
460
+ sdhci_writel (host , reg ,
461
+ SDHCI_TEGRA_SDMEM_COMP_PADCTRL );
462
+ }
463
+
464
+ } else {
465
+ /* Dual Voltage PADS Voltage selection */
466
+ if (!tegra_host -> pad_control_available )
467
+ return 0 ;
468
+
469
+ if (voltage == MMC_SIGNAL_VOLTAGE_180 ) {
470
+ ret = pinctrl_select_state (tegra_host -> pinctrl_sdmmc ,
471
+ tegra_host -> pinctrl_state_1v8 );
472
+ if (ret < 0 )
473
+ dev_err (mmc_dev (host -> mmc ),
474
+ "setting 1.8V failed, ret: %d\n" , ret );
475
+ } else {
476
+ ret = pinctrl_select_state (tegra_host -> pinctrl_sdmmc ,
477
+ tegra_host -> pinctrl_state_3v3 );
478
+ if (ret < 0 )
479
+ dev_err (mmc_dev (host -> mmc ),
480
+ "setting 3.3V failed, ret: %d\n" , ret );
481
+ }
482
+ }
483
+
484
+ return ret ;
485
+ }
486
+
414
487
static void tegra_sdhci_pad_autocalib (struct sdhci_host * host )
415
488
{
416
489
struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
@@ -437,6 +510,7 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
437
510
pdpu = offsets .pull_down_3v3 << 8 | offsets .pull_up_3v3 ;
438
511
}
439
512
513
+ /* Set initial offset before auto-calibration */
440
514
tegra_sdhci_set_pad_autocal_offset (host , pdpu );
441
515
442
516
card_clk_enabled = tegra_sdhci_configure_card_clk (host , false);
@@ -460,19 +534,15 @@ static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
460
534
if (ret ) {
461
535
dev_err (mmc_dev (host -> mmc ), "Pad autocal timed out\n" );
462
536
463
- if (ios -> signal_voltage == MMC_SIGNAL_VOLTAGE_180 )
464
- pdpu = offsets .pull_down_1v8_timeout << 8 |
465
- offsets .pull_up_1v8_timeout ;
466
- else
467
- pdpu = offsets .pull_down_3v3_timeout << 8 |
468
- offsets .pull_up_3v3_timeout ;
469
-
470
- /* Disable automatic calibration and use fixed offsets */
537
+ /* Disable automatic cal and use fixed Drive Strengths */
471
538
reg = sdhci_readl (host , SDHCI_TEGRA_AUTO_CAL_CONFIG );
472
539
reg &= ~SDHCI_AUTO_CAL_ENABLE ;
473
540
sdhci_writel (host , reg , SDHCI_TEGRA_AUTO_CAL_CONFIG );
474
541
475
- tegra_sdhci_set_pad_autocal_offset (host , pdpu );
542
+ ret = tegra_sdhci_set_padctrl (host , ios -> signal_voltage , false);
543
+ if (ret < 0 )
544
+ dev_err (mmc_dev (host -> mmc ),
545
+ "Setting drive strengths failed: %d\n" , ret );
476
546
}
477
547
}
478
548
@@ -511,26 +581,46 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host)
511
581
err = device_property_read_u32 (host -> mmc -> parent ,
512
582
"nvidia,pad-autocal-pull-up-offset-3v3-timeout" ,
513
583
& autocal -> pull_up_3v3_timeout );
514
- if (err )
584
+ if (err ) {
585
+ if (!IS_ERR (tegra_host -> pinctrl_state_3v3 ) &&
586
+ (tegra_host -> pinctrl_state_3v3_drv == NULL ))
587
+ pr_warn ("%s: Missing autocal timeout 3v3-pad drvs\n" ,
588
+ mmc_hostname (host -> mmc ));
515
589
autocal -> pull_up_3v3_timeout = 0 ;
590
+ }
516
591
517
592
err = device_property_read_u32 (host -> mmc -> parent ,
518
593
"nvidia,pad-autocal-pull-down-offset-3v3-timeout" ,
519
594
& autocal -> pull_down_3v3_timeout );
520
- if (err )
595
+ if (err ) {
596
+ if (!IS_ERR (tegra_host -> pinctrl_state_3v3 ) &&
597
+ (tegra_host -> pinctrl_state_3v3_drv == NULL ))
598
+ pr_warn ("%s: Missing autocal timeout 3v3-pad drvs\n" ,
599
+ mmc_hostname (host -> mmc ));
521
600
autocal -> pull_down_3v3_timeout = 0 ;
601
+ }
522
602
523
603
err = device_property_read_u32 (host -> mmc -> parent ,
524
604
"nvidia,pad-autocal-pull-up-offset-1v8-timeout" ,
525
605
& autocal -> pull_up_1v8_timeout );
526
- if (err )
606
+ if (err ) {
607
+ if (!IS_ERR (tegra_host -> pinctrl_state_1v8 ) &&
608
+ (tegra_host -> pinctrl_state_1v8_drv == NULL ))
609
+ pr_warn ("%s: Missing autocal timeout 1v8-pad drvs\n" ,
610
+ mmc_hostname (host -> mmc ));
527
611
autocal -> pull_up_1v8_timeout = 0 ;
612
+ }
528
613
529
614
err = device_property_read_u32 (host -> mmc -> parent ,
530
615
"nvidia,pad-autocal-pull-down-offset-1v8-timeout" ,
531
616
& autocal -> pull_down_1v8_timeout );
532
- if (err )
617
+ if (err ) {
618
+ if (!IS_ERR (tegra_host -> pinctrl_state_1v8 ) &&
619
+ (tegra_host -> pinctrl_state_1v8_drv == NULL ))
620
+ pr_warn ("%s: Missing autocal timeout 1v8-pad drvs\n" ,
621
+ mmc_hostname (host -> mmc ));
533
622
autocal -> pull_down_1v8_timeout = 0 ;
623
+ }
534
624
535
625
err = device_property_read_u32 (host -> mmc -> parent ,
536
626
"nvidia,pad-autocal-pull-up-offset-sdr104" ,
@@ -743,32 +833,6 @@ static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
743
833
return mmc_send_tuning (host -> mmc , opcode , NULL );
744
834
}
745
835
746
- static int tegra_sdhci_set_padctrl (struct sdhci_host * host , int voltage )
747
- {
748
- struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
749
- struct sdhci_tegra * tegra_host = sdhci_pltfm_priv (pltfm_host );
750
- int ret ;
751
-
752
- if (!tegra_host -> pad_control_available )
753
- return 0 ;
754
-
755
- if (voltage == MMC_SIGNAL_VOLTAGE_180 ) {
756
- ret = pinctrl_select_state (tegra_host -> pinctrl_sdmmc ,
757
- tegra_host -> pinctrl_state_1v8 );
758
- if (ret < 0 )
759
- dev_err (mmc_dev (host -> mmc ),
760
- "setting 1.8V failed, ret: %d\n" , ret );
761
- } else {
762
- ret = pinctrl_select_state (tegra_host -> pinctrl_sdmmc ,
763
- tegra_host -> pinctrl_state_3v3 );
764
- if (ret < 0 )
765
- dev_err (mmc_dev (host -> mmc ),
766
- "setting 3.3V failed, ret: %d\n" , ret );
767
- }
768
-
769
- return ret ;
770
- }
771
-
772
836
static int sdhci_tegra_start_signal_voltage_switch (struct mmc_host * mmc ,
773
837
struct mmc_ios * ios )
774
838
{
@@ -778,15 +842,15 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
778
842
int ret = 0 ;
779
843
780
844
if (ios -> signal_voltage == MMC_SIGNAL_VOLTAGE_330 ) {
781
- ret = tegra_sdhci_set_padctrl (host , ios -> signal_voltage );
845
+ ret = tegra_sdhci_set_padctrl (host , ios -> signal_voltage , true );
782
846
if (ret < 0 )
783
847
return ret ;
784
848
ret = sdhci_start_signal_voltage_switch (mmc , ios );
785
849
} else if (ios -> signal_voltage == MMC_SIGNAL_VOLTAGE_180 ) {
786
850
ret = sdhci_start_signal_voltage_switch (mmc , ios );
787
851
if (ret < 0 )
788
852
return ret ;
789
- ret = tegra_sdhci_set_padctrl (host , ios -> signal_voltage );
853
+ ret = tegra_sdhci_set_padctrl (host , ios -> signal_voltage , true );
790
854
}
791
855
792
856
if (tegra_host -> pad_calib_required )
@@ -805,6 +869,20 @@ static int tegra_sdhci_init_pinctrl_info(struct device *dev,
805
869
return -1 ;
806
870
}
807
871
872
+ tegra_host -> pinctrl_state_1v8_drv = pinctrl_lookup_state (
873
+ tegra_host -> pinctrl_sdmmc , "sdmmc-1v8-drv" );
874
+ if (IS_ERR (tegra_host -> pinctrl_state_1v8_drv )) {
875
+ if (PTR_ERR (tegra_host -> pinctrl_state_1v8_drv ) == - ENODEV )
876
+ tegra_host -> pinctrl_state_1v8_drv = NULL ;
877
+ }
878
+
879
+ tegra_host -> pinctrl_state_3v3_drv = pinctrl_lookup_state (
880
+ tegra_host -> pinctrl_sdmmc , "sdmmc-3v3-drv" );
881
+ if (IS_ERR (tegra_host -> pinctrl_state_3v3_drv )) {
882
+ if (PTR_ERR (tegra_host -> pinctrl_state_3v3_drv ) == - ENODEV )
883
+ tegra_host -> pinctrl_state_3v3_drv = NULL ;
884
+ }
885
+
808
886
tegra_host -> pinctrl_state_3v3 =
809
887
pinctrl_lookup_state (tegra_host -> pinctrl_sdmmc , "sdmmc-3v3" );
810
888
if (IS_ERR (tegra_host -> pinctrl_state_3v3 )) {
0 commit comments