Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ properties:
power-domains:
maxItems: 1

operating-points-v2: true

opp-table:
type: object

required:
- compatible
- reg
Expand Down Expand Up @@ -80,5 +85,26 @@ examples:
clock-names = "core",
"iface";
power-domains = <&gcc UFS_PHY_GDSC>;

operating-points-v2 = <&ice_opp_table>;

ice_opp_table: opp-table {
compatible = "operating-points-v2";

opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};

opp-201500000 {
opp-hz = /bits/ 64 <201500000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};

opp-403000000 {
opp-hz = /bits/ 64 <403000000>;
required-opps = <&rpmhpd_opp_nom>;
};
};
};
...
42 changes: 42 additions & 0 deletions arch/arm64/boot/dts/qcom/kodiak.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,27 @@
clock-names = "core",
"iface";
power-domains = <&rpmhpd SC7280_CX>;

operating-points-v2 = <&ice_mmc_opp_table>;

ice_mmc_opp_table: opp-table {
compatible = "operating-points-v2";

opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};

opp-150000000 {
opp-hz = /bits/ 64 <150000000>;
required-opps = <&rpmhpd_opp_svs>;
};

opp-300000000 {
opp-hz = /bits/ 64 <300000000>;
required-opps = <&rpmhpd_opp_nom>;
};
};
};

gpi_dma0: dma-controller@900000 {
Expand Down Expand Up @@ -2597,6 +2618,27 @@
clock-names = "core",
"iface";
power-domains = <&gcc GCC_UFS_PHY_GDSC>;

operating-points-v2 = <&ice_opp_table>;

ice_opp_table: opp-table {
compatible = "operating-points-v2";

opp-75000000 {
opp-hz = /bits/ 64 <75000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};

opp-150000000 {
opp-hz = /bits/ 64 <150000000>;
required-opps = <&rpmhpd_opp_svs>;
};

opp-300000000 {
opp-hz = /bits/ 64 <300000000>;
required-opps = <&rpmhpd_opp_nom>;
};
};
};

cryptobam: dma-controller@1dc4000 {
Expand Down
32 changes: 32 additions & 0 deletions arch/arm64/boot/dts/qcom/monaco.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -2730,6 +2730,22 @@
clock-names = "core",
"iface";
power-domains = <&gcc GCC_UFS_PHY_GDSC>;

operating-points-v2 = <&ice_opp_table>;

ice_opp_table: opp-table {
compatible = "operating-points-v2";

opp-201600000 {
opp-hz = /bits/ 64 <201600000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};

opp-403200000 {
opp-hz = /bits/ 64 <403200000>;
required-opps = <&rpmhpd_opp_nom>;
};
};
};

crypto: crypto@1dfa000 {
Expand Down Expand Up @@ -4787,6 +4803,22 @@
clock-names = "core",
"iface";
power-domains = <&rpmhpd RPMHPD_CX>;

operating-points-v2 = <&ice_mmc_opp_table>;

ice_mmc_opp_table: opp-table {
compatible = "operating-points-v2";

opp-150000000 {
opp-hz = /bits/ 64 <150000000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};

opp-300000000 {
opp-hz = /bits/ 64 <300000000>;
required-opps = <&rpmhpd_opp_nom>;
};
};
};

usb_1_hsphy: phy@8904000 {
Expand Down
24 changes: 24 additions & 0 deletions drivers/mmc/host/sdhci-msm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1889,6 +1889,8 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
#ifdef CONFIG_MMC_CRYPTO

static const struct blk_crypto_ll_ops sdhci_msm_crypto_ops; /* forward decl */
static int sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host, unsigned long target_freq,
bool round_ceil); /* forward decl */

static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
struct cqhci_host *cq_host)
Expand Down Expand Up @@ -1948,6 +1950,11 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,

mmc->caps2 |= MMC_CAP2_CRYPTO;
mmc->caps2 |= MMC_CAP2_CRYPTO_NO_REPROG;

