17d116dccSCC Ma /* 27d116dccSCC Ma * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 37d116dccSCC Ma * 47d116dccSCC Ma * Redistribution and use in source and binary forms, with or without 57d116dccSCC Ma * modification, are permitted provided that the following conditions are met: 67d116dccSCC Ma * 77d116dccSCC Ma * Redistributions of source code must retain the above copyright notice, this 87d116dccSCC Ma * list of conditions and the following disclaimer. 97d116dccSCC Ma * 107d116dccSCC Ma * Redistributions in binary form must reproduce the above copyright notice, 117d116dccSCC Ma * this list of conditions and the following disclaimer in the documentation 127d116dccSCC Ma * and/or other materials provided with the distribution. 137d116dccSCC Ma * 147d116dccSCC Ma * Neither the name of ARM nor the names of its contributors may be used 157d116dccSCC Ma * to endorse or promote products derived from this software without specific 167d116dccSCC Ma * prior written permission. 177d116dccSCC Ma * 187d116dccSCC Ma * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 197d116dccSCC Ma * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 207d116dccSCC Ma * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 217d116dccSCC Ma * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 227d116dccSCC Ma * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 237d116dccSCC Ma * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 247d116dccSCC Ma * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 257d116dccSCC Ma * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 267d116dccSCC Ma * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 277d116dccSCC Ma * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 287d116dccSCC Ma * POSSIBILITY OF SUCH DAMAGE. 297d116dccSCC Ma */ 307d116dccSCC Ma #include <mmio.h> 317d116dccSCC Ma #include <mt8173_def.h> 32*1a1ff8b9SJimmy Huang #include <debug.h> 337d116dccSCC Ma #include <mtcmos.h> 347d116dccSCC Ma #include <spm.h> 35*1a1ff8b9SJimmy Huang #include <spm_mcdi.h> 36*1a1ff8b9SJimmy Huang #include <delay_timer.h> 377d116dccSCC Ma 387d116dccSCC Ma enum { 397d116dccSCC Ma SRAM_ISOINT_B = 1U << 6, 407d116dccSCC Ma SRAM_CKISO = 1U << 5, 417d116dccSCC Ma PWR_CLK_DIS = 1U << 4, 427d116dccSCC Ma PWR_ON_2ND = 1U << 3, 437d116dccSCC Ma PWR_ON = 1U << 2, 447d116dccSCC Ma PWR_ISO = 1U << 1, 457d116dccSCC Ma PWR_RST_B = 1U << 0 467d116dccSCC Ma }; 477d116dccSCC Ma 487d116dccSCC Ma enum { 497d116dccSCC Ma L1_PDN_ACK = 1U << 8, 507d116dccSCC Ma L1_PDN = 1U << 0 517d116dccSCC Ma }; 527d116dccSCC Ma 537d116dccSCC Ma enum { 547d116dccSCC Ma LITTLE_CPU3 = 1U << 12, 557d116dccSCC Ma LITTLE_CPU2 = 1U << 11, 567d116dccSCC Ma LITTLE_CPU1 = 1U << 10, 577d116dccSCC Ma }; 587d116dccSCC Ma 597d116dccSCC Ma enum { 607d116dccSCC Ma SRAM_PDN = 0xf << 8, 617d116dccSCC Ma DIS_SRAM_ACK = 0x1 << 12, 627d116dccSCC Ma AUD_SRAM_ACK = 0xf << 12, 637d116dccSCC Ma }; 647d116dccSCC Ma 657d116dccSCC Ma enum { 667d116dccSCC Ma DIS_PWR_STA_MASK = 0x1 << 3, 677d116dccSCC Ma AUD_PWR_STA_MASK = 0x1 << 24, 687d116dccSCC Ma }; 697d116dccSCC Ma 70*1a1ff8b9SJimmy Huang #define SPM_VDE_PWR_CON 0x0210 71*1a1ff8b9SJimmy Huang #define SPM_MFG_PWR_CON 0x0214 72*1a1ff8b9SJimmy Huang #define SPM_VEN_PWR_CON 0x0230 73*1a1ff8b9SJimmy Huang #define SPM_ISP_PWR_CON 0x0238 74*1a1ff8b9SJimmy Huang #define SPM_DIS_PWR_CON 0x023c 75*1a1ff8b9SJimmy Huang #define SPM_VEN2_PWR_CON 0x0298 76*1a1ff8b9SJimmy Huang #define SPM_AUDIO_PWR_CON 0x029c 77*1a1ff8b9SJimmy Huang #define SPM_MFG_2D_PWR_CON 0x02c0 78*1a1ff8b9SJimmy Huang #define SPM_MFG_ASYNC_PWR_CON 0x02c4 79*1a1ff8b9SJimmy Huang #define SPM_USB_PWR_CON 0x02cc 80*1a1ff8b9SJimmy Huang 81*1a1ff8b9SJimmy Huang #define MTCMOS_CTRL_SUCCESS 0 82*1a1ff8b9SJimmy Huang #define MTCMOS_CTRL_ERROR -1 83*1a1ff8b9SJimmy Huang 84*1a1ff8b9SJimmy Huang #define MTCMOS_CTRL_EN (0x1 << 18) 85*1a1ff8b9SJimmy Huang 86*1a1ff8b9SJimmy Huang #define VDE_PWR_ON 0 87*1a1ff8b9SJimmy Huang #define VEN_PWR_ON 1 88*1a1ff8b9SJimmy Huang #define ISP_PWR_ON 2 89*1a1ff8b9SJimmy Huang #define DIS_PWR_ON 3 90*1a1ff8b9SJimmy Huang #define VEN2_PWR_ON 4 91*1a1ff8b9SJimmy Huang #define AUDIO_PWR_ON 5 92*1a1ff8b9SJimmy Huang #define MFG_ASYNC_PWR_ON 6 93*1a1ff8b9SJimmy Huang #define MFG_2D_PWR_ON 7 94*1a1ff8b9SJimmy Huang #define MFG_PWR_ON 8 95*1a1ff8b9SJimmy Huang #define USB_PWR_ON 9 96*1a1ff8b9SJimmy Huang 97*1a1ff8b9SJimmy Huang #define VDE_PWR_OFF 10 98*1a1ff8b9SJimmy Huang #define VEN_PWR_OFF 11 99*1a1ff8b9SJimmy Huang #define ISP_PWR_OFF 12 100*1a1ff8b9SJimmy Huang #define DIS_PWR_OFF 13 101*1a1ff8b9SJimmy Huang #define VEN2_PWR_OFF 14 102*1a1ff8b9SJimmy Huang #define AUDIO_PWR_OFF 15 103*1a1ff8b9SJimmy Huang #define MFG_ASYNC_PWR_OFF 16 104*1a1ff8b9SJimmy Huang #define MFG_2D_PWR_OFF 17 105*1a1ff8b9SJimmy Huang #define MFG_PWR_OFF 18 106*1a1ff8b9SJimmy Huang #define USB_PWR_OFF 19 107*1a1ff8b9SJimmy Huang 108*1a1ff8b9SJimmy Huang #define VDE_PWR_CON_PWR_STA 7 109*1a1ff8b9SJimmy Huang #define VEN_PWR_CON_PWR_STA 21 110*1a1ff8b9SJimmy Huang #define ISP_PWR_CON_PWR_STA 5 111*1a1ff8b9SJimmy Huang #define DIS_PWR_CON_PWR_STA 3 112*1a1ff8b9SJimmy Huang #define VEN2_PWR_CON_PWR_STA 20 113*1a1ff8b9SJimmy Huang #define AUDIO_PWR_CON_PWR_STA 24 114*1a1ff8b9SJimmy Huang #define MFG_ASYNC_PWR_CON_PWR_STA 23 115*1a1ff8b9SJimmy Huang #define MFG_2D_PWR_CON_PWR_STA 22 116*1a1ff8b9SJimmy Huang #define MFG_PWR_CON_PWR_STA 4 117*1a1ff8b9SJimmy Huang #define USB_PWR_CON_PWR_STA 25 118*1a1ff8b9SJimmy Huang 119*1a1ff8b9SJimmy Huang /* 120*1a1ff8b9SJimmy Huang * Timeout if the ack is not signled after 1 second. 121*1a1ff8b9SJimmy Huang * According to designer, one mtcmos operation should be done 122*1a1ff8b9SJimmy Huang * around 10us. 123*1a1ff8b9SJimmy Huang */ 124*1a1ff8b9SJimmy Huang #define MTCMOS_ACK_POLLING_MAX_COUNT 10000 125*1a1ff8b9SJimmy Huang #define MTCMOS_ACK_POLLING_INTERVAL 10 126*1a1ff8b9SJimmy Huang 1277d116dccSCC Ma static void mtcmos_ctrl_little_off(unsigned int linear_id) 1287d116dccSCC Ma { 1297d116dccSCC Ma uint32_t reg_pwr_con; 1307d116dccSCC Ma uint32_t reg_l1_pdn; 1317d116dccSCC Ma uint32_t bit_cpu; 1327d116dccSCC Ma 1337d116dccSCC Ma switch (linear_id) { 1347d116dccSCC Ma case 1: 1357d116dccSCC Ma reg_pwr_con = SPM_CA7_CPU1_PWR_CON; 1367d116dccSCC Ma reg_l1_pdn = SPM_CA7_CPU1_L1_PDN; 1377d116dccSCC Ma bit_cpu = LITTLE_CPU1; 1387d116dccSCC Ma break; 1397d116dccSCC Ma case 2: 1407d116dccSCC Ma reg_pwr_con = SPM_CA7_CPU2_PWR_CON; 1417d116dccSCC Ma reg_l1_pdn = SPM_CA7_CPU2_L1_PDN; 1427d116dccSCC Ma bit_cpu = LITTLE_CPU2; 1437d116dccSCC Ma break; 1447d116dccSCC Ma case 3: 1457d116dccSCC Ma reg_pwr_con = SPM_CA7_CPU3_PWR_CON; 1467d116dccSCC Ma reg_l1_pdn = SPM_CA7_CPU3_L1_PDN; 1477d116dccSCC Ma bit_cpu = LITTLE_CPU3; 1487d116dccSCC Ma break; 1497d116dccSCC Ma default: 1507d116dccSCC Ma /* should never come to here */ 1517d116dccSCC Ma return; 1527d116dccSCC Ma } 1537d116dccSCC Ma 1547d116dccSCC Ma /* enable register control */ 1557d116dccSCC Ma mmio_write_32(SPM_POWERON_CONFIG_SET, 1567d116dccSCC Ma (SPM_PROJECT_CODE << 16) | (1U << 0)); 1577d116dccSCC Ma 1587d116dccSCC Ma mmio_setbits_32(reg_pwr_con, PWR_ISO); 1597d116dccSCC Ma mmio_setbits_32(reg_pwr_con, SRAM_CKISO); 1607d116dccSCC Ma mmio_clrbits_32(reg_pwr_con, SRAM_ISOINT_B); 1617d116dccSCC Ma mmio_setbits_32(reg_l1_pdn, L1_PDN); 1627d116dccSCC Ma 1637d116dccSCC Ma while (!(mmio_read_32(reg_l1_pdn) & L1_PDN_ACK)) 1647d116dccSCC Ma continue; 1657d116dccSCC Ma 1667d116dccSCC Ma mmio_clrbits_32(reg_pwr_con, PWR_RST_B); 1677d116dccSCC Ma mmio_setbits_32(reg_pwr_con, PWR_CLK_DIS); 1687d116dccSCC Ma mmio_clrbits_32(reg_pwr_con, PWR_ON); 1697d116dccSCC Ma mmio_clrbits_32(reg_pwr_con, PWR_ON_2ND); 1707d116dccSCC Ma 1717d116dccSCC Ma while ((mmio_read_32(SPM_PWR_STATUS) & bit_cpu) || 1727d116dccSCC Ma (mmio_read_32(SPM_PWR_STATUS_2ND) & bit_cpu)) 1737d116dccSCC Ma continue; 1747d116dccSCC Ma } 1757d116dccSCC Ma 1767d116dccSCC Ma void mtcmos_little_cpu_off(void) 1777d116dccSCC Ma { 1787d116dccSCC Ma /* turn off little cpu 1 - 3 */ 1797d116dccSCC Ma mtcmos_ctrl_little_off(1); 1807d116dccSCC Ma mtcmos_ctrl_little_off(2); 1817d116dccSCC Ma mtcmos_ctrl_little_off(3); 1827d116dccSCC Ma } 183*1a1ff8b9SJimmy Huang 184*1a1ff8b9SJimmy Huang uint32_t wait_mtcmos_ack(uint32_t on, uint32_t mtcmos_sta, uint32_t spm_pwr_sta) 185*1a1ff8b9SJimmy Huang { 186*1a1ff8b9SJimmy Huang int i = 0; 187*1a1ff8b9SJimmy Huang uint32_t cmp, pwr_sta, pwr_sta_2nd; 188*1a1ff8b9SJimmy Huang 189*1a1ff8b9SJimmy Huang while (1) { 190*1a1ff8b9SJimmy Huang cmp = (mmio_read_32(SPM_PCM_PASR_DPD_3) >> mtcmos_sta) & 1; 191*1a1ff8b9SJimmy Huang pwr_sta = (mmio_read_32(SPM_PWR_STATUS) >> spm_pwr_sta) & 1; 192*1a1ff8b9SJimmy Huang pwr_sta_2nd = 193*1a1ff8b9SJimmy Huang (mmio_read_32(SPM_PWR_STATUS_2ND) >> spm_pwr_sta) & 1; 194*1a1ff8b9SJimmy Huang if ((cmp == on) && (pwr_sta == on) && (pwr_sta_2nd == on)) { 195*1a1ff8b9SJimmy Huang mmio_write_32(SPM_PCM_RESERVE2, 0); 196*1a1ff8b9SJimmy Huang return MTCMOS_CTRL_SUCCESS; 197*1a1ff8b9SJimmy Huang } 198*1a1ff8b9SJimmy Huang udelay(MTCMOS_ACK_POLLING_INTERVAL); 199*1a1ff8b9SJimmy Huang i++; 200*1a1ff8b9SJimmy Huang if (i > MTCMOS_ACK_POLLING_MAX_COUNT) { 201*1a1ff8b9SJimmy Huang INFO("MTCMOS control failed(%d), SPM_PWR_STA(%d),\n" 202*1a1ff8b9SJimmy Huang "SPM_PCM_RESERVE=0x%x,SPM_PCM_RESERVE2=0x%x,\n" 203*1a1ff8b9SJimmy Huang "SPM_PWR_STATUS=0x%x,SPM_PWR_STATUS_2ND=0x%x\n" 204*1a1ff8b9SJimmy Huang "SPM_PCM_PASR_DPD_3 = 0x%x\n", 205*1a1ff8b9SJimmy Huang on, spm_pwr_sta, mmio_read_32(SPM_PCM_RESERVE), 206*1a1ff8b9SJimmy Huang mmio_read_32(SPM_PCM_RESERVE2), 207*1a1ff8b9SJimmy Huang mmio_read_32(SPM_PWR_STATUS), 208*1a1ff8b9SJimmy Huang mmio_read_32(SPM_PWR_STATUS_2ND), 209*1a1ff8b9SJimmy Huang mmio_read_32(SPM_PCM_PASR_DPD_3)); 210*1a1ff8b9SJimmy Huang mmio_write_32(SPM_PCM_RESERVE2, 0); 211*1a1ff8b9SJimmy Huang return MTCMOS_CTRL_ERROR; 212*1a1ff8b9SJimmy Huang } 213*1a1ff8b9SJimmy Huang } 214*1a1ff8b9SJimmy Huang } 215*1a1ff8b9SJimmy Huang 216*1a1ff8b9SJimmy Huang uint32_t mtcmos_non_cpu_ctrl(uint32_t on, uint32_t mtcmos_num) 217*1a1ff8b9SJimmy Huang { 218*1a1ff8b9SJimmy Huang uint32_t ret = MTCMOS_CTRL_SUCCESS; 219*1a1ff8b9SJimmy Huang uint32_t power_on; 220*1a1ff8b9SJimmy Huang uint32_t power_off; 221*1a1ff8b9SJimmy Huang uint32_t power_status; 222*1a1ff8b9SJimmy Huang 223*1a1ff8b9SJimmy Huang spm_lock_get(); 224*1a1ff8b9SJimmy Huang spm_mcdi_prepare_for_mtcmos(); 225*1a1ff8b9SJimmy Huang mmio_setbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN); 226*1a1ff8b9SJimmy Huang 227*1a1ff8b9SJimmy Huang switch (mtcmos_num) { 228*1a1ff8b9SJimmy Huang case SPM_VDE_PWR_CON: 229*1a1ff8b9SJimmy Huang power_on = VDE_PWR_ON; 230*1a1ff8b9SJimmy Huang power_off = VDE_PWR_OFF; 231*1a1ff8b9SJimmy Huang power_status = VDE_PWR_CON_PWR_STA; 232*1a1ff8b9SJimmy Huang break; 233*1a1ff8b9SJimmy Huang case SPM_MFG_PWR_CON: 234*1a1ff8b9SJimmy Huang power_on = MFG_PWR_ON; 235*1a1ff8b9SJimmy Huang power_off = MFG_PWR_OFF; 236*1a1ff8b9SJimmy Huang power_status = MFG_PWR_CON_PWR_STA; 237*1a1ff8b9SJimmy Huang break; 238*1a1ff8b9SJimmy Huang case SPM_VEN_PWR_CON: 239*1a1ff8b9SJimmy Huang power_on = VEN_PWR_ON; 240*1a1ff8b9SJimmy Huang power_off = VEN_PWR_OFF; 241*1a1ff8b9SJimmy Huang power_status = VEN_PWR_CON_PWR_STA; 242*1a1ff8b9SJimmy Huang break; 243*1a1ff8b9SJimmy Huang case SPM_ISP_PWR_CON: 244*1a1ff8b9SJimmy Huang power_on = ISP_PWR_ON; 245*1a1ff8b9SJimmy Huang power_off = ISP_PWR_OFF; 246*1a1ff8b9SJimmy Huang power_status = ISP_PWR_CON_PWR_STA; 247*1a1ff8b9SJimmy Huang break; 248*1a1ff8b9SJimmy Huang case SPM_DIS_PWR_CON: 249*1a1ff8b9SJimmy Huang power_on = DIS_PWR_ON; 250*1a1ff8b9SJimmy Huang power_off = DIS_PWR_OFF; 251*1a1ff8b9SJimmy Huang power_status = DIS_PWR_CON_PWR_STA; 252*1a1ff8b9SJimmy Huang break; 253*1a1ff8b9SJimmy Huang case SPM_VEN2_PWR_CON: 254*1a1ff8b9SJimmy Huang power_on = VEN2_PWR_ON; 255*1a1ff8b9SJimmy Huang power_off = VEN2_PWR_OFF; 256*1a1ff8b9SJimmy Huang power_status = VEN2_PWR_CON_PWR_STA; 257*1a1ff8b9SJimmy Huang break; 258*1a1ff8b9SJimmy Huang case SPM_AUDIO_PWR_CON: 259*1a1ff8b9SJimmy Huang power_on = AUDIO_PWR_ON; 260*1a1ff8b9SJimmy Huang power_off = AUDIO_PWR_OFF; 261*1a1ff8b9SJimmy Huang power_status = AUDIO_PWR_CON_PWR_STA; 262*1a1ff8b9SJimmy Huang break; 263*1a1ff8b9SJimmy Huang case SPM_MFG_2D_PWR_CON: 264*1a1ff8b9SJimmy Huang power_on = MFG_2D_PWR_ON; 265*1a1ff8b9SJimmy Huang power_off = MFG_2D_PWR_OFF; 266*1a1ff8b9SJimmy Huang power_status = MFG_2D_PWR_CON_PWR_STA; 267*1a1ff8b9SJimmy Huang break; 268*1a1ff8b9SJimmy Huang case SPM_MFG_ASYNC_PWR_CON: 269*1a1ff8b9SJimmy Huang power_on = MFG_ASYNC_PWR_ON; 270*1a1ff8b9SJimmy Huang power_off = MFG_ASYNC_PWR_OFF; 271*1a1ff8b9SJimmy Huang power_status = MFG_ASYNC_PWR_CON_PWR_STA; 272*1a1ff8b9SJimmy Huang break; 273*1a1ff8b9SJimmy Huang case SPM_USB_PWR_CON: 274*1a1ff8b9SJimmy Huang power_on = USB_PWR_ON; 275*1a1ff8b9SJimmy Huang power_off = USB_PWR_OFF; 276*1a1ff8b9SJimmy Huang power_status = USB_PWR_CON_PWR_STA; 277*1a1ff8b9SJimmy Huang break; 278*1a1ff8b9SJimmy Huang default: 279*1a1ff8b9SJimmy Huang ret = MTCMOS_CTRL_ERROR; 280*1a1ff8b9SJimmy Huang INFO("No mapping MTCMOS(%d), ret = %d\n", mtcmos_num, ret); 281*1a1ff8b9SJimmy Huang break; 282*1a1ff8b9SJimmy Huang } 283*1a1ff8b9SJimmy Huang 284*1a1ff8b9SJimmy Huang if (ret == MTCMOS_CTRL_SUCCESS) { 285*1a1ff8b9SJimmy Huang mmio_setbits_32(SPM_PCM_RESERVE2, on ? 286*1a1ff8b9SJimmy Huang (1 << power_on) : (1 << power_off)); 287*1a1ff8b9SJimmy Huang ret = wait_mtcmos_ack(on, power_on, power_status); 288*1a1ff8b9SJimmy Huang VERBOSE("0x%x(%d), PWR_STATUS(0x%x), ret(%d)\n", 289*1a1ff8b9SJimmy Huang power_on, on, mmio_read_32(SPM_PWR_STATUS), ret); 290*1a1ff8b9SJimmy Huang } 291*1a1ff8b9SJimmy Huang 292*1a1ff8b9SJimmy Huang mmio_clrbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN); 293*1a1ff8b9SJimmy Huang spm_lock_release(); 294*1a1ff8b9SJimmy Huang 295*1a1ff8b9SJimmy Huang return ret; 296*1a1ff8b9SJimmy Huang } 297