Skip to content
Open
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
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 = <&sdhc_ice_opp_table>;

sdhc_ice_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_svs_l1>;
};
};
};

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
37 changes: 37 additions & 0 deletions arch/arm64/boot/dts/qcom/monaco.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -2742,6 +2742,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_svs_l1>;
};

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 @@ -4877,6 +4898,22 @@
clock-names = "core",
"iface";
power-domains = <&rpmhpd RPMHPD_CX>;

operating-points-v2 = <&sdhc_ice_opp_table>;

sdhc_ice_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
22 changes: 22 additions & 0 deletions drivers/mmc/host/sdhci-msm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1902,6 +1902,16 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)

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)
{
if (msm_host->mmc->caps2 & MMC_CAP2_CRYPTO)
return qcom_ice_scale_clk(msm_host->ice, target_freq, round_ceil);

return 0;
}

static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
struct cqhci_host *cq_host)
{
Expand Down Expand Up @@ -1960,6 +1970,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, ULONG_MAX, false);
if (err && err != -EOPNOTSUPP)
dev_warn(dev, "Unable to boost ICE clock to TURBO\n");

return 0;
}

Expand Down Expand Up @@ -2150,6 +2165,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
75 changes: 75 additions & 0 deletions drivers/soc/qcom/ice.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/xarray.h>
#include <linux/pm_opp.h>

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

Expand Down Expand Up @@ -113,6 +114,7 @@ struct qcom_ice {
bool use_hwkm;
bool hwkm_init_complete;
u8 hwkm_version;
bool has_opp;
};

static DEFINE_XARRAY(ice_handles);
Expand Down Expand Up @@ -560,6 +562,50 @@ 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.
*
* Return: 0 on success; -EOPNOTSUPP if no OPP table; or errno 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;
}

return 0;
}
EXPORT_SYMBOL_GPL(qcom_ice_scale_clk);

static struct qcom_ice *qcom_ice_create(struct device *dev,
void __iomem *base)
{
Expand Down Expand Up @@ -738,6 +784,7 @@ static int qcom_ice_probe(struct platform_device *pdev)
unsigned long phandle = pdev->dev.of_node->phandle;
struct qcom_ice *engine;
void __iomem *base;
int err;

guard(mutex)(&ice_mutex);

Expand All @@ -756,6 +803,34 @@ static int qcom_ice_probe(struct platform_device *pdev)
return PTR_ERR(engine);
}

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");
/* Store the error pointer for devm_of_qcom_ice_get() */
xa_store(&ice_handles, phandle, ERR_PTR(err), GFP_KERNEL);
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");
/* Store the error pointer for devm_of_qcom_ice_get() */
xa_store(&ice_handles, phandle, ERR_PTR(err), GFP_KERNEL);
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 err is not -ENODEV.
*/
if (err == -ENODEV)
dev_dbg(&pdev->dev, "ICE OPP table is not registered, please update your DT\n");
else
engine->has_opp = true;

xa_store(&ice_handles, phandle, engine, GFP_KERNEL);

return 0;
Expand Down
21 changes: 21 additions & 0 deletions 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 @@ -1946,6 +1961,12 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba, bool scale_up,
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__ */
Loading