text: // SPDX-License-Identifier: BSD-3-Clause
  //
  // Copyright 2020 NXP
  //
  // Author: Daniel Baluta <daniel.baluta@nxp.com>
  
  #include <sof/compiler_info.h>
  #include <sof/debug/debug.h>
  #include <sof/drivers/interrupt.h>
  #include <sof/drivers/ipc.h>
  #include <sof/drivers/mu.h>
  #include <sof/drivers/timer.h>
  #include <sof/fw-ready-metadata.h>
  #include <sof/lib/agent.h>
  #include <sof/lib/clk.h>
  #include <sof/lib/cpu.h>
  #include <sof/lib/dai.h>
  #include <sof/lib/dma.h>
  #include <sof/lib/mailbox.h>
  #include <sof/lib/memory.h>
  #include <sof/lib/mm_heap.h>
  #include <sof/platform.h>
  #include <sof/schedule/edf_schedule.h>
  #include <sof/schedule/ll_schedule.h>
  #include <sof/schedule/ll_schedule_domain.h>
  #include <sof/sof.h>
  #include <sof/trace/dma-trace.h>
  #include <ipc/dai.h>
  #include <ipc/header.h>
  #include <ipc/info.h>
  #include <kernel/abi.h>
  #include <version.h>
  #include <errno.h>
  #include <stdint.h>
  
  struct sof;
  
  static const struct sof_ipc_fw_ready ready
  	__section(".fw_ready") = {
  	.hdr = {
  		.cmd = SOF_IPC_FW_READY,
  		.size = sizeof(struct sof_ipc_fw_ready),
  	},
  	/* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */
  	.version = {
  		.hdr.size = sizeof(struct sof_ipc_fw_version),
  		.micro = SOF_MICRO,
  		.minor = SOF_MINOR,
  		.major = SOF_MAJOR,
  #ifdef DEBUG_BUILD
  		/* only added in debug for reproducability in releases */
  		.build = SOF_BUILD,
  		.date = __DATE__,
  		.time = __TIME__,
  #endif
  		.tag = SOF_TAG,
  		.abi_version = SOF_ABI_VERSION,
  	},
  	.flags = DEBUG_SET_FW_READY_FLAGS,
  };
  
  #define NUM_IMX_WINDOWS		6
  
  static const struct sof_ipc_window sram_window
  	__section(".fw_ready_metadata") = {
  	.ext_hdr	= {
  		.hdr.cmd = SOF_IPC_FW_READY,
  		.hdr.size = sizeof(struct sof_ipc_window) +
  			sizeof(struct sof_ipc_window_elem) * NUM_IMX_WINDOWS,
  		.type	= SOF_IPC_EXT_WINDOW,
  	},
  	.num_windows	= NUM_IMX_WINDOWS,
  	.window	= {
  		{
  			.type	= SOF_IPC_REGION_UPBOX,
  			.id	= 0,	/* map to host window 0 */
  			.flags	= 0, // TODO: set later
  			.size	= MAILBOX_DSPBOX_SIZE,
  			.offset	= MAILBOX_DSPBOX_OFFSET,
  		},
  		{
  			.type	= SOF_IPC_REGION_DOWNBOX,
  			.id	= 0,	/* map to host window 0 */
  			.flags	= 0, // TODO: set later
  			.size	= MAILBOX_HOSTBOX_SIZE,
  			.offset	= MAILBOX_HOSTBOX_OFFSET,
  		},
  		{
  			.type	= SOF_IPC_REGION_DEBUG,
  			.id	= 0,	/* map to host window 0 */
  			.flags	= 0, // TODO: set later
  			.size	= MAILBOX_DEBUG_SIZE,
  			.offset	= MAILBOX_DEBUG_OFFSET,
  		},
  		{
  			.type	= SOF_IPC_REGION_TRACE,
  			.id	= 0,	/* map to host window 0 */
  			.flags	= 0, // TODO: set later
  			.size	= MAILBOX_TRACE_SIZE,
  			.offset	= MAILBOX_TRACE_OFFSET,
  		},
  		{
  			.type	= SOF_IPC_REGION_STREAM,
  			.id	= 0,	/* map to host window 0 */
  			.flags	= 0, // TODO: set later
  			.size	= MAILBOX_STREAM_SIZE,
  			.offset	= MAILBOX_STREAM_OFFSET,
  		},
  		{
  			.type	= SOF_IPC_REGION_EXCEPTION,
  			.id	= 0,	/* map to host window 0 */
  			.flags	= 0, // TODO: set later
  			.size	= MAILBOX_EXCEPTION_SIZE,
  			.offset	= MAILBOX_EXCEPTION_OFFSET,
  		},
  	},
  };
  
  SHARED_DATA struct timer timer = {
  	.id = TIMER0, /* internal timer */
  	.irq = IRQ_NUM_TIMER0,
  };
  
  int platform_boot_complete(uint32_t boot_message)
  {
  	uint32_t mb_offset = 0;
  
  	mailbox_dspbox_write(mb_offset, &ready, sizeof(ready));
  	mb_offset = mb_offset + sizeof(ready);
  
  	mailbox_dspbox_write(mb_offset, &sram_window,
  			     sram_window.ext_hdr.hdr.size);
  	mb_offset = mb_offset + sram_window.ext_hdr.hdr.size;
  
  	/* variable length compiler description is a last field of cc_version */
  	mailbox_dspbox_write(mb_offset, &cc_version,
  			     cc_version.ext_hdr.hdr.size);
  	mb_offset = mb_offset + cc_version.ext_hdr.hdr.size;
  
  	mailbox_dspbox_write(mb_offset, &probe_support,
  			     probe_support.ext_hdr.hdr.size);
  	mb_offset = mb_offset + probe_support.ext_hdr.hdr.size;
  
  	mailbox_dspbox_write(mb_offset, &user_abi_version,
  			     user_abi_version.ext_hdr.hdr.size);
  
  	/* now interrupt host to tell it we are done booting */
  	imx_mu_xcr_rmw(IMX_MU_xCR_GIRn(1), 0);
  
  	/* boot now complete so we can relax the CPU */
  	/* For now skip this to gain more processing performance
  	 * for SRC component.
  	 */
  	/* clock_set_freq(CLK_CPU, CLK_DEFAULT_CPU_HZ); */
  
  	return 0;
  }
  
  int platform_init(struct sof *sof)
  {
  	int ret;
  
  	sof->platform_timer = &timer;
  	sof->cpu_timer = &timer;
  
  	platform_interrupt_init();
  	platform_clock_init(sof);
  	scheduler_init_edf();
  
  	/* init low latency domains and schedulers */
  	sof->platform_timer_domain =
  		timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK,
  				  CONFIG_SYSTICK_PERIOD);
  	scheduler_init_ll(sof->platform_timer_domain);
  
  	platform_timer_start(sof->platform_timer);
  	sa_init(sof, CONFIG_SYSTICK_PERIOD);
  
  	clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ);
  
  	/* init DMA */
  	ret = dmac_init(sof);
  	if (ret < 0)
  		return -ENODEV;
  
  	/* Init SDMA platform domain */
  	sof->platform_dma_domain =
  		dma_multi_chan_domain_init(&sof->dma_info->dma_array[1],
  					   1, PLATFORM_DEFAULT_CLOCK, true);
  	scheduler_init_ll(sof->platform_dma_domain);
  
  	/* initialize the host IPC mechanims */
  	ipc_init(sof);
  
  	ret = dai_init(sof);
  	if (ret < 0)
  		return -ENODEV;
  
  #if CONFIG_TRACE
  	/* Initialize DMA for Trace*/
  	trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE);
  	dma_trace_init_complete(sof->dmat);
  #endif
  
  	/* show heap status */
  	heap_trace_all(1);
  
  	return 0;
  }
  