summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/qoriq/mpci/intercom-mpci.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/powerpc/qoriq/mpci/intercom-mpci.c')
-rw-r--r--bsps/powerpc/qoriq/mpci/intercom-mpci.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/bsps/powerpc/qoriq/mpci/intercom-mpci.c b/bsps/powerpc/qoriq/mpci/intercom-mpci.c
new file mode 100644
index 0000000000..2cc45dd079
--- /dev/null
+++ b/bsps/powerpc/qoriq/mpci/intercom-mpci.c
@@ -0,0 +1,124 @@
+/**
+ * @file
+ *
+ * @ingroup QorIQInterCom
+ *
+ * @brief Inter-Processor Communication implementation.
+ */
+
+/*
+ * Copyright (c) 2011 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <assert.h>
+
+#include <libcpu/powerpc-utility.h>
+
+#include <bsp/intercom.h>
+
+#ifdef RTEMS_MULTIPROCESSING
+
+typedef struct {
+ intercom_packet *head;
+ intercom_packet *tail;
+} mpic_fifo;
+
+static mpic_fifo fifo;
+
+static void mpci_service(intercom_packet *packet, void *arg)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ packet->glue.next = NULL;
+ if (fifo.head != NULL) {
+ fifo.tail->glue.next = packet;
+ } else {
+ fifo.head = packet;
+ }
+ fifo.tail = packet;
+ rtems_interrupt_enable(level);
+
+ rtems_multiprocessing_announce();
+}
+
+static void mpci_init(void)
+{
+ qoriq_intercom_service_install(INTERCOM_TYPE_MPCI, mpci_service, NULL);
+}
+
+static intercom_packet *packet_of_prefix(rtems_packet_prefix *prefix)
+{
+ return (intercom_packet *) ((char *) prefix - sizeof(intercom_packet));
+}
+
+static rtems_packet_prefix *prefix_of_packet(intercom_packet *packet)
+{
+ return (rtems_packet_prefix *) packet->data;
+}
+
+static void mpci_get_packet(rtems_packet_prefix **prefix_ptr)
+{
+ intercom_packet *packet = qoriq_intercom_allocate_packet(
+ INTERCOM_TYPE_MPCI,
+ INTERCOM_SIZE_512
+ );
+ *prefix_ptr = prefix_of_packet(packet);
+}
+
+static void mpci_return_packet(rtems_packet_prefix *prefix)
+{
+ intercom_packet *packet = packet_of_prefix(prefix);
+
+ qoriq_intercom_free_packet(packet);
+}
+
+static void mpci_send_packet(uint32_t destination_node, rtems_packet_prefix *prefix)
+{
+ intercom_packet *packet = packet_of_prefix(prefix);
+ if (destination_node != MPCI_ALL_NODES) {
+ qoriq_intercom_send_packet((int) destination_node - 1, packet);
+ } else {
+ uint32_t self = ppc_processor_id();
+ int other = self == 0 ? 1 : 0;
+
+ qoriq_intercom_send_packet(other, packet);
+ }
+}
+
+static void mpci_receive_packet(rtems_packet_prefix **prefix_ptr)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ intercom_packet *packet = fifo.head;
+ if (packet != NULL) {
+ fifo.head = packet->glue.next;
+ *prefix_ptr = prefix_of_packet(packet);
+ } else {
+ *prefix_ptr = NULL;
+ }
+ rtems_interrupt_enable(level);
+}
+
+rtems_mpci_table qoriq_intercom_mpci = {
+ .default_timeout = UINT32_MAX,
+ .maximum_packet_size = 512,
+ .initialization = mpci_init,
+ .get_packet = mpci_get_packet,
+ .return_packet = mpci_return_packet,
+ .send_packet = mpci_send_packet,
+ .receive_packet = mpci_receive_packet
+};
+
+#endif /* RTEMS_MULTIPROCESSING */