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 34/* Force cache miss each time a serial controller reg is read */ 35#define CACHE_BYPASS 1 36 37#ifdef CACHE_BYPASS 38#define READ_BYTE(var) SPARC_NOCACHE_READ_BYTE((unsigned int)&(var)) 39#define READ_HWORD(var) SPARC_NOCACHE_READ_HWORD((unsigned int)&(var)) 40#define READ_WORD(var) SPARC_NOCACHE_READ((unsigned int)&(var)) 41#define READ_DWORD(var) SPARC_NOCACHE_READ_DWORD((unsigned int)&(var)) 42#endif 43 44static int leon2_serial_init(void) 45{ 46 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; 47 LEON2_Uart_regs *regs; 48 unsigned int tmp; 49 50 /* Init LEON2 UART 51 * 52 * Set scaler / baud rate 53 * 54 * Receiver & transmitter enable 55 */ 56#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 57 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; 58#else 59 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; 60#endif 61 62 regs->UART_Scaler = CONFIG_SYS_LEON2_UART1_SCALER; 63 64 /* Let bit 11 be unchanged (debug bit for GRMON) */ 65 tmp = READ_WORD(regs->UART_Control); 66 67 regs->UART_Control = ((tmp & LEON2_UART_CTRL_DBG) | 68 (LEON2_UART1_LOOPBACK_ENABLE << 7) | 69 (LEON2_UART1_FLOWCTRL_ENABLE << 6) | 70 (LEON2_UART1_PARITY_ENABLE << 5) | 71 (LEON2_UART1_ODDPAR_ENABLE << 4) | 72 LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE); 73 74 return 0; 75} 76 77static void leon2_serial_putc_raw(const char c) 78{ 79 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; 80 LEON2_Uart_regs *regs; 81 82#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 83 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; 84#else 85 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; 86#endif 87 88 /* Wait for last character to go. */ 89 while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_THE)) ; 90 91 /* Send data */ 92 regs->UART_Channel = c; 93 94#ifdef LEON_DEBUG 95 /* Wait for data to be sent */ 96 while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_TSE)) ; 97#endif 98} 99 100static void leon2_serial_putc(const char c) 101{ 102 if (c == '\n') 103 leon2_serial_putc_raw('\r'); 104 105 leon2_serial_putc_raw(c); 106} 107 108static int leon2_serial_getc(void) 109{ 110 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; 111 LEON2_Uart_regs *regs; 112 113#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 114 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; 115#else 116 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; 117#endif 118 119 /* Wait for a character to arrive. */ 120 while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR)) ; 121 122 /* read data */ 123 return READ_WORD(regs->UART_Channel); 124} 125 126static int leon2_serial_tstc(void) 127{ 128 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; 129 LEON2_Uart_regs *regs; 130 131#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 132 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; 133#else 134 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; 135#endif 136 137 return (READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR); 138} 139 140/* set baud rate for uart */ 141static void leon2_serial_setbrg(void) 142{ 143 /* update baud rate settings, read it from gd->baudrate */ 144 unsigned int scaler; 145 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; 146 LEON2_Uart_regs *regs; 147 148#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 149 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; 150#else 151 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; 152#endif 153 154 if (gd->baudrate > 0) { 155 scaler = 156 (((CONFIG_SYS_CLK_FREQ * 10) / (gd->baudrate * 8)) - 157 5) / 10; 158 regs->UART_Scaler = scaler; 159 } 160} 161 162static struct serial_device leon2_serial_drv = { 163 .name = "leon2_serial", 164 .start = leon2_serial_init, 165 .stop = NULL, 166 .setbrg = leon2_serial_setbrg, 167 .putc = leon2_serial_putc, 168 .puts = default_serial_puts, 169 .getc = leon2_serial_getc, 170 .tstc = leon2_serial_tstc, 171}; 172 173void leon2_serial_initialize(void) 174{ 175 serial_register(&leon2_serial_drv); 176} 177 178__weak struct serial_device *default_serial_console(void) 179{ 180 return &leon2_serial_drv; 181} 182