linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 0/3] Add support for SCMI-Regulator
@ 2020-11-23 20:23 Cristian Marussi
  2020-11-23 20:23 ` [PATCH v7 1/3] dt-bindings: arm: remove optional properties for SCMI Regulators Cristian Marussi
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Cristian Marussi @ 2020-11-23 20:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree
  Cc: sudeep.holla, lukasz.luba, james.quinlan, Jonathan.Cameron,
	broonie, robh, satyakim, etienne.carriere, f.fainelli,
	vincent.guittot, souvik.chakravarty, Cristian Marussi

Hi,

this series introduces the support for a new generic SCMI Regulator driver
developed on top of the recently introduced SCMI Voltage Domain Protocol
support as specified in the upcoming SCMIv3.0 specification. [1]

The underlying SCMI VD Protocol support, which was originally part of this
series, is now applied on for-next/scmi-voltage [2], and this series,
reduced to its SCMI Regulator support and dt-bindings fixes is similarly
based on top of [2]:

commit ec8838193695 ("firmware: arm_scmi: Add support to enumerated SCMI
		      voltage domain device")

Thanks,

Cristian

---
v6 --> v7
- rebased on top of for-next/scmi-voltage
- added dt-bindings fix to remove optional properties
- add proper blank lines between semantic blocks
- fix return value on error path of scmi_reg_is_enabled()
- use generic Failure message on err path of info_get()
- fix comment containing apostrophe

v5 --> v6
- reordered dt bindings patch
- removed single field struct
- reviewed args to scmi_init_voltage_levels()
- allocating scmi_voltage_info_array contiguously

v4 --> v5
- rebased
- VD Protocol
 - removed inline
 - moved segmented intervals defines
 - fixed some macros complaints by checkpatch

v3 --> v4
- DT bindings
 - using generic node names
 - listing explicitly subset of supported regulators bindings
- SCMI Regulator
 - using of_match_full_name core regulator flag
 - avoid coccinelle false flag complaints
- VD Protocol
 - avoid coccinelle false flag complaints
 - avoiding fixed size typing

v2 --> v3
- DT bindings
  - avoid awkard examples based on _cpu/_gpu regulators
- SCMI Regulator
  - remove multiple linear mappings support
  - removed duplicated voltage name printout
  - added a few comments
  - simplified return path in scmi_reg_set_voltage_sel()
- VD Protocol
  - restrict segmented voltage domain descriptors to one triplet
  - removed unneeded inline
  - free allocated resources for invalid voltage domain
  - added __must_check to info_get voltage operations
  - added a few comments
  - removed fixed size typing from struct voltage_info
    
v1 --> v2
- rebased on for-next/scmi v5.10
- DT bindings
  - removed any reference to negative voltages
- SCMI Regulator
  - removed duplicate regulator naming
  - removed redundant .get/set_voltage ops: only _sel variants implemented
  - removed condexpr on fail path to increase readability
- VD Protocol
  - fix voltage levels query loop to reload full cmd description
    between iterations as reported by Etienne Carriere
  - ensure transport rx buffer is properly sized calli scmi_reset_rx_to_maxsz
    between transfers

[1]:https://developer.arm.com/documentation/den0056/c/
[2]:https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/log/?h=for-next/scmi-voltage

Cristian Marussi (3):
  dt-bindings: arm: remove optional properties for SCMI Regulators
  regulator: core: add of_match_full_name boolean flag
  regulator: add SCMI driver

 .../devicetree/bindings/arm/arm,scmi.txt      |  11 +-
 drivers/regulator/Kconfig                     |   9 +
 drivers/regulator/Makefile                    |   1 +
 drivers/regulator/of_regulator.c              |   8 +-
 drivers/regulator/scmi-regulator.c            | 417 ++++++++++++++++++
 include/linux/regulator/driver.h              |   3 +
 6 files changed, 437 insertions(+), 12 deletions(-)
 create mode 100644 drivers/regulator/scmi-regulator.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v7 1/3] dt-bindings: arm: remove optional properties for SCMI Regulators
  2020-11-23 20:23 [PATCH v7 0/3] Add support for SCMI-Regulator Cristian Marussi
@ 2020-11-23 20:23 ` Cristian Marussi
  2020-11-23 20:23 ` [PATCH v7 2/3] regulator: core: add of_match_full_name boolean flag Cristian Marussi
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Cristian Marussi @ 2020-11-23 20:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree
  Cc: sudeep.holla, lukasz.luba, james.quinlan, Jonathan.Cameron,
	broonie, robh, satyakim, etienne.carriere, f.fainelli,
	vincent.guittot, souvik.chakravarty, Cristian Marussi

Remove optional properties bindings descriptions for SCMI Regulators.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 Documentation/devicetree/bindings/arm/arm,scmi.txt | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/arm,scmi.txt b/Documentation/devicetree/bindings/arm/arm,scmi.txt
index 6e011ca97079..b5ce5b39bb9c 100644
--- a/Documentation/devicetree/bindings/arm/arm,scmi.txt
+++ b/Documentation/devicetree/bindings/arm/arm,scmi.txt
@@ -71,20 +71,11 @@ It does not support any current operation.
 SCMI Regulators are grouped under a 'regulators' node which in turn is a child
 of the SCMI Voltage protocol node inside the desired SCMI instance node.
 
-This binding uses the common regulator binding[6] but, due to SCMI abstractions,
-supports only a subset of its properties as specified below amongst Optional
-properties.
+This binding uses the common regulator binding[6].
 
 Required properties:
  - reg : shall identify an existent SCMI Voltage Domain.
 
-Optional properties:
- - regulator-name
- - regulator-min-microvolt / regulator-max-microvolt
- - regulator-always-on / regulator-boot-on
- - regulator-max-step-microvolt
- - regulator-coupled-with / regulator-coupled-max-spread
-
 Sensor bindings for the sensors based on SCMI Message Protocol
 --------------------------------------------------------------
 SCMI provides an API to access the various sensors on the SoC.
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v7 2/3] regulator: core: add of_match_full_name boolean flag
  2020-11-23 20:23 [PATCH v7 0/3] Add support for SCMI-Regulator Cristian Marussi
  2020-11-23 20:23 ` [PATCH v7 1/3] dt-bindings: arm: remove optional properties for SCMI Regulators Cristian Marussi
