1/* 2 * Power Management driver for Marvell Kirkwood SoCs 3 * 4 * Copyright (C) 2013 Ezequiel Garcia <ezequiel@free-electrons.com> 5 * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License, 9 * version 2 of the License. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17#include <linux/kernel.h> 18#include <linux/suspend.h> 19#include <linux/io.h> 20#include "kirkwood.h" 21 22static void __iomem *ddr_operation_base; 23static void __iomem *memory_pm_ctrl; 24 25static void kirkwood_low_power(void) 26{ 27 u32 mem_pm_ctrl; 28 29 mem_pm_ctrl = readl(memory_pm_ctrl); 30 31 /* Set peripherals to low-power mode */ 32 writel_relaxed(~0, memory_pm_ctrl); 33 34 /* Set DDR in self-refresh */ 35 writel_relaxed(0x7, ddr_operation_base); 36 37 /* 38 * Set CPU in wait-for-interrupt state. 39 * This disables the CPU core clocks, 40 * the array clocks, and also the L2 controller. 41 */ 42 cpu_do_idle(); 43 44 writel_relaxed(mem_pm_ctrl, memory_pm_ctrl); 45} 46 47static int kirkwood_suspend_enter(suspend_state_t state) 48{ 49 switch (state) { 50 case PM_SUSPEND_STANDBY: 51 kirkwood_low_power(); 52 break; 53 default: 54 return -EINVAL; 55 } 56 return 0; 57} 58 59static int kirkwood_pm_valid_standby(suspend_state_t state) 60{ 61 return state == PM_SUSPEND_STANDBY; 62} 63 64static const struct platform_suspend_ops kirkwood_suspend_ops = { 65 .enter = kirkwood_suspend_enter, 66 .valid = kirkwood_pm_valid_standby, 67}; 68 69int __init kirkwood_pm_init(void) 70{ 71 ddr_operation_base = ioremap(DDR_OPERATION_BASE, 4); 72 memory_pm_ctrl = ioremap(MEMORY_PM_CTRL_PHYS, 4); 73 74 suspend_set_ops(&kirkwood_suspend_ops); 75 return 0; 76} 77