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> 321a1ff8b9SJimmy Huang #include <debug.h> 337d116dccSCC Ma #include <mtcmos.h> 347d116dccSCC Ma #include <spm.h> 351a1ff8b9SJimmy Huang #include <spm_mcdi.h> 361a1ff8b9SJimmy 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 701a1ff8b9SJimmy Huang #define SPM_VDE_PWR_CON 0x0210 711a1ff8b9SJimmy Huang #define SPM_MFG_PWR_CON 0x0214 721a1ff8b9SJimmy Huang #define SPM_VEN_PWR_CON 0x0230 731a1ff8b9SJimmy Huang #define SPM_ISP_PWR_CON 0x0238 741a1ff8b9SJimmy Huang #define SPM_DIS_PWR_CON 0x023c 751a1ff8b9SJimmy Huang #define SPM_VEN2_PWR_CON 0x0298 761a1ff8b9SJimmy Huang #define SPM_AUDIO_PWR_CON 0x029c 771a1ff8b9SJimmy Huang #define SPM_MFG_2D_PWR_CON 0x02c0 781a1ff8b9SJimmy Huang #define SPM_MFG_ASYNC_PWR_CON 0x02c4 791a1ff8b9SJimmy Huang #define SPM_USB_PWR_CON 0x02cc 801a1ff8b9SJimmy Huang 811a1ff8b9SJimmy Huang #define MTCMOS_CTRL_SUCCESS 0 821a1ff8b9SJimmy Huang #define MTCMOS_CTRL_ERROR -1 831a1ff8b9SJimmy Huang 841a1ff8b9SJimmy Huang #define MTCMOS_CTRL_EN (0x1 << 18) 851a1ff8b9SJimmy Huang 861a1ff8b9SJimmy Huang #define VDE_PWR_ON 0 871a1ff8b9SJimmy Huang #define VEN_PWR_ON 1 881a1ff8b9SJimmy Huang #define ISP_PWR_ON 2 891a1ff8b9SJimmy Huang #define DIS_PWR_ON 3 901a1ff8b9SJimmy Huang #define VEN2_PWR_ON 4 911a1ff8b9SJimmy Huang #define AUDIO_PWR_ON 5 921a1ff8b9SJimmy Huang #define MFG_ASYNC_PWR_ON 6 931a1ff8b9SJimmy Huang #define MFG_2D_PWR_ON 7 941a1ff8b9SJimmy Huang #define MFG_PWR_ON 8 951a1ff8b9SJimmy Huang #define USB_PWR_ON 9 961a1ff8b9SJimmy Huang 971a1ff8b9SJimmy Huang #define VDE_PWR_OFF 10 981a1ff8b9SJimmy Huang #define VEN_PWR_OFF 11 991a1ff8b9SJimmy Huang #define ISP_PWR_OFF 12 1001a1ff8b9SJimmy Huang #define DIS_PWR_OFF 13 1011a1ff8b9SJimmy Huang #define VEN2_PWR_OFF 14 1021a1ff8b9SJimmy Huang #define AUDIO_PWR_OFF 15 1031a1ff8b9SJimmy Huang #define MFG_ASYNC_PWR_OFF 16 1041a1ff8b9SJimmy Huang #define MFG_2D_PWR_OFF 17 1051a1ff8b9SJimmy Huang #define MFG_PWR_OFF 18 1061a1ff8b9SJimmy Huang #define USB_PWR_OFF 19 1071a1ff8b9SJimmy Huang 1081a1ff8b9SJimmy Huang #define VDE_PWR_CON_PWR_STA 7 1091a1ff8b9SJimmy Huang #define VEN_PWR_CON_PWR_STA 21 1101a1ff8b9SJimmy Huang #define ISP_PWR_CON_PWR_STA 5 1111a1ff8b9SJimmy Huang #define DIS_PWR_CON_PWR_STA 3 1121a1ff8b9SJimmy Huang #define VEN2_PWR_CON_PWR_STA 20 1131a1ff8b9SJimmy Huang #define AUDIO_PWR_CON_PWR_STA 24 1141a1ff8b9SJimmy Huang #define MFG_ASYNC_PWR_CON_PWR_STA 23 1151a1ff8b9SJimmy Huang #define MFG_2D_PWR_CON_PWR_STA 22 1161a1ff8b9SJimmy Huang #define MFG_PWR_CON_PWR_STA 4 1171a1ff8b9SJimmy Huang #define USB_PWR_CON_PWR_STA 25 1181a1ff8b9SJimmy Huang 1191a1ff8b9SJimmy Huang /* 1201a1ff8b9SJimmy Huang * Timeout if the ack is not signled after 1 second. 1211a1ff8b9SJimmy Huang * According to designer, one mtcmos operation should be done 1221a1ff8b9SJimmy Huang * around 10us. 1231a1ff8b9SJimmy Huang */ 1241a1ff8b9SJimmy Huang #define MTCMOS_ACK_POLLING_MAX_COUNT 10000 1251a1ff8b9SJimmy Huang #define MTCMOS_ACK_POLLING_INTERVAL 10 1261a1ff8b9SJimmy 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 } 1831a1ff8b9SJimmy Huang 184*8c9130c6SFan Chen uint32_t wait_mtcmos_ack(uint32_t on, uint32_t pwr_ctrl, uint32_t spm_pwr_sta) 1851a1ff8b9SJimmy Huang { 1861a1ff8b9SJimmy Huang int i = 0; 1871a1ff8b9SJimmy Huang uint32_t cmp, pwr_sta, pwr_sta_2nd; 1881a1ff8b9SJimmy Huang 1891a1ff8b9SJimmy Huang while (1) { 190*8c9130c6SFan Chen cmp = mmio_read_32(SPM_PCM_PASR_DPD_3) & pwr_ctrl; 1911a1ff8b9SJimmy Huang pwr_sta = (mmio_read_32(SPM_PWR_STATUS) >> spm_pwr_sta) & 1; 1921a1ff8b9SJimmy Huang pwr_sta_2nd = 1931a1ff8b9SJimmy Huang (mmio_read_32(SPM_PWR_STATUS_2ND) >> spm_pwr_sta) & 1; 194*8c9130c6SFan Chen if (cmp && (pwr_sta == on) && (pwr_sta_2nd == on)) { 1951a1ff8b9SJimmy Huang mmio_write_32(SPM_PCM_RESERVE2, 0); 1961a1ff8b9SJimmy Huang return MTCMOS_CTRL_SUCCESS; 1971a1ff8b9SJimmy Huang } 1981a1ff8b9SJimmy Huang udelay(MTCMOS_ACK_POLLING_INTERVAL); 1991a1ff8b9SJimmy Huang i++; 2001a1ff8b9SJimmy Huang if (i > MTCMOS_ACK_POLLING_MAX_COUNT) { 2011a1ff8b9SJimmy Huang INFO("MTCMOS control failed(%d), SPM_PWR_STA(%d),\n" 2021a1ff8b9SJimmy Huang "SPM_PCM_RESERVE=0x%x,SPM_PCM_RESERVE2=0x%x,\n" 2031a1ff8b9SJimmy Huang "SPM_PWR_STATUS=0x%x,SPM_PWR_STATUS_2ND=0x%x\n" 2041a1ff8b9SJimmy Huang "SPM_PCM_PASR_DPD_3 = 0x%x\n", 2051a1ff8b9SJimmy Huang on, spm_pwr_sta, mmio_read_32(SPM_PCM_RESERVE), 2061a1ff8b9SJimmy Huang mmio_read_32(SPM_PCM_RESERVE2), 2071a1ff8b9SJimmy Huang mmio_read_32(SPM_PWR_STATUS), 2081a1ff8b9SJimmy Huang mmio_read_32(SPM_PWR_STATUS_2ND), 2091a1ff8b9SJimmy Huang mmio_read_32(SPM_PCM_PASR_DPD_3)); 2101a1ff8b9SJimmy Huang mmio_write_32(SPM_PCM_RESERVE2, 0); 2111a1ff8b9SJimmy Huang return MTCMOS_CTRL_ERROR; 2121a1ff8b9SJimmy Huang } 2131a1ff8b9SJimmy Huang } 2141a1ff8b9SJimmy Huang } 2151a1ff8b9SJimmy Huang 2161a1ff8b9SJimmy Huang uint32_t mtcmos_non_cpu_ctrl(uint32_t on, uint32_t mtcmos_num) 2171a1ff8b9SJimmy Huang { 2181a1ff8b9SJimmy Huang uint32_t ret = MTCMOS_CTRL_SUCCESS; 2191a1ff8b9SJimmy Huang uint32_t power_on; 2201a1ff8b9SJimmy Huang uint32_t power_off; 221*8c9130c6SFan Chen uint32_t power_ctrl; 2221a1ff8b9SJimmy Huang uint32_t power_status; 2231a1ff8b9SJimmy Huang 2241a1ff8b9SJimmy Huang spm_lock_get(); 2251a1ff8b9SJimmy Huang spm_mcdi_prepare_for_mtcmos(); 2261a1ff8b9SJimmy Huang mmio_setbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN); 2271a1ff8b9SJimmy Huang 2281a1ff8b9SJimmy Huang switch (mtcmos_num) { 2291a1ff8b9SJimmy Huang case SPM_VDE_PWR_CON: 2301a1ff8b9SJimmy Huang power_on = VDE_PWR_ON; 2311a1ff8b9SJimmy Huang power_off = VDE_PWR_OFF; 2321a1ff8b9SJimmy Huang power_status = VDE_PWR_CON_PWR_STA; 2331a1ff8b9SJimmy Huang break; 2341a1ff8b9SJimmy Huang case SPM_MFG_PWR_CON: 2351a1ff8b9SJimmy Huang power_on = MFG_PWR_ON; 2361a1ff8b9SJimmy Huang power_off = MFG_PWR_OFF; 2371a1ff8b9SJimmy Huang power_status = MFG_PWR_CON_PWR_STA; 2381a1ff8b9SJimmy Huang break; 2391a1ff8b9SJimmy Huang case SPM_VEN_PWR_CON: 2401a1ff8b9SJimmy Huang power_on = VEN_PWR_ON; 2411a1ff8b9SJimmy Huang power_off = VEN_PWR_OFF; 2421a1ff8b9SJimmy Huang power_status = VEN_PWR_CON_PWR_STA; 2431a1ff8b9SJimmy Huang break; 2441a1ff8b9SJimmy Huang case SPM_ISP_PWR_CON: 2451a1ff8b9SJimmy Huang power_on = ISP_PWR_ON; 2461a1ff8b9SJimmy Huang power_off = ISP_PWR_OFF; 2471a1ff8b9SJimmy Huang power_status = ISP_PWR_CON_PWR_STA; 2481a1ff8b9SJimmy Huang break; 2491a1ff8b9SJimmy Huang case SPM_DIS_PWR_CON: 2501a1ff8b9SJimmy Huang power_on = DIS_PWR_ON; 2511a1ff8b9SJimmy Huang power_off = DIS_PWR_OFF; 2521a1ff8b9SJimmy Huang power_status = DIS_PWR_CON_PWR_STA; 2531a1ff8b9SJimmy Huang break; 2541a1ff8b9SJimmy Huang case SPM_VEN2_PWR_CON: 2551a1ff8b9SJimmy Huang power_on = VEN2_PWR_ON; 2561a1ff8b9SJimmy Huang power_off = VEN2_PWR_OFF; 2571a1ff8b9SJimmy Huang power_status = VEN2_PWR_CON_PWR_STA; 2581a1ff8b9SJimmy Huang break; 2591a1ff8b9SJimmy Huang case SPM_AUDIO_PWR_CON: 2601a1ff8b9SJimmy Huang power_on = AUDIO_PWR_ON; 2611a1ff8b9SJimmy Huang power_off = AUDIO_PWR_OFF; 2621a1ff8b9SJimmy Huang power_status = AUDIO_PWR_CON_PWR_STA; 2631a1ff8b9SJimmy Huang break; 2641a1ff8b9SJimmy Huang case SPM_MFG_2D_PWR_CON: 2651a1ff8b9SJimmy Huang power_on = MFG_2D_PWR_ON; 2661a1ff8b9SJimmy Huang power_off = MFG_2D_PWR_OFF; 2671a1ff8b9SJimmy Huang power_status = MFG_2D_PWR_CON_PWR_STA; 2681a1ff8b9SJimmy Huang break; 2691a1ff8b9SJimmy Huang case SPM_MFG_ASYNC_PWR_CON: 2701a1ff8b9SJimmy Huang power_on = MFG_ASYNC_PWR_ON; 2711a1ff8b9SJimmy Huang power_off = MFG_ASYNC_PWR_OFF; 2721a1ff8b9SJimmy Huang power_status = MFG_ASYNC_PWR_CON_PWR_STA; 2731a1ff8b9SJimmy Huang break; 2741a1ff8b9SJimmy Huang case SPM_USB_PWR_CON: 2751a1ff8b9SJimmy Huang power_on = USB_PWR_ON; 2761a1ff8b9SJimmy Huang power_off = USB_PWR_OFF; 2771a1ff8b9SJimmy Huang power_status = USB_PWR_CON_PWR_STA; 2781a1ff8b9SJimmy Huang break; 2791a1ff8b9SJimmy Huang default: 2801a1ff8b9SJimmy Huang ret = MTCMOS_CTRL_ERROR; 2811a1ff8b9SJimmy Huang INFO("No mapping MTCMOS(%d), ret = %d\n", mtcmos_num, ret); 2821a1ff8b9SJimmy Huang break; 2831a1ff8b9SJimmy Huang } 2841a1ff8b9SJimmy Huang if (ret == MTCMOS_CTRL_SUCCESS) { 285*8c9130c6SFan Chen power_ctrl = on ? (1 << power_on) : (1 << power_off); 286*8c9130c6SFan Chen mmio_setbits_32(SPM_PCM_RESERVE2, power_ctrl); 287*8c9130c6SFan Chen ret = wait_mtcmos_ack(on, power_ctrl, power_status); 2881a1ff8b9SJimmy Huang VERBOSE("0x%x(%d), PWR_STATUS(0x%x), ret(%d)\n", 289*8c9130c6SFan Chen power_ctrl, on, mmio_read_32(SPM_PWR_STATUS), ret); 2901a1ff8b9SJimmy Huang } 2911a1ff8b9SJimmy Huang 2921a1ff8b9SJimmy Huang mmio_clrbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN); 2931a1ff8b9SJimmy Huang spm_lock_release(); 2941a1ff8b9SJimmy Huang 2951a1ff8b9SJimmy Huang return ret; 2961a1ff8b9SJimmy Huang } 297