1 /* $NetBSD: sscom.c,v 1.6 2013/11/04 21:57:26 christos Exp $ */ 2 3 4 /* 5 * Copyright (c) 2002, 2003 Fujitsu Component Limited 6 * Copyright (c) 2002, 2003 Genetec Corporation 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of The Fujitsu Component Limited nor the name of 18 * Genetec corporation may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC 22 * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * DISCLAIMED. IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC 26 * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 29 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 /* derived from ns16550.c */ 36 /* 37 * Copyright (c) 2002 Wasabi Systems, Inc. 38 * All rights reserved. 39 * 40 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed for the NetBSD Project by 53 * Wasabi Systems, Inc. 54 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 55 * or promote products derived from this software without specific prior 56 * written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 60 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 61 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 62 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 63 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 64 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 65 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 66 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 67 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 68 * POSSIBILITY OF SUCH DAMAGE. 69 */ 70 /* 71 * This file provides the cons_init() function and console I/O routines 72 * for boards that use built-in UART of Samsung's S3C2xx0 CPUs. 73 */ 74 75 #include <sys/types.h> 76 #include <arch/arm/s3c2xx0/s3c2xx0reg.h> 77 #ifdef CPU_S3C2410 78 #include <arch/arm/s3c2xx0/s3c2410reg.h> 79 #endif 80 #ifdef CPU_S3C2800 81 #include <arch/arm/s3c2xx0/s3c2800reg.h> 82 #endif 83 #include <lib/libsa/stand.h> 84 85 #include "board.h" 86 87 #ifndef SSCOM_TOLERANCE 88 #define SSCOM_TOLERANCE 30 /* XXX: baud rate tolerance, in 0.1% units */ 89 #endif 90 91 #define INB(x) *((volatile uint8_t *) ((CONADDR) + (x))) 92 #define INW(x) *((volatile uint32_t *) ((CONADDR) + (x))) 93 #define OUTB(x, v) (*((volatile uint8_t *) ((CONADDR) + (x))) = (v)) 94 #define OUTW(x, v) (*((volatile uint32_t *) ((CONADDR) + (x))) = (v)) 95 96 #define ISSET(t,f) ((t) & (f)) 97 98 static long get_com_freq(void); 99 100 static int 101 sscomspeed(long speed) 102 { 103 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ 104 105 int x, err; 106 long pclk = get_com_freq(); 107 108 if (speed <= 0) 109 return -1; 110 x = divrnd(pclk / 16, speed); 111 if (x <= 0) 112 return -1; 113 err = divrnd(((quad_t)pclk) * 1000 / 16, speed * x) - 1000; 114 if (err < 0) 115 err = -err; 116 if (err > SSCOM_TOLERANCE) 117 return -1; 118 return x-1; 119 120 #undef divrnd 121 } 122 123 void 124 cons_init(void) 125 { 126 int rate; 127 128 OUTW(SSCOM_UCON, 0); 129 OUTB(SSCOM_UFCON, UFCON_TXTRIGGER_8 | UFCON_RXTRIGGER_8 | 130 UFCON_TXFIFO_RESET | UFCON_RXFIFO_RESET | 131 UFCON_FIFO_ENABLE); 132 133 rate = sscomspeed(CONSPEED); 134 OUTW(SSCOM_UBRDIV, rate); 135 OUTW(SSCOM_ULCON, ULCON_PARITY_NONE|ULCON_LENGTH_8); 136 137 /* enable UART */ 138 OUTW(SSCOM_UCON, UCON_TXMODE_INT|UCON_RXMODE_INT); 139 OUTW(SSCOM_UMCON, UMCON_RTS); 140 } 141 142 #define sscom_rxrdy() (INB(SSCOM_UTRSTAT) & UTRSTAT_RXREADY) 143 144 int 145 getchar(void) 146 { 147 uint8_t stat __unused; 148 int c; 149 150 while (!sscom_rxrdy()) 151 /* spin */ ; 152 c = INB(SSCOM_URXH); 153 stat = INB(SSCOM_UERSTAT); /* XXX */ 154 155 return c; 156 } 157 158 static void 159 iputchar(int c) 160 { 161 uint32_t stat; 162 int timo; 163 164 /* Wait for any pending transmission to finish. */ 165 timo = 50000; 166 while (ISSET(stat = INW(SSCOM_UFSTAT), UFSTAT_TXFULL) && --timo) 167 /* spin */ ; 168 169 OUTB(SSCOM_UTXH, c); 170 171 #if 0 172 /* Wait for this transmission to complete. */ 173 timo = 1500000; 174 while (!ISSET(stat = INW(SSCOM_UFSTAT), UFSTAT_TXFULL) && --timo) 175 /* spin */ ; 176 #endif 177 } 178 179 void 180 putchar(int c) 181 { 182 183 if (c == '\n') 184 iputchar('\r'); 185 iputchar(c); 186 } 187 188 189 #define read_reg(addr) (*(volatile uint32_t *)(addr)) 190 191 static long 192 get_com_freq(void) 193 { 194 long clk; 195 #ifdef CPU_S3C2800 196 uint32_t pllcon = read_reg(S3C2800_CLKMAN_BASE+CLKMAN_PLLCON); 197 uint32_t div = read_reg(S3C2800_CLKMAN_BASE+CLKMAN_CLKCON); 198 #define HDIV CLKCON_HCLK 199 #define PDIV CLKCON_PCLK 200 #endif 201 #ifdef CPU_S3C2410 202 uint32_t pllcon = read_reg(S3C2410_CLKMAN_BASE+CLKMAN_MPLLCON); 203 uint32_t div = read_reg(S3C2410_CLKMAN_BASE+CLKMAN_CLKDIVN); 204 #define HDIV CLKDIVN_HDIVN 205 #define PDIV CLKDIVN_PDIVN 206 #endif 207 208 int mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT; 209 int pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT; 210 int sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT; 211 212 #if XTAL_CLK < 1000 /* in MHz */ 213 clk = (XTAL_CLK * 1000000 * (8 + mdiv)) / ((pdiv + 2) << sdiv); 214 #else /* in Hz */ 215 clk = (XTAL_CLK * (8 + mdiv)) / ((pdiv + 2) << sdiv); 216 #endif 217 218 /*printf( "M=%d P=%d S=%d\n", mdiv, pdiv, sdiv);*/ 219 220 if (div & HDIV) 221 clk /= 2; 222 if (div & PDIV) 223 clk /= 2; 224 225 return clk; 226 } 227