diff options
Diffstat (limited to 'middleware/multicore/open-amp/porting/imx7d_m4/platform.c')
-rw-r--r-- | middleware/multicore/open-amp/porting/imx7d_m4/platform.c | 273 |
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; } |