All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lee Jones <lee.jones@linaro.org>
To: "Clément Léger" <clement.leger@bootlin.com>
Cc: Rob Herring <robh+dt@kernel.org>, Mark Brown <broonie@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	"Rafael J. Wysocki" <rafael@kernel.org>,
	Arnd Bergmann <arnd@arndb.de>,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	Peng Fan <peng.fan@nxp.com>, Sudeep Holla <sudeep.holla@arm.com>,
	Alexandre Belloni <alexandre.belloni@bootlin.com>
Subject: Re: [PATCH 2/3] syscon: add support for "syscon-smc" compatible
Date: Fri, 23 Jul 2021 16:27:59 +0100	[thread overview]
Message-ID: <YPrf/5g7JAtf1c4u@google.com> (raw)
In-Reply-To: <20210723135239.388325-3-clement.leger@bootlin.com>

On Fri, 23 Jul 2021, Clément Léger wrote:

> System controllers can be placed under secure monitor control when running
> under them. In order to keep existing code which accesses such system
> controllers using a syscon, add support for "syscon-smc" compatible.
> 
> When enable, the syscon will handle this new compatible and look for an
> "arm,smc-id" property to execute the appropriate SMC. A SMC regmap is then
> created to forward register access to the secure monitor.
> 
> Signed-off-by: Clément Léger <clement.leger@bootlin.com>
> ---
>  drivers/mfd/syscon.c | 170 ++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 145 insertions(+), 25 deletions(-)

I'm going to let Arnd have at this, but just a couple of points.

> diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
> index 765c0210cb52..eb727b146315 100644
> --- a/drivers/mfd/syscon.c
> +++ b/drivers/mfd/syscon.c
> @@ -40,7 +40,15 @@ static const struct regmap_config syscon_regmap_config = {
>  	.reg_stride = 4,
>  };
>  
> -static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
> +static void syscon_add(struct syscon *syscon)
> +{
> +	spin_lock(&syscon_list_slock);
> +	list_add_tail(&syscon->list, &syscon_list);
> +	spin_unlock(&syscon_list_slock);
> +}
> +
> +static struct syscon *of_syscon_register_mmio(struct device_node *np,
> +					      bool check_clk)
>  {
>  	struct clk *clk;
>  	struct syscon *syscon;
> @@ -132,10 +140,6 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
>  	syscon->regmap = regmap;
>  	syscon->np = np;
>  
> -	spin_lock(&syscon_list_slock);
> -	list_add_tail(&syscon->list, &syscon_list);
> -	spin_unlock(&syscon_list_slock);
> -
>  	return syscon;
>  
>  err_attach:
> @@ -150,8 +154,49 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
>  	return ERR_PTR(ret);
>  }
>  
> +#ifdef CONFIG_REGMAP_SMCCC
> +static struct syscon *of_syscon_register_smccc(struct device_node *np)
> +{
> +	struct syscon *syscon;
> +	struct regmap *regmap;
> +	u32 reg_io_width = 4, smc_id;
> +	int ret;
> +	struct regmap_config syscon_config = syscon_regmap_config;
> +
> +	ret = of_property_read_u32(np, "arm,smc-id", &smc_id);

So this is Arm specific.

Not sure we want to be creating bespoke support for specific
architectures/platforms in the generic syscon implementation.

> +	if (ret)
> +		return ERR_PTR(-ENODEV);
> +
> +	syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);
> +	if (!syscon)
> +		return ERR_PTR(-ENOMEM);
> +
> +	of_property_read_u32(np, "reg-io-width", &reg_io_width);
> +
> +	syscon_config.name = kasprintf(GFP_KERNEL, "%pOFn@smc%x", np, smc_id);
> +	syscon_config.val_bits = reg_io_width * 8;
> +
> +	regmap = regmap_init_smccc(NULL, smc_id, &syscon_config);
> +	if (IS_ERR(regmap)) {
> +		ret = PTR_ERR(regmap);
> +		goto err_regmap;
> +	}
> +
> +	syscon->regmap = regmap;
> +	syscon->np = np;
> +
> +	return syscon;
> +
> +err_regmap:
> +	kfree(syscon_config.name);
> +	kfree(syscon);
> +
> +	return ERR_PTR(ret);
> +}
> +#endif
> +
>  static struct regmap *device_node_get_regmap(struct device_node *np,
> -					     bool check_clk)
> +					     bool check_clk, bool use_smccc)
>  {
>  	struct syscon *entry, *syscon = NULL;
>  
> @@ -165,8 +210,19 @@ static struct regmap *device_node_get_regmap(struct device_node *np,
>  
>  	spin_unlock(&syscon_list_slock);
>  
> -	if (!syscon)
> -		syscon = of_syscon_register(np, check_clk);
> +	if (!syscon) {
> +		if (use_smccc)
> +#ifdef CONFIG_REGMAP_SMCCC
> +			syscon = of_syscon_register_smccc(np);
> +#else
> +			syscon = NULL;
> +#endif

... and we certainly don't want to be doing so using #ifdefery.

Please find a better way to support this feature.

> +		else
> +			syscon = of_syscon_register_mmio(np, check_clk);
> +
> +		if (!IS_ERR(syscon))
> +			syscon_add(syscon);
> +	}
>  
>  	if (IS_ERR(syscon))
>  		return ERR_CAST(syscon);
> @@ -176,16 +232,19 @@ static struct regmap *device_node_get_regmap(struct device_node *np,
>  
>  struct regmap *device_node_to_regmap(struct device_node *np)
>  {
> -	return device_node_get_regmap(np, false);
> +	return device_node_get_regmap(np, false, false);
>  }
>  EXPORT_SYMBOL_GPL(device_node_to_regmap);
>  
>  struct regmap *syscon_node_to_regmap(struct device_node *np)
>  {
> -	if (!of_device_is_compatible(np, "syscon"))
> -		return ERR_PTR(-EINVAL);
> +	if (of_device_is_compatible(np, "syscon"))
> +		return device_node_get_regmap(np, true, false);
> +
> +	if (of_device_is_compatible(np, "syscon-smc"))
> +		return device_node_get_regmap(np, true, true);
>  
> -	return device_node_get_regmap(np, true);
> +	return ERR_PTR(-EINVAL);
>  }
>  EXPORT_SYMBOL_GPL(syscon_node_to_regmap);
>  
> @@ -273,19 +332,19 @@ struct regmap *syscon_regmap_lookup_by_phandle_optional(struct device_node *np,
>  }
>  EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle_optional);
>  
> -static int syscon_probe(struct platform_device *pdev)
> +struct syscon_driver_data {
> +	int (*probe_func)(struct platform_device *pdev, struct device *dev,
> +			  struct syscon *syscon);
> +};
> +
> +static int syscon_probe_mmio(struct platform_device *pdev,
> +			     struct device *dev,
> +			     struct syscon *syscon)
>  {
> -	struct device *dev = &pdev->dev;
> -	struct syscon_platform_data *pdata = dev_get_platdata(dev);
> -	struct syscon *syscon;
>  	struct regmap_config syscon_config = syscon_regmap_config;
>  	struct resource *res;
>  	void __iomem *base;
>  
> -	syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL);
> -	if (!syscon)
> -		return -ENOMEM;
> -
>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	if (!res)
>  		return -ENOENT;
> @@ -295,23 +354,84 @@ static int syscon_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  
>  	syscon_config.max_register = resource_size(res) - 4;
> -	if (pdata)
> -		syscon_config.name = pdata->label;
> +
>  	syscon->regmap = devm_regmap_init_mmio(dev, base, &syscon_config);
>  	if (IS_ERR(syscon->regmap)) {
>  		dev_err(dev, "regmap init failed\n");
>  		return PTR_ERR(syscon->regmap);
>  	}
>  
> -	platform_set_drvdata(pdev, syscon);
> +	dev_dbg(dev, "regmap_mmio %pR registered\n", res);
> +
> +	return 0;
> +}
> +
> +static const struct syscon_driver_data syscon_mmio_data = {
> +	.probe_func = &syscon_probe_mmio,
> +};
> +
> +#ifdef CONFIG_REGMAP_SMCCC
> +
> +static int syscon_probe_smc(struct platform_device *pdev,
> +			    struct device *dev,
> +			    struct syscon *syscon)
> +{
> +	struct regmap_config syscon_config = syscon_regmap_config;
> +	int smc_id, ret;
> +
> +	ret = of_property_read_u32(dev->of_node, "arm,smc-id", &smc_id);
> +	if (!ret)
> +		return -ENODEV;
> +
> +	syscon->regmap = devm_regmap_init_smccc(dev, smc_id, &syscon_config);
> +	if (IS_ERR(syscon->regmap)) {
> +		dev_err(dev, "regmap init failed\n");
> +		return PTR_ERR(syscon->regmap);
> +	}
>  
> -	dev_dbg(dev, "regmap %pR registered\n", res);
> +	dev_dbg(dev, "regmap_smccc %x registered\n", smc_id);
> +
> +	return 0;
> +}
> +
> +static const struct syscon_driver_data syscon_smc_data = {
> +	.probe_func = &syscon_probe_smc,
> +};
> +#endif
> +
> +static int syscon_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct device *dev = &pdev->dev;
> +	struct syscon_platform_data *pdata = dev_get_platdata(dev);
> +	struct regmap_config syscon_config = syscon_regmap_config;
> +	struct syscon *syscon;
> +	const struct syscon_driver_data *driver_data;
> +
> +	if (pdata)
> +		syscon_config.name = pdata->label;
> +
> +	syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL);
> +	if (!syscon)
> +		return -ENOMEM;
> +
> +	driver_data = (const struct syscon_driver_data *)
> +				platform_get_device_id(pdev)->driver_data;
> +
> +	ret = driver_data->probe_func(pdev, dev, syscon);
> +	if (ret)
> +		return ret;
> +
> +	platform_set_drvdata(pdev, syscon);
>  
>  	return 0;
>  }
>  
>  static const struct platform_device_id syscon_ids[] = {
> -	{ "syscon", },
> +	{ .name = "syscon",	.driver_data = (kernel_ulong_t)&syscon_mmio_data},
> +#ifdef CONFIG_REGMAP_SMCCC
> +	{ .name = "syscon-smc",	.driver_data = (kernel_ulong_t)&syscon_smc_data},
> +#endif
>  	{ }
>  };
>  