@ 2020-11-23 20:23 ` Cristian Marussi
  2020-11-23 20:23 ` [PATCH v7 3/3] regulator: add SCMI driver Cristian Marussi
  2020-11-23 21:46 ` [PATCH v7 0/3] Add support for SCMI-Regulator Mark Brown
  3 siblings, 0 replies; 5+ messages in thread
From: Cristian Marussi @ 2020-11-23 20:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree
  Cc: sudeep.holla, lukasz.luba, james.quinlan, Jonathan.Cameron,
	broonie, robh, satyakim, etienne.carriere, f.fainelli,
	vincent.guittot, souvik.chakravarty, Cristian Marussi

During regulators registration, if .of_match and .regulators_node are
defined as non-null strings in struct regulator_desc the core searches the
DT subtree rooted at .regulators_node trying to match, at first, .of_match
against the 'regulator-compatible' property and, then, falling back to use
the name of the node itself to determine a good match.

Property 'regulator-compatible', though, is now deprecated and falling back
to match against the node name, works fine only as long as the involved
nodes are named in an unique way across the searched subtree; if that's not
the case, like when using <common-name>@<unit> style naming for properties
indexed via 'reg' property (as advised by the standard), the above matching
mechanism based on the simple common name will lead to multiple matches and
the only viable alternative would be to properly define the now deprecated
'regulator-compatible' as the node full name, i.e. <common-name>@<unit>.

In order to address this case without using such deprecated binding, define
a new boolean flag .of_match_full_name in struct regulator_desc to force
the core to match against the node full-name instead of the plain name.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 drivers/regulator/of_regulator.c | 8 ++++++--
 include/linux/regulator/driver.h | 3 +++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 06c0b15fe4c0..564f928eb1db 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -413,8 +413,12 @@ device_node *regulator_of_get_init_node(struct device *dev,
 
 	for_each_available_child_of_node(search, child) {
 		name = of_get_property(child, "regulator-compatible", NULL);
-		if (!name)
-			name = child->name;
+		if (!name) {
+			if (!desc->of_match_full_name)
+				name = child->name;
+			else
+				name = child->full_name;
+		}
 
 		if (!strcmp(desc->of_match, name)) {
 			of_node_put(search);
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 11cade73726c..d7c77ee370f3 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -223,6 +223,8 @@ enum regulator_type {
  * @name: Identifying name for the regulator.
  * @supply_name: Identifying the regulator supply
  * @of_match: Name used to identify regulator in DT.
+ * @of_match_full_name: A flag to indicate that the of_match string, if
+ *			present, should be matched against the node full_name.
  * @regulators_node: Name of node containing regulator definitions in DT.
  * @of_parse_cb: Optional callback called only if of_match is present.
  *               Will be called for each regulator parsed from DT, during
@@ -314,6 +316,7 @@ struct regulator_desc {
 	const char *name;
 	const char *supply_name;
 	const char *of_match;
+	bool of_match_full_name;
 	const char *regulators_node;
 	int (*of_parse_cb)(struct device_node *,
 			    const struct regulator_desc *,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v7 3/3] regulator: add SCMI driver
  2020-11-23 20:23 [PATCH v7 0/3] Add support for SCMI-Regulator Cristian Marussi
  2020-11-23 20:23 ` [PATCH v7 1/3] dt-bindings: arm: remove optional properties for SCMI Regulators Cristian Marussi
  2020-11-23 20:23 ` [PATCH v7 2/3] regulator: core: add of_match_full_name boolean flag Cristian Marussi
@ 2020-11-23 20:23 ` Cristian Marussi
  2020-11-23 21:46 ` [PATCH v7 0/3] Add support for SCMI-Regulator Mark Brown
  3 siblings, 0 replies; 5+ messages in thread
From: Cristian Marussi @ 2020-11-23 20:23 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, devicetree
  Cc: sudeep.holla, lukasz.luba, james.quinlan, Jonathan.Cameron,
	broonie, robh, satyakim, etienne.carriere, f.fainelli,
	vincent.guittot, souvik.chakravarty, Cristian Marussi

Add a simple regulator based on SCMI Voltage Domain Protocol.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
----
v6 --> v7
- add proper blank lines between semantic blocks
- fix return value on error path of scmi_reg_is_enabled()
- use generic Failure message on err path of info_get()
- fix comment containing apostrophe

v3 --> v4
- using of_match_full_name core regulator flag
- avoid coccinelle falde complaints about pointer-sized allocations

v2 --> v3
- remove multiple linear mappings support
- removed duplicated voltage name printout
- added a few comments
- simplified return path in scmi_reg_set_voltage_sel()

v1 --> v2
- removed duplicate regulator naming
- removed redundant .get/set_voltage ops: only _sel variants implemented
- removed condexpr on fail path to increase readability

v0 --> v1
- fixed init_data constraint parsing
- fixes for v5.8 (linear_range.h)
- fixed commit message content and subject line format
- factored out SCMI core specific changes to distinct patch
- reworked Kconfig and Makefile to keep proper alphabetic order
- fixed SPDX comment style
- removed unneeded inline functions
- reworked conditionals for legibility
- fixed some return paths to properly report SCMI original errors codes
- added some more descriptive error messages when fw returns invalid ranges
- removed unneeded explicit devm_regulator_unregister from .remove()
---
 drivers/regulator/Kconfig          |   9 +
 drivers/regulator/Makefile         |   1 +
 drivers/regulator/scmi-regulator.c | 417 +++++++++++++++++++++++++++++
 3 files changed, 427 insertions(+)
 create mode 100644 drivers/regulator/scmi-regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 020a00d6696b..5617c56fbe9b 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -155,6 +155,15 @@ config REGULATOR_ARIZONA_MICSUPP
 	  and Wolfson Microelectronic Arizona codecs
 	  devices.
 
+config REGULATOR_ARM_SCMI
+	tristate "SCMI based regulator driver"
+	depends on ARM_SCMI_PROTOCOL && OF
+	help
+	  This adds the regulator driver support for ARM platforms using SCMI
+	  protocol for device voltage management.
+	  This driver uses SCMI Message Protocol driver to interact with the
+	  firmware providing the device Voltage functionality.
+
 config REGULATOR_AS3711
 	tristate "AS3711 PMIC"
 	depends on MFD_AS3711
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 6ebae516258e..aeed0b6079b2 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
 obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA_LDO1) += arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_ARIZONA_MICSUPP) += arizona-micsupp.o
+obj-$(CONFIG_REGULATOR_ARM_SCMI) += scmi-regulator.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
 obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
diff --git a/drivers/regulator/scmi-regulator.c b/drivers/regulator/scmi-regulator.c
new file mode 100644
index 000000000000..0e8b3caa8146
--- /dev/null
+++ b/drivers/regulator/scmi-regulator.c
@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// System Control and Management Interface (SCMI) based regulator driver
+//
+// Copyright (C) 2020 ARM Ltd.
+//
+// Implements a regulator driver on top of the SCMI Voltage Protocol.
+//
+// The ARM SCMI Protocol aims in general to hide as much as possible all the
+// underlying operational details while providing an abstracted interface for
+// its users to operate upon: as a consequence the resulting operational
+// capabilities and configurability of this regulator device are much more
+// limited than the ones usually available on a standard physical regulator.
+//
+// The supported SCMI regulator ops are restricted to the bare minimum:
+//
+//  - 'status_ops': enable/disable/is_enabled
+//  - 'voltage_ops': get_voltage_sel/set_voltage_sel
+//		     list_voltage/map_voltage
+//
+// Each SCMI regulator instance is associated, through the means of a proper DT
+// entry description, to a specific SCMI Voltage Domain.
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/linear_range.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/scmi_protocol.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+struct scmi_regulator {
+	u32 id;
+	struct scmi_device *sdev;
+	struct regulator_dev *rdev;
+	struct device_node *of_node;
+	struct regulator_desc desc;
+	struct regulator_config conf;
+};
+
+struct scmi_regulator_info {
+	int num_doms;
+	struct scmi_regulator **sregv;
+};
+
+static int scmi_reg_enable(struct regulator_dev *rdev)
+{
+	struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
+	const struct scmi_handle *handle = sreg->sdev->handle;
+
+	return handle->voltage_ops->config_set(handle, sreg->id,
+					       SCMI_VOLTAGE_ARCH_STATE_ON);
+}
+
+static int scmi_reg_disable(struct regulator_dev *rdev)
+{
+	struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
+	const struct scmi_handle *handle = sreg->sdev->handle;
+
+	return handle->voltage_ops->config_set(handle, sreg->id,
+					       SCMI_VOLTAGE_ARCH_STATE_OFF);
+}
+
+static int scmi_reg_is_enabled(struct regulator_dev *rdev)
+{
+	int ret;
+	u32 config;
+	struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
+	const struct scmi_handle *handle = sreg->sdev->handle;
+
+	ret = handle->voltage_ops->config_get(handle, sreg->id,
+					      &config);
+	if (ret) {
+		dev_err(&sreg->sdev->dev,
+			"Error %d reading regulator %s status.\n",
+			ret, sreg->desc.name);
+		return ret;
+	}
+
+	return config & SCMI_VOLTAGE_ARCH_STATE_ON;
+}
+
+static int scmi_reg_get_voltage_sel(struct regulator_dev *rdev)
+{
+	int ret;
+	s32 volt_uV;
+	struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
+	const struct scmi_handle *handle = sreg->sdev->handle;
+
+	ret = handle->voltage_ops->level_get(handle, sreg->id, &volt_uV);
+	if (ret)
+		return ret;
+
+	return sreg->desc.ops->map_voltage(rdev, volt_uV, volt_uV);
+}
+
+static int scmi_reg_set_voltage_sel(struct regulator_dev *rdev,
+				    unsigned int selector)
+{
+	s32 volt_uV;
+	struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
+	const struct scmi_handle *handle = sreg->sdev->handle;
+
+	volt_uV = sreg->desc.ops->list_voltage(rdev, selector);
+	if (volt_uV <= 0)
+		return -EINVAL;
+
+	return handle->voltage_ops->level_set(handle, sreg->id, 0x0, volt_uV);
+}
+
+static const struct regulator_ops scmi_reg_fixed_ops = {
+	.enable = scmi_reg_enable,
+	.disable = scmi_reg_disable,
+	.is_enabled = scmi_reg_is_enabled,
+};
+
+static const struct regulator_ops scmi_reg_linear_ops = {
+	.enable = scmi_reg_enable,
+	.disable = scmi_reg_disable,
+	.is_enabled = scmi_reg_is_enabled,
+	.get_voltage_sel = scmi_reg_get_voltage_sel,
+	.set_voltage_sel = scmi_reg_set_voltage_sel,
+	.list_voltage = regulator_list_voltage_linear,
+	.map_voltage = regulator_map_voltage_linear,
+};
+
+static const struct regulator_ops scmi_reg_discrete_ops = {
+	.enable = scmi_reg_enable,
+	.disable = scmi_reg_disable,
+	.is_enabled = scmi_reg_is_enabled,
+	.get_voltage_sel = scmi_reg_get_voltage_sel,
+	.set_voltage_sel = scmi_reg_set_voltage_sel,
+	.list_voltage = regulator_list_voltage_table,
+	.map_voltage = regulator_map_voltage_iterate,
+};
+
+static int
+scmi_config_linear_regulator_mappings(struct scmi_regulator *sreg,
+				      const struct scmi_voltage_info *vinfo)
+{
+	s32 delta_uV;
+
+	/*
+	 * Note that SCMI voltage domains describable by linear ranges
+	 * (segments) {low, high, step} are guaranteed to come in one single
+	 * triplet by the SCMI Voltage Domain protocol support itself.
+	 */
+
+	delta_uV = (vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_HIGH] -
+			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW]);
+
+	/* Rule out buggy negative-intervals answers from fw */
+	if (delta_uV < 0) {
+		dev_err(&sreg->sdev->dev,
+			"Invalid volt-range %d-%duV for domain %d\n",
+			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW],
+			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_HIGH],
+			sreg->id);
+		return -EINVAL;
+	}
+
+	if (!delta_uV) {
+		/* Just one fixed voltage exposed by SCMI */
+		sreg->desc.fixed_uV =
+			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW];
+		sreg->desc.n_voltages = 1;
+		sreg->desc.ops = &scmi_reg_fixed_ops;
+	} else {
+		/* One simple linear mapping. */
+		sreg->desc.min_uV =
+			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW];
+		sreg->desc.uV_step =
+			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_STEP];
+		sreg->desc.linear_min_sel = 0;
+		sreg->desc.n_voltages = delta_uV / sreg->desc.uV_step;
+		sreg->desc.ops = &scmi_reg_linear_ops;
+	}
+
+	return 0;
+}
+
+static int
+scmi_config_discrete_regulator_mappings(struct scmi_regulator *sreg,
+					const struct scmi_voltage_info *vinfo)
+{
+	/* Discrete non linear levels are mapped to volt_table */
+	sreg->desc.n_voltages = vinfo->num_levels;
+
+	if (sreg->desc.n_voltages > 1) {
+		sreg->desc.volt_table = (const unsigned int *)vinfo->levels_uv;
+		sreg->desc.ops = &scmi_reg_discrete_ops;
+	} else {
+		sreg->desc.fixed_uV = vinfo->levels_uv[0];
+		sreg->desc.ops = &scmi_reg_fixed_ops;
+	}
+
+	return 0;
+}
+
+static int scmi_regulator_common_init(struct scmi_regulator *sreg)
+{
+	int ret;
+	const struct scmi_handle *handle = sreg->sdev->handle;
+	struct device *dev = &sreg->sdev->dev;
+	const struct scmi_voltage_info *vinfo;
+
+	vinfo = handle->voltage_ops->info_get(handle, sreg->id);
+	if (!vinfo) {
+		dev_warn(dev, "Failure to get voltage domain %d\n",
+			 sreg->id);
+		return -ENODEV;
+	}
+
+	/*
+	 * Regulator framework does not fully support negative voltages
+	 * so we discard any voltage domain reported as supporting negative
+	 * voltages: as a consequence each levels_uv entry is guaranteed to
+	 * be non-negative from here on.
+	 */
+	if (vinfo->negative_volts_allowed) {
+		dev_warn(dev, "Negative voltages NOT supported...skip %s\n",
+			 sreg->of_node->full_name);
+		return -EOPNOTSUPP;
+	}
+
+	sreg->desc.name = devm_kasprintf(dev, GFP_KERNEL, "%s", vinfo->name);
+	if (!sreg->desc.name)
+		return -ENOMEM;
+
+	sreg->desc.id = sreg->id;
+	sreg->desc.type = REGULATOR_VOLTAGE;
+	sreg->desc.owner = THIS_MODULE;
+	sreg->desc.of_match_full_name = true;
+	sreg->desc.of_match = sreg->of_node->full_name;
+	sreg->desc.regulators_node = "regulators";
+	if (vinfo->segmented)
+		ret = scmi_config_linear_regulator_mappings(sreg, vinfo);
+	else
+		ret = scmi_config_discrete_regulator_mappings(sreg, vinfo);
+	if (ret)
+		return ret;
+
+	/*
+	 * Using the scmi device here to have DT searched from Voltage
+	 * protocol node down.
+	 */
+	sreg->conf.dev = dev;
+
+	/* Store for later retrieval via rdev_get_drvdata() */
+	sreg->conf.driver_data = sreg;
+
+	return 0;
+}
+
+static int process_scmi_regulator_of_node(struct scmi_device *sdev,
+					  struct device_node *np,
+					  struct scmi_regulator_info *rinfo)
+{
+	u32 dom, ret;
+
+	ret = of_property_read_u32(np, "reg", &dom);
+	if (ret)
+		return ret;
+
+	if (dom >= rinfo->num_doms)
+		return -ENODEV;
+
+	if (rinfo->sregv[dom]) {
+		dev_err(&sdev->dev,
+			"SCMI Voltage Domain %d already in use. Skipping: %s\n",
+			dom, np->full_name);
+		return -EINVAL;
+	}
+
+	rinfo->sregv[dom] = devm_kzalloc(&sdev->dev,
+					 sizeof(struct scmi_regulator),
+					 GFP_KERNEL);
+	if (!rinfo->sregv[dom])
+		return -ENOMEM;
+
+	rinfo->sregv[dom]->id = dom;
+	rinfo->sregv[dom]->sdev = sdev;
+
+	/* get hold of good nodes */
+	of_node_get(np);
+	rinfo->sregv[dom]->of_node = np;
+
+	dev_dbg(&sdev->dev,
+		"Found SCMI Regulator entry -- OF node [%d] -> %s\n",
+		dom, np->full_name);
+
+	return 0;
+}
+
+static int scmi_regulator_probe(struct scmi_device *sdev)
+{
+	int d, ret, num_doms;
+	struct device_node *np, *child;
+	const struct scmi_handle *handle = sdev->handle;
+	struct scmi_regulator_info *rinfo;
+
+	if (!handle || !handle->voltage_ops)
+		return -ENODEV;
+
+	num_doms = handle->voltage_ops->num_domains_get(handle);
+	if (num_doms <= 0) {
+		if (!num_doms) {
+			dev_err(&sdev->dev,
+				"number of voltage domains invalid\n");
+			num_doms = -EINVAL;
+		} else {
+			dev_err(&sdev->dev,
+				"failed to get voltage domains - err:%d\n",
+				num_doms);
+		}
+
+		return num_doms;
+	}
+
+	rinfo = devm_kzalloc(&sdev->dev, sizeof(*rinfo), GFP_KERNEL);
+	if (!rinfo)
+		return -ENOMEM;
+
+	/* Allocate pointers array for all possible domains */
+	rinfo->sregv = devm_kcalloc(&sdev->dev, num_doms,
+				    sizeof(void *), GFP_KERNEL);
+	if (!rinfo->sregv)
+		return -ENOMEM;
+
+	rinfo->num_doms = num_doms;
+
+	/*
+	 * Start collecting into rinfo->sregv possibly good SCMI Regulators as
+	 * described by a well-formed DT entry and associated with an existing
+	 * plausible SCMI Voltage Domain number, all belonging to this SCMI
+	 * platform instance node (handle->dev->of_node).
+	 */
+	np = of_find_node_by_name(handle->dev->of_node, "regulators");
+	for_each_child_of_node(np, child) {
+		ret = process_scmi_regulator_of_node(sdev, child, rinfo);
+		/* abort on any mem issue */
+		if (ret == -ENOMEM)
+			return ret;
+	}
+
+	/*
+	 * Register a regulator for each valid regulator-DT-entry that we
+	 * can successfully reach via SCMI and has a valid associated voltage
+	 * domain.
+	 */
+	for (d = 0; d < num_doms; d++) {
+		struct scmi_regulator *sreg = rinfo->sregv[d];
+
+		/* Skip empty slots */
+		if (!sreg)
+			continue;
+
+		ret = scmi_regulator_common_init(sreg);
+		/* Skip invalid voltage domains */
+		if (ret)
+			continue;
+
+		sreg->rdev = devm_regulator_register(&sdev->dev, &sreg->desc,
+						     &sreg->conf);
+		if (IS_ERR(sreg->rdev)) {
+			sreg->rdev = NULL;
+			continue;
+		}
+
+		dev_info(&sdev->dev,
+			 "Regulator %s registered for domain [%d]\n",
+			 sreg->desc.name, sreg->id);
+	}
+
+	dev_set_drvdata(&sdev->dev, rinfo);
+
+	return 0;
+}
+
+static void scmi_regulator_remove(struct scmi_device *sdev)
+{
+	int d;
+	struct scmi_regulator_info *rinfo;
+
+	rinfo = dev_get_drvdata(&sdev->dev);
+	if (!rinfo)
+		return;
+
+	for (d = 0; d < rinfo->num_doms; d++) {
+		if (!rinfo->sregv[d])
+			continue;
+		of_node_put(rinfo->sregv[d]->of_node);
+	}
+}
+
+static const struct scmi_device_id scmi_regulator_id_table[] = {
+	{ SCMI_PROTOCOL_VOLTAGE,  "regulator" },
+	{ },
+};
+MODULE_DEVICE_TABLE(scmi, scmi_regulator_id_table);
+
+static struct scmi_driver scmi_drv = {
+	.name		= "scmi-regulator",
+	.probe		= scmi_regulator_probe,
+	.remove		= scmi_regulator_remove,
+	.id_table	= scmi_regulator_id_table,
+};
+
+module_scmi_driver(scmi_drv);
+
+MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI regulator driver");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v7 0/3] Add support for SCMI-Regulator
  2020-11-23 20:23 [PATCH v7 0/3] Add support for SCMI-Regulator Cristian Marussi
                   ` (2 preceding siblings ...)
  2020-11-23 20:23 ` [PATCH v7 3/3] regulator: add SCMI driver Cristian Marussi
@ 2020-11-23 21:46 ` Mark Brown
  3 siblings, 0 replies; 5+ messages in thread
