1 | // SPDX-License-Identifier: GPL-2.0-only |
---|---|
2 | /* |
3 | * Power Management driver for Marvell Kirkwood SoCs |
4 | * |
5 | * Copyright (C) 2013 Ezequiel Garcia <ezequiel@free-electrons.com> |
6 | * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com> |
7 | */ |
8 | |
9 | #include <linux/kernel.h> |
10 | #include <linux/suspend.h> |
11 | #include <linux/io.h> |
12 | #include "kirkwood.h" |
13 | #include "kirkwood-pm.h" |
14 | |
15 | static void __iomem *ddr_operation_base; |
16 | static void __iomem *memory_pm_ctrl; |
17 | |
18 | static void kirkwood_low_power(void) |
19 | { |
20 | u32 mem_pm_ctrl; |
21 | |
22 | mem_pm_ctrl = readl(addr: memory_pm_ctrl); |
23 | |
24 | /* Set peripherals to low-power mode */ |
25 | writel_relaxed(~0, memory_pm_ctrl); |
26 | |
27 | /* Set DDR in self-refresh */ |
28 | writel_relaxed(0x7, ddr_operation_base); |
29 | |
30 | /* |
31 | * Set CPU in wait-for-interrupt state. |
32 | * This disables the CPU core clocks, |
33 | * the array clocks, and also the L2 controller. |
34 | */ |
35 | cpu_do_idle(); |
36 | |
37 | writel_relaxed(mem_pm_ctrl, memory_pm_ctrl); |
38 | } |
39 | |
40 | static int kirkwood_suspend_enter(suspend_state_t state) |
41 | { |
42 | switch (state) { |
43 | case PM_SUSPEND_STANDBY: |
44 | kirkwood_low_power(); |
45 | break; |
46 | default: |
47 | return -EINVAL; |
48 | } |
49 | return 0; |
50 | } |
51 | |
52 | static int kirkwood_pm_valid_standby(suspend_state_t state) |
53 | { |
54 | return state == PM_SUSPEND_STANDBY; |
55 | } |
56 | |
57 | static const struct platform_suspend_ops kirkwood_suspend_ops = { |
58 | .enter = kirkwood_suspend_enter, |
59 | .valid = kirkwood_pm_valid_standby, |
60 | }; |
61 | |
62 | void __init kirkwood_pm_init(void) |
63 | { |
64 | ddr_operation_base = ioremap(DDR_OPERATION_BASE, size: 4); |
65 | memory_pm_ctrl = ioremap(MEMORY_PM_CTRL_PHYS, size: 4); |
66 | |
67 | suspend_set_ops(ops: &kirkwood_suspend_ops); |
68 | } |
69 |