altera_jtag_uart.c revision 329175
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: stable/11/stand/mips/beri/common/altera_jtag_uart.c 329175 2018-02-12 17:44:35Z kevans $
31 */
32
33#include "stand.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 */
94static char	buffer_data;
95static 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 */
101static inline uint32_t
102uart_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
109static inline void
110uart_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
117static inline uint32_t
118uart_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
125static inline void
126uart_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
133static int
134uart_readable(void)
135{
136	uint32_t v;
137
138	if (buffer_valid)
139		return (1);
140	v = uart_data_read();
141	if ((v & ALTERA_JTAG_UART_DATA_RVALID) != 0) {
142		buffer_valid = 1;
143		buffer_data = (v & ALTERA_JTAG_UART_DATA_DATA);
144	}
145	return (0);
146}
147
148int
149keyhit(int seconds)
150{
151	register_t stoptime;
152
153	stoptime = cp0_count_get() + seconds * 100000000;	/* 100 MHz. */
154	do {
155		if (uart_readable())
156			return (1);
157	} while (cp0_count_get() < stoptime);
158	return (0);
159}
160
161int
162getc(void)
163{
164
165	while (!(uart_readable()));
166	buffer_valid = 0;
167	return (buffer_data);
168}
169
170void
171putc(int ch)
172{
173
174	uart_data_write(ch);
175}
176