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