mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-04 18:41:03 +00:00
161 lines
3.5 KiB
C
161 lines
3.5 KiB
C
|
// SPDX-License-Identifier: GPL-2.0+
|
||
|
/*
|
||
|
* Copyright (c) 2023 SberDevices, Inc.
|
||
|
* Author: Alexey Romanov <avromanov@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),
|
||
|
};
|