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 28static 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*/ 79int 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} 101