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