[POWERPC] 4xx: Add early udbg support for 40x processors
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 21 Dec 2007 04:39:26 +0000 (15:39 +1100)
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>
Sun, 23 Dec 2007 19:13:03 +0000 (13:13 -0600)
This adds some basic real mode based early udbg support for 40x
in order to debug things more easily

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
arch/powerpc/Kconfig.debug
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/udbg.c
arch/powerpc/kernel/udbg_16550.c
arch/powerpc/platforms/Kconfig.cputype
include/asm-powerpc/udbg.h

index d20ccf5f2ca99cc1f06ab37e809a4984a547f596..179a453f7e04323148ccec6ead957bd9ef2a6cf8 100644 (file)
@@ -227,6 +227,14 @@ config PPC_EARLY_DEBUG_44x
          Select this to enable early debugging for IBM 44x chips via the
          inbuilt serial port.
 
+config PPC_EARLY_DEBUG_40x
+       bool "Early serial debugging for IBM/AMCC 40x CPUs"
+       depends on 40x
+       help
+         Select this to enable early debugging for IBM 40x chips via the
+         inbuilt serial port. This works on chips with a 16550 compatible
+         UART. Xilinx chips with uartlite cannot use this option.
+
 config PPC_EARLY_DEBUG_CPM
        bool "Early serial debugging for Freescale CPM-based serial ports"
        depends on SERIAL_CPM
@@ -248,6 +256,11 @@ config PPC_EARLY_DEBUG_44x_PHYSHIGH
        depends on PPC_EARLY_DEBUG_44x
        default "0x1"
 
+config PPC_EARLY_DEBUG_40x_PHYSADDR
+       hex "Early debug UART physical address"
+       depends on PPC_EARLY_DEBUG_40x
+       default "0xef600300"
+
 config PPC_EARLY_DEBUG_CPM_ADDR
        hex "CPM UART early debug transmit descriptor address"
        depends on PPC_EARLY_DEBUG_CPM
index ea1137851a4adc4a6ae7adfcba8aa74ed303340c..be09f0d2d90b27802d9687ae05bb1795957815ea 100644 (file)
@@ -206,6 +206,45 @@ _GLOBAL(_nmask_and_or_msr)
        isync
        blr                     /* Done */
 
+#ifdef CONFIG_40x
+
+/*
+ * Do an IO access in real mode
+ */
+_GLOBAL(real_readb)
+       mfmsr   r7
+       ori     r0,r7,MSR_DR
+       xori    r0,r0,MSR_DR
+       sync
+       mtmsr   r0
+       sync
+       isync
+       lbz     r3,0(r3)
+       sync
+       mtmsr   r7
+       sync
+       isync
+       blr
+
+       /*
+ * Do an IO access in real mode
+ */
+_GLOBAL(real_writeb)
+       mfmsr   r7
+       ori     r0,r7,MSR_DR
+       xori    r0,r0,MSR_DR
+       sync
+       mtmsr   r0
+       sync
+       isync
+       stb     r3,0(r4)
+       sync
+       mtmsr   r7
+       sync
+       isync
+       blr
+
+#endif /* CONFIG_40x */
 
 /*
  * Flush MMU TLB
index eba148f2a31c09b7b65a68def74628b4987c3815..7aad6203e411e926580dba0517deb918d3558a83 100644 (file)
@@ -54,6 +54,9 @@ void __init udbg_early_init(void)
 #elif defined(CONFIG_PPC_EARLY_DEBUG_44x)
        /* PPC44x debug */
        udbg_init_44x_as1();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_40x)
+       /* PPC40x debug */
+       udbg_init_40x_realmode();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_CPM)
        udbg_init_cpm();
 #endif
index df740eae77b856edc047ad4324df2dd1f579a991..cb01ebc593876b5736cc96640904a8117a5da3c6 100644 (file)
@@ -225,3 +225,36 @@ void __init udbg_init_44x_as1(void)
        udbg_getc = udbg_44x_as1_getc;
 }
 #endif /* CONFIG_PPC_EARLY_DEBUG_44x */
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_40x
+static void udbg_40x_real_putc(char c)
+{
+       if (udbg_comport) {
+               while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
+                       /* wait for idle */;
+               real_writeb(c, &udbg_comport->thr); eieio();
+               if (c == '\n')
+                       udbg_40x_real_putc('\r');
+       }
+}
+
+static int udbg_40x_real_getc(void)
+{
+       if (udbg_comport) {
+               while ((real_readb(&udbg_comport->lsr) & LSR_DR) == 0)
+                       ; /* wait for char */
+               return real_readb(&udbg_comport->rbr);
+       }
+       return -1;
+}
+
+void __init udbg_init_40x_realmode(void)
+{
+       udbg_comport = (struct NS16550 __iomem *)
+               CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR;
+
+       udbg_putc = udbg_40x_real_putc;
+       udbg_getc = udbg_40x_real_getc;
+       udbg_getc_poll = NULL;
+}
+#endif /* CONFIG_PPC_EARLY_DEBUG_40x */
index 99684ea606afef4b399a46ab1e059baef6002767..c3ee0b58d539da470f305114e41d90ee29731e25 100644 (file)
@@ -43,6 +43,7 @@ config 40x
        bool "AMCC 40x"
        select PPC_DCR_NATIVE
        select WANT_DEVICE_TREE
+       select PPC_UDBG_16550
 
 config 44x
        bool "AMCC 44x"
index a9e0b0ebcb0fe33cd8070f84a60e1a2a8b2ab020..6418ceea44b70f27d69027b3a30ee85d8bd4b3fd 100644 (file)
@@ -48,6 +48,7 @@ extern void __init udbg_init_rtas_console(void);
 extern void __init udbg_init_debug_beat(void);
 extern void __init udbg_init_btext(void);
 extern void __init udbg_init_44x_as1(void);
+extern void __init udbg_init_40x_realmode(void);
 extern void __init udbg_init_cpm(void);
 
 #endif /* __KERNEL__ */