aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/power/qcom,rpmpd.yaml3
-rw-r--r--drivers/soc/qcom/Kconfig4
-rw-r--r--drivers/soc/qcom/cmd-db.c8
-rw-r--r--drivers/soc/qcom/llcc-qcom.c115
-rw-r--r--drivers/soc/qcom/rpmh-rsc.c7
-rw-r--r--drivers/soc/qcom/rpmpd.c85
-rw-r--r--drivers/soc/qcom/smp2p.c5
-rw-r--r--include/dt-bindings/power/qcom-rpmpd.h29
8 files changed, 208 insertions, 48 deletions
diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
index 8058955fb3b9..e07453417f45 100644
--- a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
+++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
@@ -16,10 +16,13 @@ description:
properties:
compatible:
enum:
+ - qcom,msm8916-rpmpd
+ - qcom,msm8939-rpmpd
- qcom,msm8976-rpmpd
- qcom,msm8996-rpmpd
- qcom,msm8998-rpmpd
- qcom,qcs404-rpmpd
+ - qcom,sdm660-rpmpd
- qcom,sc7180-rpmhpd
- qcom,sdm845-rpmhpd
- qcom,sm8150-rpmhpd
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 6a3b69b43ad5..9b4ae9c16ba7 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -17,7 +17,7 @@ config QCOM_AOSS_QMP
Subsystem (AOSS) using Qualcomm Messaging Protocol (QMP).
config QCOM_COMMAND_DB
- bool "Qualcomm Command DB"
+ tristate "Qualcomm Command DB"
depends on ARCH_QCOM || COMPILE_TEST
depends on OF_RESERVED_MEM
help
@@ -108,7 +108,7 @@ config QCOM_RMTFS_MEM
Say y here if you intend to boot the modem remoteproc.
config QCOM_RPMH
- bool "Qualcomm RPM-Hardened (RPMH) Communication"
+ tristate "Qualcomm RPM-Hardened (RPMH) Communication"
depends on ARCH_QCOM || COMPILE_TEST
help
Support for communication with the hardened-RPM blocks in
diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index fc5610603b17..dd872017f345 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -1,8 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. */
+/* Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved. */
#include <linux/debugfs.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_reserved_mem.h>
@@ -340,12 +341,14 @@ static const struct of_device_id cmd_db_match_table[] = {
{ .compatible = "qcom,cmd-db" },
{ }
};
+MODULE_DEVICE_TABLE(of, cmd_db_match_table);
static struct platform_driver cmd_db_dev_driver = {
.probe = cmd_db_dev_probe,
.driver = {
.name = "cmd-db",
.of_match_table = cmd_db_match_table,
+ .suppress_bind_attrs = true,
},
};
@@ -354,3 +357,6 @@ static int __init cmd_db_device_init(void)
return platform_driver_register(&cmd_db_dev_driver);
}
arch_initcall(cmd_db_device_init);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Command DB Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
index 70fbe70c6213..40e7df1e1cbb 100644
--- a/drivers/soc/qcom/llcc-qcom.c
+++ b/drivers/soc/qcom/llcc-qcom.c
@@ -45,6 +45,9 @@
#define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + SZ_8 * n)
#define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + SZ_8 * n)
+#define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00
+#define LLCC_TRP_PCB_ACT 0x21f04
+
#define BANK_OFFSET_STRIDE 0x80000
/**
@@ -89,6 +92,7 @@ struct llcc_slice_config {
struct qcom_llcc_config {
const struct llcc_slice_config *sct_data;
int size;
+ bool need_llcc_cfg;
};
static const struct llcc_slice_config sc7180_data[] = {
@@ -122,11 +126,13 @@ static const struct llcc_slice_config sdm845_data[] = {
static const struct qcom_llcc_config sc7180_cfg = {
.sct_data = sc7180_data,
.size = ARRAY_SIZE(sc7180_data),
+ .need_llcc_cfg = true,
};
static const struct qcom_llcc_config sdm845_cfg = {
.sct_data = sdm845_data,
.size = ARRAY_SIZE(sdm845_data),
+ .need_llcc_cfg = false,
};
static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
@@ -318,62 +324,91 @@ size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
}
EXPORT_SYMBOL_GPL(llcc_get_slice_size);
-static int qcom_llcc_cfg_program(struct platform_device *pdev)
+static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config,
+ const struct qcom_llcc_config *cfg)
{
- int i;
+ int ret;
u32 attr1_cfg;
u32 attr0_cfg;
u32 attr1_val;
u32 attr0_val;
u32 max_cap_cacheline;
+ struct llcc_slice_desc desc;
+
+ attr1_val = config->cache_mode;
+ attr1_val |= config->probe_target_ways << ATTR1_PROBE_TARGET_WAYS_SHIFT;
+ attr1_val |= config->fixed_size << ATTR1_FIXED_SIZE_SHIFT;
+ attr1_val |= config->priority << ATTR1_PRIORITY_SHIFT;
+
+ max_cap_cacheline = MAX_CAP_TO_BYTES(config->max_cap);
+
+ /*
+ * LLCC instances can vary for each target.
+ * The SW writes to broadcast register which gets propagated
+ * to each llcc instance (llcc0,.. llccN).
+ * Since the size of the memory is divided equally amongst the
+ * llcc instances, we need to configure the max cap accordingly.
+ */
+ max_cap_cacheline = max_cap_cacheline / drv_data->num_banks;
+ max_cap_cacheline >>= CACHE_LINE_SIZE_SHIFT;
+ attr1_val |= max_cap_cacheline << ATTR1_MAX_CAP_SHIFT;
+
+ attr1_cfg = LLCC_TRP_ATTR1_CFGn(config->slice_id);
+
+ ret = regmap_write(drv_data->bcast_regmap, attr1_cfg, attr1_val);
+ if (ret)
+ return ret;
+
+ attr0_val = config->res_ways & ATTR0_RES_WAYS_MASK;
+ attr0_val |= config->bonus_ways << ATTR0_BONUS_WAYS_SHIFT;
+
+ attr0_cfg = LLCC_TRP_ATTR0_CFGn(config->slice_id);
+
+ ret = regmap_write(drv_data->bcast_regmap, attr0_cfg, attr0_val);
+ if (ret)
+ return ret;
+
+ if (cfg->need_llcc_cfg) {
+ u32 disable_cap_alloc, retain_pc;
+
+ disable_cap_alloc = config->dis_cap_alloc << config->slice_id;
+ ret = regmap_write(drv_data->bcast_regmap,
+ LLCC_TRP_SCID_DIS_CAP_ALLOC, disable_cap_alloc);
+ if (ret)
+ return ret;
+
+ retain_pc = config->retain_on_pc << config->slice_id;
+ ret = regmap_write(drv_data->bcast_regmap,
+ LLCC_TRP_PCB_ACT, retain_pc);
+ if (ret)
+ return ret;
+ }
+
+ if (config->activate_on_init) {
+ desc.slice_id = config->slice_id;
+ ret = llcc_slice_activate(&desc);
+ }
+
+ return ret;
+}
+
+static int qcom_llcc_cfg_program(struct platform_device *pdev,
+ const struct qcom_llcc_config *cfg)
+{
+ int i;
u32 sz;
int ret = 0;
const struct llcc_slice_config *llcc_table;
- struct llcc_slice_desc desc;
sz = drv_data->cfg_size;
llcc_table = drv_data->cfg;
for (i = 0; i < sz; i++) {
- attr1_cfg = LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
- attr0_cfg = LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
-
- attr1_val = llcc_table[i].cache_mode;
- attr1_val |= llcc_table[i].probe_target_ways <<
- ATTR1_PROBE_TARGET_WAYS_SHIFT;
- attr1_val |= llcc_table[i].fixed_size <<
- ATTR1_FIXED_SIZE_SHIFT;
- attr1_val |= llcc_table[i].priority <<
- ATTR1_PRIORITY_SHIFT;
-
- max_cap_cacheline = MAX_CAP_TO_BYTES(llcc_table[i].max_cap);
-
- /* LLCC instances can vary for each target.
- * The SW writes to broadcast register which gets propagated
- * to each llcc instace (llcc0,.. llccN).
- * Since the size of the memory is divided equally amongst the
- * llcc instances, we need to configure the max cap accordingly.
- */
- max_cap_cacheline = max_cap_cacheline / drv_data->num_banks;
- max_cap_cacheline >>= CACHE_LINE_SIZE_SHIFT;
- attr1_val |= max_cap_cacheline << ATTR1_MAX_CAP_SHIFT;
-
- attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK;
- attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT;
-
- ret = regmap_write(drv_data->bcast_regmap, attr1_cfg,
- attr1_val);
- if (ret)
- return ret;
- ret = regmap_write(drv_data->bcast_regmap, attr0_cfg,
- attr0_val);
+ ret = _qcom_llcc_cfg_program(&llcc_table[i], cfg);
if (ret)
return ret;
- if (llcc_table[i].activate_on_init) {
- desc.slice_id = llcc_table[i].slice_id;
- ret = llcc_slice_activate(&desc);
- }
}
+
return ret;
}
@@ -472,7 +507,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
mutex_init(&drv_data->lock);
platform_set_drvdata(pdev, drv_data);
- ret = qcom_llcc_cfg_program(pdev);
+ ret = qcom_llcc_cfg_program(pdev, cfg);
if (ret)
goto err;
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index a297911afe57..37969dcbaf14 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -13,6 +13,7 @@
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/list.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
@@ -497,7 +498,7 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id,
write_tcs_cmd(drv, RSC_DRV_CMD_MSGID, tcs_id, j, msgid);
write_tcs_cmd(drv, RSC_DRV_CMD_ADDR, tcs_id, j, cmd->addr);
write_tcs_cmd(drv, RSC_DRV_CMD_DATA, tcs_id, j, cmd->data);
- trace_rpmh_send_msg_rcuidle(drv, tcs_id, j, msgid, cmd);
+ trace_rpmh_send_msg(drv, tcs_id, j, msgid, cmd);
}
write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, cmd_complete);
@@ -1018,6 +1019,7 @@ static const struct of_device_id rpmh_drv_match[] = {
{ .compatible = "qcom,rpmh-rsc", },
{ }
};
+MODULE_DEVICE_TABLE(of, rpmh_drv_match);
static struct platform_driver rpmh_driver = {
.probe = rpmh_rsc_probe,
@@ -1033,3 +1035,6 @@ static int __init rpmh_driver_init(void)
return platform_driver_register(&rpmh_driver);
}
arch_initcall(rpmh_driver_init);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPMh Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
index f2168e4259b2..85d1207b72d7 100644
--- a/drivers/soc/qcom/rpmpd.c
+++ b/drivers/soc/qcom/rpmpd.c
@@ -35,7 +35,7 @@
#define KEY_FLOOR_LEVEL 0x6c6676 /* vfl */
#define KEY_LEVEL 0x6c766c76 /* vlvl */
-#define MAX_8996_RPMPD_STATE 6
+#define MAX_CORNER_RPMPD_STATE 6
#define DEFINE_RPMPD_PAIR(_platform, _name, _active, r_type, r_key, \
r_id) \
@@ -116,6 +116,52 @@ struct rpmpd_desc {
static DEFINE_MUTEX(rpmpd_lock);
+/* msm8939 RPM Power Domains */
+DEFINE_RPMPD_PAIR(msm8939, vddmd, vddmd_ao, SMPA, CORNER, 1);
+DEFINE_RPMPD_VFC(msm8939, vddmd_vfc, SMPA, 1);
+
+DEFINE_RPMPD_PAIR(msm8939, vddcx, vddcx_ao, SMPA, CORNER, 2);
+DEFINE_RPMPD_VFC(msm8939, vddcx_vfc, SMPA, 2);
+
+DEFINE_RPMPD_PAIR(msm8939, vddmx, vddmx_ao, LDOA, CORNER, 3);
+
+static struct rpmpd *msm8939_rpmpds[] = {
+ [MSM8939_VDDMDCX] = &msm8939_vddmd,
+ [MSM8939_VDDMDCX_AO] = &msm8939_vddmd_ao,
+ [MSM8939_VDDMDCX_VFC] = &msm8939_vddmd_vfc,
+ [MSM8939_VDDCX] = &msm8939_vddcx,
+ [MSM8939_VDDCX_AO] = &msm8939_vddcx_ao,
+ [MSM8939_VDDCX_VFC] = &msm8939_vddcx_vfc,
+ [MSM8939_VDDMX] = &msm8939_vddmx,
+ [MSM8939_VDDMX_AO] = &msm8939_vddmx_ao,
+};
+
+static const struct rpmpd_desc msm8939_desc = {
+ .rpmpds = msm8939_rpmpds,
+ .num_pds = ARRAY_SIZE(msm8939_rpmpds),
+ .max_state = MAX_CORNER_RPMPD_STATE,
+};
+
+/* msm8916 RPM Power Domains */
+DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
+DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
+
+DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
+
+static struct rpmpd *msm8916_rpmpds[] = {
+ [MSM8916_VDDCX] = &msm8916_vddcx,
+ [MSM8916_VDDCX_AO] = &msm8916_vddcx_ao,
+ [MSM8916_VDDCX_VFC] = &msm8916_vddcx_vfc,
+ [MSM8916_VDDMX] = &msm8916_vddmx,
+ [MSM8916_VDDMX_AO] = &msm8916_vddmx_ao,
+};
+
+static const struct rpmpd_desc msm8916_desc = {
+ .rpmpds = msm8916_rpmpds,
+ .num_pds = ARRAY_SIZE(msm8916_rpmpds),
+ .max_state = MAX_CORNER_RPMPD_STATE,
+};
+
/* msm8976 RPM Power Domains */
DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
@@ -159,7 +205,7 @@ static struct rpmpd *msm8996_rpmpds[] = {
static const struct rpmpd_desc msm8996_desc = {
.rpmpds = msm8996_rpmpds,
.num_pds = ARRAY_SIZE(msm8996_rpmpds),
- .max_state = MAX_8996_RPMPD_STATE,
+ .max_state = MAX_CORNER_RPMPD_STATE,
};
/* msm8998 RPM Power domains */
@@ -220,11 +266,46 @@ static const struct rpmpd_desc qcs404_desc = {
.max_state = RPM_SMD_LEVEL_BINNING,
};
+/* sdm660 RPM Power domains */
+DEFINE_RPMPD_PAIR(sdm660, vddcx, vddcx_ao, RWCX, LEVEL, 0);
+DEFINE_RPMPD_VFL(sdm660, vddcx_vfl, RWCX, 0);
+
+DEFINE_RPMPD_PAIR(sdm660, vddmx, vddmx_ao, RWMX, LEVEL, 0);
+DEFINE_RPMPD_VFL(sdm660, vddmx_vfl, RWMX, 0);
+
+DEFINE_RPMPD_LEVEL(sdm660, vdd_ssccx, RWLC, 0);
+DEFINE_RPMPD_VFL(sdm660, vdd_ssccx_vfl, RWLC, 0);
+
+DEFINE_RPMPD_LEVEL(sdm660, vdd_sscmx, RWLM, 0);
+DEFINE_RPMPD_VFL(sdm660, vdd_sscmx_vfl, RWLM, 0);
+
+static struct rpmpd *sdm660_rpmpds[] = {
+ [SDM660_VDDCX] = &sdm660_vddcx,
+ [SDM660_VDDCX_AO] = &sdm660_vddcx_ao,
+ [SDM660_VDDCX_VFL] = &sdm660_vddcx_vfl,
+ [SDM660_VDDMX] = &sdm660_vddmx,
+ [SDM660_VDDMX_AO] = &sdm660_vddmx_ao,
+ [SDM660_VDDMX_VFL] = &sdm660_vddmx_vfl,
+ [SDM660_SSCCX] = &sdm660_vdd_ssccx,
+ [SDM660_SSCCX_VFL] = &sdm660_vdd_ssccx_vfl,
+ [SDM660_SSCMX] = &sdm660_vdd_sscmx,
+ [SDM660_SSCMX_VFL] = &sdm660_vdd_sscmx_vfl,
+};
+
+static const struct rpmpd_desc sdm660_desc = {
+ .rpmpds = sdm660_rpmpds,
+ .num_pds = ARRAY_SIZE(sdm660_rpmpds),
+ .max_state = RPM_SMD_LEVEL_TURBO,
+};
+
static const struct of_device_id rpmpd_match_table[] = {
+ { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
+ { .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc },
{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
{ .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
+ { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
{ }
};
MODULE_DEVICE_TABLE(of, rpmpd_match_table);
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index 07183d731d74..a9709aae54ab 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -318,15 +318,16 @@ static int qcom_smp2p_inbound_entry(struct qcom_smp2p *smp2p,
static int smp2p_update_bits(void *data, u32 mask, u32 value)
{
struct smp2p_entry *entry = data;
+ unsigned long flags;
u32 orig;
u32 val;
- spin_lock(&entry->lock);
+ spin_lock_irqsave(&entry->lock, flags);
val = orig = readl(entry->value);
val &= ~mask;
val |= value;
writel(val, entry->value);
- spin_unlock(&entry->lock);
+ spin_unlock_irqrestore(&entry->lock, flags);
if (val != orig)
qcom_smp2p_kick(entry->smp2p);
diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
index 5e61eaf73bdd..973329c62509 100644
--- a/include/dt-bindings/power/qcom-rpmpd.h
+++ b/include/dt-bindings/power/qcom-rpmpd.h
@@ -64,6 +64,23 @@
#define RPMH_REGULATOR_LEVEL_TURBO 384
#define RPMH_REGULATOR_LEVEL_TURBO_L1 416
+/* MSM8939 Power Domains */
+#define MSM8939_VDDMDCX 0
+#define MSM8939_VDDMDCX_AO 1
+#define MSM8939_VDDMDCX_VFC 2
+#define MSM8939_VDDCX 3
+#define MSM8939_VDDCX_AO 4
+#define MSM8939_VDDCX_VFC 5
+#define MSM8939_VDDMX 6
+#define MSM8939_VDDMX_AO 7
+
+/* MSM8916 Power Domain Indexes */
+#define MSM8916_VDDCX 0
+#define MSM8916_VDDCX_AO 1
+#define MSM8916_VDDCX_VFC 2
+#define MSM8916_VDDMX 3
+#define MSM8916_VDDMX_AO 4
+
/* MSM8976 Power Domain Indexes */
#define MSM8976_VDDCX 0
#define MSM8976_VDDCX_AO 1
@@ -102,6 +119,18 @@
#define QCS404_LPIMX 5
#define QCS404_LPIMX_VFL 6
+/* SDM660 Power Domains */
+#define SDM660_VDDCX 0
+#define SDM660_VDDCX_AO 1
+#define SDM660_VDDCX_VFL 2
+#define SDM660_VDDMX 3
+#define SDM660_VDDMX_AO 4
+#define SDM660_VDDMX_VFL 5
+#define SDM660_SSCCX 6
+#define SDM660_SSCCX_VFL 7
+#define SDM660_SSCMX 8
+#define SDM660_SSCMX_VFL 9
+
/* RPM SMD Power Domain performance levels */
#define RPM_SMD_LEVEL_RETENTION 16
#define RPM_SMD_LEVEL_RETENTION_PLUS 32