summaryrefslogtreecommitdiffstats
path: root/sys/contrib/octeon-sdk/cvmx-debug-uart.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/octeon-sdk/cvmx-debug-uart.c')
-rw-r--r--sys/contrib/octeon-sdk/cvmx-debug-uart.c267
1 files changed, 267 insertions, 0 deletions
diff --git a/sys/contrib/octeon-sdk/cvmx-debug-uart.c b/sys/contrib/octeon-sdk/cvmx-debug-uart.c
new file mode 100644
index 0000000..4c80a86
--- /dev/null
+++ b/sys/contrib/octeon-sdk/cvmx-debug-uart.c
@@ -0,0 +1,267 @@
+/***********************license start***************
+ * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights
+ * reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+
+ * * Neither the name of Cavium Inc. nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+
+ * This Software, including technical data, may be subject to U.S. export control
+ * laws, including the U.S. Export Administration Act and its associated
+ * regulations, and may be subject to export or import regulations in other
+ * countries.
+
+ * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+ * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
+ * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
+ * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
+ * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
+ * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
+ * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
+ * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
+ * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
+ * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+ ***********************license end**************************************/
+
+
+#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
+#include <linux/module.h>
+#include <asm/octeon/cvmx.h>
+#include <asm/octeon/cvmx-debug.h>
+#include <asm/octeon/cvmx-uart.h>
+#include <asm/octeon/octeon-boot-info.h>
+#include <asm/octeon/cvmx-spinlock.h>
+
+int cvmx_debug_uart = 1;
+
+#else
+#include <limits.h>
+#include "executive-config.h"
+#include "cvmx.h"
+#include "cvmx-debug.h"
+#include "cvmx-uart.h"
+#include "cvmx-spinlock.h"
+#include "octeon-boot-info.h"
+#endif
+
+/*
+ * NOTE: CARE SHOULD BE TAKEN USING STD C LIBRARY FUNCTIONS IN
+ * THIS FILE IF SOMEONE PUTS A BREAKPOINT ON THOSE FUNCTIONS
+ * DEBUGGING WILL FAIL.
+ */
+
+
+#ifdef CVMX_BUILD_FOR_TOOLCHAIN
+#pragma weak cvmx_uart_enable_intr
+int cvmx_debug_uart = 1;
+#endif
+
+
+/* Default to second uart port for backward compatibility. The default (if
+ -debug does not set the uart number) can now be overridden with
+ CVMX_DEBUG_COMM_UART_NUM. */
+#ifndef CVMX_DEBUG_COMM_UART_NUM
+# define CVMX_DEBUG_COMM_UART_NUM 1
+#endif
+
+static CVMX_SHARED cvmx_spinlock_t cvmx_debug_uart_lock;
+
+/**
+ * Interrupt handler for debugger Control-C interrupts.
+ *
+ * @param irq_number IRQ interrupt number
+ * @param registers CPU registers at the time of the interrupt
+ * @param user_arg Unused user argument
+ */
+void cvmx_debug_uart_process_debug_interrupt(int irq_number, uint64_t registers[32], void *user_arg)
+{
+ cvmx_uart_lsr_t lsrval;
+
+ /* Check for a Control-C interrupt from the debugger. This loop will eat
+ all input received on the uart */
+ lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(cvmx_debug_uart));
+ while (lsrval.s.dr)
+ {
+ int c = cvmx_read_csr(CVMX_MIO_UARTX_RBR(cvmx_debug_uart));
+ if (c == '\003')
+ {
+ register uint64_t tmp;
+#ifndef CVMX_BUILD_FOR_LINUX_KERNEL
+ fflush(stderr);
+ fflush(stdout);
+#endif
+ /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also
+ set the MCD0 to be not masked by this core so we know
+ the signal is received by someone */
+ asm volatile (
+ "dmfc0 %0, $22\n"
+ "ori %0, %0, 0x1110\n"
+ "dmtc0 %0, $22\n"
+ : "=r" (tmp));
+ }
+ lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(cvmx_debug_uart));
+ }
+}
+
+
+static void cvmx_debug_uart_init(void)
+{
+ if (cvmx_debug_uart == -1)
+ cvmx_debug_uart = CVMX_DEBUG_COMM_UART_NUM;
+}
+
+static void cvmx_debug_uart_install_break_handler(void)
+{
+#ifndef CVMX_BUILD_FOR_LINUX_KERNEL
+#ifdef CVMX_BUILD_FOR_TOOLCHAIN
+ if (cvmx_uart_enable_intr)
+#endif
+ cvmx_uart_enable_intr(cvmx_debug_uart, cvmx_debug_uart_process_debug_interrupt);
+#endif
+}
+
+/**
+ * Routines to handle hex data
+ *
+ * @param ch
+ * @return
+ */
+static inline int cvmx_debug_uart_hex(char ch)
+{
+ if ((ch >= 'a') && (ch <= 'f'))
+ return(ch - 'a' + 10);
+ if ((ch >= '0') && (ch <= '9'))
+ return(ch - '0');
+ if ((ch >= 'A') && (ch <= 'F'))
+ return(ch - 'A' + 10);
+ return(-1);
+}
+
+/* Get a packet from the UART, return 0 on failure and 1 on success. */
+
+static int cvmx_debug_uart_getpacket(char *buffer, size_t size)
+{
+ while (1)
+ {
+ unsigned char checksum;
+ int timedout = 0;
+ size_t count;
+ char ch;
+
+ ch = cvmx_uart_read_byte_with_timeout(cvmx_debug_uart, &timedout, __SHRT_MAX__);
+
+ if (timedout)
+ return 0;
+
+ /* if this is not the start character, ignore it. */
+ if (ch != '$')
+ continue;
+
+ retry:
+ checksum = 0;
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < size)
+ {
+ ch = cvmx_uart_read_byte(cvmx_debug_uart);
+ if (ch == '$')
+ goto retry;
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#')
+ {
+ char csumchars0, csumchars1;
+ unsigned xmitcsum;
+ int n0, n1;
+
+ csumchars0 = cvmx_uart_read_byte(cvmx_debug_uart);
+ csumchars1 = cvmx_uart_read_byte(cvmx_debug_uart);
+ n0 = cvmx_debug_uart_hex(csumchars0);
+ n1 = cvmx_debug_uart_hex(csumchars1);
+ if (n0 == -1 || n1 == -1)
+ return 0;
+
+ xmitcsum = (n0 << 4) | n1;
+ return checksum == xmitcsum;
+ }
+ }
+ return 0;
+}
+
+/* Put the hex value of t into str. */
+static void cvmx_debug_uart_strhex(char *str, unsigned char t)
+{
+ char hexchar[] = "0123456789ABCDEF";
+ str[0] = hexchar[(t>>4)];
+ str[1] = hexchar[t&0xF];
+ str[2] = 0;
+}
+
+static int cvmx_debug_uart_putpacket(char *packet)
+{
+ size_t i;
+ unsigned char csum;
+ unsigned char *ptr = (unsigned char *) packet;
+ char csumstr[3];
+
+ for (csum = 0, i = 0; ptr[i]; i++)
+ csum += ptr[i];
+ cvmx_debug_uart_strhex(csumstr, csum);
+
+ cvmx_spinlock_lock(&cvmx_debug_uart_lock);
+ cvmx_uart_write_byte(cvmx_debug_uart, '$');
+ cvmx_uart_write_string(cvmx_debug_uart, packet);
+ cvmx_uart_write_byte(cvmx_debug_uart, '#');
+ cvmx_uart_write_string(cvmx_debug_uart, csumstr);
+ cvmx_spinlock_unlock(&cvmx_debug_uart_lock);
+
+ return 0;
+}
+
+static void cvmx_debug_uart_change_core(int oldcore, int newcore)
+{
+#ifndef CVMX_BUILD_FOR_LINUX_KERNEL
+ cvmx_ciu_intx0_t irq_control;
+
+ irq_control.u64 = cvmx_read_csr(CVMX_CIU_INTX_EN0(newcore * 2));
+ irq_control.s.uart |= (1u<<cvmx_debug_uart);
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(newcore * 2), irq_control.u64);
+
+ /* Disable interrupts to this core since he is about to die */
+ irq_control.u64 = cvmx_read_csr(CVMX_CIU_INTX_EN0(oldcore * 2));
+ irq_control.s.uart &= ~(1u<<cvmx_debug_uart);
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(oldcore* 2), irq_control.u64);
+#endif
+}
+
+cvmx_debug_comm_t cvmx_debug_uart_comm =
+{
+ .init = cvmx_debug_uart_init,
+ .install_break_handler = cvmx_debug_uart_install_break_handler,
+ .needs_proxy = 1,
+ .getpacket = cvmx_debug_uart_getpacket,
+ .putpacket = cvmx_debug_uart_putpacket,
+ .wait_for_resume = NULL,
+ .change_core = cvmx_debug_uart_change_core,
+};
OpenPOWER on IntegriCloud