diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt index b43cb9883db6..93ba9b9c9f0c 100644 --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt @@ -11,6 +11,8 @@ Required properties: "qcom,ufshc" - interrupts : - reg : + first entry should contain UFS host controller register address space (mandatory), + second entry is the device ref. clock control register map (optional). Optional properties: - phys : phandle to UFS PHY node @@ -57,7 +59,7 @@ regulators or clocks are always on. Example: ufshc@0xfc598000 { compatible = "jedec,ufs-1.1"; - reg = <0xfc598000 0x800>; + reg = <0xfc598000 0x800>, <0xfd512074 0x4>; interrupts = <0 28 0>; ufs-qcom-crypto = <&ufs_ice>; diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 69077678a198..f3e2fde8b4c0 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -801,17 +801,16 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host) return err; } -#define UFS_REF_CLK_EN (1 << 5) -static void ufs_qcom_enable_dev_ref_clk(struct ufs_qcom_host *host, bool enable) +static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable) { if (host->dev_ref_clk_ctrl_mmio && (enable ^ host->is_dev_ref_clk_enabled)) { u32 temp = readl_relaxed(host->dev_ref_clk_ctrl_mmio); if (enable) - temp |= UFS_REF_CLK_EN; + temp |= host->dev_ref_clk_en_mask; else - temp &= ~UFS_REF_CLK_EN; + temp &= ~host->dev_ref_clk_en_mask; /* * If we are here to disable this clock it might be immediately @@ -885,7 +884,7 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, /* enable the device ref clock before changing to HS mode */ if (!ufshcd_is_hs_mode(&hba->pwr_info) && ufshcd_is_hs_mode(dev_req_params)) - ufs_qcom_enable_dev_ref_clk(host, true); + ufs_qcom_dev_ref_clk_ctrl(host, true); break; case POST_CHANGE: if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx, @@ -917,7 +916,7 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, /* disable the device ref clock if entered PWM mode */ if (ufshcd_is_hs_mode(&hba->pwr_info) && !ufshcd_is_hs_mode(dev_req_params)) - ufs_qcom_enable_dev_ref_clk(host, false); + ufs_qcom_dev_ref_clk_ctrl(host, false); break; default: ret = -EINVAL; @@ -1075,7 +1074,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) } /* enable the device ref clock for HS mode*/ if (ufshcd_is_hs_mode(&hba->pwr_info)) - ufs_qcom_enable_dev_ref_clk(host, true); + ufs_qcom_dev_ref_clk_ctrl(host, true); vote = host->bus_vote.saved_vote; if (vote == host->bus_vote.min_bw_vote) ufs_qcom_update_bus_bw_vote(host); @@ -1086,7 +1085,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) /* turn off UFS local PHY ref_clk */ ufs_qcom_phy_disable_ref_clk(host->generic_phy); /* disable device ref_clk */ - ufs_qcom_enable_dev_ref_clk(host, false); + ufs_qcom_dev_ref_clk_ctrl(host, false); } vote = host->bus_vote.min_bw_vote; } @@ -1196,8 +1195,6 @@ static int ufs_qcom_init(struct ufs_hba *hba) struct device *dev = hba->dev; struct platform_device *pdev = to_platform_device(dev); struct ufs_qcom_host *host; - u8 major; - u16 minor, step; struct resource *res; if (strlen(android_boot_dev) && strcmp(android_boot_dev, dev_name(dev))) @@ -1252,10 +1249,32 @@ static int ufs_qcom_init(struct ufs_hba *hba) if (err) goto out_host_free; - ufs_qcom_get_controller_revision(hba, &major, &minor, &step); + ufs_qcom_get_controller_revision(hba, &host->hw_ver.major, + &host->hw_ver.minor, &host->hw_ver.step); + + /* "dev_ref_clk_ctrl_mem" is optional resource */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_info(dev, "%s: dev_ref_clk_ctrl_mem resource not found\n", + __func__); + } else { + host->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res); + if (IS_ERR(host->dev_ref_clk_ctrl_mmio)) { + dev_warn(dev, + "%s: could not map dev_ref_clk_ctrl_mmio, err %ld\n", + __func__, PTR_ERR(host->dev_ref_clk_ctrl_mmio)); + host->dev_ref_clk_ctrl_mmio = NULL; + } + /* Set the correct mask for the device ref. clock enable bit */ + if (host->hw_ver.major >= 0x02) + host->dev_ref_clk_en_mask = BIT(26); + else + host->dev_ref_clk_en_mask = BIT(5); + } + /* update phy revision information before calling phy_init() */ ufs_qcom_phy_save_controller_version(host->generic_phy, - major, minor, step); + host->hw_ver.major, host->hw_ver.minor, host->hw_ver.step); phy_init(host->generic_phy); err = phy_power_on(host->generic_phy); @@ -1267,8 +1286,6 @@ static int ufs_qcom_init(struct ufs_hba *hba) goto out_disable_phy; ufs_qcom_set_caps(hba); - ufs_qcom_get_controller_revision(hba, &host->hw_ver.major, - &host->hw_ver.minor, &host->hw_ver.step); ufs_qcom_advertise_quirks(hba); hba->caps |= UFSHCD_CAP_CLK_GATING | @@ -1277,21 +1294,6 @@ static int ufs_qcom_init(struct ufs_hba *hba) hba->caps |= UFSHCD_CAP_HIBERN8_ENTER_ON_IDLE; ufs_qcom_setup_clocks(hba, true); - /* "dev_ref_clk_ctrl_mem" is optional resource */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) { - dev_dbg(dev, "%s: dev_ref_clk_ctrl_mem resource not found\n", - __func__); - } else { - host->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res); - if (IS_ERR(host->dev_ref_clk_ctrl_mmio)) { - dev_warn(dev, - "%s: could not map dev_ref_clk_ctrl_mmio, err %ld\n", - __func__, PTR_ERR(host->dev_ref_clk_ctrl_mmio)); - host->dev_ref_clk_ctrl_mmio = NULL; - } - } - if (hba->dev->id < MAX_UFS_QCOM_HOSTS) ufs_qcom_hosts[hba->dev->id] = host; diff --git a/include/linux/scsi/ufs/ufs-qcom.h b/include/linux/scsi/ufs/ufs-qcom.h index fc8b2c98f191..e7baca9cbd09 100644 --- a/include/linux/scsi/ufs/ufs-qcom.h +++ b/include/linux/scsi/ufs/ufs-qcom.h @@ -251,6 +251,7 @@ struct ufs_qcom_host { void __iomem *dev_ref_clk_ctrl_mmio; bool is_dev_ref_clk_enabled; struct ufs_hw_version hw_ver; + u32 dev_ref_clk_en_mask; #ifdef CONFIG_DEBUG_FS struct qcom_debugfs_files debugfs_files; #endif