2018-06-27 05:15:47

by Rajendra Nayak

[permalink] [raw]
Subject: [PATCH v4 0/6] Add power domain driver for corners on msm8996/sdm845

Changes in v4:
* Included the patch to add qcom-opp bindings (dropped accidentally in v3)
* merged the patches to add bindings for rpm and rpmh, added consumer binding example
* Made the drivers built in, removed .remove
* Added better description in changelog for PATCH 6/6
* Updated rpmhpd_aggregate_corner() based on Davids feedback
* rpmhpd_set_performance_state() returns max corner, in cases where its called
with an INT_MAX
* Dropped the patch to max vote on all corners at init, the patch did not
work anyway, and it shouldn't be needed now

Changes in v3:
* Bindings split into seperate patches
* Bindings updated to remove duplicate OPP table phandles
* DT headers defining macros for Power domain indexes and OPP levels
* Optimisations to use rpmh_write_async() whereever applicable
* Fixed up handling of ACTIVE_ONLY/WAKE_ONLY/SLEEP voting for RPMh
* Fixed the vlvl to hlvl conversions in set_performance
* Other minor fixes based on review of v2
* TODO: This series does not handle the case where all VDD_MX votes
should be higher than VDD_CX from APPs, as pointed out
by David Collins in v2. This needs support at genpd to propogate performance
state up the parents, if we model these as Parent/Child to handle the
interdependency.

Changes in v2:
* added a power domain driver for sdm845 which supports communicating to RPMh
* dropped the changes to sdhc driver to move over to using OPP
as there is active discussion on using OPP as the interface vs
handling all of it in clock drivers
* Other minor binding updates based on review of v1

With performance state support for genpd/OPP merged, this is an effort
to model a power domain driver to communicate corner/level
values for qualcomm platforms to RPM (Remote Power Manager) and RPMh.

Rajendra Nayak (6):
dt-bindings: opp: Introduce qcom-opp bindings
dt-bindings: power: Add qcom rpm power domain driver bindings
soc: qcom: rpmpd: Add a Power domain driver to model corners
soc: qcom: rpmpd: Add support for get/set performance state
arm64: dts: msm8996: Add rpmpd device node
soc: qcom: rpmhpd: Add RPMh Power domain driver

.../devicetree/bindings/opp/qcom-opp.txt | 25 ++
.../devicetree/bindings/power/qcom,rpmpd.txt | 146 +++++++
arch/arm64/boot/dts/qcom/msm8996.dtsi | 34 ++
drivers/soc/qcom/Kconfig | 18 +
drivers/soc/qcom/Makefile | 2 +
drivers/soc/qcom/rpmhpd.c | 406 ++++++++++++++++++
drivers/soc/qcom/rpmpd.c | 340 +++++++++++++++
include/dt-bindings/power/qcom-rpmpd.h | 39 ++
8 files changed, 1010 insertions(+)
create mode 100644 Documentation/devicetree/bindings/opp/qcom-opp.txt
create mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.txt
create mode 100644 drivers/soc/qcom/rpmhpd.c
create mode 100644 drivers/soc/qcom/rpmpd.c
create mode 100644 include/dt-bindings/power/qcom-rpmpd.h

--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



2018-06-27 05:12:03

by Rajendra Nayak

[permalink] [raw]
Subject: [PATCH v4 6/6] soc: qcom: rpmhpd: Add RPMh Power domain driver

The RPMh Power domain driver aggregates the corner votes from various
consumers for the ARC resources and communicates it to RPMh.

With RPMh we use 2 different numbering space for corners, one used
by the clients to express their performance needs, and another used
to communicate to RPMh hardware.

The clients express their performance requirements using a sparse
numbering space which are mapped to meaningful levels like RET, SVS,
NOMINAL, TURBO etc which then get mapped to another number space
between 0 and 15 which is communicated to RPMh. The sparse number space,
also referred to as vlvl is mapped to the continuous number space of 0
to 15, also referred to as hlvl, using command DB.

Some power domain clients could request a performance state only while
the CPU is active, while some others could request for a certain
performance state all the time regardless of the state of the CPU.
We handle this by internally aggregating the votes from both type of
clients and then send the aggregated votes to RPMh.

There are also 3 different types of Votes that are comunicated to RPMh
for every resource.
1. ACTIVE_ONLY: This specifies the requirement for the resource when the
CPU is active
2. SLEEP: This specifies the requirement for the resource when the CPU
is going to sleep
3. WAKE_ONLY: This specifies the requirement for the resource when the
CPU is coming out of sleep to active state

We add data for all power domains on sdm845 SoC as part of the patch.
The driver can be extended to support other SoCs which support RPMh

Signed-off-by: Rajendra Nayak <[email protected]>
Reviewed-by: Ulf Hansson <[email protected]>
---
drivers/soc/qcom/Kconfig | 9 +
drivers/soc/qcom/Makefile | 1 +
drivers/soc/qcom/rpmhpd.c | 406 ++++++++++++++++++++++++++++++++++++++
3 files changed, 416 insertions(+)
create mode 100644 drivers/soc/qcom/rpmhpd.c

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 131da9d34a40..3cb6085a851d 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -74,6 +74,15 @@ config QCOM_RMTFS_MEM

Say y here if you intend to boot the modem remoteproc.

+config QCOM_RPMHPD
+ bool "Qualcomm RPMh Power domain driver"
+ depends on QCOM_RPMH && QCOM_COMMAND_DB
+ help
+ QCOM RPMh Power domain driver to support power-domains with
+ performance states. The driver communicates a performance state
+ value to RPMh which then translates it into corresponding voltage
+ for the voltage rail.
+
config QCOM_RPMPD
bool "Qualcomm RPM Power domain driver"
depends on MFD_QCOM_RPM && QCOM_SMD_RPM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 9550c170de93..499513f63bef 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_QCOM_SMSM) += smsm.o
obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
obj-$(CONFIG_QCOM_APR) += apr.o
obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
+obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c
new file mode 100644
index 000000000000..a364fa5aac57
--- /dev/null
+++ b/drivers/soc/qcom/rpmhpd.c
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.*/
+
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <soc/qcom/cmd-db.h>
+#include <soc/qcom/rpmh.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+#define domain_to_rpmhpd(domain) container_of(domain, struct rpmhpd, pd)
+
+#define DEFINE_RPMHPD_AO(_platform, _name, _active) \
+ static struct rpmhpd _platform##_##_active; \
+ static struct rpmhpd _platform##_##_name = { \
+ .pd = { .name = #_name, }, \
+ .peer = &_platform##_##_active, \
+ .res_name = #_name".lvl", \
+ }; \
+ static struct rpmhpd _platform##_##_active = { \
+ .pd = { .name = #_active, }, \
+ .peer = &_platform##_##_name, \
+ .active_only = true, \
+ .res_name = #_name".lvl", \
+ }
+
+#define DEFINE_RPMHPD(_platform, _name) \
+ static struct rpmhpd _platform##_##_name = { \
+ .pd = { .name = #_name, }, \
+ .res_name = #_name".lvl", \
+ }
+
+/*
+ * This is the number of bytes used for each command DB aux data entry of an
+ * ARC resource.
+ */
+#define RPMH_ARC_LEVEL_SIZE 2
+#define RPMH_ARC_MAX_LEVELS 16
+
+/**
+ * struct rpmhpd - top level RPMh power domain resource data structure
+ * @dev: rpmh power domain controller device
+ * @pd: generic_pm_domain corrresponding to the power domain
+ * @peer: A peer power domain in case Active only Voting is supported
+ * @active_only: True if it represents an Active only peer
+ * @level: An array of level (vlvl) to corner (hlvl) mappings derived from cmd-db
+ * @level_count: Number of levels supported by the power domain. max being 16 (0 - 15)
+ * @enabled: true if the power domain is enabled
+ * @res_name: Resource name used for cmd-db lookup
+ * @addr: Resource address as looped up using resource name from cmd-db
+ */
+struct rpmhpd {
+ struct device *dev;
+ struct generic_pm_domain pd;
+ struct rpmhpd *peer;
+ const bool active_only;
+ unsigned int corner;
+ unsigned int active_corner;
+ u32 level[RPMH_ARC_MAX_LEVELS];
+ int level_count;
+ bool enabled;
+ const char *res_name;
+ u32 addr;
+};
+
+struct rpmhpd_desc {
+ struct rpmhpd **rpmhpds;
+ size_t num_pds;
+};
+
+static DEFINE_MUTEX(rpmhpd_lock);
+
+/* sdm845 RPMh Power domains */
+DEFINE_RPMHPD(sdm845, ebi);
+DEFINE_RPMHPD_AO(sdm845, mx, mx_ao);
+DEFINE_RPMHPD_AO(sdm845, cx, cx_ao);
+DEFINE_RPMHPD(sdm845, lmx);
+DEFINE_RPMHPD(sdm845, lcx);
+DEFINE_RPMHPD(sdm845, gfx);
+DEFINE_RPMHPD(sdm845, mss);
+
+static struct rpmhpd *sdm845_rpmhpds[] = {
+ [SDM845_EBI] = &sdm845_ebi,
+ [SDM845_MX] = &sdm845_mx,
+ [SDM845_MX_AO] = &sdm845_mx_ao,
+ [SDM845_CX] = &sdm845_cx,
+ [SDM845_CX_AO] = &sdm845_cx_ao,
+ [SDM845_LMX] = &sdm845_lmx,
+ [SDM845_LCX] = &sdm845_lcx,
+ [SDM845_GFX] = &sdm845_gfx,
+ [SDM845_MSS] = &sdm845_mss,
+};
+
+static const struct rpmhpd_desc sdm845_desc = {
+ .rpmhpds = sdm845_rpmhpds,
+ .num_pds = ARRAY_SIZE(sdm845_rpmhpds),
+};
+
+static const struct of_device_id rpmhpd_match_table[] = {
+ { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rpmhpd_match_table);
+
+static int rpmhpd_send_corner(struct rpmhpd *pd, int state,
+ unsigned int corner, bool sync)
+{
+ struct tcs_cmd cmd = {
+ .addr = pd->addr,
+ .data = corner,
+ };
+
+ /*
+ * Wait for an ack only when we are increasing the
+ * perf state of the power domain
+ */
+ if (sync)
+ return rpmh_write(pd->dev, state, &cmd, 1);
+ else
+ return rpmh_write_async(pd->dev, state, &cmd, 1);
+}
+
+static void to_active_sleep(struct rpmhpd *pd, unsigned int corner,
+ unsigned int *active, unsigned int *sleep)
+{
+ *active = corner;
+
+ if (pd->active_only)
+ *sleep = 0;
+ else
+ *sleep = *active;
+}
+
+/*
+ * This function is used to aggregate the votes across the active only
+ * resources and its peers. The aggregated votes are sent to RPMh as
+ * ACTIVE_ONLY votes (which take effect immediately), as WAKE_ONLY votes
+ * (applied by RPMh on system wakeup) and as SLEEP votes (applied by RPMh
+ * on system sleep).
+ * We send ACTIVE_ONLY votes for resources without any peers. For others,
+ * which have an active only peer, all 3 votes are sent.
+ */
+static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner)
+{
+ int ret;
+ struct rpmhpd *peer = pd->peer;
+ unsigned int active_corner, sleep_corner;
+ unsigned int this_active_corner = 0, this_sleep_corner = 0;
+ unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
+
+ to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner);
+
+ if (peer && peer->enabled)
+ to_active_sleep(peer, peer->corner, &peer_active_corner,
+ &peer_sleep_corner);
+
+ active_corner = max(this_active_corner, peer_active_corner);
+
+ ret = rpmhpd_send_corner(pd, RPMH_ACTIVE_ONLY_STATE, active_corner,
+ active_corner > pd->active_corner);
+ if (ret)
+ return ret;
+
+ pd->active_corner = active_corner;
+
+ if (peer) {
+ peer->active_corner = active_corner;
+
+ ret = rpmhpd_send_corner(pd, RPMH_WAKE_ONLY_STATE,
+ active_corner, false);
+ if (ret)
+ return ret;
+
+ sleep_corner = max(this_sleep_corner, peer_sleep_corner);
+
+ return rpmhpd_send_corner(pd, RPMH_SLEEP_STATE, sleep_corner,
+ false);
+ }
+
+ return ret;
+}
+
+static int rpmhpd_power_on(struct generic_pm_domain *domain)
+{
+ struct rpmhpd *pd = domain_to_rpmhpd(domain);
+ int ret = 0;
+
+ mutex_lock(&rpmhpd_lock);
+
+ if (pd->corner)
+ ret = rpmhpd_aggregate_corner(pd, pd->corner);
+
+ if (!ret)
+ pd->enabled = true;
+
+ mutex_unlock(&rpmhpd_lock);
+
+ return ret;
+}
+
+static int rpmhpd_power_off(struct generic_pm_domain *domain)
+{
+ struct rpmhpd *pd = domain_to_rpmhpd(domain);
+ int ret = 0;
+
+ mutex_lock(&rpmhpd_lock);
+
+ ret = rpmhpd_aggregate_corner(pd, pd->level[0]);
+
+ if (!ret)
+ pd->enabled = false;
+
+ mutex_unlock(&rpmhpd_lock);
+
+ return ret;
+}
+
+static int rpmhpd_set_performance_state(struct generic_pm_domain *domain,
+ unsigned int level)
+{
+ struct rpmhpd *pd = domain_to_rpmhpd(domain);
+ int ret = 0, i;
+
+ mutex_lock(&rpmhpd_lock);
+
+ for (i = 0; i < pd->level_count; i++)
+ if (level <= pd->level[i])
+ break;
+
+ /*
+ * If the level requested is more than that supported by the
+ * max corner, just set it to max anyway.
+ */
+ if (i == pd->level_count)
+ i--;
+
+ if (pd->enabled) {
+ ret = rpmhpd_aggregate_corner(pd, i);
+ if (ret)
+ goto out;
+ }
+
+ pd->corner = i;
+out:
+ mutex_unlock(&rpmhpd_lock);
+
+ return ret;
+}
+
+static unsigned int rpmhpd_get_performance_state(struct generic_pm_domain *genpd,
+ struct dev_pm_opp *opp)
+{
+ struct device_node *np;
+ unsigned int level = 0;
+
+ np = dev_pm_opp_get_of_node(opp);
+ if (of_property_read_u32(np, "qcom,level", &level)) {
+ pr_err("%s: missing 'qcom,level' property\n", __func__);
+ return 0;
+ }
+
+ of_node_put(np);
+
+ return level;
+}
+
+static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd)
+{
+ u8 buf[RPMH_ARC_MAX_LEVELS * RPMH_ARC_LEVEL_SIZE];
+ int i, j, len, ret;
+
+ len = cmd_db_read_aux_data_len(rpmhpd->res_name);
+ if (len <= 0)
+ return len;
+ else if (len > RPMH_ARC_MAX_LEVELS * RPMH_ARC_LEVEL_SIZE)
+ return -EINVAL;
+
+ ret = cmd_db_read_aux_data(rpmhpd->res_name, buf, len);
+ if (ret < 0)
+ return ret;
+
+ rpmhpd->level_count = len / RPMH_ARC_LEVEL_SIZE;
+
+ for (i = 0; i < rpmhpd->level_count; i++) {
+ rpmhpd->level[i] = 0;
+ for (j = 0; j < RPMH_ARC_LEVEL_SIZE; j++)
+ rpmhpd->level[i] |=
+ buf[i * RPMH_ARC_LEVEL_SIZE + j] << (8 * j);
+
+ /*
+ * The AUX data may be zero padded. These 0 valued entries at
+ * the end of the map must be ignored.
+ */
+ if (i > 0 && rpmhpd->level[i] == 0) {
+ rpmhpd->level_count = i;
+ break;
+ }
+ pr_debug("%s: ARC hlvl=%2d --> vlvl=%4u\n", rpmhpd->res_name, i,
+ rpmhpd->level[i]);
+ }
+
+ return 0;
+}
+
+static int rpmhpd_probe(struct platform_device *pdev)
+{
+ int i, ret;
+ size_t num_pds;
+ struct device *dev = &pdev->dev;
+ struct genpd_onecell_data *data;
+ struct rpmhpd **rpmhpds;
+ const struct rpmhpd_desc *desc;
+
+ desc = of_device_get_match_data(dev);
+ if (!desc)
+ return -EINVAL;
+
+ rpmhpds = desc->rpmhpds;
+ num_pds = desc->num_pds;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->domains = devm_kcalloc(dev, num_pds, sizeof(*data->domains),
+ GFP_KERNEL);
+ if (!data->domains)
+ return -ENOMEM;
+
+ data->num_domains = num_pds;
+
+ ret = cmd_db_ready();
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Command DB unavailable, ret=%d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < num_pds; i++) {
+ if (!rpmhpds[i]) {
+ dev_warn(dev, "rpmhpds[%d] is empty\n", i);
+ continue;
+ }
+
+ rpmhpds[i]->dev = dev;
+ rpmhpds[i]->addr = cmd_db_read_addr(rpmhpds[i]->res_name);
+ if (!rpmhpds[i]->addr) {
+ dev_err(dev, "Could not find RPMh address for resource %s\n",
+ rpmhpds[i]->res_name);
+ return -ENODEV;
+ }
+
+ ret = cmd_db_read_slave_id(rpmhpds[i]->res_name);
+ if (ret != CMD_DB_HW_ARC) {
+ dev_err(dev, "RPMh slave ID mismatch\n");
+ return -EINVAL;
+ }
+
+ ret = rpmhpd_update_level_mapping(rpmhpds[i]);
+ if (ret)
+ return ret;
+
+ rpmhpds[i]->pd.power_off = rpmhpd_power_off;
+ rpmhpds[i]->pd.power_on = rpmhpd_power_on;
+ rpmhpds[i]->pd.set_performance_state = rpmhpd_set_performance_state;
+ rpmhpds[i]->pd.opp_to_performance_state = rpmhpd_get_performance_state;
+ pm_genpd_init(&rpmhpds[i]->pd, NULL, true);
+
+ data->domains[i] = &rpmhpds[i]->pd;
+ }
+
+ return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
+}
+
+static struct platform_driver rpmhpd_driver = {
+ .driver = {
+ .name = "qcom-rpmhpd",
+ .of_match_table = rpmhpd_match_table,
+ },
+ .probe = rpmhpd_probe,
+};
+
+static int __init rpmhpd_init(void)
+{
+ return platform_driver_register(&rpmhpd_driver);
+}
+core_initcall(rpmhpd_init);
+
+static void __exit rpmhpd_exit(void)
+{
+ platform_driver_unregister(&rpmhpd_driver);
+}
+module_exit(rpmhpd_exit);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPMh Power Domain Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qcom-rpmhpd");
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


