Merge branch 'for-3.5/debug' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren...
authorOlof Johansson <olof@lixom.net>
Thu, 10 May 2012 06:53:05 +0000 (23:53 -0700)
committerOlof Johansson <olof@lixom.net>
Thu, 10 May 2012 06:53:05 +0000 (23:53 -0700)
By Stephen Warren
via Stephen Warren
* 'for-3.5/debug' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra:
  ARM: tegra: uncompress.h: Implement TEGRA_DEBUG_UART_AUTO_ODMDATA

arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/include/mach/uncompress.h

index d0f2546706ca1b53d6cae8d3eecb84dc89f79a17..204d3d4d73882ea6b00ee5d953d56af7f08c8ea0 100644 (file)
@@ -111,7 +111,7 @@ config MACH_VENTANA
          Support for the nVidia Ventana development platform
 
 choice
-        prompt "Low-level debug console UART"
+        prompt "Default low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
 
 config TEGRA_DEBUG_UART_NONE
@@ -134,6 +134,33 @@ config TEGRA_DEBUG_UARTE
 
 endchoice
 
+choice
+       prompt "Automatic low-level debug console UART"
+       default TEGRA_DEBUG_UART_AUTO_NONE
+
+config TEGRA_DEBUG_UART_AUTO_NONE
+       bool "None"
+
+config TEGRA_DEBUG_UART_AUTO_ODMDATA
+       bool "Via ODMDATA"
+       help
+         Automatically determines which UART to use for low-level debug based
+         on the ODMDATA value. This value is part of the BCT, and is written
+         to the boot memory device using nvflash, or other flashing tool.
+         When bits 19:18 are 3, then bits 17:15 indicate which UART to use;
+         0/1/2/3/4 are UART A/B/C/D/E.
+
+config TEGRA_DEBUG_UART_AUTO_SCRATCH
+       bool "Via UART scratch register"
+       help
+         Automatically determines which UART to use for low-level debug based
+         on the UART scratch register value. Some bootloaders put ASCII 'D'
+         in this register when they initialize their own console UART output.
+         Using this option allows the kernel to automatically pick the same
+         UART.
+
+endchoice
+
 config TEGRA_SYSTEM_DMA
        bool "Enable system DMA driver for NVIDIA Tegra SoCs"
        default y
index 5a440f315e575d29c43958fd1c84226843056447..937c4c50219e1a818c89b32f965598318fbd55cc 100644 (file)
@@ -63,52 +63,86 @@ static inline void save_uart_address(void)
                buf[0] = 0;
 }
 