-- 
Lee Jones [李琼斯]
Senior Technical Lead - Developer Services
Linaro.org │ Open source software for Arm SoCs
Follow Linaro: Facebook | Twitter | Blog

  reply	other threads:[~2021-07-23 15:29 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-23 13:52 [PATCH 0/3] add SMC based regmap driver for secure syscon access Clément Léger
2021-07-23 13:52 ` [PATCH 1/3] regmap: add regmap using ARM SMCCC Clément Léger
2021-07-23 14:43   ` Mark Brown
2021-07-23 15:53     ` Clément Léger
2021-07-23 16:37       ` Mark Brown
2021-07-23 13:52 ` [PATCH 2/3] syscon: add support for "syscon-smc" compatible Clément Léger
2021-07-23 15:27   ` Lee Jones [this message]
2021-07-23 15:56     ` Clément Léger
2021-07-23 16:07   ` Arnd Bergmann
2021-07-23 16:41     ` Mark Brown
2021-07-24 12:36     ` Peng Fan (OSS)
2021-07-24  7:00   ` kernel test robot
2021-07-24  7:00     ` kernel test robot
2021-07-23 13:52 ` [PATCH 3/3] dt-bindings: mfd: add "syscon-smc" YAML description Clément Léger
2021-07-29 21:19   ` Rob Herring
2021-07-30  7:21     ` Clément Léger

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=YPrf/5g7JAtf1c4u@google.com \
    --to=lee.jones@linaro.org \
    --cc=alexandre.belloni@bootlin.com \
    --cc=arnd@arndb.de \
    --cc=broonie@kernel.org \
    --cc=clement.leger@bootlin.com \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peng.fan@nxp.com \
    --cc=rafael@kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=sudeep.holla@arm.com \
    /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.