]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
reset: imx: Add SCU reset driver for i.MX8QXP and i.MX8QM
authorFrank Li <Frank.Li@nxp.com>
Mon, 10 Feb 2025 20:59:21 +0000 (15:59 -0500)
committerPhilipp Zabel <p.zabel@pengutronix.de>
Thu, 13 Mar 2025 08:06:27 +0000 (09:06 +0100)
Add System Controller Firmware(SCU) reset driver for i.MX8QM and i.MX8QXP.
SCU Manage resets for peripherals such as MIPI CSI. Currently, support two
reset sources: IMX_SC_R_CSI_0 and IMX_SC_R_CSI_1.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20250210-8qxp_camera-v3-2-324f5105accc@nxp.com
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/reset-imx-scu.c [new file with mode: 0644]

index 5b3abb6db24898ed19cc672a026019e5899f977b..99f6f9784e6865faddf8621ccfca095778c4dc47 100644 (file)
@@ -96,6 +96,13 @@ config RESET_HSDK
        help
          This enables the reset controller driver for HSDK board.
 
+config RESET_IMX_SCU
+       tristate "i.MX8Q Reset Driver"
+       depends on IMX_SCU && HAVE_ARM_SMCCC
+       depends on (ARM64 && ARCH_MXC) || COMPILE_TEST
+       help
+          This enables the reset controller driver for i.MX8QM/i.MX8QXP
+
 config RESET_IMX7
        tristate "i.MX7/8 Reset Driver"
        depends on HAS_IOMEM
index 677c4d1e263201b0c7aef58373c991beda1cc345..31f9904d13f9c3a107fc1ee1ec9f9baba016d101 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
 obj-$(CONFIG_RESET_EYEQ) += reset-eyeq.o
 obj-$(CONFIG_RESET_GPIO) += reset-gpio.o
 obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
+obj-$(CONFIG_RESET_IMX_SCU) += reset-imx-scu.o
 obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
 obj-$(CONFIG_RESET_IMX8MP_AUDIOMIX) += reset-imx8mp-audiomix.o
 obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o
diff --git a/drivers/reset/reset-imx-scu.c b/drivers/reset/reset-imx-scu.c
new file mode 100644 (file)
index 0000000..d3074ea
--- /dev/null
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2025 NXP
+ * Frank Li <Frank.Li@nxp.com>
+ */
+#include <linux/firmware/imx/svc/misc.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/firmware/imx/rsrc.h>
+
+struct imx_scu_reset {
+       struct reset_controller_dev rc;
+       struct imx_sc_ipc *ipc_handle;
+};
+
+static struct imx_scu_reset *to_imx_scu(struct reset_controller_dev *rc)
+{
+       return container_of(rc, struct imx_scu_reset, rc);
+}
+
+struct imx_scu_id_map {
+       u32 resource_id;
+       u32 command_id;
+};
+
+static const struct imx_scu_id_map imx_scu_id_map[] = {
+       { IMX_SC_R_CSI_0, IMX_SC_C_MIPI_RESET },
+       { IMX_SC_R_CSI_1, IMX_SC_C_MIPI_RESET },
+};
+
+static int imx_scu_reset_assert(struct reset_controller_dev *rc, unsigned long id)
+{
+       struct imx_scu_reset *priv = to_imx_scu(rc);
+
+       return imx_sc_misc_set_control(priv->ipc_handle, imx_scu_id_map[id].resource_id,
+                                      imx_scu_id_map[id].command_id, true);
+}
+
+static const struct reset_control_ops imx_scu_reset_ops = {
+       .assert = imx_scu_reset_assert,
+};
+
+static int imx_scu_xlate(struct reset_controller_dev *rc, const struct of_phandle_args *reset_spec)
+{
+       int i;
+
+       for (i = 0; i < rc->nr_resets; i++)
+               if (reset_spec->args[0] == imx_scu_id_map[i].resource_id)
+                       return i;
+
+       return -EINVAL;
+}
+
+static int imx_scu_reset_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct imx_scu_reset *priv;
+       int ret;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, &priv->rc);
+
+       ret = imx_scu_get_handle(&priv->ipc_handle);
+       if (ret)
+               return dev_err_probe(dev, ret, "sc_misc_MIPI get ipc handle failed!\n");
+
+       priv->rc.ops = &imx_scu_reset_ops;
+       priv->rc.owner = THIS_MODULE;
+       priv->rc.of_node = dev->of_node;
+       priv->rc.of_reset_n_cells = 1;
+       priv->rc.of_xlate = imx_scu_xlate;
+       priv->rc.nr_resets = ARRAY_SIZE(imx_scu_id_map);
+
+       return devm_reset_controller_register(dev, &priv->rc);
+}
+
+static const struct of_device_id imx_scu_reset_ids[] = {
+       { .compatible = "fsl,imx-scu-reset", },
+       {}
+};
+MODULE_DEVICE_TABLE(platform, imx_scu_reset_ids);
+
+static struct platform_driver imx_scu_reset_driver = {
+       .probe          = imx_scu_reset_probe,
+       .driver = {
+               .name = "scu-reset",
+               .of_match_table = imx_scu_reset_ids,
+       },
+};
+module_platform_driver(imx_scu_reset_driver);
+
+MODULE_AUTHOR("Frank Li <Frank.Li@nxp.com>");
+MODULE_DESCRIPTION("i.MX scu reset driver");
+MODULE_LICENSE("GPL");