<commit_before>/*
 * Copyright (C) 2018 Marvell International Ltd.
 *
 * SPDX-License-Identifier:     BSD-3-Clause
 * https://spdx.org/licenses
 */

#include <assert.h>

#include <platform_def.h>

#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <mg_conf_cm3/mg_conf_cm3.h>
#include <lib/mmio.h>

#include <plat_pm_trace.h>
#include <mss_scp_bootloader.h>
#include <mss_ipc_drv.h>
#include <mss_mem.h>
#include <mss_scp_bl2_format.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_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_DMA_TIMEOUT			1000
#define MSS_EXTERNAL_SPACE		0x50000000
#define MSS_EXTERNAL_ADDR_MASK		0xfffffff
#define MSS_INTERNAL_SPACE		0x40000000
#define MSS_INTERNAL_ADDR_MASK		0x00ffffff

#define DMA_SIZE			128

#define MSS_HANDSHAKE_TIMEOUT		50

static int mss_check_image_ready(volatile 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_ACKNOWLEDGMENT) &&
						(timeout-- > 0))
		mdelay(1);

	if (mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT)
		return -1;

	mss_pm_crtl->handshake = HOST_ACKNOWLEDGMENT;

	return 0;
}

static int mss_iram_dma_load(uint32_t src_addr, uint32_t size,
			     uintptr_t mss_regs)
{
	uint32_t i, loop_num, timeout;

	/* load image to MSS RAM using DMA */
	loop_num = (size / DMA_SIZE) + !!(size % DMA_SIZE);
	for (i = 0; i < loop_num; i++) {
		/* write source address */
		mmio_write_32(MSS_DMA_SRCBR(mss_regs),
			      src_addr + (i * DMA_SIZE));
		/* write destination address */
		mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE));
		/* make sure DMA data is ready before triggering it */
		dsb();
		/* 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 > 0U) {
			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("\nMSS DMA failed (timeout)\n");
			return 1;
		}
	}
	return 0;
}

static int mss_image_load(uint32_t src_addr, uint32_t size,
			  uintptr_t mss_regs, uintptr_t sram)
{
	uint32_t chunks = 1; /* !sram case */
	uint32_t chunk_num;
	int ret;

	/* Check if the img size is not bigger than ID-RAM size of MSS CM3 */
	if (size > MSS_IDRAM_SIZE) {
		ERROR("image is too big to fit into MSS CM3 memory\n");
		return 1;
	}

	/* The CPx MSS DMA cannot access DRAM directly in secure boot mode
	 * Copy the MSS FW image to MSS SRAM by the CPU first, then run
	 * MSS DMA for SRAM to IRAM copy
	 */
	if (sram != 0) {
		chunks = size / MSS_SRAM_SIZE + !!(size % MSS_SRAM_SIZE);
	}

	NOTICE("%s Loading MSS FW from addr. 0x%x Size 0x%x to MSS at 0x%lx\n",
	       sram == 0 ? "" : "SECURELY", src_addr, size, mss_regs);
	for (chunk_num = 0; chunk_num < chunks; chunk_num++) {
		size_t chunk_size = size;
		uint32_t img_src = MSS_EXTERNAL_SPACE | /* no SRAM */
				   (src_addr & MSS_EXTERNAL_ADDR_MASK);

		if (sram != 0) {
			uintptr_t chunk_source =
				  src_addr + MSS_SRAM_SIZE * chunk_num;

			if (chunk_num != (size / MSS_SRAM_SIZE)) {
				chunk_size = MSS_SRAM_SIZE;
			} else {
				chunk_size =  size % MSS_SRAM_SIZE;
			}

			if (chunk_size == 0) {
				break;
			}

			VERBOSE("Chunk %d -> SRAM 0x%lx from 0x%lx SZ 0x%lx\n",
				chunk_num, sram, chunk_source, chunk_size);
			memcpy((void *)sram, (void *)chunk_source, chunk_size);
			dsb();
			img_src = MSS_INTERNAL_SPACE |
				  (sram & MSS_INTERNAL_ADDR_MASK);
		}

		ret = mss_iram_dma_load(img_src, chunk_size, mss_regs);
		if (ret != 0) {
			ERROR("MSS FW chunk %d load failed\n", chunk_num);
			return ret;
		}
	}

	bl2_plat_configure_mss_windows(mss_regs);

	/* 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");<commit_msg>plat/marvell/armada: cleanup MSS SRAM if used for copy<commit_after>/*
 * Copyright (C) 2018 Marvell International Ltd.
 *
 * SPDX-License-Identifier:     BSD-3-Clause
 * https://spdx.org/licenses
 */