2018-06-27 05:12:08

by Rajendra Nayak

[permalink] [raw]
Subject: [PATCH v4 5/6] arm64: dts: msm8996: Add rpmpd device node

Add rpmpd device node and its OPP table

Signed-off-by: Rajendra Nayak <[email protected]>
Signed-off-by: Viresh Kumar <[email protected]>
Reviewed-by: Ulf Hansson <[email protected]>
---
arch/arm64/boot/dts/qcom/msm8996.dtsi | 34 +++++++++++++++++++++++++++
1 file changed, 34 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 8c7f9ca25b53..404a08630ccd 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -308,6 +308,40 @@
#clock-cells = <1>;
};

+ rpmpd: power-controller {
+ compatible = "qcom,msm8996-rpmpd";
+ #power-domain-cells = <1>;
+ operating-points-v2 = <&rpmpd_opp_table>;
+ };
+
+ rpmpd_opp_table: opp-table {
+ compatible = "operating-points-v2-qcom-level";
+
+ rpmpd_opp1: opp1 {
+ qcom,level = <1>;
+ };
+
+ rpmpd_opp2: opp2 {
+ qcom,level = <2>;
+ };
+
+ rpmpd_opp3: opp3 {
+ qcom,level = <3>;
+ };
+
+ rpmpd_opp4: opp4 {
+ qcom,level = <4>;
+ };
+
+ rpmpd_opp5: opp5 {
+ qcom,level = <5>;
+ };
+
+ rpmpd_opp6: opp6 {
+ qcom,level = <6>;
+ };
+ };
+
pm8994-regulators {
compatible = "qcom,rpm-pm8994-regulators";

--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


2018-06-27 05:14:20

by Rajendra Nayak

[permalink] [raw]
Subject: [PATCH v4 4/6] soc: qcom: rpmpd: Add support for get/set performance state

Add support for the .set_performace_state() and .opp_to_performance_state()
callbacks in the rpmpd driver.

Signed-off-by: Rajendra Nayak <[email protected]>
Signed-off-by: Viresh Kumar <[email protected]>
Reviewed-by: Ulf Hansson <[email protected]>
---
drivers/soc/qcom/rpmpd.c | 46 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)

diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
index a0b9f122d793..eb1cfa6a03d6 100644
--- a/drivers/soc/qcom/rpmpd.c
+++ b/drivers/soc/qcom/rpmpd.c
@@ -12,6 +12,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
#include <linux/soc/qcom/smd-rpm.h>

#include <dt-bindings/mfd/qcom-rpm.h>
@@ -28,6 +29,8 @@
#define KEY_ENABLE 0x6e657773 /* swen */
#define KEY_FLOOR_CORNER 0x636676 /* vfc */

+#define MAX_RPMPD_STATE 6
+
#define DEFINE_RPMPD_CORN_SMPA(_platform, _name, _active, r_id) \
static struct rpmpd _platform##_##_active; \
static struct rpmpd _platform##_##_name = { \
@@ -221,6 +224,47 @@ static int rpmpd_power_off(struct generic_pm_domain *domain)
return ret;
}