-/*
- * Setup before decompression.  This is where we do UART selection for
- * earlyprintk and init the uart_base register.
- */
-static inline void arch_decomp_setup(void)
+static const struct {
+       u32 base;
+       u32 reset_reg;
+       u32 clock_reg;
+       u32 bit;
+} uarts[] = {
+       {
+               TEGRA_UARTA_BASE,
+               TEGRA_CLK_RESET_BASE + 0x04,
+               TEGRA_CLK_RESET_BASE + 0x10,
+               6,
+       },
+       {
+               TEGRA_UARTB_BASE,
+               TEGRA_CLK_RESET_BASE + 0x04,
+               TEGRA_CLK_RESET_BASE + 0x10,
+               7,
+       },
+       {
+               TEGRA_UARTC_BASE,
+               TEGRA_CLK_RESET_BASE + 0x08,
+               TEGRA_CLK_RESET_BASE + 0x14,
+               23,
+       },
+       {
+               TEGRA_UARTD_BASE,
+               TEGRA_CLK_RESET_BASE + 0x0c,
+               TEGRA_CLK_RESET_BASE + 0x18,
+               1,
+       },
+       {
+               TEGRA_UARTE_BASE,
+               TEGRA_CLK_RESET_BASE + 0x0c,
+               TEGRA_CLK_RESET_BASE + 0x18,
+               2,
+       },
+};
+
+static inline bool uart_clocked(int i)
+{
+       if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
+               return false;
+
+       if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
+               return false;
+
+       return true;
+}
+
+#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA
+int auto_odmdata(void)
+{
+       volatile u32 *pmc = (volatile u32 *)TEGRA_PMC_BASE;
+       u32 odmdata = pmc[0xa0 / 4];
+
+       /*
+        * Bits 19:18 are the console type: 0=default, 1=none, 2==DCC, 3==UART
+        * Some boards apparently swap the last two values, but we don't have
+        * any way of catering for that here, so we just accept either. If this
+        * doesn't make sense for your board, just don't enable this feature.
+        *
+        * Bits 17:15 indicate the UART to use, 0/1/2/3/4 are UART A/B/C/D/E.
+        */
+
+       switch  ((odmdata >> 18) & 3) {
+       case 2:
+       case 3:
+               break;
+       default:
+               return -1;
+       }
+
+       return (odmdata >> 15) & 7;
+}
+#endif
+
+#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH
+int auto_scratch(void)
 {
-       static const struct {
-               u32 base;
-               u32 reset_reg;
-               u32 clock_reg;
-               u32 bit;
-       } uarts[] = {
-               {
-                       TEGRA_UARTA_BASE,
-                       TEGRA_CLK_RESET_BASE + 0x04,
-                       TEGRA_CLK_RESET_BASE + 0x10,
-                       6,
-               },
-               {
-                       TEGRA_UARTB_BASE,
-                       TEGRA_CLK_RESET_BASE + 0x04,
-                       TEGRA_CLK_RESET_BASE + 0x10,
-                       7,
-               },
-               {
-                       TEGRA_UARTC_BASE,
-                       TEGRA_CLK_RESET_BASE + 0x08,
-                       TEGRA_CLK_RESET_BASE + 0x14,
-                       23,
-               },
-               {
-                       TEGRA_UARTD_BASE,
-                       TEGRA_CLK_RESET_BASE + 0x0c,
-                       TEGRA_CLK_RESET_BASE + 0x18,
-                       1,
-               },
-               {
-                       TEGRA_UARTE_BASE,
-                       TEGRA_CLK_RESET_BASE + 0x0c,
-                       TEGRA_CLK_RESET_BASE + 0x18,
-                       2,
-               },
-       };
        int i;
-       volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
-       u32 chip, div;
 
        /*
         * Look for the first UART that:
@@ -125,20 +159,60 @@ static inline void arch_decomp_setup(void)
         * back to what's specified in TEGRA_DEBUG_UART_BASE.
         */
        for (i = 0; i < ARRAY_SIZE(uarts); i++) {
-               if (*(u8 *)uarts[i].reset_reg & BIT(uarts[i].bit))
-                       continue;
-
-               if (!(*(u8 *)uarts[i].clock_reg & BIT(uarts[i].bit)))
+               if (!uart_clocked(i))
                        continue;
 
                uart = (volatile u8 *)uarts[i].base;
                if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
                        continue;
 
-               break;
+               return i;
        }
-       if (i == ARRAY_SIZE(uarts))
-               uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
+
+       return -1;
+}
+#endif
+
+/*
+ * Setup before decompression.  This is where we do UART selection for
+ * earlyprintk and init the uart_base register.
+ */
+static inline void arch_decomp_setup(void)
+{
+       int uart_id, auto_uart_id;
+       volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
+       u32 chip, div;
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTA)
+       uart_id = 0;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
+       uart_id = 1;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
+       uart_id = 2;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
+       uart_id = 3;
+#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
+       uart_id = 4;
+#else
+       uart_id = -1;
+#endif
+
+#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
+       auto_uart_id = auto_odmdata();
+#elif defined(CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH)
+       auto_uart_id = auto_scratch();
+#else
+       auto_uart_id = -1;
+#endif
+       if (auto_uart_id != -1)
+               uart_id = auto_uart_id;
+
+       if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) ||
+           !uart_clocked(uart_id))
+               uart = NULL;
+       else
+               uart = (volatile u8 *)uarts[uart_id].base;
+
        save_uart_address();
        if (uart == NULL)
                return;
This page took 0.028285 seconds and 5 git commands to generate.