17d116dccSCC Ma /* 27d116dccSCC Ma * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 37d116dccSCC Ma * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 57d116dccSCC Ma */ 6*ee1ebbd1SIsla Mitchell 7*ee1ebbd1SIsla Mitchell #include <debug.h> 8*ee1ebbd1SIsla Mitchell #include <delay_timer.h> 97d116dccSCC Ma #include <mmio.h> 107d116dccSCC Ma #include <mt8173_def.h> 117d116dccSCC Ma #include <mtcmos.h> 127d116dccSCC Ma #include <spm.h> 131a1ff8b9SJimmy Huang #include <spm_mcdi.h> 147d116dccSCC Ma 157d116dccSCC Ma enum { 167d116dccSCC Ma SRAM_ISOINT_B = 1U << 6, 177d116dccSCC Ma SRAM_CKISO = 1U << 5, 187d116dccSCC Ma PWR_CLK_DIS = 1U << 4, 197d116dccSCC Ma PWR_ON_2ND = 1U << 3, 207d116dccSCC Ma PWR_ON = 1U << 2, 217d116dccSCC Ma PWR_ISO = 1U << 1, 227d116dccSCC Ma PWR_RST_B = 1U << 0 237d116dccSCC Ma }; 247d116dccSCC Ma 257d116dccSCC Ma enum { 267d116dccSCC Ma L1_PDN_ACK = 1U << 8, 277d116dccSCC Ma L1_PDN = 1U << 0 287d116dccSCC Ma }; 297d116dccSCC Ma 307d116dccSCC Ma enum { 317d116dccSCC Ma LITTLE_CPU3 = 1U << 12, 327d116dccSCC Ma LITTLE_CPU2 = 1U << 11, 337d116dccSCC Ma LITTLE_CPU1 = 1U << 10, 347d116dccSCC Ma }; 357d116dccSCC Ma 367d116dccSCC Ma enum { 377d116dccSCC Ma SRAM_PDN = 0xf << 8, 387d116dccSCC Ma DIS_SRAM_ACK = 0x1 << 12, 397d116dccSCC Ma AUD_SRAM_ACK = 0xf << 12, 407d116dccSCC Ma }; 417d116dccSCC Ma 427d116dccSCC Ma enum { 437d116dccSCC Ma DIS_PWR_STA_MASK = 0x1 << 3, 447d116dccSCC Ma AUD_PWR_STA_MASK = 0x1 << 24, 457d116dccSCC Ma }; 467d116dccSCC Ma 471a1ff8b9SJimmy Huang #define SPM_VDE_PWR_CON 0x0210 481a1ff8b9SJimmy Huang #define SPM_MFG_PWR_CON 0x0214 491a1ff8b9SJimmy Huang #define SPM_VEN_PWR_CON 0x0230 501a1ff8b9SJimmy Huang #define SPM_ISP_PWR_CON 0x0238 511a1ff8b9SJimmy Huang #define SPM_DIS_PWR_CON 0x023c 521a1ff8b9SJimmy Huang #define SPM_VEN2_PWR_CON 0x0298 531a1ff8b9SJimmy Huang #define SPM_AUDIO_PWR_CON 0x029c 541a1ff8b9SJimmy Huang #define SPM_MFG_2D_PWR_CON 0x02c0 551a1ff8b9SJimmy Huang #define SPM_MFG_ASYNC_PWR_CON 0x02c4 561a1ff8b9SJimmy Huang #define SPM_USB_PWR_CON 0x02cc 571a1ff8b9SJimmy Huang 581a1ff8b9SJimmy Huang #define MTCMOS_CTRL_SUCCESS 0 591a1ff8b9SJimmy Huang #define MTCMOS_CTRL_ERROR -1 601a1ff8b9SJimmy Huang 611a1ff8b9SJimmy Huang #define MTCMOS_CTRL_EN (0x1 << 18) 621a1ff8b9SJimmy Huang 631a1ff8b9SJimmy Huang #define VDE_PWR_ON 0 641a1ff8b9SJimmy Huang #define VEN_PWR_ON 1 651a1ff8b9SJimmy Huang #define ISP_PWR_ON 2 661a1ff8b9SJimmy Huang #define DIS_PWR_ON 3 671a1ff8b9SJimmy Huang #define VEN2_PWR_ON 4 681a1ff8b9SJimmy Huang #define AUDIO_PWR_ON 5 691a1ff8b9SJimmy Huang #define MFG_ASYNC_PWR_ON 6 701a1ff8b9SJimmy Huang #define MFG_2D_PWR_ON 7 711a1ff8b9SJimmy Huang #define MFG_PWR_ON 8 721a1ff8b9SJimmy Huang #define USB_PWR_ON 9 731a1ff8b9SJimmy Huang 741a1ff8b9SJimmy Huang #define VDE_PWR_OFF 10 751a1ff8b9SJimmy Huang #define VEN_PWR_OFF 11 761a1ff8b9SJimmy Huang #define ISP_PWR_OFF 12 771a1ff8b9SJimmy Huang #define DIS_PWR_OFF 13 781a1ff8b9SJimmy Huang #define VEN2_PWR_OFF 14 791a1ff8b9SJimmy Huang #define AUDIO_PWR_OFF 15 801a1ff8b9SJimmy Huang #define MFG_ASYNC_PWR_OFF 16 811a1ff8b9SJimmy Huang #define MFG_2D_PWR_OFF 17 821a1ff8b9SJimmy Huang #define MFG_PWR_OFF 18 831a1ff8b9SJimmy Huang #define USB_PWR_OFF 19 841a1ff8b9SJimmy Huang 851a1ff8b9SJimmy Huang #define VDE_PWR_CON_PWR_STA 7 861a1ff8b9SJimmy Huang #define VEN_PWR_CON_PWR_STA 21 871a1ff8b9SJimmy Huang #define ISP_PWR_CON_PWR_STA 5 881a1ff8b9SJimmy Huang #define DIS_PWR_CON_PWR_STA 3 891a1ff8b9SJimmy Huang #define VEN2_PWR_CON_PWR_STA 20 901a1ff8b9SJimmy Huang #define AUDIO_PWR_CON_PWR_STA 24 911a1ff8b9SJimmy Huang #define MFG_ASYNC_PWR_CON_PWR_STA 23 921a1ff8b9SJimmy Huang #define MFG_2D_PWR_CON_PWR_STA 22 931a1ff8b9SJimmy Huang #define MFG_PWR_CON_PWR_STA 4 941a1ff8b9SJimmy Huang #define USB_PWR_CON_PWR_STA 25 951a1ff8b9SJimmy Huang 961a1ff8b9SJimmy Huang /* 971a1ff8b9SJimmy Huang * Timeout if the ack is not signled after 1 second. 981a1ff8b9SJimmy Huang * According to designer, one mtcmos operation should be done 991a1ff8b9SJimmy Huang * around 10us. 1001a1ff8b9SJimmy Huang */ 1011a1ff8b9SJimmy Huang #define MTCMOS_ACK_POLLING_MAX_COUNT 10000 1021a1ff8b9SJimmy Huang #define MTCMOS_ACK_POLLING_INTERVAL 10 1031a1ff8b9SJimmy Huang 1047d116dccSCC Ma static void mtcmos_ctrl_little_off(unsigned int linear_id) 1057d116dccSCC Ma { 1067d116dccSCC Ma uint32_t reg_pwr_con; 1077d116dccSCC Ma uint32_t reg_l1_pdn; 1087d116dccSCC Ma uint32_t bit_cpu; 1097d116dccSCC Ma 1107d116dccSCC Ma switch (linear_id) { 1117d116dccSCC Ma case 1: 1127d116dccSCC Ma reg_pwr_con = SPM_CA7_CPU1_PWR_CON; 1137d116dccSCC Ma reg_l1_pdn = SPM_CA7_CPU1_L1_PDN; 1147d116dccSCC Ma bit_cpu = LITTLE_CPU1; 1157d116dccSCC Ma break; 1167d116dccSCC Ma case 2: 1177d116dccSCC Ma reg_pwr_con = SPM_CA7_CPU2_PWR_CON; 1187d116dccSCC Ma reg_l1_pdn = SPM_CA7_CPU2_L1_PDN; 1197d116dccSCC Ma bit_cpu = LITTLE_CPU2; 1207d116dccSCC Ma break; 1217d116dccSCC Ma case 3: 1227d116dccSCC Ma reg_pwr_con = SPM_CA7_CPU3_PWR_CON; 1237d116dccSCC Ma reg_l1_pdn = SPM_CA7_CPU3_L1_PDN; 1247d116dccSCC Ma bit_cpu = LITTLE_CPU3; 1257d116dccSCC Ma break; 1267d116dccSCC Ma default: 1277d116dccSCC Ma /* should never come to here */ 1287d116dccSCC Ma return; 1297d116dccSCC Ma } 1307d116dccSCC Ma 1317d116dccSCC Ma /* enable register control */ 1327d116dccSCC Ma mmio_write_32(SPM_POWERON_CONFIG_SET, 1337d116dccSCC Ma (SPM_PROJECT_CODE << 16) | (1U << 0)); 1347d116dccSCC Ma 1357d116dccSCC Ma mmio_setbits_32(reg_pwr_con, PWR_ISO); 1367d116dccSCC Ma mmio_setbits_32(reg_pwr_con, SRAM_CKISO); 1377d116dccSCC Ma mmio_clrbits_32(reg_pwr_con, SRAM_ISOINT_B); 1387d116dccSCC Ma mmio_setbits_32(reg_l1_pdn, L1_PDN); 1397d116dccSCC Ma 1407d116dccSCC Ma while (!(mmio_read_32(reg_l1_pdn) & L1_PDN_ACK)) 1417d116dccSCC Ma continue; 1427d116dccSCC Ma 1437d116dccSCC Ma mmio_clrbits_32(reg_pwr_con, PWR_RST_B); 1447d116dccSCC Ma mmio_setbits_32(reg_pwr_con, PWR_CLK_DIS); 1457d116dccSCC Ma mmio_clrbits_32(reg_pwr_con, PWR_ON); 1467d116dccSCC Ma mmio_clrbits_32(reg_pwr_con, PWR_ON_2ND); 1477d116dccSCC Ma 1487d116dccSCC Ma while ((mmio_read_32(SPM_PWR_STATUS) & bit_cpu) || 1497d116dccSCC Ma (mmio_read_32(SPM_PWR_STATUS_2ND) & bit_cpu)) 1507d116dccSCC Ma continue; 1517d116dccSCC Ma } 1527d116dccSCC Ma 1537d116dccSCC Ma void mtcmos_little_cpu_off(void) 1547d116dccSCC Ma { 1557d116dccSCC Ma /* turn off little cpu 1 - 3 */ 1567d116dccSCC Ma mtcmos_ctrl_little_off(1); 1577d116dccSCC Ma mtcmos_ctrl_little_off(2); 1587d116dccSCC Ma mtcmos_ctrl_little_off(3); 1597d116dccSCC Ma } 1601a1ff8b9SJimmy Huang 1618c9130c6SFan Chen uint32_t wait_mtcmos_ack(uint32_t on, uint32_t pwr_ctrl, uint32_t spm_pwr_sta) 1621a1ff8b9SJimmy Huang { 1631a1ff8b9SJimmy Huang int i = 0; 1641a1ff8b9SJimmy Huang uint32_t cmp, pwr_sta, pwr_sta_2nd; 1651a1ff8b9SJimmy Huang 1661a1ff8b9SJimmy Huang while (1) { 1678c9130c6SFan Chen cmp = mmio_read_32(SPM_PCM_PASR_DPD_3) & pwr_ctrl; 1681a1ff8b9SJimmy Huang pwr_sta = (mmio_read_32(SPM_PWR_STATUS) >> spm_pwr_sta) & 1; 1691a1ff8b9SJimmy Huang pwr_sta_2nd = 1701a1ff8b9SJimmy Huang (mmio_read_32(SPM_PWR_STATUS_2ND) >> spm_pwr_sta) & 1; 1718c9130c6SFan Chen if (cmp && (pwr_sta == on) && (pwr_sta_2nd == on)) { 1721a1ff8b9SJimmy Huang mmio_write_32(SPM_PCM_RESERVE2, 0); 1731a1ff8b9SJimmy Huang return MTCMOS_CTRL_SUCCESS; 1741a1ff8b9SJimmy Huang } 1751a1ff8b9SJimmy Huang udelay(MTCMOS_ACK_POLLING_INTERVAL); 1761a1ff8b9SJimmy Huang i++; 1771a1ff8b9SJimmy Huang if (i > MTCMOS_ACK_POLLING_MAX_COUNT) { 1781a1ff8b9SJimmy Huang INFO("MTCMOS control failed(%d), SPM_PWR_STA(%d),\n" 1791a1ff8b9SJimmy Huang "SPM_PCM_RESERVE=0x%x,SPM_PCM_RESERVE2=0x%x,\n" 1801a1ff8b9SJimmy Huang "SPM_PWR_STATUS=0x%x,SPM_PWR_STATUS_2ND=0x%x\n" 1811a1ff8b9SJimmy Huang "SPM_PCM_PASR_DPD_3 = 0x%x\n", 1821a1ff8b9SJimmy Huang on, spm_pwr_sta, mmio_read_32(SPM_PCM_RESERVE), 1831a1ff8b9SJimmy Huang mmio_read_32(SPM_PCM_RESERVE2), 1841a1ff8b9SJimmy Huang mmio_read_32(SPM_PWR_STATUS), 1851a1ff8b9SJimmy Huang mmio_read_32(SPM_PWR_STATUS_2ND), 1861a1ff8b9SJimmy Huang mmio_read_32(SPM_PCM_PASR_DPD_3)); 1871a1ff8b9SJimmy Huang mmio_write_32(SPM_PCM_RESERVE2, 0); 1881a1ff8b9SJimmy Huang return MTCMOS_CTRL_ERROR; 1891a1ff8b9SJimmy Huang } 1901a1ff8b9SJimmy Huang } 1911a1ff8b9SJimmy Huang } 1921a1ff8b9SJimmy Huang 1931a1ff8b9SJimmy Huang uint32_t mtcmos_non_cpu_ctrl(uint32_t on, uint32_t mtcmos_num) 1941a1ff8b9SJimmy Huang { 1951a1ff8b9SJimmy Huang uint32_t ret = MTCMOS_CTRL_SUCCESS; 1961a1ff8b9SJimmy Huang uint32_t power_on; 1971a1ff8b9SJimmy Huang uint32_t power_off; 1988c9130c6SFan Chen uint32_t power_ctrl; 1991a1ff8b9SJimmy Huang uint32_t power_status; 2001a1ff8b9SJimmy Huang 2011a1ff8b9SJimmy Huang spm_lock_get(); 2021a1ff8b9SJimmy Huang spm_mcdi_prepare_for_mtcmos(); 2031a1ff8b9SJimmy Huang mmio_setbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN); 2041a1ff8b9SJimmy Huang 2051a1ff8b9SJimmy Huang switch (mtcmos_num) { 2061a1ff8b9SJimmy Huang case SPM_VDE_PWR_CON: 2071a1ff8b9SJimmy Huang power_on = VDE_PWR_ON; 2081a1ff8b9SJimmy Huang power_off = VDE_PWR_OFF; 2091a1ff8b9SJimmy Huang power_status = VDE_PWR_CON_PWR_STA; 2101a1ff8b9SJimmy Huang break; 2111a1ff8b9SJimmy Huang case SPM_MFG_PWR_CON: 2121a1ff8b9SJimmy Huang power_on = MFG_PWR_ON; 2131a1ff8b9SJimmy Huang power_off = MFG_PWR_OFF; 2141a1ff8b9SJimmy Huang power_status = MFG_PWR_CON_PWR_STA; 2151a1ff8b9SJimmy Huang break; 2161a1ff8b9SJimmy Huang case SPM_VEN_PWR_CON: 2171a1ff8b9SJimmy Huang power_on = VEN_PWR_ON; 2181a1ff8b9SJimmy Huang power_off = VEN_PWR_OFF; 2191a1ff8b9SJimmy Huang power_status = VEN_PWR_CON_PWR_STA; 2201a1ff8b9SJimmy Huang break; 2211a1ff8b9SJimmy Huang case SPM_ISP_PWR_CON: 2221a1ff8b9SJimmy Huang power_on = ISP_PWR_ON; 2231a1ff8b9SJimmy Huang power_off = ISP_PWR_OFF; 2241a1ff8b9SJimmy Huang power_status = ISP_PWR_CON_PWR_STA; 2251a1ff8b9SJimmy Huang break; 2261a1ff8b9SJimmy Huang case SPM_DIS_PWR_CON: 2271a1ff8b9SJimmy Huang power_on = DIS_PWR_ON; 2281a1ff8b9SJimmy Huang power_off = DIS_PWR_OFF; 2291a1ff8b9SJimmy Huang power_status = DIS_PWR_CON_PWR_STA; 2301a1ff8b9SJimmy Huang break; 2311a1ff8b9SJimmy Huang case SPM_VEN2_PWR_CON: 2321a1ff8b9SJimmy Huang power_on = VEN2_PWR_ON; 2331a1ff8b9SJimmy Huang power_off = VEN2_PWR_OFF; 2341a1ff8b9SJimmy Huang power_status = VEN2_PWR_CON_PWR_STA; 2351a1ff8b9SJimmy Huang break; 2361a1ff8b9SJimmy Huang case SPM_AUDIO_PWR_CON: 2371a1ff8b9SJimmy Huang power_on = AUDIO_PWR_ON; 2381a1ff8b9SJimmy Huang power_off = AUDIO_PWR_OFF; 2391a1ff8b9SJimmy Huang power_status = AUDIO_PWR_CON_PWR_STA; 2401a1ff8b9SJimmy Huang break; 2411a1ff8b9SJimmy Huang case SPM_MFG_2D_PWR_CON: 2421a1ff8b9SJimmy Huang power_on = MFG_2D_PWR_ON; 2431a1ff8b9SJimmy Huang power_off = MFG_2D_PWR_OFF; 2441a1ff8b9SJimmy Huang power_status = MFG_2D_PWR_CON_PWR_STA; 2451a1ff8b9SJimmy Huang break; 2461a1ff8b9SJimmy Huang case SPM_MFG_ASYNC_PWR_CON: 2471a1ff8b9SJimmy Huang power_on = MFG_ASYNC_PWR_ON; 2481a1ff8b9SJimmy Huang power_off = MFG_ASYNC_PWR_OFF; 2491a1ff8b9SJimmy Huang power_status = MFG_ASYNC_PWR_CON_PWR_STA; 2501a1ff8b9SJimmy Huang break; 2511a1ff8b9SJimmy Huang case SPM_USB_PWR_CON: 2521a1ff8b9SJimmy Huang power_on = USB_PWR_ON; 2531a1ff8b9SJimmy Huang power_off = USB_PWR_OFF; 2541a1ff8b9SJimmy Huang power_status = USB_PWR_CON_PWR_STA; 2551a1ff8b9SJimmy Huang break; 2561a1ff8b9SJimmy Huang default: 2571a1ff8b9SJimmy Huang ret = MTCMOS_CTRL_ERROR; 2581a1ff8b9SJimmy Huang INFO("No mapping MTCMOS(%d), ret = %d\n", mtcmos_num, ret); 2591a1ff8b9SJimmy Huang break; 2601a1ff8b9SJimmy Huang } 2611a1ff8b9SJimmy Huang if (ret == MTCMOS_CTRL_SUCCESS) { 2628c9130c6SFan Chen power_ctrl = on ? (1 << power_on) : (1 << power_off); 2638c9130c6SFan Chen mmio_setbits_32(SPM_PCM_RESERVE2, power_ctrl); 2648c9130c6SFan Chen ret = wait_mtcmos_ack(on, power_ctrl, power_status); 2651a1ff8b9SJimmy Huang VERBOSE("0x%x(%d), PWR_STATUS(0x%x), ret(%d)\n", 2668c9130c6SFan Chen power_ctrl, on, mmio_read_32(SPM_PWR_STATUS), ret); 2671a1ff8b9SJimmy Huang } 2681a1ff8b9SJimmy Huang 2691a1ff8b9SJimmy Huang mmio_clrbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN); 2701a1ff8b9SJimmy Huang spm_lock_release(); 2711a1ff8b9SJimmy Huang 2721a1ff8b9SJimmy Huang return ret; 2731a1ff8b9SJimmy Huang } 274