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 <drivers/delay_timer.h> 9*91f16700Schasinglulu #include <lib/mmio.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <mt8173_def.h> 12*91f16700Schasinglulu #include <mtcmos.h> 13*91f16700Schasinglulu #include <spm.h> 14*91f16700Schasinglulu #include <spm_mcdi.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu enum { 17*91f16700Schasinglulu SRAM_ISOINT_B = 1U << 6, 18*91f16700Schasinglulu SRAM_CKISO = 1U << 5, 19*91f16700Schasinglulu PWR_CLK_DIS = 1U << 4, 20*91f16700Schasinglulu PWR_ON_2ND = 1U << 3, 21*91f16700Schasinglulu PWR_ON = 1U << 2, 22*91f16700Schasinglulu PWR_ISO = 1U << 1, 23*91f16700Schasinglulu PWR_RST_B = 1U << 0 24*91f16700Schasinglulu }; 25*91f16700Schasinglulu 26*91f16700Schasinglulu enum { 27*91f16700Schasinglulu L1_PDN_ACK = 1U << 8, 28*91f16700Schasinglulu L1_PDN = 1U << 0 29*91f16700Schasinglulu }; 30*91f16700Schasinglulu 31*91f16700Schasinglulu enum { 32*91f16700Schasinglulu LITTLE_CPU3 = 1U << 12, 33*91f16700Schasinglulu LITTLE_CPU2 = 1U << 11, 34*91f16700Schasinglulu LITTLE_CPU1 = 1U << 10, 35*91f16700Schasinglulu }; 36*91f16700Schasinglulu 37*91f16700Schasinglulu enum { 38*91f16700Schasinglulu SRAM_PDN = 0xf << 8, 39*91f16700Schasinglulu DIS_SRAM_ACK = 0x1 << 12, 40*91f16700Schasinglulu AUD_SRAM_ACK = 0xf << 12, 41*91f16700Schasinglulu }; 42*91f16700Schasinglulu 43*91f16700Schasinglulu enum { 44*91f16700Schasinglulu DIS_PWR_STA_MASK = 0x1 << 3, 45*91f16700Schasinglulu AUD_PWR_STA_MASK = 0x1 << 24, 46*91f16700Schasinglulu }; 47*91f16700Schasinglulu 48*91f16700Schasinglulu #define SPM_VDE_PWR_CON 0x0210 49*91f16700Schasinglulu #define SPM_MFG_PWR_CON 0x0214 50*91f16700Schasinglulu #define SPM_VEN_PWR_CON 0x0230 51*91f16700Schasinglulu #define SPM_ISP_PWR_CON 0x0238 52*91f16700Schasinglulu #define SPM_DIS_PWR_CON 0x023c 53*91f16700Schasinglulu #define SPM_VEN2_PWR_CON 0x0298 54*91f16700Schasinglulu #define SPM_AUDIO_PWR_CON 0x029c 55*91f16700Schasinglulu #define SPM_MFG_2D_PWR_CON 0x02c0 56*91f16700Schasinglulu #define SPM_MFG_ASYNC_PWR_CON 0x02c4 57*91f16700Schasinglulu #define SPM_USB_PWR_CON 0x02cc 58*91f16700Schasinglulu 59*91f16700Schasinglulu #define MTCMOS_CTRL_SUCCESS 0 60*91f16700Schasinglulu #define MTCMOS_CTRL_ERROR -1 61*91f16700Schasinglulu 62*91f16700Schasinglulu #define MTCMOS_CTRL_EN (0x1 << 18) 63*91f16700Schasinglulu 64*91f16700Schasinglulu #define VDE_PWR_ON 0 65*91f16700Schasinglulu #define VEN_PWR_ON 1 66*91f16700Schasinglulu #define ISP_PWR_ON 2 67*91f16700Schasinglulu #define DIS_PWR_ON 3 68*91f16700Schasinglulu #define VEN2_PWR_ON 4 69*91f16700Schasinglulu #define AUDIO_PWR_ON 5 70*91f16700Schasinglulu #define MFG_ASYNC_PWR_ON 6 71*91f16700Schasinglulu #define MFG_2D_PWR_ON 7 72*91f16700Schasinglulu #define MFG_PWR_ON 8 73*91f16700Schasinglulu #define USB_PWR_ON 9 74*91f16700Schasinglulu 75*91f16700Schasinglulu #define VDE_PWR_OFF 10 76*91f16700Schasinglulu #define VEN_PWR_OFF 11 77*91f16700Schasinglulu #define ISP_PWR_OFF 12 78*91f16700Schasinglulu #define DIS_PWR_OFF 13 79*91f16700Schasinglulu #define VEN2_PWR_OFF 14 80*91f16700Schasinglulu #define AUDIO_PWR_OFF 15 81*91f16700Schasinglulu #define MFG_ASYNC_PWR_OFF 16 82*91f16700Schasinglulu #define MFG_2D_PWR_OFF 17 83*91f16700Schasinglulu #define MFG_PWR_OFF 18 84*91f16700Schasinglulu #define USB_PWR_OFF 19 85*91f16700Schasinglulu 86*91f16700Schasinglulu #define VDE_PWR_CON_PWR_STA 7 87*91f16700Schasinglulu #define VEN_PWR_CON_PWR_STA 21 88*91f16700Schasinglulu #define ISP_PWR_CON_PWR_STA 5 89*91f16700Schasinglulu #define DIS_PWR_CON_PWR_STA 3 90*91f16700Schasinglulu #define VEN2_PWR_CON_PWR_STA 20 91*91f16700Schasinglulu #define AUDIO_PWR_CON_PWR_STA 24 92*91f16700Schasinglulu #define MFG_ASYNC_PWR_CON_PWR_STA 23 93*91f16700Schasinglulu #define MFG_2D_PWR_CON_PWR_STA 22 94*91f16700Schasinglulu #define MFG_PWR_CON_PWR_STA 4 95*91f16700Schasinglulu #define USB_PWR_CON_PWR_STA 25 96*91f16700Schasinglulu 97*91f16700Schasinglulu /* 98*91f16700Schasinglulu * Timeout if the ack is not signled after 1 second. 99*91f16700Schasinglulu * According to designer, one mtcmos operation should be done 100*91f16700Schasinglulu * around 10us. 101*91f16700Schasinglulu */ 102*91f16700Schasinglulu #define MTCMOS_ACK_POLLING_MAX_COUNT 10000 103*91f16700Schasinglulu #define MTCMOS_ACK_POLLING_INTERVAL 10 104*91f16700Schasinglulu 105*91f16700Schasinglulu static void mtcmos_ctrl_little_off(unsigned int linear_id) 106*91f16700Schasinglulu { 107*91f16700Schasinglulu uint32_t reg_pwr_con; 108*91f16700Schasinglulu uint32_t reg_l1_pdn; 109*91f16700Schasinglulu uint32_t bit_cpu; 110*91f16700Schasinglulu 111*91f16700Schasinglulu switch (linear_id) { 112*91f16700Schasinglulu case 1: 113*91f16700Schasinglulu reg_pwr_con = SPM_CA7_CPU1_PWR_CON; 114*91f16700Schasinglulu reg_l1_pdn = SPM_CA7_CPU1_L1_PDN; 115*91f16700Schasinglulu bit_cpu = LITTLE_CPU1; 116*91f16700Schasinglulu break; 117*91f16700Schasinglulu case 2: 118*91f16700Schasinglulu reg_pwr_con = SPM_CA7_CPU2_PWR_CON; 119*91f16700Schasinglulu reg_l1_pdn = SPM_CA7_CPU2_L1_PDN; 120*91f16700Schasinglulu bit_cpu = LITTLE_CPU2; 121*91f16700Schasinglulu break; 122*91f16700Schasinglulu case 3: 123*91f16700Schasinglulu reg_pwr_con = SPM_CA7_CPU3_PWR_CON; 124*91f16700Schasinglulu reg_l1_pdn = SPM_CA7_CPU3_L1_PDN; 125*91f16700Schasinglulu bit_cpu = LITTLE_CPU3; 126*91f16700Schasinglulu break; 127*91f16700Schasinglulu default: 128*91f16700Schasinglulu /* should never come to here */ 129*91f16700Schasinglulu return; 130*91f16700Schasinglulu } 131*91f16700Schasinglulu 132*91f16700Schasinglulu /* enable register control */ 133*91f16700Schasinglulu mmio_write_32(SPM_POWERON_CONFIG_SET, 134*91f16700Schasinglulu (SPM_PROJECT_CODE << 16) | (1U << 0)); 135*91f16700Schasinglulu 136*91f16700Schasinglulu mmio_setbits_32(reg_pwr_con, PWR_ISO); 137*91f16700Schasinglulu mmio_setbits_32(reg_pwr_con, SRAM_CKISO); 138*91f16700Schasinglulu mmio_clrbits_32(reg_pwr_con, SRAM_ISOINT_B); 139*91f16700Schasinglulu mmio_setbits_32(reg_l1_pdn, L1_PDN); 140*91f16700Schasinglulu 141*91f16700Schasinglulu while (!(mmio_read_32(reg_l1_pdn) & L1_PDN_ACK)) 142*91f16700Schasinglulu continue; 143*91f16700Schasinglulu 144*91f16700Schasinglulu mmio_clrbits_32(reg_pwr_con, PWR_RST_B); 145*91f16700Schasinglulu mmio_setbits_32(reg_pwr_con, PWR_CLK_DIS); 146*91f16700Schasinglulu mmio_clrbits_32(reg_pwr_con, PWR_ON); 147*91f16700Schasinglulu mmio_clrbits_32(reg_pwr_con, PWR_ON_2ND); 148*91f16700Schasinglulu 149*91f16700Schasinglulu while ((mmio_read_32(SPM_PWR_STATUS) & bit_cpu) || 150*91f16700Schasinglulu (mmio_read_32(SPM_PWR_STATUS_2ND) & bit_cpu)) 151*91f16700Schasinglulu continue; 152*91f16700Schasinglulu } 153*91f16700Schasinglulu 154*91f16700Schasinglulu void mtcmos_little_cpu_off(void) 155*91f16700Schasinglulu { 156*91f16700Schasinglulu /* turn off little cpu 1 - 3 */ 157*91f16700Schasinglulu mtcmos_ctrl_little_off(1); 158*91f16700Schasinglulu mtcmos_ctrl_little_off(2); 159*91f16700Schasinglulu mtcmos_ctrl_little_off(3); 160*91f16700Schasinglulu } 161*91f16700Schasinglulu 162*91f16700Schasinglulu uint32_t wait_mtcmos_ack(uint32_t on, uint32_t pwr_ctrl, uint32_t spm_pwr_sta) 163*91f16700Schasinglulu { 164*91f16700Schasinglulu int i = 0; 165*91f16700Schasinglulu uint32_t cmp, pwr_sta, pwr_sta_2nd; 166*91f16700Schasinglulu 167*91f16700Schasinglulu while (1) { 168*91f16700Schasinglulu cmp = mmio_read_32(SPM_PCM_PASR_DPD_3) & pwr_ctrl; 169*91f16700Schasinglulu pwr_sta = (mmio_read_32(SPM_PWR_STATUS) >> spm_pwr_sta) & 1; 170*91f16700Schasinglulu pwr_sta_2nd = 171*91f16700Schasinglulu (mmio_read_32(SPM_PWR_STATUS_2ND) >> spm_pwr_sta) & 1; 172*91f16700Schasinglulu if (cmp && (pwr_sta == on) && (pwr_sta_2nd == on)) { 173*91f16700Schasinglulu mmio_write_32(SPM_PCM_RESERVE2, 0); 174*91f16700Schasinglulu return MTCMOS_CTRL_SUCCESS; 175*91f16700Schasinglulu } 176*91f16700Schasinglulu udelay(MTCMOS_ACK_POLLING_INTERVAL); 177*91f16700Schasinglulu i++; 178*91f16700Schasinglulu if (i > MTCMOS_ACK_POLLING_MAX_COUNT) { 179*91f16700Schasinglulu INFO("MTCMOS control failed(%d), SPM_PWR_STA(%d),\n" 180*91f16700Schasinglulu "SPM_PCM_RESERVE=0x%x,SPM_PCM_RESERVE2=0x%x,\n" 181*91f16700Schasinglulu "SPM_PWR_STATUS=0x%x,SPM_PWR_STATUS_2ND=0x%x\n" 182*91f16700Schasinglulu "SPM_PCM_PASR_DPD_3 = 0x%x\n", 183*91f16700Schasinglulu on, spm_pwr_sta, mmio_read_32(SPM_PCM_RESERVE), 184*91f16700Schasinglulu mmio_read_32(SPM_PCM_RESERVE2), 185*91f16700Schasinglulu mmio_read_32(SPM_PWR_STATUS), 186*91f16700Schasinglulu mmio_read_32(SPM_PWR_STATUS_2ND), 187*91f16700Schasinglulu mmio_read_32(SPM_PCM_PASR_DPD_3)); 188*91f16700Schasinglulu mmio_write_32(SPM_PCM_RESERVE2, 0); 189*91f16700Schasinglulu return MTCMOS_CTRL_ERROR; 190*91f16700Schasinglulu } 191*91f16700Schasinglulu } 192*91f16700Schasinglulu } 193*91f16700Schasinglulu 194*91f16700Schasinglulu uint32_t mtcmos_non_cpu_ctrl(uint32_t on, uint32_t mtcmos_num) 195*91f16700Schasinglulu { 196*91f16700Schasinglulu uint32_t ret = MTCMOS_CTRL_SUCCESS; 197*91f16700Schasinglulu uint32_t power_on; 198*91f16700Schasinglulu uint32_t power_off; 199*91f16700Schasinglulu uint32_t power_ctrl; 200*91f16700Schasinglulu uint32_t power_status; 201*91f16700Schasinglulu 202*91f16700Schasinglulu spm_lock_get(); 203*91f16700Schasinglulu spm_mcdi_prepare_for_mtcmos(); 204*91f16700Schasinglulu mmio_setbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN); 205*91f16700Schasinglulu 206*91f16700Schasinglulu switch (mtcmos_num) { 207*91f16700Schasinglulu case SPM_VDE_PWR_CON: 208*91f16700Schasinglulu power_on = VDE_PWR_ON; 209*91f16700Schasinglulu power_off = VDE_PWR_OFF; 210*91f16700Schasinglulu power_status = VDE_PWR_CON_PWR_STA; 211*91f16700Schasinglulu break; 212*91f16700Schasinglulu case SPM_MFG_PWR_CON: 213*91f16700Schasinglulu power_on = MFG_PWR_ON; 214*91f16700Schasinglulu power_off = MFG_PWR_OFF; 215*91f16700Schasinglulu power_status = MFG_PWR_CON_PWR_STA; 216*91f16700Schasinglulu break; 217*91f16700Schasinglulu case SPM_VEN_PWR_CON: 218*91f16700Schasinglulu power_on = VEN_PWR_ON; 219*91f16700Schasinglulu power_off = VEN_PWR_OFF; 220*91f16700Schasinglulu power_status = VEN_PWR_CON_PWR_STA; 221*91f16700Schasinglulu break; 222*91f16700Schasinglulu case SPM_ISP_PWR_CON: 223*91f16700Schasinglulu power_on = ISP_PWR_ON; 224*91f16700Schasinglulu power_off = ISP_PWR_OFF; 225*91f16700Schasinglulu power_status = ISP_PWR_CON_PWR_STA; 226*91f16700Schasinglulu break; 227*91f16700Schasinglulu case SPM_DIS_PWR_CON: 228*91f16700Schasinglulu power_on = DIS_PWR_ON; 229*91f16700Schasinglulu power_off = DIS_PWR_OFF; 230*91f16700Schasinglulu power_status = DIS_PWR_CON_PWR_STA; 231*91f16700Schasinglulu break; 232*91f16700Schasinglulu case SPM_VEN2_PWR_CON: 233*91f16700Schasinglulu power_on = VEN2_PWR_ON; 234*91f16700Schasinglulu power_off = VEN2_PWR_OFF; 235*91f16700Schasinglulu power_status = VEN2_PWR_CON_PWR_STA; 236*91f16700Schasinglulu break; 237*91f16700Schasinglulu case SPM_AUDIO_PWR_CON: 238*91f16700Schasinglulu power_on = AUDIO_PWR_ON; 239*91f16700Schasinglulu power_off = AUDIO_PWR_OFF; 240*91f16700Schasinglulu power_status = AUDIO_PWR_CON_PWR_STA; 241*91f16700Schasinglulu break; 242*91f16700Schasinglulu case SPM_MFG_2D_PWR_CON: 243*91f16700Schasinglulu power_on = MFG_2D_PWR_ON; 244*91f16700Schasinglulu power_off = MFG_2D_PWR_OFF; 245*91f16700Schasinglulu power_status = MFG_2D_PWR_CON_PWR_STA; 246*91f16700Schasinglulu break; 247*91f16700Schasinglulu case SPM_MFG_ASYNC_PWR_CON: 248*91f16700Schasinglulu power_on = MFG_ASYNC_PWR_ON; 249*91f16700Schasinglulu power_off = MFG_ASYNC_PWR_OFF; 250*91f16700Schasinglulu power_status = MFG_ASYNC_PWR_CON_PWR_STA; 251*91f16700Schasinglulu break; 252*91f16700Schasinglulu case SPM_USB_PWR_CON: 253*91f16700Schasinglulu power_on = USB_PWR_ON; 254*91f16700Schasinglulu power_off = USB_PWR_OFF; 255*91f16700Schasinglulu power_status = USB_PWR_CON_PWR_STA; 256*91f16700Schasinglulu break; 257*91f16700Schasinglulu default: 258*91f16700Schasinglulu ret = MTCMOS_CTRL_ERROR; 259*91f16700Schasinglulu INFO("No mapping MTCMOS(%d), ret = %d\n", mtcmos_num, ret); 260*91f16700Schasinglulu break; 261*91f16700Schasinglulu } 262*91f16700Schasinglulu if (ret == MTCMOS_CTRL_SUCCESS) { 263*91f16700Schasinglulu power_ctrl = on ? (1 << power_on) : (1 << power_off); 264*91f16700Schasinglulu mmio_setbits_32(SPM_PCM_RESERVE2, power_ctrl); 265*91f16700Schasinglulu ret = wait_mtcmos_ack(on, power_ctrl, power_status); 266*91f16700Schasinglulu VERBOSE("0x%x(%d), PWR_STATUS(0x%x), ret(%d)\n", 267*91f16700Schasinglulu power_ctrl, on, mmio_read_32(SPM_PWR_STATUS), ret); 268*91f16700Schasinglulu } 269*91f16700Schasinglulu 270*91f16700Schasinglulu mmio_clrbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN); 271*91f16700Schasinglulu spm_lock_release(); 272*91f16700Schasinglulu 273*91f16700Schasinglulu return ret; 274*91f16700Schasinglulu } 275