From d58577d8f36f66dbb5dec30fc01dfddda0cfd1fa Mon Sep 17 00:00:00 2001 From: John Linn Date: Wed, 2 Jul 2008 15:11:28 -0700 Subject: [PATCH] powerpc/virtex: Fix booting of Xilinx FPGAs with 16550 for 405 and 440 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 Signed-off-by: Grant Likely --- arch/powerpc/boot/Makefile | 2 +- arch/powerpc/boot/simpleboot.c | 6 ++ arch/powerpc/boot/virtex.c | 100 +++++++++++++++++++++++++++++++++ arch/powerpc/boot/wrapper | 6 +- 4 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/boot/virtex.c diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 751a6e6070..df6e62116e 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -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)) diff --git a/arch/powerpc/boot/simpleboot.c b/arch/powerpc/boot/simpleboot.c index 86cd285bcc..c58a0dada9 100644 --- a/arch/powerpc/boot/simpleboot.c +++ b/arch/powerpc/boot/simpleboot.c @@ -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 index 0000000000..f622805f80 --- /dev/null +++ b/arch/powerpc/boot/virtex.c @@ -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 **)®_base, 1) < 1) + return -1; + + n = getprop(devp, "reg-offset", ®_offset, sizeof(reg_offset)); + if (n == sizeof(reg_offset)) + reg_base += reg_offset; + + n = getprop(devp, "reg-shift", ®_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; +} diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index df2358e9f1..592a6ea474 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -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) -- 2.39.5