[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210414012622.23610-1-zhangqing@loongson.cn>
Date: Wed, 14 Apr 2021 09:26:22 +0800
From: Qing Zhang <zhangqing@...ngson.cn>
To: Thomas Bogendoerfer <tsbogend@...ha.franken.de>,
Jiaxun Yang <jiaxun.yang@...goat.com>,
Huacai Chen <chenhuacai@...nel.org>
Cc: linux-mips@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH] MIPS: Loongson64: Add Loongson-2K1000 reset support
Add power management register operations to support reboot and poweroff.
Signed-off-by: Qing Zhang <zhangqing@...ngson.cn>
---
.../include/asm/mach-loongson64/loongson.h | 8 ++++++
arch/mips/loongson64/reset.c | 28 ++++++++++++++++---
2 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/arch/mips/include/asm/mach-loongson64/loongson.h b/arch/mips/include/asm/mach-loongson64/loongson.h
index f7c3ab6d724e..9d254a7b438a 100644
--- a/arch/mips/include/asm/mach-loongson64/loongson.h
+++ b/arch/mips/include/asm/mach-loongson64/loongson.h
@@ -263,4 +263,12 @@ extern u64 loongson_freqctrl[MAX_PACKAGES];
#define LOONGSON_PCIMAP_WIN(WIN, ADDR) \
((((ADDR)>>26) & LOONGSON_PCIMAP_PCIMAP_LO0) << ((WIN)*6))
+/* Loongson-2K1000 Power management related registers */
+#define PM1_STS 0x0C /* Power Management1 Status Register */
+#define PM1_CNT 0x14 /* Power Management 1 Control Register */
+#define RST_CNT 0x30 /* Reset Control Register */
+#define SLP_TYP GENMASK(12, 10) /* Sleep Enable */
+#define SLP_EN BIT(13) /* Soft Off */
+#define ACPI_OFF 0x7000
+
#endif /* __ASM_MACH_LOONGSON64_LOONGSON_H */
diff --git a/arch/mips/loongson64/reset.c b/arch/mips/loongson64/reset.c
index 3bb8a1ed9348..b4348bf50538 100644
--- a/arch/mips/loongson64/reset.c
+++ b/arch/mips/loongson64/reset.c
@@ -18,9 +18,16 @@
static void loongson_restart(char *command)
{
- void (*fw_restart)(void) = (void *)loongson_sysconf.restart_addr;
+ if ((read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64R) {
+ unsigned long base;
- fw_restart();
+ base = CKSEG1ADDR(LOONGSON_REG_BASE) + ACPI_OFF;
+ writel(1, (void *)(base + RST_CNT));
+ } else {
+ void (*fw_restart)(void) = (void *)loongson_sysconf.restart_addr;
+
+ fw_restart();
+ }
while (1) {
if (cpu_wait)
cpu_wait();
@@ -29,9 +36,22 @@ static void loongson_restart(char *command)
static void loongson_poweroff(void)
{
- void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
- fw_poweroff();
+ if ((read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64R) {
+ unsigned long base;
+ unsigned int acpi_ctrl;
+
+ base = CKSEG1ADDR(LOONGSON_REG_BASE) + ACPI_OFF;
+ acpi_ctrl = readl((void *)(base + PM1_STS));
+ acpi_ctrl &= 0xffffffff;
+ writel(acpi_ctrl, (void *)(base + PM1_STS));
+ acpi_ctrl = SLP_EN | SLP_TYP;
+ writel(acpi_ctrl, (void *)(base + PM1_CNT));
+ } else {
+ void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
+
+ fw_poweroff();
+ }
while (1) {
if (cpu_wait)
cpu_wait();
--
2.31.0
Powered by blists - more mailing lists