| /* |
| * Copyright (c) 2016, Intel Corporation |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * * Neither the name of the Intel Corporation nor the |
| * names of its contributors may be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| * |
| * Author: Lech Betlej <lech.betlej@linux.intel.com> |
| */ |
| |
| /** |
| * \file platform/apollolake/power_down.S |
| * \brief Power gating memory banks - implementation specific for Apollolake |
| * \author Lech Betlej <lech.betlej@linux.intel.com> |
| */ |
| #include <platform/asm_memory_management.h> |
| |
| .section .text, "ax" |
| .align 64 |
| literals: |
| .literal_position |
| .global power_down |
| .type power_down, @function |
| /** |
| * Perform power down. |
| * |
| * Depending on arguments, memories are switched off. |
| * A2 - argument for LPSRAM |
| * A3 - pointer to array containing power gating mask. |
| * |
| * Finally, core enters waiti. |
| */ |
| //TODO: add IPC reply sending before core enters waiti |
| |
| #define b_enable_lpsram a2 |
| #define pu32_hpsram_mask a3 |
| #define temp_reg0 a6 |
| #define temp_reg1 a7 |
| #define temp_reg2 a8 |
| #define temp_reg3 a9 |
| #define pfl_reg a15 |
| |
| .align 64 |
| power_down: |
| entry sp, 32 |
| // effectively executes: |
| // xthal_dcache_region_lock(&literals, 128); |
| // xthal_dcache_region_lock(&power_down, 384); |
| // xthal_dcache_region_lock(&pu32_hpsram_mask, 64); |
| movi pfl_reg, literals |
| dpfl pfl_reg, 0 |
| dpfl pfl_reg, 64 |
| |
| movi pfl_reg, power_down |
| ipfl pfl_reg, 0 |
| ipfl pfl_reg, 64 |
| ipfl pfl_reg, 128 |
| ipfl pfl_reg, 192 |
| addi pfl_reg, pfl_reg, 256 |
| ipfl pfl_reg, 0 |
| ipfl pfl_reg, 64 |
| |
| mov pfl_reg, pu32_hpsram_mask |
| dpfl pfl_reg, 0 |
| |
| // if b_enable_lpsram = 0 (bool disable_lpsram) - do not disable lpsram. |
| beqz b_enable_lpsram, _PD_DISABLE_HPSRAM |
| |
| |
| _PD_DISABLE_LPSRAM: |
| m_cavs_lpsram_power_off temp_reg0, temp_reg1, temp_reg2 |
| |
| // DISABLE_HPSRAM is aligned so there can be zeros between it |
| // and last instr. |
| j _PD_DISABLE_HPSRAM |
| |
| // workaround for incidental gnu assembler bug - no alignment here |
| // (see comment before IPFL) ... |
| // .align 64 |
| _PD_DISABLE_HPSRAM: |
| // if value in memory pointed by pu32_hpsram_mask = 0 |
| // (hpsram_pwrgating_mask) - do not disable hpsram. |
| l32i temp_reg0, pu32_hpsram_mask, 0 |
| beqz temp_reg0, _PD_SLEEP |
| |
| // TODO: add full support switching off LDO incl. HW W/A |
| |
| m_cavs_hpsram_power_off temp_reg0, temp_reg1, temp_reg2 |
| |
| |
| // For BXT-P we need to deassert VNN request and select slow XTAL |
| // as clock source |
| // APL specific code _PD_SWITCH_TO_XTAL_CLOCK: and _PD_RELEASE_VNN |
| _PD_SWITCH_TO_XTAL_CLOCK: |
| // TODO: move to CLOCK hal macros |
| movi temp_reg0, (SHIM_BASE + SHIM_CLKCTL) |
| movi temp_reg1, ~(SHIM_CLKCTL_HDOCS | SHIM_CLKCTL_LDOCS) |
| movi temp_reg2, (SHIM_CLKCTL_LDCS | SHIM_CLKCTL_HDCS) |
| l32i temp_reg3, temp_reg0, 0 |
| // Reset LDOCS & HDOCS bits to select XTAL |
| and temp_reg3, temp_reg3, temp_reg1 |
| // Set LDCS & HDCS so clock selection depends on LDOCS & HDOCS |
| or temp_reg3, temp_reg3, temp_reg2 |
| s32i temp_reg3, temp_reg0, 0 |
| |
| _PD_RELEASE_VNN: |
| // TODO: move to VNN/SHIM hal macros |
| movi temp_reg0, (SHIM_BASE + SHIM_SPSREQ) |
| movi temp_reg1, ~SHIM_SPSREQ_RVNNP |
| l32i temp_reg2, temp_reg0, 0 |
| and temp_reg2, temp_reg2, temp_reg1 |
| s32i temp_reg2, temp_reg0, 0 |
| l32i temp_reg2, temp_reg0, 0 |
| // We cannot wait for VNN to drop since it can be held by something else |
| // and never drop |
| |
| //TODO: add sending IPC reply from L1$ locked code |
| |
| _PD_SLEEP: |
| // effecfively executes: |
| // xmp_spin() |
| // waiti 5 |
| movi temp_reg0, 128 |
| loop: |
| addi temp_reg0, temp_reg0, -1 |
| bnez temp_reg0, loop |
| |
| extw |
| extw |
| waiti 5 |
| j _PD_SLEEP |
| |
| .size power_down , . - power_down |
| |
| |