diff options
| author | GUI <[email protected]> | 2025-12-19 21:20:17 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-12-19 21:20:17 +0800 |
| commit | 43733268c1e22f65c67c796f9e3fe8908267aefd (patch) | |
| tree | fb98d71f46e640f57fc5756f026746ed24e1cc02 /components/drivers/reset | |
| parent | 77fbed5744872a825ce71222796b9bdcee30526c (diff) | |
[dm][firmware][scmi] support ARM-SCMI interface #11069
Diffstat (limited to 'components/drivers/reset')
| -rw-r--r-- | components/drivers/reset/Kconfig | 6 | ||||
| -rwxr-xr-x | components/drivers/reset/SConscript | 3 | ||||
| -rwxr-xr-x | components/drivers/reset/reset-scmi.c | 129 |
3 files changed, 138 insertions, 0 deletions
diff --git a/components/drivers/reset/Kconfig b/components/drivers/reset/Kconfig index ccba575750..238fee2e98 100644 --- a/components/drivers/reset/Kconfig +++ b/components/drivers/reset/Kconfig @@ -4,6 +4,12 @@ menuconfig RT_USING_RESET depends on RT_USING_OFW default n +config RT_RESET_SCMI + bool "Reset driver controlled via ARM SCMI interface" + depends on RT_USING_RESET + depends on RT_FIRMWARE_ARM_SCMI + default n + config RT_RESET_SIMPLE bool "Simple Reset Controller Driver" depends on RT_USING_RESET diff --git a/components/drivers/reset/SConscript b/components/drivers/reset/SConscript index 8e64f78643..5d9adee728 100755 --- a/components/drivers/reset/SConscript +++ b/components/drivers/reset/SConscript @@ -13,6 +13,9 @@ src = ['reset.c'] if GetDepend(['RT_RESET_SIMPLE']): src += ['reset-simple.c'] +if GetDepend(['RT_RESET_SCMI']): + src += ['reset-scmi.c'] + group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) Return('group') diff --git a/components/drivers/reset/reset-scmi.c b/components/drivers/reset/reset-scmi.c new file mode 100755 index 0000000000..d10d296d86 --- /dev/null +++ b/components/drivers/reset/reset-scmi.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-11-26 GuEe-GUI first version + */ + +#include <rtthread.h> +#include <rtdevice.h> + +#define DBG_TAG "reset.scmi" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +struct scmi_reset +{ + struct rt_reset_controller parent; + + struct rt_scmi_device *sdev; +}; + +#define raw_to_scmi_reset(raw) rt_container_of(raw, struct scmi_reset, parent) + +static rt_err_t scmi_reset_do(struct scmi_reset *srst, int domain, + rt_uint32_t flags, rt_uint32_t state) +{ + struct scmi_reset_in in = + { + .domain_id = rt_cpu_to_le32(domain), + .flags = rt_cpu_to_le32(flags), + .reset_state = rt_cpu_to_le32(state), + }; + struct scmi_reset_out out; + struct rt_scmi_msg msg = RT_SCMI_MSG_IN_OUT(SCMI_RESET_RESET, &in, &out); + + return rt_scmi_process_msg(srst->sdev, &msg); +} + +static rt_err_t scmi_reset_reset(struct rt_reset_control *rstc) +{ + struct scmi_reset *srst = raw_to_scmi_reset(rstc); + + return scmi_reset_do(srst, rstc->id, SCMI_RESET_FLAG_RESET, SCMI_ARCH_COLD_RESET); +} + +static rt_err_t scmi_reset_assert(struct rt_reset_control *rstc) +{ + struct scmi_reset *srst = raw_to_scmi_reset(rstc); + + return scmi_reset_do(srst, rstc->id, SCMI_RESET_FLAG_ASSERT, SCMI_ARCH_COLD_RESET); +} + +static rt_err_t scmi_reset_deassert(struct rt_reset_control *rstc) +{ + struct scmi_reset *srst = raw_to_scmi_reset(rstc); + + return scmi_reset_do(srst, rstc->id, 0, SCMI_ARCH_COLD_RESET); +} + +static rt_err_t scmi_reset_ofw_parse(struct rt_reset_control *rstc, + struct rt_ofw_cell_args *args) +{ + rt_err_t err; + struct scmi_reset *srst = raw_to_scmi_reset(rstc); + struct scmi_reset_attr_in in = + { + .domain_id = rt_cpu_to_le32(rstc->id), + }; + struct scmi_reset_attr_out out; + struct rt_scmi_msg msg = RT_SCMI_MSG_IN_OUT(SCMI_RESET_DOMAIN_ATTRIBUTES, &in, &out); + + if ((err = rt_scmi_process_msg(srst->sdev, &msg))) + { + return err; + } + + return rt_le32_to_cpu(out.status) == 0 ? RT_EOK : -RT_ERROR; +} + +static const struct rt_reset_control_ops scmi_reset_ops = +{ + .ofw_parse = scmi_reset_ofw_parse, + .reset = scmi_reset_reset, + .assert = scmi_reset_assert, + .deassert = scmi_reset_deassert, +}; + +static rt_err_t scmi_reset_probe(struct rt_scmi_device *sdev) +{ + rt_err_t err; + struct rt_reset_controller *rstcer; + struct scmi_reset *srst = rt_calloc(1, sizeof(*srst)); + + if (!srst) + { + return -RT_ENOMEM; + } + + rstcer = &srst->parent; + + rstcer->priv = srst; + rstcer->ofw_node = sdev->parent.ofw_node; + rstcer->ops = &scmi_reset_ops; + + if ((err = rt_reset_controller_register(&srst->parent))) + { + rt_free(srst); + } + + return err; +} + +static const struct rt_scmi_device_id scmi_reset_ids[] = +{ + { SCMI_PROTOCOL_ID_RESET, "reset" }, + { /* sentinel */ }, +}; + +static struct rt_scmi_driver scmi_reset_driver = +{ + .name = "reset-scmi", + .ids = scmi_reset_ids, + + .probe = scmi_reset_probe, +}; +RT_SCMI_DRIVER_EXPORT(scmi_reset_driver); |
