summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-imx/mcc_imx6sx.c23
-rw-r--r--arch/arm/mach-imx/mcc_linux.c140
-rw-r--r--include/linux/mcc_config_linux.h56
-rw-r--r--include/linux/mcc_imx6sx.h2
-rw-r--r--include/linux/mcc_linux.h22
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__ */