1 | // SPDX-License-Identifier: GPL-2.0 |
---|---|
2 | /* |
3 | * Copyright (C) 2021, Qing Zhang <zhangqing@loongson.cn> |
4 | * Loongson-2K1000 reset support |
5 | */ |
6 | |
7 | #include <linux/of_address.h> |
8 | #include <linux/pm.h> |
9 | #include <asm/reboot.h> |
10 | |
11 | #define PM1_STS 0x0c /* Power Management 1 Status Register */ |
12 | #define PM1_CNT 0x14 /* Power Management 1 Control Register */ |
13 | #define RST_CNT 0x30 /* Reset Control Register */ |
14 | |
15 | static void __iomem *base; |
16 | |
17 | static void ls2k_restart(char *command) |
18 | { |
19 | writel(val: 0x1, addr: base + RST_CNT); |
20 | } |
21 | |
22 | static void ls2k_poweroff(void) |
23 | { |
24 | /* Clear */ |
25 | writel(val: (readl(addr: base + PM1_STS) & 0xffffffff), addr: base + PM1_STS); |
26 | /* Sleep Enable | Soft Off*/ |
27 | writel(GENMASK(12, 10) | BIT(13), addr: base + PM1_CNT); |
28 | } |
29 | |
30 | static int ls2k_reset_init(void) |
31 | { |
32 | struct device_node *np; |
33 | |
34 | np = of_find_compatible_node(NULL, NULL, compat: "loongson,ls2k-pm"); |
35 | if (!np) { |
36 | pr_info("Failed to get PM node\n"); |
37 | return -ENODEV; |
38 | } |
39 | |
40 | base = of_iomap(node: np, index: 0); |
41 | of_node_put(node: np); |
42 | if (!base) { |
43 | pr_info("Failed to map PM register base address\n"); |
44 | return -ENOMEM; |
45 | } |
46 | |
47 | _machine_restart = ls2k_restart; |
48 | pm_power_off = ls2k_poweroff; |
49 | |
50 | return 0; |
51 | } |
52 | |
53 | arch_initcall(ls2k_reset_init); |
54 |