1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * OMAP2/3 clockdomain framework functions 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 2008, 2012 Texas Instruments, Inc. 6*4882a593Smuzhiyun * Copyright (C) 2008-2011 Nokia Corporation 7*4882a593Smuzhiyun * 8*4882a593Smuzhiyun * Paul Walmsley 9*4882a593Smuzhiyun */ 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun #ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H 12*4882a593Smuzhiyun #define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun #include <linux/init.h> 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun #include "powerdomain.h" 17*4882a593Smuzhiyun #include "clock.h" 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun /* 20*4882a593Smuzhiyun * Clockdomain flags 21*4882a593Smuzhiyun * 22*4882a593Smuzhiyun * XXX Document CLKDM_CAN_* flags 23*4882a593Smuzhiyun * 24*4882a593Smuzhiyun * CLKDM_NO_AUTODEPS: Prevent "autodeps" from being added/removed from this 25*4882a593Smuzhiyun * clockdomain. (Currently, this applies to OMAP3 clockdomains only.) 26*4882a593Smuzhiyun * CLKDM_ACTIVE_WITH_MPU: The PRCM guarantees that this clockdomain is 27*4882a593Smuzhiyun * active whenever the MPU is active. True for interconnects and 28*4882a593Smuzhiyun * the WKUP clockdomains. 29*4882a593Smuzhiyun * CLKDM_MISSING_IDLE_REPORTING: The idle status of the IP blocks and 30*4882a593Smuzhiyun * clocks inside this clockdomain are not taken into account by 31*4882a593Smuzhiyun * the PRCM when determining whether the clockdomain is idle. 32*4882a593Smuzhiyun * Without this flag, if the clockdomain is set to 33*4882a593Smuzhiyun * hardware-supervised idle mode, the PRCM may transition the 34*4882a593Smuzhiyun * enclosing powerdomain to a low power state, even when devices 35*4882a593Smuzhiyun * inside the clockdomain and powerdomain are in use. (An example 36*4882a593Smuzhiyun * of such a clockdomain is the EMU clockdomain on OMAP3/4.) If 37*4882a593Smuzhiyun * this flag is set, and the clockdomain does not support the 38*4882a593Smuzhiyun * force-sleep mode, then the HW_AUTO mode will be used to put the 39*4882a593Smuzhiyun * clockdomain to sleep. Similarly, if the clockdomain supports 40*4882a593Smuzhiyun * the force-wakeup mode, then it will be used whenever a clock or 41*4882a593Smuzhiyun * IP block inside the clockdomain is active, rather than the 42*4882a593Smuzhiyun * HW_AUTO mode. 43*4882a593Smuzhiyun */ 44*4882a593Smuzhiyun #define CLKDM_CAN_FORCE_SLEEP (1 << 0) 45*4882a593Smuzhiyun #define CLKDM_CAN_FORCE_WAKEUP (1 << 1) 46*4882a593Smuzhiyun #define CLKDM_CAN_ENABLE_AUTO (1 << 2) 47*4882a593Smuzhiyun #define CLKDM_CAN_DISABLE_AUTO (1 << 3) 48*4882a593Smuzhiyun #define CLKDM_NO_AUTODEPS (1 << 4) 49*4882a593Smuzhiyun #define CLKDM_ACTIVE_WITH_MPU (1 << 5) 50*4882a593Smuzhiyun #define CLKDM_MISSING_IDLE_REPORTING (1 << 6) 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun #define CLKDM_CAN_HWSUP (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO) 53*4882a593Smuzhiyun #define CLKDM_CAN_SWSUP (CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP) 54*4882a593Smuzhiyun #define CLKDM_CAN_HWSUP_SWSUP (CLKDM_CAN_SWSUP | CLKDM_CAN_HWSUP) 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun /** 57*4882a593Smuzhiyun * struct clkdm_autodep - clkdm deps to add when entering/exiting hwsup mode 58*4882a593Smuzhiyun * @clkdm: clockdomain to add wkdep+sleepdep on - set name member only 59*4882a593Smuzhiyun * 60*4882a593Smuzhiyun * A clockdomain that should have wkdeps and sleepdeps added when a 61*4882a593Smuzhiyun * clockdomain should stay active in hwsup mode; and conversely, 62*4882a593Smuzhiyun * removed when the clockdomain should be allowed to go inactive in 63*4882a593Smuzhiyun * hwsup mode. 64*4882a593Smuzhiyun * 65*4882a593Smuzhiyun * Autodeps are deprecated and should be removed after 66*4882a593Smuzhiyun * omap_hwmod-based fine-grained module idle control is added. 67*4882a593Smuzhiyun */ 68*4882a593Smuzhiyun struct clkdm_autodep { 69*4882a593Smuzhiyun union { 70*4882a593Smuzhiyun const char *name; 71*4882a593Smuzhiyun struct clockdomain *ptr; 72*4882a593Smuzhiyun } clkdm; 73*4882a593Smuzhiyun }; 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun /** 76*4882a593Smuzhiyun * struct clkdm_dep - encode dependencies between clockdomains 77*4882a593Smuzhiyun * @clkdm_name: clockdomain name 78*4882a593Smuzhiyun * @clkdm: pointer to the struct clockdomain of @clkdm_name 79*4882a593Smuzhiyun * @wkdep_usecount: Number of wakeup dependencies causing this clkdm to wake 80*4882a593Smuzhiyun * @sleepdep_usecount: Number of sleep deps that could prevent clkdm from idle 81*4882a593Smuzhiyun * 82*4882a593Smuzhiyun * Statically defined. @clkdm is resolved from @clkdm_name at runtime and 83*4882a593Smuzhiyun * should not be pre-initialized. 84*4882a593Smuzhiyun * 85*4882a593Smuzhiyun * XXX Should also include hardware (fixed) dependencies. 86*4882a593Smuzhiyun */ 87*4882a593Smuzhiyun struct clkdm_dep { 88*4882a593Smuzhiyun const char *clkdm_name; 89*4882a593Smuzhiyun struct clockdomain *clkdm; 90*4882a593Smuzhiyun s16 wkdep_usecount; 91*4882a593Smuzhiyun s16 sleepdep_usecount; 92*4882a593Smuzhiyun }; 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun /* Possible flags for struct clockdomain._flags */ 95*4882a593Smuzhiyun #define _CLKDM_FLAG_HWSUP_ENABLED BIT(0) 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun struct omap_hwmod; 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun /** 100*4882a593Smuzhiyun * struct clockdomain - OMAP clockdomain 101*4882a593Smuzhiyun * @name: clockdomain name 102*4882a593Smuzhiyun * @pwrdm: powerdomain containing this clockdomain 103*4882a593Smuzhiyun * @clktrctrl_reg: CLKSTCTRL reg for the given clock domain 104*4882a593Smuzhiyun * @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg 105*4882a593Smuzhiyun * @flags: Clockdomain capability flags 106*4882a593Smuzhiyun * @_flags: Flags for use only by internal clockdomain code 107*4882a593Smuzhiyun * @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit 108*4882a593Smuzhiyun * @prcm_partition: (OMAP4 only) PRCM partition ID for this clkdm's registers 109*4882a593Smuzhiyun * @cm_inst: (OMAP4 only) CM instance register offset 110*4882a593Smuzhiyun * @clkdm_offs: (OMAP4 only) CM clockdomain register offset 111*4882a593Smuzhiyun * @wkdep_srcs: Clockdomains that can be told to wake this powerdomain up 112*4882a593Smuzhiyun * @sleepdep_srcs: Clockdomains that can be told to keep this clkdm from inact 113*4882a593Smuzhiyun * @usecount: Usecount tracking 114*4882a593Smuzhiyun * @forcewake_count: Usecount for forcing the domain active 115*4882a593Smuzhiyun * @node: list_head to link all clockdomains together 116*4882a593Smuzhiyun * 117*4882a593Smuzhiyun * @prcm_partition should be a macro from mach-omap2/prcm44xx.h (OMAP4 only) 118*4882a593Smuzhiyun * @cm_inst should be a macro ending in _INST from the OMAP4 CM instance 119*4882a593Smuzhiyun * definitions (OMAP4 only) 120*4882a593Smuzhiyun * @clkdm_offs should be a macro ending in _CDOFFS from the OMAP4 CM instance 121*4882a593Smuzhiyun * definitions (OMAP4 only) 122*4882a593Smuzhiyun */ 123*4882a593Smuzhiyun struct clockdomain { 124*4882a593Smuzhiyun const char *name; 125*4882a593Smuzhiyun union { 126*4882a593Smuzhiyun const char *name; 127*4882a593Smuzhiyun struct powerdomain *ptr; 128*4882a593Smuzhiyun } pwrdm; 129*4882a593Smuzhiyun const u16 clktrctrl_mask; 130*4882a593Smuzhiyun const u8 flags; 131*4882a593Smuzhiyun u8 _flags; 132*4882a593Smuzhiyun const u8 dep_bit; 133*4882a593Smuzhiyun const u8 prcm_partition; 134*4882a593Smuzhiyun const u16 cm_inst; 135*4882a593Smuzhiyun const u16 clkdm_offs; 136*4882a593Smuzhiyun struct clkdm_dep *wkdep_srcs; 137*4882a593Smuzhiyun struct clkdm_dep *sleepdep_srcs; 138*4882a593Smuzhiyun int usecount; 139*4882a593Smuzhiyun int forcewake_count; 140*4882a593Smuzhiyun struct list_head node; 141*4882a593Smuzhiyun u32 context; 142*4882a593Smuzhiyun }; 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun /** 145*4882a593Smuzhiyun * struct clkdm_ops - Arch specific function implementations 146*4882a593Smuzhiyun * @clkdm_add_wkdep: Add a wakeup dependency between clk domains 147*4882a593Smuzhiyun * @clkdm_del_wkdep: Delete a wakeup dependency between clk domains 148*4882a593Smuzhiyun * @clkdm_read_wkdep: Read wakeup dependency state between clk domains 149*4882a593Smuzhiyun * @clkdm_clear_all_wkdeps: Remove all wakeup dependencies from the clk domain 150*4882a593Smuzhiyun * @clkdm_add_sleepdep: Add a sleep dependency between clk domains 151*4882a593Smuzhiyun * @clkdm_del_sleepdep: Delete a sleep dependency between clk domains 152*4882a593Smuzhiyun * @clkdm_read_sleepdep: Read sleep dependency state between clk domains 153*4882a593Smuzhiyun * @clkdm_clear_all_sleepdeps: Remove all sleep dependencies from the clk domain 154*4882a593Smuzhiyun * @clkdm_sleep: Force a clockdomain to sleep 155*4882a593Smuzhiyun * @clkdm_wakeup: Force a clockdomain to wakeup 156*4882a593Smuzhiyun * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain 157*4882a593Smuzhiyun * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain 158*4882a593Smuzhiyun * @clkdm_clk_enable: Put the clkdm in right state for a clock enable 159*4882a593Smuzhiyun * @clkdm_clk_disable: Put the clkdm in right state for a clock disable 160*4882a593Smuzhiyun * @clkdm_save_context: Save the current clkdm context 161*4882a593Smuzhiyun * @clkdm_restore_context: Restore the clkdm context 162*4882a593Smuzhiyun */ 163*4882a593Smuzhiyun struct clkdm_ops { 164*4882a593Smuzhiyun int (*clkdm_add_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 165*4882a593Smuzhiyun int (*clkdm_del_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 166*4882a593Smuzhiyun int (*clkdm_read_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 167*4882a593Smuzhiyun int (*clkdm_clear_all_wkdeps)(struct clockdomain *clkdm); 168*4882a593Smuzhiyun int (*clkdm_add_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 169*4882a593Smuzhiyun int (*clkdm_del_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 170*4882a593Smuzhiyun int (*clkdm_read_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 171*4882a593Smuzhiyun int (*clkdm_clear_all_sleepdeps)(struct clockdomain *clkdm); 172*4882a593Smuzhiyun int (*clkdm_sleep)(struct clockdomain *clkdm); 173*4882a593Smuzhiyun int (*clkdm_wakeup)(struct clockdomain *clkdm); 174*4882a593Smuzhiyun void (*clkdm_allow_idle)(struct clockdomain *clkdm); 175*4882a593Smuzhiyun void (*clkdm_deny_idle)(struct clockdomain *clkdm); 176*4882a593Smuzhiyun int (*clkdm_clk_enable)(struct clockdomain *clkdm); 177*4882a593Smuzhiyun int (*clkdm_clk_disable)(struct clockdomain *clkdm); 178*4882a593Smuzhiyun int (*clkdm_save_context)(struct clockdomain *clkdm); 179*4882a593Smuzhiyun int (*clkdm_restore_context)(struct clockdomain *clkdm); 180*4882a593Smuzhiyun }; 181*4882a593Smuzhiyun 182*4882a593Smuzhiyun int clkdm_register_platform_funcs(struct clkdm_ops *co); 183*4882a593Smuzhiyun int clkdm_register_autodeps(struct clkdm_autodep *ia); 184*4882a593Smuzhiyun int clkdm_register_clkdms(struct clockdomain **c); 185*4882a593Smuzhiyun int clkdm_complete_init(void); 186*4882a593Smuzhiyun 187*4882a593Smuzhiyun struct clockdomain *clkdm_lookup(const char *name); 188*4882a593Smuzhiyun 189*4882a593Smuzhiyun int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user), 190*4882a593Smuzhiyun void *user); 191*4882a593Smuzhiyun struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm); 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 194*4882a593Smuzhiyun int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 195*4882a593Smuzhiyun int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 196*4882a593Smuzhiyun int clkdm_clear_all_wkdeps(struct clockdomain *clkdm); 197*4882a593Smuzhiyun int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 198*4882a593Smuzhiyun int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 199*4882a593Smuzhiyun int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); 200*4882a593Smuzhiyun int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm); 201*4882a593Smuzhiyun 202*4882a593Smuzhiyun void clkdm_allow_idle_nolock(struct clockdomain *clkdm); 203*4882a593Smuzhiyun void clkdm_allow_idle(struct clockdomain *clkdm); 204*4882a593Smuzhiyun void clkdm_deny_idle_nolock(struct clockdomain *clkdm); 205*4882a593Smuzhiyun void clkdm_deny_idle(struct clockdomain *clkdm); 206*4882a593Smuzhiyun bool clkdm_in_hwsup(struct clockdomain *clkdm); 207*4882a593Smuzhiyun bool clkdm_missing_idle_reporting(struct clockdomain *clkdm); 208*4882a593Smuzhiyun 209*4882a593Smuzhiyun int clkdm_wakeup_nolock(struct clockdomain *clkdm); 210*4882a593Smuzhiyun int clkdm_wakeup(struct clockdomain *clkdm); 211*4882a593Smuzhiyun int clkdm_sleep_nolock(struct clockdomain *clkdm); 212*4882a593Smuzhiyun int clkdm_sleep(struct clockdomain *clkdm); 213*4882a593Smuzhiyun 214*4882a593Smuzhiyun int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); 215*4882a593Smuzhiyun int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); 216*4882a593Smuzhiyun int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh); 217*4882a593Smuzhiyun int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh); 218*4882a593Smuzhiyun 219*4882a593Smuzhiyun void clkdm_save_context(void); 220*4882a593Smuzhiyun void clkdm_restore_context(void); 221*4882a593Smuzhiyun 222*4882a593Smuzhiyun extern void __init omap242x_clockdomains_init(void); 223*4882a593Smuzhiyun extern void __init omap243x_clockdomains_init(void); 224*4882a593Smuzhiyun extern void __init omap3xxx_clockdomains_init(void); 225*4882a593Smuzhiyun extern void __init am33xx_clockdomains_init(void); 226*4882a593Smuzhiyun extern void __init ti814x_clockdomains_init(void); 227*4882a593Smuzhiyun extern void __init ti816x_clockdomains_init(void); 228*4882a593Smuzhiyun extern void __init omap44xx_clockdomains_init(void); 229*4882a593Smuzhiyun extern void __init omap54xx_clockdomains_init(void); 230*4882a593Smuzhiyun extern void __init dra7xx_clockdomains_init(void); 231*4882a593Smuzhiyun void am43xx_clockdomains_init(void); 232*4882a593Smuzhiyun 233*4882a593Smuzhiyun extern void clkdm_add_autodeps(struct clockdomain *clkdm); 234*4882a593Smuzhiyun extern void clkdm_del_autodeps(struct clockdomain *clkdm); 235*4882a593Smuzhiyun 236*4882a593Smuzhiyun extern struct clkdm_ops omap2_clkdm_operations; 237*4882a593Smuzhiyun extern struct clkdm_ops omap3_clkdm_operations; 238*4882a593Smuzhiyun extern struct clkdm_ops omap4_clkdm_operations; 239*4882a593Smuzhiyun extern struct clkdm_ops am33xx_clkdm_operations; 240*4882a593Smuzhiyun extern struct clkdm_ops am43xx_clkdm_operations; 241*4882a593Smuzhiyun 242*4882a593Smuzhiyun extern struct clkdm_dep gfx_24xx_wkdeps[]; 243*4882a593Smuzhiyun extern struct clkdm_dep dsp_24xx_wkdeps[]; 244*4882a593Smuzhiyun extern struct clockdomain wkup_common_clkdm; 245*4882a593Smuzhiyun 246*4882a593Smuzhiyun #endif 247