summaryrefslogtreecommitdiff
path: root/include/soc/qcom/pm.h
blob: ea19c2562f660932fcb58e643faf4b3ca8a9025f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/*
 * Copyright (C) 2007 Google, Inc.
 * Copyright (c) 2009-2016, The Linux Foundation. All rights reserved.
 * Author: San Mehat <san@android.com>
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#ifndef __ARCH_ARM_MACH_MSM_PM_H
#define __ARCH_ARM_MACH_MSM_PM_H

#include <linux/types.h>
#include <linux/cpuidle.h>
#include <asm/smp_plat.h>
#include <asm/barrier.h>
#include <dt-bindings/msm/pm.h>

#if !defined(CONFIG_SMP)
#define msm_secondary_startup NULL
#elif defined(CONFIG_CPU_V7)
#define msm_secondary_startup secondary_startup
#else
#define msm_secondary_startup secondary_holding_pen
#endif

enum msm_pm_sleep_mode {
	MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
	MSM_PM_SLEEP_MODE_RETENTION,
	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
	MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
	MSM_PM_SLEEP_MODE_FASTPC,
	MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND,
	MSM_PM_SLEEP_MODE_NR,
	MSM_PM_SLEEP_MODE_NOT_SELECTED,
};

enum msm_pm_l2_scm_flag {
	MSM_SCM_L2_ON = 0,
	MSM_SCM_L2_OFF = 1,
	MSM_SCM_L2_GDHS = 3,
	MSM_SCM_L3_PC_OFF = 4,
};

#define MSM_PM_MODE(cpu, mode_nr)  ((cpu) * MSM_PM_SLEEP_MODE_NR + (mode_nr))

struct msm_pm_time_params {
	uint32_t latency_us;
	uint32_t sleep_us;
	uint32_t next_event_us;
	uint32_t modified_time_us;
};

struct msm_pm_sleep_status_data {
	void *base_addr;
	uint32_t mask;
};

struct latency_level {
	int affinity_level;
	int reset_level;
	const char *level_name;
};

/**
 * lpm_cpu_pre_pc_cb(): API to get the L2 flag to pass to TZ
 *
 * @cpu: cpuid of the CPU going down.
 *
 * Returns the l2 flush flag enum that is passed down to TZ during power
 * collaps
 */
enum msm_pm_l2_scm_flag lpm_cpu_pre_pc_cb(unsigned int cpu);

/**
 * msm_pm_sleep_mode_allow() - API to determine if sleep mode is allowed.
 * @cpu:	CPU on which to check for the sleep mode.
 * @mode:	Sleep Mode to check for.
 * @idle:	Idle or Suspend Sleep Mode.
 *
 * Helper function to determine if a Idle or Suspend
 * Sleep mode is allowed for a specific CPU.
 *
 * Return: 1 for allowed; 0 if not allowed.
 */
int msm_pm_sleep_mode_allow(unsigned int, unsigned int, bool);

/**
 * msm_pm_sleep_mode_supported() - API to determine if sleep mode is
 * supported.
 * @cpu:	CPU on which to check for the sleep mode.
 * @mode:	Sleep Mode to check for.
 * @idle:	Idle or Suspend Sleep Mode.
 *
 * Helper function to determine if a Idle or Suspend
 * Sleep mode is allowed and enabled for a specific CPU.
 *
 * Return: 1 for supported; 0 if not supported.
 */
int msm_pm_sleep_mode_supported(unsigned int, unsigned int, bool);

struct msm_pm_cpr_ops {
	void (*cpr_suspend)(void);
	void (*cpr_resume)(void);
};

void __init msm_pm_set_tz_retention_flag(unsigned int flag);
void msm_pm_enable_retention(bool enable);
bool msm_pm_retention_enabled(void);
bool msm_cpu_pm_enter_sleep(enum msm_pm_sleep_mode mode, bool from_idle);
static inline void msm_arch_idle(void)
{
	mb();
	wfi();
}

#ifdef CONFIG_MSM_PM

void msm_pm_set_rpm_wakeup_irq(unsigned int irq);
int msm_pm_wait_cpu_shutdown(unsigned int cpu);
int __init msm_pm_sleep_status_init(void);
void lpm_cpu_hotplug_enter(unsigned int cpu);
s32 msm_cpuidle_get_deep_idle_latency(void);
int msm_pm_collapse(unsigned long unused);

/**
 * lpm_get_latency() - API to get latency for a low power mode
 * @latency_level:	pointer to structure with below elements
 * affinity_level: The level (CPU/L2/CCI etc.) for which the
 *	latency is required.
 *	LPM_AFF_LVL_CPU : CPU level
 *	LPM_AFF_LVL_L2  : L2 level
 *	LPM_AFF_LVL_CCI : CCI level
 * reset_level: Can be passed "LPM_RESET_LVL_GDHS" for
 *	low power mode with control logic power collapse or
 *	"LPM_RESET_LVL_PC" for low power mode with control and
 *	memory logic power collapse or "LPM_RESET_LVL_RET" for
 *	retention mode.
 * level_name: Pointer to the cluster name for which the latency
 *	is required or NULL if the minimum value out of all the
 *	clusters is to be returned. For CPU level, the name of the
 *	L2 cluster to be passed. For CCI it has no effect.
 * @latency:	address to get the latency value.
 *
 * latency value will be for the particular cluster or the minimum
 * value out of all the clusters at the particular affinity_level
 * and reset_level.
 *
 * Return: 0 for success; Error number for failure.
 */
int lpm_get_latency(struct latency_level *level, uint32_t *latency);

#else
static inline void msm_pm_set_rpm_wakeup_irq(unsigned int irq) {}
static inline int msm_pm_wait_cpu_shutdown(unsigned int cpu) { return 0; }
static inline int msm_pm_sleep_status_init(void) { return 0; };

static inline void lpm_cpu_hotplug_enter(unsigned int cpu)
{
	msm_arch_idle();
};

static inline s32 msm_cpuidle_get_deep_idle_latency(void) { return 0; }
#define msm_pm_collapse NULL

static inline int lpm_get_latency(struct latency_level *level,
						uint32_t *latency)
{
	return 0;
}
#endif

#ifdef CONFIG_HOTPLUG_CPU
int msm_platform_secondary_init(unsigned int cpu);
#else
static inline int msm_platform_secondary_init(unsigned int cpu) { return 0; }
#endif

enum msm_pm_time_stats_id {
	MSM_PM_STAT_REQUESTED_IDLE = 0,
	MSM_PM_STAT_IDLE_SPIN,
	MSM_PM_STAT_IDLE_WFI,
	MSM_PM_STAT_RETENTION,
	MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
	MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE,
	MSM_PM_STAT_IDLE_POWER_COLLAPSE,
	MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE,
	MSM_PM_STAT_SUSPEND,
	MSM_PM_STAT_FAILED_SUSPEND,
	MSM_PM_STAT_NOT_IDLE,
	MSM_PM_STAT_COUNT
};

#ifdef CONFIG_MSM_IDLE_STATS
void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size);
void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t);
void msm_pm_l2_add_stat(uint32_t id, int64_t t);
#else
static inline void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats,
		int size) {}
static inline void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t) {}
static inline void msm_pm_l2_add_stat(uint32_t id, int64_t t) {}
#endif

void msm_pm_set_cpr_ops(struct msm_pm_cpr_ops *ops);
extern dma_addr_t msm_pc_debug_counters_phys;
#endif  /* __ARCH_ARM_MACH_MSM_PM_H */