[PATCH v2 3/3] drivers: meson: introduce secure power controller driver

neil.armstrong at linaro.org neil.armstrong at linaro.org
Wed May 31 11:47:08 CEST 2023


On 31/05/2023 11:31, Alexey Romanov wrote:
> This patch adds Power controller driver support for Amlogic
> A1 family using secure monitor calls. The power domains register
> only can access in secure world.
> 
> Signed-off-by: Alexey Romanov <avromanov at sberdevices.ru>
> ---
>   drivers/power/domain/Kconfig             |   7 +
>   drivers/power/domain/Makefile            |   1 +
>   drivers/power/domain/meson-secure-pwrc.c | 160 +++++++++++++++++++++++
>   3 files changed, 168 insertions(+)
>   create mode 100644 drivers/power/domain/meson-secure-pwrc.c
> 
> diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
> index 7e1b8c072fa..411c210756a 100644
> --- a/drivers/power/domain/Kconfig
> +++ b/drivers/power/domain/Kconfig
> @@ -68,6 +68,13 @@ config MESON_EE_POWER_DOMAIN
>   	  Enable support for manipulating Amlogic Meson Everything-Else power
>   	  domains.
>   
> +config MESON_SECURE_POWER_DOMAIN
> +	bool "Enable Amlogic Secure power domain driver"
> +	depends on POWER_DOMAIN && ARCH_MESON && MESON_A1
> +	help
> +	  Enable support for manipulating Amlogic Meson Secure power domains.
> +	  Support for Amlogic A1 series.
> +
>   config SANDBOX_POWER_DOMAIN
>   	bool "Enable the sandbox power domain test driver"
>   	depends on POWER_DOMAIN && SANDBOX
> diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
> index e6244776216..aa5a4ba57cd 100644
> --- a/drivers/power/domain/Makefile
> +++ b/drivers/power/domain/Makefile
> @@ -12,6 +12,7 @@ obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o
>   obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o
>   obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
>   obj-$(CONFIG_MESON_EE_POWER_DOMAIN) += meson-ee-pwrc.o
> +obj-$(CONFIG_MESON_SECURE_POWER_DOMAIN) += meson-secure-pwrc.o
>   obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
>   obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o
>   obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o
> diff --git a/drivers/power/domain/meson-secure-pwrc.c b/drivers/power/domain/meson-secure-pwrc.c
> new file mode 100644
> index 00000000000..f70f8e02423
> --- /dev/null
> +++ b/drivers/power/domain/meson-secure-pwrc.c
> @@ -0,0 +1,160 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2023 SberDevices, Inc.
> + * Author: Alexey Romanov <avromanov at sberdevices.ru>
> + */
> +
> +#include <dm.h>
> +#include <asm/arch/sm.h>
> +#include <power-domain.h>
> +#include <power-domain-uclass.h>
> +#include <dt-bindings/power/meson-a1-power.h>
> +
> +struct meson_secure_pwrc_domain_desc {
> +	char *name;
> +	size_t index;
> +};
> +
> +struct meson_secure_pwrc_domain_data {
> +	unsigned int count;
> +	struct meson_secure_pwrc_domain_desc *domains;
> +};
> +
> +struct meson_secure_pwrc_priv {
> +	const struct meson_secure_pwrc_domain_data *data;
> +};
> +
> +static int meson_secure_pwrc_on(struct power_domain *power_domain)
> +{
> +	struct meson_secure_pwrc_priv *priv = dev_get_priv(power_domain->dev);
> +	struct meson_secure_pwrc_domain_desc *pwrc_domain;
> +	int err;
> +
> +	pwrc_domain = &priv->data->domains[power_domain->id];
> +
> +	err = meson_sm_pwrdm_on(pwrc_domain->index);
> +	if (err) {
> +		pr_err("meson_sm_pwrdm_on() failed (%d)\n", err);
> +		return err;
> +	}
> +
> +	pr_debug("enable %s power domain\n", pwrc_domain->name);
> +
> +	return 0;
> +}
> +
> +static int meson_secure_pwrc_off(struct power_domain *power_domain)
> +{
> +	struct meson_secure_pwrc_priv *priv = dev_get_priv(power_domain->dev);
> +	struct meson_secure_pwrc_domain_desc *pwrc_domain;
> +	int err;
> +
> +	pwrc_domain = &priv->data->domains[power_domain->id];
> +
> +	err = meson_sm_pwrdm_off(pwrc_domain->index);
> +	if (err) {
> +		pr_err("meson_sm_pwrdm_off() failed (%d)\n", err);
> +		return err;
> +	}
> +
> +	pr_debug("disable %s power domain\n", pwrc_domain->name);
> +
> +	return 0;
> +}
> +
> +static int meson_secure_pwrc_of_xlate(struct power_domain *power_domain,
> +				  struct ofnode_phandle_args *args)
> +{
> +	struct meson_secure_pwrc_priv *priv = dev_get_priv(power_domain->dev);
> +	struct meson_secure_pwrc_domain_desc *pwrc_domain;
> +
> +	if (args->args_count < 1) {
> +		pr_err("invalid args count: %d\n", args->args_count);
> +		return -EINVAL;
> +	}
> +
> +	power_domain->id = args->args[0];
> +
> +	if (power_domain->id >= priv->data->count) {
> +		pr_err("domain with ID=%lu is invalid\n", power_domain->id);
> +		return -EINVAL;
> +	}
> +
> +	pwrc_domain = &priv->data->domains[power_domain->id];
> +
> +	if (!pwrc_domain->name) {
> +		pr_err("domain with ID=%lu is invalid\n", power_domain->id);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +#define SEC_PD(__name)			\
> +[PWRC_##__name##_ID] =			\
> +{					\
> +	.name = #__name,		\
> +	.index = PWRC_##__name##_ID,	\
> +}
> +
> +static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = {
> +	SEC_PD(DSPA),
> +	SEC_PD(DSPB),
> +	SEC_PD(UART),
> +	SEC_PD(DMC),
> +	SEC_PD(I2C),
> +	SEC_PD(PSRAM),
> +	SEC_PD(ACODEC),
> +	SEC_PD(AUDIO),
> +	SEC_PD(OTP),
> +	SEC_PD(DMA),
> +	SEC_PD(SD_EMMC),
> +	SEC_PD(RAMA),
> +	SEC_PD(RAMB),
> +	SEC_PD(IR),
> +	SEC_PD(SPICC),
> +	SEC_PD(SPIFC),
> +	SEC_PD(USB),
> +	SEC_PD(NIC),
> +	SEC_PD(PDMIN),
> +	SEC_PD(RSA),
> +};
> +
> +struct power_domain_ops meson_secure_pwrc_ops = {
> +	.on = meson_secure_pwrc_on,
> +	.off = meson_secure_pwrc_off,
> +	.of_xlate = meson_secure_pwrc_of_xlate,
> +};
> +
> +static struct meson_secure_pwrc_domain_data meson_secure_a1_pwrc_data = {
> +	.count = ARRAY_SIZE(a1_pwrc_domains),
> +	.domains = a1_pwrc_domains,
> +};
> +
> +static const struct udevice_id meson_secure_pwrc_ids[] = {
> +	{
> +		.compatible = "amlogic,meson-a1-pwrc",
> +		.data = (unsigned long)&meson_secure_a1_pwrc_data,
> +	},
> +	{ }
> +};
> +
> +static int meson_secure_pwrc_probe(struct udevice *dev)
> +{
> +	struct meson_secure_pwrc_priv *priv = dev_get_priv(dev);
> +
> +	priv->data = (void *)dev_get_driver_data(dev);
> +	if (!priv->data)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +U_BOOT_DRIVER(meson_secure_pwrc) = {
> +	.name = "meson_secure_pwrc",
> +	.id = UCLASS_POWER_DOMAIN,
> +	.of_match = meson_secure_pwrc_ids,
> +	.probe = meson_secure_pwrc_probe,
> +	.ops = &meson_secure_pwrc_ops,
> +	.priv_auto = sizeof(struct meson_secure_pwrc_priv),
> +};

Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>


More information about the U-Boot mailing list