From: Mark Brown @ 2020-11-23 21:46 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, devicetree, Cristian Marussi
  Cc: Jonathan.Cameron, souvik.chakravarty, sudeep.holla, lukasz.luba,
	etienne.carriere, james.quinlan, satyakim, vincent.guittot,
	f.fainelli, robh

On Mon, 23 Nov 2020 20:23:33 +0000, Cristian Marussi wrote:
> this series introduces the support for a new generic SCMI Regulator driver
> developed on top of the recently introduced SCMI Voltage Domain Protocol
> support as specified in the upcoming SCMIv3.0 specification. [1]
> 
> The underlying SCMI VD Protocol support, which was originally part of this
> series, is now applied on for-next/scmi-voltage [2], and this series,
> reduced to its SCMI Regulator support and dt-bindings fixes is similarly
> based on top of [2]:
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next

Thanks!

[1/2] dt-bindings: arm: remove optional properties for SCMI Regulators
      commit: e8056bf01080eeb13b0229f3fa4cb25a5a2de6a5
[2/2] regulator: add SCMI driver
      commit: 0fbeae70ee7ce98e18a47337cd1f205dd88589e9

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-11-23 21:47 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-23 20:23 [PATCH v7 0/3] Add support for SCMI-Regulator Cristian Marussi
2020-11-23 20:23 ` [PATCH v7 1/3] dt-bindings: arm: remove optional properties for SCMI Regulators Cristian Marussi
2020-11-23 20:23 ` [PATCH v7 2/3] regulator: core: add of_match_full_name boolean flag Cristian Marussi
2020-11-23 20:23 ` [PATCH v7 3/3] regulator: add SCMI driver Cristian Marussi
2020-11-23 21:46 ` [PATCH v7 0/3] Add support for SCMI-Regulator Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).