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