diff options
author | Ahmad Fatoum <a.fatoum@pengutronix.de> | 2022-02-20 13:47:25 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2022-02-23 11:15:44 +0100 |
commit | 3e3ddeb7cbd65924f6d1bd0973c7827fbcf8450e (patch) | |
tree | 9eff5acfc8d626e92a005de3a24071dba00bec98 /drivers/reset | |
parent | 8993005bda72568429ad57fabe9ef955bbc83927 (diff) | |
download | barebox-3e3ddeb7cbd65924f6d1bd0973c7827fbcf8450e.tar.gz barebox-3e3ddeb7cbd65924f6d1bd0973c7827fbcf8450e.tar.xz |
reset: add SCMI support
Import the Linux v5.13 state of the SCMI reset protocol driver.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Link: https://lore.barebox.org/20220220124736.3052502-14-a.fatoum@pengutronix.de
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/reset')
-rw-r--r-- | drivers/reset/Kconfig | 11 | ||||
-rw-r--r-- | drivers/reset/Makefile | 1 | ||||
-rw-r--r-- | drivers/reset/reset-scmi.c | 130 |
3 files changed, 142 insertions, 0 deletions
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 21a6e1a50d..913b309eac 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -45,4 +45,15 @@ config RESET_STARFIVE help This enables the reset controller driver for the StarFive JH7100. +config RESET_SCMI + tristate "Reset driver controlled via ARM SCMI interface" + depends on ARM_SCMI_PROTOCOL || COMPILE_TEST + default ARM_SCMI_PROTOCOL + help + This driver provides support for reset signal/domains that are + controlled by firmware that implements the SCMI interface. + + This driver uses SCMI Message Protocol to interact with the + firmware controlling all the reset signals. + endif diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 6d0cd51f86..b1668433d7 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o obj-$(CONFIG_RESET_STARFIVE) += reset-starfive-vic.o +obj-$(CONFIG_RESET_SCMI) += reset-scmi.o diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c new file mode 100644 index 0000000000..c33bbc5c8a --- /dev/null +++ b/drivers/reset/reset-scmi.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ARM System Control and Management Interface (ARM SCMI) reset driver + * + * Copyright (C) 2019-2021 ARM Ltd. + */ + +#include <common.h> +#include <of.h> +#include <driver.h> +#include <linux/reset-controller.h> +#include <linux/scmi_protocol.h> + +static const struct scmi_reset_proto_ops *reset_ops; + +/** + * struct scmi_reset_data - reset controller information structure + * @rcdev: reset controller entity + * @ph: ARM SCMI protocol handle used for communication with system controller + */ +struct scmi_reset_data { + struct reset_controller_dev rcdev; + const struct scmi_protocol_handle *ph; +}; + +#define to_scmi_reset_data(p) container_of((p), struct scmi_reset_data, rcdev) +#define to_scmi_handle(p) (to_scmi_reset_data(p)->ph) + +/** + * scmi_reset_assert() - assert device reset + * @rcdev: reset controller entity + * @id: ID of the reset to be asserted + * + * This function implements the reset driver op to assert a device's reset + * using the ARM SCMI protocol. + * + * Return: 0 for successful request, else a corresponding error value + */ +static int +scmi_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) +{ + const struct scmi_protocol_handle *ph = to_scmi_handle(rcdev); + + return reset_ops->assert(ph, id); +} + +/** + * scmi_reset_deassert() - deassert device reset + * @rcdev: reset controller entity + * @id: ID of the reset to be deasserted + * + * This function implements the reset driver op to deassert a device's reset + * using the ARM SCMI protocol. + * + * Return: 0 for successful request, else a corresponding error value + */ +static int +scmi_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) +{ + const struct scmi_protocol_handle *ph = to_scmi_handle(rcdev); + + return reset_ops->deassert(ph, id); +} + +/** + * scmi_reset_reset() - reset the device + * @rcdev: reset controller entity + * @id: ID of the reset signal to be reset(assert + deassert) + * + * This function implements the reset driver op to trigger a device's + * reset signal using the ARM SCMI protocol. + * + * Return: 0 for successful request, else a corresponding error value + */ +static int +scmi_reset_reset(struct reset_controller_dev *rcdev, unsigned long id) +{ + const struct scmi_protocol_handle *ph = to_scmi_handle(rcdev); + + return reset_ops->reset(ph, id); +} + +static const struct reset_control_ops scmi_reset_ops = { + .assert = scmi_reset_assert, + .deassert = scmi_reset_deassert, + .reset = scmi_reset_reset, +}; + +static int scmi_reset_probe(struct scmi_device *sdev) +{ + struct scmi_reset_data *data; + struct device_d *dev = &sdev->dev; + struct device_node *np = dev->device_node; + const struct scmi_handle *handle = sdev->handle; + struct scmi_protocol_handle *ph; + + if (!handle) + return -ENODEV; + + reset_ops = handle->protocol_get(sdev, SCMI_PROTOCOL_RESET, &ph); + if (IS_ERR(reset_ops)) + return PTR_ERR(reset_ops); + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->rcdev.ops = &scmi_reset_ops; + data->rcdev.of_node = np; + data->rcdev.nr_resets = reset_ops->num_domains_get(ph); + data->ph = ph; + + return reset_controller_register(&data->rcdev); +} + +static const struct scmi_device_id scmi_id_table[] = { + { SCMI_PROTOCOL_RESET, "reset" }, + { }, +}; + +static struct scmi_driver scmi_reset_driver = { + .name = "scmi-reset", + .probe = scmi_reset_probe, + .id_table = scmi_id_table, +}; +core_scmi_driver(scmi_reset_driver); + +MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>"); +MODULE_DESCRIPTION("ARM SCMI reset controller driver"); +MODULE_LICENSE("GPL v2"); |