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