+static int rpmpd_set_performance(struct generic_pm_domain *domain,
+ unsigned int state)
+{
+ int ret = 0;
+ struct rpmpd *pd = domain_to_rpmpd(domain);
+
+ mutex_lock(&rpmpd_lock);
+
+ if (state > MAX_RPMPD_STATE)
+ goto out;
+
+ pd->corner = state;
+
+ if (!pd->enabled && (pd->key != KEY_FLOOR_CORNER))
+ goto out;
+
+ ret = rpmpd_aggregate_corner(pd);
+
+out:
+ mutex_unlock(&rpmpd_lock);
+
+ return ret;
+}
+
+static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd,
+ struct dev_pm_opp *opp)
+{
+ struct device_node *np;
+ unsigned int corner = 0;
+
+ np = dev_pm_opp_get_of_node(opp);
+ if (of_property_read_u32(np, "qcom,level", &corner)) {
+ pr_err("%s: missing 'qcom,level' property\n", __func__);
+ return 0;
+ }
+
+ of_node_put(np);
+
+ return corner;
+}
+
static int rpmpd_probe(struct platform_device *pdev)
{
int i;
@@ -261,6 +305,8 @@ static int rpmpd_probe(struct platform_device *pdev)
rpmpds[i]->rpm = rpm;
rpmpds[i]->pd.power_off = rpmpd_power_off;
rpmpds[i]->pd.power_on = rpmpd_power_on;
+ rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
+ rpmpds[i]->pd.opp_to_performance_state = rpmpd_get_performance;
pm_genpd_init(&rpmpds[i]->pd, NULL, true);

data->domains[i] = &rpmpds[i]->pd;
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


2018-06-27 05:14:53

by Rajendra Nayak

[permalink] [raw]
Subject: [PATCH v4 3/6] soc: qcom: rpmpd: Add a Power domain driver to model corners

The Power domains for corners just pass the performance state set by the
consumers to the RPM (Remote Power manager) which then takes care
of setting the appropriate voltage on the corresponding rails to
meet the performance needs.

We add all Power domain data needed on msm8996 here. This driver can easily
be extended by adding data for other qualcomm SoCs as well.

Signed-off-by: Rajendra Nayak <[email protected]>
Signed-off-by: Viresh Kumar <[email protected]>
Reviewed-by: Ulf Hansson <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
drivers/soc/qcom/Kconfig | 9 ++
drivers/soc/qcom/Makefile | 1 +
drivers/soc/qcom/rpmpd.c | 294 ++++++++++++++++++++++++++++++++++++++
3 files changed, 304 insertions(+)
create mode 100644 drivers/soc/qcom/rpmpd.c

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 9dc02f390ba3..131da9d34a40 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -74,6 +74,15 @@ config QCOM_RMTFS_MEM

Say y here if you intend to boot the modem remoteproc.

+config QCOM_RPMPD
+ bool "Qualcomm RPM Power domain driver"
+ depends on MFD_QCOM_RPM && QCOM_SMD_RPM
+ help
+ QCOM RPM Power domain driver to support power-domains with
+ performance states. The driver communicates a performance state
+ value to RPM which then translates it into corresponding voltage
+ for the voltage rail.
+
config QCOM_SMEM
tristate "Qualcomm Shared Memory Manager (SMEM)"
depends on ARCH_QCOM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 19dcf957cb3a..9550c170de93 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
obj-$(CONFIG_QCOM_SMSM) += smsm.o
obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
obj-$(CONFIG_QCOM_APR) += apr.o
+obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c
new file mode 100644
index 000000000000..a0b9f122d793
--- /dev/null
+++ b/drivers/soc/qcom/rpmpd.c
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */
+
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pm_domain.h>
+#include <linux/mfd/qcom_rpm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/smd-rpm.h>
+
+#include <dt-bindings/mfd/qcom-rpm.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+#define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd)
+
+/* Resource types */
+#define RPMPD_SMPA 0x61706d73
+#define RPMPD_LDOA 0x616f646c
+
+/* Operation Keys */
+#define KEY_CORNER 0x6e726f63 /* corn */
+#define KEY_ENABLE 0x6e657773 /* swen */
+#define KEY_FLOOR_CORNER 0x636676 /* vfc */
+
+#define DEFINE_RPMPD_CORN_SMPA(_platform, _name, _active, r_id) \
+ static struct rpmpd _platform##_##_active; \
+ static struct rpmpd _platform##_##_name = { \
+ .pd = { .name = #_name, }, \
+ .peer = &_platform##_##_active, \
+ .res_type = RPMPD_SMPA, \
+ .res_id = r_id, \
+ .key = KEY_CORNER, \
+ }; \
+ static struct rpmpd _platform##_##_active = { \
+ .pd = { .name = #_active, }, \
+ .peer = &_platform##_##_name, \
+ .active_only = true, \
+ .res_type = RPMPD_SMPA, \
+ .res_id = r_id, \
+ .key = KEY_CORNER, \
+ }
+
+#define DEFINE_RPMPD_CORN_LDOA(_platform, _name, r_id) \
+ static struct rpmpd _platform##_##_name = { \
+ .pd = { .name = #_name, }, \
+ .res_type = RPMPD_LDOA, \
+ .res_id = r_id, \
+ .key = KEY_CORNER, \
+ }
+
+#define DEFINE_RPMPD_VFC(_platform, _name, r_id, r_type) \
+ static struct rpmpd _platform##_##_name = { \
+ .pd = { .name = #_name, }, \
+ .res_type = r_type, \
+ .res_id = r_id, \
+ .key = KEY_FLOOR_CORNER, \
+ }
+
+#define DEFINE_RPMPD_VFC_SMPA(_platform, _name, r_id) \
+ DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_SMPA)
+
+#define DEFINE_RPMPD_VFC_LDOA(_platform, _name, r_id) \
+ DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_LDOA)
+
+struct rpmpd_req {
+ __le32 key;
+ __le32 nbytes;
+ __le32 value;
+};
+
+struct rpmpd {
+ struct generic_pm_domain pd;
+ struct rpmpd *peer;
+ const bool active_only;
+ unsigned int corner;
+ bool enabled;
+ const char *res_name;
+ const int res_type;
+ const int res_id;
+ struct qcom_smd_rpm *rpm;
+ __le32 key;
+};
+
+struct rpmpd_desc {
+ struct rpmpd **rpmpds;
+ size_t num_pds;
+};
+
+static DEFINE_MUTEX(rpmpd_lock);
+
+/* msm8996 RPM Power domains */
+DEFINE_RPMPD_CORN_SMPA(msm8996, vddcx, vddcx_ao, 1);
+DEFINE_RPMPD_CORN_SMPA(msm8996, vddmx, vddmx_ao, 2);
+DEFINE_RPMPD_CORN_LDOA(msm8996, vddsscx, 26);
+
+DEFINE_RPMPD_VFC_SMPA(msm8996, vddcx_vfc, 1);
+DEFINE_RPMPD_VFC_LDOA(msm8996, vddsscx_vfc, 26);
+
+static struct rpmpd *msm8996_rpmpds[] = {
+ [MSM8996_VDDCX] = &msm8996_vddcx,
+ [MSM8996_VDDCX_AO] = &msm8996_vddcx_ao,
+ [MSM8996_VDDCX_VFC] = &msm8996_vddcx_vfc,
+ [MSM8996_VDDMX] = &msm8996_vddmx,
+ [MSM8996_VDDMX_AO] = &msm8996_vddmx_ao,
+ [MSM8996_VDDSSCX] = &msm8996_vddsscx,
+ [MSM8996_VDDSSCX_VFC] = &msm8996_vddsscx_vfc,
+};
+
+static const struct rpmpd_desc msm8996_desc = {
+ .rpmpds = msm8996_rpmpds,
+ .num_pds = ARRAY_SIZE(msm8996_rpmpds),
+};
+
+static const struct of_device_id rpmpd_match_table[] = {
+ { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rpmpd_match_table);
+
+static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
+{
+ struct rpmpd_req req = {
+ .key = KEY_ENABLE,
+ .nbytes = cpu_to_le32(sizeof(u32)),
+ .value = cpu_to_le32(enable),
+ };
+
+ return qcom_rpm_smd_write(pd->rpm, QCOM_RPM_ACTIVE_STATE, pd->res_type,
+ pd->res_id, &req, sizeof(req));
+}
+
+static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
+{
+ struct rpmpd_req req = {
+ .key = pd->key,
+ .nbytes = cpu_to_le32(sizeof(u32)),
+ .value = cpu_to_le32(corner),
+ };
+
+ return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id,
+ &req, sizeof(req));
+};
+
+static void to_active_sleep(struct rpmpd *pd, unsigned int corner,
+ unsigned int *active, unsigned int *sleep)
+{
+ *active = corner;
+
+ if (pd->active_only)
+ *sleep = 0;
+ else
+ *sleep = *active;
+}
+
+static int rpmpd_aggregate_corner(struct rpmpd *pd)
+{
+ int ret;
+ struct rpmpd *peer = pd->peer;
+ unsigned int active_corner, sleep_corner;
+ unsigned int this_active_corner = 0, this_sleep_corner = 0;
+ unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
+
+ to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
+
+ if (peer && peer->enabled)
+ to_active_sleep(peer, peer->corner, &peer_active_corner,
+ &peer_sleep_corner);
+
+ active_corner = max(this_active_corner, peer_active_corner);
+
+ ret = rpmpd_send_corner(pd, QCOM_RPM_ACTIVE_STATE, active_corner);
+ if (ret)
+ return ret;
+
+ sleep_corner = max(this_sleep_corner, peer_sleep_corner);
+
+ return rpmpd_send_corner(pd, QCOM_RPM_SLEEP_STATE, sleep_corner);
+}
+
+static int rpmpd_power_on(struct generic_pm_domain *domain)
+{
+ int ret;
+ struct rpmpd *pd = domain_to_rpmpd(domain);
+
+ mutex_lock(&rpmpd_lock);
+
+ ret = rpmpd_send_enable(pd, true);
+ if (ret)
+ goto out;
+
+ pd->enabled = true;
+
+ if (pd->corner)
+ ret = rpmpd_aggregate_corner(pd);
+
+out:
+ mutex_unlock(&rpmpd_lock);
+
+ return ret;
+}
+
+static int rpmpd_power_off(struct generic_pm_domain *domain)
+{
+ int ret;
+ struct rpmpd *pd = domain_to_rpmpd(domain);
+
+ mutex_lock(&rpmpd_lock);
+
+ ret = rpmpd_send_enable(pd, false);
+ if (!ret)
+ pd->enabled = false;
+
+ mutex_unlock(&rpmpd_lock);
+
+ return ret;
+}
+
+static int rpmpd_probe(struct platform_device *pdev)
+{
+ int i;
+ size_t num;
+ struct genpd_onecell_data *data;
+ struct qcom_smd_rpm *rpm;
+ struct rpmpd **rpmpds;
+ const struct rpmpd_desc *desc;
+
+ rpm = dev_get_drvdata(pdev->dev.parent);
+ if (!rpm) {
+ dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
+ return -ENODEV;
+ }
+
+ desc = of_device_get_match_data(&pdev->dev);
+ if (!desc)
+ return -EINVAL;
+
+ rpmpds = desc->rpmpds;
+ num = desc->num_pds;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
+ GFP_KERNEL);
+ data->num_domains = num;
+
+ for (i = 0; i < num; i++) {
+ if (!rpmpds[i]) {
+ dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n",
+ i);
+ continue;
+ }
+
+ rpmpds[i]->rpm = rpm;
+ rpmpds[i]->pd.power_off = rpmpd_power_off;
+ rpmpds[i]->pd.power_on = rpmpd_power_on;
+ pm_genpd_init(&rpmpds[i]->pd, NULL, true);
+
+ data->domains[i] = &rpmpds[i]->pd;
+ }
+
+ return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
+}
+
+static struct platform_driver rpmpd_driver = {
+ .driver = {
+ .name = "qcom-rpmpd",
+ .of_match_table = rpmpd_match_table,
+ },
+ .probe = rpmpd_probe,
+};
+
+static int __init rpmpd_init(void)
+{
+ return platform_driver_register(&rpmpd_driver);
+}
+core_initcall(rpmpd_init);
+
+static void __exit rpmpd_exit(void)
+{
+ platform_driver_unregister(&rpmpd_driver);
+}
+module_exit(rpmpd_exit);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPM Power Domain Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qcom-rpmpd");
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


2018-06-27 05:15:21

by Rajendra Nayak

[permalink] [raw]
Subject: [PATCH v4 1/6] dt-bindings: opp: Introduce qcom-opp bindings

On Qualcomm Technologies, Inc. platforms, an OPP node needs
to describe an additional level/corner value that is then communicated
to a remote microprocessor by the CPU, which then takes some
actions (like adjusting voltage values across various rails)
based on the value passed.

Describe these bindings in the qcom-opp bindings document.

Signed-off-by: Rajendra Nayak <[email protected]>
Acked-by: Viresh Kumar <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
.../devicetree/bindings/opp/qcom-opp.txt | 25 +++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 Documentation/devicetree/bindings/opp/qcom-opp.txt

diff --git a/Documentation/devicetree/bindings/opp/qcom-opp.txt b/Documentation/devicetree/bindings/opp/qcom-opp.txt
new file mode 100644
index 000000000000..db4d970c7ec7
--- /dev/null
+++ b/Documentation/devicetree/bindings/opp/qcom-opp.txt
@@ -0,0 +1,25 @@
+Qualcomm OPP bindings to descibe OPP nodes with corner/level values
+
+OPP tables for devices on Qualcomm platforms require an additional
+platform specific corner/level value to be specified.
+This value is passed on to the RPM (Resource Power Manager) by
+the CPU, which then takes the necessary actions to set a voltage
+rail to an appropriate voltage based on the value passed.
+
+The bindings are based on top of the operating-points-v2 bindings
+described in Documentation/devicetree/bindings/opp/opp.txt
+Additional properties are described below.
+
+* OPP Table Node
+
+Required properties:
+- compatible: Allow OPPs to express their compatibility. It should be:
+ "operating-points-v2-qcom-level"
+
+* OPP Node
+
+Required properties:
+- qcom,level: On Qualcomm platforms an OPP node can describe a positive value
+representing a corner/level that's communicated with a remote microprocessor
+(usually called the RPM) which then translates it into a certain voltage on
+a voltage rail.
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


2018-06-27 06:28:01

by Rajendra Nayak

[permalink] [raw]
Subject: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings

Add DT bindings to describe the rpm/rpmh power domains found on Qualcomm
Technologies, Inc. SoCs. These power domains communicate a performance
state to RPM/RPMh, which then translates it into corresponding voltage on a
PMIC rail.

Signed-off-by: Rajendra Nayak <[email protected]>
Signed-off-by: Viresh Kumar <[email protected]>
Reviewed-by: Ulf Hansson <[email protected]>
---
.../devicetree/bindings/power/qcom,rpmpd.txt | 146 ++++++++++++++++++
include/dt-bindings/power/qcom-rpmpd.h | 39 +++++
2 files changed, 185 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.txt
create mode 100644 include/dt-bindings/power/qcom-rpmpd.h

diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt
new file mode 100644
index 000000000000..8825080afa5a
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt
@@ -0,0 +1,146 @@
+Qualcomm RPM/RPMh Power domains
+
+For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh
+which then translates it into a corresponding voltage on a rail
+
+Required Properties:
+ - compatible: Should be one of the following
+ * qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC
+ * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC
+ - power-domain-cells: number of cells in Power domain specifier
+ must be 1.
+ - operating-points-v2: Phandle to the OPP table for the Power domain.
+ Refer to Documentation/devicetree/bindings/power/power_domain.txt
+ and Documentation/devicetree/bindings/opp/qcom-opp.txt for more details
+
+Refer to <dt-bindings/power/qcom-rpmpd.h> for the level values for
+various OPPs for different platforms as well as Power domain indexes
+
+Example: rpmh power domain controller and OPP table
+
+#include <dt-bindings/power/qcom-rpmhpd.h>
+
+qcom,level values specified in the OPP tables for RPMh power domains
+should use the RPMH_REGULATOR_LEVEL_* constants from
+<dt-bindings/power/qcom-rpmhpd.h>
+
+ rpmhpd: power-controller {
+ compatible = "qcom,sdm845-rpmhpd";
+ #power-domain-cells = <1>;
+ operating-points-v2 = <&rpmhpd_opp_table>;
+ };
+
+ rpmhpd_opp_table: opp-table {
+ compatible = "operating-points-v2-qcom-level";
+
+ rpmhpd_opp_ret: opp1 {
+ qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
+ };
+
+ rpmhpd_opp_min_svs: opp2 {
+ qcom,level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
+ };
+
+ rpmhpd_opp_low_svs: opp3 {
+ qcom,level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
+ };
+
+ rpmhpd_opp_svs: opp4 {
+ qcom,level = <RPMH_REGULATOR_LEVEL_SVS>;
+ };
+
+ rpmhpd_opp_svs_l1: opp5 {
+ qcom,level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
+ };
+
+ rpmhpd_opp_nom: opp6 {
+ qcom,level = <RPMH_REGULATOR_LEVEL_NOM>;
+ };
+
+ rpmhpd_opp_nom_l1: opp7 {
+ qcom,level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
+ };
+
+ rpmhpd_opp_nom_l2: opp8 {
+ qcom,level = <RPMH_REGULATOR_LEVEL_NOM_L2>;
+ };
+
+ rpmhpd_opp_turbo: opp9 {
+ qcom,level = <RPMH_REGULATOR_LEVEL_TURBO>;
+ };
+
+ rpmhpd_opp_turbo_l1: opp10 {
+ qcom,level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
+ };
+ };
+
+Example: rpm power domain controller and OPP table
+
+ rpmpd: power-controller {
+ compatible = "qcom,msm8996-rpmpd";
+ #power-domain-cells = <1>;
+ operating-points-v2 = <&rpmpd_opp_table>;
+ };
+
+ rpmpd_opp_table: opp-table {
+ compatible = "operating-points-v2-qcom-level";
+
+ rpmpd_opp_low: opp1 {
+ qcom,level = <1>;
+ };
+
+ rpmpd_opp_ret: opp2 {
+ qcom,level = <2>;
+ };
+
+ rpmpd_opp_svs: opp3 {
+ qcom,level = <3>;
+ };
+
+ rpmpd_opp_normal: opp4 {
+ qcom,level = <4>;
+ };
+
+ rpmpd_opp_high: opp5 {
+ qcom,level = <5>;
+ };
+
+ rpmpd_opp_turbo: opp6 {
+ qcom,level = <6>;
+ };
+ };
+
+Example: Client/Consumer device using OPP table
+
+ leaky-device0@12350000 {
+ compatible = "foo,i-leak-current";
+ reg = <0x12350000 0x1000>;
+ power-domains = <&rpmhpd SDM845_MX>;
+ operating-points-v2 = <&leaky_opp_table>;
+ };
+
+
+ leaky_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp1 {
+ opp-hz = /bits/ 64 <144000>;
+ required-opps = <&rpmhpd_opp_low>;
+ };
+
+ opp2 {
+ opp-hz = /bits/ 64 <400000>;
+ required-opps = <&rpmhpd_opp_ret>;
+ };
+
+ opp3 {
+ opp-hz = /bits/ 64 <20000000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+
+ opp4 {
+ opp-hz = /bits/ 64 <25000000>;
+ required-opps = <&rpmpd_opp_normal>;
+ };
+
+ };
diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h
new file mode 100644
index 000000000000..87d9c6611682
--- /dev/null
+++ b/include/dt-bindings/power/qcom-rpmpd.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved. */
+
+#ifndef _DT_BINDINGS_POWER_QCOM_RPMPD_H
+#define _DT_BINDINGS_POWER_QCOM_RPMPD_H
+
+/* SDM845 Power Domain Indexes */
+#define SDM845_EBI 0
+#define SDM845_MX 1
+#define SDM845_MX_AO 2
+#define SDM845_CX 3
+#define SDM845_CX_AO 4
+#define SDM845_LMX 5
+#define SDM845_LCX 6
+#define SDM845_GFX 7
+#define SDM845_MSS 8
+
+/* SDM845 Power Domain performance levels */
+#define RPMH_REGULATOR_LEVEL_RETENTION 16
+#define RPMH_REGULATOR_LEVEL_MIN_SVS 48
+#define RPMH_REGULATOR_LEVEL_LOW_SVS 64
+#define RPMH_REGULATOR_LEVEL_SVS 128
+#define RPMH_REGULATOR_LEVEL_SVS_L1 192
+#define RPMH_REGULATOR_LEVEL_NOM 256
+#define RPMH_REGULATOR_LEVEL_NOM_L1 320
+#define RPMH_REGULATOR_LEVEL_NOM_L2 336
+#define RPMH_REGULATOR_LEVEL_TURBO 384
+#define RPMH_REGULATOR_LEVEL_TURBO_L1 416
+
+/* MSM8996 Power Domain Indexes */
+#define MSM8996_VDDCX 0
+#define MSM8996_VDDCX_AO 1
+#define MSM8996_VDDCX_VFC 2
+#define MSM8996_VDDMX 3
+#define MSM8996_VDDMX_AO 4
+#define MSM8996_VDDSSCX 5
+#define MSM8996_VDDSSCX_VFC 6
+
+#endif
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


2018-07-03 22:36:55

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings

