1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * power management entry for CSR SiRFprimaII 4 * 5 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. 6 */ 7 8#include <linux/kernel.h> 9#include <linux/suspend.h> 10#include <linux/slab.h> 11#include <linux/export.h> 12#include <linux/of.h> 13#include <linux/of_address.h> 14#include <linux/of_device.h> 15#include <linux/of_platform.h> 16#include <linux/io.h> 17#include <linux/rtc/sirfsoc_rtciobrg.h> 18#include <asm/outercache.h> 19#include <asm/suspend.h> 20#include <asm/hardware/cache-l2x0.h> 21 22#include "pm.h" 23 24/* 25 * suspend asm codes will access these to make DRAM become self-refresh and 26 * system sleep 27 */ 28u32 sirfsoc_pwrc_base; 29void __iomem *sirfsoc_memc_base; 30 31static void sirfsoc_set_wakeup_source(void) 32{ 33 u32 pwr_trigger_en_reg; 34 pwr_trigger_en_reg = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base + 35 SIRFSOC_PWRC_TRIGGER_EN); 36#define X_ON_KEY_B (1 << 0) 37#define RTC_ALARM0_B (1 << 2) 38#define RTC_ALARM1_B (1 << 3) 39 sirfsoc_rtc_iobrg_writel(pwr_trigger_en_reg | X_ON_KEY_B | 40 RTC_ALARM0_B | RTC_ALARM1_B, 41 sirfsoc_pwrc_base + SIRFSOC_PWRC_TRIGGER_EN); 42} 43 44static void sirfsoc_set_sleep_mode(u32 mode) 45{ 46 u32 sleep_mode = sirfsoc_rtc_iobrg_readl(sirfsoc_pwrc_base + 47 SIRFSOC_PWRC_PDN_CTRL); 48 sleep_mode &= ~(SIRFSOC_SLEEP_MODE_MASK << 1); 49 sleep_mode |= mode << 1; 50 sirfsoc_rtc_iobrg_writel(sleep_mode, sirfsoc_pwrc_base + 51 SIRFSOC_PWRC_PDN_CTRL); 52} 53 54static int sirfsoc_pre_suspend_power_off(void) 55{ 56 u32 wakeup_entry = __pa_symbol(cpu_resume); 57 58 sirfsoc_rtc_iobrg_writel(wakeup_entry, sirfsoc_pwrc_base + 59 SIRFSOC_PWRC_SCRATCH_PAD1); 60 61 sirfsoc_set_wakeup_source(); 62 63 sirfsoc_set_sleep_mode(SIRFSOC_DEEP_SLEEP_MODE); 64 65 return 0; 66} 67 68static int sirfsoc_pm_enter(suspend_state_t state) 69{ 70 switch (state) { 71 case PM_SUSPEND_MEM: 72 sirfsoc_pre_suspend_power_off(); 73 74 outer_disable(); 75 /* go zzz */ 76 cpu_suspend(0, sirfsoc_finish_suspend); 77 outer_resume(); 78 break; 79 default: 80 return -EINVAL; 81 } 82 return 0; 83} 84 85static const struct platform_suspend_ops sirfsoc_pm_ops = { 86 .enter = sirfsoc_pm_enter, 87 .valid = suspend_valid_only_mem, 88}; 89 90static const struct of_device_id pwrc_ids[] = { 91 { .compatible = "sirf,prima2-pwrc" }, 92 {} 93}; 94 95static int __init sirfsoc_of_pwrc_init(void) 96{ 97 struct device_node *np; 98 99 np = of_find_matching_node(NULL, pwrc_ids); 100 if (!np) { 101 pr_err("unable to find compatible sirf pwrc node in dtb\n"); 102 return -ENOENT; 103 } 104 105 /* 106 * pwrc behind rtciobrg is not located in memory space 107 * though the property is named reg. reg only means base 108 * offset for pwrc. then of_iomap is not suitable here. 109 */ 110 if (of_property_read_u32(np, "reg", &sirfsoc_pwrc_base)) 111 panic("unable to find base address of pwrc node in dtb\n"); 112 113 of_node_put(np); 114 115 return 0; 116} 117 118static const struct of_device_id memc_ids[] = { 119 { .compatible = "sirf,prima2-memc" }, 120 {} 121}; 122 123static int sirfsoc_memc_probe(struct platform_device *op) 124{ 125 struct device_node *np = op->dev.of_node; 126 127 sirfsoc_memc_base = of_iomap(np, 0); 128 if (!sirfsoc_memc_base) 129 panic("unable to map memc registers\n"); 130 131 return 0; 132} 133 134static struct platform_driver sirfsoc_memc_driver = { 135 .probe = sirfsoc_memc_probe, 136 .driver = { 137 .name = "sirfsoc-memc", 138 .of_match_table = memc_ids, 139 }, 140}; 141 142static int __init sirfsoc_memc_init(void) 143{ 144 return platform_driver_register(&sirfsoc_memc_driver); 145} 146 147int __init sirfsoc_pm_init(void) 148{ 149 sirfsoc_of_pwrc_init(); 150 sirfsoc_memc_init(); 151 suspend_set_ops(&sirfsoc_pm_ops); 152 return 0; 153} 154