1*7d116dccSCC Ma /* 2*7d116dccSCC Ma * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3*7d116dccSCC Ma * 4*7d116dccSCC Ma * Redistribution and use in source and binary forms, with or without 5*7d116dccSCC Ma * modification, are permitted provided that the following conditions are met: 6*7d116dccSCC Ma * 7*7d116dccSCC Ma * Redistributions of source code must retain the above copyright notice, this 8*7d116dccSCC Ma * list of conditions and the following disclaimer. 9*7d116dccSCC Ma * 10*7d116dccSCC Ma * Redistributions in binary form must reproduce the above copyright notice, 11*7d116dccSCC Ma * this list of conditions and the following disclaimer in the documentation 12*7d116dccSCC Ma * and/or other materials provided with the distribution. 13*7d116dccSCC Ma * 14*7d116dccSCC Ma * Neither the name of ARM nor the names of its contributors may be used 15*7d116dccSCC Ma * to endorse or promote products derived from this software without specific 16*7d116dccSCC Ma * prior written permission. 17*7d116dccSCC Ma * 18*7d116dccSCC Ma * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19*7d116dccSCC Ma * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*7d116dccSCC Ma * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*7d116dccSCC Ma * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22*7d116dccSCC Ma * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*7d116dccSCC Ma * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*7d116dccSCC Ma * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*7d116dccSCC Ma * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*7d116dccSCC Ma * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*7d116dccSCC Ma * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*7d116dccSCC Ma * POSSIBILITY OF SUCH DAMAGE. 29*7d116dccSCC Ma */ 30*7d116dccSCC Ma #include <bakery_lock.h> 31*7d116dccSCC Ma #include <debug.h> 32*7d116dccSCC Ma #include <mmio.h> 33*7d116dccSCC Ma #include <mt8173_def.h> 34*7d116dccSCC Ma #include <spm.h> 35*7d116dccSCC Ma #include <spm_suspend.h> 36*7d116dccSCC Ma 37*7d116dccSCC Ma /* 38*7d116dccSCC Ma * System Power Manager (SPM) is a hardware module, which controls cpu or 39*7d116dccSCC Ma * system power for different power scenarios using different firmware, i.e., 40*7d116dccSCC Ma * - spm_hotplug.c for cpu power control in cpu hotplug flow. 41*7d116dccSCC Ma * - spm_mcdi.c for cpu power control in cpu idle power saving state. 42*7d116dccSCC Ma * - spm_suspend.c for system power control in system suspend scenario. 43*7d116dccSCC Ma * 44*7d116dccSCC Ma * This file provide utility functions common to hotplug, mcdi(idle), suspend 45*7d116dccSCC Ma * power scenarios. A bakery lock (software lock) is incoporated to protect 46*7d116dccSCC Ma * certain critical sections to avoid kicking different SPM firmware 47*7d116dccSCC Ma * concurrently. 48*7d116dccSCC Ma */ 49*7d116dccSCC Ma 50*7d116dccSCC Ma #define SPM_SYSCLK_SETTLE 128 /* 3.9ms */ 51*7d116dccSCC Ma 52*7d116dccSCC Ma #if DEBUG 53*7d116dccSCC Ma static int spm_dormant_sta = CPU_DORMANT_RESET; 54*7d116dccSCC Ma #endif 55*7d116dccSCC Ma 56*7d116dccSCC Ma static bakery_lock_t spm_lock __attribute__ ((section("tzfw_coherent_mem"))); 57*7d116dccSCC Ma static int spm_hotplug_ready __attribute__ ((section("tzfw_coherent_mem"))); 58*7d116dccSCC Ma static int spm_mcdi_ready __attribute__ ((section("tzfw_coherent_mem"))); 59*7d116dccSCC Ma static int spm_suspend_ready __attribute__ ((section("tzfw_coherent_mem"))); 60*7d116dccSCC Ma 61*7d116dccSCC Ma void spm_lock_init(void) 62*7d116dccSCC Ma { 63*7d116dccSCC Ma bakery_lock_init(&spm_lock); 64*7d116dccSCC Ma } 65*7d116dccSCC Ma 66*7d116dccSCC Ma void spm_lock_get(void) 67*7d116dccSCC Ma { 68*7d116dccSCC Ma bakery_lock_get(&spm_lock); 69*7d116dccSCC Ma } 70*7d116dccSCC Ma 71*7d116dccSCC Ma void spm_lock_release(void) 72*7d116dccSCC Ma { 73*7d116dccSCC Ma bakery_lock_release(&spm_lock); 74*7d116dccSCC Ma } 75*7d116dccSCC Ma 76*7d116dccSCC Ma int is_mcdi_ready(void) 77*7d116dccSCC Ma { 78*7d116dccSCC Ma return spm_mcdi_ready; 79*7d116dccSCC Ma } 80*7d116dccSCC Ma 81*7d116dccSCC Ma int is_hotplug_ready(void) 82*7d116dccSCC Ma { 83*7d116dccSCC Ma return spm_hotplug_ready; 84*7d116dccSCC Ma } 85*7d116dccSCC Ma 86*7d116dccSCC Ma int is_suspend_ready(void) 87*7d116dccSCC Ma { 88*7d116dccSCC Ma return spm_suspend_ready; 89*7d116dccSCC Ma } 90*7d116dccSCC Ma 91*7d116dccSCC Ma void set_mcdi_ready(void) 92*7d116dccSCC Ma { 93*7d116dccSCC Ma spm_mcdi_ready = 1; 94*7d116dccSCC Ma spm_hotplug_ready = 0; 95*7d116dccSCC Ma spm_suspend_ready = 0; 96*7d116dccSCC Ma } 97*7d116dccSCC Ma 98*7d116dccSCC Ma void set_hotplug_ready(void) 99*7d116dccSCC Ma { 100*7d116dccSCC Ma spm_mcdi_ready = 0; 101*7d116dccSCC Ma spm_hotplug_ready = 1; 102*7d116dccSCC Ma spm_suspend_ready = 0; 103*7d116dccSCC Ma } 104*7d116dccSCC Ma 105*7d116dccSCC Ma void set_suspend_ready(void) 106*7d116dccSCC Ma { 107*7d116dccSCC Ma spm_mcdi_ready = 0; 108*7d116dccSCC Ma spm_hotplug_ready = 0; 109*7d116dccSCC Ma spm_suspend_ready = 1; 110*7d116dccSCC Ma } 111*7d116dccSCC Ma 112*7d116dccSCC Ma void clear_all_ready(void) 113*7d116dccSCC Ma { 114*7d116dccSCC Ma spm_mcdi_ready = 0; 115*7d116dccSCC Ma spm_hotplug_ready = 0; 116*7d116dccSCC Ma spm_suspend_ready = 0; 117*7d116dccSCC Ma } 118*7d116dccSCC Ma 119*7d116dccSCC Ma void spm_register_init(void) 120*7d116dccSCC Ma { 121*7d116dccSCC Ma mmio_write_32(SPM_POWERON_CONFIG_SET, SPM_REGWR_CFG_KEY | SPM_REGWR_EN); 122*7d116dccSCC Ma 123*7d116dccSCC Ma mmio_write_32(SPM_POWER_ON_VAL0, 0); 124*7d116dccSCC Ma mmio_write_32(SPM_POWER_ON_VAL1, POWER_ON_VAL1_DEF); 125*7d116dccSCC Ma mmio_write_32(SPM_PCM_PWR_IO_EN, 0); 126*7d116dccSCC Ma 127*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET); 128*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY); 129*7d116dccSCC Ma if (mmio_read_32(SPM_PCM_FSM_STA) != PCM_FSM_STA_DEF) 130*7d116dccSCC Ma WARN("PCM reset failed\n"); 131*7d116dccSCC Ma 132*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_SLEEP_DVS); 133*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON1, CON1_CFG_KEY | CON1_EVENT_LOCK_EN | 134*7d116dccSCC Ma CON1_SPM_SRAM_ISO_B | CON1_SPM_SRAM_SLP_B | CON1_MIF_APBEN); 135*7d116dccSCC Ma mmio_write_32(SPM_PCM_IM_PTR, 0); 136*7d116dccSCC Ma mmio_write_32(SPM_PCM_IM_LEN, 0); 137*7d116dccSCC Ma 138*7d116dccSCC Ma mmio_write_32(SPM_CLK_CON, CC_SYSCLK0_EN_1 | CC_SYSCLK0_EN_0 | 139*7d116dccSCC Ma CC_SYSCLK1_EN_0 | CC_SRCLKENA_MASK_0 | CC_CLKSQ1_SEL | 140*7d116dccSCC Ma CC_CXO32K_RM_EN_MD2 | CC_CXO32K_RM_EN_MD1 | CC_MD32_DCM_EN); 141*7d116dccSCC Ma 142*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_ISR_MASK, 0xff0c); 143*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_ISR_STATUS, 0xc); 144*7d116dccSCC Ma mmio_write_32(SPM_PCM_SW_INT_CLEAR, 0xff); 145*7d116dccSCC Ma mmio_write_32(SPM_MD32_SRAM_CON, 0xff0); 146*7d116dccSCC Ma } 147*7d116dccSCC Ma 148*7d116dccSCC Ma void spm_reset_and_init_pcm(void) 149*7d116dccSCC Ma { 150*7d116dccSCC Ma unsigned int con1; 151*7d116dccSCC Ma int i = 0; 152*7d116dccSCC Ma 153*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET); 154*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY); 155*7d116dccSCC Ma while (mmio_read_32(SPM_PCM_FSM_STA) != PCM_FSM_STA_DEF) { 156*7d116dccSCC Ma i++; 157*7d116dccSCC Ma if (i > 1000) { 158*7d116dccSCC Ma i = 0; 159*7d116dccSCC Ma WARN("PCM reset failed\n"); 160*7d116dccSCC Ma break; 161*7d116dccSCC Ma } 162*7d116dccSCC Ma } 163*7d116dccSCC Ma 164*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_SLEEP_DVS); 165*7d116dccSCC Ma 166*7d116dccSCC Ma con1 = mmio_read_32(SPM_PCM_CON1) & 167*7d116dccSCC Ma (CON1_PCM_WDT_WAKE_MODE | CON1_PCM_WDT_EN); 168*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON1, con1 | CON1_CFG_KEY | CON1_EVENT_LOCK_EN | 169*7d116dccSCC Ma CON1_SPM_SRAM_ISO_B | CON1_SPM_SRAM_SLP_B | 170*7d116dccSCC Ma CON1_IM_NONRP_EN | CON1_MIF_APBEN); 171*7d116dccSCC Ma } 172*7d116dccSCC Ma 173*7d116dccSCC Ma void spm_init_pcm_register(void) 174*7d116dccSCC Ma { 175*7d116dccSCC Ma mmio_write_32(SPM_PCM_REG_DATA_INI, mmio_read_32(SPM_POWER_ON_VAL0)); 176*7d116dccSCC Ma mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R0); 177*7d116dccSCC Ma mmio_write_32(SPM_PCM_PWR_IO_EN, 0); 178*7d116dccSCC Ma 179*7d116dccSCC Ma mmio_write_32(SPM_PCM_REG_DATA_INI, mmio_read_32(SPM_POWER_ON_VAL1)); 180*7d116dccSCC Ma mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R7); 181*7d116dccSCC Ma mmio_write_32(SPM_PCM_PWR_IO_EN, 0); 182*7d116dccSCC Ma } 183*7d116dccSCC Ma 184*7d116dccSCC Ma void spm_set_power_control(const struct pwr_ctrl *pwrctrl) 185*7d116dccSCC Ma { 186*7d116dccSCC Ma mmio_write_32(SPM_AP_STANBY_CON, (!pwrctrl->md32_req_mask << 21) | 187*7d116dccSCC Ma (!pwrctrl->mfg_req_mask << 17) | 188*7d116dccSCC Ma (!pwrctrl->disp_req_mask << 16) | 189*7d116dccSCC Ma (!!pwrctrl->mcusys_idle_mask << 7) | 190*7d116dccSCC Ma (!!pwrctrl->ca15top_idle_mask << 6) | 191*7d116dccSCC Ma (!!pwrctrl->ca7top_idle_mask << 5) | 192*7d116dccSCC Ma (!!pwrctrl->wfi_op << 4)); 193*7d116dccSCC Ma mmio_write_32(SPM_PCM_SRC_REQ, (!!pwrctrl->pcm_apsrc_req << 0)); 194*7d116dccSCC Ma mmio_write_32(SPM_PCM_PASR_DPD_2, 0); 195*7d116dccSCC Ma 196*7d116dccSCC Ma mmio_clrsetbits_32(SPM_CLK_CON, CC_SRCLKENA_MASK_0, 197*7d116dccSCC Ma (pwrctrl->srclkenai_mask ? CC_SRCLKENA_MASK_0 : 0)); 198*7d116dccSCC Ma 199*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_CA15_WFI0_EN, !!pwrctrl->ca15_wfi0_en); 200*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_CA15_WFI1_EN, !!pwrctrl->ca15_wfi1_en); 201*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_CA15_WFI2_EN, !!pwrctrl->ca15_wfi2_en); 202*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_CA15_WFI3_EN, !!pwrctrl->ca15_wfi3_en); 203*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_CA7_WFI0_EN, !!pwrctrl->ca7_wfi0_en); 204*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_CA7_WFI1_EN, !!pwrctrl->ca7_wfi1_en); 205*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_CA7_WFI2_EN, !!pwrctrl->ca7_wfi2_en); 206*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_CA7_WFI3_EN, !!pwrctrl->ca7_wfi3_en); 207*7d116dccSCC Ma } 208*7d116dccSCC Ma 209*7d116dccSCC Ma void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl) 210*7d116dccSCC Ma { 211*7d116dccSCC Ma unsigned int val, mask; 212*7d116dccSCC Ma 213*7d116dccSCC Ma if (pwrctrl->timer_val_cust == 0) 214*7d116dccSCC Ma val = pwrctrl->timer_val ? pwrctrl->timer_val : PCM_TIMER_MAX; 215*7d116dccSCC Ma else 216*7d116dccSCC Ma val = pwrctrl->timer_val_cust; 217*7d116dccSCC Ma 218*7d116dccSCC Ma mmio_write_32(SPM_PCM_TIMER_VAL, val); 219*7d116dccSCC Ma mmio_setbits_32(SPM_PCM_CON1, CON1_CFG_KEY); 220*7d116dccSCC Ma 221*7d116dccSCC Ma if (pwrctrl->wake_src_cust == 0) 222*7d116dccSCC Ma mask = pwrctrl->wake_src; 223*7d116dccSCC Ma else 224*7d116dccSCC Ma mask = pwrctrl->wake_src_cust; 225*7d116dccSCC Ma 226*7d116dccSCC Ma if (pwrctrl->syspwreq_mask) 227*7d116dccSCC Ma mask &= ~WAKE_SRC_SYSPWREQ; 228*7d116dccSCC Ma 229*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_WAKEUP_EVENT_MASK, ~mask); 230*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_ISR_MASK, 0xfe04); 231*7d116dccSCC Ma } 232*7d116dccSCC Ma 233*7d116dccSCC Ma void spm_get_wakeup_status(struct wake_status *wakesta) 234*7d116dccSCC Ma { 235*7d116dccSCC Ma wakesta->assert_pc = mmio_read_32(SPM_PCM_REG_DATA_INI); 236*7d116dccSCC Ma wakesta->r12 = mmio_read_32(SPM_PCM_REG12_DATA); 237*7d116dccSCC Ma wakesta->raw_sta = mmio_read_32(SPM_SLEEP_ISR_RAW_STA); 238*7d116dccSCC Ma wakesta->wake_misc = mmio_read_32(SPM_SLEEP_WAKEUP_MISC); 239*7d116dccSCC Ma wakesta->timer_out = mmio_read_32(SPM_PCM_TIMER_OUT); 240*7d116dccSCC Ma wakesta->r13 = mmio_read_32(SPM_PCM_REG13_DATA); 241*7d116dccSCC Ma wakesta->idle_sta = mmio_read_32(SPM_SLEEP_SUBSYS_IDLE_STA); 242*7d116dccSCC Ma wakesta->debug_flag = mmio_read_32(SPM_PCM_PASR_DPD_3); 243*7d116dccSCC Ma wakesta->event_reg = mmio_read_32(SPM_PCM_EVENT_REG_STA); 244*7d116dccSCC Ma wakesta->isr = mmio_read_32(SPM_SLEEP_ISR_STATUS); 245*7d116dccSCC Ma } 246*7d116dccSCC Ma 247*7d116dccSCC Ma void spm_init_event_vector(const struct pcm_desc *pcmdesc) 248*7d116dccSCC Ma { 249*7d116dccSCC Ma /* init event vector register */ 250*7d116dccSCC Ma mmio_write_32(SPM_PCM_EVENT_VECTOR0, pcmdesc->vec0); 251*7d116dccSCC Ma mmio_write_32(SPM_PCM_EVENT_VECTOR1, pcmdesc->vec1); 252*7d116dccSCC Ma mmio_write_32(SPM_PCM_EVENT_VECTOR2, pcmdesc->vec2); 253*7d116dccSCC Ma mmio_write_32(SPM_PCM_EVENT_VECTOR3, pcmdesc->vec3); 254*7d116dccSCC Ma mmio_write_32(SPM_PCM_EVENT_VECTOR4, pcmdesc->vec4); 255*7d116dccSCC Ma mmio_write_32(SPM_PCM_EVENT_VECTOR5, pcmdesc->vec5); 256*7d116dccSCC Ma mmio_write_32(SPM_PCM_EVENT_VECTOR6, pcmdesc->vec6); 257*7d116dccSCC Ma mmio_write_32(SPM_PCM_EVENT_VECTOR7, pcmdesc->vec7); 258*7d116dccSCC Ma 259*7d116dccSCC Ma /* event vector will be enabled by PCM itself */ 260*7d116dccSCC Ma } 261*7d116dccSCC Ma 262*7d116dccSCC Ma void spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc) 263*7d116dccSCC Ma { 264*7d116dccSCC Ma unsigned int ptr = 0, len, con0; 265*7d116dccSCC Ma 266*7d116dccSCC Ma ptr = (unsigned int)(unsigned long)(pcmdesc->base); 267*7d116dccSCC Ma len = pcmdesc->size - 1; 268*7d116dccSCC Ma if (mmio_read_32(SPM_PCM_IM_PTR) != ptr || 269*7d116dccSCC Ma mmio_read_32(SPM_PCM_IM_LEN) != len || 270*7d116dccSCC Ma pcmdesc->sess > 2) { 271*7d116dccSCC Ma mmio_write_32(SPM_PCM_IM_PTR, ptr); 272*7d116dccSCC Ma mmio_write_32(SPM_PCM_IM_LEN, len); 273*7d116dccSCC Ma } else { 274*7d116dccSCC Ma mmio_setbits_32(SPM_PCM_CON1, CON1_CFG_KEY | CON1_IM_SLAVE); 275*7d116dccSCC Ma } 276*7d116dccSCC Ma 277*7d116dccSCC Ma /* kick IM to fetch (only toggle IM_KICK) */ 278*7d116dccSCC Ma con0 = mmio_read_32(SPM_PCM_CON0) & ~(CON0_IM_KICK | CON0_PCM_KICK); 279*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_IM_KICK); 280*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY); 281*7d116dccSCC Ma 282*7d116dccSCC Ma /* kick IM to fetch (only toggle PCM_KICK) */ 283*7d116dccSCC Ma con0 = mmio_read_32(SPM_PCM_CON0) & ~(CON0_IM_KICK | CON0_PCM_KICK); 284*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_PCM_KICK); 285*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY); 286*7d116dccSCC Ma } 287*7d116dccSCC Ma 288*7d116dccSCC Ma void spm_set_sysclk_settle(void) 289*7d116dccSCC Ma { 290*7d116dccSCC Ma mmio_write_32(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE); 291*7d116dccSCC Ma 292*7d116dccSCC Ma INFO("settle = %u\n", mmio_read_32(SPM_CLK_SETTLE)); 293*7d116dccSCC Ma } 294*7d116dccSCC Ma 295*7d116dccSCC Ma void spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl) 296*7d116dccSCC Ma { 297*7d116dccSCC Ma unsigned int con1; 298*7d116dccSCC Ma 299*7d116dccSCC Ma con1 = mmio_read_32(SPM_PCM_CON1) & 300*7d116dccSCC Ma ~(CON1_PCM_WDT_WAKE_MODE | CON1_PCM_WDT_EN); 301*7d116dccSCC Ma 302*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON1, CON1_CFG_KEY | con1); 303*7d116dccSCC Ma 304*7d116dccSCC Ma if (mmio_read_32(SPM_PCM_TIMER_VAL) > PCM_TIMER_MAX) 305*7d116dccSCC Ma mmio_write_32(SPM_PCM_TIMER_VAL, PCM_TIMER_MAX); 306*7d116dccSCC Ma 307*7d116dccSCC Ma mmio_write_32(SPM_PCM_WDT_TIMER_VAL, 308*7d116dccSCC Ma mmio_read_32(SPM_PCM_TIMER_VAL) + PCM_WDT_TIMEOUT); 309*7d116dccSCC Ma 310*7d116dccSCC Ma mmio_write_32(SPM_PCM_CON1, con1 | CON1_CFG_KEY | CON1_PCM_WDT_EN); 311*7d116dccSCC Ma mmio_write_32(SPM_PCM_PASR_DPD_0, 0); 312*7d116dccSCC Ma 313*7d116dccSCC Ma mmio_write_32(SPM_PCM_MAS_PAUSE_MASK, 0xffffffff); 314*7d116dccSCC Ma mmio_write_32(SPM_PCM_REG_DATA_INI, 0); 315*7d116dccSCC Ma mmio_clrbits_32(SPM_CLK_CON, CC_DISABLE_DORM_PWR); 316*7d116dccSCC Ma 317*7d116dccSCC Ma mmio_write_32(SPM_PCM_FLAGS, pwrctrl->pcm_flags); 318*7d116dccSCC Ma 319*7d116dccSCC Ma mmio_clrsetbits_32(SPM_CLK_CON, CC_LOCK_INFRA_DCM, 320*7d116dccSCC Ma (pwrctrl->infra_dcm_lock ? CC_LOCK_INFRA_DCM : 0)); 321*7d116dccSCC Ma 322*7d116dccSCC Ma mmio_write_32(SPM_PCM_PWR_IO_EN, 323*7d116dccSCC Ma (pwrctrl->r0_ctrl_en ? PCM_PWRIO_EN_R0 : 0) | 324*7d116dccSCC Ma (pwrctrl->r7_ctrl_en ? PCM_PWRIO_EN_R7 : 0)); 325*7d116dccSCC Ma } 326*7d116dccSCC Ma 327*7d116dccSCC Ma void spm_clean_after_wakeup(void) 328*7d116dccSCC Ma { 329*7d116dccSCC Ma mmio_clrsetbits_32(SPM_PCM_CON1, CON1_PCM_WDT_EN, CON1_CFG_KEY); 330*7d116dccSCC Ma 331*7d116dccSCC Ma mmio_write_32(SPM_PCM_PWR_IO_EN, 0); 332*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_CPU_WAKEUP_EVENT, 0); 333*7d116dccSCC Ma mmio_clrsetbits_32(SPM_PCM_CON1, CON1_PCM_TIMER_EN, CON1_CFG_KEY); 334*7d116dccSCC Ma 335*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_WAKEUP_EVENT_MASK, ~0); 336*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_ISR_MASK, 0xFF0C); 337*7d116dccSCC Ma mmio_write_32(SPM_SLEEP_ISR_STATUS, 0xC); 338*7d116dccSCC Ma mmio_write_32(SPM_PCM_SW_INT_CLEAR, 0xFF); 339*7d116dccSCC Ma } 340*7d116dccSCC Ma 341*7d116dccSCC Ma enum wake_reason_t spm_output_wake_reason(struct wake_status *wakesta) 342*7d116dccSCC Ma { 343*7d116dccSCC Ma enum wake_reason_t wr; 344*7d116dccSCC Ma int i; 345*7d116dccSCC Ma 346*7d116dccSCC Ma wr = WR_UNKNOWN; 347*7d116dccSCC Ma 348*7d116dccSCC Ma if (wakesta->assert_pc != 0) { 349*7d116dccSCC Ma ERROR("PCM ASSERT AT %u, r12=0x%x, r13=0x%x, debug_flag=0x%x\n", 350*7d116dccSCC Ma wakesta->assert_pc, wakesta->r12, wakesta->r13, 351*7d116dccSCC Ma wakesta->debug_flag); 352*7d116dccSCC Ma return WR_PCM_ASSERT; 353*7d116dccSCC Ma } 354*7d116dccSCC Ma 355*7d116dccSCC Ma if (wakesta->r12 & WAKE_SRC_SPM_MERGE) { 356*7d116dccSCC Ma if (wakesta->wake_misc & WAKE_MISC_PCM_TIMER) 357*7d116dccSCC Ma wr = WR_PCM_TIMER; 358*7d116dccSCC Ma if (wakesta->wake_misc & WAKE_MISC_CPU_WAKE) 359*7d116dccSCC Ma wr = WR_WAKE_SRC; 360*7d116dccSCC Ma } 361*7d116dccSCC Ma 362*7d116dccSCC Ma for (i = 1; i < 32; i++) { 363*7d116dccSCC Ma if (wakesta->r12 & (1U << i)) 364*7d116dccSCC Ma wr = WR_WAKE_SRC; 365*7d116dccSCC Ma } 366*7d116dccSCC Ma 367*7d116dccSCC Ma if ((wakesta->event_reg & 0x100000) == 0) { 368*7d116dccSCC Ma INFO("pcm sleep abort!\n"); 369*7d116dccSCC Ma wr = WR_PCM_ABORT; 370*7d116dccSCC Ma } 371*7d116dccSCC Ma 372*7d116dccSCC Ma INFO("timer_out = %u, r12 = 0x%x, r13 = 0x%x, debug_flag = 0x%x\n", 373*7d116dccSCC Ma wakesta->timer_out, wakesta->r12, wakesta->r13, 374*7d116dccSCC Ma wakesta->debug_flag); 375*7d116dccSCC Ma 376*7d116dccSCC Ma INFO("raw_sta = 0x%x, idle_sta = 0x%x, event_reg = 0x%x, isr = 0x%x\n", 377*7d116dccSCC Ma wakesta->raw_sta, wakesta->idle_sta, wakesta->event_reg, 378*7d116dccSCC Ma wakesta->isr); 379*7d116dccSCC Ma 380*7d116dccSCC Ma INFO("dormant state = %d\n", spm_dormant_sta); 381*7d116dccSCC Ma return wr; 382*7d116dccSCC Ma } 383*7d116dccSCC Ma 384*7d116dccSCC Ma void spm_boot_init(void) 385*7d116dccSCC Ma { 386*7d116dccSCC Ma /* Only CPU0 is online during boot, initialize cpu online reserve bit */ 387*7d116dccSCC Ma mmio_write_32(SPM_PCM_RESERVE, 0xFE); 388*7d116dccSCC Ma spm_lock_init(); 389*7d116dccSCC Ma spm_register_init(); 390*7d116dccSCC Ma } 391