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 <john.linn@xilinx.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
This commit is contained in:
parent
dc568ec490
commit
d58577d8f3
4 changed files with 112 additions and 2 deletions
|
@ -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))
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
100
arch/powerpc/boot/virtex.c
Normal file
100
arch/powerpc/boot/virtex.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue