1/* GRLIB APBUART Serial controller driver 2 * 3 * (C) Copyright 2008 4 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. 5 * 6 * See file CREDITS for list of people who contributed to this 7 * project. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of 12 * the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 22 * MA 02111-1307 USA 23 * 24 */ 25 26#include <common.h> 27#include <asm/processor.h> 28#include <asm/leon.h> 29#include <serial.h> 30#include <linux/compiler.h> 31 32DECLARE_GLOBAL_DATA_PTR; 33 34static int leon2_serial_init(void) 35{ 36 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; 37 LEON2_Uart_regs *regs; 38 unsigned int tmp; 39 40 /* Init LEON2 UART 41 * 42 * Set scaler / baud rate 43 * 44 * Receiver & transmitter enable 45 */ 46#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 47 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; 48#else 49 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; 50#endif 51 52 regs->UART_Scaler = CONFIG_SYS_LEON2_UART1_SCALER; 53 54 /* Let bit 11 be unchanged (debug bit for GRMON) */ 55 tmp = READ_WORD(regs->UART_Control); 56 57 regs->UART_Control = ((tmp & LEON2_UART_CTRL_DBG) | 58 (LEON2_UART1_LOOPBACK_ENABLE << 7) | 59 (LEON2_UART1_FLOWCTRL_ENABLE << 6) | 60 (LEON2_UART1_PARITY_ENABLE << 5) | 61 (LEON2_UART1_ODDPAR_ENABLE << 4) | 62 LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE); 63 64 return 0; 65} 66 67static void leon2_serial_putc_raw(const char c) 68{ 69 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; 70 LEON2_Uart_regs *regs; 71 72#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 73 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; 74#else 75 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; 76#endif 77 78 /* Wait for last character to go. */ 79 while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_THE)) ; 80 81 /* Send data */ 82 regs->UART_Channel = c; 83 84#ifdef LEON_DEBUG 85 /* Wait for data to be sent */ 86 while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_TSE)) ; 87#endif 88} 89 90static void leon2_serial_putc(const char c) 91{ 92 if (c == '\n') 93 leon2_serial_putc_raw('\r'); 94 95 leon2_serial_putc_raw(c); 96} 97 98static int leon2_serial_getc(void) 99{ 100 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; 101 LEON2_Uart_regs *regs; 102 103#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 104 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; 105#else 106 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; 107#endif 108 109 /* Wait for a character to arrive. */ 110 while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR)) ; 111 112 /* read data */ 113 return READ_WORD(regs->UART_Channel); 114} 115 116static int leon2_serial_tstc(void) 117{ 118 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; 119 LEON2_Uart_regs *regs; 120 121#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 122 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; 123#else 124 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; 125#endif 126 127 return (READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR); 128} 129 130/* set baud rate for uart */ 131static void leon2_serial_setbrg(void) 132{ 133 /* update baud rate settings, read it from gd->baudrate */ 134 unsigned int scaler; 135 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; 136 LEON2_Uart_regs *regs; 137 138#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 139 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; 140#else 141 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; 142#endif 143 144 if (gd->baudrate > 0) { 145 scaler = 146 (((CONFIG_SYS_CLK_FREQ * 10) / (gd->baudrate * 8)) - 147 5) / 10; 148 regs->UART_Scaler = scaler; 149 } 150} 151 152static struct serial_device leon2_serial_drv = { 153 .name = "leon2_serial", 154 .start = leon2_serial_init, 155 .stop = NULL, 156 .setbrg = leon2_serial_setbrg, 157 .putc = leon2_serial_putc, 158 .puts = default_serial_puts, 159 .getc = leon2_serial_getc, 160 .tstc = leon2_serial_tstc, 161}; 162 163void leon2_serial_initialize(void) 164{ 165 serial_register(&leon2_serial_drv); 166} 167 168__weak struct serial_device *default_serial_console(void) 169{ 170 return &leon2_serial_drv; 171} 172