1215976Sjmallett/***********************license start*************** 2215976Sjmallett * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights 3215976Sjmallett * reserved. 4215976Sjmallett * 5215976Sjmallett * 6215976Sjmallett * Redistribution and use in source and binary forms, with or without 7215976Sjmallett * modification, are permitted provided that the following conditions are 8215976Sjmallett * met: 9215976Sjmallett * 10215976Sjmallett * * Redistributions of source code must retain the above copyright 11215976Sjmallett * notice, this list of conditions and the following disclaimer. 12215976Sjmallett * 13215976Sjmallett * * Redistributions in binary form must reproduce the above 14215976Sjmallett * copyright notice, this list of conditions and the following 15215976Sjmallett * disclaimer in the documentation and/or other materials provided 16215976Sjmallett * with the distribution. 17215976Sjmallett 18215976Sjmallett * * Neither the name of Cavium Networks nor the names of 19215976Sjmallett * its contributors may be used to endorse or promote products 20215976Sjmallett * derived from this software without specific prior written 21215976Sjmallett * permission. 22215976Sjmallett 23215976Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215976Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215976Sjmallett * regulations, and may be subject to export or import regulations in other 26215976Sjmallett * countries. 27215976Sjmallett 28215976Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29215976Sjmallett * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR 30215976Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215976Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215976Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215976Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215976Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215976Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215976Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215976Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38215976Sjmallett ***********************license end**************************************/ 39215976Sjmallett 40215976Sjmallett 41215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 42215976Sjmallett#include <linux/module.h> 43215976Sjmallett#include <asm/octeon/cvmx.h> 44215976Sjmallett#include <asm/octeon/cvmx-debug.h> 45215976Sjmallett#include <asm/octeon/cvmx-uart.h> 46215976Sjmallett#include <asm/octeon/octeon-boot-info.h> 47215976Sjmallett#include <asm/octeon/cvmx-spinlock.h> 48215976Sjmallett 49215976Sjmallettint cvmx_debug_uart = 1; 50215976Sjmallett 51215976Sjmallett#else 52215976Sjmallett#include <limits.h> 53215976Sjmallett#include "executive-config.h" 54215976Sjmallett#include "cvmx.h" 55215976Sjmallett#include "cvmx-debug.h" 56215976Sjmallett#include "cvmx-uart.h" 57215976Sjmallett#include "cvmx-spinlock.h" 58215976Sjmallett 59215976Sjmallett#ifndef __OCTEON_NEWLIB__ 60215976Sjmallett#include "../../bootloader/u-boot/include/octeon_mem_map.h" 61215976Sjmallett#else 62215976Sjmallett#include "octeon-boot-info.h" 63215976Sjmallett#endif 64215976Sjmallett 65215976Sjmallett#endif 66215976Sjmallett 67215976Sjmallett 68215976Sjmallett#ifdef __OCTEON_NEWLIB__ 69215976Sjmallett#pragma weak cvmx_uart_enable_intr 70215976Sjmallettint cvmx_debug_uart = 1; 71215976Sjmallett#endif 72215976Sjmallett 73215976Sjmallett 74215976Sjmallett/* Default to second uart port for backward compatibility. The default (if 75215976Sjmallett -debug does not set the uart number) can now be overridden with 76215976Sjmallett CVMX_DEBUG_COMM_UART_NUM. */ 77215976Sjmallett#ifndef CVMX_DEBUG_COMM_UART_NUM 78215976Sjmallett# define CVMX_DEBUG_COMM_UART_NUM 1 79215976Sjmallett#endif 80215976Sjmallett 81215976Sjmallettstatic CVMX_SHARED cvmx_spinlock_t cvmx_debug_uart_lock; 82215976Sjmallett 83215976Sjmallett/** 84215976Sjmallett * Interrupt handler for debugger Control-C interrupts. 85215976Sjmallett * 86215976Sjmallett * @param irq_number IRQ interrupt number 87215976Sjmallett * @param registers CPU registers at the time of the interrupt 88215976Sjmallett * @param user_arg Unused user argument 89215976Sjmallett */ 90215976Sjmallettvoid cvmx_debug_uart_process_debug_interrupt(int irq_number, uint64_t registers[32], void *user_arg) 91215976Sjmallett{ 92215976Sjmallett cvmx_uart_lsr_t lsrval; 93215976Sjmallett 94215976Sjmallett /* Check for a Control-C interrupt from the debugger. This loop will eat 95215976Sjmallett all input received on the uart */ 96215976Sjmallett lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(cvmx_debug_uart)); 97215976Sjmallett while (lsrval.s.dr) 98215976Sjmallett { 99215976Sjmallett int c = cvmx_read_csr(CVMX_MIO_UARTX_RBR(cvmx_debug_uart)); 100215976Sjmallett if (c == '\003') 101215976Sjmallett { 102215976Sjmallett register uint64_t tmp; 103215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 104215976Sjmallett fflush(stderr); 105215976Sjmallett fflush(stdout); 106215976Sjmallett#endif 107215976Sjmallett /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also 108215976Sjmallett set the MCD0 to be not masked by this core so we know 109215976Sjmallett the signal is received by someone */ 110215976Sjmallett asm volatile ( 111215976Sjmallett "dmfc0 %0, $22\n" 112215976Sjmallett "ori %0, %0, 0x1110\n" 113215976Sjmallett "dmtc0 %0, $22\n" 114215976Sjmallett : "=r" (tmp)); 115215976Sjmallett } 116215976Sjmallett lsrval.u64 = cvmx_read_csr(CVMX_MIO_UARTX_LSR(cvmx_debug_uart)); 117215976Sjmallett } 118215976Sjmallett} 119215976Sjmallett 120215976Sjmallett 121215976Sjmallettstatic void cvmx_debug_uart_init(void) 122215976Sjmallett{ 123215976Sjmallett if (cvmx_debug_uart == -1) 124215976Sjmallett cvmx_debug_uart = CVMX_DEBUG_COMM_UART_NUM; 125215976Sjmallett} 126215976Sjmallett 127215976Sjmallettstatic void cvmx_debug_uart_install_break_handler(void) 128215976Sjmallett{ 129215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 130215976Sjmallett#ifdef __OCTEON_NEWLIB__ 131215976Sjmallett if (cvmx_uart_enable_intr) 132215976Sjmallett#endif 133215976Sjmallett cvmx_uart_enable_intr(cvmx_debug_uart, cvmx_debug_uart_process_debug_interrupt); 134215976Sjmallett#endif 135215976Sjmallett} 136215976Sjmallett 137215976Sjmallett/* Get a packet from the UART, return 0 on failure and 1 on success. */ 138215976Sjmallett 139215976Sjmallettstatic int cvmx_debug_uart_getpacket(char *buffer, size_t size) 140215976Sjmallett{ 141215976Sjmallett while (1) 142215976Sjmallett { 143215976Sjmallett unsigned char checksum; 144215976Sjmallett int timedout = 0; 145215976Sjmallett size_t count; 146215976Sjmallett char ch; 147215976Sjmallett 148215976Sjmallett ch = cvmx_uart_read_byte_with_timeout(cvmx_debug_uart, &timedout, __SHRT_MAX__); 149215976Sjmallett 150215976Sjmallett if (timedout) 151215976Sjmallett return 0; 152215976Sjmallett 153215976Sjmallett /* if this is not the start character, ignore it. */ 154215976Sjmallett if (ch != '$') 155215976Sjmallett continue; 156215976Sjmallett 157215976Sjmallett retry: 158215976Sjmallett checksum = 0; 159215976Sjmallett count = 0; 160215976Sjmallett 161215976Sjmallett /* now, read until a # or end of buffer is found */ 162215976Sjmallett while (count < size) 163215976Sjmallett { 164215976Sjmallett ch = cvmx_uart_read_byte(cvmx_debug_uart); 165215976Sjmallett if (ch == '$') 166215976Sjmallett goto retry; 167215976Sjmallett if (ch == '#') 168215976Sjmallett break; 169215976Sjmallett checksum = checksum + ch; 170215976Sjmallett buffer[count] = ch; 171215976Sjmallett count = count + 1; 172215976Sjmallett } 173215976Sjmallett buffer[count] = 0; 174215976Sjmallett 175215976Sjmallett if (ch == '#') 176215976Sjmallett { 177215976Sjmallett char csumchars[2]; 178215976Sjmallett unsigned xmitcsum; 179215976Sjmallett int n; 180215976Sjmallett 181215976Sjmallett csumchars[0] = cvmx_uart_read_byte(cvmx_debug_uart); 182215976Sjmallett csumchars[1] = cvmx_uart_read_byte(cvmx_debug_uart); 183215976Sjmallett n = sscanf(csumchars, "%2x", &xmitcsum); 184215976Sjmallett if (n != 1) 185215976Sjmallett return 1; 186215976Sjmallett 187215976Sjmallett return checksum == xmitcsum; 188215976Sjmallett } 189215976Sjmallett } 190215976Sjmallett return 0; 191215976Sjmallett} 192215976Sjmallett 193215976Sjmallettstatic int cvmx_debug_uart_putpacket(char *packet) 194215976Sjmallett{ 195215976Sjmallett size_t i; 196215976Sjmallett unsigned char csum; 197215976Sjmallett unsigned char *ptr = (unsigned char *) packet; 198215976Sjmallett char csumstr[3]; 199215976Sjmallett 200215976Sjmallett for (csum = 0, i = 0; ptr[i]; i++) 201215976Sjmallett csum += ptr[i]; 202215976Sjmallett sprintf(csumstr, "%02x", csum); 203215976Sjmallett 204215976Sjmallett cvmx_spinlock_lock(&cvmx_debug_uart_lock); 205215976Sjmallett cvmx_uart_write_byte(cvmx_debug_uart, '$'); 206215976Sjmallett cvmx_uart_write_string(cvmx_debug_uart, packet); 207215976Sjmallett cvmx_uart_write_byte(cvmx_debug_uart, '#'); 208215976Sjmallett cvmx_uart_write_string(cvmx_debug_uart, csumstr); 209215976Sjmallett cvmx_spinlock_unlock(&cvmx_debug_uart_lock); 210215976Sjmallett 211215976Sjmallett return 0; 212215976Sjmallett} 213215976Sjmallett 214215976Sjmallettstatic void cvmx_debug_uart_change_core(int oldcore, int newcore) 215215976Sjmallett{ 216215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 217215976Sjmallett cvmx_ciu_intx0_t irq_control; 218215976Sjmallett 219215976Sjmallett irq_control.u64 = cvmx_read_csr(CVMX_CIU_INTX_EN0(newcore * 2)); 220215976Sjmallett irq_control.s.uart |= (1<<cvmx_debug_uart); 221215976Sjmallett cvmx_write_csr(CVMX_CIU_INTX_EN0(newcore * 2), irq_control.u64); 222215976Sjmallett 223215976Sjmallett /* Disable interrupts to this core since he is about to die */ 224215976Sjmallett irq_control.u64 = cvmx_read_csr(CVMX_CIU_INTX_EN0(oldcore * 2)); 225215976Sjmallett irq_control.s.uart &= ~(1<<cvmx_debug_uart); 226215976Sjmallett cvmx_write_csr(CVMX_CIU_INTX_EN0(oldcore* 2), irq_control.u64); 227215976Sjmallett#endif 228215976Sjmallett} 229215976Sjmallett 230215976Sjmallettcvmx_debug_comm_t cvmx_debug_uart_comm = 231215976Sjmallett{ 232215976Sjmallett .init = cvmx_debug_uart_init, 233215976Sjmallett .install_break_handler = cvmx_debug_uart_install_break_handler, 234215976Sjmallett .needs_proxy = 1, 235215976Sjmallett .getpacket = cvmx_debug_uart_getpacket, 236215976Sjmallett .putpacket = cvmx_debug_uart_putpacket, 237215976Sjmallett .wait_for_resume = NULL, 238215976Sjmallett .change_core = cvmx_debug_uart_change_core, 239215976Sjmallett}; 240