1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2003, 2004 Marcel Moolenaar
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 */
30
31#ifndef _DEV_UART_CPU_H_
32#define _DEV_UART_CPU_H_
33
34#include <sys/kdb.h>
35#include <sys/lock.h>
36#include <sys/mutex.h>
37
38struct uart_softc;
39
40/*
41 * Low-level operations for use by console and/or debug port support.
42 */
43struct uart_ops {
44	int (*probe)(struct uart_bas *);
45	void (*init)(struct uart_bas *, int, int, int, int);
46	void (*term)(struct uart_bas *);
47	void (*putc)(struct uart_bas *, int);
48	int (*rxready)(struct uart_bas *);
49	int (*getc)(struct uart_bas *, struct mtx *);
50};
51
52extern bus_space_tag_t uart_bus_space_io;
53extern bus_space_tag_t uart_bus_space_mem;
54
55/*
56 * Console and debug port device info.
57 */
58struct uart_devinfo {
59	SLIST_ENTRY(uart_devinfo) next;
60	struct uart_ops *ops;
61	struct uart_bas bas;
62	int	baudrate;
63	int	databits;
64	int	stopbits;
65	int	parity;
66	int	type;
67#define	UART_DEV_CONSOLE	0
68#define	UART_DEV_DBGPORT	1
69#define	UART_DEV_KEYBOARD	2
70	int	(*attach)(struct uart_softc*);
71	int	(*detach)(struct uart_softc*);
72	void	*cookie;		/* Type dependent use. */
73	struct mtx *hwmtx;
74	struct uart_softc *sc;		/* valid only from start of attach */
75};
76
77int uart_cpu_eqres(struct uart_bas *, struct uart_bas *);
78int uart_cpu_getdev(int, struct uart_devinfo *);
79
80int uart_getenv(int, struct uart_devinfo *, struct uart_class *);
81const char *uart_getname(struct uart_class *);
82struct uart_ops *uart_getops(struct uart_class *);
83int uart_getrange(struct uart_class *);
84u_int uart_getregshift(struct uart_class *);
85u_int uart_getregiowidth(struct uart_class *);
86
87void uart_add_sysdev(struct uart_devinfo *);
88
89/*
90 * Operations for low-level access to the UART. Primarily for use
91 * by console and debug port logic.
92 */
93
94static __inline void
95uart_lock(struct mtx *hwmtx)
96{
97	if (!kdb_active && hwmtx != NULL)
98		mtx_lock_spin(hwmtx);
99}
100
101static __inline void
102uart_unlock(struct mtx *hwmtx)
103{
104	if (!kdb_active && hwmtx != NULL)
105		mtx_unlock_spin(hwmtx);
106}
107
108static __inline int
109uart_probe(struct uart_devinfo *di)
110{
111	int res;
112
113	uart_lock(di->hwmtx);
114	res = di->ops->probe(&di->bas);
115	uart_unlock(di->hwmtx);
116	return (res);
117}
118
119static __inline void
120uart_init(struct uart_devinfo *di)
121{
122	uart_lock(di->hwmtx);
123	di->ops->init(&di->bas, di->baudrate, di->databits, di->stopbits,
124	    di->parity);
125	uart_unlock(di->hwmtx);
126}
127
128static __inline void
129uart_term(struct uart_devinfo *di)
130{
131	uart_lock(di->hwmtx);
132	di->ops->term(&di->bas);
133	uart_unlock(di->hwmtx);
134}
135
136static __inline void
137uart_putc(struct uart_devinfo *di, int c)
138{
139	uart_lock(di->hwmtx);
140	di->ops->putc(&di->bas, c);
141	uart_unlock(di->hwmtx);
142}
143
144static __inline int
145uart_rxready(struct uart_devinfo *di)
146{
147	int res;
148
149	uart_lock(di->hwmtx);
150	res = di->ops->rxready(&di->bas);
151	uart_unlock(di->hwmtx);
152	return (res);
153}
154
155static __inline int
156uart_poll(struct uart_devinfo *di)
157{
158	int res;
159
160	uart_lock(di->hwmtx);
161	if (di->ops->rxready(&di->bas))
162		res = di->ops->getc(&di->bas, NULL);
163	else
164		res = -1;
165	uart_unlock(di->hwmtx);
166	return (res);
167}
168
169static __inline int
170uart_getc(struct uart_devinfo *di)
171{
172
173	return (di->ops->getc(&di->bas, di->hwmtx));
174}
175
176void uart_grab(struct uart_devinfo *di);
177void uart_ungrab(struct uart_devinfo *di);
178
179#endif /* _DEV_UART_CPU_H_ */
180