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