50
50
#define HCI_ERR_EN_N_LAYER 0x80
51
51
#define HCI_ERR_EN_T_LAYER 0x84
52
52
#define HCI_ERR_EN_DME_LAYER 0x88
53
+ #define HCI_V2P1_CTRL 0x8C
54
+ #define IA_TICK_SEL BIT(16)
53
55
#define HCI_CLKSTOP_CTRL 0xB0
54
56
#define REFCLKOUT_STOP BIT(4)
55
57
#define MPHY_APBCLK_STOP BIT(3)
59
61
#define CLK_STOP_MASK (REFCLKOUT_STOP | REFCLK_STOP |\
60
62
UNIPRO_MCLK_STOP | MPHY_APBCLK_STOP|\
61
63
UNIPRO_PCLK_STOP)
64
+ /* HCI_MISC is also known as HCI_FORCE_HCS */
62
65
#define HCI_MISC 0xB4
63
66
#define REFCLK_CTRL_EN BIT(7)
64
67
#define UNIPRO_PCLK_CTRL_EN BIT(6)
@@ -136,6 +139,9 @@ enum {
136
139
/*
137
140
* UNIPRO registers
138
141
*/
142
+ #define UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER0 0x7888
143
+ #define UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER1 0x788c
144
+ #define UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER2 0x7890
139
145
#define UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER0 0x78B8
140
146
#define UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER1 0x78BC
141
147
#define UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER2 0x78C0
@@ -306,8 +312,9 @@ static int exynosauto_ufs_post_pwr_change(struct exynos_ufs *ufs,
306
312
307
313
static int exynos7_ufs_pre_link (struct exynos_ufs * ufs )
308
314
{
315
+ struct exynos_ufs_uic_attr * attr = ufs -> drv_data -> uic_attr ;
316
+ u32 val = attr -> pa_dbg_opt_suite1_val ;
309
317
struct ufs_hba * hba = ufs -> hba ;
310
- u32 val = ufs -> drv_data -> uic_attr -> pa_dbg_option_suite ;
311
318
int i ;
312
319
313
320
exynos_ufs_enable_ov_tm (hba );
@@ -324,12 +331,13 @@ static int exynos7_ufs_pre_link(struct exynos_ufs *ufs)
324
331
UIC_ARG_MIB_SEL (TX_HIBERN8_CONTROL , i ), 0x0 );
325
332
ufshcd_dme_set (hba , UIC_ARG_MIB (PA_DBG_TXPHY_CFGUPDT ), 0x1 );
326
333
udelay (1 );
327
- ufshcd_dme_set (hba , UIC_ARG_MIB (PA_DBG_OPTION_SUITE ), val | (1 << 12 ));
334
+ ufshcd_dme_set (hba , UIC_ARG_MIB (attr -> pa_dbg_opt_suite1_off ),
335
+ val | (1 << 12 ));
328
336
ufshcd_dme_set (hba , UIC_ARG_MIB (PA_DBG_SKIP_RESET_PHY ), 0x1 );
329
337
ufshcd_dme_set (hba , UIC_ARG_MIB (PA_DBG_SKIP_LINE_RESET ), 0x1 );
330
338
ufshcd_dme_set (hba , UIC_ARG_MIB (PA_DBG_LINE_RESET_REQ ), 0x1 );
331
339
udelay (1600 );
332
- ufshcd_dme_set (hba , UIC_ARG_MIB (PA_DBG_OPTION_SUITE ), val );
340
+ ufshcd_dme_set (hba , UIC_ARG_MIB (attr -> pa_dbg_opt_suite1_off ), val );
333
341
334
342
return 0 ;
335
343
}
@@ -921,14 +929,23 @@ static int exynos_ufs_phy_init(struct exynos_ufs *ufs)
921
929
922
930
static void exynos_ufs_config_unipro (struct exynos_ufs * ufs )
923
931
{
932
+ struct exynos_ufs_uic_attr * attr = ufs -> drv_data -> uic_attr ;
924
933
struct ufs_hba * hba = ufs -> hba ;
925
934
926
- ufshcd_dme_set (hba , UIC_ARG_MIB (PA_DBG_CLK_PERIOD ),
927
- DIV_ROUND_UP (NSEC_PER_SEC , ufs -> mclk_rate ));
935
+ if (attr -> pa_dbg_clk_period_off )
936
+ ufshcd_dme_set (hba , UIC_ARG_MIB (attr -> pa_dbg_clk_period_off ),
937
+ DIV_ROUND_UP (NSEC_PER_SEC , ufs -> mclk_rate ));
938
+
928
939
ufshcd_dme_set (hba , UIC_ARG_MIB (PA_TXTRAILINGCLOCKS ),
929
940
ufs -> drv_data -> uic_attr -> tx_trailingclks );
930
- ufshcd_dme_set (hba , UIC_ARG_MIB (PA_DBG_OPTION_SUITE ),
931
- ufs -> drv_data -> uic_attr -> pa_dbg_option_suite );
941
+
942
+ if (attr -> pa_dbg_opt_suite1_off )
943
+ ufshcd_dme_set (hba , UIC_ARG_MIB (attr -> pa_dbg_opt_suite1_off ),
944
+ attr -> pa_dbg_opt_suite1_val );
945
+
946
+ if (attr -> pa_dbg_opt_suite2_off )
947
+ ufshcd_dme_set (hba , UIC_ARG_MIB (attr -> pa_dbg_opt_suite2_off ),
948
+ attr -> pa_dbg_opt_suite2_val );
932
949
}
933
950
934
951
static void exynos_ufs_config_intr (struct exynos_ufs * ufs , u32 errs , u8 index )
@@ -1005,6 +1022,13 @@ static void exynos_ufs_fit_aggr_timeout(struct exynos_ufs *ufs)
1005
1022
{
1006
1023
u32 val ;
1007
1024
1025
+ /* Select function clock (mclk) for timer tick */
1026
+ if (ufs -> opts & EXYNOS_UFS_OPT_TIMER_TICK_SELECT ) {
1027
+ val = hci_readl (ufs , HCI_V2P1_CTRL );
1028
+ val |= IA_TICK_SEL ;
1029
+ hci_writel (ufs , val , HCI_V2P1_CTRL );
1030
+ }
1031
+
1008
1032
val = exynos_ufs_calc_time_cntr (ufs , IATOVAL_NSEC / CNTR_DIV_VAL );
1009
1033
hci_writel (ufs , val & CNT_VAL_1US_MASK , HCI_1US_TO_CNT_VAL );
1010
1034
}
@@ -1186,7 +1210,8 @@ static int exynos_ufs_init(struct ufs_hba *hba)
1186
1210
if (ret )
1187
1211
goto out ;
1188
1212
exynos_ufs_specify_phy_time_attr (ufs );
1189
- exynos_ufs_config_smu (ufs );
1213
+ if (!(ufs -> opts & EXYNOS_UFS_OPT_UFSPR_SECURE ))
1214
+ exynos_ufs_config_smu (ufs );
1190
1215
1191
1216
hba -> host -> dma_alignment = SZ_4K - 1 ;
1192
1217
return 0 ;
@@ -1477,10 +1502,11 @@ static int exynosauto_ufs_vh_init(struct ufs_hba *hba)
1477
1502
1478
1503
static int fsd_ufs_pre_link (struct exynos_ufs * ufs )
1479
1504
{
1480
- int i ;
1505
+ struct exynos_ufs_uic_attr * attr = ufs -> drv_data -> uic_attr ;
1481
1506
struct ufs_hba * hba = ufs -> hba ;
1507
+ int i ;
1482
1508
1483
- ufshcd_dme_set (hba , UIC_ARG_MIB (PA_DBG_CLK_PERIOD ),
1509
+ ufshcd_dme_set (hba , UIC_ARG_MIB (attr -> pa_dbg_clk_period_off ),
1484
1510
DIV_ROUND_UP (NSEC_PER_SEC , ufs -> mclk_rate ));
1485
1511
ufshcd_dme_set (hba , UIC_ARG_MIB (0x201 ), 0x12 );
1486
1512
ufshcd_dme_set (hba , UIC_ARG_MIB (0x200 ), 0x40 );
@@ -1504,7 +1530,9 @@ static int fsd_ufs_pre_link(struct exynos_ufs *ufs)
1504
1530
1505
1531
ufshcd_dme_set (hba , UIC_ARG_MIB (0x200 ), 0x0 );
1506
1532
ufshcd_dme_set (hba , UIC_ARG_MIB (PA_DBG_AUTOMODE_THLD ), 0x4E20 );
1507
- ufshcd_dme_set (hba , UIC_ARG_MIB (PA_DBG_OPTION_SUITE ), 0x2e820183 );
1533
+
1534
+ ufshcd_dme_set (hba , UIC_ARG_MIB (attr -> pa_dbg_opt_suite1_off ),
1535
+ 0x2e820183 );
1508
1536
ufshcd_dme_set (hba , UIC_ARG_MIB (PA_LOCAL_TX_LCC_ENABLE ), 0x0 );
1509
1537
1510
1538
exynos_ufs_establish_connt (ufs );
@@ -1568,6 +1596,96 @@ static int fsd_ufs_pre_pwr_change(struct exynos_ufs *ufs,
1568
1596
return 0 ;
1569
1597
}
1570
1598
1599
+ static inline u32 get_mclk_period_unipro_18 (struct exynos_ufs * ufs )
1600
+ {
1601
+ return (16 * 1000 * 1000000UL / ufs -> mclk_rate );
1602
+ }
1603
+
1604
+ static int gs101_ufs_pre_link (struct exynos_ufs * ufs )
1605
+ {
1606
+ struct ufs_hba * hba = ufs -> hba ;
1607
+ int i ;
1608
+ u32 tx_line_reset_period , rx_line_reset_period ;
1609
+
1610
+ rx_line_reset_period = (RX_LINE_RESET_TIME * ufs -> mclk_rate )
1611
+ / NSEC_PER_MSEC ;
1612
+ tx_line_reset_period = (TX_LINE_RESET_TIME * ufs -> mclk_rate )
1613
+ / NSEC_PER_MSEC ;
1614
+
1615
+ unipro_writel (ufs , get_mclk_period_unipro_18 (ufs ), COMP_CLK_PERIOD );
1616
+
1617
+ ufshcd_dme_set (hba , UIC_ARG_MIB (0x200 ), 0x40 );
1618
+
1619
+ for_each_ufs_rx_lane (ufs , i ) {
1620
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_RX_CLK_PRD , i ),
1621
+ DIV_ROUND_UP (NSEC_PER_SEC , ufs -> mclk_rate ));
1622
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_RX_CLK_PRD_EN , i ), 0x0 );
1623
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_RX_LINERESET_VALUE2 , i ),
1624
+ (rx_line_reset_period >> 16 ) & 0xFF );
1625
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_RX_LINERESET_VALUE1 , i ),
1626
+ (rx_line_reset_period >> 8 ) & 0xFF );
1627
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_RX_LINERESET_VALUE0 , i ),
1628
+ (rx_line_reset_period ) & 0xFF );
1629
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (0x2f , i ), 0x69 );
1630
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (0x84 , i ), 0x1 );
1631
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (0x25 , i ), 0xf6 );
1632
+ }
1633
+
1634
+ for_each_ufs_tx_lane (ufs , i ) {
1635
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_TX_CLK_PRD , i ),
1636
+ DIV_ROUND_UP (NSEC_PER_SEC , ufs -> mclk_rate ));
1637
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_TX_CLK_PRD_EN , i ),
1638
+ 0x02 );
1639
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_TX_LINERESET_PVALUE2 , i ),
1640
+ (tx_line_reset_period >> 16 ) & 0xFF );
1641
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_TX_LINERESET_PVALUE1 , i ),
1642
+ (tx_line_reset_period >> 8 ) & 0xFF );
1643
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_TX_LINERESET_PVALUE0 , i ),
1644
+ (tx_line_reset_period ) & 0xFF );
1645
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (0x04 , i ), 1 );
1646
+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (0x7F , i ), 0 );
1647
+ }
1648
+
1649
+ ufshcd_dme_set (hba , UIC_ARG_MIB (0x200 ), 0x0 );
1650
+ ufshcd_dme_set (hba , UIC_ARG_MIB (PA_LOCAL_TX_LCC_ENABLE ), 0x0 );
1651
+ ufshcd_dme_set (hba , UIC_ARG_MIB (N_DEVICEID ), 0x0 );
1652
+ ufshcd_dme_set (hba , UIC_ARG_MIB (N_DEVICEID_VALID ), 0x1 );
1653
+ ufshcd_dme_set (hba , UIC_ARG_MIB (T_PEERDEVICEID ), 0x1 );
1654
+ ufshcd_dme_set (hba , UIC_ARG_MIB (T_CONNECTIONSTATE ), CPORT_CONNECTED );
1655
+ ufshcd_dme_set (hba , UIC_ARG_MIB (0xA006 ), 0x8000 );
1656
+
1657
+ return 0 ;
1658
+ }
1659
+
1660
+ static int gs101_ufs_post_link (struct exynos_ufs * ufs )
1661
+ {
1662
+ struct ufs_hba * hba = ufs -> hba ;
1663
+
1664
+ exynos_ufs_enable_dbg_mode (hba );
1665
+ ufshcd_dme_set (hba , UIC_ARG_MIB (PA_SAVECONFIGTIME ), 0x3e8 );
1666
+ exynos_ufs_disable_dbg_mode (hba );
1667
+
1668
+ return 0 ;
1669
+ }
1670
+
1671
+ static int gs101_ufs_pre_pwr_change (struct exynos_ufs * ufs ,
1672
+ struct ufs_pa_layer_attr * pwr )
1673
+ {
1674
+ struct ufs_hba * hba = ufs -> hba ;
1675
+
1676
+ ufshcd_dme_set (hba , UIC_ARG_MIB (PA_PWRMODEUSERDATA0 ), 12000 );
1677
+ ufshcd_dme_set (hba , UIC_ARG_MIB (PA_PWRMODEUSERDATA1 ), 32000 );
1678
+ ufshcd_dme_set (hba , UIC_ARG_MIB (PA_PWRMODEUSERDATA2 ), 16000 );
1679
+ unipro_writel (ufs , 8064 , UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER0 );
1680
+ unipro_writel (ufs , 28224 , UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER1 );
1681
+ unipro_writel (ufs , 20160 , UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER2 );
1682
+ unipro_writel (ufs , 12000 , UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER0 );
1683
+ unipro_writel (ufs , 32000 , UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER1 );
1684
+ unipro_writel (ufs , 16000 , UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER2 );
1685
+
1686
+ return 0 ;
1687
+ }
1688
+
1571
1689
static const struct ufs_hba_variant_ops ufs_hba_exynos_ops = {
1572
1690
.name = "exynos_ufs" ,
1573
1691
.init = exynos_ufs_init ,
@@ -1640,7 +1758,9 @@ static struct exynos_ufs_uic_attr exynos7_uic_attr = {
1640
1758
.rx_hs_g1_prep_sync_len_cap = PREP_LEN (0xf ),
1641
1759
.rx_hs_g2_prep_sync_len_cap = PREP_LEN (0xf ),
1642
1760
.rx_hs_g3_prep_sync_len_cap = PREP_LEN (0xf ),
1643
- .pa_dbg_option_suite = 0x30103 ,
1761
+ .pa_dbg_clk_period_off = PA_DBG_CLK_PERIOD ,
1762
+ .pa_dbg_opt_suite1_val = 0x30103 ,
1763
+ .pa_dbg_opt_suite1_off = PA_DBG_OPTION_SUITE ,
1644
1764
};
1645
1765
1646
1766
static const struct exynos_ufs_drv_data exynosauto_ufs_drvs = {
@@ -1692,6 +1812,34 @@ static const struct exynos_ufs_drv_data exynos_ufs_drvs = {
1692
1812
.post_pwr_change = exynos7_ufs_post_pwr_change ,
1693
1813
};
1694
1814
1815
+ static struct exynos_ufs_uic_attr gs101_uic_attr = {
1816
+ .tx_trailingclks = 0xff ,
1817
+ .tx_dif_p_nsec = 3000000 , /* unit: ns */
1818
+ .tx_dif_n_nsec = 1000000 , /* unit: ns */
1819
+ .tx_high_z_cnt_nsec = 20000 , /* unit: ns */
1820
+ .tx_base_unit_nsec = 100000 , /* unit: ns */
1821
+ .tx_gran_unit_nsec = 4000 , /* unit: ns */
1822
+ .tx_sleep_cnt = 1000 , /* unit: ns */
1823
+ .tx_min_activatetime = 0xa ,
1824
+ .rx_filler_enable = 0x2 ,
1825
+ .rx_dif_p_nsec = 1000000 , /* unit: ns */
1826
+ .rx_hibern8_wait_nsec = 4000000 , /* unit: ns */
1827
+ .rx_base_unit_nsec = 100000 , /* unit: ns */
1828
+ .rx_gran_unit_nsec = 4000 , /* unit: ns */
1829
+ .rx_sleep_cnt = 1280 , /* unit: ns */
1830
+ .rx_stall_cnt = 320 , /* unit: ns */
1831
+ .rx_hs_g1_sync_len_cap = SYNC_LEN_COARSE (0xf ),
1832
+ .rx_hs_g2_sync_len_cap = SYNC_LEN_COARSE (0xf ),
1833
+ .rx_hs_g3_sync_len_cap = SYNC_LEN_COARSE (0xf ),
1834
+ .rx_hs_g1_prep_sync_len_cap = PREP_LEN (0xf ),
1835
+ .rx_hs_g2_prep_sync_len_cap = PREP_LEN (0xf ),
1836
+ .rx_hs_g3_prep_sync_len_cap = PREP_LEN (0xf ),
1837
+ .pa_dbg_opt_suite1_val = 0x90913C1C ,
1838
+ .pa_dbg_opt_suite1_off = PA_GS101_DBG_OPTION_SUITE1 ,
1839
+ .pa_dbg_opt_suite2_val = 0xE01C115F ,
1840
+ .pa_dbg_opt_suite2_off = PA_GS101_DBG_OPTION_SUITE2 ,
1841
+ };
1842
+
1695
1843
static struct exynos_ufs_uic_attr fsd_uic_attr = {
1696
1844
.tx_trailingclks = 0x10 ,
1697
1845
.tx_dif_p_nsec = 3000000 , /* unit: ns */
@@ -1714,7 +1862,9 @@ static struct exynos_ufs_uic_attr fsd_uic_attr = {
1714
1862
.rx_hs_g1_prep_sync_len_cap = PREP_LEN (0xf ),
1715
1863
.rx_hs_g2_prep_sync_len_cap = PREP_LEN (0xf ),
1716
1864
.rx_hs_g3_prep_sync_len_cap = PREP_LEN (0xf ),
1717
- .pa_dbg_option_suite = 0x2E820183 ,
1865
+ .pa_dbg_clk_period_off = PA_DBG_CLK_PERIOD ,
1866
+ .pa_dbg_opt_suite1_val = 0x2E820183 ,
1867
+ .pa_dbg_opt_suite1_off = PA_DBG_OPTION_SUITE ,
1718
1868
};
1719
1869
1720
1870
static const struct exynos_ufs_drv_data fsd_ufs_drvs = {
@@ -1733,7 +1883,27 @@ static const struct exynos_ufs_drv_data fsd_ufs_drvs = {
1733
1883
.pre_pwr_change = fsd_ufs_pre_pwr_change ,
1734
1884
};
1735
1885
1886
+ static const struct exynos_ufs_drv_data gs101_ufs_drvs = {
1887
+ .uic_attr = & gs101_uic_attr ,
1888
+ .quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN |
1889
+ UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR |
1890
+ UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR |
1891
+ UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR |
1892
+ UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL |
1893
+ UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING ,
1894
+ .opts = EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL |
1895
+ EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR |
1896
+ EXYNOS_UFS_OPT_UFSPR_SECURE |
1897
+ EXYNOS_UFS_OPT_TIMER_TICK_SELECT ,
1898
+ .drv_init = exynosauto_ufs_drv_init ,
1899
+ .pre_link = gs101_ufs_pre_link ,
1900
+ .post_link = gs101_ufs_post_link ,
1901
+ .pre_pwr_change = gs101_ufs_pre_pwr_change ,
1902
+ };
1903
+
1736
1904
static const struct of_device_id exynos_ufs_of_match [] = {
1905
+ { .compatible = "google,gs101-ufs" ,
1906
+ .data = & gs101_ufs_drvs },
1737
1907
{ .compatible = "samsung,exynos7-ufs" ,
1738
1908
.data = & exynos_ufs_drvs },
1739
1909
{ .compatible = "samsung,exynosautov9-ufs" ,
0 commit comments