1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2011-2012, 2016 Robert N. M. Watson
5  * All rights reserved.
6  *
7  * This software was developed by SRI International and the University of
8  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9  * ("CTSRD"), as part of the DARPA CRASH research programme.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include <sys/param.h>
37 #include <sys/bus.h>
38 #include <sys/cons.h>
39 #include <sys/endian.h>
40 #include <sys/kdb.h>
41 #include <sys/rman.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/reboot.h>
45 #include <sys/sysctl.h>
46 #include <sys/tty.h>
47 
48 #include <ddb/ddb.h>
49 
50 #include <machine/atomic.h>
51 #include <machine/bus.h>
52 
53 #include <dev/altera/jtag_uart/altera_jtag_uart.h>
54 
55 /*
56  * If one of the Altera JTAG UARTs is currently the system console, register
57  * it here.
58  */
59 static struct altera_jtag_uart_softc	*aju_cons_sc;
60 
61 static tsw_outwakeup_t	aju_outwakeup;
62 static void		aju_ac_callout(void *);
63 static void		aju_io_callout(void *);
64 
65 static struct ttydevsw aju_ttydevsw = {
66 	.tsw_flags	= TF_NOPREFIX,
67 	.tsw_outwakeup	= aju_outwakeup,
68 };
69 
70 /*
71  * When polling for the AC bit, the number of times we have to not see it
72  * before assuming JTAG has disappeared on us.  By default, four seconds.
73  */
74 #define	AJU_JTAG_MAXMISS		20
75 
76 /*
77  * Polling intervals for input/output and JTAG connection events.
78  */
79 #define	AJU_IO_POLLINTERVAL		(hz/100)
80 #define	AJU_AC_POLLINTERVAL		(hz/5)
81 
82 /*
83  * Statistics on JTAG removal events when sending, for debugging purposes
84  * only.
85  */
86 static u_int aju_jtag_vanished;
87 SYSCTL_UINT(_debug, OID_AUTO, aju_jtag_vanished, CTLFLAG_RW,
88     &aju_jtag_vanished, 0, "Number of times JTAG has vanished");
89 
90 static u_int aju_jtag_appeared;
91 SYSCTL_UINT(_debug, OID_AUTO, aju_jtag_appeared, CTLFLAG_RW,
92     &aju_jtag_appeared, 0, "Number of times JTAG has appeared");
93 
94 SYSCTL_INT(_debug, OID_AUTO, aju_cons_jtag_present, CTLFLAG_RW,
95     &aju_cons_jtag_present, 0, "JTAG console present flag");
96 
97 SYSCTL_UINT(_debug, OID_AUTO, aju_cons_jtag_missed, CTLFLAG_RW,
98     &aju_cons_jtag_missed, 0, "JTAG console missed counter");
99 
100 /*
101  * Interrupt-related statistics.
102  */
103 static u_int aju_intr_readable_enabled;
104 SYSCTL_UINT(_debug, OID_AUTO, aju_intr_readable_enabled, CTLFLAG_RW,
105     &aju_intr_readable_enabled, 0, "Number of times read interrupt enabled");
106 
107 static u_int aju_intr_writable_disabled;
108 SYSCTL_UINT(_debug, OID_AUTO, aju_intr_writable_disabled, CTLFLAG_RW,
109     &aju_intr_writable_disabled, 0,
110     "Number of times write interrupt disabled");
111 
112 static u_int aju_intr_writable_enabled;
113 SYSCTL_UINT(_debug, OID_AUTO, aju_intr_writable_enabled, CTLFLAG_RW,
114     &aju_intr_writable_enabled, 0,
115     "Number of times write interrupt enabled");
116 
117 static u_int aju_intr_disabled;
118 SYSCTL_UINT(_debug, OID_AUTO, aju_intr_disabled, CTLFLAG_RW,
119     &aju_intr_disabled, 0, "Number of times write interrupt disabled");
120 
121 static u_int aju_intr_read_count;
122 SYSCTL_UINT(_debug, OID_AUTO, aju_intr_read_count, CTLFLAG_RW,
123     &aju_intr_read_count, 0, "Number of times read interrupt fired");
124 
125 static u_int aju_intr_write_count;
126 SYSCTL_UINT(_debug, OID_AUTO, aju_intr_write_count, CTLFLAG_RW,
127     &aju_intr_write_count, 0, "Number of times write interrupt fired");
128 
129 /*
130  * Low-level read and write register routines; the Altera UART is little
131  * endian, so we byte swap 32-bit reads and writes.
132  */
133 static inline uint32_t
134 aju_data_read(struct altera_jtag_uart_softc *sc)
135 {
136 
137 	return (le32toh(bus_read_4(sc->ajus_mem_res,
138 	    ALTERA_JTAG_UART_DATA_OFF)));
139 }
140 
141 static inline void
142 aju_data_write(struct altera_jtag_uart_softc *sc, uint32_t v)
143 {
144 
145 	bus_write_4(sc->ajus_mem_res, ALTERA_JTAG_UART_DATA_OFF, htole32(v));
146 }
147 
148 static inline uint32_t
149 aju_control_read(struct altera_jtag_uart_softc *sc)
150 {
151 
152 	return (le32toh(bus_read_4(sc->ajus_mem_res,
153 	    ALTERA_JTAG_UART_CONTROL_OFF)));
154 }
155 
156 static inline void
157 aju_control_write(struct altera_jtag_uart_softc *sc, uint32_t v)
158 {
159 
160 	bus_write_4(sc->ajus_mem_res, ALTERA_JTAG_UART_CONTROL_OFF,
161 	    htole32(v));
162 }
163 
164 /*
165  * Slightly higher-level routines aware of buffering and flow control.
166  */
167 static inline int
168 aju_writable(struct altera_jtag_uart_softc *sc)
169 {
170 
171 	return ((aju_control_read(sc) &
172 	    ALTERA_JTAG_UART_CONTROL_WSPACE) != 0);
173 }
174 
175 static inline int
176 aju_readable(struct altera_jtag_uart_softc *sc)
177 {
178 	uint32_t v;
179 
180 	AJU_LOCK_ASSERT(sc);
181 
182 	if (*sc->ajus_buffer_validp)
183 		return (1);
184 	v = aju_data_read(sc);
185 	if ((v & ALTERA_JTAG_UART_DATA_RVALID) != 0) {
186 		*sc->ajus_buffer_validp = 1;
187 		*sc->ajus_buffer_datap = (v & ALTERA_JTAG_UART_DATA_DATA);
188 		return (1);
189 	}
190 	return (0);
191 }
192 
193 static char
194 aju_read(struct altera_jtag_uart_softc *sc)
195 {
196 
197 	AJU_LOCK_ASSERT(sc);
198 
199 	while (!aju_readable(sc));
200 	*sc->ajus_buffer_validp = 0;
201 	return (*sc->ajus_buffer_datap);
202 }
203 
204 /*
205  * Routines for enabling and disabling interrupts for read and write.
206  */
207 static void
208 aju_intr_readable_enable(struct altera_jtag_uart_softc *sc)
209 {
210 	uint32_t v;
211 
212 	AJU_LOCK_ASSERT(sc);
213 
214 	atomic_add_int(&aju_intr_readable_enabled, 1);
215 	v = aju_control_read(sc);
216 	v |= ALTERA_JTAG_UART_CONTROL_RE;
217 	aju_control_write(sc, v);
218 }
219 
220 static void
221 aju_intr_writable_enable(struct altera_jtag_uart_softc *sc)
222 {
223 	uint32_t v;
224 
225 	AJU_LOCK_ASSERT(sc);
226 
227 	atomic_add_int(&aju_intr_writable_enabled, 1);
228 	v = aju_control_read(sc);
229 	v |= ALTERA_JTAG_UART_CONTROL_WE;
230 	aju_control_write(sc, v);
231 }
232 
233 static void
234 aju_intr_writable_disable(struct altera_jtag_uart_softc *sc)
235 {
236 	uint32_t v;
237 
238 	AJU_LOCK_ASSERT(sc);
239 
240 	atomic_add_int(&aju_intr_writable_disabled, 1);
241 	v = aju_control_read(sc);
242 	v &= ~ALTERA_JTAG_UART_CONTROL_WE;
243 	aju_control_write(sc, v);
244 }
245 
246 static void
247 aju_intr_disable(struct altera_jtag_uart_softc *sc)
248 {
249 	uint32_t v;
250 
251 	AJU_LOCK_ASSERT(sc);
252 
253 	atomic_add_int(&aju_intr_disabled, 1);
254 	v = aju_control_read(sc);
255 	v &= ~(ALTERA_JTAG_UART_CONTROL_RE | ALTERA_JTAG_UART_CONTROL_WE);
256 	aju_control_write(sc, v);
257 }
258 
259 /*
260  * The actual work of checking for, and handling, available reads.  This is
261  * used in both polled and interrupt-driven modes, as JTAG UARTs may be hooked
262  * up with, or without, IRQs allocated.
263  */
264 static void
265 aju_handle_input(struct altera_jtag_uart_softc *sc, struct tty *tp)
266 {
267 	int c;
268 
269 	tty_assert_locked(tp);
270 	AJU_LOCK_ASSERT(sc);
271 
272 	while (aju_readable(sc)) {
273 		c = aju_read(sc);
274 		AJU_UNLOCK(sc);
275 #ifdef KDB
276 		if (sc->ajus_flags & ALTERA_JTAG_UART_FLAG_CONSOLE)
277 			kdb_alt_break(c, &sc->ajus_alt_break_state);
278 #endif
279 		ttydisc_rint(tp, c, 0);
280 		AJU_LOCK(sc);
281 	}
282 	AJU_UNLOCK(sc);
283 	ttydisc_rint_done(tp);
284 	AJU_LOCK(sc);
285 }
286 
287 /*
288  * Send output to the UART until either there's none left to send, or we run
289  * out of room and need to await an interrupt so that we can start sending
290  * again.
291  *
292  * XXXRW: It would be nice to query WSPACE at the beginning and write to the
293  * FIFO in bugger chunks.
294  */
295 static void
296 aju_handle_output(struct altera_jtag_uart_softc *sc, struct tty *tp)
297 {
298 	uint32_t v;
299 	uint8_t ch;
300 
301 	tty_assert_locked(tp);
302 	AJU_LOCK_ASSERT(sc);
303 
304 	AJU_UNLOCK(sc);
305 	while (ttydisc_getc_poll(tp) != 0) {
306 		AJU_LOCK(sc);
307 		if (*sc->ajus_jtag_presentp == 0) {
308 			/*
309 			 * If JTAG is not present, then we will drop this
310 			 * character instead of perhaps scheduling an
311 			 * interrupt to let us know when there is buffer
312 			 * space.  Otherwise we might get a write interrupt
313 			 * later even though we aren't interested in sending
314 			 * anymore.  Loop to drain TTY-layer buffer.
315 			 */
316 			AJU_UNLOCK(sc);
317 			if (ttydisc_getc(tp, &ch, sizeof(ch)) !=
318 			    sizeof(ch))
319 				panic("%s: ttydisc_getc", __func__);
320 			continue;
321 		}
322 		v = aju_control_read(sc);
323 		if ((v & ALTERA_JTAG_UART_CONTROL_WSPACE) == 0) {
324 			if (sc->ajus_irq_res != NULL &&
325 			    (v & ALTERA_JTAG_UART_CONTROL_WE) == 0)
326 				aju_intr_writable_enable(sc);
327 			return;
328 		}
329 		AJU_UNLOCK(sc);
330 		if (ttydisc_getc(tp, &ch, sizeof(ch)) != sizeof(ch))
331 			panic("%s: ttydisc_getc 2", __func__);
332 		AJU_LOCK(sc);
333 
334 		/*
335 		 * XXXRW: There is a slight race here in which we test for
336 		 * writability, drop the lock, get the character from the tty
337 		 * layer, re-acquire the lock, and then write.  It's possible
338 		 * for other code -- specifically, the low-level console -- to
339 		 * have* written in the mean time, which might mean that there
340 		 * is no longer space.  The BERI memory bus will cause this
341 		 * write to block, wedging the processor until space is
342 		 * available -- which could be a while if JTAG is not
343 		 * attached!
344 		 *
345 		 * The 'easy' fix is to drop the character if WSPACE has
346 		 * become unset.  Not sure what the 'hard' fix is.
347 		 */
348 		aju_data_write(sc, ch);
349 		AJU_UNLOCK(sc);
350 	}
351 	AJU_LOCK(sc);
352 
353 	/*
354 	 * If interrupts are configured, and there's no data to write, but we
355 	 * had previously enabled write interrupts, disable them now.
356 	 */
357 	v = aju_control_read(sc);
358 	if (sc->ajus_irq_res != NULL && (v & ALTERA_JTAG_UART_CONTROL_WE) != 0)
359 		aju_intr_writable_disable(sc);
360 }
361 
362 static void
363 aju_outwakeup(struct tty *tp)
364 {
365 	struct altera_jtag_uart_softc *sc = tty_softc(tp);
366 
367 	tty_assert_locked(tp);
368 
369 	AJU_LOCK(sc);
370 	aju_handle_output(sc, tp);
371 	AJU_UNLOCK(sc);
372 }
373 
374 static void
375 aju_io_callout(void *arg)
376 {
377 	struct altera_jtag_uart_softc *sc = arg;
378 	struct tty *tp = sc->ajus_ttyp;
379 
380 	tty_lock(tp);
381 	AJU_LOCK(sc);
382 
383 	/*
384 	 * It would be convenient if we could share code with aju_intr() here
385 	 * by testing the control register for ALTERA_JTAG_UART_CONTROL_RI and
386 	 * ALTERA_JTAG_UART_CONTROL_WI.  Unfortunately, it's not clear that
387 	 * this is supported, so do all the work to poll for both input and
388 	 * output.
389 	 */
390 	aju_handle_input(sc, tp);
391 	aju_handle_output(sc, tp);
392 
393 	/*
394 	 * Reschedule next poll attempt.  There's some argument that we should
395 	 * do adaptive polling based on the expectation of I/O: is something
396 	 * pending in the output buffer, or have we recently had input, but we
397 	 * don't.
398 	 */
399 	callout_reset(&sc->ajus_io_callout, AJU_IO_POLLINTERVAL,
400 	    aju_io_callout, sc);
401 	AJU_UNLOCK(sc);
402 	tty_unlock(tp);
403 }
404 
405 static void
406 aju_ac_callout(void *arg)
407 {
408 	struct altera_jtag_uart_softc *sc = arg;
409 	struct tty *tp = sc->ajus_ttyp;
410 	uint32_t v;
411 
412 	tty_lock(tp);
413 	AJU_LOCK(sc);
414 	v = aju_control_read(sc);
415 	if (v & ALTERA_JTAG_UART_CONTROL_AC) {
416 		v &= ~ALTERA_JTAG_UART_CONTROL_AC;
417 		aju_control_write(sc, v);
418 		if (*sc->ajus_jtag_presentp == 0) {
419 			*sc->ajus_jtag_presentp = 1;
420 			atomic_add_int(&aju_jtag_appeared, 1);
421 			aju_handle_output(sc, tp);
422 		}
423 
424 		/* Any hit eliminates all recent misses. */
425 		*sc->ajus_jtag_missedp = 0;
426 	} else if (*sc->ajus_jtag_presentp != 0) {
427 		/*
428 		 * If we've exceeded our tolerance for misses, mark JTAG as
429 		 * disconnected and drain output.  Otherwise, bump the miss
430 		 * counter.
431 		 */
432 		if (*sc->ajus_jtag_missedp > AJU_JTAG_MAXMISS) {
433 			*sc->ajus_jtag_presentp = 0;
434 			atomic_add_int(&aju_jtag_vanished, 1);
435 			aju_handle_output(sc, tp);
436 		} else
437 			(*sc->ajus_jtag_missedp)++;
438 	}
439 	callout_reset(&sc->ajus_ac_callout, AJU_AC_POLLINTERVAL,
440 	    aju_ac_callout, sc);
441 	AJU_UNLOCK(sc);
442 	tty_unlock(tp);
443 }
444 
445 static void
446 aju_intr(void *arg)
447 {
448 	struct altera_jtag_uart_softc *sc = arg;
449 	struct tty *tp = sc->ajus_ttyp;
450 	uint32_t v;
451 
452 	tty_lock(tp);
453 	AJU_LOCK(sc);
454 	v = aju_control_read(sc);
455 	if (v & ALTERA_JTAG_UART_CONTROL_RI) {
456 		atomic_add_int(&aju_intr_read_count, 1);
457 		aju_handle_input(sc, tp);
458 	}
459 	if (v & ALTERA_JTAG_UART_CONTROL_WI) {
460 		atomic_add_int(&aju_intr_write_count, 1);
461 		aju_handle_output(sc, tp);
462 	}
463 	AJU_UNLOCK(sc);
464 	tty_unlock(tp);
465 }
466 
467 int
468 altera_jtag_uart_attach(struct altera_jtag_uart_softc *sc)
469 {
470 	struct tty *tp;
471 	int error;
472 
473 	AJU_LOCK_INIT(sc);
474 
475 	/*
476 	 * XXXRW: Currently, we detect the console solely based on it using a
477 	 * reserved address, and borrow console-level locks and buffer if so.
478 	 * Is there a better way?
479 	 */
480 	if (rman_get_start(sc->ajus_mem_res) == BERI_UART_BASE) {
481 		sc->ajus_lockp = &aju_cons_lock;
482 		sc->ajus_buffer_validp = &aju_cons_buffer_valid;
483 		sc->ajus_buffer_datap = &aju_cons_buffer_data;
484 		sc->ajus_jtag_presentp = &aju_cons_jtag_present;
485 		sc->ajus_jtag_missedp = &aju_cons_jtag_missed;
486 		sc->ajus_flags |= ALTERA_JTAG_UART_FLAG_CONSOLE;
487 	} else {
488 		sc->ajus_lockp = &sc->ajus_lock;
489 		sc->ajus_buffer_validp = &sc->ajus_buffer_valid;
490 		sc->ajus_buffer_datap = &sc->ajus_buffer_data;
491 		sc->ajus_jtag_presentp = &sc->ajus_jtag_present;
492 		sc->ajus_jtag_missedp = &sc->ajus_jtag_missed;
493 	}
494 
495 	/*
496 	 * Disable interrupts regardless of whether or not we plan to use
497 	 * them.  We will register an interrupt handler now if they will be
498 	 * used, but not re-enable intil later once the remainder of the tty
499 	 * layer is properly initialised, as we're not ready for input yet.
500 	 */
501 	AJU_LOCK(sc);
502 	aju_intr_disable(sc);
503 	AJU_UNLOCK(sc);
504 	if (sc->ajus_irq_res != NULL) {
505 		error = bus_setup_intr(sc->ajus_dev, sc->ajus_irq_res,
506 		    INTR_ENTROPY | INTR_TYPE_TTY | INTR_MPSAFE, NULL,
507 		    aju_intr, sc, &sc->ajus_irq_cookie);
508 		if (error) {
509 			device_printf(sc->ajus_dev,
510 			    "could not activate interrupt\n");
511 			AJU_LOCK_DESTROY(sc);
512 			return (error);
513 		}
514 	}
515 	tp = sc->ajus_ttyp = tty_alloc(&aju_ttydevsw, sc);
516 	if (sc->ajus_flags & ALTERA_JTAG_UART_FLAG_CONSOLE) {
517 		aju_cons_sc = sc;
518 		tty_init_console(tp, 0);
519 	}
520 	tty_makedev(tp, NULL, "%s%d", AJU_TTYNAME, sc->ajus_unit);
521 
522 	/*
523 	 * If we will be using interrupts, enable them now; otherwise, start
524 	 * polling.  From this point onwards, input can arrive.
525 	 */
526 	if (sc->ajus_irq_res != NULL) {
527 		AJU_LOCK(sc);
528 		aju_intr_readable_enable(sc);
529 		AJU_UNLOCK(sc);
530 	} else {
531 		callout_init(&sc->ajus_io_callout, 1);
532 		callout_reset(&sc->ajus_io_callout, AJU_IO_POLLINTERVAL,
533 		    aju_io_callout, sc);
534 	}
535 	callout_init(&sc->ajus_ac_callout, 1);
536 	callout_reset(&sc->ajus_ac_callout, AJU_AC_POLLINTERVAL,
537 	    aju_ac_callout, sc);
538 	return (0);
539 }
540 
541 void
542 altera_jtag_uart_detach(struct altera_jtag_uart_softc *sc)
543 {
544 	struct tty *tp = sc->ajus_ttyp;
545 
546 	/*
547 	 * If we're using interrupts, disable and release the interrupt
548 	 * handler now.  Otherwise drain the polling timeout.
549 	 */
550 	if (sc->ajus_irq_res != NULL) {
551 		AJU_LOCK(sc);
552 		aju_intr_disable(sc);
553 		AJU_UNLOCK(sc);
554 		bus_teardown_intr(sc->ajus_dev, sc->ajus_irq_res,
555 		    sc->ajus_irq_cookie);
556 	} else
557 		callout_drain(&sc->ajus_io_callout);
558 	callout_drain(&sc->ajus_ac_callout);
559 	if (sc->ajus_flags & ALTERA_JTAG_UART_FLAG_CONSOLE)
560 		aju_cons_sc = NULL;
561 	tty_lock(tp);
562 	tty_rel_gone(tp);
563 	AJU_LOCK_DESTROY(sc);
564 }
565