All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jaehoon Chung <jh80.chung@samsung.com>
To: u-boot@lists.denx.de
Subject: [PATCH v4 1/5] firmware: scmi: voltage regulator
Date: Wed, 10 Mar 2021 07:42:38 +0900	[thread overview]
Message-ID: <a60ca6ae-c160-5a5a-8eb5-783378b53c53@samsung.com> (raw)
In-Reply-To: <20210308213810.29535-1-etienne.carriere@linaro.org>

On 3/9/21 6:38 AM, Etienne Carriere wrote:
> Implement voltage regulators interfaced by the SCMI voltage domain
> protocol. The DT bindings are defined in the Linux kernel since
> SCMI voltage domain and regulators patches [1] and [2] integration
> in v5.11-rc7.
> 
> Link: [1] https://protect2.fireeye.com/v1/url?k=4762535a-18f96b93-4763d815-0cc47a336fae-3c00cacbc555f86e&q=1&e=d232145a-df26-46c6-b2ed-fd2b665c4b71&u=https%3A%2F%2Fgithub.com%2Ftorvalds%2Flinux%2Fcommit%2F0f80fcec08e9c50b8d2992cf26495673765ebaba
> Link: [2] https://protect2.fireeye.com/v1/url?k=3da6e589-623ddd40-3da76ec6-0cc47a336fae-8f68d44282000af5&q=1&e=d232145a-df26-46c6-b2ed-fd2b665c4b71&u=https%3A%2F%2Fgithub.com%2Ftorvalds%2Flinux%2Fcommit%2F2add5cacff3531e54c50b0832128299faa9f0563
> Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>

Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>

Best Regards,
Jaehoon Chung

