]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
reset: thead: Add TH1520 reset controller driver
authorMichal Wilczynski <m.wilczynski@samsung.com>
Mon, 3 Mar 2025 15:25:11 +0000 (16:25 +0100)
committerPhilipp Zabel <p.zabel@pengutronix.de>
Mon, 7 Apr 2025 08:19:27 +0000 (10:19 +0200)
Add reset controller driver for the T-HEAD TH1520 SoC that manages
hardware reset lines for various subsystems. The driver currently
implements support for GPU reset control, with infrastructure in place
to extend support for NPU and Watchdog Timer resets in future updates.

Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
Link: https://lore.kernel.org/r/20250303152511.494405-3-m.wilczynski@samsung.com
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
MAINTAINERS
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/reset-th1520.c [new file with mode: 0644]

index 88f9e8b7fa74b37ca1ab4185b29913b9ff33349e..10ec129c066d90ccd5171775c28aab55347dd1b7 100644 (file)
@@ -20833,6 +20833,7 @@ F:      drivers/mailbox/mailbox-th1520.c
 F:     drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c
 F:     drivers/pinctrl/pinctrl-th1520.c
 F:     drivers/pmdomain/thead/
+F:     drivers/reset/reset-th1520.c
 F:     include/dt-bindings/clock/thead,th1520-clk-ap.h
 F:     include/dt-bindings/power/thead,th1520-power.h
 F:     include/dt-bindings/reset/thead,th1520-reset.h
index 99f6f9784e6865faddf8621ccfca095778c4dc47..11ce86c8156b940ed3e07f00ef3ec058f6fd9fa0 100644 (file)
@@ -279,6 +279,16 @@ config RESET_SUNXI
        help
          This enables the reset driver for Allwinner SoCs.
 
+config RESET_TH1520
+       tristate "T-HEAD 1520 reset controller"
+       depends on ARCH_THEAD || COMPILE_TEST
+       select REGMAP_MMIO
+       help
+         This driver provides support for the T-HEAD TH1520 SoC reset controller,
+         which manages hardware reset lines for SoC components such as the GPU.
+         Enable this option if you need to control hardware resets on TH1520-based
+         systems.
+
 config RESET_TI_SCI
        tristate "TI System Control Interface (TI-SCI) reset driver"
        depends on TI_SCI_PROTOCOL || (COMPILE_TEST && TI_SCI_PROTOCOL=n)
index 31f9904d13f9c3a107fc1ee1ec9f9baba016d101..6322a191e2a82c4d75b65184b62f00dce1682727 100644 (file)
@@ -36,6 +36,7 @@ obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
 obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
+obj-$(CONFIG_RESET_TH1520) += reset-th1520.o
 obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
 obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
 obj-$(CONFIG_RESET_TI_TPS380X) += reset-tps380x.o
diff --git a/drivers/reset/reset-th1520.c b/drivers/reset/reset-th1520.c
new file mode 100644 (file)
index 0000000..7874f06
--- /dev/null
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Author: Michal Wilczynski <m.wilczynski@samsung.com>
+ */
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/reset/thead,th1520-reset.h>
+
+ /* register offset in VOSYS_REGMAP */
+#define TH1520_GPU_RST_CFG             0x0
+#define TH1520_GPU_RST_CFG_MASK                GENMASK(1, 0)
+
+/* register values */
+#define TH1520_GPU_SW_GPU_RST          BIT(0)
+#define TH1520_GPU_SW_CLKGEN_RST       BIT(1)
+
+struct th1520_reset_priv {
+       struct reset_controller_dev rcdev;
+       struct regmap *map;
+};
+
+struct th1520_reset_map {
+       u32 bit;
+       u32 reg;
+};
+
+static const struct th1520_reset_map th1520_resets[] = {
+       [TH1520_RESET_ID_GPU] = {
+               .bit = TH1520_GPU_SW_GPU_RST,
+               .reg = TH1520_GPU_RST_CFG,
+       },
+       [TH1520_RESET_ID_GPU_CLKGEN] = {
+               .bit = TH1520_GPU_SW_CLKGEN_RST,
+               .reg = TH1520_GPU_RST_CFG,
+       }
+};
+
+static inline struct th1520_reset_priv *
+to_th1520_reset(struct reset_controller_dev *rcdev)
+{
+       return container_of(rcdev, struct th1520_reset_priv, rcdev);
+}
+
+static int th1520_reset_assert(struct reset_controller_dev *rcdev,
+                              unsigned long id)
+{
+       struct th1520_reset_priv *priv = to_th1520_reset(rcdev);
+       const struct th1520_reset_map *reset;
+
+       reset = &th1520_resets[id];
+
+       return regmap_update_bits(priv->map, reset->reg, reset->bit, 0);
+}
+
+static int th1520_reset_deassert(struct reset_controller_dev *rcdev,
+                                unsigned long id)
+{
+       struct th1520_reset_priv *priv = to_th1520_reset(rcdev);
+       const struct th1520_reset_map *reset;
+
+       reset = &th1520_resets[id];
+
+       return regmap_update_bits(priv->map, reset->reg, reset->bit,
+                                 reset->bit);
+}
+
+static const struct reset_control_ops th1520_reset_ops = {
+       .assert = th1520_reset_assert,
+       .deassert = th1520_reset_deassert,
+};
+
+static const struct regmap_config th1520_reset_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+       .fast_io = true,
+};
+
+static int th1520_reset_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct th1520_reset_priv *priv;
+       void __iomem *base;
+       int ret;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       priv->map = devm_regmap_init_mmio(dev, base,
+                                         &th1520_reset_regmap_config);
+       if (IS_ERR(priv->map))
+               return PTR_ERR(priv->map);
+
+       /* Initialize GPU resets to asserted state */
+       ret = regmap_update_bits(priv->map, TH1520_GPU_RST_CFG,
+                                TH1520_GPU_RST_CFG_MASK, 0);
+       if (ret)
+               return ret;
+
+       priv->rcdev.owner = THIS_MODULE;
+       priv->rcdev.nr_resets = ARRAY_SIZE(th1520_resets);
+       priv->rcdev.ops = &th1520_reset_ops;
+       priv->rcdev.of_node = dev->of_node;
+
+       return devm_reset_controller_register(dev, &priv->rcdev);
+}
+
+static const struct of_device_id th1520_reset_match[] = {
+       { .compatible = "thead,th1520-reset" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, th1520_reset_match);
+
+static struct platform_driver th1520_reset_driver = {
+       .driver = {
+               .name = "th1520-reset",
+               .of_match_table = th1520_reset_match,
+       },
+       .probe = th1520_reset_probe,
+};
+module_platform_driver(th1520_reset_driver);
+
+MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
+MODULE_DESCRIPTION("T-HEAD TH1520 SoC reset controller");
+MODULE_LICENSE("GPL");