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