diff options
-rw-r--r-- | arch/arm/mach-imx/mcc_imx6sx.c | 23 | ||||
-rw-r--r-- | arch/arm/mach-imx/mcc_linux.c | 140 | ||||
-rw-r--r-- | include/linux/mcc_config_linux.h | 56 | ||||
-rw-r--r-- | include/linux/mcc_imx6sx.h | 2 | ||||
-rw-r--r-- | include/linux/mcc_linux.h | 22 |
5 files changed, 226 insertions, 17 deletions
diff --git a/arch/arm/mach-imx/mcc_imx6sx.c b/arch/arm/mach-imx/mcc_imx6sx.c index 43e9a837bb78..d750b3d1e04b 100644 --- a/arch/arm/mach-imx/mcc_imx6sx.c +++ b/arch/arm/mach-imx/mcc_imx6sx.c @@ -1,7 +1,6 @@ /* * Copyright (C) 2014 Freescale Semiconductor, Inc. * Freescale IMX Linux-specific MCC implementation. - * iMX6sx-specific MCC library functions. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -20,9 +19,13 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/regmap.h> +#include <linux/mcc_config_linux.h> +#include <linux/mcc_common.h> #include <linux/mcc_imx6sx.h> #include <linux/mcc_linux.h> +#include "mcc_config.h" + /*! * \brief This function returns the core number * @@ -30,7 +33,25 @@ */ unsigned int _psp_core_num(void) { +#if (MCC_OS_USED == MCC_MQX) + return 1; +#elif (MCC_OS_USED == MCC_LINUX) return 0; +#endif +} + +/*! + * \brief This function returns the node number + * + * \return unsigned int + */ +unsigned int _psp_node_num(void) +{ +#if (MCC_OS_USED == MCC_MQX) + return MCC_MQX_NODE_NUMBER ; +#elif (MCC_OS_USED == MCC_LINUX) + return MCC_LINUX_NODE_NUMBER; +#endif } /* diff --git a/arch/arm/mach-imx/mcc_linux.c b/arch/arm/mach-imx/mcc_linux.c index 554df365aff2..94526c6d04ff 100644 --- a/arch/arm/mach-imx/mcc_linux.c +++ b/arch/arm/mach-imx/mcc_linux.c @@ -1,7 +1,6 @@ /* * Copyright (C) 2014 Freescale Semiconductor, Inc. * Freescale IMX Linux-specific MCC implementation. - * Linux-specific MCC library functions * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -19,12 +18,14 @@ #include <linux/busfreq-imx6.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/io.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <linux/sched.h> #include <linux/wait.h> #include <linux/imx_sema4.h> #include "mcc_config.h" +#include <linux/mcc_config_linux.h> #include <linux/mcc_common.h> #include <linux/mcc_api.h> #include <linux/mcc_imx6sx.h> @@ -44,6 +45,8 @@ unsigned int imx_mcc_buffer_freed = 0, imx_mcc_buffer_queued = 0; DECLARE_WAIT_QUEUE_HEAD(buffer_freed_wait_queue); /* Used for blocking send */ DECLARE_WAIT_QUEUE_HEAD(buffer_queued_wait_queue); /* Used for blocking recv */ +MCC_BOOKEEPING_STRUCT *bookeeping_data; + /*! * \brief This function is the CPU-to-CPU interrupt handler. * @@ -305,12 +308,7 @@ void mcc_memcpy(void *src, void *dest, unsigned int size) memcpy(dest, src, size); } -void _mem_zero(void *ptr, unsigned int size) -{ - memset(ptr, 0, size); -} - -void *virt_to_mqx(void *x) +void *mcc_virt_to_phys(void *x) { if (null == x) return NULL; @@ -318,10 +316,136 @@ void *virt_to_mqx(void *x) return (void *)((unsigned long) (x) - mcc_shm_offset); } -void *mqx_to_virt(void *x) +void *mcc_phys_to_virt(void *x) { if (null == x) return NULL; else return (void *)((unsigned long) (x) + mcc_shm_offset); } + +int mcc_init_os_sync(void) +{ + /* No used in linux */ + return MCC_SUCCESS; +} + +int mcc_deinit_os_sync(void) +{ + /* No used in linux */ + return MCC_SUCCESS; +} + +void mcc_clear_os_sync_for_ep(MCC_ENDPOINT *endpoint) +{ + /* No used in linux */ +} + +int mcc_wait_for_buffer_freed(MCC_RECEIVE_BUFFER **buffer, unsigned int timeout) +{ + int return_value; + unsigned long timeout_j; /* jiffies */ + MCC_RECEIVE_BUFFER *buf = null; + + /* + * Blocking calls: CPU-to-CPU ISR sets the event and thus + * resumes tasks waiting for a free MCC buffer. + * As the interrupt request is send to all cores when a buffer + * is freed it could happen that several tasks from different + * cores/nodes are waiting for a free buffer and all of them + * are notified that the buffer has been freed. This function + * has to check (after the wake up) that a buffer is really + * available and has not been already grabbed by another + * "competitor task" that has been faster. If so, it has to + * wait again for the next notification. + */ + while (buf == null) { + if (timeout == 0xffffffff) { + /* + * In order to level up the robust, do not always + * wait event here. Wake up itself after every 1~s. + */ + timeout_j = usecs_to_jiffies(1000); + wait_event_timeout(buffer_freed_wait_queue, + imx_mcc_buffer_freed == 1, timeout_j); + } else { + timeout_j = msecs_to_jiffies(timeout); + wait_event_timeout(buffer_freed_wait_queue, + imx_mcc_buffer_freed == 1, timeout_j); + } + + return_value = mcc_get_semaphore(); + if (return_value != MCC_SUCCESS) + return return_value; + + MCC_DCACHE_INVALIDATE_MLINES((void *) + &bookeeping_data->free_list, + sizeof(MCC_RECEIVE_LIST *)); + + buf = mcc_dequeue_buffer(&bookeeping_data->free_list); + mcc_release_semaphore(); + if (imx_mcc_buffer_freed) + imx_mcc_buffer_freed = 0; + } + + *buffer = buf; + return MCC_SUCCESS; +} + +int mcc_wait_for_buffer_queued(MCC_ENDPOINT *endpoint, unsigned int timeout) +{ + unsigned long timeout_j; /* jiffies */ + MCC_RECEIVE_LIST *tmp_list; + + /* Get list of buffers kept by the particular endpoint */ + tmp_list = mcc_get_endpoint_list(*endpoint); + + if (timeout == 0xffffffff) { + wait_event(buffer_queued_wait_queue, + imx_mcc_buffer_queued == 1); + mcc_get_semaphore(); + /* + * double check if the tmp_list head is still null + * or not, if yes, wait again. + */ + while (tmp_list->head == null) { + imx_mcc_buffer_queued = 0; + mcc_release_semaphore(); + wait_event(buffer_queued_wait_queue, + imx_mcc_buffer_queued == 1); + mcc_get_semaphore(); + } + } else { + timeout_j = msecs_to_jiffies(timeout); + wait_event_timeout(buffer_queued_wait_queue, + imx_mcc_buffer_queued == 1, timeout_j); + mcc_get_semaphore(); + } + + if (imx_mcc_buffer_queued) + imx_mcc_buffer_queued = 0; + + if (tmp_list->head == null) { + pr_err("%s can't get queued buffer.\n", __func__); + mcc_release_semaphore(); + return MCC_ERR_TIMEOUT; + } + + tmp_list->head = (MCC_RECEIVE_BUFFER *) + MCC_MEM_PHYS_TO_VIRT(tmp_list->head); + mcc_release_semaphore(); + + return MCC_SUCCESS; +} + +MCC_BOOKEEPING_STRUCT *mcc_get_bookeeping_data(void) +{ + MCC_BOOKEEPING_STRUCT *bookeeping_data; + + bookeeping_data = (MCC_BOOKEEPING_STRUCT *)ioremap_nocache + (MCC_BASE_ADDRESS, sizeof(struct mcc_bookeeping_struct)); + mcc_shm_offset = (unsigned long)bookeeping_data + - (unsigned long)MCC_BASE_ADDRESS; + + return bookeeping_data; +} diff --git a/include/linux/mcc_config_linux.h b/include/linux/mcc_config_linux.h new file mode 100644 index 000000000000..49339904fd3d --- /dev/null +++ b/include/linux/mcc_config_linux.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * Freescale IMX Linux-specific MCC implementation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __MCC_LINUX_CONFIG_ +#define __MCC_CLINUX_CONFIG_ + +/* base address of shared memory */ +#define MCC_BASE_ADDRESS (0xBFF00000) + +/* size (in bytes) and number of receive buffers */ +#define MCC_ATTR_NUM_RECEIVE_BUFFERS (10) +#define MCC_ATTR_BUFFER_SIZE_IN_BYTES (1024) + +/* maximum number of receive endpoints (application specific setting), + * do not assign it to a value greater than 255 ! */ +#define MCC_ATTR_MAX_RECEIVE_ENDPOINTS (5) + +/* size of the signal queue */ +#define MCC_MAX_OUTSTANDING_SIGNALS (10) + +/* number of cores */ +#define MCC_NUM_CORES (2) + +/* core number */ +#define MCC_CORE_NUMBER (_psp_core_num()) + +/* node number */ +#define MCC_NODE_NUMBER (_psp_node_num()) + +/* semaphore number */ +#define MCC_SHMEM_SEMAPHORE_NUMBER (1) +#define MCC_PRINTF_SEMAPHORE_NUMBER (2) +#define MCC_I2C_SEMAPHORE_NUMBER (3) +#define MCC_RESERVED1_SEMAPHORE_NUMBER (4) +#define MCC_RESERVED2_SEMAPHORE_NUMBER (5) +#define MCC_POWER_SHMEM_NUMBER (6) + +/* data non-copy mechanisms enabled */ +#define MCC_SEND_RECV_NOCOPY_API_ENABLED (1) + +#endif /* __MCC_LINUX_CONFIG_*/ + diff --git a/include/linux/mcc_imx6sx.h b/include/linux/mcc_imx6sx.h index 427cae50cd34..931d670d7484 100644 --- a/include/linux/mcc_imx6sx.h +++ b/include/linux/mcc_imx6sx.h @@ -1,7 +1,6 @@ /* * Copyright (C) 2014 Freescale Semiconductor, Inc. * Freescale IMX Linux-specific MCC implementation. - * Prototypes for iMX6sx-specific MCC library functions. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -49,6 +48,7 @@ extern struct regmap *imx_mu_reg; /* Return core num. A9 0, M4 1 */ unsigned int _psp_core_num(void); +unsigned int _psp_node_num(void); unsigned int mcc_get_cpu_to_cpu_vector(unsigned int); void mcc_clear_cpu_to_cpu_interrupt(unsigned int); diff --git a/include/linux/mcc_linux.h b/include/linux/mcc_linux.h index f8591de63e74..a2806c7ffcec 100644 --- a/include/linux/mcc_linux.h +++ b/include/linux/mcc_linux.h @@ -1,7 +1,6 @@ /* * Copyright (C) 2014 Freescale Semiconductor, Inc. * Freescale IMX Linux-specific MCC implementation. - * Prototypes for Linunx-specific MCC library functions * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -19,6 +18,9 @@ #ifndef __MCC_LINUX__ #define __MCC_LINUX__ +#include <linux/sched.h> +#include <linux/string.h> + /* Define the kinds of cache macros */ #define MCC_DCACHE_ENABLE(n) #define MCC_DCACHE_DISABLE() @@ -29,12 +31,12 @@ #define MCC_DCACHE_INVALIDATE_LINE(p) #define MCC_DCACHE_INVALIDATE_MLINES(p, m) -#define _mem_size unsigned int +#define MCC_LINUX_NODE_NUMBER (0) -void * virt_to_mqx(void *); -void * mqx_to_virt(void *); -#define VIRT_TO_MQX(x) virt_to_mqx(x) -#define MQX_TO_VIRT(x) mqx_to_virt(x) +void * mcc_virt_to_phys(void *); +void * mcc_phys_to_virt(void *); +#define MCC_MEM_VIRT_TO_PHYS(x) mcc_virt_to_phys(x) +#define MCC_MEM_PHYS_TO_VIRT(x) mcc_phys_to_virt(x) /* Semaphore-related functions */ int mcc_init_semaphore(unsigned int); @@ -48,6 +50,12 @@ int mcc_generate_cpu_to_cpu_interrupt(void); /* Memory management-related functions */ void mcc_memcpy(void *, void *, unsigned int); -void _mem_zero(void *, unsigned int); +int mcc_init_os_sync(void); +int mcc_deinit_os_sync(void); +void mcc_clear_os_sync_for_ep(MCC_ENDPOINT *); +int mcc_wait_for_buffer_freed(MCC_RECEIVE_BUFFER **, unsigned int); +int mcc_wait_for_buffer_queued(MCC_ENDPOINT *, unsigned int); + +MCC_BOOKEEPING_STRUCT *mcc_get_bookeeping_data(void); #endif /* __MCC_LINUX__ */ |