]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/mips/beri/common/altera_jtag_uart.c
Re-sync loader.mk and ficl.mk to where they should be
[FreeBSD/FreeBSD.git] / stand / mips / beri / common / altera_jtag_uart.c
1 /*-
2  * Copyright (c) 2011, 2013 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7  * ("CTSRD"), as part of the DARPA CRASH research programme.
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  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 #include "util.h"
34 #include "mips.h"
35
36 /*-
37  * Routines for interacting with the CHERI console UART.  Programming details
38  * from the June 2011 "Embedded Peripherals User Guide" by Altera
39  * Corporation, tables 6-2 (JTAG UART Core Register Map), 6-3 (Data Register
40  * Bits), and 6-4 (Control Register Bits).
41  *
42  * Hard-coded physical address for the first JTAG UART -- true on all BERI and
43  * CHERI boards.
44  */
45 #define CHERI_UART_BASE         0x7f000000      /* JTAG UART */
46
47 /*
48  *
49  * Offsets of data and control registers relative to the base.  Altera
50  * conventions are maintained in CHERI.
51  */
52 #define ALTERA_JTAG_UART_DATA_OFF       0x00000000
53 #define ALTERA_JTAG_UART_CONTROL_OFF    0x00000004
54
55 /*
56  * Offset 0: 'data' register -- bits 31-16 (RAVAIL), 15 (RVALID),
57  * 14-8 (Reserved), 7-0 (DATA).
58  *
59  * DATA - One byte read or written.
60  * RAVAIL - Bytes available to read (excluding the current byte).
61  * RVALID - Whether the byte in DATA is valid.
62  */
63 #define ALTERA_JTAG_UART_DATA_DATA              0x000000ff
64 #define ALTERA_JTAG_UART_DATA_RESERVED          0x00007f00
65 #define ALTERA_JTAG_UART_DATA_RVALID            0x00008000
66 #define ALTERA_JTAG_UART_DATA_RAVAIL            0xffff0000
67 #define ALTERA_JTAG_UART_DATA_RAVAIL_SHIFT      16
68
69 /*-
70  * Offset 1: 'control' register -- bits 31-16 (WSPACE), 15-11 (Reserved),
71  * 10 (AC), 9 (WI), 8 (RI), 7..2 (Reserved), 1 (WE), 0 (RE).
72  *
73  * RE - Enable read interrupts.
74  * WE - Enable write interrupts.
75  * RI - Read interrupt pending.
76  * WI - Write interrupt pending.
77  * AC - Activity bit; set to '1' to clear to '0'.
78  * WSPACE - Space available in the write FIFO.
79  */
80 #define ALTERA_JTAG_UART_CONTROL_RE             0x00000001
81 #define ALTERA_JTAG_UART_CONTROL_WE             0x00000002
82 #define ALTERA_JTAG_UART_CONTROL_RESERVED0      0x000000fc
83 #define ALTERA_JTAG_UART_CONTROL_RI             0x00000100
84 #define ALTERA_JTAG_UART_CONTROL_WI             0x00000200
85 #define ALTERA_JTAG_UART_CONTROL_AC             0x00000400
86 #define ALTERA_JTAG_UART_CONTROL_RESERVED1      0x0000f800
87 #define ALTERA_JTAG_UART_CONTROL_WSPACE         0xffff0000
88 #define ALTERA_JTAG_UART_CONTROL_WSPACE_SHIFT   16
89
90 /*
91  * One-byte buffer as we can't check whether the UART is readable without
92  * actually reading from it.
93  */
94 static char     buffer_data;
95 static int      buffer_valid;
96
97 /*
98  * Low-level read and write register routines; the Altera UART is little
99  * endian, so we byte swap 32-bit reads and writes.
100  */
101 static inline uint32_t
102 uart_data_read(void)
103 {
104
105         return (mips_ioread_uint32le(mips_phys_to_uncached(CHERI_UART_BASE +
106             ALTERA_JTAG_UART_DATA_OFF)));
107 }
108
109 static inline void
110 uart_data_write(uint32_t v)
111 {
112
113         mips_iowrite_uint32le(mips_phys_to_uncached(CHERI_UART_BASE +
114             ALTERA_JTAG_UART_DATA_OFF), v);
115 }
116
117 static inline uint32_t
118 uart_control_read(void)
119 {
120
121         return (mips_ioread_uint32le(mips_phys_to_uncached(CHERI_UART_BASE +
122             ALTERA_JTAG_UART_CONTROL_OFF)));
123 }
124
125 static inline void
126 uart_control_write(uint32_t v)
127 {
128
129         mips_iowrite_uint32le(mips_phys_to_uncached(CHERI_UART_BASE +
130             ALTERA_JTAG_UART_DATA_OFF), v);
131 }
132
133 static int
134 uart_writable(void)
135 {
136
137         return ((uart_control_read() & ALTERA_JTAG_UART_CONTROL_WSPACE) != 0);
138 }
139
140 static int
141 uart_readable(void)
142 {
143         uint32_t v;
144
145         if (buffer_valid)
146                 return (1);
147         v = uart_data_read();
148         if ((v & ALTERA_JTAG_UART_DATA_RVALID) != 0) {
149                 buffer_valid = 1;
150                 buffer_data = (v & ALTERA_JTAG_UART_DATA_DATA);
151         }
152         return (0);
153 }
154
155 int
156 keyhit(int seconds)
157 {
158         register_t stoptime;
159
160         stoptime = cp0_count_get() + seconds * 100000000;       /* 100 MHz. */
161         do {
162                 if (uart_readable())
163                         return (1);
164         } while (cp0_count_get() < stoptime);
165         return (0);
166 }
167
168 int
169 getc(void)
170 {
171
172         while (!(uart_readable()));
173         buffer_valid = 0;
174         return (buffer_data);
175 }
176
177 void
178 putc(int ch)
179 {
180
181         uart_data_write(ch);
182 }