Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754280Ab0KITyk (ORCPT ); Tue, 9 Nov 2010 14:54:40 -0500 Received: from mail-pv0-f174.google.com ([74.125.83.174]:45326 "EHLO mail-pv0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754202Ab0KITyh (ORCPT ); Tue, 9 Nov 2010 14:54:37 -0500 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=PB2VoVIc4tSOv6zzsLa8n+u+5Bn8hZzQGTt5RIKEAMR8QDuIfd2QAXTjUlSx6O5Nxu 6604txW/DQ4bH3xTbxUonceOE4IZ2QW5JEqi336HysJ5zC8r78Uy11qM1UBytLXymRrn 3gQIqpwWcvCp3HjJJQNO9h8MWKyAVcrZB8yhs= From: dirk.brandewie@gmail.com To: linux-kernel@vger.kernel.org Cc: Dirk Brandewie , x86@kernel.org Subject: [PATCH 4/6] ce4100: Add errata fixes for UART on CE4100 Date: Tue, 9 Nov 2010 12:08:07 -0800 Message-Id: <395c11879580e72e3a47272ef8cf5e04fa334210.1289331834.git.dirk.brandewie@gmail.com> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4428 Lines: 147 From: Dirk Brandewie This patch enables the UART on the CE4100. The UART has a couple of issues that need to be worked around. First the UART is mostly PC compatible except that it is clocked eight times faster than a standard PC so the default configuration provided in arch/x86/include/asm/serial.h needs to be overridden. Second the TX interrupt may not be set correctly all the time. Lastly accessing the UART via I/O space for early_prink() hangs the chip when the IOAPIC is enabled. A custom mem_serial_in() is provided to work around the TX interrupt issue. The configuration issues are dealt with in the call back registered with the 8250 driver via serial8250_set_isa_configurator() Signed-off-by: Dirk Brandewie --- arch/x86/kernel/ce4100.c | 92 ++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 89 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/ce4100.c b/arch/x86/kernel/ce4100.c index b8f1c48..d2c0d51 100644 --- a/arch/x86/kernel/ce4100.c +++ b/arch/x86/kernel/ce4100.c @@ -12,25 +12,111 @@ #include #include #include +#include +#include #include - +#include static int ce4100_i8042_detect(void) { return 0; } -static void __init sdv_arch_setup(void) +static void __init sdv_find_smp_config(void) { +} + +#ifdef CONFIG_SERIAL_8250 + +static unsigned int mem_serial_in(struct uart_port *p, int offset) +{ + offset = offset << p->regshift; + return readl(p->membase + offset); } +/* + * The UART Tx interrupts are not set under some conditions and therefore serial + * transmission hangs. This is a silicon issue and has not been root caused. The + * workaround for this silicon issue checks UART_LSR_THRE bit and UART_LSR_TEMT + * bit of LSR register in interrupt handler to see whether at least one of these + * two bits is set, if so then process the transmit request. If this workaround + * is not applied, then the serial transmission may hang. This workaround is for + * errata number 9 in Errata - B step. +*/ -static void __init sdv_find_smp_config(void) +static unsigned int ce4100_mem_serial_in(struct uart_port *p, int offset) +{ + unsigned int ret, ier, lsr; + + if (offset == UART_IIR) { + offset = offset << p->regshift; + ret = readl(p->membase + offset); + if (ret & UART_IIR_NO_INT) { + /* see if the TX interrupt should have really set */ + ier = mem_serial_in(p, UART_IER); + /* see if the UART's XMIT interrupt is enabled */ + if (ier & UART_IER_THRI) { + lsr = mem_serial_in(p, UART_LSR); + /* now check to see if the UART should be + generating an interrupt (but isn't) */ + if (lsr & (UART_LSR_THRE | UART_LSR_TEMT)) + ret &= ~UART_IIR_NO_INT; + } + } + } else + ret = mem_serial_in(p, offset); + return ret; +} + +static void ce4100_mem_serial_out(struct uart_port *p, int offset, int value) +{ + offset = offset << p->regshift; + writel(value, p->membase + offset); +} + +static void ce4100_serial_fixup(int port, struct uart_port *up, + unsigned short *capabilites) +{ +#ifdef CONFIG_EARLY_PRINTK + /* + * Over ride the legacy port configuration that comes from + * asm/serial.h. Using the ioport driver then switching to the + * PCI memmaped driver hangs the IOAPIC + */ + if (up->iotype != UPIO_MEM32) { + up->uartclk = 14745600; + up->mapbase = 0xdffe0200; + set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, + up->mapbase & PAGE_MASK); + up->membase = + (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); + up->membase += up->mapbase & ~PAGE_MASK; + up->iotype = UPIO_MEM32; + up->regshift = 2; + } +#endif + up->iobase = 0; + up->serial_in = ce4100_mem_serial_in; + up->serial_out = ce4100_mem_serial_out; + + *capabilites |= (1 << 12); +} + +static __init void sdv_serial_fixup(void) { + serial8250_set_isa_configurator(ce4100_serial_fixup); } +#else +static inline void sdv_serial_fixup(void); +#endif + +static void __init sdv_arch_setup(void) +{ + sdv_serial_fixup(); +} /* * CE4100 specific x86_init function overrides and early setup -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/