powerpc/virtex: Fix booting of Xilinx FPGAs with 16550 for 405 and 440
authorJohn Linn <john.linn@xilinx.com>
Wed, 2 Jul 2008 22:11:28 +0000 (15:11 -0700)
committerGrant Likely <grant.likely@secretlab.ca>
Fri, 4 Jul 2008 06:58:59 +0000 (00:58 -0600)
The following changes add processing to initialize the Xilinx 16550 UART
in the boot wrapper for Virtex targets without firmware.  Normally the
boot wrapper assumes that the serial port has already been initialized by
firmware.

The wrapper was also modified to add the 440 build.

Signed-off-by: John Linn <john.linn@xilinx.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
arch/powerpc/boot/Makefile
arch/powerpc/boot/simpleboot.c
arch/powerpc/boot/virtex.c [new file with mode: 0644]
arch/powerpc/boot/wrapper

index 751a6e6070d232340223d05c69bb19c1404fcc8a..df6e62116e37097444422277fac0dbee670da218 100644 (file)
@@ -68,7 +68,7 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c
                fixed-head.S ep88xc.c ep405.c cuboot-c2k.c \
                cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
                cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
-               virtex405-head.S redboot-83xx.c cuboot-sam440ep.c
+               virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
 src-boot := $(addprefix $(obj)/, $(src-boot))
index 86cd285bccc6b2c32e53ec82dffb81aa5b90a815..c58a0dada992eef1c9edd4d901a6c9901fba413a 100644 (file)
@@ -23,6 +23,8 @@
 
 BSS_STACK(4*1024);
 
+extern int platform_specific_init(void) __attribute__((weak));
+
 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                   unsigned long r6, unsigned long r7)
 {
@@ -80,5 +82,9 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 
        /* prepare the device tree and find the console */
        fdt_init(_dtb_start);
+
+       if (platform_specific_init)
+               platform_specific_init();
+
        serial_console_init();
 }
diff --git a/arch/powerpc/boot/virtex.c b/arch/powerpc/boot/virtex.c
new file mode 100644 (file)
index 0000000..f622805
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * The platform specific code for virtex devices since a boot loader is not
+ * always used.
+ *
+ * (C) Copyright 2008 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "ops.h"
+#include "io.h"
+#include "stdio.h"
+
+#define UART_DLL               0       /* Out: Divisor Latch Low */
+#define UART_DLM               1       /* Out: Divisor Latch High */
+#define UART_FCR               2       /* Out: FIFO Control Register */
+#define UART_FCR_CLEAR_RCVR    0x02    /* Clear the RCVR FIFO */
+#define UART_FCR_CLEAR_XMIT    0x04    /* Clear the XMIT FIFO */
+#define UART_LCR               3       /* Out: Line Control Register */
+#define UART_MCR               4       /* Out: Modem Control Register */
+#define UART_MCR_RTS           0x02    /* RTS complement */
+#define UART_MCR_DTR           0x01    /* DTR complement */
+#define UART_LCR_DLAB          0x80    /* Divisor latch access bit */
+#define UART_LCR_WLEN8         0x03    /* Wordlength: 8 bits */
+
+static int virtex_ns16550_console_init(void *devp)
+{
+       unsigned char *reg_base;
+       u32 reg_shift, reg_offset, clk, spd;
+       u16 divisor;
+       int n;
+
+       if (dt_get_virtual_reg(devp, (void **)&reg_base, 1) < 1)
+               return -1;
+
+       n = getprop(devp, "reg-offset", &reg_offset, sizeof(reg_offset));
+       if (n == sizeof(reg_offset))
+               reg_base += reg_offset;
+
+       n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift));
+       if (n != sizeof(reg_shift))
+               reg_shift = 0;
+
+       n = getprop(devp, "current-speed", (void *)&spd, sizeof(spd));
+       if (n != sizeof(spd))
+               spd = 9600;
+
+       /* should there be a default clock rate?*/
+       n = getprop(devp, "clock-frequency", (void *)&clk, sizeof(clk));
+       if (n != sizeof(clk))
+               return -1;
+
+       divisor = clk / (16 * spd);
+
+       /* Access baud rate */
+       out_8(reg_base + (UART_LCR << reg_shift), UART_LCR_DLAB);
+
+       /* Baud rate based on input clock */
+       out_8(reg_base + (UART_DLL << reg_shift), divisor & 0xFF);
+       out_8(reg_base + (UART_DLM << reg_shift), divisor >> 8);
+
+       /* 8 data, 1 stop, no parity */
+       out_8(reg_base + (UART_LCR << reg_shift), UART_LCR_WLEN8);
+
+       /* RTS/DTR */
+       out_8(reg_base + (UART_MCR << reg_shift), UART_MCR_RTS | UART_MCR_DTR);
+
+       /* Clear transmitter and receiver */
+       out_8(reg_base + (UART_FCR << reg_shift),
+                               UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR);
+       return 0;
+}
+
+/* For virtex, the kernel may be loaded without using a bootloader and if so
+   some UARTs need more setup than is provided in the normal console init
+*/
+int platform_specific_init(void)
+{
+       void *devp;
+       char devtype[MAX_PROP_LEN];
+       char path[MAX_PATH_LEN];
+
+       devp = finddevice("/chosen");
+       if (devp == NULL)
+               return -1;
+
+       if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) {
+               devp = finddevice(path);
+               if (devp == NULL)
+                       return -1;
+
+               if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0)
+                               && !strcmp(devtype, "serial")
+                               && (dt_is_compatible(devp, "ns16550")))
+                               virtex_ns16550_console_init(devp);
+       }
+       return 0;
+}
index df2358e9f1ca7eef060e5a8a564ddfbc3ab80592..592a6ea474f64882f26efe3fe81bb1c699cf70ae 100755 (executable)
@@ -207,7 +207,11 @@ adder875-redboot)
     binary=y
     ;;
 simpleboot-virtex405-*)
-    platformo="$object/virtex405-head.o $object/simpleboot.o"
+    platformo="$object/virtex405-head.o $object/simpleboot.o $object/virtex.o"
+    binary=y
+    ;;
+simpleboot-virtex440-*)
+    platformo="$object/simpleboot.o $object/virtex.o"
     binary=y
     ;;
 asp834x-redboot)