1/* 2 * AU1X00 UART support 3 * 4 * Hardcoded to UART 0 for now 5 * Speed and options also hardcoded to 115200 8N1 6 * 7 * Copyright (c) 2003 Thomas.Lange@corelatus.se 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 */ 11 12#include <config.h> 13#include <common.h> 14#include <mach/au1x00.h> 15#include <serial.h> 16#include <linux/compiler.h> 17 18/****************************************************************************** 19* 20* serial_init - initialize a channel 21* 22* This routine initializes the number of data bits, parity 23* and set the selected baud rate. Interrupts are disabled. 24* Set the modem control signals if the option is selected. 25* 26* RETURNS: N/A 27*/ 28 29static int au1x00_serial_init(void) 30{ 31 volatile u32 *uart_fifoctl = (volatile u32*)(UART0_ADDR+UART_FCR); 32 volatile u32 *uart_enable = (volatile u32*)(UART0_ADDR+UART_ENABLE); 33 34 /* Enable clocks first */ 35 *uart_enable = UART_EN_CE; 36 37 /* Then release reset */ 38 /* Must release reset before setting other regs */ 39 *uart_enable = UART_EN_CE|UART_EN_E; 40 41 /* Activate fifos, reset tx and rx */ 42 /* Set tx trigger level to 12 */ 43 *uart_fifoctl = UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR| 44 UART_FCR_CLEAR_XMIT|UART_FCR_T_TRIGGER_12; 45 46 serial_setbrg(); 47 48 return 0; 49} 50 51 52static void au1x00_serial_setbrg(void) 53{ 54 volatile u32 *uart_clk = (volatile u32*)(UART0_ADDR+UART_CLK); 55 volatile u32 *uart_lcr = (volatile u32*)(UART0_ADDR+UART_LCR); 56 volatile u32 *sys_powerctrl = (u32 *)SYS_POWERCTRL; 57 int sd; 58 int divisorx2; 59 60 /* sd is system clock divisor */ 61 /* see section 10.4.5 in au1550 datasheet */ 62 sd = (*sys_powerctrl & 0x03) + 2; 63 64 /* calulate 2x baudrate and round */ 65 divisorx2 = ((CONFIG_SYS_MIPS_TIMER_FREQ/(sd * 16 * CONFIG_BAUDRATE))); 66 67 if (divisorx2 & 0x01) 68 divisorx2 = divisorx2 + 1; 69 70 *uart_clk = divisorx2 / 2; 71 72 /* Set parity, stop bits and word length to 8N1 */ 73 *uart_lcr = UART_LCR_WLEN8; 74} 75 76static void au1x00_serial_putc(const char c) 77{ 78 volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR); 79 volatile u32 *uart_tx = (volatile u32*)(UART0_ADDR+UART_TX); 80 81 if (c == '\n') 82 au1x00_serial_putc('\r'); 83 84 /* Wait for fifo to shift out some bytes */ 85 while((*uart_lsr&UART_LSR_THRE)==0); 86 87 *uart_tx = (u32)c; 88} 89 90static int au1x00_serial_getc(void) 91{ 92 volatile u32 *uart_rx = (volatile u32*)(UART0_ADDR+UART_RX); 93 char c; 94 95 while (!serial_tstc()); 96 97 c = (*uart_rx&0xFF); 98 return c; 99} 100 101static int au1x00_serial_tstc(void) 102{ 103 volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR); 104 105 if(*uart_lsr&UART_LSR_DR){ 106 /* Data in rfifo */ 107 return(1); 108 } 109 return 0; 110} 111 112static struct serial_device au1x00_serial_drv = { 113 .name = "au1x00_serial", 114 .start = au1x00_serial_init, 115 .stop = NULL, 116 .setbrg = au1x00_serial_setbrg, 117 .putc = au1x00_serial_putc, 118 .puts = default_serial_puts, 119 .getc = au1x00_serial_getc, 120 .tstc = au1x00_serial_tstc, 121}; 122 123void au1x00_serial_initialize(void) 124{ 125 serial_register(&au1x00_serial_drv); 126} 127 128__weak struct serial_device *default_serial_console(void) 129{ 130 return &au1x00_serial_drv; 131} 132