> ---
> Changes in v4:
> - define a device for SCMI voltage protocol that binds the SCMI regulators
>   as suggested by Patrick.
> - removed Simon and Jaehoon tags since changes.
> 
> Changes in v3:
> - applied review tags
> 
> Changes in v2:
> - no change
> ---
>  doc/device-tree-bindings/arm/arm,scmi.txt |  34 ++++
>  drivers/firmware/scmi/scmi_agent-uclass.c |  10 ++
>  drivers/power/regulator/Kconfig           |   8 +
>  drivers/power/regulator/Makefile          |   1 +
>  drivers/power/regulator/scmi_regulator.c  | 195 ++++++++++++++++++++++
>  include/scmi_protocols.h                  | 113 +++++++++++++
>  6 files changed, 361 insertions(+)
>  create mode 100644 drivers/power/regulator/scmi_regulator.c
> 
> diff --git a/doc/device-tree-bindings/arm/arm,scmi.txt b/doc/device-tree-bindings/arm/arm,scmi.txt
> index 1f293ea24..a76124f4a 100644
> --- a/doc/device-tree-bindings/arm/arm,scmi.txt
> +++ b/doc/device-tree-bindings/arm/arm,scmi.txt
> @@ -62,6 +62,20 @@ Required properties:
>   - #power-domain-cells : Should be 1. Contains the device or the power
>  			 domain ID value used by SCMI commands.
>  
> +Regulator bindings for the SCMI Regulator based on SCMI Message Protocol
> +------------------------------------------------------------
> +An SCMI Regulator is permanently bound to a well defined SCMI Voltage Domain,
> +and should be always positioned as a root regulator.
> +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].
> +
> +Required properties:
> + - reg : shall identify an existent SCMI Voltage Domain.
> +
>  Sensor bindings for the sensors based on SCMI Message Protocol
>  --------------------------------------------------------------
>  SCMI provides an API to access the various sensors on the SoC.
> @@ -105,6 +119,7 @@ Required sub-node properties:
>  [3] Documentation/devicetree/bindings/thermal/thermal.txt
>  [4] Documentation/devicetree/bindings/sram/sram.yaml
>  [5] Documentation/devicetree/bindings/reset/reset.txt
> +[6] Documentation/devicetree/bindings/regulator/regulator.yaml
>  
>  Example:
>  
> @@ -169,6 +184,25 @@ firmware {
>  			reg = <0x16>;
>  			#reset-cells = <1>;
>  		};
> +
> +		scmi_voltage: protocol at 17 {
> +			reg = <0x17>;
> +
> +			regulators {
> +				regulator_devX: regulator at 0 {
> +					reg = <0x0>;
> +					regulator-max-microvolt = <3300000>;
> +				};
> +
> +				regulator_devY: regulator at 9 {
> +					reg = <0x9>;
> +					regulator-min-microvolt = <500000>;
> +					regulator-max-microvolt = <4200000>;
> +				};
> +
> +				...
> +			};
> +		};
>  	};
>  };
>  
> diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
> index 516e690ac..f13e46c36 100644
> --- a/drivers/firmware/scmi/scmi_agent-uclass.c
> +++ b/drivers/firmware/scmi/scmi_agent-uclass.c
> @@ -79,6 +79,16 @@ static int scmi_bind_protocols(struct udevice *dev)
>  			if (IS_ENABLED(CONFIG_RESET_SCMI))
>  				drv = DM_DRIVER_GET(scmi_reset_domain);
>  			break;
> +		case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
> +			if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) {
> +				node = ofnode_find_subnode(node, "regulators");
> +				if (!ofnode_valid(node)) {
> +					dev_err(dev, "no regulators node\n");
> +					return -ENXIO;
> +				}
> +				drv = DM_DRIVER_GET(scmi_voltage_domain);
> +			}
> +			break;
>  		default:
>  			break;
>  		}
> diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
> index fbbea18c7..5d6180229 100644
> --- a/drivers/power/regulator/Kconfig
> +++ b/drivers/power/regulator/Kconfig
> @@ -353,3 +353,11 @@ config DM_REGULATOR_TPS65941
>  	TPS65941 series of PMICs have 5 single phase BUCKs that can also
>  	be configured in multi phase modes & 4 LDOs. The driver implements
>  	get/set api for value and enable.
> +
> +config DM_REGULATOR_SCMI
> +	bool "Enable driver for SCMI voltage domain regulators"
> +	depends on DM_REGULATOR
> +	select SCMI_AGENT
> +        help
> +          Enable this option if you want to support regulators exposed through
> +	  the SCMI voltage domain protocol by a SCMI server.
> diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
> index 9d58112dc..b2f5972ea 100644
> --- a/drivers/power/regulator/Makefile
> +++ b/drivers/power/regulator/Makefile
> @@ -30,3 +30,4 @@ obj-$(CONFIG_DM_REGULATOR_TPS65910) += tps65910_regulator.o
>  obj-$(CONFIG_DM_REGULATOR_TPS62360) += tps62360_regulator.o
>  obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMIC1) += stpmic1.o
>  obj-$(CONFIG_DM_REGULATOR_TPS65941) += tps65941_regulator.o
> +obj-$(CONFIG_DM_REGULATOR_SCMI) += scmi_regulator.o
> diff --git a/drivers/power/regulator/scmi_regulator.c b/drivers/power/regulator/scmi_regulator.c
> new file mode 100644
> index 000000000..b3142bf4e
> --- /dev/null
> +++ b/drivers/power/regulator/scmi_regulator.c
> @@ -0,0 +1,195 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2020-2021 Linaro Limited
> + */
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <scmi_agent.h>
> +#include <scmi_protocols.h>
> +#include <asm/types.h>
> +#include <dm/device.h>
> +#include <dm/device_compat.h>
> +#include <dm/device-internal.h>
> +#include <linux/kernel.h>
> +#include <power/regulator.h>
> +
> +/**
> + * struct scmi_regulator_platdata - Platform data for a scmi voltage domain regulator
> + * @domain_id: ID representing the regulator for the related SCMI agent
> + */
> +struct scmi_regulator_platdata {
> +	u32 domain_id;
> +};
> +
> +static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
> +{
> +	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> +	struct scmi_voltd_config_set_in in = {
> +		.domain_id = pdata->domain_id,
> +		.config = enable ? SCMI_VOLTD_CONFIG_ON : SCMI_VOLTD_CONFIG_OFF,
> +	};
> +	struct scmi_voltd_config_set_out out;
> +	struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
> +					  SCMI_VOLTAGE_DOMAIN_CONFIG_SET,
> +					  in, out);
> +	int ret;
> +
> +	ret = devm_scmi_process_msg(dev->parent->parent, &msg);
> +	if (ret)
> +		return ret;
> +
> +	ret = scmi_to_linux_errno(out.status);
> +	if (ret)
> +		return ret;
> +
> +	return ret;
> +}
> +
> +static int scmi_voltd_get_enable(struct udevice *dev)
> +{
> +	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> +	struct scmi_voltd_config_get_in in = {
> +		.domain_id = pdata->domain_id,
> +	};
> +	struct scmi_voltd_config_get_out out;
> +	struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
> +					  SCMI_VOLTAGE_DOMAIN_CONFIG_GET,
> +					  in, out);
> +	int ret;
> +
> +	ret = devm_scmi_process_msg(dev->parent->parent, &msg);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = scmi_to_linux_errno(out.status);
> +	if (ret < 0)
> +		return ret;
> +
> +	return out.config == SCMI_VOLTD_CONFIG_ON;
> +}
> +
> +static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
> +{
> +	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> +	struct scmi_voltd_level_set_in in = {
> +		.domain_id = pdata->domain_id,
> +		.voltage_level = uV,
> +	};
> +	struct scmi_voltd_level_set_out out;
> +	struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
> +					  SCMI_VOLTAGE_DOMAIN_LEVEL_SET,
> +					  in, out);
> +	int ret;
> +
> +	ret = devm_scmi_process_msg(dev->parent->parent, &msg);
> +	if (ret < 0)
> +		return ret;
> +
> +	return scmi_to_linux_errno(out.status);
> +}
> +
> +static int scmi_voltd_get_voltage_level(struct udevice *dev)
> +{
> +	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> +	struct scmi_voltd_level_get_in in = {
> +		.domain_id = pdata->domain_id,
> +	};
> +	struct scmi_voltd_level_get_out out;
> +	struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
> +					  SCMI_VOLTAGE_DOMAIN_LEVEL_GET,
> +					  in, out);
> +	int ret;
> +
> +	ret = devm_scmi_process_msg(dev->parent->parent, &msg);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = scmi_to_linux_errno(out.status);
> +	if (ret < 0)
> +		return ret;
> +
> +	return out.voltage_level;
> +}
> +
> +static int scmi_regulator_of_to_plat(struct udevice *dev)
> +{
> +	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> +	fdt_addr_t reg;
> +
> +	reg = dev_read_addr(dev);
> +	if (reg == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	pdata->domain_id = (u32)reg;
> +
> +	return 0;
> +}
> +
> +static int scmi_regulator_probe(struct udevice *dev)
> +{
> +	struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
> +	struct scmi_voltd_attr_in in = { 0 };
> +	struct scmi_voltd_attr_out out = { 0 };
> +	struct scmi_msg scmi_msg = {
> +		.protocol_id = SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
> +		.message_id = SCMI_VOLTAGE_DOMAIN_ATTRIBUTES,
> +		.in_msg = (u8 *)&in,
> +		.in_msg_sz = sizeof(in),
> +		.out_msg = (u8 *)&out,
> +		.out_msg_sz = sizeof(out),
> +	};
> +	int ret;
> +
> +	/* Check voltage domain is known from SCMI server */
> +	in.domain_id = pdata->domain_id;
> +
> +	ret = devm_scmi_process_msg(dev->parent->parent, &scmi_msg);
> +	if (ret) {
> +		dev_err(dev, "Failed to query voltage domain %u: %d\n",
> +			pdata->domain_id, ret);
> +		return -ENXIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dm_regulator_ops scmi_voltd_ops = {
> +	.get_value = scmi_voltd_get_voltage_level,
> +	.set_value = scmi_voltd_set_voltage_level,
> +	.get_enable = scmi_voltd_get_enable,
> +	.set_enable = scmi_voltd_set_enable,
> +};
> +
> +U_BOOT_DRIVER(scmi_regulator) = {
> +	.name = "scmi_regulator",
> +	.id = UCLASS_REGULATOR,
> +	.ops = &scmi_voltd_ops,
> +	.probe = scmi_regulator_probe,
> +	.of_to_plat = scmi_regulator_of_to_plat,
> +	.plat_auto = sizeof(struct scmi_regulator_platdata),
> +};
> +
> +static int scmi_regulator_bind(struct udevice *dev)
> +{
> +	struct driver *drv;
> +	ofnode node;
> +	int ret;
> +
> +	drv = DM_DRIVER_GET(scmi_regulator);
> +
> +	ofnode_for_each_subnode(node, dev_ofnode(dev)) {
> +		ret = device_bind(dev, drv, ofnode_get_name(node),
> +				  NULL, node, NULL);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +U_BOOT_DRIVER(scmi_voltage_domain) = {
> +	.name = "scmi_voltage_domain",
> +	.id = UCLASS_NOP,
> +	.bind = scmi_regulator_bind,
> +};
> diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h
> index ccab97c96..2db71697e 100644
> --- a/include/scmi_protocols.h
> +++ b/include/scmi_protocols.h
> @@ -23,6 +23,7 @@ enum scmi_std_protocol {
>  	SCMI_PROTOCOL_ID_CLOCK = 0x14,
>  	SCMI_PROTOCOL_ID_SENSOR = 0x15,
>  	SCMI_PROTOCOL_ID_RESET_DOMAIN = 0x16,
> +	SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN = 0x17,
>  };
>  
>  enum scmi_status_code {
> @@ -176,4 +177,116 @@ struct scmi_rd_reset_out {
>  	s32 status;
>  };
>  
> +/*
> + * SCMI Voltage Domain Protocol
> + */
> +
> +enum scmi_voltage_domain_message_id {
> +	SCMI_VOLTAGE_DOMAIN_ATTRIBUTES = 0x3,
> +	SCMI_VOLTAGE_DOMAIN_CONFIG_SET = 0x5,
> +	SCMI_VOLTAGE_DOMAIN_CONFIG_GET = 0x6,
> +	SCMI_VOLTAGE_DOMAIN_LEVEL_SET = 0x7,
> +	SCMI_VOLTAGE_DOMAIN_LEVEL_GET = 0x8,
> +};
> +
> +#define SCMI_VOLTD_NAME_LEN		16
> +
> +#define SCMI_VOLTD_CONFIG_MASK		GENMASK(3, 0)
> +#define SCMI_VOLTD_CONFIG_OFF		0
> +#define SCMI_VOLTD_CONFIG_ON		0x7
> +
> +/**
> + * struct scmi_voltd_attr_in - Payload for VOLTAGE_DOMAIN_ATTRIBUTES message
> + * @domain_id:	SCMI voltage domain ID
> + */
> +struct scmi_voltd_attr_in {
> +	u32 domain_id;
> +};
> +
> +/**
> + * struct scmi_voltd_attr_out - Payload for VOLTAGE_DOMAIN_ATTRIBUTES response
> + * @status:	SCMI command status
> + * @attributes:	Retrieved attributes of the voltage domain
> + * @name:	Voltage domain name
> + */
> +struct scmi_voltd_attr_out {
> +	s32 status;
> +	u32 attributes;
> +	char name[SCMI_VOLTD_NAME_LEN];
> +};
> +
> +/**
> + * struct scmi_voltd_config_set_in - Message payload for VOLTAGE_CONFIG_SET cmd
> + * @domain_id:	SCMI voltage domain ID
> + * @config:	Configuration data of the voltage domain
> + */
> +struct scmi_voltd_config_set_in {
> +	u32 domain_id;
> +	u32 config;
> +};
> +
> +/**
> + * struct scmi_voltd_config_set_out - Response for VOLTAGE_CONFIG_SET command
> + * @status:	SCMI command status
> + */
> +struct scmi_voltd_config_set_out {
> +	s32 status;
> +};
> +
> +/**
> + * struct scmi_voltd_config_get_in - Message payload for VOLTAGE_CONFIG_GET cmd
> + * @domain_id:	SCMI voltage domain ID
> + */
> +struct scmi_voltd_config_get_in {
> +	u32 domain_id;
> +};
> +
> +/**
> + * struct scmi_voltd_config_get_out - Response for VOLTAGE_CONFIG_GET command
> + * @status:	SCMI command status
> + * @config:	Configuration data of the voltage domain
> + */
> +struct scmi_voltd_config_get_out {
> +	s32 status;
> +	u32 config;
> +};
> +
> +/**
> + * struct scmi_voltd_level_set_in - Message payload for VOLTAGE_LEVEL_SET cmd
> + * @domain_id:		SCMI voltage domain ID
> + * @flags:		Parameter flags for configuring target level
> + * @voltage_level:	Target voltage level in microvolts (uV)
> + */
> +struct scmi_voltd_level_set_in {
> +	u32 domain_id;
> +	u32 flags;
> +	s32 voltage_level;
> +};
> +
> +/**
> + * struct scmi_voltd_level_set_out - Response for VOLTAGE_LEVEL_SET command
> + * @status:	SCMI	command status
> + */
> +struct scmi_voltd_level_set_out {
> +	s32 status;
> +};
> +
> +/**
> + * struct scmi_voltd_level_get_in - Message payload for VOLTAGE_LEVEL_GET cmd
> + * @domain_id:		SCMI voltage domain ID
> + */
> +struct scmi_voltd_level_get_in {
> +	u32 domain_id;
> +};
> +
> +/**
> + * struct scmi_voltd_level_get_out - Response for VOLTAGE_LEVEL_GET command
> + * @status:		SCMI command status
> + * @voltage_level:	Voltage level in microvolts (uV)
> + */
> +struct scmi_voltd_level_get_out {
> +	s32 status;
> +	s32 voltage_level;
> +};
> +
>  #endif /* _SCMI_PROTOCOLS_H */
> 

  parent reply	other threads:[~2021-03-09 22:42 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20210308213832epcas1p27f05cc8ec78225e216a44d374e365ebd@epcas1p2.samsung.com>
2021-03-08 21:38 ` [PATCH v4 1/5] firmware: scmi: voltage regulator Etienne Carriere
2021-03-08 21:38   ` [PATCH v4 2/5] firmware: scmi: sandbox test for " Etienne Carriere
2021-04-13 14:28     ` Tom Rini
2021-03-08 21:38   ` [PATCH v4 3/5] firmware: scmi: fix inline comments and minor coding style issues Etienne Carriere
2021-04-13 14:28     ` Tom Rini
2021-03-08 21:38   ` [PATCH v4 4/5] test: scmi: add local variables for scmi agent reference Etienne Carriere
2021-03-12  4:45     ` Simon Glass
2021-04-13 14:28     ` Tom Rini
2021-03-08 21:38   ` [PATCH v4 5/5] regulator: scmi: fix header file inclusion order Etienne Carriere
2021-03-12  4:45     ` Simon Glass
2021-03-09 22:42   ` Jaehoon Chung [this message]
2021-04-13 14:28   ` [PATCH v4 1/5] firmware: scmi: voltage regulator Tom Rini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a60ca6ae-c160-5a5a-8eb5-783378b53c53@samsung.com \
    --to=jh80.chung@samsung.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.