Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge patch series "UFS cleanups and enhancements to ufs-exynos for gs101"

Peter Griffin <peter.griffin@linaro.org> says:

Hi folks,

This series provides a few cleanups, bug fixes and feature enhancements for
the ufs-exynos driver, particularly for gs101 SoC.

Regarding cleanup we remove some unused phy attribute data that isn't
required when EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR is not set.

Regarding bug fixes the check for EXYNOS_UFS_OPT_UFSPR_SECURE is moved
inside exynos_ufs_config_smu() which fixes a Serror in the resume path
for gs101.

Regarding feature enhancements:
* Gear 4 is enabled which has higher speeds and better power management.
* WriteBooster capability is enabled for gs101 which increases write
performance.
* Clock gating and hibern8 capabilities are enabled for gs101. This leads
to a significantly cooler phone when running the upstream kernel on
Pixel 6. Approximately 10 degrees cooler after 20 minutes at a shell
prompt.
* AXI bus on gs101 is correctly configured for write line unique transactions
* ACG is set to be controlled by UFS_ACG_DISABLE for gs101

Additionally in v3 I've added 2 minor cleanup patches from Tudor and also
an update to MAINTAINERS to add myself as a reviewer and the linux-samsung-soc
list.

Note: In v1 I mentioned the phy hibern8 series in [1] that is still under
discussion however further testing reveals hibern8 feature still works without
the additional UFS phy register writes done in [1]. So this series can be merged
as is and has no runtime dependencies on [1] to be functional.

[1] https://lore.kernel.org/linux-arm-kernel/20241002201555.3332138-3-peter.griffin@linaro.org/T/

regards,

Peter

Link: https://lore.kernel.org/r/20241031150033.3440894-1-peter.griffin@linaro.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