err = sdhci_msm_ice_scale_clk(msm_host, INT_MAX, false);
if (err && err != -EOPNOTSUPP)
dev_warn(dev, "Unable to boost ICE clock to TURBO\n");

return 0;
}

Expand All @@ -1973,6 +1980,16 @@ static int sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
return 0;
}

static int sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host,
unsigned long target_freq,
bool round_ceil)
{
if (msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)
return qcom_ice_scale_clk(msm_host->ice, target_freq, round_ceil);

return 0;
}

static inline struct sdhci_msm_host *
sdhci_msm_host_from_crypto_profile(struct blk_crypto_profile *profile)
{
Expand Down Expand Up @@ -2076,6 +2093,13 @@ sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
{
return 0;
}

static inline int
sdhci_msm_ice_scale_clk(struct sdhci_msm_host *msm_host, unsigned long target_freq,
bool round_ceil)
{
return 0;
}
#endif /* !CONFIG_MMC_CRYPTO */

/*****************************************************************************\
Expand Down
92 changes: 92 additions & 0 deletions drivers/soc/qcom/ice.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>

#include <linux/firmware/qcom/qcom_scm.h>

Expand Down Expand Up @@ -112,6 +113,8 @@ struct qcom_ice {
bool use_hwkm;
bool hwkm_init_complete;
u8 hwkm_version;
unsigned long core_clk_freq;
bool has_opp;
};

static bool qcom_ice_check_supported(struct qcom_ice *ice)
Expand Down Expand Up @@ -311,6 +314,10 @@ int qcom_ice_resume(struct qcom_ice *ice)
struct device *dev = ice->dev;
int err;

/* Restore the ICE core clk freq */
if (ice->has_opp && ice->core_clk_freq)
dev_pm_opp_set_rate(ice->dev, ice->core_clk_freq);

err = clk_prepare_enable(ice->core_clk);
if (err) {
dev_err(dev, "Failed to enable core clock: %d\n", err);
Expand All @@ -331,6 +338,11 @@ int qcom_ice_suspend(struct qcom_ice *ice)
{
clk_disable_unprepare(ice->iface_clk);
clk_disable_unprepare(ice->core_clk);

/* Drop the clock votes while suspend */
if (ice->has_opp)
dev_pm_opp_set_rate(ice->dev, 0);

ice->hwkm_init_complete = false;

return 0;
Expand Down Expand Up @@ -556,6 +568,51 @@ int qcom_ice_import_key(struct qcom_ice *ice,
}
EXPORT_SYMBOL_GPL(qcom_ice_import_key);

/**
* qcom_ice_scale_clk() - Scale ICE clock for DVFS-aware operations
* @ice: ICE driver data
* @target_freq: requested frequency in Hz
* @round_ceil: when true, selects nearest freq >= @target_freq;
* otherwise, selects nearest freq <= @target_freq
*
* Selects an OPP frequency based on @target_freq and the rounding direction
* specified by @round_ceil, then programs it using dev_pm_opp_set_rate(),
* including any voltage or power-domain transitions handled by the OPP
* framework. Updates ice->core_clk_freq on success.
*
* Return: 0 on success; -EOPNOTSUPP if no OPP table; or error from
* dev_pm_opp_set_rate()/OPP lookup.
*/
int qcom_ice_scale_clk(struct qcom_ice *ice, unsigned long target_freq,
bool round_ceil)
{
unsigned long ice_freq = target_freq;
struct dev_pm_opp *opp;
int ret;

if (!ice->has_opp)
return -EOPNOTSUPP;

if (round_ceil)
opp = dev_pm_opp_find_freq_ceil(ice->dev, &ice_freq);
else
opp = dev_pm_opp_find_freq_floor(ice->dev, &ice_freq);

if (IS_ERR(opp))
return PTR_ERR(opp);
dev_pm_opp_put(opp);

ret = dev_pm_opp_set_rate(ice->dev, ice_freq);
if (ret) {
dev_err(ice->dev, "Unable to scale ICE clock rate\n");
return ret;
}
ice->core_clk_freq = ice_freq;

return ret;
}
EXPORT_SYMBOL_GPL(qcom_ice_scale_clk);

static struct qcom_ice *qcom_ice_create(struct device *dev,
void __iomem *base)
{
Expand Down Expand Up @@ -731,6 +788,7 @@ static int qcom_ice_probe(struct platform_device *pdev)
{
struct qcom_ice *engine;
void __iomem *base;
int err;

base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base)) {
Expand All @@ -742,6 +800,40 @@ static int qcom_ice_probe(struct platform_device *pdev)
if (IS_ERR(engine))
return PTR_ERR(engine);

/* qcom_ice_create() may return NULL if scm calls are not available */
if (!engine)
return -EOPNOTSUPP;

err = devm_pm_opp_set_clkname(&pdev->dev, "core");
if (err && err != -ENOENT) {
dev_err(&pdev->dev, "Unable to set core clkname to OPP-table\n");
return err;
}

/* OPP table is optional */
err = devm_pm_opp_of_add_table(&pdev->dev);
if (err && err != -ENODEV) {
dev_err(&pdev->dev, "Invalid OPP table in Device tree\n");
return err;
}

/*
* The OPP table is optional. devm_pm_opp_of_add_table() returns
* -ENODEV when no OPP table is present in DT, which is not treated
* as an error. Therefore, track successful OPP registration only
* when the return value is 0.
*/
engine->has_opp = (err == 0);
if (!engine->has_opp)
dev_info(&pdev->dev, "ICE OPP table is not registered, please update your DT\n");

/*
* Store the core clock rate for suspend resume cycles,
* against OPP aware DVFS operations. core_clk_freq will
* have a valid value only for non-legacy bindings.
*/
engine->core_clk_freq = clk_get_rate(engine->core_clk);

platform_set_drvdata(pdev, engine);

return 0;
Expand Down
22 changes: 21 additions & 1 deletion drivers/ufs/host/ufs-qcom.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,15 @@ static int ufs_qcom_ice_prepare_key(struct blk_crypto_profile *profile,
return qcom_ice_prepare_key(host->ice, lt_key, lt_key_size, eph_key);
}

static int ufs_qcom_ice_scale_clk(struct ufs_qcom_host *host, unsigned long target_freq,
bool round_ceil)
{
if (host->hba->caps & UFSHCD_CAP_CRYPTO)
return qcom_ice_scale_clk(host->ice, target_freq, round_ceil);

return 0;
}

static const struct blk_crypto_ll_ops ufs_qcom_crypto_ops = {
.keyslot_program = ufs_qcom_ice_keyslot_program,
.keyslot_evict = ufs_qcom_ice_keyslot_evict,
Expand Down Expand Up @@ -340,6 +349,12 @@ static void ufs_qcom_config_ice_allocator(struct ufs_qcom_host *host)
{
}

static int ufs_qcom_ice_scale_clk(struct ufs_qcom_host *host, unsigned long target_freq,
bool round_ceil)
{
return 0;
}

#endif

static void ufs_qcom_disable_lane_clks(struct ufs_qcom_host *host)
Expand Down Expand Up @@ -1743,12 +1758,17 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba, bool scale_up,
else
err = ufs_qcom_clk_scale_down_post_change(hba, target_freq);


if (err) {
ufshcd_uic_hibern8_exit(hba);
return err;
}

err = ufs_qcom_ice_scale_clk(host, target_freq, !scale_up);
if (err && err != -EOPNOTSUPP) {
ufshcd_uic_hibern8_exit(hba);
return err;
}

ufs_qcom_icc_update_bw(host);
ufshcd_uic_hibern8_exit(hba);
}
Expand Down
2 changes: 2 additions & 0 deletions include/soc/qcom/ice.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@ int qcom_ice_import_key(struct qcom_ice *ice,
const u8 *raw_key, size_t raw_key_size,
u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE]);
struct qcom_ice *devm_of_qcom_ice_get(struct device *dev);
int qcom_ice_scale_clk(struct qcom_ice *ice, unsigned long target_freq,
bool round_ceil);

#endif /* __QCOM_ICE_H__ */