xref: /netbsd-src/sys/arch/hpcsh/dev/hd64465/hd64465uart.c (revision 7433666e375b3ac4cc764df5a6726be98bc1cdd5)
1*7433666eSthorpej /*	$NetBSD: hd64465uart.c,v 1.21 2023/12/20 14:50:03 thorpej Exp $	*/
2b67fd34cSuch 
3b67fd34cSuch /*-
4b67fd34cSuch  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
5b67fd34cSuch  * All rights reserved.
6b67fd34cSuch  *
7b67fd34cSuch  * Redistribution and use in source and binary forms, with or without
8b67fd34cSuch  * modification, are permitted provided that the following conditions
9b67fd34cSuch  * are met:
10b67fd34cSuch  * 1. Redistributions of source code must retain the above copyright
11b67fd34cSuch  *    notice, this list of conditions and the following disclaimer.
12b67fd34cSuch  * 2. Redistributions in binary form must reproduce the above copyright
13b67fd34cSuch  *    notice, this list of conditions and the following disclaimer in the
14b67fd34cSuch  *    documentation and/or other materials provided with the distribution.
15b67fd34cSuch  *
16b67fd34cSuch  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17b67fd34cSuch  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18b67fd34cSuch  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19b67fd34cSuch  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20b67fd34cSuch  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21b67fd34cSuch  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22b67fd34cSuch  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23b67fd34cSuch  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24b67fd34cSuch  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25b67fd34cSuch  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26b67fd34cSuch  * POSSIBILITY OF SUCH DAMAGE.
27b67fd34cSuch  */
28b67fd34cSuch 
290c82163cSlukem #include <sys/cdefs.h>
30*7433666eSthorpej __KERNEL_RCSID(0, "$NetBSD: hd64465uart.c,v 1.21 2023/12/20 14:50:03 thorpej Exp $");
310c82163cSlukem 
32b67fd34cSuch #include "opt_kgdb.h"
33b67fd34cSuch 
34b67fd34cSuch #include <sys/param.h>
35b67fd34cSuch #include <sys/systm.h>
36b67fd34cSuch #include <sys/reboot.h>
37b67fd34cSuch #include <sys/device.h>
386042c0a3Such #include <sys/kgdb.h>
39f48d88bfSdyoung #include <sys/bus.h>
40b67fd34cSuch 
41b67fd34cSuch #include <sys/termios.h>
42b67fd34cSuch #include <dev/cons.h>
43b67fd34cSuch #include <sys/conf.h>
44b67fd34cSuch 
45b67fd34cSuch #include <machine/intr.h>
46b67fd34cSuch #include <machine/console.h>
47b67fd34cSuch 
48b67fd34cSuch #include <dev/ic/comvar.h>
49b67fd34cSuch #include <dev/ic/comreg.h>
50b67fd34cSuch 
51b67fd34cSuch #include <machine/debug.h>
52b67fd34cSuch 
53b67fd34cSuch #include <hpcsh/dev/hd64465/hd64465var.h>
54260c29f0Such #include <hpcsh/dev/hd64465/hd64465intcreg.h>
55b67fd34cSuch #include <hpcsh/dev/hd64465/hd64465uartvar.h>
56b67fd34cSuch #include <hpcsh/dev/hd64465/hd64465uartreg.h>
57b67fd34cSuch 
58b67fd34cSuch STATIC struct hd64465uart_chip {
59b67fd34cSuch 	struct hpcsh_bus_space __tag_body;
60b67fd34cSuch 	bus_space_tag_t io_tag;
61b67fd34cSuch 	int console;
62b67fd34cSuch } hd64465uart_chip;
63b67fd34cSuch 
64b67fd34cSuch struct hd64465uart_softc {
65b67fd34cSuch 	struct com_softc sc_com;
66b67fd34cSuch 
67b67fd34cSuch 	struct hd64465uart_chip *sc_chip;
68b67fd34cSuch 	enum hd64465_module_id sc_module_id;
69b67fd34cSuch };
70b67fd34cSuch 
71b67fd34cSuch /* boot console */
726042c0a3Such void hd64465uartcnprobe(struct consdev *);
736042c0a3Such void hd64465uartcninit(struct consdev *);
74b67fd34cSuch 
75607ead0eScube STATIC int hd64465uart_match(device_t, cfdata_t , void *);
76607ead0eScube STATIC void hd64465uart_attach(device_t, device_t, void *);
77b67fd34cSuch 
78607ead0eScube CFATTACH_DECL_NEW(hd64465uart, sizeof(struct hd64465uart_softc),
79bd5bb465Sthorpej     hd64465uart_match, hd64465uart_attach, NULL, NULL);
80b67fd34cSuch 
81b67fd34cSuch STATIC void hd64465uart_init(void);
82970e24eeSuwe STATIC uint8_t hd64465uart_read_1(void *, bus_space_handle_t, bus_size_t);
83b67fd34cSuch STATIC void hd64465uart_write_1(void *, bus_space_handle_t, bus_size_t,
84970e24eeSuwe     uint8_t);
85b67fd34cSuch 
86b67fd34cSuch #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
87b67fd34cSuch #ifndef COMCN_SPEED
88b67fd34cSuch #define COMCN_SPEED	19200
89b67fd34cSuch #endif
90b67fd34cSuch 
91b67fd34cSuch void
hd64465uartcnprobe(struct consdev * cp)926042c0a3Such hd64465uartcnprobe(struct consdev *cp)
93b67fd34cSuch {
9477a6b82bSgehenna 	extern struct cdevsw com_cdevsw;
95b67fd34cSuch 	int maj;
96b67fd34cSuch 
97b67fd34cSuch 	/* locate the major number */
9877a6b82bSgehenna 	maj = cdevsw_lookup_major(&com_cdevsw);
99b67fd34cSuch 
100b67fd34cSuch 	/* Initialize required fields. */
101b67fd34cSuch 	cp->cn_dev = makedev(maj, 0);
102b67fd34cSuch 	cp->cn_pri = CN_NORMAL;
103b67fd34cSuch }
104b67fd34cSuch 
105b67fd34cSuch void
hd64465uartcninit(struct consdev * cp)1066042c0a3Such hd64465uartcninit(struct consdev *cp)
107b67fd34cSuch {
108b67fd34cSuch 
109b67fd34cSuch 	hd64465uart_init();
110b67fd34cSuch 
111b67fd34cSuch 	comcnattach(hd64465uart_chip.io_tag, 0x0, COMCN_SPEED, COM_FREQ,
1120eff6718Sthorpej 	    COM_TYPE_NORMAL, CONMODE);
113b67fd34cSuch 
114b67fd34cSuch 	hd64465uart_chip.console = 1;
115b67fd34cSuch }
116b67fd34cSuch 
1176042c0a3Such #ifdef KGDB
1186042c0a3Such int
hd64465uart_kgdb_init(void)1191d7f24eaSmatt hd64465uart_kgdb_init(void)
1206042c0a3Such {
1216042c0a3Such 
1226042c0a3Such 	if (strcmp(kgdb_devname, "hd64465uart") != 0)
1236042c0a3Such 		return (1);
1246042c0a3Such 
1257592c6aaSuch 	if (hd64465uart_chip.console)
1267592c6aaSuch 		return (1);	/* can't share with console */
1277592c6aaSuch 
1286042c0a3Such 	hd64465uart_init();
1296042c0a3Such 
1306042c0a3Such 	if (com_kgdb_attach(hd64465uart_chip.io_tag, 0x0, kgdb_rate,
1310eff6718Sthorpej 	    COM_FREQ, COM_TYPE_NORMAL, CONMODE) != 0) {
1329b2b412cSperry 		printf("%s: KGDB console open failed.\n", __func__);
1336042c0a3Such 		return (1);
1346042c0a3Such 	}
1356042c0a3Such 
1366042c0a3Such 	return (0);
1376042c0a3Such }
1386042c0a3Such #endif /* KGDB */
1396042c0a3Such 
140b67fd34cSuch int
hd64465uart_match(device_t parent,cfdata_t cf,void * aux)141607ead0eScube hd64465uart_match(device_t parent, cfdata_t cf, void *aux)
142b67fd34cSuch {
143b67fd34cSuch 	struct hd64465_attach_args *ha = aux;
144b67fd34cSuch 
145b67fd34cSuch 	return (ha->ha_module_id == HD64465_MODULE_UART);
146b67fd34cSuch }
147b67fd34cSuch 
148b67fd34cSuch void
hd64465uart_attach(device_t parent,device_t self,void * aux)149607ead0eScube hd64465uart_attach(device_t parent, device_t self, void *aux)
150b67fd34cSuch {
151b67fd34cSuch 	struct hd64465_attach_args *ha = aux;
152607ead0eScube 	struct hd64465uart_softc *sc = device_private(self);
153b67fd34cSuch 	struct com_softc *csc = &sc->sc_com;
15434537908Sgdamore 	bus_space_handle_t ioh;
155b67fd34cSuch 
156607ead0eScube 	csc->sc_dev = self;
157b67fd34cSuch 	sc->sc_chip = &hd64465uart_chip;
158b67fd34cSuch 
159b67fd34cSuch 	sc->sc_module_id = ha->ha_module_id;
160b67fd34cSuch 
1617592c6aaSuch 	if (!sc->sc_chip->console)
162b67fd34cSuch 		hd64465uart_init();
163b67fd34cSuch 
16434537908Sgdamore 	bus_space_map(sc->sc_chip->io_tag, 0, 8, 0, &ioh);
1656d487047Sthorpej 	com_init_regs(&csc->sc_regs, sc->sc_chip->io_tag, ioh, 0);
166b67fd34cSuch 	csc->sc_frequency = COM_FREQ;
167b67fd34cSuch 
168b67fd34cSuch 	/* supply clock XXX notyet */
169b67fd34cSuch 
170b67fd34cSuch 	/* sanity check */
17134537908Sgdamore 	if (!com_probe_subr(&csc->sc_regs)) {
172607ead0eScube 		aprint_error(": device problem. don't attach.\n");
173b67fd34cSuch 
174b67fd34cSuch 		/* stop clock XXX notyet */
175b67fd34cSuch 		return;
176b67fd34cSuch 	}
177b67fd34cSuch 
178b67fd34cSuch 	com_attach_subr(csc);
179b67fd34cSuch 
180b67fd34cSuch 	/* register interrupt handler */
181260c29f0Such 	hd64465_intr_establish(HD64465_UART, IST_LEVEL, IPL_TTY,
182b67fd34cSuch 	    comintr, self);
183b67fd34cSuch }
184b67fd34cSuch 
185b67fd34cSuch void
hd64465uart_init(void)1861d7f24eaSmatt hd64465uart_init(void)
187b67fd34cSuch {
188b67fd34cSuch 
189b67fd34cSuch 	if (hd64465uart_chip.io_tag)
190b67fd34cSuch 		return;
191b67fd34cSuch 
192b67fd34cSuch 	hd64465uart_chip.io_tag = bus_space_create(
193b67fd34cSuch 		&hd64465uart_chip.__tag_body, "HD64465 UART I/O",
194b67fd34cSuch 		0xb0008000, 0); /* no extent */
195b67fd34cSuch 
196b67fd34cSuch 	/* override bus_space_read_1, bus_space_write_1 */
197b67fd34cSuch 	hd64465uart_chip.io_tag->hbs_r_1 = hd64465uart_read_1;
198b67fd34cSuch 	hd64465uart_chip.io_tag->hbs_w_1 = hd64465uart_write_1;
199b67fd34cSuch }
200b67fd34cSuch 
201970e24eeSuwe uint8_t
hd64465uart_read_1(void * t,bus_space_handle_t h,bus_size_t ofs)202b67fd34cSuch hd64465uart_read_1(void *t, bus_space_handle_t h, bus_size_t ofs)
203b67fd34cSuch {
204b67fd34cSuch 
205970e24eeSuwe 	return *(volatile uint8_t *)(h + (ofs << 1));
206b67fd34cSuch }
207b67fd34cSuch 
208b67fd34cSuch void
hd64465uart_write_1(void * t,bus_space_handle_t h,bus_size_t ofs,uint8_t val)209b67fd34cSuch hd64465uart_write_1(void *t, bus_space_handle_t h, bus_size_t ofs,
210970e24eeSuwe     uint8_t val)
211b67fd34cSuch {
212b67fd34cSuch 
213970e24eeSuwe 	*(volatile uint8_t *)(h + (ofs << 1)) = val;
214b67fd34cSuch }
215