+76 -64
+2
MAINTAINERS
··· 23816 23816 23817 23817 UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER EXYNOS HOOKS 23818 23818 M: Alim Akhtar <alim.akhtar@samsung.com> 23819 + R: Peter Griffin <peter.griffin@linaro.org> 23819 23820 L: linux-scsi@vger.kernel.org 23821 + L: linux-samsung-soc@vger.kernel.org 23820 23822 S: Maintained 23821 23823 F: drivers/ufs/host/ufs-exynos* 23822 23824
+73 -63
drivers/ufs/host/ufs-exynos.c
··· 48 48 #define HCI_UNIPRO_APB_CLK_CTRL 0x68 49 49 #define UNIPRO_APB_CLK(v, x) (((v) & ~0xF) | ((x) & 0xF)) 50 50 #define HCI_AXIDMA_RWDATA_BURST_LEN 0x6C 51 + #define WLU_EN BIT(31) 52 + #define WLU_BURST_LEN(x) ((x) << 27 | ((x) & 0xF)) 51 53 #define HCI_GPIO_OUT 0x70 52 54 #define HCI_ERR_EN_PA_LAYER 0x78 53 55 #define HCI_ERR_EN_DL_LAYER 0x7C ··· 76 74 #define CLK_CTRL_EN_MASK (REFCLK_CTRL_EN |\ 77 75 UNIPRO_PCLK_CTRL_EN |\ 78 76 UNIPRO_MCLK_CTRL_EN) 77 + 78 + #define HCI_IOP_ACG_DISABLE 0x100 79 + #define HCI_IOP_ACG_DISABLE_EN BIT(0) 80 + 79 81 /* Device fatal error */ 80 82 #define DFES_ERR_EN BIT(31) 81 83 #define DFES_DEF_L2_ERRS (UIC_DATA_LINK_LAYER_ERROR_RX_BUF_OF |\ ··· 204 198 exynos_ufs_ctrl_clkstop(ufs, false); 205 199 } 206 200 207 - static int exynos7_ufs_drv_init(struct device *dev, struct exynos_ufs *ufs) 201 + static int exynos_ufs_shareability(struct exynos_ufs *ufs) 208 202 { 209 - return 0; 210 - } 211 - 212 - static int exynosauto_ufs_drv_init(struct device *dev, struct exynos_ufs *ufs) 213 - { 214 - struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; 215 - 216 203 /* IO Coherency setting */ 217 204 if (ufs->sysreg) { 218 205 return regmap_update_bits(ufs->sysreg, ··· 213 214 UFS_SHARABLE, UFS_SHARABLE); 214 215 } 215 216 216 - attr->tx_dif_p_nsec = 3200000; 217 - 218 217 return 0; 218 + } 219 + 220 + static int gs101_ufs_drv_init(struct exynos_ufs *ufs) 221 + { 222 + struct ufs_hba *hba = ufs->hba; 223 + u32 reg; 224 + 225 + /* Enable WriteBooster */ 226 + hba->caps |= UFSHCD_CAP_WB_EN; 227 + 228 + /* Enable clock gating and hibern8 */ 229 + hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_HIBERN8_WITH_CLK_GATING; 230 + 231 + /* set ACG to be controlled by UFS_ACG_DISABLE */ 232 + reg = hci_readl(ufs, HCI_IOP_ACG_DISABLE); 233 + hci_writel(ufs, reg & (~HCI_IOP_ACG_DISABLE_EN), HCI_IOP_ACG_DISABLE); 234 + 235 + return exynos_ufs_shareability(ufs); 236 + } 237 + 238 + static int exynosauto_ufs_drv_init(struct exynos_ufs *ufs) 239 + { 240 + return exynos_ufs_shareability(ufs); 219 241 } 220 242 221 243 static int exynosauto_ufs_post_hce_enable(struct exynos_ufs *ufs) ··· 566 546 struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; 567 547 struct ufs_phy_time_cfg *t_cfg = &ufs->t_cfg; 568 548 549 + if (ufs->opts & EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR) 550 + return; 551 + 569 552 t_cfg->tx_linereset_p = 570 553 exynos_ufs_calc_time_cntr(ufs, attr->tx_dif_p_nsec); 571 554 t_cfg->tx_linereset_n = ··· 747 724 { 748 725 u32 reg, val; 749 726 727 + if (ufs->opts & EXYNOS_UFS_OPT_UFSPR_SECURE) 728 + return; 729 + 750 730 exynos_ufs_disable_auto_ctrl_hcc_save(ufs, &val); 751 731 752 732 /* make encryption disabled by default */ ··· 797 771 exynos_ufs_disable_ov_tm(hba); 798 772 } 799 773 774 + #define UFS_HW_VER_MAJOR_MASK GENMASK(15, 8) 775 + 776 + static u32 exynos_ufs_get_hs_gear(struct ufs_hba *hba) 777 + { 778 + u8 major; 779 + 780 + major = FIELD_GET(UFS_HW_VER_MAJOR_MASK, hba->ufs_version); 781 + 782 + if (major >= 3) 783 + return UFS_HS_G4; 784 + 785 + /* Default is HS-G3 */ 786 + return UFS_HS_G3; 787 + } 788 + 800 789 static int exynos_ufs_pre_pwr_mode(struct ufs_hba *hba, 801 790 struct ufs_pa_layer_attr *dev_max_params, 802 791 struct ufs_pa_layer_attr *dev_req_params) ··· 828 787 } 829 788 830 789 ufshcd_init_host_params(&host_params); 790 + 791 + /* This driver only support symmetric gear setting e.g. hs_tx_gear == hs_rx_gear */ 792 + host_params.hs_tx_gear = exynos_ufs_get_hs_gear(hba); 793 + host_params.hs_rx_gear = exynos_ufs_get_hs_gear(hba); 831 794 832 795 ret = ufshcd_negotiate_pwr_params(&host_params, dev_max_params, dev_req_params); 833 796 if (ret) { ··· 1474 1429 exynos_ufs_fmp_init(hba, ufs); 1475 1430 1476 1431 if (ufs->drv_data->drv_init) { 1477 - ret = ufs->drv_data->drv_init(dev, ufs); 1432 + ret = ufs->drv_data->drv_init(ufs); 1478 1433 if (ret) { 1479 1434 dev_err(dev, "failed to init drv-data\n"); 1480 1435 goto out; ··· 1485 1440 if (ret) 1486 1441 goto out; 1487 1442 exynos_ufs_specify_phy_time_attr(ufs); 1488 - if (!(ufs->opts & EXYNOS_UFS_OPT_UFSPR_SECURE)) 1489 - exynos_ufs_config_smu(ufs); 1443 + 1444 + exynos_ufs_config_smu(ufs); 1490 1445 1491 1446 hba->host->dma_alignment = DATA_UNIT_SIZE - 1; 1492 1447 return 0; ··· 1529 1484 hci_writel(ufs, 1 << 0, HCI_GPIO_OUT); 1530 1485 } 1531 1486 1532 - static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, u8 enter) 1487 + static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, enum uic_cmd_dme cmd) 1533 1488 { 1534 1489 struct exynos_ufs *ufs = ufshcd_get_variant(hba); 1535 1490 struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr; 1536 1491 1537 - if (!enter) { 1492 + if (cmd == UIC_CMD_DME_HIBER_EXIT) { 1538 1493 if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL) 1539 1494 exynos_ufs_disable_auto_ctrl_hcc(ufs); 1540 1495 exynos_ufs_ungate_clks(ufs); ··· 1562 1517 } 1563 1518 } 1564 1519 1565 - static void exynos_ufs_post_hibern8(struct ufs_hba *hba, u8 enter) 1520 + static void exynos_ufs_post_hibern8(struct ufs_hba *hba, enum uic_cmd_dme cmd) 1566 1521 { 1567 1522 struct exynos_ufs *ufs = ufshcd_get_variant(hba); 1568 1523 1569 - if (!enter) { 1570 - u32 cur_mode = 0; 1571 - u32 pwrmode; 1572 - 1573 - if (ufshcd_is_hs_mode(&ufs->dev_req_params)) 1574 - pwrmode = FAST_MODE; 1575 - else 1576 - pwrmode = SLOW_MODE; 1577 - 1578 - ufshcd_dme_get(hba, UIC_ARG_MIB(PA_PWRMODE), &cur_mode); 1579 - if (cur_mode != (pwrmode << 4 | pwrmode)) { 1580 - dev_warn(hba->dev, "%s: power mode change\n", __func__); 1581 - hba->pwr_info.pwr_rx = (cur_mode >> 4) & 0xf; 1582 - hba->pwr_info.pwr_tx = cur_mode & 0xf; 1583 - ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info); 1584 - } 1585 - 1586 - if (!(ufs->opts & EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB)) 1587 - exynos_ufs_establish_connt(ufs); 1588 - } else { 1524 + if (cmd == UIC_CMD_DME_HIBER_ENTER) { 1589 1525 ufs->entry_hibern8_t = ktime_get(); 1590 1526 exynos_ufs_gate_clks(ufs); 1591 1527 if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL) ··· 1653 1627 } 1654 1628 1655 1629 static void exynos_ufs_hibern8_notify(struct ufs_hba *hba, 1656 - enum uic_cmd_dme enter, 1630 + enum uic_cmd_dme cmd, 1657 1631 enum ufs_notify_change_status notify) 1658 1632 { 1659 1633 switch ((u8)notify) { 1660 1634 case PRE_CHANGE: 1661 - exynos_ufs_pre_hibern8(hba, enter); 1635 + exynos_ufs_pre_hibern8(hba, cmd); 1662 1636 break; 1663 1637 case POST_CHANGE: 1664 - exynos_ufs_post_hibern8(hba, enter); 1638 + exynos_ufs_post_hibern8(hba, cmd); 1665 1639 break; 1666 1640 } 1667 1641 } ··· 1917 1891 { 1918 1892 struct ufs_hba *hba = ufs->hba; 1919 1893 1894 + /* 1895 + * Enable Write Line Unique. This field has to be 0x3 1896 + * to support Write Line Unique transaction on gs101. 1897 + */ 1898 + hci_writel(ufs, WLU_EN | WLU_BURST_LEN(3), HCI_AXIDMA_RWDATA_BURST_LEN); 1899 + 1920 1900 exynos_ufs_enable_dbg_mode(hba); 1921 1901 ufshcd_dme_set(hba, UIC_ARG_MIB(PA_SAVECONFIGTIME), 0x3e8); 1922 1902 exynos_ufs_disable_dbg_mode(hba); ··· 2068 2036 EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX | 2069 2037 EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB | 2070 2038 EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER, 2071 - .drv_init = exynos7_ufs_drv_init, 2072 2039 .pre_link = exynos7_ufs_pre_link, 2073 2040 .post_link = exynos7_ufs_post_link, 2074 2041 .pre_pwr_change = exynos7_ufs_pre_pwr_change, ··· 2076 2045 2077 2046 static struct exynos_ufs_uic_attr gs101_uic_attr = { 2078 2047 .tx_trailingclks = 0xff, 2079 - .tx_dif_p_nsec = 3000000, /* unit: ns */ 2080 - .tx_dif_n_nsec = 1000000, /* unit: ns */ 2081 - .tx_high_z_cnt_nsec = 20000, /* unit: ns */ 2082 - .tx_base_unit_nsec = 100000, /* unit: ns */ 2083 - .tx_gran_unit_nsec = 4000, /* unit: ns */ 2084 - .tx_sleep_cnt = 1000, /* unit: ns */ 2085 - .tx_min_activatetime = 0xa, 2086 - .rx_filler_enable = 0x2, 2087 - .rx_dif_p_nsec = 1000000, /* unit: ns */ 2088 - .rx_hibern8_wait_nsec = 4000000, /* unit: ns */ 2089 - .rx_base_unit_nsec = 100000, /* unit: ns */ 2090 - .rx_gran_unit_nsec = 4000, /* unit: ns */ 2091 - .rx_sleep_cnt = 1280, /* unit: ns */ 2092 - .rx_stall_cnt = 320, /* unit: ns */ 2093 - .rx_hs_g1_sync_len_cap = SYNC_LEN_COARSE(0xf), 2094 - .rx_hs_g2_sync_len_cap = SYNC_LEN_COARSE(0xf), 2095 - .rx_hs_g3_sync_len_cap = SYNC_LEN_COARSE(0xf), 2096 - .rx_hs_g1_prep_sync_len_cap = PREP_LEN(0xf), 2097 - .rx_hs_g2_prep_sync_len_cap = PREP_LEN(0xf), 2098 - .rx_hs_g3_prep_sync_len_cap = PREP_LEN(0xf), 2099 2048 .pa_dbg_opt_suite1_val = 0x90913C1C, 2100 2049 .pa_dbg_opt_suite1_off = PA_GS101_DBG_OPTION_SUITE1, 2101 2050 .pa_dbg_opt_suite2_val = 0xE01C115F, ··· 2133 2122 UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR | 2134 2123 UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL | 2135 2124 UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING, 2136 - .opts = EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL | 2137 - EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR | 2125 + .opts = EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR | 2138 2126 EXYNOS_UFS_OPT_UFSPR_SECURE | 2139 2127 EXYNOS_UFS_OPT_TIMER_TICK_SELECT, 2140 - .drv_init = exynosauto_ufs_drv_init, 2128 + .drv_init = gs101_ufs_drv_init, 2141 2129 .pre_link = gs101_ufs_pre_link, 2142 2130 .post_link = gs101_ufs_post_link, 2143 2131 .pre_pwr_change = gs101_ufs_pre_pwr_change,
+1 -1
drivers/ufs/host/ufs-exynos.h
··· 182 182 unsigned int quirks; 183 183 unsigned int opts; 184 184 /* SoC's specific operations */ 185 - int (*drv_init)(struct device *dev, struct exynos_ufs *ufs); 185 + int (*drv_init)(struct exynos_ufs *ufs); 186 186 int (*pre_link)(struct exynos_ufs *ufs); 187 187 int (*post_link)(struct exynos_ufs *ufs); 188 188 int (*pre_pwr_change)(struct exynos_ufs *ufs,