diff options
Diffstat (limited to 'plat/marvell/a8k/common/mss')
-rw-r--r-- | plat/marvell/a8k/common/mss/mss_bl2_setup.c | 64 | ||||
-rw-r--r-- | plat/marvell/a8k/common/mss/mss_common.mk | 52 | ||||
-rw-r--r-- | plat/marvell/a8k/common/mss/mss_ipc_drv.c | 147 | ||||
-rw-r--r-- | plat/marvell/a8k/common/mss/mss_ipc_drv.h | 168 | ||||
-rw-r--r-- | plat/marvell/a8k/common/mss/mss_mem.h | 87 | ||||
-rw-r--r-- | plat/marvell/a8k/common/mss/mss_pm_ipc.c | 147 | ||||
-rw-r--r-- | plat/marvell/a8k/common/mss/mss_pm_ipc.h | 88 | ||||
-rw-r--r-- | plat/marvell/a8k/common/mss/mss_scp_bootloader.c | 218 | ||||
-rw-r--r-- | plat/marvell/a8k/common/mss/mss_scp_bootloader.h | 40 |
9 files changed, 1011 insertions, 0 deletions
diff --git a/plat/marvell/a8k/common/mss/mss_bl2_setup.c b/plat/marvell/a8k/common/mss/mss_bl2_setup.c new file mode 100644 index 00000000..e5f4f6b8 --- /dev/null +++ b/plat/marvell/a8k/common/mss/mss_bl2_setup.c @@ -0,0 +1,64 @@ +/* + * *************************************************************************** + * Copyright (C) 2016 Marvell International Ltd. + * *************************************************************************** + * + * 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 Marvell 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 HOLDER 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. + * + *************************************************************************** + */ + +#include <bl_common.h> +#include <debug.h> +#include <plat_private.h> /* timer functionality */ +#include "mss_scp_bootloader.h" + + +/******************************************************************************* + * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. + * Return 0 on success, -1 otherwise. + ******************************************************************************/ +int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + int ret; + + INFO("BL2: Initiating SCP_BL2 transfer to SCP\n"); + printf("BL2: Initiating SCP_BL2 transfer to SCP\n"); + + /* initialize time (for delay functionality) */ + plat_delay_timer_init(); + + ret = scp_bootloader_transfer((void *)scp_bl2_image_info->image_base, + scp_bl2_image_info->image_size); + + if (ret == 0) + INFO("BL2: SCP_BL2 transferred to SCP\n"); + else + ERROR("BL2: SCP_BL2 transfer failure\n"); + + return ret; +} diff --git a/plat/marvell/a8k/common/mss/mss_common.mk b/plat/marvell/a8k/common/mss/mss_common.mk new file mode 100644 index 00000000..b806dc13 --- /dev/null +++ b/plat/marvell/a8k/common/mss/mss_common.mk @@ -0,0 +1,52 @@ +# +# *************************************************************************** +# Copyright (C) 2016 Marvell International Ltd. +# *************************************************************************** +# +# 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 Marvell 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 HOLDER 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. +# + +PLAT_MARVELL := plat/marvell +MSS_SOURCE := $(PLAT_MARVELL)/a8k/common/mss + +BL2_SOURCES += $(MSS_SOURCE)/mss_bl2_setup.c \ + $(MSS_SOURCE)/mss_scp_bootloader.c \ + $(PLAT_MARVELL)/common/plat_delay_timer.c \ + drivers/delay_timer/delay_timer.c + +BL31_SOURCES += $(MSS_SOURCE)/mss_ipc_drv.c \ + $(MSS_SOURCE)/mss_pm_ipc.c + +PLAT_INCLUDES += -I$(MSS_SOURCE) + +ifneq (${SCP_BL2},) +# Subsystems require a SCP_BL2 image +$(eval $(call FIP_ADD_IMG,SCP_BL2,--scp-fw)) + +# This define is used to inidcate the SCP image is present +$(eval $(call add_define,SCP_IMAGE)) +endif diff --git a/plat/marvell/a8k/common/mss/mss_ipc_drv.c b/plat/marvell/a8k/common/mss/mss_ipc_drv.c new file mode 100644 index 00000000..e261bb44 --- /dev/null +++ b/plat/marvell/a8k/common/mss/mss_ipc_drv.c @@ -0,0 +1,147 @@ +/* + * *************************************************************************** + * Copyright (C) 2016 Marvell International Ltd. + * *************************************************************************** + * + * 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 Marvell 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 HOLDER 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. + * + *************************************************************************** + */ + +#include <debug.h> +#include <string.h> +#include <mss_ipc_drv.h> +#include <mmio.h> + +#define IPC_MSG_BASE_MASK MVEBU_REGS_BASE_MASK + + +unsigned long mv_pm_ipc_msg_base; +unsigned int mv_pm_ipc_num_of_ch; +unsigned int mv_pm_ipc_channel_size; +unsigned int mv_pm_ipc_queue_size; + +/******************************************************************************* + * mss_pm_ipc_init + * + * DESCRIPTION: Initialize PM IPC infrastructure + ****************************************************************************** + */ +int mv_pm_ipc_init(unsigned long ipc_control_addr) +{ + struct mss_pm_ipc_ctrl *ipc_control = + (struct mss_pm_ipc_ctrl *)ipc_control_addr; + + /* Initialize PM IPC control block */ + mv_pm_ipc_msg_base = ipc_control->msg_base_address | + IPC_MSG_BASE_MASK; + mv_pm_ipc_num_of_ch = ipc_control->num_of_channels; + mv_pm_ipc_channel_size = ipc_control->channel_size; + mv_pm_ipc_queue_size = ipc_control->queue_size; + + return 0; +} + +/******************************************************************************* + * mv_pm_ipc_queue_addr_get + * + * DESCRIPTION: Returns the IPC queue address + ****************************************************************************** + */ +unsigned int mv_pm_ipc_queue_addr_get(unsigned int channel_id, + unsigned int direction) +{ + return (unsigned int)(mv_pm_ipc_msg_base + + (channel_id * mv_pm_ipc_channel_size) + + (direction * mv_pm_ipc_queue_size)); +} + +/******************************************************************************* + * mv_pm_ipc_msg_rx + * + * DESCRIPTION: Retrieve message from IPC channel + ****************************************************************************** + */ +int mv_pm_ipc_msg_rx(unsigned int channel_id, unsigned int direction, + struct mss_pm_ipc_msg *msg) +{ + unsigned int addr = mv_pm_ipc_queue_addr_get(channel_id, direction); + + msg->msg_reply = mmio_read_32(addr + IPC_MSG_REPLY_LOC); + + return 0; +} + +/******************************************************************************* + * mss_pm_ipc_msg_reply + * + * DESCRIPTION: Send message via IPC channel + ****************************************************************************** + */ +int mv_pm_ipc_msg_tx(unsigned int channel_id, unsigned int direction, + unsigned int cluster_power_state) +{ + unsigned int addr = mv_pm_ipc_queue_addr_get(channel_id, direction); + + mmio_write_32(addr + IPC_MSG_POWER_STATE_LOC, cluster_power_state); + mmio_write_32(addr + IPC_MSG_STATE_LOC, IPC_MSG_OCCUPY); + + return 0; +} + +/******************************************************************************* + * mv_pm_ipc_msg_validate + * + * DESCRIPTION: Validate IPC channel state + ****************************************************************************** + */ +int mv_pm_ipc_msg_validate(unsigned int channel_id, unsigned int direction, + unsigned int state) +{ + unsigned int addr = mv_pm_ipc_queue_addr_get(channel_id, direction); + + if (mmio_read_32(addr + IPC_MSG_STATE_LOC) != state) + return -1; + + return 0; +} + +/******************************************************************************* + * mv_pm_ipc_msg_update + * + * DESCRIPTION: Update IPC channel state + ****************************************************************************** + */ +int mv_pm_ipc_msg_update(unsigned int channel_id, unsigned int direction, + unsigned int state) +{ + unsigned int addr = mv_pm_ipc_queue_addr_get(channel_id, direction); + + mmio_write_32(addr + IPC_MSG_STATE_LOC, state); + + return 0; +} diff --git a/plat/marvell/a8k/common/mss/mss_ipc_drv.h b/plat/marvell/a8k/common/mss/mss_ipc_drv.h new file mode 100644 index 00000000..7c8995cf --- /dev/null +++ b/plat/marvell/a8k/common/mss/mss_ipc_drv.h @@ -0,0 +1,168 @@ +/* + * *************************************************************************** + * Copyright (C) 2016 Marvell International Ltd. + * *************************************************************************** + * + * 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 Marvell 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 HOLDER 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. + * + *************************************************************************** + */ + +#ifndef __PM_IPC_DRV_H +#define __PM_IPC_DRV_H + + +#include <platform_def.h> + + +#define MV_PM_FW_IPC_VERSION_MAGIC (0xCA530000) /* Do NOT change */ +/* Increament for each version */ +#define MV_PM_FW_IPC_VERSION_SEQ (0x00000001) +#define MV_PM_FW_IPC_VERSION (MV_PM_FW_IPC_VERSION_MAGIC | \ + MV_PM_FW_IPC_VERSION_SEQ) + +#define IPC_MSG_STATE_LOC (0x0) +#define IPC_MSG_SYNC_ID_LOC (0x4) +#define IPC_MSG_ID_LOC (0x8) +#define IPC_MSG_RET_CH_ID_LOC (0xC) +#define IPC_MSG_CPU_ID_LOC (0x10) +#define IPC_MSG_CLUSTER_ID_LOC (0x14) +#define IPC_MSG_SYSTEM_ID_LOC (0x18) +#define IPC_MSG_POWER_STATE_LOC (0x1C) +#define IPC_MSG_REPLY_LOC (0x20) +#define IPC_MSG_RESERVED_LOC (0x24) + +/* IPC initialization state */ +enum mss_pm_ipc_init_state { + IPC_UN_INITIALIZED = 1, + IPC_INITIALIZED = 2 +}; + +/* IPC queue direction */ +enum mss_pm_ipc_init_msg_dir { + IPC_MSG_TX = 0, + IPC_MSG_RX = 1 +}; + +/* IPC message state */ +enum mss_pm_ipc_msg_state { + IPC_MSG_FREE = 1, + IPC_MSG_OCCUPY = 2 + +}; + +/* IPC control block */ +struct mss_pm_ipc_ctrl { + unsigned int ctrl_base_address; + unsigned int msg_base_address; + unsigned int num_of_channels; + unsigned int channel_size; + unsigned int queue_size; +}; + +/* IPC message types */ +enum mss_pm_msg_id { + PM_IPC_MSG_CPU_SUSPEND = 1, + PM_IPC_MSG_CPU_OFF = 2, + PM_IPC_MSG_CPU_ON = 3, + PM_IPC_MSG_SYSTEM_RESET = 4, + PM_IPC_MSG_SYSTEM_SUSPEND = 5, + PM_IPC_MAX_MSG +}; + +struct mss_pm_ipc_msg { + unsigned int msg_sync_id; /* + * Sync number, validate message + * reply corresponding to message + * received + */ + unsigned int msg_id; /* Message Id */ + unsigned int ret_channel_id; /* IPC channel reply */ + unsigned int cpu_id; /* CPU Id */ + unsigned int cluster_id; /* Cluster Id */ + unsigned int system_id; /* System Id */ + unsigned int power_state; + unsigned int msg_reply; /* Message reply */ +}; + +/* IPC queue */ +struct mss_pm_ipc_queue { + unsigned int state; + struct mss_pm_ipc_msg msg; +}; + +/* IPC channel */ +struct mss_pm_ipc_ch { + struct mss_pm_ipc_queue *tx_queue; + struct mss_pm_ipc_queue *rx_queue; +}; + +/******************************************************************************* + * mv_pm_ipc_init + * + * DESCRIPTION: Initialize PM IPC infrastructure + ****************************************************************************** + */ +int mv_pm_ipc_init(unsigned long ipc_control_addr); + +/******************************************************************************* + * mv_pm_ipc_msg_rx + * + * DESCRIPTION: Retrieve message from IPC channel + ****************************************************************************** + */ +int mv_pm_ipc_msg_rx(unsigned int channel_id, unsigned int direction, + struct mss_pm_ipc_msg *msg); + +/******************************************************************************* + * mv_pm_ipc_msg_tx + * + * DESCRIPTION: Send message via IPC channel + ****************************************************************************** + */ +int mv_pm_ipc_msg_tx(unsigned int channel_id, unsigned int direction, + unsigned int cluster_power_state); + +/******************************************************************************* + * mv_pm_ipc_msg_validate + * + * DESCRIPTION: Validate IPC channel state + ****************************************************************************** + */ +int mv_pm_ipc_msg_validate(unsigned int channel_id, unsigned int direction, + unsigned int state); + +/******************************************************************************* + * mv_pm_ipc_msg_update + * + * DESCRIPTION: Update IPC channel state + ****************************************************************************** + */ +int mv_pm_ipc_msg_update(unsigned int channel_id, unsigned int direction, + unsigned int state); + +#endif /* __PM_IPC_DRV_H */ diff --git a/plat/marvell/a8k/common/mss/mss_mem.h b/plat/marvell/a8k/common/mss/mss_mem.h new file mode 100644 index 00000000..bed5584c --- /dev/null +++ b/plat/marvell/a8k/common/mss/mss_mem.h @@ -0,0 +1,87 @@ +/* + * *************************************************************************** + * Copyright (C) 2016 Marvell International Ltd. + * *************************************************************************** + * + * 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 Marvell 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 HOLDER 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. + * + *************************************************************************** + */ + +#ifndef __MSS_PM_MEM_H +#define __MSS_PM_MEM_H + +/* MSS SRAM Memory base */ +#define MSS_SRAM_PM_CONTROL_BASE (MVEBU_REGS_BASE + 0x520000) + +enum mss_pm_ctrl_handshake { + MSS_UN_INITIALIZED = 0, + MSS_COMPATIBILITY_ERROR = 1, + MSS_ACKNOWLEDGEMENT = 2, + HOST_ACKNOWLEDGEMENT = 3 +}; + +enum mss_pm_ctrl_rtos_env { + MSS_MULTI_PROCESS_ENV = 0, + MSS_SINGLE_PROCESS_ENV = 1, + MSS_MAX_PROCESS_ENV +}; + +struct mss_pm_ctrl_block { + /* This field is used to synchronize the Host + * and MSS initialization sequence + * Valid Values + * 0 - Un-Initialized + * 1 - Compatibility Error + * 2 - MSS Acknowledgment + * 3 - Host Acknowledgment + */ + unsigned int handshake; + + /* + * This field include Host IPC version. Once received by the MSS + * It will be compared to MSS IPC version and set MSS Acknowledge to + * "compatibility error" in case there is no match + */ + unsigned int ipc_version; + unsigned int ipc_base_address; + unsigned int ipc_state; + + /* Following fields defines firmware core architecture */ + unsigned int num_of_cores; + unsigned int num_of_clusters; + unsigned int num_of_cores_per_cluster; + + /* Following fields define pm trace debug base address */ + unsigned int pm_trace_ctrl_base_address; + unsigned int pm_trace_info_base_address; + unsigned int pm_trace_info_core_size; + + unsigned int ctrl_blk_size; +}; + +#endif /* __MSS_PM_MEM_H */ diff --git a/plat/marvell/a8k/common/mss/mss_pm_ipc.c b/plat/marvell/a8k/common/mss/mss_pm_ipc.c new file mode 100644 index 00000000..c5b01465 --- /dev/null +++ b/plat/marvell/a8k/common/mss/mss_pm_ipc.c @@ -0,0 +1,147 @@ +/* + * *************************************************************************** + * Copyright (C) 2016 Marvell International Ltd. + * *************************************************************************** + * + * 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 Marvell 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 HOLDER 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. + * + *************************************************************************** + */ + +#include <mmio.h> +#include <psci.h> +#include <debug.h> +#include <string.h> + +#include <mss_ipc_drv.h> +#include <mss_pm_ipc.h> + +/* + ** SISR is 32 bit interrupt register representing 32 interrupts + ** + ** +==================+==================+==================+=============+ + ** + Suspend msg int + Off msg int + On msg int + Reserved + + ** +==================+==================+==================+=============+ + ** + Bits 31 30 29 28 + Bits 27 26 25 24 + Bits 23 22 21 20 + Bits 19 - 0 + + ** +==================+==================+==================+=============+ + ** + Core 3 2 1 0 + Core 3 2 1 0 + Core 3 2 1 0 + + + ** +==================+==================+==================+=============+ + ** + ** Example: Bit 26 = Off Message Interrupt to core #2 + */ +#define MSS_SISR (MVEBU_REGS_BASE + 0x5800D0) + +#define MSS_CPU_SUSPEND_INT_SET_OFFSET (28) +#define MSS_CPU_OFF_INT_SET_OFFSET (24) +#define MSS_CPU_ON_INT_SET_OFFSET (20) + +/******************************************************************************* + * mss_pm_ipc_msg_send + * + * DESCRIPTION: create and transmit IPC message + ****************************************************************************** + */ +int mss_pm_ipc_msg_send(unsigned int channel_id, + const psci_power_state_t *target_state) +{ + /* Transmit IPC message */ +#ifndef DISABLE_CLUSTER_LEVEL + mv_pm_ipc_msg_tx(channel_id, IPC_MSG_TX, + (unsigned int)target_state->pwr_domain_state[MPIDR_AFFLVL1]); +#else + mv_pm_ipc_msg_tx(channel_id, IPC_MSG_TX, 0); +#endif + + return 0; +} + +/******************************************************************************* + * mss_pm_ipc_msg_recv + * + * DESCRIPTION: wait from reception of IPC message indication, + * once received, read the message from IPC channel, + * mark IPC channel as Free, and validate reply + ****************************************************************************** + */ +int mss_pm_ipc_msg_recv(unsigned int channel_id, unsigned int msg_id) +{ + struct mss_pm_ipc_msg msg; + + /* Wait for PC message indication */ + do {} while (mv_pm_ipc_msg_validate(channel_id, + IPC_MSG_RX, IPC_MSG_OCCUPY) != 0); + + /* Read the message from IPC channel */ + mv_pm_ipc_msg_rx(channel_id, IPC_MSG_RX, &msg); + + /* Mark IPC channel as Free */ + mv_pm_ipc_msg_update(channel_id, IPC_MSG_RX, IPC_MSG_FREE); + + if (msg_id != msg.msg_reply) { + ERROR("MSS Error, Invalid reply message type %d\n", + msg.msg_reply); + return -1; + } + + return 0; +} + +/******************************************************************************* + * mss_pm_ipc_on_msg_trigger + * + * DESCRIPTION: Trigger IPC ON message interrupt to MSS + ****************************************************************************** + */ +int mss_pm_ipc_on_msg_trigger(unsigned int cpu_id) +{ + mmio_write_32(MSS_SISR, 1 << (MSS_CPU_ON_INT_SET_OFFSET + cpu_id)); + return 0; +} + +/******************************************************************************* + * mss_pm_ipc_msg_trigger + * + * DESCRIPTION: Trigger IPC OFF message interrupt to MSS + ****************************************************************************** + */ +int mss_pm_ipc_suspend_msg_trigger(unsigned int cpu_id) +{ + mmio_write_32(MSS_SISR, 1 << (MSS_CPU_SUSPEND_INT_SET_OFFSET + cpu_id)); + return 0; +} + +/******************************************************************************* + * mss_pm_ipc_msg_trigger + * + * DESCRIPTION: Trigger IPC SUSPEND message interrupt to MSS + ****************************************************************************** + */ +int mss_pm_ipc_off_msg_trigger(unsigned int cpu_id) +{ + mmio_write_32(MSS_SISR, 1 << (MSS_CPU_OFF_INT_SET_OFFSET + cpu_id)); + return 0; +} diff --git a/plat/marvell/a8k/common/mss/mss_pm_ipc.h b/plat/marvell/a8k/common/mss/mss_pm_ipc.h new file mode 100644 index 00000000..16044c06 --- /dev/null +++ b/plat/marvell/a8k/common/mss/mss_pm_ipc.h @@ -0,0 +1,88 @@ +/* + * *************************************************************************** + * Copyright (C) 2016 Marvell International Ltd. + * *************************************************************************** + * + * 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 Marvell 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 HOLDER 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. + * + *************************************************************************** + */ + +#ifndef __MSS_PM_IPC_H +#define __MSS_PM_IPC_H + + +#include <mss_ipc_drv.h> +/* Currently MSS does not support Cluster level Power Down */ +#define DISABLE_CLUSTER_LEVEL + + +/******************************************************************************* + * mss_pm_ipc_msg_send + * + * DESCRIPTION: create and transmit IPC message + ****************************************************************************** + */ +int mss_pm_ipc_msg_send(unsigned int channel_id, + const psci_power_state_t *target_state); + +/******************************************************************************* + * mss_pm_ipc_msg_recv + * + * DESCRIPTION: wait from reception of IPC message indication, + * once received, read the message from IPC channel, + * mark IPC channel as Free, and validate reply + ****************************************************************************** + */ +int mss_pm_ipc_msg_recv(unsigned int channel_id, unsigned int msg_id); + +/******************************************************************************* + * mss_pm_ipc_on_msg_trigger + * + * DESCRIPTION: Trigger IPC ON message interrupt to MSS + ****************************************************************************** + */ +int mss_pm_ipc_on_msg_trigger(unsigned int cpu_id); + +/******************************************************************************* + * mss_pm_ipc_on_msg_trigger + * + * DESCRIPTION: Trigger IPC OFF message interrupt to MSS + ****************************************************************************** + */ +int mss_pm_ipc_off_msg_trigger(unsigned int cpu_id); + +/******************************************************************************* + * mss_pm_ipc_on_msg_trigger + * + * DESCRIPTION: Trigger IPC SUSPEND message interrupt to MSS + ****************************************************************************** + */ +int mss_pm_ipc_suspend_msg_trigger(unsigned int cpu_id); + + +#endif /* __MSS_PM_IPC_H */ diff --git a/plat/marvell/a8k/common/mss/mss_scp_bootloader.c b/plat/marvell/a8k/common/mss/mss_scp_bootloader.c new file mode 100644 index 00000000..2fc93120 --- /dev/null +++ b/plat/marvell/a8k/common/mss/mss_scp_bootloader.c @@ -0,0 +1,218 @@ +/* + * *************************************************************************** + * Copyright (C) 2016 Marvell International Ltd. + * *************************************************************************** + * + * 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 Marvell 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 HOLDER 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. + * + *************************************************************************** + */ + +#include <assert.h> +#include <debug.h> +#include <mmio.h> +#include <arch_helpers.h> /* for cache maintanance operations */ +#include <platform_def.h> +#include <delay_timer.h> +#include <apn806_setup.h> + +#include <plat_pm_trace.h> +#include <mss_scp_bootloader.h> +#include <mss_ipc_drv.h> +#include <mss_mem.h> + + +#define MSS_DMA_SRCBR(base) (base + 0xC0) +#define MSS_DMA_DSTBR(base) (base + 0xC4) +#define MSS_DMA_CTRLR(base) (base + 0xC8) +#define MSS_M3_RSTCR(base) (base + 0xFC) +#define MSS_AEBR(base) (base + 0x160) +#define MSS_AIBR(base) (base + 0x164) + +#define MSS_DMA_CTRLR_SIZE_OFFSET (0) +#define MSS_DMA_CTRLR_REQ_OFFSET (15) +#define MSS_DMA_CTRLR_REQ_SET (1) +#define MSS_DMA_CTRLR_ACK_OFFSET (12) +#define MSS_DMA_CTRLR_ACK_MASK (0x1) +#define MSS_DMA_CTRLR_ACK_READY (1) +#define MSS_M3_RSTCR_RST_OFFSET (0) +#define MSS_M3_RSTCR_RST_OFF (1) +#define MSS_AEBR_MASK 0xFFF +#define MSS_AIBR_MASK 0xFFF + +#define MSS_DMA_TIMEOUT 1000 +#define MSS_EXTERNAL_SPACE 0x50000000 +#define MSS_EXTERNAL_ACCESS_BIT 28 +#define MSS_EXTERNAL_ADDR_MASK 0xfffffff +#define MSS_INTERNAL_ACCESS_BIT 28 + +#define DMA_SIZE 128 + +#define MSS_HANDSHAKE_TIMEOUT 50 +/* TODO: Fix this */ +#define AP_MSS_REG_BASE (MVEBU_REGS_BASE + 0x580000) + + +static int mss_check_image_ready(struct mss_pm_ctrl_block *mss_pm_crtl) +{ + int timeout = MSS_HANDSHAKE_TIMEOUT; + + /* Wait for SCP to signal it's ready */ + while ((mss_pm_crtl->handshake != MSS_ACKNOWLEDGEMENT) && + (timeout-- > 0)) + mdelay(1); + + /* + * Check that the handshake was completed successfully + * Note: since A0 doesn't support MSS load, this check is skipped + */ + if ((mss_pm_crtl->handshake != MSS_ACKNOWLEDGEMENT) && + (apn806_rev_id_get() != APN806_REV_ID_A0)) + return -1; + + mss_pm_crtl->handshake = HOST_ACKNOWLEDGEMENT; + + return 0; +} + + +static int mss_image_load(uint32_t src_addr, uint32_t size, uintptr_t mss_regs) +{ + uint32_t i, loop_num, timeout; + + NOTICE("Loading MSS image from address 0x%x Size 0x%x to MSS at 0x%x\n", + src_addr, size, (uint32_t)mss_regs); + /* load image to MSS RAM using DMA */ + loop_num = (size / DMA_SIZE) + (((size & (DMA_SIZE - 1)) == 0) ? 0 : 1); + + /* set AXI External and Internal Address Bus extension */ + mmio_write_32(MSS_AEBR(mss_regs), ((src_addr >> MSS_EXTERNAL_ACCESS_BIT) + & MSS_AEBR_MASK)); + mmio_write_32(MSS_AIBR(mss_regs), ((mss_regs >> MSS_INTERNAL_ACCESS_BIT) + & MSS_AIBR_MASK)); + + for (i = 0; i < loop_num; i++) { + /* write destination and source addresses */ + mmio_write_32(MSS_DMA_SRCBR(mss_regs), + MSS_EXTERNAL_SPACE | + ((src_addr & MSS_EXTERNAL_ADDR_MASK) + + (i * DMA_SIZE))); + mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE)); + + dsb(); /* make sure DMA data is ready before triggering it */ + + /* set the DMA control register */ + mmio_write_32(MSS_DMA_CTRLR(mss_regs), ((MSS_DMA_CTRLR_REQ_SET + << MSS_DMA_CTRLR_REQ_OFFSET) | + (DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET))); + + /* Poll DMA_ACK at MSS_DMACTLR until it is ready */ + timeout = MSS_DMA_TIMEOUT; + while (timeout) { + if ((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >> + MSS_DMA_CTRLR_ACK_OFFSET & MSS_DMA_CTRLR_ACK_MASK) + == MSS_DMA_CTRLR_ACK_READY) { + break; + } + + udelay(50); + timeout--; + } + + if (timeout == 0) { + ERROR("\nDMA failed to load MSS image\n"); + return 1; + } + } + + /* Release M3 from reset */ + mmio_write_32(MSS_M3_RSTCR(mss_regs), (MSS_M3_RSTCR_RST_OFF << + MSS_M3_RSTCR_RST_OFFSET)); + + NOTICE("Done\n"); + + return 0; +} + +int scp_bootloader_transfer(void *image, unsigned int image_size) +{ + int ret; + struct mss_pm_ctrl_block *mss_pm_crtl; + + assert((uintptr_t) image == SCP_BL2_BASE); + + if ((image_size == 0) || (image_size % 4 != 0)) { + ERROR("SCP_BL2 image size must be a multiple of 4 bytes\n"); + ERROR("and not zero (current size = 0x%x)\n", image_size); + return -1; + } + + /* TODO: add PM Control Info from platform */ + mss_pm_crtl = (struct mss_pm_ctrl_block *)MSS_SRAM_PM_CONTROL_BASE; + mss_pm_crtl->ipc_version = MV_PM_FW_IPC_VERSION; + mss_pm_crtl->num_of_clusters = PLAT_MARVELL_CLUSTER_COUNT; + mss_pm_crtl->num_of_cores_per_cluster = + PLAT_MARVELL_CLUSTER_CORE_COUNT; + mss_pm_crtl->num_of_cores = PLAT_MARVELL_CLUSTER_COUNT * + PLAT_MARVELL_CLUSTER_CORE_COUNT; + mss_pm_crtl->pm_trace_ctrl_base_address = AP_MSS_ATF_CORE_CTRL_BASE; + mss_pm_crtl->pm_trace_info_base_address = AP_MSS_ATF_CORE_INFO_BASE; + mss_pm_crtl->pm_trace_info_core_size = AP_MSS_ATF_CORE_INFO_SIZE; + VERBOSE("MSS Control Block = 0x%x\n", MSS_SRAM_PM_CONTROL_BASE); + VERBOSE("mss_pm_crtl->ipc_version = 0x%x\n", + mss_pm_crtl->ipc_version); + VERBOSE("mss_pm_crtl->num_of_cores = 0x%x\n", + mss_pm_crtl->num_of_cores); + VERBOSE("mss_pm_crtl->num_of_clusters = 0x%x\n", + mss_pm_crtl->num_of_clusters); + VERBOSE("mss_pm_crtl->num_of_cores_per_cluster = 0x%x\n", + mss_pm_crtl->num_of_cores_per_cluster); + VERBOSE("mss_pm_crtl->pm_trace_ctrl_base_address = 0x%x\n", + mss_pm_crtl->pm_trace_ctrl_base_address); + VERBOSE("mss_pm_crtl->pm_trace_info_base_address = 0x%x\n", + mss_pm_crtl->pm_trace_info_base_address); + VERBOSE("mss_pm_crtl->pm_trace_info_core_size = 0x%x\n", + mss_pm_crtl->pm_trace_info_core_size); + + /* TODO: add checksum to image */ + VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n"); + NOTICE("Load image to AP MSS\n"); + ret = mss_image_load((uintptr_t)image, image_size, AP_MSS_REG_BASE); + if (ret != 0) { + ERROR("SCP Image load failed\n"); + return -1; + } + + /* check that the image was loaded successfully */ + ret = mss_check_image_ready(mss_pm_crtl); + if (ret != 0) { + ERROR("SCP Image check failed\n"); + return -1; + } + + return 0; +} diff --git a/plat/marvell/a8k/common/mss/mss_scp_bootloader.h b/plat/marvell/a8k/common/mss/mss_scp_bootloader.h new file mode 100644 index 00000000..fe97e7a5 --- /dev/null +++ b/plat/marvell/a8k/common/mss/mss_scp_bootloader.h @@ -0,0 +1,40 @@ +/* + * *************************************************************************** + * Copyright (C) 2016 Marvell International Ltd. + * *************************************************************************** + * + * 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 Marvell 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 HOLDER 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. + * + *************************************************************************** + */ + +#ifndef __MSS_SCP_BOOTLOADER_H__ +#define __MSS_SCP_BOOTLOADER_H__ + +int scp_bootloader_transfer(void *image, unsigned int image_size); + +#endif /* __MSS_SCP_BOOTLOADER_H__ */ |