From patchwork Thu Oct 13 07:00:03 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Eisele X-Patchwork-Id: 119360 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id EB3C6B6F81 for ; Thu, 13 Oct 2011 18:06:43 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751262Ab1JMHGn (ORCPT ); Thu, 13 Oct 2011 03:06:43 -0400 Received: from mail176c2.megamailservers.com ([69.49.111.76]:33289 "EHLO mail176c2.megamailservers.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751023Ab1JMHGm (ORCPT ); Thu, 13 Oct 2011 03:06:42 -0400 X-Authenticated-User: konrad.gaisler.com Received: from localhost.localdomain (gaisler.se [92.33.28.242]) (authenticated bits=0) by mail176c2.megamailservers.com (8.13.6/8.13.1) with ESMTP id p9D76Xb1003036; Thu, 13 Oct 2011 03:06:39 -0400 From: Konrad Eisele To: davem@davemloft.net Cc: sparclinux@vger.kernel.org, daniel@gaisler.com Subject: [PATCH 2/4] apbuart: add support for virtual KGDB<->GRMON channel Date: Thu, 13 Oct 2011 09:00:03 +0200 Message-Id: <1318489205-315-3-git-send-email-konrad@gaisler.com> X-Mailer: git-send-email 1.6.4.1 In-Reply-To: <20111011.143858.923549997692641372.davem@davemloft.net> References: <20111011.143858.923549997692641372.davem@davemloft.net> X-CSC: 0 X-CHA: v=1.1 cv=2Gf4Xu/7czTJIpW45n6TwY/zr/fxhY4s3JkmIjrDDIY= c=1 sm=1 a=BzMK5cQDNJAA:10 a=U62ajLuCel8A:10 a=jXKJviUpWSOlMmIvGrHOfw==:17 a=ebG-ZW-8AAAA:8 a=u5EK6AxiuC_L0Z3TNSoA:9 a=XisPoeRqINTeSkEMAJMA:7 a=cCYF7-FHeg4A:10 a=jXKJviUpWSOlMmIvGrHOfw==:117 Sender: sparclinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: sparclinux@vger.kernel.org Add support for a virtual GRMON<->KGDB channel that is created using share memory polling by GRMON. Start GRMON with the option "-vchannel" to enable polling. This feature enables connecting to KGDB without having an hardware serial connection, but using GRMON as an tunnel. Reorder Makefile addition so that apbuart.o gets inserted before kgdboc.o. Add Kconfig option SERIAL_GRLIB_GAISLER_APBUART_GRMON_VIRTUAL to enable the feature. Signed-off-by: Konrad Eisele --- drivers/tty/serial/Kconfig | 12 +++++ drivers/tty/serial/Makefile | 2 +- drivers/tty/serial/apbuart.c | 100 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 1 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index b3692e6..896042b 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1526,6 +1526,18 @@ config SERIAL_GRLIB_GAISLER_APBUART_CONSOLE help Support for running a console on the GRLIB APBUART +config SERIAL_GRLIB_GAISLER_APBUART_GRMON_VIRTUAL + bool "Virtual channel created by GRMON to communicate with KGDB" + depends on SERIAL_GRLIB_GAISLER_APBUART=y + default y + help + Add support for a virtual GRMON<->KGDB channel that + is created using share memory polling by GRMON. Start + GRMON with the option "-vchannel" to enable polling. This + feature enables connecting to KGDB without having an hardware + serial connection, but using GRMON as an tunnel. Also + enable KGDB_SERIAL_CONSOLE to use this feature. + config SERIAL_ALTERA_JTAGUART tristate "Altera JTAG UART support" select SERIAL_CORE diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index cb2628f..ea3fc05 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -81,10 +81,10 @@ obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o +obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o obj-$(CONFIG_SERIAL_QE) += ucc_uart.o obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o -obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c index 153e065..583f41b 100644 --- a/drivers/tty/serial/apbuart.c +++ b/drivers/tty/serial/apbuart.c @@ -355,6 +355,83 @@ static struct uart_ops grlib_apbuart_ops = { #endif }; +#undef CONFIG_SERIAL_GRLIB_GAISLER_APBUART_GRMON_VIRTUAL_HAS +#if defined(CONFIG_SERIAL_GRLIB_GAISLER_APBUART_GRMON_VIRTUAL) && defined(CONFIG_SPARC_LEON) && defined(CONFIG_CONSOLE_POLL) +#define CONFIG_SERIAL_GRLIB_GAISLER_APBUART_GRMON_VIRTUAL_HAS +#include + +/* + * Use a memory array that is continuously read/written by GRMON + * as a communication channel. GRMON will test for the existence + * of symbol apbuart_grmon_vchannel. If present the "shared memory" + * of apbuart_grmon_vchannel will be used to comunicate with linux. + * apbuart_grmon_vchannel is only used for KGDB polling communication. + */ +unsigned int apbuart_grmon_vchannel[4] = { 0, 0, 0, 0 }; + +EXPORT_SYMBOL(apbuart_grmon_vchannel); + +static void apbuart_set_termios_v(struct uart_port *port, + struct ktermios *termios, + struct ktermios *old) +{ + return; +} + +unsigned char apbuart_poll_get_char_v_b[4]; +unsigned char apbuart_poll_get_char_v_c = 0; +static int apbuart_poll_get_char_v(struct uart_port *port) +{ + int c = NO_POLL_CHAR, cnt, i; + if (apbuart_poll_get_char_v_c) { + apbuart_poll_get_char_v_c--; + c = apbuart_poll_get_char_v_b[0] & 0xff; + for (i = 0; i < apbuart_poll_get_char_v_c; i++) { + apbuart_poll_get_char_v_b[i] = + apbuart_poll_get_char_v_b[i + 1]; + } + } + + /* + * poll for new char GRMON from. When grmon has a new char it + * will set write it into apbuart_grmon_vchannel[0] and then + * set apbuart_grmon_vchannel[1] + */ + else if ((cnt = LEON3_BYPASS_LOAD_PA(__pa(&apbuart_grmon_vchannel[1])))) { + unsigned int ar = + LEON3_BYPASS_LOAD_PA(__pa(&apbuart_grmon_vchannel[0])); + LEON_BYPASS_STORE_PA(__pa(&apbuart_grmon_vchannel[1]), 0); + c = ar & 0xff; + for (i = 1; i < cnt; i++) { + apbuart_poll_get_char_v_b[apbuart_poll_get_char_v_c++] = + (ar >> (8 * i)) & 0xff; + } + } + + return c; +} +static void apbuart_console_putchar_v(struct uart_port *port, unsigned char ch) +{ + /* + * poll for GRMON readout. When grmon has read apbuart_grmon_vchannel[3] + * it will clear apbuart_grmon_vchannel[2] + */ + while (LEON3_BYPASS_LOAD_PA(__pa(&apbuart_grmon_vchannel[2]))) { + } + LEON_BYPASS_STORE_PA(__pa(&apbuart_grmon_vchannel[3]), ch & 0xff); + LEON_BYPASS_STORE_PA(__pa(&apbuart_grmon_vchannel[2]), 1); + return; +} + +static struct uart_ops grlib_apbuart_v_ops = { + .set_termios = apbuart_set_termios_v, + .poll_get_char = apbuart_poll_get_char_v, + .poll_put_char = apbuart_console_putchar_v, +}; + +static struct uart_port grlib_apbuart_vport; +#endif + static struct uart_port grlib_apbuart_ports[UART_NR]; static struct device_node *grlib_apbuart_nodes[UART_NR]; @@ -671,6 +748,18 @@ static int grlib_apbuart_configure(void) break; } +#ifdef CONFIG_SERIAL_GRLIB_GAISLER_APBUART_GRMON_VIRTUAL_HAS + grlib_apbuart_vport.mapbase = 0; + grlib_apbuart_vport.membase = 0; + grlib_apbuart_vport.irq = 0; + grlib_apbuart_vport.iotype = UPIO_MEM; + grlib_apbuart_vport.ops = &grlib_apbuart_v_ops; + grlib_apbuart_vport.flags = UPF_BOOT_AUTOCONF; + grlib_apbuart_vport.line = line; + grlib_apbuart_vport.fifosize = 0; + line++; +#endif + grlib_apbuart_driver.nr = grlib_apbuart_port_nr = line; return line ? 0 : -ENODEV; } @@ -702,6 +791,17 @@ static int __init grlib_apbuart_init(void) uart_unregister_driver(&grlib_apbuart_driver); return ret; } +#ifdef CONFIG_SERIAL_GRLIB_GAISLER_APBUART_GRMON_VIRTUAL_HAS + + /* register an extra virtual port that is used for + * GRMON<->KGDB communication */ + uart_add_one_port(&grlib_apbuart_driver, + (struct uart_port *)&grlib_apbuart_vport); + printk(KERN_INFO + "apbuart: virtual KGDB channel for grmon, use cmdline arg \"kgdboc=kms,ttyS%d,38400\".\napbuart: Use option \"-vchannel\" when starting GRMON.\napbuart: apbuart_grmon_vchannel at pa:0x%x\n", + grlib_apbuart_vport.line, (int)__pa(&apbuart_grmon_vchannel)); + +#endif return ret; }