On Wed, Jun 27, 2018 at 10:22:30AM +0530, Rajendra Nayak wrote:
> Add DT bindings to describe the rpm/rpmh power domains found on Qualcomm
> Technologies, Inc. SoCs. These power domains communicate a performance
> state to RPM/RPMh, which then translates it into corresponding voltage on a
> PMIC rail.
>
> Signed-off-by: Rajendra Nayak <[email protected]>
> Signed-off-by: Viresh Kumar <[email protected]>
> Reviewed-by: Ulf Hansson <[email protected]>
> ---
> .../devicetree/bindings/power/qcom,rpmpd.txt | 146 ++++++++++++++++++
> include/dt-bindings/power/qcom-rpmpd.h | 39 +++++
> 2 files changed, 185 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.txt
> create mode 100644 include/dt-bindings/power/qcom-rpmpd.h
>
> diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt
> new file mode 100644
> index 000000000000..8825080afa5a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt
> @@ -0,0 +1,146 @@
> +Qualcomm RPM/RPMh Power domains
> +
> +For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh
> +which then translates it into a corresponding voltage on a rail
> +
> +Required Properties:
> + - compatible: Should be one of the following
> + * qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC
> + * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC
> + - power-domain-cells: number of cells in Power domain specifier
> + must be 1.
> + - operating-points-v2: Phandle to the OPP table for the Power domain.
> + Refer to Documentation/devicetree/bindings/power/power_domain.txt
> + and Documentation/devicetree/bindings/opp/qcom-opp.txt for more details
> +
> +Refer to <dt-bindings/power/qcom-rpmpd.h> for the level values for
> +various OPPs for different platforms as well as Power domain indexes
> +
> +Example: rpmh power domain controller and OPP table
> +
> +#include <dt-bindings/power/qcom-rpmhpd.h>
> +
> +qcom,level values specified in the OPP tables for RPMh power domains
> +should use the RPMH_REGULATOR_LEVEL_* constants from
> +<dt-bindings/power/qcom-rpmhpd.h>
> +
> + rpmhpd: power-controller {
> + compatible = "qcom,sdm845-rpmhpd";
> + #power-domain-cells = <1>;
> + operating-points-v2 = <&rpmhpd_opp_table>;
> + };
> +
> + rpmhpd_opp_table: opp-table {
> + compatible = "operating-points-v2-qcom-level";
> +
> + rpmhpd_opp_ret: opp1 {
> + qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
> + };

I don't see the point in using the OPP binding here when you aren't
using *any* of the properties from it.

Rob

2018-07-04 05:59:04

by Viresh Kumar

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings

On 03-07-18, 16:35, Rob Herring wrote:
> > +qcom,level values specified in the OPP tables for RPMh power domains
> > +should use the RPMH_REGULATOR_LEVEL_* constants from
> > +<dt-bindings/power/qcom-rpmhpd.h>
> > +
> > + rpmhpd: power-controller {
> > + compatible = "qcom,sdm845-rpmhpd";
> > + #power-domain-cells = <1>;
> > + operating-points-v2 = <&rpmhpd_opp_table>;
> > + };
> > +
> > + rpmhpd_opp_table: opp-table {
> > + compatible = "operating-points-v2-qcom-level";
> > +
> > + rpmhpd_opp_ret: opp1 {
> > + qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
> > + };
>
> I don't see the point in using the OPP binding here when you aren't
> using *any* of the properties from it.

Yeah, that's the case for now. But there are cases (as Stephen
mentioned earlier [1]) where the voltage values (and maybe other
values like current, etc) would be known and filled in DT. And that's
why we all agreed to use OPP tables for PM domains as well, as these
are really "operating performance points" of these PM domains.

--
viresh

[1] lkml.kernel.org/r/[email protected]

2018-08-30 06:33:39

by Rajendra Nayak

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings



On 7/4/2018 11:27 AM, Viresh Kumar wrote:
> On 03-07-18, 16:35, Rob Herring wrote:
>>> +qcom,level values specified in the OPP tables for RPMh power domains
>>> +should use the RPMH_REGULATOR_LEVEL_* constants from
>>> +<dt-bindings/power/qcom-rpmhpd.h>
>>> +
>>> + rpmhpd: power-controller {
>>> + compatible = "qcom,sdm845-rpmhpd";
>>> + #power-domain-cells = <1>;
>>> + operating-points-v2 = <&rpmhpd_opp_table>;
>>> + };
>>> +
>>> + rpmhpd_opp_table: opp-table {
>>> + compatible = "operating-points-v2-qcom-level";
>>> +
>>> + rpmhpd_opp_ret: opp1 {
>>> + qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
>>> + };
>>
>> I don't see the point in using the OPP binding here when you aren't
>> using *any* of the properties from it.
>
> Yeah, that's the case for now. But there are cases (as Stephen
> mentioned earlier [1]) where the voltage values (and maybe other
> values like current, etc) would be known and filled in DT. And that's
> why we all agreed to use OPP tables for PM domains as well, as these
> are really "operating performance points" of these PM domains.

Rob, are you fine with these bindings then?
If so, can we please have your reviewed-by?

2018-08-30 06:37:43

by Rajendra Nayak

[permalink] [raw]
Subject: Re: [PATCH v4 0/6] Add power domain driver for corners on msm8996/sdm845



On 6/27/2018 10:22 AM, Rajendra Nayak wrote:
> Changes in v4:
> * Included the patch to add qcom-opp bindings (dropped accidentally in v3)
> * merged the patches to add bindings for rpm and rpmh, added consumer binding example
> * Made the drivers built in, removed .remove
> * Added better description in changelog for PATCH 6/6
> * Updated rpmhpd_aggregate_corner() based on Davids feedback
> * rpmhpd_set_performance_state() returns max corner, in cases where its called
> with an INT_MAX
> * Dropped the patch to max vote on all corners at init, the patch did not
> work anyway, and it shouldn't be needed now

These patches have been out on the list for a while (8 weeks).
I haven't seen any further comments from anyone, except on PATCH 2/6
by Rob. I requested Rob to provide his Ack if he is fine with the bindings.

Can we plan to pull these in for 4.20?

>
> Changes in v3:
> * Bindings split into seperate patches
> * Bindings updated to remove duplicate OPP table phandles
> * DT headers defining macros for Power domain indexes and OPP levels
> * Optimisations to use rpmh_write_async() whereever applicable
> * Fixed up handling of ACTIVE_ONLY/WAKE_ONLY/SLEEP voting for RPMh
> * Fixed the vlvl to hlvl conversions in set_performance
> * Other minor fixes based on review of v2
> * TODO: This series does not handle the case where all VDD_MX votes
> should be higher than VDD_CX from APPs, as pointed out
> by David Collins in v2. This needs support at genpd to propogate performance
> state up the parents, if we model these as Parent/Child to handle the
> interdependency.
>
> Changes in v2:
> * added a power domain driver for sdm845 which supports communicating to RPMh
> * dropped the changes to sdhc driver to move over to using OPP
> as there is active discussion on using OPP as the interface vs
> handling all of it in clock drivers
> * Other minor binding updates based on review of v1
>
> With performance state support for genpd/OPP merged, this is an effort
> to model a power domain driver to communicate corner/level
> values for qualcomm platforms to RPM (Remote Power Manager) and RPMh.
>
> Rajendra Nayak (6):
> dt-bindings: opp: Introduce qcom-opp bindings
> dt-bindings: power: Add qcom rpm power domain driver bindings
> soc: qcom: rpmpd: Add a Power domain driver to model corners
> soc: qcom: rpmpd: Add support for get/set performance state
> arm64: dts: msm8996: Add rpmpd device node
> soc: qcom: rpmhpd: Add RPMh Power domain driver
>
> .../devicetree/bindings/opp/qcom-opp.txt | 25 ++
> .../devicetree/bindings/power/qcom,rpmpd.txt | 146 +++++++
> arch/arm64/boot/dts/qcom/msm8996.dtsi | 34 ++
> drivers/soc/qcom/Kconfig | 18 +
> drivers/soc/qcom/Makefile | 2 +
> drivers/soc/qcom/rpmhpd.c | 406 ++++++++++++++++++
> drivers/soc/qcom/rpmpd.c | 340 +++++++++++++++
> include/dt-bindings/power/qcom-rpmpd.h | 39 ++
> 8 files changed, 1010 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/opp/qcom-opp.txt
> create mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.txt
> create mode 100644 drivers/soc/qcom/rpmhpd.c
> create mode 100644 drivers/soc/qcom/rpmpd.c
> create mode 100644 include/dt-bindings/power/qcom-rpmpd.h
>

2018-08-30 08:22:44

by Niklas Cassel

[permalink] [raw]
Subject: Re: [PATCH v4 0/6] Add power domain driver for corners on msm8996/sdm845

On Thu, Aug 30, 2018 at 12:05:14PM +0530, Rajendra Nayak wrote:
>
>
> On 6/27/2018 10:22 AM, Rajendra Nayak wrote:
> > Changes in v4:
> > * Included the patch to add qcom-opp bindings (dropped accidentally in v3)
> > * merged the patches to add bindings for rpm and rpmh, added consumer binding example
> > * Made the drivers built in, removed .remove
> > * Added better description in changelog for PATCH 6/6
> > * Updated rpmhpd_aggregate_corner() based on Davids feedback
> > * rpmhpd_set_performance_state() returns max corner, in cases where its called
> > with an INT_MAX
> > * Dropped the patch to max vote on all corners at init, the patch did not
> > work anyway, and it shouldn't be needed now
>
> These patches have been out on the list for a while (8 weeks).
> I haven't seen any further comments from anyone, except on PATCH 2/6
> by Rob. I requested Rob to provide his Ack if he is fine with the bindings.
>
> Can we plan to pull these in for 4.20?

Hello Rajendra,

FYI: these patches do no longer cleanly apply to v4.19-rc1, it's a trivial
conflict, but most maintainers prefer for the patch author to rebase, not
sure what Andy prefers.

If it builds correctly with COMPILE_TEST, please consider adding that to
your new Kconfig:
depends on MFD_QCOM_RPM && QCOM_SMD_RPM || COMPILE_TEST

Kind regards,
Niklas

>
> >
> > Changes in v3:
> > * Bindings split into seperate patches
> > * Bindings updated to remove duplicate OPP table phandles
> > * DT headers defining macros for Power domain indexes and OPP levels
> > * Optimisations to use rpmh_write_async() whereever applicable
> > * Fixed up handling of ACTIVE_ONLY/WAKE_ONLY/SLEEP voting for RPMh
> > * Fixed the vlvl to hlvl conversions in set_performance
> > * Other minor fixes based on review of v2
> > * TODO: This series does not handle the case where all VDD_MX votes
> > should be higher than VDD_CX from APPs, as pointed out
> > by David Collins in v2. This needs support at genpd to propogate performance
> > state up the parents, if we model these as Parent/Child to handle the
> > interdependency.
> >
> > Changes in v2:
> > * added a power domain driver for sdm845 which supports communicating to RPMh
> > * dropped the changes to sdhc driver to move over to using OPP
> > as there is active discussion on using OPP as the interface vs
> > handling all of it in clock drivers
> > * Other minor binding updates based on review of v1
> >
> > With performance state support for genpd/OPP merged, this is an effort
> > to model a power domain driver to communicate corner/level
> > values for qualcomm platforms to RPM (Remote Power Manager) and RPMh.
> >
> > Rajendra Nayak (6):
> > dt-bindings: opp: Introduce qcom-opp bindings
> > dt-bindings: power: Add qcom rpm power domain driver bindings
> > soc: qcom: rpmpd: Add a Power domain driver to model corners
> > soc: qcom: rpmpd: Add support for get/set performance state
> > arm64: dts: msm8996: Add rpmpd device node
> > soc: qcom: rpmhpd: Add RPMh Power domain driver
> >
> > .../devicetree/bindings/opp/qcom-opp.txt | 25 ++
> > .../devicetree/bindings/power/qcom,rpmpd.txt | 146 +++++++
> > arch/arm64/boot/dts/qcom/msm8996.dtsi | 34 ++
> > drivers/soc/qcom/Kconfig | 18 +
> > drivers/soc/qcom/Makefile | 2 +
> > drivers/soc/qcom/rpmhpd.c | 406 ++++++++++++++++++
> > drivers/soc/qcom/rpmpd.c | 340 +++++++++++++++
> > include/dt-bindings/power/qcom-rpmpd.h | 39 ++
> > 8 files changed, 1010 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/opp/qcom-opp.txt
> > create mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.txt
> > create mode 100644 drivers/soc/qcom/rpmhpd.c
> > create mode 100644 drivers/soc/qcom/rpmpd.c
> > create mode 100644 include/dt-bindings/power/qcom-rpmpd.h
> >

2018-09-20 18:52:10

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings

On Wed, Aug 29, 2018 at 11:31 PM Rajendra Nayak <[email protected]> wrote:
>
>
>
> On 7/4/2018 11:27 AM, Viresh Kumar wrote:
> > On 03-07-18, 16:35, Rob Herring wrote:
> >>> +qcom,level values specified in the OPP tables for RPMh power domains
> >>> +should use the RPMH_REGULATOR_LEVEL_* constants from
> >>> +<dt-bindings/power/qcom-rpmhpd.h>
> >>> +
> >>> + rpmhpd: power-controller {
> >>> + compatible = "qcom,sdm845-rpmhpd";
> >>> + #power-domain-cells = <1>;
> >>> + operating-points-v2 = <&rpmhpd_opp_table>;
> >>> + };
> >>> +
> >>> + rpmhpd_opp_table: opp-table {
> >>> + compatible = "operating-points-v2-qcom-level";
> >>> +
> >>> + rpmhpd_opp_ret: opp1 {
> >>> + qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
> >>> + };
> >>
> >> I don't see the point in using the OPP binding here when you aren't
> >> using *any* of the properties from it.
> >
> > Yeah, that's the case for now. But there are cases (as Stephen
> > mentioned earlier [1]) where the voltage values (and maybe other
> > values like current, etc) would be known and filled in DT. And that's
> > why we all agreed to use OPP tables for PM domains as well, as these
> > are really "operating performance points" of these PM domains.
>
> Rob, are you fine with these bindings then?

Okay, my only thought is whether we should just use 'reg' here, or do
we need 'level' for anything else and should make it common?

Rob

2018-09-25 10:27:02

by Rajendra Nayak

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings

Hi Rob,

[]...
>>>>> + rpmhpd_opp_table: opp-table {
>>>>> + compatible = "operating-points-v2-qcom-level";
>>>>> +
>>>>> + rpmhpd_opp_ret: opp1 {
>>>>> + qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
>>>>> + };
>>>>
>>>> I don't see the point in using the OPP binding here when you aren't
>>>> using *any* of the properties from it.
>>>
>>> Yeah, that's the case for now. But there are cases (as Stephen
>>> mentioned earlier [1]) where the voltage values (and maybe other
>>> values like current, etc) would be known and filled in DT. And that's
>>> why we all agreed to use OPP tables for PM domains as well, as these
>>> are really "operating performance points" of these PM domains.
>>
>> Rob, are you fine with these bindings then?
>
> Okay, my only thought is whether we should just use 'reg' here, or do
> we need 'level' for anything else and should make it common?

I am not quite sure I understood what you are suggesting here :(


2018-09-25 19:43:59

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings

On Tue, Sep 25, 2018 at 5:25 AM Rajendra Nayak <[email protected]> wrote:
>
> Hi Rob,
>
> []...
> >>>>> + rpmhpd_opp_table: opp-table {
> >>>>> + compatible = "operating-points-v2-qcom-level";
> >>>>> +
> >>>>> + rpmhpd_opp_ret: opp1 {
> >>>>> + qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
> >>>>> + };
> >>>>
> >>>> I don't see the point in using the OPP binding here when you aren't
> >>>> using *any* of the properties from it.
> >>>
> >>> Yeah, that's the case for now. But there are cases (as Stephen
> >>> mentioned earlier [1]) where the voltage values (and maybe other
> >>> values like current, etc) would be known and filled in DT. And that's
> >>> why we all agreed to use OPP tables for PM domains as well, as these
> >>> are really "operating performance points" of these PM domains.
> >>
> >> Rob, are you fine with these bindings then?
> >
> > Okay, my only thought is whether we should just use 'reg' here, or do
> > we need 'level' for anything else and should make it common?
>
> I am not quite sure I understood what you are suggesting here :(

You could use the 'reg' property instead of 'qcom,level'. Any reason
not to do that?

Alternatively, would 'level' be something useful in other situations
and should not be QCom specific?

Rob

2018-10-04 08:37:42

by Viresh Kumar

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings

On 25-09-18, 14:43, Rob Herring wrote:
> On Tue, Sep 25, 2018 at 5:25 AM Rajendra Nayak <[email protected]> wrote:
> >
> > Hi Rob,
> >
> > []...
> > >>>>> + rpmhpd_opp_table: opp-table {
> > >>>>> + compatible = "operating-points-v2-qcom-level";
> > >>>>> +
> > >>>>> + rpmhpd_opp_ret: opp1 {
> > >>>>> + qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
> > >>>>> + };
> > >>>>
> > >>>> I don't see the point in using the OPP binding here when you aren't
> > >>>> using *any* of the properties from it.
> > >>>
> > >>> Yeah, that's the case for now. But there are cases (as Stephen
> > >>> mentioned earlier [1]) where the voltage values (and maybe other
> > >>> values like current, etc) would be known and filled in DT. And that's
> > >>> why we all agreed to use OPP tables for PM domains as well, as these
> > >>> are really "operating performance points" of these PM domains.
> > >>
> > >> Rob, are you fine with these bindings then?
> > >
> > > Okay, my only thought is whether we should just use 'reg' here, or do
> > > we need 'level' for anything else and should make it common?
> >
> > I am not quite sure I understood what you are suggesting here :(
>
> You could use the 'reg' property instead of 'qcom,level'. Any reason
> not to do that?

They can use any property which uniquely identifies the OPP nodes in
the table. Though I never thought we can use 'reg' property in such a
way. I always thought it must be related to registers somehow :)

Yeah, CPU is one of the examples where 'reg' has a special meaning.

> Alternatively, would 'level' be something useful in other situations
> and should not be QCom specific?

It is too early to say that. The only platform which needs this is
Qcom right now, lets see what the requirements from other users are.

--
viresh

2018-10-04 15:19:00

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings

On Thu, Oct 4, 2018 at 3:36 AM Viresh Kumar <[email protected]> wrote:
>
> On 25-09-18, 14:43, Rob Herring wrote:
> > On Tue, Sep 25, 2018 at 5:25 AM Rajendra Nayak <[email protected]> wrote:
> > >
> > > Hi Rob,
> > >
> > > []...
> > > >>>>> + rpmhpd_opp_table: opp-table {
> > > >>>>> + compatible = "operating-points-v2-qcom-level";
> > > >>>>> +
> > > >>>>> + rpmhpd_opp_ret: opp1 {
> > > >>>>> + qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
> > > >>>>> + };
> > > >>>>
> > > >>>> I don't see the point in using the OPP binding here when you aren't
> > > >>>> using *any* of the properties from it.
> > > >>>
> > > >>> Yeah, that's the case for now. But there are cases (as Stephen
> > > >>> mentioned earlier [1]) where the voltage values (and maybe other
> > > >>> values like current, etc) would be known and filled in DT. And that's
> > > >>> why we all agreed to use OPP tables for PM domains as well, as these
> > > >>> are really "operating performance points" of these PM domains.
> > > >>
> > > >> Rob, are you fine with these bindings then?
> > > >
> > > > Okay, my only thought is whether we should just use 'reg' here, or do
> > > > we need 'level' for anything else and should make it common?
> > >
> > > I am not quite sure I understood what you are suggesting here :(
> >
> > You could use the 'reg' property instead of 'qcom,level'. Any reason
> > not to do that?
>
> They can use any property which uniquely identifies the OPP nodes in
> the table. Though I never thought we can use 'reg' property in such a
> way. I always thought it must be related to registers somehow :)

That's almost certainly where the name originates from back in the
90s. I view 'reg' as how you identify or address a device. This can be
channels of something like an ADC.

It's perhaps a stretch for OPP nodes as they aren't really a device,
but if the levels are part of the h/w then perhaps reg is a good
match.

Rob

2018-10-04 19:17:51

by Niklas Cassel

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings

On Thu, Oct 04, 2018 at 10:18:22AM -0500, Rob Herring wrote:
> On Thu, Oct 4, 2018 at 3:36 AM Viresh Kumar <[email protected]> wrote:
> >
> > On 25-09-18, 14:43, Rob Herring wrote:
> > > On Tue, Sep 25, 2018 at 5:25 AM Rajendra Nayak <[email protected]> wrote:
> > > >
> > > > Hi Rob,
> > > >
> > > > []...
> > > > >>>>> + rpmhpd_opp_table: opp-table {
> > > > >>>>> + compatible = "operating-points-v2-qcom-level";
> > > > >>>>> +
> > > > >>>>> + rpmhpd_opp_ret: opp1 {
> > > > >>>>> + qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
> > > > >>>>> + };
> > > > >>>>
> > > > >>>> I don't see the point in using the OPP binding here when you aren't
> > > > >>>> using *any* of the properties from it.
> > > > >>>
> > > > >>> Yeah, that's the case for now. But there are cases (as Stephen
> > > > >>> mentioned earlier [1]) where the voltage values (and maybe other
> > > > >>> values like current, etc) would be known and filled in DT. And that's
> > > > >>> why we all agreed to use OPP tables for PM domains as well, as these
> > > > >>> are really "operating performance points" of these PM domains.
> > > > >>
> > > > >> Rob, are you fine with these bindings then?
> > > > >
> > > > > Okay, my only thought is whether we should just use 'reg' here, or do
> > > > > we need 'level' for anything else and should make it common?
> > > >
> > > > I am not quite sure I understood what you are suggesting here :(
> > >
> > > You could use the 'reg' property instead of 'qcom,level'. Any reason
> > > not to do that?
> >
> > They can use any property which uniquely identifies the OPP nodes in
> > the table. Though I never thought we can use 'reg' property in such a
> > way. I always thought it must be related to registers somehow :)
>
> That's almost certainly where the name originates from back in the
> 90s. I view 'reg' as how you identify or address a device. This can be
> channels of something like an ADC.
>
> It's perhaps a stretch for OPP nodes as they aren't really a device,
> but if the levels are part of the h/w then perhaps reg is a good
> match.
>

FWIW, I actually have a use case on qcom SoCs.

I'm working on reviving an old patch series from Stephen Boyd:
https://lkml.org/lkml/2015/9/18/833


Rajendra's Documentation/devicetree/bindings/opp/qcom-opp.txt currently has:

Required properties:
- qcom,level: On Qualcomm platforms an OPP node can describe a positive value
representing a corner/level that's communicated with a remote microprocessor
(usually called the RPM) which then translates it into a certain voltage on
a voltage rail


I'm planning on extending it with something like:

Optional properties:
-qcom,fuse-level: On Qualcomm platforms, not all corners/levels are real
corners/levels, i.e., not all corners/levels have a unique eFuse associated.
Usually more than one corner/level uses the same eFuse corner/level.


So for each OPP I would have:

opp1 {
qcom,level = <foo>;
qcom,fuse-level = <bar>;
}


Not sure if this changes your opinion about using reg,
but I thought that it was worth mentioning.


Kind regards,
Niklas

2018-10-04 22:18:19

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings

On Thu, Oct 4, 2018 at 2:17 PM Niklas Cassel <[email protected]> wrote:
>
> On Thu, Oct 04, 2018 at 10:18:22AM -0500, Rob Herring wrote:
> > On Thu, Oct 4, 2018 at 3:36 AM Viresh Kumar <[email protected]> wrote:
> > >
> > > On 25-09-18, 14:43, Rob Herring wrote:
> > > > On Tue, Sep 25, 2018 at 5:25 AM Rajendra Nayak <[email protected]> wrote:
> > > > >
> > > > > Hi Rob,
> > > > >
> > > > > []...
> > > > > >>>>> + rpmhpd_opp_table: opp-table {
> > > > > >>>>> + compatible = "operating-points-v2-qcom-level";
> > > > > >>>>> +
> > > > > >>>>> + rpmhpd_opp_ret: opp1 {
> > > > > >>>>> + qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
> > > > > >>>>> + };
> > > > > >>>>
> > > > > >>>> I don't see the point in using the OPP binding here when you aren't
> > > > > >>>> using *any* of the properties from it.
> > > > > >>>
> > > > > >>> Yeah, that's the case for now. But there are cases (as Stephen
> > > > > >>> mentioned earlier [1]) where the voltage values (and maybe other
> > > > > >>> values like current, etc) would be known and filled in DT. And that's
> > > > > >>> why we all agreed to use OPP tables for PM domains as well, as these
> > > > > >>> are really "operating performance points" of these PM domains.
> > > > > >>
> > > > > >> Rob, are you fine with these bindings then?
> > > > > >
> > > > > > Okay, my only thought is whether we should just use 'reg' here, or do
> > > > > > we need 'level' for anything else and should make it common?
> > > > >
> > > > > I am not quite sure I understood what you are suggesting here :(
> > > >
> > > > You could use the 'reg' property instead of 'qcom,level'. Any reason
> > > > not to do that?
> > >
> > > They can use any property which uniquely identifies the OPP nodes in
> > > the table. Though I never thought we can use 'reg' property in such a
> > > way. I always thought it must be related to registers somehow :)
> >
> > That's almost certainly where the name originates from back in the
> > 90s. I view 'reg' as how you identify or address a device. This can be
> > channels of something like an ADC.
> >
> > It's perhaps a stretch for OPP nodes as they aren't really a device,
> > but if the levels are part of the h/w then perhaps reg is a good
> > match.
> >
>
> FWIW, I actually have a use case on qcom SoCs.
>
> I'm working on reviving an old patch series from Stephen Boyd:
> https://lkml.org/lkml/2015/9/18/833
>
>
> Rajendra's Documentation/devicetree/bindings/opp/qcom-opp.txt currently has:
>
> Required properties:
> - qcom,level: On Qualcomm platforms an OPP node can describe a positive value
> representing a corner/level that's communicated with a remote microprocessor
> (usually called the RPM) which then translates it into a certain voltage on
> a voltage rail
>
>
> I'm planning on extending it with something like:
>
> Optional properties:
> -qcom,fuse-level: On Qualcomm platforms, not all corners/levels are real
> corners/levels, i.e., not all corners/levels have a unique eFuse associated.
> Usually more than one corner/level uses the same eFuse corner/level.

Is that because there's additional parameters not covered as part of a corner?

> So for each OPP I would have:
>
> opp1 {
> qcom,level = <foo>;
> qcom,fuse-level = <bar>;
> }
>
>
> Not sure if this changes your opinion about using reg,
> but I thought that it was worth mentioning.

'reg' is probably not the right fit then.

Does any of this fuse-level apply to platforms using this binding? If
so, then it should be incorporated here. I don't want incomplete
bindings that get one property added at a time.

Rob

2018-10-05 20:45:02

by Niklas Cassel

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] dt-bindings: power: Add qcom rpm power domain driver bindings

On Thu, Oct 04, 2018 at 05:17:42PM -0500, Rob Herring wrote:
> On Thu, Oct 4, 2018 at 2:17 PM Niklas Cassel <[email protected]> wrote:
> >
> > On Thu, Oct 04, 2018 at 10:18:22AM -0500, Rob Herring wrote:
> > > On Thu, Oct 4, 2018 at 3:36 AM Viresh Kumar <[email protected]> wrote:
> > > >
> > > > On 25-09-18, 14:43, Rob Herring wrote:
> > > > > On Tue, Sep 25, 2018 at 5:25 AM Rajendra Nayak <[email protected]> wrote:
> > > > > >
> > > > > > Hi Rob,
> > > > > >
> > > > > > []...
> > > > > > >>>>> + rpmhpd_opp_table: opp-table {
> > > > > > >>>>> + compatible = "operating-points-v2-qcom-level";
> > > > > > >>>>> +
> > > > > > >>>>> + rpmhpd_opp_ret: opp1 {
> > > > > > >>>>> + qcom,level = <RPMH_REGULATOR_LEVEL_RETENTION>;
> > > > > > >>>>> + };
> > > > > > >>>>
> > > > > > >>>> I don't see the point in using the OPP binding here when you aren't
> > > > > > >>>> using *any* of the properties from it.
> > > > > > >>>
> > > > > > >>> Yeah, that's the case for now. But there are cases (as Stephen
> > > > > > >>> mentioned earlier [1]) where the voltage values (and maybe other
> > > > > > >>> values like current, etc) would be known and filled in DT. And that's
> > > > > > >>> why we all agreed to use OPP tables for PM domains as well, as these
> > > > > > >>> are really "operating performance points" of these PM domains.
> > > > > > >>
> > > > > > >> Rob, are you fine with these bindings then?
> > > > > > >
> > > > > > > Okay, my only thought is whether we should just use 'reg' here, or do
> > > > > > > we need 'level' for anything else and should make it common?
> > > > > >
> > > > > > I am not quite sure I understood what you are suggesting here :(
> > > > >
> > > > > You could use the 'reg' property instead of 'qcom,level'. Any reason
> > > > > not to do that?
> > > >
> > > > They can use any property which uniquely identifies the OPP nodes in
> > > > the table. Though I never thought we can use 'reg' property in such a
> > > > way. I always thought it must be related to registers somehow :)
> > >
> > > That's almost certainly where the name originates from back in the
> > > 90s. I view 'reg' as how you identify or address a device. This can be
> > > channels of something like an ADC.
> > >
> > > It's perhaps a stretch for OPP nodes as they aren't really a device,
> > > but if the levels are part of the h/w then perhaps reg is a good
> > > match.
> > >
> >
> > FWIW, I actually have a use case on qcom SoCs.
> >
> > I'm working on reviving an old patch series from Stephen Boyd:
> > https://lkml.org/lkml/2015/9/18/833
> >
> >
> > Rajendra's Documentation/devicetree/bindings/opp/qcom-opp.txt currently has:
> >
> > Required properties:
> > - qcom,level: On Qualcomm platforms an OPP node can describe a positive value
> > representing a corner/level that's communicated with a remote microprocessor
> > (usually called the RPM) which then translates it into a certain voltage on
> > a voltage rail
> >
> >
> > I'm planning on extending it with something like:
> >
> > Optional properties:
> > -qcom,fuse-level: On Qualcomm platforms, not all corners/levels are real
> > corners/levels, i.e., not all corners/levels have a unique eFuse associated.
> > Usually more than one corner/level uses the same eFuse corner/level.
>
> Is that because there's additional parameters not covered as part of a corner?


Turns out that while qcom,fuse-level is a good idea for msm8916,
it will not suffice for msm8996.. Feel free to jump the the TL;DR below.


Looking at downstream, a corner is just something virtual:

https://source.codeaurora.org/quic/la/kernel/msm-3.10/tree/Documentation/devicetree/bindings/regulator/cpr-regulator.txt?h=msm-3.10#n362

In this example there are 9 virtual corners, but only 3 fuse-corners:

https://source.codeaurora.org/quic/la/kernel/msm-3.10/tree/arch/arm/boot/dts/qcom/msm8916-regulator.dtsi?h=msm-3.10#n90

qcom,cpr-corner-frequency-map = each frequency gets a virtual corner (probably
for simplicity).

qcom,cpr-corner-map = has a member for each virtual corner, defining what
fuse-corner each virtual corner really maps to.

Looking at the code:

https://source.codeaurora.org/quic/la/kernel/msm-3.10/tree/drivers/regulator/cpr-regulator.c?h=msm-3.10#n5460

These fuse-corners are really just efuses, where each fuse-corner
contains e.g. ref_uV, min_uV, max_uV.

>
> > So for each OPP I would have:
> >
> > opp1 {
> > qcom,level = <foo>;
> > qcom,fuse-level = <bar>;
> > }
> >
> >
> > Not sure if this changes your opinion about using reg,
> > but I thought that it was worth mentioning.
>
> 'reg' is probably not the right fit then.
>
> Does any of this fuse-level apply to platforms using this binding? If
> so, then it should be incorporated here. I don't want incomplete
> bindings that get one property added at a time.

This binding is new, but Rajendra uses it for RPM in msm8996 and sdm845.

RPM does not need the fuse-corner property. (Not sure why it doesn't.)

Looking at the downstream CPR DT bindings for msm8996, they still have
a fuse-corner for each corner. However, the DT binding has changed
compared to msm8916. They now have:

https://source.codeaurora.org/quic/la/kernel/msm-4.4/tree/arch/arm/boot/dts/qcom/msm8996-regulator.dtsi?h=msm-4.4#n646

qcom,cpr-corner-fmax-map = array for each fuse-corner, defining the
maximum virtual corner that this fuse-corner maps to.

Each speed bin has a different number of supported OPPs.

In upstream we use opp-supported-hw, together with the speedbin efuse,
to determine what subset of OPPs the hardware supports.

The problem with msm8996, compared to msm8916, is that each speed bin
has its own qcom,cpr-corner-fmax-map.

So for msm8996, it will not be enough to simply have a single
qcom,fuse-level property for each OPP.
We could add a qcom,fuse-level property for each speedbin, for each OPP.

Like this:

opp1 {
qcom,level = <foo>;
qcom-fuse-level-speed0 = <bar>;
qcom-fuse-level-speed1 = <bax>;
qcom-fuse-level-speed2 = <baz>;
}



TL;DR:

Perhaps I should just try to add something like
qcom,cpr-corner-fmax-map, where there is an array per speedbin,
to Documentation/devicetree/bindings/opp/qcom-opp.txt
Like "compatible", it could be a property in the opp-table node.

Something like:

qcom,speed-bins = <3>;
qcom,fuse-level-to-max-level-map =
/* Speed bin 0 */
<1 2 7 12 16>,

/* Speed bin 1 */
<1 2 7 12 13>,

/* Speed bin 2 */
<1 2 7 12 16>;

Since this would work for both msm8916 and msm8996.
And this way you could still change qcom,level to use
reg if you want.


Kind regards,
Niklas

2018-10-15 12:50:23

by Niklas Cassel

[permalink] [raw]
Subject: [RFC PATCH] dt-bindings: opp: Extend qcom-opp bindings with properties needed for CPR

Extend qcom-opp bindings with properties needed for Core Power Reduction
(CPR).

CPR is included in a great variety of Qualcomm SoC, e.g. msm8916 and
msm8996, and was first introduced in msm8974.

Signed-off-by: Niklas Cassel <[email protected]>
---
Hello Rob, Rajendra,

Sorry for not replying sooner.
Since Rob wanted the binding to be complete before merging,
this is my proposal to extend the OPP binding with properties
needed to support CPR (both for msm8916 and msm8996).
I've discussed the proposal with Viresh, and this proposal
seems better than what I previously suggested here:
https://lore.kernel.org/lkml/[email protected]/

.../devicetree/bindings/opp/qcom-opp.txt | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

diff --git a/Documentation/devicetree/bindings/opp/qcom-opp.txt b/Documentation/devicetree/bindings/opp/qcom-opp.txt
index db4d970c7ec7..3ab5dd84de86 100644
--- a/Documentation/devicetree/bindings/opp/qcom-opp.txt
+++ b/Documentation/devicetree/bindings/opp/qcom-opp.txt
@@ -23,3 +23,22 @@ Required properties:
representing a corner/level that's communicated with a remote microprocessor
(usually called the RPM) which then translates it into a certain voltage on
a voltage rail.
+
+Optional properties:
+- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer. Even
+ though a power domain doesn't need a opp-hz, there can be devices in the
+ power domain that need to know the highest supported frequency for each
+ corner/level (e.g. CPR), in order to properly initialize the hardware.
+
+- qcom,fuse-level: A positive value representing the fuse corner/level
+ associated with this OPP node. Sometimes several corners/levels shares
+ a certain fuse corner/level. A fuse corner/level contains e.g. ref uV,
+ min uV, and max uV.
+
+- qcom,fuse-level-<name>: Named qcom,fuse-level property. This is exactly
+ similar to the above qcom,fuse-level property, but allows multiple
+ fuse corners/levels to be provided for the same OPP. At runtime, the
+ platform can pick a <name> and matching qcom,fuse-level-<name> property
+ will be enabled for all OPPs. If the platform doesn't pick a specific
+ <name> or the <name> doesn't match with any qcom,fuse-level-<name>
+ properties, then qcom,fuse-level property shall be used, if present.
--
2.17.2


2018-10-22 05:52:54

by Viresh Kumar

[permalink] [raw]
Subject: Re: [RFC PATCH] dt-bindings: opp: Extend qcom-opp bindings with properties needed for CPR

On 15-10-18, 14:47, Niklas Cassel wrote:
> Extend qcom-opp bindings with properties needed for Core Power Reduction
> (CPR).
>
> CPR is included in a great variety of Qualcomm SoC, e.g. msm8916 and
> msm8996, and was first introduced in msm8974.
>
> Signed-off-by: Niklas Cassel <[email protected]>
> ---
> Hello Rob, Rajendra,
>
> Sorry for not replying sooner.
> Since Rob wanted the binding to be complete before merging,
> this is my proposal to extend the OPP binding with properties
> needed to support CPR (both for msm8916 and msm8996).
> I've discussed the proposal with Viresh, and this proposal
> seems better than what I previously suggested here:
> https://lore.kernel.org/lkml/[email protected]/
>
> .../devicetree/bindings/opp/qcom-opp.txt | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/opp/qcom-opp.txt b/Documentation/devicetree/bindings/opp/qcom-opp.txt
> index db4d970c7ec7..3ab5dd84de86 100644
> --- a/Documentation/devicetree/bindings/opp/qcom-opp.txt
> +++ b/Documentation/devicetree/bindings/opp/qcom-opp.txt
> @@ -23,3 +23,22 @@ Required properties:
> representing a corner/level that's communicated with a remote microprocessor
> (usually called the RPM) which then translates it into a certain voltage on
> a voltage rail.
> +
> +Optional properties:
> +- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer. Even
> + though a power domain doesn't need a opp-hz, there can be devices in the
> + power domain that need to know the highest supported frequency for each
> + corner/level (e.g. CPR), in order to properly initialize the hardware.
> +
> +- qcom,fuse-level: A positive value representing the fuse corner/level
> + associated with this OPP node. Sometimes several corners/levels shares
> + a certain fuse corner/level. A fuse corner/level contains e.g. ref uV,
> + min uV, and max uV.
> +
> +- qcom,fuse-level-<name>: Named qcom,fuse-level property. This is exactly
> + similar to the above qcom,fuse-level property, but allows multiple
> + fuse corners/levels to be provided for the same OPP. At runtime, the
> + platform can pick a <name> and matching qcom,fuse-level-<name> property
> + will be enabled for all OPPs. If the platform doesn't pick a specific
> + <name> or the <name> doesn't match with any qcom,fuse-level-<name>
> + properties, then qcom,fuse-level property shall be used, if present.

LGTM.

--
viresh

2018-11-05 23:18:24

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [RFC PATCH] dt-bindings: opp: Extend qcom-opp bindings with properties needed for CPR

On Mon, Oct 15, 2018 at 02:47:49PM +0200, Niklas Cassel wrote:
> Extend qcom-opp bindings with properties needed for Core Power Reduction
> (CPR).
>
> CPR is included in a great variety of Qualcomm SoC, e.g. msm8916 and
> msm8996, and was first introduced in msm8974.
>
> Signed-off-by: Niklas Cassel <[email protected]>
> ---
> Hello Rob, Rajendra,
>
> Sorry for not replying sooner.
> Since Rob wanted the binding to be complete before merging,
> this is my proposal to extend the OPP binding with properties
> needed to support CPR (both for msm8916 and msm8996).
> I've discussed the proposal with Viresh, and this proposal
> seems better than what I previously suggested here:
> https://lore.kernel.org/lkml/[email protected]/
>
> .../devicetree/bindings/opp/qcom-opp.txt | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/opp/qcom-opp.txt b/Documentation/devicetree/bindings/opp/qcom-opp.txt
> index db4d970c7ec7..3ab5dd84de86 100644
> --- a/Documentation/devicetree/bindings/opp/qcom-opp.txt
> +++ b/Documentation/devicetree/bindings/opp/qcom-opp.txt
> @@ -23,3 +23,22 @@ Required properties:
> representing a corner/level that's communicated with a remote microprocessor
> (usually called the RPM) which then translates it into a certain voltage on
> a voltage rail.

I've lost the context here. Please send this all together.

> +
> +Optional properties:
> +- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer. Even
> + though a power domain doesn't need a opp-hz, there can be devices in the
> + power domain that need to know the highest supported frequency for each
> + corner/level (e.g. CPR), in order to properly initialize the hardware.
> +
> +- qcom,fuse-level: A positive value representing the fuse corner/level
> + associated with this OPP node. Sometimes several corners/levels shares
> + a certain fuse corner/level. A fuse corner/level contains e.g. ref uV,
> + min uV, and max uV.
> +
> +- qcom,fuse-level-<name>: Named qcom,fuse-level property. This is exactly
> + similar to the above qcom,fuse-level property, but allows multiple
> + fuse corners/levels to be provided for the same OPP. At runtime, the
> + platform can pick a <name> and matching qcom,fuse-level-<name> property
> + will be enabled for all OPPs. If the platform doesn't pick a specific
> + <name> or the <name> doesn't match with any qcom,fuse-level-<name>
> + properties, then qcom,fuse-level property shall be used, if present.

We've generally moved away from having variable property names (gpio and
regulators are the big exceptions) as they are harder to parse.

I'm not clear why you'd need this. Just make qcom,fuse-level an array
and search each 'qcom,fuse-level' for the matching level number.

Rob

2018-11-09 16:40:57

by Niklas Cassel

[permalink] [raw]
Subject: Re: [RFC PATCH] dt-bindings: opp: Extend qcom-opp bindings with properties needed for CPR

On Mon, Nov 05, 2018 at 05:17:45PM -0600, Rob Herring wrote:
> On Mon, Oct 15, 2018 at 02:47:49PM +0200, Niklas Cassel wrote:
> > Extend qcom-opp bindings with properties needed for Core Power Reduction
> > (CPR).
> >
> > CPR is included in a great variety of Qualcomm SoC, e.g. msm8916 and
> > msm8996, and was first introduced in msm8974.
> >
> > Signed-off-by: Niklas Cassel <[email protected]>
> > ---
> > Hello Rob, Rajendra,
> >
> > Sorry for not replying sooner.
> > Since Rob wanted the binding to be complete before merging,
> > this is my proposal to extend the OPP binding with properties
> > needed to support CPR (both for msm8916 and msm8996).
> > I've discussed the proposal with Viresh, and this proposal
> > seems better than what I previously suggested here:
> > https://lore.kernel.org/lkml/[email protected]/
> >
> > .../devicetree/bindings/opp/qcom-opp.txt | 19 +++++++++++++++++++
> > 1 file changed, 19 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/opp/qcom-opp.txt b/Documentation/devicetree/bindings/opp/qcom-opp.txt
> > index db4d970c7ec7..3ab5dd84de86 100644
> > --- a/Documentation/devicetree/bindings/opp/qcom-opp.txt
> > +++ b/Documentation/devicetree/bindings/opp/qcom-opp.txt
> > @@ -23,3 +23,22 @@ Required properties:
> > representing a corner/level that's communicated with a remote microprocessor
> > (usually called the RPM) which then translates it into a certain voltage on
> > a voltage rail.
>
> I've lost the context here. Please send this all together.

Will do, as soon as I've gotten your feedback on this mail.

>
> > +
> > +Optional properties:
> > +- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer. Even
> > + though a power domain doesn't need a opp-hz, there can be devices in the
> > + power domain that need to know the highest supported frequency for each
> > + corner/level (e.g. CPR), in order to properly initialize the hardware.
> > +
> > +- qcom,fuse-level: A positive value representing the fuse corner/level
> > + associated with this OPP node. Sometimes several corners/levels shares
> > + a certain fuse corner/level. A fuse corner/level contains e.g. ref uV,
> > + min uV, and max uV.
> > +
> > +- qcom,fuse-level-<name>: Named qcom,fuse-level property. This is exactly
> > + similar to the above qcom,fuse-level property, but allows multiple
> > + fuse corners/levels to be provided for the same OPP. At runtime, the
> > + platform can pick a <name> and matching qcom,fuse-level-<name> property
> > + will be enabled for all OPPs. If the platform doesn't pick a specific
> > + <name> or the <name> doesn't match with any qcom,fuse-level-<name>
> > + properties, then qcom,fuse-level property shall be used, if present.
>
> We've generally moved away from having variable property names (gpio and
> regulators are the big exceptions) as they are harder to parse.
>
> I'm not clear why you'd need this. Just make qcom,fuse-level an array
> and search each 'qcom,fuse-level' for the matching level number.

This was my first thought as well, but then Viresh told me that the OPP
framework already has logic for parsing and using this.

If we call dev_pm_opp_set_prop_name(<name>)

We will automatically use all the named-properties with that suffix (e.g.):
opp-microvolt-<name>
opp-microamp-<name>
opp-fuse-corner-<name>

if and only if they exist, otherwise the regular properties will be used:
opp-microvolt
opp-microamp
opp-fuse-corner

This also means that not all OPPs will need the named variants,
e.g. if all the speedbins have the same fuse-corner:
opp-fuse-corner-speedbin0 = <1>;
opp-fuse-corner-speedbin1 = <1>;
opp-fuse-corner-speedbin2 = <1>;
this can simplified to:
opp-fuse-corner = <1>;


Another reason why I think that using named-properties might be good is
because I recently found out that certain Qualcomm SoCs have several fuse
revisions for each speedbin, e.g. msm8996 SG has 8 fuse revisions per
speedbin:
https://source.codeaurora.org/quic/la/kernel/msm-3.18/tree/arch/arm/boot/dts/qcom/msm8996pro.dtsi?h=msm-3.18#n62
https://source.codeaurora.org/quic/la/kernel/msm-3.18/tree/drivers/regulator/cpr3-hmss-regulator.c?h=msm-3.18#n88

Which means that some SoCs (in worst case) will actually need:
opp-fuse-corner-speedbin0-rev0 = <x>;
opp-fuse-corner-speedbin0-rev1 = <x>;
opp-fuse-corner-speedbin0-rev2 = <x>;
opp-fuse-corner-speedbin0-rev3 = <x>;
opp-fuse-corner-speedbin0-rev4 = <x>;
opp-fuse-corner-speedbin0-rev5 = <x>;
opp-fuse-corner-speedbin0-rev6 = <x>;
opp-fuse-corner-speedbin0-rev7 = <x>;
opp-fuse-corner-speedbin1-rev0 = <x>;
opp-fuse-corner-speedbin1-rev1 = <x>;
opp-fuse-corner-speedbin1-rev2 = <x>;
opp-fuse-corner-speedbin1-rev3 = <x>;
opp-fuse-corner-speedbin1-rev4 = <x>;
opp-fuse-corner-speedbin1-rev5 = <x>;
opp-fuse-corner-speedbin1-rev6 = <x>;
opp-fuse-corner-speedbin1-rev7 = <x>;
opp-fuse-corner-speedbin2-rev0 = <x>;
opp-fuse-corner-speedbin2-rev1 = <x>;
opp-fuse-corner-speedbin2-rev2 = <x>;
opp-fuse-corner-speedbin2-rev3 = <x>;
opp-fuse-corner-speedbin2-rev4 = <x>;
opp-fuse-corner-speedbin2-rev5 = <x>;
opp-fuse-corner-speedbin2-rev6 = <x>;
opp-fuse-corner-speedbin2-rev7 = <x>;

For each OPP.
Fortunately, it's not always this messy, some SoCs only have a single
fuse revision.
I think that having named-properties probably helps if more speedbins or
fuse-revisions are added.


I guess the alternative would be to do like downstream, where they have a
bunch of arrays instead, but then we wouldn't be able to use the logic
from the OPP framework.

qcom,cpr-corner-fmax-map =
/* Speed bin 0 */
<1 6 9 14 19>, //fuse rev0
<1 6 9 14 19>, //fuse rev1
<3 6 9 14 19>, //fuse rev2
<3 6 9 14 19>, //fuse rev3
<3 6 9 14 19>, //fuse rev4
<3 6 9 14 19>, //fuse rev5
<3 6 9 14 19>, //fuse rev6
<3 6 9 14 19>, //fuse rev7

/* Speed bin 1 */
<1 6 9 14 19>, //fuse rev0
<1 6 9 14 19>, //fuse rev1
<3 6 9 14 19>, //fuse rev2
<3 6 9 14 19>, //fuse rev3
<3 6 9 14 19>, //fuse rev4
<3 6 9 14 19>, //fuse rev5
<3 6 9 14 19>, //fuse rev6
<3 6 9 14 19>, //fuse rev7

/* Speed bin 2 */
<1 6 9 14 19>, //fuse rev0
<1 6 9 14 19>, //fuse rev1
<3 6 9 14 19>, //fuse rev2
<3 6 9 14 19>, //fuse rev3
<3 6 9 14 19>, //fuse rev4
<3 6 9 14 19>, //fuse rev5
<3 6 9 14 19>, //fuse rev6
<3 6 9 14 19>; //fuse rev7


Kind regards,
Niklas

2018-11-20 04:13:22

by Rajendra Nayak

[permalink] [raw]
Subject: Re: [RFC PATCH] dt-bindings: opp: Extend qcom-opp bindings with properties needed for CPR



On 11/9/2018 10:09 PM, Niklas Cassel wrote:
> On Mon, Nov 05, 2018 at 05:17:45PM -0600, Rob Herring wrote:
>> On Mon, Oct 15, 2018 at 02:47:49PM +0200, Niklas Cassel wrote:
>>> Extend qcom-opp bindings with properties needed for Core Power Reduction
>>> (CPR).
>>>
>>> CPR is included in a great variety of Qualcomm SoC, e.g. msm8916 and
>>> msm8996, and was first introduced in msm8974.
>>>
>>> Signed-off-by: Niklas Cassel <[email protected]>
>>> ---
>>> Hello Rob, Rajendra,
>>>
>>> Sorry for not replying sooner.
>>> Since Rob wanted the binding to be complete before merging,
>>> this is my proposal to extend the OPP binding with properties
>>> needed to support CPR (both for msm8916 and msm8996).
>>> I've discussed the proposal with Viresh, and this proposal
>>> seems better than what I previously suggested here:
>>> https://lore.kernel.org/lkml/[email protected]/
>>>
>>> .../devicetree/bindings/opp/qcom-opp.txt | 19 +++++++++++++++++++
>>> 1 file changed, 19 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/opp/qcom-opp.txt b/Documentation/devicetree/bindings/opp/qcom-opp.txt
>>> index db4d970c7ec7..3ab5dd84de86 100644
>>> --- a/Documentation/devicetree/bindings/opp/qcom-opp.txt
>>> +++ b/Documentation/devicetree/bindings/opp/qcom-opp.txt
>>> @@ -23,3 +23,22 @@ Required properties:
>>> representing a corner/level that's communicated with a remote microprocessor
>>> (usually called the RPM) which then translates it into a certain voltage on
>>> a voltage rail.
>>
>> I've lost the context here. Please send this all together.
>
> Will do, as soon as I've gotten your feedback on this mail.

Niklas, are you still waiting for feedback on this mail from Rob?

2018-11-20 17:55:10

by Niklas Cassel

[permalink] [raw]
Subject: Re: [RFC PATCH] dt-bindings: opp: Extend qcom-opp bindings with properties needed for CPR

On Tue, Nov 20, 2018 at 09:42:05AM +0530, Rajendra Nayak wrote:
>
>
> On 11/9/2018 10:09 PM, Niklas Cassel wrote:
> > On Mon, Nov 05, 2018 at 05:17:45PM -0600, Rob Herring wrote:
> > > On Mon, Oct 15, 2018 at 02:47:49PM +0200, Niklas Cassel wrote:
> > > > Extend qcom-opp bindings with properties needed for Core Power Reduction
> > > > (CPR).
> > > >
> > > > CPR is included in a great variety of Qualcomm SoC, e.g. msm8916 and
> > > > msm8996, and was first introduced in msm8974.
> > > >
> > > > Signed-off-by: Niklas Cassel <[email protected]>
> > > > ---
> > > > Hello Rob, Rajendra,
> > > >
> > > > Sorry for not replying sooner.
> > > > Since Rob wanted the binding to be complete before merging,
> > > > this is my proposal to extend the OPP binding with properties
> > > > needed to support CPR (both for msm8916 and msm8996).
> > > > I've discussed the proposal with Viresh, and this proposal
> > > > seems better than what I previously suggested here:
> > > > https://lore.kernel.org/lkml/[email protected]/
> > > >
> > > > .../devicetree/bindings/opp/qcom-opp.txt | 19 +++++++++++++++++++
> > > > 1 file changed, 19 insertions(+)
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/opp/qcom-opp.txt b/Documentation/devicetree/bindings/opp/qcom-opp.txt
> > > > index db4d970c7ec7..3ab5dd84de86 100644
> > > > --- a/Documentation/devicetree/bindings/opp/qcom-opp.txt
> > > > +++ b/Documentation/devicetree/bindings/opp/qcom-opp.txt
> > > > @@ -23,3 +23,22 @@ Required properties:
> > > > representing a corner/level that's communicated with a remote microprocessor
> > > > (usually called the RPM) which then translates it into a certain voltage on
> > > > a voltage rail.
> > >
> > > I've lost the context here. Please send this all together.
> >
> > Will do, as soon as I've gotten your feedback on this mail.
>
> Niklas, are you still waiting for feedback on this mail from Rob?

Yes.

Rajendra, I realize that your patches have been ready for merging for
a long time, and this fuse-level is quite complex, so the discussion
has been taken longer than expected. Sorry for that.

Hopefully Rob will reply soon, or perhaps he could agree to merge your
binding as is, and I could extend it later, when we have reached a
consensus.


Kind regards,
Niklas

2018-11-27 05:56:51

by Rajendra Nayak

[permalink] [raw]
Subject: Re: [RFC PATCH] dt-bindings: opp: Extend qcom-opp bindings with properties needed for CPR


On 11/20/2018 9:44 PM, Niklas Cassel wrote:
> On Tue, Nov 20, 2018 at 09:42:05AM +0530, Rajendra Nayak wrote:
>>
>>
>> On 11/9/2018 10:09 PM, Niklas Cassel wrote:
>>> On Mon, Nov 05, 2018 at 05:17:45PM -0600, Rob Herring wrote:
>>>> On Mon, Oct 15, 2018 at 02:47:49PM +0200, Niklas Cassel wrote:
>>>>> Extend qcom-opp bindings with properties needed for Core Power Reduction
>>>>> (CPR).
>>>>>
>>>>> CPR is included in a great variety of Qualcomm SoC, e.g. msm8916 and
>>>>> msm8996, and was first introduced in msm8974.
>>>>>
>>>>> Signed-off-by: Niklas Cassel <[email protected]>
>>>>> ---
>>>>> Hello Rob, Rajendra,
>>>>>
>>>>> Sorry for not replying sooner.
>>>>> Since Rob wanted the binding to be complete before merging,
>>>>> this is my proposal to extend the OPP binding with properties
>>>>> needed to support CPR (both for msm8916 and msm8996).
>>>>> I've discussed the proposal with Viresh, and this proposal
>>>>> seems better than what I previously suggested here:
>>>>> https://lore.kernel.org/lkml/[email protected]/
>>>>>
>>>>> .../devicetree/bindings/opp/qcom-opp.txt | 19 +++++++++++++++++++
>>>>> 1 file changed, 19 insertions(+)
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/opp/qcom-opp.txt b/Documentation/devicetree/bindings/opp/qcom-opp.txt
>>>>> index db4d970c7ec7..3ab5dd84de86 100644
>>>>> --- a/Documentation/devicetree/bindings/opp/qcom-opp.txt
>>>>> +++ b/Documentation/devicetree/bindings/opp/qcom-opp.txt
>>>>> @@ -23,3 +23,22 @@ Required properties:
>>>>> representing a corner/level that's communicated with a remote microprocessor
>>>>> (usually called the RPM) which then translates it into a certain voltage on
>>>>> a voltage rail.
>>>>
>>>> I've lost the context here. Please send this all together.
>>>
>>> Will do, as soon as I've gotten your feedback on this mail.
>>
>> Niklas, are you still waiting for feedback on this mail from Rob?
>
> Yes.

Rob, did you have any further feedback for Niklas based on his binding proposal?

>
> Rajendra, I realize that your patches have been ready for merging for
> a long time, and this fuse-level is quite complex, so the discussion
> has been taken longer than expected. Sorry for that.
>
> Hopefully Rob will reply soon, or perhaps he could agree to merge your
> binding as is, and I could extend it later, when we have reached a
> consensus.

Or should we merge the qcom,level binding for now (since I though we agreed
'reg' is probably not the right fit for it) and then discuss further on how to
describe the legacy platforms which require more details like fuse bindings?
Note that the current platform (sdm845) only needs the qcom,level binding.
What Niklas is proposing is for describing the older SoCs.