summaryrefslogtreecommitdiff
path: root/middleware/multicore/open-amp/porting/imx7d_m4/platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'middleware/multicore/open-amp/porting/imx7d_m4/platform.c')
-rw-r--r--middleware/multicore/open-amp/porting/imx7d_m4/platform.c273
1 files changed, 238 insertions, 35 deletions
diff --git a/middleware/multicore/open-amp/porting/imx7d_m4/platform.c b/middleware/multicore/open-amp/porting/imx7d_m4/platform.c
index 6b1fc8f..c682fc6 100644
--- a/middleware/multicore/open-amp/porting/imx7d_m4/platform.c
+++ b/middleware/multicore/open-amp/porting/imx7d_m4/platform.c
@@ -1,6 +1,5 @@
/*
- * Copyright (c) 2015, Freescale Corporation
- * All rights reserved.
+ * Copyright (c) 2015 Freescale Semiconductor, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -10,7 +9,7 @@
* 2. 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.
- * 3. Neither the name of Mentor Graphics Corporation nor the names of its
+ * 3. Neither the name of Freescale Semiconductor nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@@ -35,81 +34,285 @@
* DESCRIPTION
*
* This file is the Implementation of IPC hardware layer interface
- * for Freescale i.MX7 Dual platform.
+ * for Freescale i.MX 7Dual platform.
*
**************************************************************************/
-#include "device_imx.h"
+#include <assert.h>
#include "platform.h"
-#include "plat_porting.h"
#include "mu_imx.h"
+#include "common/hil/hil.h"
+#include "porting/env/env.h"
-extern void freertos_env_isr(int vector);
+static int _enable_interrupt(struct proc_vring *vring_hw)
+{
+ /* Register ISR*/
+ env_register_isr(vring_hw->intr_info.vect_id, vring_hw, platform_isr);
+
+ /* Prepare the MU Hardware, enable channel 1 interrupt */
+ MU_EnableRxFullInt(MUB, RPMSG_MU_CHANNEL);
+
+ return 0;
+}
+
+static void _notify(int cpu_id, struct proc_intr *intr_info)
+{
+ /* As Linux suggests, use MU->Data Channle 1 as communication channel */
+ uint32_t msg = (intr_info->vect_id) << 16;
+ MU_SendMsg(MUB, RPMSG_MU_CHANNEL, msg);
+}
+
+static int _boot_cpu(int cpu_id, unsigned int load_addr)
+{
+ /* not imlemented */
+ assert(0);
+ return 0;
+}
-// uint32_t channel_id;
-/*--------------------------- Globals ---------------------------------- */
+static void _shutdown_cpu(int cpu_id)
+{
+ /* not imlemented */
+ assert(0);
+}
struct hil_platform_ops proc_ops = {
- .enable_interrupt = _enable_interrupt,
+ .enable_interrupt = _enable_interrupt,
.notify = _notify,
.boot_cpu = _boot_cpu,
.shutdown_cpu = _shutdown_cpu,
};
+/**
+ * rpmsg_handler
+ *
+ * Called directly from ISR. Convert IRQ number to channel
+ * number and invoke 'env_isr'.
+ *
+ */
void rpmsg_handler(void)
{
uint32_t msg, channel;
- if (MU_TryReceiveMsg(MU0_B, MU_RPMSG_CHANNEL, &msg) == kStatus_MU_Success) {
+ if (MU_TryReceiveMsg(MUB, RPMSG_MU_CHANNEL, &msg) == kStatus_MU_Success)
+ {
channel = msg >> 16;
- freertos_env_isr(channel);
+ env_isr(channel);
}
return;
}
-int _enable_interrupt(struct proc_vring *vring_hw) { /*enable_interrupt*/
- /* Register ISR*/
- env_register_isr(vring_hw->intr_info.vect_id, vring_hw, platform_isr);
+#define PLATFORM_DISABLE_COUNTERS 2
+static int disable_counters[PLATFORM_DISABLE_COUNTERS] = {0};
+static int disable_counter_all = 0;
- /*
- * Prepare the MU Hardware, enable channel 1 interrupt
- */
- MU_EnableRxFullInt(MU0_B, MU_RPMSG_CHANNEL);
+/**
+ * platform_time_delay
+ *
+ * @param num_msec - delay time in ms.
+ *
+ * This is not an accurate delay, it ensures at least num_msec passed when return.
+ */
+void platform_time_delay(int num_msec)
+{
+ uint32_t loop;
- return 0;
+ /* Recalculate the CPU frequency */
+ SystemCoreClockUpdate();
+
+ /* Calculate the CPU loops to delay, each loop has 3 cycles */
+ loop = SystemCoreClock / 3 / 1000 * num_msec;
+
+ /* There's some difference among toolchains, 3 or 4 cycles each loop */
+ while (loop)
+ {
+ __NOP();
+ loop--;
+ }
}
-void _notify(int cpu_id, struct proc_intr *intr_info)
+/**
+ * platform_isr
+ *
+ * RPMSG platform IRQ callback
+ *
+ */
+void platform_isr(int vect_id, void *data)
{
- /*
- * As Linux suggests, use MU->Data Channle 1 as communication channel
- */
- uint32_t msg = (intr_info->vect_id) << 16;
- MU_SendMsg(MU0_B, MU_RPMSG_CHANNEL, msg);
+ hil_isr(((struct proc_vring *) data));
}
+/**
+ * platform_in_isr
+ *
+ * Return whether CPU is processing IRQ
+ *
+ * @return - true for IRQ, false otherwise.
+ *
+ */
+int platform_in_isr(void)
+{
+ return ((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0);
+}
-int _boot_cpu(int cpu_id, unsigned int load_addr)
+/**
+ * platform_interrupt_enable
+ *
+ * Enable peripheral-related interrupt with passed priority and type.
+ *
+ * @param vector_id - vector ID that need to be converted to IRQ number
+ * @param trigger_type - IRQ active level
+ * @param trigger_type - IRQ priority
+ *
+ * @return - vector_id. Return value is never checked..
+ *
+ */
+int platform_interrupt_enable(unsigned int vector_id, unsigned int trigger_type,
+ unsigned int priority)
{
- return 0;
+ assert(vector_id < PLATFORM_DISABLE_COUNTERS);
+ assert(0 < disable_counters[vector_id]);
+ disable_counters[vector_id]--;
+ // channels use the same NVIC vector
+ // enable only if all counters are zero
+ for (int i = 0; i < PLATFORM_DISABLE_COUNTERS; i++)
+ {
+ if (disable_counters[i])
+ return (vector_id);
+ }
+ NVIC_EnableIRQ(MU_M4_IRQn);
+ return (vector_id);
+}
+
+/**
+ * platform_interrupt_disable
+ *
+ * Disable peripheral-related interrupt.
+ *
+ * @param vector_id - vector ID that need to be converted to IRQ number
+ *
+ * @return - vector_id. Return value is never checked.
+ *
+ */
+int platform_interrupt_disable(unsigned int vector_id)
+{
+ assert(vector_id < PLATFORM_DISABLE_COUNTERS);
+ assert(0 <= disable_counters[vector_id]);
+ int disabled = 0;
+ // channels use the same NVIC vector
+ // if one counter is set - the interrupts are disabled
+ for (int i = 0; i < PLATFORM_DISABLE_COUNTERS; i++)
+ {
+ if (disable_counters[i])
+ {
+ disabled = 1;
+ break;
+ }
+ }
+ // if not disabled - disable interrutps
+ if (!disabled)
+ NVIC_DisableIRQ(MU_M4_IRQn);
+ disable_counters[vector_id]++;
+ return (vector_id);
}
-void _shutdown_cpu(int cpu_id)
+/**
+ * platform_interrupt_enable_all
+ *
+ * Enable all platform-related interrupts.
+ *
+ */
+void platform_interrupt_enable_all(void)
{
+ assert(0 < disable_counter_all);
+ disable_counter_all--;
+ if (0 == disable_counter_all)
+ platform_interrupt_enable(0, 0, 0);
}
-void platform_isr(int vect_id, void *data)
+/**
+ * platform_interrupt_disable_all
+ *
+ * Enable all platform-related interrupts.
+ *
+ */
+void platform_interrupt_disable_all(void)
{
- hil_isr(((struct proc_vring *) data));
+ assert(0 <= disable_counter_all);
+ if (0 == disable_counter_all)
+ platform_interrupt_disable(0);
+ disable_counter_all++;
}
-void platform_interrupt_enable()
+/**
+ * platform_map_mem_region
+ *
+ * Dummy implementation
+ *
+ */
+void platform_map_mem_region(unsigned int vrt_addr, unsigned int phy_addr,
+ unsigned int size, unsigned int flags)
{
- NVIC_EnableIRQ(MU_INT_M4_IRQn);
}
-void platform_interrupt_disable()
+/**
+ * platform_cache_all_flush_invalidate
+ *
+ * Dummy implementation
+ *
+ */
+void platform_cache_all_flush_invalidate()
{
- NVIC_DisableIRQ(MU_INT_M4_IRQn);
+}
+
+/**
+ * platform_cache_disable
+ *
+ * Dummy implementation
+ *
+ */
+void platform_cache_disable()
+{
+}
+
+/**
+ * platform_vatopa
+ *
+ * Dummy implementation
+ *
+ */
+unsigned long platform_vatopa(void *addr)
+{
+ return ((unsigned long)addr);
+}
+
+/**
+ * platform_patova
+ *
+ * Dummy implementation
+ *
+ */
+void *platform_patova(unsigned long addr)
+{
+ return ((void *)addr);
+}
+
+/**
+ * platform_init
+ *
+ * platform/environment init
+ */
+int platform_init(void)
+{
+ return 0;
+}
+
+/**
+ * platform_deinit
+ *
+ * platform/environment deinit process
+ */
+int platform_deinit(void)
+{
+ return 0;
}