diff options
Diffstat (limited to 'arch/powerpc/boot/virtex.c')
| -rw-r--r-- | arch/powerpc/boot/virtex.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/arch/powerpc/boot/virtex.c b/arch/powerpc/boot/virtex.c new file mode 100644 index 000000000000..f622805f8000 --- /dev/null +++ b/arch/powerpc/boot/virtex.c | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | /* | ||
| 2 | * The platform specific code for virtex devices since a boot loader is not | ||
| 3 | * always used. | ||
| 4 | * | ||
| 5 | * (C) Copyright 2008 Xilinx, Inc. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License version 2 as published | ||
| 9 | * by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include "ops.h" | ||
| 13 | #include "io.h" | ||
| 14 | #include "stdio.h" | ||
| 15 | |||
| 16 | #define UART_DLL 0 /* Out: Divisor Latch Low */ | ||
| 17 | #define UART_DLM 1 /* Out: Divisor Latch High */ | ||
| 18 | #define UART_FCR 2 /* Out: FIFO Control Register */ | ||
| 19 | #define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ | ||
| 20 | #define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ | ||
| 21 | #define UART_LCR 3 /* Out: Line Control Register */ | ||
| 22 | #define UART_MCR 4 /* Out: Modem Control Register */ | ||
| 23 | #define UART_MCR_RTS 0x02 /* RTS complement */ | ||
| 24 | #define UART_MCR_DTR 0x01 /* DTR complement */ | ||
| 25 | #define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ | ||
| 26 | #define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ | ||
| 27 | |||
| 28 | static int virtex_ns16550_console_init(void *devp) | ||
| 29 | { | ||
| 30 | unsigned char *reg_base; | ||
| 31 | u32 reg_shift, reg_offset, clk, spd; | ||
| 32 | u16 divisor; | ||
| 33 | int n; | ||
| 34 | |||
| 35 | if (dt_get_virtual_reg(devp, (void **)®_base, 1) < 1) | ||
| 36 | return -1; | ||
| 37 | |||
| 38 | n = getprop(devp, "reg-offset", ®_offset, sizeof(reg_offset)); | ||
| 39 | if (n == sizeof(reg_offset)) | ||
| 40 | reg_base += reg_offset; | ||
| 41 | |||
| 42 | n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift)); | ||
| 43 | if (n != sizeof(reg_shift)) | ||
| 44 | reg_shift = 0; | ||
| 45 | |||
| 46 | n = getprop(devp, "current-speed", (void *)&spd, sizeof(spd)); | ||
| 47 | if (n != sizeof(spd)) | ||
| 48 | spd = 9600; | ||
| 49 | |||
| 50 | /* should there be a default clock rate?*/ | ||
| 51 | n = getprop(devp, "clock-frequency", (void *)&clk, sizeof(clk)); | ||
| 52 | if (n != sizeof(clk)) | ||
| 53 | return -1; | ||
| 54 | |||
| 55 | divisor = clk / (16 * spd); | ||
| 56 | |||
| 57 | /* Access baud rate */ | ||
| 58 | out_8(reg_base + (UART_LCR << reg_shift), UART_LCR_DLAB); | ||
| 59 | |||
| 60 | /* Baud rate based on input clock */ | ||
| 61 | out_8(reg_base + (UART_DLL << reg_shift), divisor & 0xFF); | ||
| 62 | out_8(reg_base + (UART_DLM << reg_shift), divisor >> 8); | ||
| 63 | |||
| 64 | /* 8 data, 1 stop, no parity */ | ||
| 65 | out_8(reg_base + (UART_LCR << reg_shift), UART_LCR_WLEN8); | ||
| 66 | |||
| 67 | /* RTS/DTR */ | ||
| 68 | out_8(reg_base + (UART_MCR << reg_shift), UART_MCR_RTS | UART_MCR_DTR); | ||
| 69 | |||
| 70 | /* Clear transmitter and receiver */ | ||
| 71 | out_8(reg_base + (UART_FCR << reg_shift), | ||
| 72 | UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR); | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | /* For virtex, the kernel may be loaded without using a bootloader and if so | ||
| 77 | some UARTs need more setup than is provided in the normal console init | ||
| 78 | */ | ||
| 79 | int platform_specific_init(void) | ||
| 80 | { | ||
| 81 | void *devp; | ||
| 82 | char devtype[MAX_PROP_LEN]; | ||
| 83 | char path[MAX_PATH_LEN]; | ||
| 84 | |||
| 85 | devp = finddevice("/chosen"); | ||
| 86 | if (devp == NULL) | ||
| 87 | return -1; | ||
| 88 | |||
| 89 | if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) { | ||
| 90 | devp = finddevice(path); | ||
| 91 | if (devp == NULL) | ||
| 92 | return -1; | ||
| 93 | |||
| 94 | if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0) | ||
| 95 | && !strcmp(devtype, "serial") | ||
| 96 | && (dt_is_compatible(devp, "ns16550"))) | ||
| 97 | virtex_ns16550_console_init(devp); | ||
| 98 | } | ||
| 99 | return 0; | ||
| 100 | } | ||
