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: host: mediatek: Provide features and fixes in MediaTek platforms"

peter.wang@mediatek.com says:

This series fixes some defects and provide features in MediaTek UFS drivers.

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

+328 -33
+296 -33
drivers/ufs/host/ufs-mediatek.c
··· 96 96 { 97 97 struct ufs_mtk_host *host = ufshcd_get_variant(hba); 98 98 99 - return !!(host->caps & UFS_MTK_CAP_BOOST_CRYPT_ENGINE); 99 + return host->caps & UFS_MTK_CAP_BOOST_CRYPT_ENGINE; 100 100 } 101 101 102 102 static bool ufs_mtk_is_va09_supported(struct ufs_hba *hba) 103 103 { 104 104 struct ufs_mtk_host *host = ufshcd_get_variant(hba); 105 105 106 - return !!(host->caps & UFS_MTK_CAP_VA09_PWR_CTRL); 106 + return host->caps & UFS_MTK_CAP_VA09_PWR_CTRL; 107 107 } 108 108 109 109 static bool ufs_mtk_is_broken_vcc(struct ufs_hba *hba) 110 110 { 111 111 struct ufs_mtk_host *host = ufshcd_get_variant(hba); 112 112 113 - return !!(host->caps & UFS_MTK_CAP_BROKEN_VCC); 113 + return host->caps & UFS_MTK_CAP_BROKEN_VCC; 114 114 } 115 115 116 116 static bool ufs_mtk_is_pmc_via_fastauto(struct ufs_hba *hba) 117 117 { 118 118 struct ufs_mtk_host *host = ufshcd_get_variant(hba); 119 119 120 - return !!(host->caps & UFS_MTK_CAP_PMC_VIA_FASTAUTO); 120 + return host->caps & UFS_MTK_CAP_PMC_VIA_FASTAUTO; 121 121 } 122 122 123 123 static bool ufs_mtk_is_tx_skew_fix(struct ufs_hba *hba) 124 124 { 125 125 struct ufs_mtk_host *host = ufshcd_get_variant(hba); 126 126 127 - return (host->caps & UFS_MTK_CAP_TX_SKEW_FIX); 127 + return host->caps & UFS_MTK_CAP_TX_SKEW_FIX; 128 128 } 129 129 130 130 static bool ufs_mtk_is_rtff_mtcmos(struct ufs_hba *hba) 131 131 { 132 132 struct ufs_mtk_host *host = ufshcd_get_variant(hba); 133 133 134 - return (host->caps & UFS_MTK_CAP_RTFF_MTCMOS); 134 + return host->caps & UFS_MTK_CAP_RTFF_MTCMOS; 135 135 } 136 136 137 137 static bool ufs_mtk_is_allow_vccqx_lpm(struct ufs_hba *hba) 138 138 { 139 139 struct ufs_mtk_host *host = ufshcd_get_variant(hba); 140 140 141 - return (host->caps & UFS_MTK_CAP_ALLOW_VCCQX_LPM); 141 + return host->caps & UFS_MTK_CAP_ALLOW_VCCQX_LPM; 142 + } 143 + 144 + static bool ufs_mtk_is_clk_scale_ready(struct ufs_hba *hba) 145 + { 146 + struct ufs_mtk_host *host = ufshcd_get_variant(hba); 147 + struct ufs_mtk_clk *mclk = &host->mclk; 148 + 149 + return mclk->ufs_sel_clki && 150 + mclk->ufs_sel_max_clki && 151 + mclk->ufs_sel_min_clki; 142 152 } 143 153 144 154 static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable) ··· 277 267 ufshcd_writel(hba, 278 268 ufshcd_readl(hba, REG_UFS_XOUFS_CTRL) | 0x80, 279 269 REG_UFS_XOUFS_CTRL); 270 + 271 + /* DDR_EN setting */ 272 + if (host->ip_ver >= IP_VER_MT6989) { 273 + ufshcd_rmwl(hba, UFS_MASK(0x7FFF, 8), 274 + 0x453000, REG_UFS_MMIO_OPT_CTRL_0); 275 + } 276 + 280 277 } 281 278 282 279 return 0; ··· 361 344 362 345 dev_err(hba->dev, "missing ack of refclk req, reg: 0x%x\n", value); 363 346 364 - ufs_mtk_ref_clk_notify(host->ref_clk_enabled, POST_CHANGE, res); 347 + /* 348 + * If clock on timeout, assume clock is off, notify tfa do clock 349 + * off setting.(keep DIFN disable, release resource) 350 + * If clock off timeout, assume clock will off finally, 351 + * set ref_clk_enabled directly.(keep DIFN disable, keep resource) 352 + */ 353 + if (on) 354 + ufs_mtk_ref_clk_notify(false, POST_CHANGE, res); 355 + else 356 + host->ref_clk_enabled = false; 365 357 366 358 return -ETIMEDOUT; 367 359 ··· 689 663 if (of_property_read_bool(np, "mediatek,ufs-rtff-mtcmos")) 690 664 host->caps |= UFS_MTK_CAP_RTFF_MTCMOS; 691 665 666 + if (of_property_read_bool(np, "mediatek,ufs-broken-rtc")) 667 + host->caps |= UFS_MTK_CAP_MCQ_BROKEN_RTC; 668 + 692 669 dev_info(hba->dev, "caps: 0x%x", host->caps); 693 670 } 694 671 ··· 808 779 return ret; 809 780 } 810 781 782 + static u32 ufs_mtk_mcq_get_irq(struct ufs_hba *hba, unsigned int cpu) 783 + { 784 + struct ufs_mtk_host *host = ufshcd_get_variant(hba); 785 + struct blk_mq_tag_set *tag_set = &hba->host->tag_set; 786 + struct blk_mq_queue_map *map = &tag_set->map[HCTX_TYPE_DEFAULT]; 787 + unsigned int nr = map->nr_queues; 788 + unsigned int q_index; 789 + 790 + q_index = map->mq_map[cpu]; 791 + if (q_index > nr) { 792 + dev_err(hba->dev, "hwq index %d exceed %d\n", 793 + q_index, nr); 794 + return MTK_MCQ_INVALID_IRQ; 795 + } 796 + 797 + return host->mcq_intr_info[q_index].irq; 798 + } 799 + 800 + static void ufs_mtk_mcq_set_irq_affinity(struct ufs_hba *hba, unsigned int cpu) 801 + { 802 + unsigned int irq, _cpu; 803 + int ret; 804 + 805 + irq = ufs_mtk_mcq_get_irq(hba, cpu); 806 + if (irq == MTK_MCQ_INVALID_IRQ) { 807 + dev_err(hba->dev, "invalid irq. unable to bind irq to cpu%d", cpu); 808 + return; 809 + } 810 + 811 + /* force migrate irq of cpu0 to cpu3 */ 812 + _cpu = (cpu == 0) ? 3 : cpu; 813 + ret = irq_set_affinity(irq, cpumask_of(_cpu)); 814 + if (ret) { 815 + dev_err(hba->dev, "set irq %d affinity to CPU %d failed\n", 816 + irq, _cpu); 817 + return; 818 + } 819 + dev_info(hba->dev, "set irq %d affinity to CPU: %d\n", irq, _cpu); 820 + } 821 + 822 + static bool ufs_mtk_is_legacy_chipset(struct ufs_hba *hba, u32 hw_ip_ver) 823 + { 824 + bool is_legacy = false; 825 + 826 + switch (hw_ip_ver) { 827 + case IP_LEGACY_VER_MT6893: 828 + case IP_LEGACY_VER_MT6781: 829 + /* can add other legacy chipset ID here accordingly */ 830 + is_legacy = true; 831 + break; 832 + default: 833 + break; 834 + } 835 + dev_info(hba->dev, "legacy IP version - 0x%x, is legacy : %d", hw_ip_ver, is_legacy); 836 + 837 + return is_legacy; 838 + } 839 + 840 + /* 841 + * HW version format has been changed from 01MMmmmm to 1MMMmmmm, since 842 + * project MT6878. In order to perform correct version comparison, 843 + * version number is changed by SW for the following projects. 844 + * IP_VER_MT6983 0x00360000 to 0x10360000 845 + * IP_VER_MT6897 0x01440000 to 0x10440000 846 + * IP_VER_MT6989 0x01450000 to 0x10450000 847 + * IP_VER_MT6991 0x01460000 to 0x10460000 848 + */ 849 + static void ufs_mtk_get_hw_ip_version(struct ufs_hba *hba) 850 + { 851 + struct ufs_mtk_host *host = ufshcd_get_variant(hba); 852 + u32 hw_ip_ver; 853 + 854 + hw_ip_ver = ufshcd_readl(hba, REG_UFS_MTK_IP_VER); 855 + 856 + if (((hw_ip_ver & (0xFF << 24)) == (0x1 << 24)) || 857 + ((hw_ip_ver & (0xFF << 24)) == 0)) { 858 + hw_ip_ver &= ~(0xFF << 24); 859 + hw_ip_ver |= (0x1 << 28); 860 + } 861 + 862 + host->ip_ver = hw_ip_ver; 863 + 864 + host->legacy_ip_ver = ufs_mtk_is_legacy_chipset(hba, hw_ip_ver); 865 + } 866 + 811 867 static void ufs_mtk_get_controller_version(struct ufs_hba *hba) 812 868 { 813 869 struct ufs_mtk_host *host = ufshcd_get_variant(hba); ··· 932 818 { 933 819 struct ufs_mtk_host *host = ufshcd_get_variant(hba); 934 820 struct list_head *head = &hba->clk_list_head; 935 - struct ufs_mtk_clk *mclk = &host->mclk; 936 821 struct ufs_clk_info *clki, *clki_tmp; 822 + struct device *dev = hba->dev; 823 + struct regulator *reg; 824 + u32 volt; 937 825 938 826 /* 939 827 * Find private clocks and store them in struct ufs_mtk_clk. ··· 953 837 host->mclk.ufs_sel_min_clki = clki; 954 838 clk_disable_unprepare(clki->clk); 955 839 list_del(&clki->list); 840 + } else if (!strcmp(clki->name, "ufs_fde")) { 841 + host->mclk.ufs_fde_clki = clki; 842 + } else if (!strcmp(clki->name, "ufs_fde_max_src")) { 843 + host->mclk.ufs_fde_max_clki = clki; 844 + clk_disable_unprepare(clki->clk); 845 + list_del(&clki->list); 846 + } else if (!strcmp(clki->name, "ufs_fde_min_src")) { 847 + host->mclk.ufs_fde_min_clki = clki; 848 + clk_disable_unprepare(clki->clk); 849 + list_del(&clki->list); 956 850 } 957 851 } 958 852 959 - if (!mclk->ufs_sel_clki || !mclk->ufs_sel_max_clki || 960 - !mclk->ufs_sel_min_clki) { 853 + list_for_each_entry(clki, head, list) { 854 + dev_info(hba->dev, "clk \"%s\" present", clki->name); 855 + } 856 + 857 + if (!ufs_mtk_is_clk_scale_ready(hba)) { 961 858 hba->caps &= ~UFSHCD_CAP_CLK_SCALING; 962 859 dev_info(hba->dev, 963 860 "%s: Clk-scaling not ready. Feature disabled.", 964 861 __func__); 862 + return; 863 + } 864 + 865 + /* 866 + * Default get vcore if dts have these settings. 867 + * No matter clock scaling support or not. (may disable by customer) 868 + */ 869 + reg = devm_regulator_get_optional(dev, "dvfsrc-vcore"); 870 + if (IS_ERR(reg)) { 871 + dev_info(dev, "failed to get dvfsrc-vcore: %ld", 872 + PTR_ERR(reg)); 873 + return; 874 + } 875 + 876 + if (of_property_read_u32(dev->of_node, "clk-scale-up-vcore-min", 877 + &volt)) { 878 + dev_info(dev, "failed to get clk-scale-up-vcore-min"); 879 + return; 880 + } 881 + 882 + host->mclk.reg_vcore = reg; 883 + host->mclk.vcore_volt = volt; 884 + 885 + /* If default boot is max gear, request vcore */ 886 + if (reg && volt && host->clk_scale_up) { 887 + if (regulator_set_voltage(reg, volt, INT_MAX)) { 888 + dev_info(hba->dev, 889 + "Failed to set vcore to %d\n", volt); 890 + } 965 891 } 966 892 } 967 893 ··· 1172 1014 1173 1015 /* Enable clk scaling*/ 1174 1016 hba->caps |= UFSHCD_CAP_CLK_SCALING; 1017 + host->clk_scale_up = true; /* default is max freq */ 1175 1018 1176 1019 /* Set runtime pm delay to replace default */ 1177 1020 shost->rpm_autosuspend_delay = MTK_RPM_AUTOSUSPEND_DELAY_MS; 1178 1021 1179 1022 hba->quirks |= UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL; 1023 + 1180 1024 hba->quirks |= UFSHCD_QUIRK_MCQ_BROKEN_INTR; 1181 - hba->quirks |= UFSHCD_QUIRK_MCQ_BROKEN_RTC; 1025 + if (host->caps & UFS_MTK_CAP_MCQ_BROKEN_RTC) 1026 + hba->quirks |= UFSHCD_QUIRK_MCQ_BROKEN_RTC; 1027 + 1182 1028 hba->vps->wb_flush_threshold = UFS_WB_BUF_REMAIN_PERCENT(80); 1183 1029 1184 1030 if (host->caps & UFS_MTK_CAP_DISABLE_AH8) ··· 1212 1050 1213 1051 ufs_mtk_setup_clocks(hba, true, POST_CHANGE); 1214 1052 1215 - host->ip_ver = ufshcd_readl(hba, REG_UFS_MTK_IP_VER); 1053 + ufs_mtk_get_hw_ip_version(hba); 1216 1054 1217 1055 goto out; 1218 1056 ··· 1667 1505 { 1668 1506 struct ufs_dev_info *dev_info = &hba->dev_info; 1669 1507 u16 mid = dev_info->wmanufacturerid; 1508 + unsigned int cpu; 1509 + 1510 + if (hba->mcq_enabled) { 1511 + /* Iterate all cpus to set affinity for mcq irqs */ 1512 + for (cpu = 0; cpu < nr_cpu_ids; cpu++) 1513 + ufs_mtk_mcq_set_irq_affinity(hba, cpu); 1514 + } 1670 1515 1671 1516 if (mid == UFS_VENDOR_SAMSUNG) { 1672 1517 ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 6); ··· 1767 1598 hba->vps->ondemand_data.downdifferential = 20; 1768 1599 } 1769 1600 1601 + static void _ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up) 1602 + { 1603 + struct ufs_mtk_host *host = ufshcd_get_variant(hba); 1604 + struct ufs_mtk_clk *mclk = &host->mclk; 1605 + struct ufs_clk_info *clki = mclk->ufs_sel_clki; 1606 + struct ufs_clk_info *fde_clki = mclk->ufs_fde_clki; 1607 + struct regulator *reg; 1608 + int volt, ret = 0; 1609 + bool clk_bind_vcore = false; 1610 + bool clk_fde_scale = false; 1611 + 1612 + if (!hba->clk_scaling.is_initialized) 1613 + return; 1614 + 1615 + if (!clki || !fde_clki) 1616 + return; 1617 + 1618 + reg = host->mclk.reg_vcore; 1619 + volt = host->mclk.vcore_volt; 1620 + if (reg && volt != 0) 1621 + clk_bind_vcore = true; 1622 + 1623 + if (mclk->ufs_fde_max_clki && mclk->ufs_fde_min_clki) 1624 + clk_fde_scale = true; 1625 + 1626 + ret = clk_prepare_enable(clki->clk); 1627 + if (ret) { 1628 + dev_info(hba->dev, 1629 + "clk_prepare_enable() fail, ret: %d\n", ret); 1630 + return; 1631 + } 1632 + 1633 + if (clk_fde_scale) { 1634 + ret = clk_prepare_enable(fde_clki->clk); 1635 + if (ret) { 1636 + dev_info(hba->dev, 1637 + "fde clk_prepare_enable() fail, ret: %d\n", ret); 1638 + return; 1639 + } 1640 + } 1641 + 1642 + if (scale_up) { 1643 + if (clk_bind_vcore) { 1644 + ret = regulator_set_voltage(reg, volt, INT_MAX); 1645 + if (ret) { 1646 + dev_info(hba->dev, 1647 + "Failed to set vcore to %d\n", volt); 1648 + goto out; 1649 + } 1650 + } 1651 + 1652 + ret = clk_set_parent(clki->clk, mclk->ufs_sel_max_clki->clk); 1653 + if (ret) { 1654 + dev_info(hba->dev, "Failed to set clk mux, ret = %d\n", 1655 + ret); 1656 + } 1657 + 1658 + if (clk_fde_scale) { 1659 + ret = clk_set_parent(fde_clki->clk, 1660 + mclk->ufs_fde_max_clki->clk); 1661 + if (ret) { 1662 + dev_info(hba->dev, 1663 + "Failed to set fde clk mux, ret = %d\n", 1664 + ret); 1665 + } 1666 + } 1667 + } else { 1668 + if (clk_fde_scale) { 1669 + ret = clk_set_parent(fde_clki->clk, 1670 + mclk->ufs_fde_min_clki->clk); 1671 + if (ret) { 1672 + dev_info(hba->dev, 1673 + "Failed to set fde clk mux, ret = %d\n", 1674 + ret); 1675 + goto out; 1676 + } 1677 + } 1678 + 1679 + ret = clk_set_parent(clki->clk, mclk->ufs_sel_min_clki->clk); 1680 + if (ret) { 1681 + dev_info(hba->dev, "Failed to set clk mux, ret = %d\n", 1682 + ret); 1683 + goto out; 1684 + } 1685 + 1686 + if (clk_bind_vcore) { 1687 + ret = regulator_set_voltage(reg, 0, INT_MAX); 1688 + if (ret) { 1689 + dev_info(hba->dev, 1690 + "failed to set vcore to MIN\n"); 1691 + } 1692 + } 1693 + } 1694 + 1695 + out: 1696 + clk_disable_unprepare(clki->clk); 1697 + 1698 + if (clk_fde_scale) 1699 + clk_disable_unprepare(fde_clki->clk); 1700 + } 1701 + 1770 1702 /** 1771 1703 * ufs_mtk_clk_scale - Internal clk scaling operation 1772 1704 * ··· 1885 1615 struct ufs_mtk_host *host = ufshcd_get_variant(hba); 1886 1616 struct ufs_mtk_clk *mclk = &host->mclk; 1887 1617 struct ufs_clk_info *clki = mclk->ufs_sel_clki; 1888 - int ret = 0; 1889 1618 1890 - ret = clk_prepare_enable(clki->clk); 1891 - if (ret) { 1892 - dev_info(hba->dev, 1893 - "clk_prepare_enable() fail, ret: %d\n", ret); 1894 - return; 1895 - } 1619 + if (host->clk_scale_up == scale_up) 1620 + goto out; 1896 1621 1897 - if (scale_up) { 1898 - ret = clk_set_parent(clki->clk, mclk->ufs_sel_max_clki->clk); 1622 + if (scale_up) 1623 + _ufs_mtk_clk_scale(hba, true); 1624 + else 1625 + _ufs_mtk_clk_scale(hba, false); 1626 + 1627 + host->clk_scale_up = scale_up; 1628 + 1629 + /* Must always set before clk_set_rate() */ 1630 + if (scale_up) 1899 1631 clki->curr_freq = clki->max_freq; 1900 - } else { 1901 - ret = clk_set_parent(clki->clk, mclk->ufs_sel_min_clki->clk); 1632 + else 1902 1633 clki->curr_freq = clki->min_freq; 1903 - } 1904 - 1905 - if (ret) { 1906 - dev_info(hba->dev, 1907 - "Failed to set ufs_sel_clki, ret: %d\n", ret); 1908 - } 1909 - 1910 - clk_disable_unprepare(clki->clk); 1911 - 1634 + out: 1912 1635 trace_ufs_mtk_clk_scale(clki->name, scale_up, clk_get_rate(clki->clk)); 1913 1636 } 1914 1637
+32
drivers/ufs/host/ufs-mediatek.h
··· 133 133 UFS_MTK_CAP_DISABLE_MCQ = 1 << 8, 134 134 /* Control MTCMOS with RTFF */ 135 135 UFS_MTK_CAP_RTFF_MTCMOS = 1 << 9, 136 + 137 + UFS_MTK_CAP_MCQ_BROKEN_RTC = 1 << 10, 136 138 }; 137 139 138 140 struct ufs_mtk_crypt_cfg { ··· 149 147 struct ufs_clk_info *ufs_sel_clki; /* Mux */ 150 148 struct ufs_clk_info *ufs_sel_max_clki; /* Max src */ 151 149 struct ufs_clk_info *ufs_sel_min_clki; /* Min src */ 150 + struct ufs_clk_info *ufs_fde_clki; /* Mux */ 151 + struct ufs_clk_info *ufs_fde_max_clki; /* Max src */ 152 + struct ufs_clk_info *ufs_fde_min_clki; /* Min src */ 153 + struct regulator *reg_vcore; 154 + int vcore_volt; 152 155 }; 153 156 154 157 struct ufs_mtk_hw_ver { ··· 183 176 bool mphy_powered_on; 184 177 bool unipro_lpm; 185 178 bool ref_clk_enabled; 179 + bool clk_scale_up; 186 180 u16 ref_clk_ungating_wait_us; 187 181 u16 ref_clk_gating_wait_us; 188 182 u32 ip_ver; 183 + bool legacy_ip_ver; 189 184 190 185 bool mcq_set_intr; 191 186 bool is_mcq_intr_enabled; ··· 200 191 201 192 /* MTK RTT support number */ 202 193 #define MTK_MAX_NUM_RTT 2 194 + 195 + /* UFSHCI MTK ip version value */ 196 + enum { 197 + /* UFSHCI 3.1 */ 198 + IP_VER_MT6983 = 0x10360000, 199 + IP_VER_MT6878 = 0x10420200, 200 + 201 + /* UFSHCI 4.0 */ 202 + IP_VER_MT6897 = 0x10440000, 203 + IP_VER_MT6989 = 0x10450000, 204 + IP_VER_MT6899 = 0x10450100, 205 + IP_VER_MT6991_A0 = 0x10460000, 206 + IP_VER_MT6991_B0 = 0x10470000, 207 + IP_VER_MT6993 = 0x10480000, 208 + 209 + IP_VER_NONE = 0xFFFFFFFF 210 + }; 211 + 212 + enum ip_ver_legacy { 213 + IP_LEGACY_VER_MT6781 = 0x10380000, 214 + IP_LEGACY_VER_MT6879 = 0x10360000, 215 + IP_LEGACY_VER_MT6893 = 0x20160706 216 + }; 203 217 204 218 #endif /* !_UFS_MEDIATEK_H */