#include <assert.h>

#include <platform_def.h>

#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <mg_conf_cm3/mg_conf_cm3.h>
#include <lib/mmio.h>

#include <plat_pm_trace.h>
#include <mss_scp_bootloader.h>
#include <mss_ipc_drv.h>
#include <mss_mem.h>
#include <mss_scp_bl2_format.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_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_DMA_TIMEOUT			1000
#define MSS_EXTERNAL_SPACE		0x50000000
#define MSS_EXTERNAL_ADDR_MASK		0xfffffff
#define MSS_INTERNAL_SPACE		0x40000000
#define MSS_INTERNAL_ADDR_MASK		0x00ffffff

#define DMA_SIZE			128

#define MSS_HANDSHAKE_TIMEOUT		50

static int mss_check_image_ready(volatile 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_ACKNOWLEDGMENT) &&
						(timeout-- > 0))
		mdelay(1);

	if (mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT)
		return -1;

	mss_pm_crtl->handshake = HOST_ACKNOWLEDGMENT;

	return 0;
}

static int mss_iram_dma_load(uint32_t src_addr, uint32_t size,
			     uintptr_t mss_regs)
{
	uint32_t i, loop_num, timeout;

	/* load image to MSS RAM using DMA */
	loop_num = (size / DMA_SIZE) + !!(size % DMA_SIZE);
	for (i = 0; i < loop_num; i++) {
		/* write source address */
		mmio_write_32(MSS_DMA_SRCBR(mss_regs),
			      src_addr + (i * DMA_SIZE));
		/* write destination address */
		mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE));
		/* make sure DMA data is ready before triggering it */
		dsb();
		/* 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 > 0U) {
			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("\nMSS DMA failed (timeout)\n");
			return 1;
		}
	}
	return 0;
}

static int mss_image_load(uint32_t src_addr, uint32_t size,
			  uintptr_t mss_regs, uintptr_t sram)
{
	uint32_t chunks = 1; /* !sram case */
	uint32_t chunk_num;
	int ret;

	/* Check if the img size is not bigger than ID-RAM size of MSS CM3 */
	if (size > MSS_IDRAM_SIZE) {
		ERROR("image is too big to fit into MSS CM3 memory\n");
		return 1;
	}

	/* The CPx MSS DMA cannot access DRAM directly in secure boot mode
	 * Copy the MSS FW image to MSS SRAM by the CPU first, then run
	 * MSS DMA for SRAM to IRAM copy
	 */
	if (sram != 0) {
		chunks = size / MSS_SRAM_SIZE + !!(size % MSS_SRAM_SIZE);
	}

	NOTICE("%s Loading MSS FW from addr. 0x%x Size 0x%x to MSS at 0x%lx\n",
	       sram == 0 ? "" : "SECURELY", src_addr, size, mss_regs);
	for (chunk_num = 0; chunk_num < chunks; chunk_num++) {
		size_t chunk_size = size;
		uint32_t img_src = MSS_EXTERNAL_SPACE | /* no SRAM */
				   (src_addr & MSS_EXTERNAL_ADDR_MASK);

		if (sram != 0) {
			uintptr_t chunk_source =
				  src_addr + MSS_SRAM_SIZE * chunk_num;

			if (chunk_num != (size / MSS_SRAM_SIZE)) {
				chunk_size = MSS_SRAM_SIZE;
			} else {
				chunk_size =  size % MSS_SRAM_SIZE;
			}

			if (chunk_size == 0) {
				break;
			}

			VERBOSE("Chunk %d -> SRAM 0x%lx from 0x%lx SZ 0x%lx\n",
				chunk_num, sram, chunk_source, chunk_size);
			memcpy((void *)sram, (void *)chunk_source, chunk_size);
			dsb();
			img_src = MSS_INTERNAL_SPACE |
				  (sram & MSS_INTERNAL_ADDR_MASK);
		}

		ret = mss_iram_dma_load(img_src, chunk_size, mss_regs);
		if (ret != 0) {
			ERROR("MSS FW chunk %d load failed\n", chunk_num);
			return ret;
		}
	}

	bl2_plat_configure_mss_windows(mss_regs);

	/* Wipe the MSS SRAM after using it as copy buffer */
	if (sram) {
		memset((void *)sram, 0, MSS_SRAM_SIZE);
	}

	/* 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");
{'fraction_non_alphanumeric': 0.11679547186241428, 'fraction_numerical': 0.0257973223032546, 'mean_word_length': 3.845991561181435, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 45, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 6, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4549757', 'n_tokens_mistral': 4371, 'n_tokens_neox': 3840, 'n_words': 852}