diff mbox series

[09/10] power: reset: cv18xx: New driver

Message ID 20250209220646.1090868-10-alexander.sverdlin@gmail.com
State New
Headers show
Series arm64 support for Milk-V Duo Module 01 EVB | expand

Commit Message

Alexander Sverdlin Feb. 9, 2025, 10:06 p.m. UTC
Add new driver to support cold and warm reset on Cvitek CV18xx and Sophgo
SG2000 SoCs.

Link: https://github.com/sophgo/sophgo-doc/releases/download/sg2000-trm-v1.01/sg2000_trm_en.pdf
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
 MAINTAINERS                        |  1 +
 drivers/power/reset/Kconfig        | 12 ++++
 drivers/power/reset/Makefile       |  1 +
 drivers/power/reset/cv18xx-reset.c | 89 ++++++++++++++++++++++++++++++
 4 files changed, 103 insertions(+)
 create mode 100644 drivers/power/reset/cv18xx-reset.c
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index e4f5d8f68581..b7fec02f7673 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22147,6 +22147,7 @@  M:	Chen Wang <unicorn_wang@outlook.com>
 M:	Inochi Amaoto <inochiama@outlook.com>
 T:	git https://github.com/sophgo/linux.git
 S:	Maintained
+F:	drivers/power/reset/cv18xx-reset.c
 N:	sophgo
 K:	sophgo
 
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 60bf0ca64cf3..d41ed3c2a30d 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -75,6 +75,18 @@  config POWER_RESET_BRCMSTB
 	  Say Y here if you have a Broadcom STB board and you wish
 	  to have restart support.
 
+config POWER_RESET_CV18XX
+	bool "Cvitek CV18XX/Sophgo SG2000 reset driver"
+	depends on ARCH_SOPHGO || COMPILE_TEST
+	depends on MFD_SYSCON
+	default ARCH_SOPHGO
+	help
+	  This driver provides restart support for Cvitek CV18xx and
+	  Sophgo SG2000 SoCs.
+
+	  Say Y here if you have a Cvitek CV18xx or Sophgo SG2000 SoC and
+	  you wish to have restart support.
+
 config POWER_RESET_EP93XX
 	bool "Cirrus EP93XX reset driver" if COMPILE_TEST
 	depends on MFD_SYSCON
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 10782d32e1da..ce24e74e0477 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -7,6 +7,7 @@  obj-$(CONFIG_POWER_RESET_ATC260X) += atc260x-poweroff.o
 obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
 obj-$(CONFIG_POWER_RESET_BRCMKONA) += brcm-kona-reset.o
 obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
+obj-$(CONFIG_POWER_RESET_CV18XX) += cv18xx-reset.o
 obj-$(CONFIG_POWER_RESET_EP93XX) += ep93xx-restart.o
 obj-$(CONFIG_POWER_RESET_GEMINI_POWEROFF) += gemini-poweroff.o
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
diff --git a/drivers/power/reset/cv18xx-reset.c b/drivers/power/reset/cv18xx-reset.c
new file mode 100644
index 000000000000..bc1797e7d3f5
--- /dev/null
+++ b/drivers/power/reset/cv18xx-reset.c
@@ -0,0 +1,89 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* RTCSYS_CTRL registers */
+#define RTC_CTRL_UNLOCKKEY		0x04
+#define RTC_CTRL0			0x08
+#define  REQ_PWR_CYC			BIT(3)
+#define  REQ_WARM_RST			BIT(4)
+
+/* RTCSYS_CORE registers */
+#define RTC_EN_PWR_CYC_REQ		0xC8
+#define RTC_EN_WARM_RST_REQ		0xCC
+
+static struct regmap *rtcsys_ctrl_regs;
+static struct regmap *rtcsys_core_regs;
+
+static int cv18xx_restart_handler(struct sys_off_data *data)
+{
+	u32 reg_en = RTC_EN_WARM_RST_REQ;
+	u32 request = 0xFFFF0800;
+
+	if (data->mode == REBOOT_COLD) {
+		reg_en = RTC_EN_PWR_CYC_REQ;
+		request |= REQ_PWR_CYC;
+	} else {
+		request |= REQ_WARM_RST;
+	}
+
+	/* Enable reset request */
+	regmap_write(rtcsys_core_regs, reg_en, 1);
+	/* Enable CTRL0 register access */
+	regmap_write(rtcsys_ctrl_regs, RTC_CTRL_UNLOCKKEY, 0xAB18);
+	/* Request reset */
+	regmap_write(rtcsys_ctrl_regs, RTC_CTRL0, request);
+
+	return NOTIFY_DONE;
+}
+
+static int cv18xx_reset_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	int ret;
+
+	if (!np)
+		return -ENODEV;
+
+	rtcsys_ctrl_regs = syscon_regmap_lookup_by_phandle(np, "sophgo,rtcsys-ctrl");
+	if (IS_ERR(rtcsys_ctrl_regs))
+		return dev_err_probe(dev, PTR_ERR(rtcsys_ctrl_regs),
+				     "sophgo,rtcsys-ctrl lookup failed\n");
+
+	rtcsys_core_regs = syscon_regmap_lookup_by_phandle(np, "sophgo,rtcsys-core");
+	if (IS_ERR(rtcsys_core_regs))
+		return dev_err_probe(dev, PTR_ERR(rtcsys_core_regs),
+				     "sophgo,rtcsys-core lookup failed\n");
+
+	ret = devm_register_restart_handler(&pdev->dev, cv18xx_restart_handler, NULL);
+	if (ret)
+		dev_err(&pdev->dev, "Cannot register restart handler (%pe)\n", ERR_PTR(ret));
+	return ret;
+}
+
+static const struct of_device_id cv18xx_reset_of_match[] = {
+	{ .compatible = "sophgo,cv1800-reset" },
+	{}
+};
+MODULE_DEVICE_TABLE(platform, cv18xx_reset_of_match);
+
+static struct platform_driver cv18xx_reset_driver = {
+	.probe = cv18xx_reset_probe,
+	.driver = {
+		.name = "cv18xx-reset",
+		.of_match_table = cv18xx_reset_of_match,
+	},
+};
+module_platform_driver(cv18xx_reset_driver);
+
+MODULE_AUTHOR("Alexander Sverdlin <alexander.sverdlin@gmail.com>");
+MODULE_DESCRIPTION("Cvitek CV18xx/Sophgo SG2000 Reset Driver");
+MODULE_ALIAS("platform:cv18xx-reset");