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