Add power management register operations to support reboot and poweroff. Signed-off-by: Qing Zhang <zhangqing@xxxxxxxxxxx> --- .../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