|
61 | 61 | #define CLK_STOP_MASK (REFCLKOUT_STOP | REFCLK_STOP |\
|
62 | 62 | UNIPRO_MCLK_STOP | MPHY_APBCLK_STOP|\
|
63 | 63 | UNIPRO_PCLK_STOP)
|
| 64 | +/* HCI_MISC is also known as HCI_FORCE_HCS */ |
64 | 65 | #define HCI_MISC 0xB4
|
65 | 66 | #define REFCLK_CTRL_EN BIT(7)
|
66 | 67 | #define UNIPRO_PCLK_CTRL_EN BIT(6)
|
@@ -138,6 +139,9 @@ enum {
|
138 | 139 | /*
|
139 | 140 | * UNIPRO registers
|
140 | 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 |
141 | 145 | #define UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER0 0x78B8
|
142 | 146 | #define UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER1 0x78BC
|
143 | 147 | #define UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER2 0x78C0
|
@@ -938,6 +942,10 @@ static void exynos_ufs_config_unipro(struct exynos_ufs *ufs)
|
938 | 942 | if (attr->pa_dbg_opt_suite1_off)
|
939 | 943 | ufshcd_dme_set(hba, UIC_ARG_MIB(attr->pa_dbg_opt_suite1_off),
|
940 | 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); |
941 | 949 | }
|
942 | 950 |
|
943 | 951 | static void exynos_ufs_config_intr(struct exynos_ufs *ufs, u32 errs, u8 index)
|
@@ -1593,6 +1601,96 @@ static int fsd_ufs_pre_pwr_change(struct exynos_ufs *ufs,
|
1593 | 1601 | return 0;
|
1594 | 1602 | }
|
1595 | 1603 |
|
| 1604 | +static inline u32 get_mclk_period_unipro_18(struct exynos_ufs *ufs) |
| 1605 | +{ |
| 1606 | + return (16 * 1000 * 1000000UL / ufs->mclk_rate); |
| 1607 | +} |
| 1608 | + |
| 1609 | +static int gs101_ufs_pre_link(struct exynos_ufs *ufs) |
| 1610 | +{ |
| 1611 | + struct ufs_hba *hba = ufs->hba; |
| 1612 | + int i; |
| 1613 | + u32 tx_line_reset_period, rx_line_reset_period; |
| 1614 | + |
| 1615 | + rx_line_reset_period = (RX_LINE_RESET_TIME * ufs->mclk_rate) |
| 1616 | + / NSEC_PER_MSEC; |
| 1617 | + tx_line_reset_period = (TX_LINE_RESET_TIME * ufs->mclk_rate) |
| 1618 | + / NSEC_PER_MSEC; |
| 1619 | + |
| 1620 | + unipro_writel(ufs, get_mclk_period_unipro_18(ufs), COMP_CLK_PERIOD); |
| 1621 | + |
| 1622 | + ufshcd_dme_set(hba, UIC_ARG_MIB(0x200), 0x40); |
| 1623 | + |
| 1624 | + for_each_ufs_rx_lane(ufs, i) { |
| 1625 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_RX_CLK_PRD, i), |
| 1626 | + DIV_ROUND_UP(NSEC_PER_SEC, ufs->mclk_rate)); |
| 1627 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_RX_CLK_PRD_EN, i), 0x0); |
| 1628 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_RX_LINERESET_VALUE2, i), |
| 1629 | + (rx_line_reset_period >> 16) & 0xFF); |
| 1630 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_RX_LINERESET_VALUE1, i), |
| 1631 | + (rx_line_reset_period >> 8) & 0xFF); |
| 1632 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_RX_LINERESET_VALUE0, i), |
| 1633 | + (rx_line_reset_period) & 0xFF); |
| 1634 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x2f, i), 0x69); |
| 1635 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x84, i), 0x1); |
| 1636 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x25, i), 0xf6); |
| 1637 | + } |
| 1638 | + |
| 1639 | + for_each_ufs_tx_lane(ufs, i) { |
| 1640 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_TX_CLK_PRD, i), |
| 1641 | + DIV_ROUND_UP(NSEC_PER_SEC, ufs->mclk_rate)); |
| 1642 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_TX_CLK_PRD_EN, i), |
| 1643 | + 0x02); |
| 1644 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_TX_LINERESET_PVALUE2, i), |
| 1645 | + (tx_line_reset_period >> 16) & 0xFF); |
| 1646 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_TX_LINERESET_PVALUE1, i), |
| 1647 | + (tx_line_reset_period >> 8) & 0xFF); |
| 1648 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VND_TX_LINERESET_PVALUE0, i), |
| 1649 | + (tx_line_reset_period) & 0xFF); |
| 1650 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x04, i), 1); |
| 1651 | + ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x7F, i), 0); |
| 1652 | + } |
| 1653 | + |
| 1654 | + ufshcd_dme_set(hba, UIC_ARG_MIB(0x200), 0x0); |
| 1655 | + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0x0); |
| 1656 | + ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID), 0x0); |
| 1657 | + ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID_VALID), 0x1); |
| 1658 | + ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERDEVICEID), 0x1); |
| 1659 | + ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), CPORT_CONNECTED); |
| 1660 | + ufshcd_dme_set(hba, UIC_ARG_MIB(0xA006), 0x8000); |
| 1661 | + |
| 1662 | + return 0; |
| 1663 | +} |
| 1664 | + |
| 1665 | +static int gs101_ufs_post_link(struct exynos_ufs *ufs) |
| 1666 | +{ |
| 1667 | + struct ufs_hba *hba = ufs->hba; |
| 1668 | + |
| 1669 | + exynos_ufs_enable_dbg_mode(hba); |
| 1670 | + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_SAVECONFIGTIME), 0x3e8); |
| 1671 | + exynos_ufs_disable_dbg_mode(hba); |
| 1672 | + |
| 1673 | + return 0; |
| 1674 | +} |
| 1675 | + |
| 1676 | +static int gs101_ufs_pre_pwr_change(struct exynos_ufs *ufs, |
| 1677 | + struct ufs_pa_layer_attr *pwr) |
| 1678 | +{ |
| 1679 | + struct ufs_hba *hba = ufs->hba; |
| 1680 | + |
| 1681 | + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA0), 12000); |
| 1682 | + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA1), 32000); |
| 1683 | + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA2), 16000); |
| 1684 | + unipro_writel(ufs, 8064, UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER0); |
| 1685 | + unipro_writel(ufs, 28224, UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER1); |
| 1686 | + unipro_writel(ufs, 20160, UNIPRO_DME_POWERMODE_REQ_LOCALL2TIMER2); |
| 1687 | + unipro_writel(ufs, 12000, UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER0); |
| 1688 | + unipro_writel(ufs, 32000, UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER1); |
| 1689 | + unipro_writel(ufs, 16000, UNIPRO_DME_POWERMODE_REQ_REMOTEL2TIMER2); |
| 1690 | + |
| 1691 | + return 0; |
| 1692 | +} |
| 1693 | + |
1596 | 1694 | static const struct ufs_hba_variant_ops ufs_hba_exynos_ops = {
|
1597 | 1695 | .name = "exynos_ufs",
|
1598 | 1696 | .init = exynos_ufs_init,
|
@@ -1720,6 +1818,34 @@ static const struct exynos_ufs_drv_data exynos_ufs_drvs = {
|
1720 | 1818 | .post_pwr_change = exynos7_ufs_post_pwr_change,
|
1721 | 1819 | };
|
1722 | 1820 |
|
| 1821 | +static struct exynos_ufs_uic_attr gs101_uic_attr = { |
| 1822 | + .tx_trailingclks = 0xff, |
| 1823 | + .tx_dif_p_nsec = 3000000, /* unit: ns */ |
| 1824 | + .tx_dif_n_nsec = 1000000, /* unit: ns */ |
| 1825 | + .tx_high_z_cnt_nsec = 20000, /* unit: ns */ |
| 1826 | + .tx_base_unit_nsec = 100000, /* unit: ns */ |
| 1827 | + .tx_gran_unit_nsec = 4000, /* unit: ns */ |
| 1828 | + .tx_sleep_cnt = 1000, /* unit: ns */ |
| 1829 | + .tx_min_activatetime = 0xa, |
| 1830 | + .rx_filler_enable = 0x2, |
| 1831 | + .rx_dif_p_nsec = 1000000, /* unit: ns */ |
| 1832 | + .rx_hibern8_wait_nsec = 4000000, /* unit: ns */ |
| 1833 | + .rx_base_unit_nsec = 100000, /* unit: ns */ |
| 1834 | + .rx_gran_unit_nsec = 4000, /* unit: ns */ |
| 1835 | + .rx_sleep_cnt = 1280, /* unit: ns */ |
| 1836 | + .rx_stall_cnt = 320, /* unit: ns */ |
| 1837 | + .rx_hs_g1_sync_len_cap = SYNC_LEN_COARSE(0xf), |
| 1838 | + .rx_hs_g2_sync_len_cap = SYNC_LEN_COARSE(0xf), |
| 1839 | + .rx_hs_g3_sync_len_cap = SYNC_LEN_COARSE(0xf), |
| 1840 | + .rx_hs_g1_prep_sync_len_cap = PREP_LEN(0xf), |
| 1841 | + .rx_hs_g2_prep_sync_len_cap = PREP_LEN(0xf), |
| 1842 | + .rx_hs_g3_prep_sync_len_cap = PREP_LEN(0xf), |
| 1843 | + .pa_dbg_opt_suite1_val = 0x90913C1C, |
| 1844 | + .pa_dbg_opt_suite1_off = PA_GS101_DBG_OPTION_SUITE1, |
| 1845 | + .pa_dbg_opt_suite2_val = 0xE01C115F, |
| 1846 | + .pa_dbg_opt_suite2_off = PA_GS101_DBG_OPTION_SUITE2, |
| 1847 | +}; |
| 1848 | + |
1723 | 1849 | static struct exynos_ufs_uic_attr fsd_uic_attr = {
|
1724 | 1850 | .tx_trailingclks = 0x10,
|
1725 | 1851 | .tx_dif_p_nsec = 3000000, /* unit: ns */
|
@@ -1763,7 +1889,27 @@ static const struct exynos_ufs_drv_data fsd_ufs_drvs = {
|
1763 | 1889 | .pre_pwr_change = fsd_ufs_pre_pwr_change,
|
1764 | 1890 | };
|
1765 | 1891 |
|
| 1892 | +static const struct exynos_ufs_drv_data gs101_ufs_drvs = { |
| 1893 | + .uic_attr = &gs101_uic_attr, |
| 1894 | + .quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN | |
| 1895 | + UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR | |
| 1896 | + UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR | |
| 1897 | + UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR | |
| 1898 | + UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL | |
| 1899 | + UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING, |
| 1900 | + .opts = EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL | |
| 1901 | + EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR | |
| 1902 | + EXYNOS_UFS_OPT_UFSPR_SECURE | |
| 1903 | + EXYNOS_UFS_OPT_TIMER_TICK_SELECT, |
| 1904 | + .drv_init = exynosauto_ufs_drv_init, |
| 1905 | + .pre_link = gs101_ufs_pre_link, |
| 1906 | + .post_link = gs101_ufs_post_link, |
| 1907 | + .pre_pwr_change = gs101_ufs_pre_pwr_change, |
| 1908 | +}; |
| 1909 | + |
1766 | 1910 | static const struct of_device_id exynos_ufs_of_match[] = {
|
| 1911 | + { .compatible = "google,gs101-ufs", |
| 1912 | + .data = &gs101_ufs_drvs }, |
1767 | 1913 | { .compatible = "samsung,exynos7-ufs",
|
1768 | 1914 | .data = &exynos_ufs_drvs },
|
1769 | 1915 | { .compatible = "samsung,exynosautov9-ufs",
|
|
0 commit comments