xref: /OK3568_Linux_fs/kernel/arch/arm/mach-omap2/powerdomain.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * OMAP2/3/4 powerdomain control
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2007-2008, 2010 Texas Instruments, Inc.
6*4882a593Smuzhiyun  * Copyright (C) 2007-2011 Nokia Corporation
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Paul Walmsley
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * XXX This should be moved to the mach-omap2/ directory at the earliest
11*4882a593Smuzhiyun  * opportunity.
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
15*4882a593Smuzhiyun #define __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <linux/types.h>
18*4882a593Smuzhiyun #include <linux/list.h>
19*4882a593Smuzhiyun #include <linux/spinlock.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /* Powerdomain basic power states */
22*4882a593Smuzhiyun #define PWRDM_POWER_OFF		0x0
23*4882a593Smuzhiyun #define PWRDM_POWER_RET		0x1
24*4882a593Smuzhiyun #define PWRDM_POWER_INACTIVE	0x2
25*4882a593Smuzhiyun #define PWRDM_POWER_ON		0x3
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define PWRDM_MAX_PWRSTS	4
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /* Powerdomain allowable state bitfields */
30*4882a593Smuzhiyun #define PWRSTS_ON		(1 << PWRDM_POWER_ON)
31*4882a593Smuzhiyun #define PWRSTS_INACTIVE		(1 << PWRDM_POWER_INACTIVE)
32*4882a593Smuzhiyun #define PWRSTS_RET		(1 << PWRDM_POWER_RET)
33*4882a593Smuzhiyun #define PWRSTS_OFF		(1 << PWRDM_POWER_OFF)
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define PWRSTS_OFF_ON		(PWRSTS_OFF | PWRSTS_ON)
36*4882a593Smuzhiyun #define PWRSTS_OFF_RET		(PWRSTS_OFF | PWRSTS_RET)
37*4882a593Smuzhiyun #define PWRSTS_RET_ON		(PWRSTS_RET | PWRSTS_ON)
38*4882a593Smuzhiyun #define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | PWRSTS_ON)
39*4882a593Smuzhiyun #define PWRSTS_INA_ON		(PWRSTS_INACTIVE | PWRSTS_ON)
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun  * Powerdomain flags (struct powerdomain.flags)
44*4882a593Smuzhiyun  *
45*4882a593Smuzhiyun  * PWRDM_HAS_HDWR_SAR - powerdomain has hardware save-and-restore support
46*4882a593Smuzhiyun  *
47*4882a593Smuzhiyun  * PWRDM_HAS_MPU_QUIRK - MPU pwr domain has MEM bank 0 bits in MEM
48*4882a593Smuzhiyun  * bank 1 position. This is true for OMAP3430
49*4882a593Smuzhiyun  *
50*4882a593Smuzhiyun  * PWRDM_HAS_LOWPOWERSTATECHANGE - can transition from a sleep state
51*4882a593Smuzhiyun  * to a lower sleep state without waking up the powerdomain
52*4882a593Smuzhiyun  */
53*4882a593Smuzhiyun #define PWRDM_HAS_HDWR_SAR		BIT(0)
54*4882a593Smuzhiyun #define PWRDM_HAS_MPU_QUIRK		BIT(1)
55*4882a593Smuzhiyun #define PWRDM_HAS_LOWPOWERSTATECHANGE	BIT(2)
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /*
58*4882a593Smuzhiyun  * Number of memory banks that are power-controllable.	On OMAP4430, the
59*4882a593Smuzhiyun  * maximum is 5.
60*4882a593Smuzhiyun  */
61*4882a593Smuzhiyun #define PWRDM_MAX_MEM_BANKS	5
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun /*
64*4882a593Smuzhiyun  * Maximum number of clockdomains that can be associated with a powerdomain.
65*4882a593Smuzhiyun  * PER powerdomain on AM33XX is the worst case
66*4882a593Smuzhiyun  */
67*4882a593Smuzhiyun #define PWRDM_MAX_CLKDMS	11
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun /* XXX A completely arbitrary number. What is reasonable here? */
70*4882a593Smuzhiyun #define PWRDM_TRANSITION_BAILOUT 100000
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun struct clockdomain;
73*4882a593Smuzhiyun struct powerdomain;
74*4882a593Smuzhiyun struct voltagedomain;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun /**
77*4882a593Smuzhiyun  * struct powerdomain - OMAP powerdomain
78*4882a593Smuzhiyun  * @name: Powerdomain name
79*4882a593Smuzhiyun  * @voltdm: voltagedomain containing this powerdomain
80*4882a593Smuzhiyun  * @prcm_offs: the address offset from CM_BASE/PRM_BASE
81*4882a593Smuzhiyun  * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs
82*4882a593Smuzhiyun  * @pwrsts: Possible powerdomain power states
83*4882a593Smuzhiyun  * @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION
84*4882a593Smuzhiyun  * @flags: Powerdomain flags
85*4882a593Smuzhiyun  * @banks: Number of software-controllable memory banks in this powerdomain
86*4882a593Smuzhiyun  * @pwrsts_mem_ret: Possible memory bank pwrstates when pwrdm in RETENTION
87*4882a593Smuzhiyun  * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON
88*4882a593Smuzhiyun  * @pwrdm_clkdms: Clockdomains in this powerdomain
89*4882a593Smuzhiyun  * @node: list_head linking all powerdomains
90*4882a593Smuzhiyun  * @voltdm_node: list_head linking all powerdomains in a voltagedomain
91*4882a593Smuzhiyun  * @pwrstctrl_offs: (AM33XX only) XXX_PWRSTCTRL reg offset from prcm_offs
92*4882a593Smuzhiyun  * @pwrstst_offs: (AM33XX only) XXX_PWRSTST reg offset from prcm_offs
93*4882a593Smuzhiyun  * @logicretstate_mask: (AM33XX only) mask for logic retention bitfield
94*4882a593Smuzhiyun  *	in @pwrstctrl_offs
95*4882a593Smuzhiyun  * @mem_on_mask: (AM33XX only) mask for mem on bitfield in @pwrstctrl_offs
96*4882a593Smuzhiyun  * @mem_ret_mask: (AM33XX only) mask for mem ret bitfield in @pwrstctrl_offs
97*4882a593Smuzhiyun  * @mem_pwrst_mask: (AM33XX only) mask for mem state bitfield in @pwrstst_offs
98*4882a593Smuzhiyun  * @mem_retst_mask: (AM33XX only) mask for mem retention state bitfield
99*4882a593Smuzhiyun  *	in @pwrstctrl_offs
100*4882a593Smuzhiyun  * @state:
101*4882a593Smuzhiyun  * @state_counter:
102*4882a593Smuzhiyun  * @timer:
103*4882a593Smuzhiyun  * @state_timer:
104*4882a593Smuzhiyun  * @_lock: spinlock used to serialize powerdomain and some clockdomain ops
105*4882a593Smuzhiyun  * @_lock_flags: stored flags when @_lock is taken
106*4882a593Smuzhiyun  *
107*4882a593Smuzhiyun  * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h.
108*4882a593Smuzhiyun  */
109*4882a593Smuzhiyun struct powerdomain {
110*4882a593Smuzhiyun 	const char *name;
111*4882a593Smuzhiyun 	union {
112*4882a593Smuzhiyun 		const char *name;
113*4882a593Smuzhiyun 		struct voltagedomain *ptr;
114*4882a593Smuzhiyun 	} voltdm;
115*4882a593Smuzhiyun 	const s16 prcm_offs;
116*4882a593Smuzhiyun 	const u8 pwrsts;
117*4882a593Smuzhiyun 	const u8 pwrsts_logic_ret;
118*4882a593Smuzhiyun 	const u8 flags;
119*4882a593Smuzhiyun 	const u8 banks;
120*4882a593Smuzhiyun 	const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS];
121*4882a593Smuzhiyun 	const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS];
122*4882a593Smuzhiyun 	const u8 prcm_partition;
123*4882a593Smuzhiyun 	struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
124*4882a593Smuzhiyun 	struct list_head node;
125*4882a593Smuzhiyun 	struct list_head voltdm_node;
126*4882a593Smuzhiyun 	int state;
127*4882a593Smuzhiyun 	unsigned state_counter[PWRDM_MAX_PWRSTS];
128*4882a593Smuzhiyun 	unsigned ret_logic_off_counter;
129*4882a593Smuzhiyun 	unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
130*4882a593Smuzhiyun 	spinlock_t _lock;
131*4882a593Smuzhiyun 	unsigned long _lock_flags;
132*4882a593Smuzhiyun 	const u8 pwrstctrl_offs;
133*4882a593Smuzhiyun 	const u8 pwrstst_offs;
134*4882a593Smuzhiyun 	const u32 logicretstate_mask;
135*4882a593Smuzhiyun 	const u32 mem_on_mask[PWRDM_MAX_MEM_BANKS];
136*4882a593Smuzhiyun 	const u32 mem_ret_mask[PWRDM_MAX_MEM_BANKS];
137*4882a593Smuzhiyun 	const u32 mem_pwrst_mask[PWRDM_MAX_MEM_BANKS];
138*4882a593Smuzhiyun 	const u32 mem_retst_mask[PWRDM_MAX_MEM_BANKS];
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun #ifdef CONFIG_PM_DEBUG
141*4882a593Smuzhiyun 	s64 timer;
142*4882a593Smuzhiyun 	s64 state_timer[PWRDM_MAX_PWRSTS];
143*4882a593Smuzhiyun #endif
144*4882a593Smuzhiyun 	u32 context;
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun /**
148*4882a593Smuzhiyun  * struct pwrdm_ops - Arch specific function implementations
149*4882a593Smuzhiyun  * @pwrdm_set_next_pwrst: Set the target power state for a pd
150*4882a593Smuzhiyun  * @pwrdm_read_next_pwrst: Read the target power state set for a pd
151*4882a593Smuzhiyun  * @pwrdm_read_pwrst: Read the current power state of a pd
152*4882a593Smuzhiyun  * @pwrdm_read_prev_pwrst: Read the prev power state entered by the pd
153*4882a593Smuzhiyun  * @pwrdm_set_logic_retst: Set the logic state in RET for a pd
154*4882a593Smuzhiyun  * @pwrdm_set_mem_onst: Set the Memory state in ON for a pd
155*4882a593Smuzhiyun  * @pwrdm_set_mem_retst: Set the Memory state in RET for a pd
156*4882a593Smuzhiyun  * @pwrdm_read_logic_pwrst: Read the current logic state of a pd
157*4882a593Smuzhiyun  * @pwrdm_read_prev_logic_pwrst: Read the previous logic state entered by a pd
158*4882a593Smuzhiyun  * @pwrdm_read_logic_retst: Read the logic state in RET for a pd
159*4882a593Smuzhiyun  * @pwrdm_read_mem_pwrst: Read the current memory state of a pd
160*4882a593Smuzhiyun  * @pwrdm_read_prev_mem_pwrst: Read the previous memory state entered by a pd
161*4882a593Smuzhiyun  * @pwrdm_read_mem_retst: Read the memory state in RET for a pd
162*4882a593Smuzhiyun  * @pwrdm_clear_all_prev_pwrst: Clear all previous power states logged for a pd
163*4882a593Smuzhiyun  * @pwrdm_enable_hdwr_sar: Enable Hardware Save-Restore feature for the pd
164*4882a593Smuzhiyun  * @pwrdm_disable_hdwr_sar: Disable Hardware Save-Restore feature for a pd
165*4882a593Smuzhiyun  * @pwrdm_set_lowpwrstchange: Enable pd transitions from a shallow to deep sleep
166*4882a593Smuzhiyun  * @pwrdm_wait_transition: Wait for a pd state transition to complete
167*4882a593Smuzhiyun  * @pwrdm_has_voltdm: Check if a voltdm association is needed
168*4882a593Smuzhiyun  *
169*4882a593Smuzhiyun  * Regarding @pwrdm_set_lowpwrstchange: On the OMAP2 and 3-family
170*4882a593Smuzhiyun  * chips, a powerdomain's power state is not allowed to directly
171*4882a593Smuzhiyun  * transition from one low-power state (e.g., CSWR) to another
172*4882a593Smuzhiyun  * low-power state (e.g., OFF) without first waking up the
173*4882a593Smuzhiyun  * powerdomain.  This wastes energy.  So OMAP4 chips support the
174*4882a593Smuzhiyun  * ability to transition a powerdomain power state directly from one
175*4882a593Smuzhiyun  * low-power state to another.  The function pointed to by
176*4882a593Smuzhiyun  * @pwrdm_set_lowpwrstchange is intended to configure the OMAP4
177*4882a593Smuzhiyun  * hardware powerdomain state machine to enable this feature.
178*4882a593Smuzhiyun  */
179*4882a593Smuzhiyun struct pwrdm_ops {
180*4882a593Smuzhiyun 	int	(*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
181*4882a593Smuzhiyun 	int	(*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
182*4882a593Smuzhiyun 	int	(*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
183*4882a593Smuzhiyun 	int	(*pwrdm_read_prev_pwrst)(struct powerdomain *pwrdm);
184*4882a593Smuzhiyun 	int	(*pwrdm_set_logic_retst)(struct powerdomain *pwrdm, u8 pwrst);
185*4882a593Smuzhiyun 	int	(*pwrdm_set_mem_onst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
186*4882a593Smuzhiyun 	int	(*pwrdm_set_mem_retst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
187*4882a593Smuzhiyun 	int	(*pwrdm_read_logic_pwrst)(struct powerdomain *pwrdm);
188*4882a593Smuzhiyun 	int	(*pwrdm_read_prev_logic_pwrst)(struct powerdomain *pwrdm);
189*4882a593Smuzhiyun 	int	(*pwrdm_read_logic_retst)(struct powerdomain *pwrdm);
190*4882a593Smuzhiyun 	int	(*pwrdm_read_mem_pwrst)(struct powerdomain *pwrdm, u8 bank);
191*4882a593Smuzhiyun 	int	(*pwrdm_read_prev_mem_pwrst)(struct powerdomain *pwrdm, u8 bank);
192*4882a593Smuzhiyun 	int	(*pwrdm_read_mem_retst)(struct powerdomain *pwrdm, u8 bank);
193*4882a593Smuzhiyun 	int	(*pwrdm_clear_all_prev_pwrst)(struct powerdomain *pwrdm);
194*4882a593Smuzhiyun 	int	(*pwrdm_enable_hdwr_sar)(struct powerdomain *pwrdm);
195*4882a593Smuzhiyun 	int	(*pwrdm_disable_hdwr_sar)(struct powerdomain *pwrdm);
196*4882a593Smuzhiyun 	int	(*pwrdm_set_lowpwrstchange)(struct powerdomain *pwrdm);
197*4882a593Smuzhiyun 	int	(*pwrdm_wait_transition)(struct powerdomain *pwrdm);
198*4882a593Smuzhiyun 	int	(*pwrdm_has_voltdm)(void);
199*4882a593Smuzhiyun 	void	(*pwrdm_save_context)(struct powerdomain *pwrdm);
200*4882a593Smuzhiyun 	void	(*pwrdm_restore_context)(struct powerdomain *pwrdm);
201*4882a593Smuzhiyun };
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
204*4882a593Smuzhiyun int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
205*4882a593Smuzhiyun int pwrdm_complete_init(void);
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun struct powerdomain *pwrdm_lookup(const char *name);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
210*4882a593Smuzhiyun 			void *user);
211*4882a593Smuzhiyun int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
212*4882a593Smuzhiyun 			void *user);
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun u8 pwrdm_get_valid_lp_state(struct powerdomain *pwrdm,
219*4882a593Smuzhiyun 			    bool is_logic_state, u8 req_state);
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
222*4882a593Smuzhiyun int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
223*4882a593Smuzhiyun int pwrdm_read_pwrst(struct powerdomain *pwrdm);
224*4882a593Smuzhiyun int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
225*4882a593Smuzhiyun int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
228*4882a593Smuzhiyun int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
229*4882a593Smuzhiyun int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm);
232*4882a593Smuzhiyun int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm);
233*4882a593Smuzhiyun int pwrdm_read_logic_retst(struct powerdomain *pwrdm);
234*4882a593Smuzhiyun int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
235*4882a593Smuzhiyun int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
236*4882a593Smuzhiyun int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm);
239*4882a593Smuzhiyun int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm);
240*4882a593Smuzhiyun bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun int pwrdm_state_switch_nolock(struct powerdomain *pwrdm);
243*4882a593Smuzhiyun int pwrdm_state_switch(struct powerdomain *pwrdm);
244*4882a593Smuzhiyun int pwrdm_pre_transition(struct powerdomain *pwrdm);
245*4882a593Smuzhiyun int pwrdm_post_transition(struct powerdomain *pwrdm);
246*4882a593Smuzhiyun int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
247*4882a593Smuzhiyun bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state);
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun extern void omap242x_powerdomains_init(void);
252*4882a593Smuzhiyun extern void omap243x_powerdomains_init(void);
253*4882a593Smuzhiyun extern void omap3xxx_powerdomains_init(void);
254*4882a593Smuzhiyun extern void am33xx_powerdomains_init(void);
255*4882a593Smuzhiyun extern void omap44xx_powerdomains_init(void);
256*4882a593Smuzhiyun extern void omap54xx_powerdomains_init(void);
257*4882a593Smuzhiyun extern void dra7xx_powerdomains_init(void);
258*4882a593Smuzhiyun void am43xx_powerdomains_init(void);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun extern struct pwrdm_ops omap2_pwrdm_operations;
261*4882a593Smuzhiyun extern struct pwrdm_ops omap3_pwrdm_operations;
262*4882a593Smuzhiyun extern struct pwrdm_ops am33xx_pwrdm_operations;
263*4882a593Smuzhiyun extern struct pwrdm_ops omap4_pwrdm_operations;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun /* Common Internal functions used across OMAP rev's */
266*4882a593Smuzhiyun extern u32 omap2_pwrdm_get_mem_bank_onstate_mask(u8 bank);
267*4882a593Smuzhiyun extern u32 omap2_pwrdm_get_mem_bank_retst_mask(u8 bank);
268*4882a593Smuzhiyun extern u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun extern struct powerdomain wkup_omap2_pwrdm;
271*4882a593Smuzhiyun extern struct powerdomain gfx_omap2_pwrdm;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun extern void pwrdm_lock(struct powerdomain *pwrdm);
274*4882a593Smuzhiyun extern void pwrdm_unlock(struct powerdomain *pwrdm);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun extern void pwrdms_save_context(void);
277*4882a593Smuzhiyun extern void pwrdms_restore_context(void);
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun extern void pwrdms_lost_power(void);
280*4882a593Smuzhiyun #endif
281