1/*	$NetBSD: hd64465uart.c,v 1.21 2023/12/20 14:50:03 thorpej Exp $	*/
2
3/*-
4 * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
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 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: hd64465uart.c,v 1.21 2023/12/20 14:50:03 thorpej Exp $");
31
32#include "opt_kgdb.h"
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/reboot.h>
37#include <sys/device.h>
38#include <sys/kgdb.h>
39#include <sys/bus.h>
40
41#include <sys/termios.h>
42#include <dev/cons.h>
43#include <sys/conf.h>
44
45#include <machine/intr.h>
46#include <machine/console.h>
47
48#include <dev/ic/comvar.h>
49#include <dev/ic/comreg.h>
50
51#include <machine/debug.h>
52
53#include <hpcsh/dev/hd64465/hd64465var.h>
54#include <hpcsh/dev/hd64465/hd64465intcreg.h>
55#include <hpcsh/dev/hd64465/hd64465uartvar.h>
56#include <hpcsh/dev/hd64465/hd64465uartreg.h>
57
58STATIC struct hd64465uart_chip {
59	struct hpcsh_bus_space __tag_body;
60	bus_space_tag_t io_tag;
61	int console;
62} hd64465uart_chip;
63
64struct hd64465uart_softc {
65	struct com_softc sc_com;
66
67	struct hd64465uart_chip *sc_chip;
68	enum hd64465_module_id sc_module_id;
69};
70
71/* boot console */
72void hd64465uartcnprobe(struct consdev *);
73void hd64465uartcninit(struct consdev *);
74
75STATIC int hd64465uart_match(device_t, cfdata_t , void *);
76STATIC void hd64465uart_attach(device_t, device_t, void *);
77
78CFATTACH_DECL_NEW(hd64465uart, sizeof(struct hd64465uart_softc),
79    hd64465uart_match, hd64465uart_attach, NULL, NULL);
80
81STATIC void hd64465uart_init(void);
82STATIC uint8_t hd64465uart_read_1(void *, bus_space_handle_t, bus_size_t);
83STATIC void hd64465uart_write_1(void *, bus_space_handle_t, bus_size_t,
84    uint8_t);
85
86#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
87#ifndef COMCN_SPEED
88#define COMCN_SPEED	19200
89#endif
90
91void
92hd64465uartcnprobe(struct consdev *cp)
93{
94	extern struct cdevsw com_cdevsw;
95	int maj;
96
97	/* locate the major number */
98	maj = cdevsw_lookup_major(&com_cdevsw);
99
100	/* Initialize required fields. */
101	cp->cn_dev = makedev(maj, 0);
102	cp->cn_pri = CN_NORMAL;
103}
104
105void
106hd64465uartcninit(struct consdev *cp)
107{
108
109	hd64465uart_init();
110
111	comcnattach(hd64465uart_chip.io_tag, 0x0, COMCN_SPEED, COM_FREQ,
112	    COM_TYPE_NORMAL, CONMODE);
113
114	hd64465uart_chip.console = 1;
115}
116
117#ifdef KGDB
118int
119hd64465uart_kgdb_init(void)
120{
121
122	if (strcmp(kgdb_devname, "hd64465uart") != 0)
123		return (1);
124
125	if (hd64465uart_chip.console)
126		return (1);	/* can't share with console */
127
128	hd64465uart_init();
129
130	if (com_kgdb_attach(hd64465uart_chip.io_tag, 0x0, kgdb_rate,
131	    COM_FREQ, COM_TYPE_NORMAL, CONMODE) != 0) {
132		printf("%s: KGDB console open failed.\n", __func__);
133		return (1);
134	}
135
136	return (0);
137}
138#endif /* KGDB */
139
140int
141hd64465uart_match(device_t parent, cfdata_t cf, void *aux)
142{
143	struct hd64465_attach_args *ha = aux;
144
145	return (ha->ha_module_id == HD64465_MODULE_UART);
146}
147
148void
149hd64465uart_attach(device_t parent, device_t self, void *aux)
150{
151	struct hd64465_attach_args *ha = aux;
152	struct hd64465uart_softc *sc = device_private(self);
153	struct com_softc *csc = &sc->sc_com;
154	bus_space_handle_t ioh;
155
156	csc->sc_dev = self;
157	sc->sc_chip = &hd64465uart_chip;
158
159	sc->sc_module_id = ha->ha_module_id;
160
161	if (!sc->sc_chip->console)
162		hd64465uart_init();
163
164	bus_space_map(sc->sc_chip->io_tag, 0, 8, 0, &ioh);
165	com_init_regs(&csc->sc_regs, sc->sc_chip->io_tag, ioh, 0);
166	csc->sc_frequency = COM_FREQ;
167
168	/* supply clock XXX notyet */
169
170	/* sanity check */
171	if (!com_probe_subr(&csc->sc_regs)) {
172		aprint_error(": device problem. don't attach.\n");
173
174		/* stop clock XXX notyet */
175		return;
176	}
177
178	com_attach_subr(csc);
179
180	/* register interrupt handler */
181	hd64465_intr_establish(HD64465_UART, IST_LEVEL, IPL_TTY,
182	    comintr, self);
183}
184
185void
186hd64465uart_init(void)
187{
188
189	if (hd64465uart_chip.io_tag)
190		return;
191
192	hd64465uart_chip.io_tag = bus_space_create(
193		&hd64465uart_chip.__tag_body, "HD64465 UART I/O",
194		0xb0008000, 0); /* no extent */
195
196	/* override bus_space_read_1, bus_space_write_1 */
197	hd64465uart_chip.io_tag->hbs_r_1 = hd64465uart_read_1;
198	hd64465uart_chip.io_tag->hbs_w_1 = hd64465uart_write_1;
199}
200
201uint8_t
202hd64465uart_read_1(void *t, bus_space_handle_t h, bus_size_t ofs)
203{
204
205	return *(volatile uint8_t *)(h + (ofs << 1));
206}
207
208void
209hd64465uart_write_1(void *t, bus_space_handle_t h, bus_size_t ofs,
210    uint8_t val)
211{
212
213	*(volatile uint8_t *)(h + (ofs << 1)) = val;
214}
215