1160814Ssimon/*	$NetBSD: hd64465uart.c,v 1.21 2023/12/20 14:50:03 thorpej Exp $	*/
2160814Ssimon
3160814Ssimon/*-
4160814Ssimon * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
5160814Ssimon * All rights reserved.
6160814Ssimon *
7160814Ssimon * Redistribution and use in source and binary forms, with or without
8160814Ssimon * modification, are permitted provided that the following conditions
9296341Sdelphij * are met:
10160814Ssimon * 1. Redistributions of source code must retain the above copyright
11160814Ssimon *    notice, this list of conditions and the following disclaimer.
12160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
13160814Ssimon *    notice, this list of conditions and the following disclaimer in the
14160814Ssimon *    documentation and/or other materials provided with the distribution.
15160814Ssimon *
16160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17160814Ssimon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18160814Ssimon * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19160814Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20160814Ssimon * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21160814Ssimon * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22160814Ssimon * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23160814Ssimon * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24160814Ssimon * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26160814Ssimon * POSSIBILITY OF SUCH DAMAGE.
27160814Ssimon */
28160814Ssimon
29160814Ssimon#include <sys/cdefs.h>
30160814Ssimon__KERNEL_RCSID(0, "$NetBSD: hd64465uart.c,v 1.21 2023/12/20 14:50:03 thorpej Exp $");
31160814Ssimon
32160814Ssimon#include "opt_kgdb.h"
33160814Ssimon
34160814Ssimon#include <sys/param.h>
35160814Ssimon#include <sys/systm.h>
36160814Ssimon#include <sys/reboot.h>
37160814Ssimon#include <sys/device.h>
38160814Ssimon#include <sys/kgdb.h>
39160814Ssimon#include <sys/bus.h>
40160814Ssimon
41160814Ssimon#include <sys/termios.h>
42160814Ssimon#include <dev/cons.h>
43160814Ssimon#include <sys/conf.h>
44160814Ssimon
45160814Ssimon#include <machine/intr.h>
46160814Ssimon#include <machine/console.h>
47160814Ssimon
48160814Ssimon#include <dev/ic/comvar.h>
49160814Ssimon#include <dev/ic/comreg.h>
50160814Ssimon
51160814Ssimon#include <machine/debug.h>
52160814Ssimon
53160814Ssimon#include <hpcsh/dev/hd64465/hd64465var.h>
54160814Ssimon#include <hpcsh/dev/hd64465/hd64465intcreg.h>
55160814Ssimon#include <hpcsh/dev/hd64465/hd64465uartvar.h>
56160814Ssimon#include <hpcsh/dev/hd64465/hd64465uartreg.h>
57160814Ssimon
58160814SsimonSTATIC struct hd64465uart_chip {
59160814Ssimon	struct hpcsh_bus_space __tag_body;
60238405Sjkim	bus_space_tag_t io_tag;
61296341Sdelphij	int console;
62296341Sdelphij} hd64465uart_chip;
63160814Ssimon
64296341Sdelphijstruct hd64465uart_softc {
65160814Ssimon	struct com_softc sc_com;
66160814Ssimon
67160814Ssimon	struct hd64465uart_chip *sc_chip;
68194206Ssimon	enum hd64465_module_id sc_module_id;
69296341Sdelphij};
70194206Ssimon
71238405Sjkim/* boot console */
72296341Sdelphijvoid hd64465uartcnprobe(struct consdev *);
73194206Ssimonvoid hd64465uartcninit(struct consdev *);
74194206Ssimon
75160814SsimonSTATIC int hd64465uart_match(device_t, cfdata_t , void *);
76160814SsimonSTATIC void hd64465uart_attach(device_t, device_t, void *);
77160814Ssimon
78160814SsimonCFATTACH_DECL_NEW(hd64465uart, sizeof(struct hd64465uart_softc),
79160814Ssimon    hd64465uart_match, hd64465uart_attach, NULL, NULL);
80296341Sdelphij
81160814SsimonSTATIC void hd64465uart_init(void);
82160814SsimonSTATIC uint8_t hd64465uart_read_1(void *, bus_space_handle_t, bus_size_t);
83296341SdelphijSTATIC void hd64465uart_write_1(void *, bus_space_handle_t, bus_size_t,
84160814Ssimon    uint8_t);
85160814Ssimon
86296341Sdelphij#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
87160814Ssimon#ifndef COMCN_SPEED
88160814Ssimon#define COMCN_SPEED	19200
89160814Ssimon#endif
90296341Sdelphij
91296341Sdelphijvoid
92296341Sdelphijhd64465uartcnprobe(struct consdev *cp)
93296341Sdelphij{
94296341Sdelphij	extern struct cdevsw com_cdevsw;
95296341Sdelphij	int maj;
96160814Ssimon
97296341Sdelphij	/* locate the major number */
98296341Sdelphij	maj = cdevsw_lookup_major(&com_cdevsw);
99160814Ssimon
100296341Sdelphij	/* Initialize required fields. */
101160814Ssimon	cp->cn_dev = makedev(maj, 0);
102160814Ssimon	cp->cn_pri = CN_NORMAL;
103160814Ssimon}
104296341Sdelphij
105160814Ssimonvoid
106160814Ssimonhd64465uartcninit(struct consdev *cp)
107160814Ssimon{
108160814Ssimon
109160814Ssimon	hd64465uart_init();
110160814Ssimon
111160814Ssimon	comcnattach(hd64465uart_chip.io_tag, 0x0, COMCN_SPEED, COM_FREQ,
112160814Ssimon	    COM_TYPE_NORMAL, CONMODE);
113296341Sdelphij
114160814Ssimon	hd64465uart_chip.console = 1;
115296341Sdelphij}
116160814Ssimon
117296341Sdelphij#ifdef KGDB
118296341Sdelphijint
119296341Sdelphijhd64465uart_kgdb_init(void)
120296341Sdelphij{
121296341Sdelphij
122160814Ssimon	if (strcmp(kgdb_devname, "hd64465uart") != 0)
123160814Ssimon		return (1);
124296341Sdelphij
125296341Sdelphij	if (hd64465uart_chip.console)
126296341Sdelphij		return (1);	/* can't share with console */
127296341Sdelphij
128160814Ssimon	hd64465uart_init();
129160814Ssimon
130296341Sdelphij	if (com_kgdb_attach(hd64465uart_chip.io_tag, 0x0, kgdb_rate,
131160814Ssimon	    COM_FREQ, COM_TYPE_NORMAL, CONMODE) != 0) {
132296341Sdelphij		printf("%s: KGDB console open failed.\n", __func__);
133296341Sdelphij		return (1);
134160814Ssimon	}
135160814Ssimon
136296341Sdelphij	return (0);
137160814Ssimon}
138296341Sdelphij#endif /* KGDB */
139296341Sdelphij
140160814Ssimonint
141160814Ssimonhd64465uart_match(device_t parent, cfdata_t cf, void *aux)
142296341Sdelphij{
143296341Sdelphij	struct hd64465_attach_args *ha = aux;
144296341Sdelphij
145160814Ssimon	return (ha->ha_module_id == HD64465_MODULE_UART);
146160814Ssimon}
147160814Ssimon
148296341Sdelphijvoid
149160814Ssimonhd64465uart_attach(device_t parent, device_t self, void *aux)
150296341Sdelphij{
151296341Sdelphij	struct hd64465_attach_args *ha = aux;
152296341Sdelphij	struct hd64465uart_softc *sc = device_private(self);
153160814Ssimon	struct com_softc *csc = &sc->sc_com;
154160814Ssimon	bus_space_handle_t ioh;
155296341Sdelphij
156160814Ssimon	csc->sc_dev = self;
157160814Ssimon	sc->sc_chip = &hd64465uart_chip;
158296341Sdelphij
159160814Ssimon	sc->sc_module_id = ha->ha_module_id;
160160814Ssimon
161296341Sdelphij	if (!sc->sc_chip->console)
162160814Ssimon		hd64465uart_init();
163296341Sdelphij
164296341Sdelphij	bus_space_map(sc->sc_chip->io_tag, 0, 8, 0, &ioh);
165296341Sdelphij	com_init_regs(&csc->sc_regs, sc->sc_chip->io_tag, ioh, 0);
166160814Ssimon	csc->sc_frequency = COM_FREQ;
167160814Ssimon
168296341Sdelphij	/* supply clock XXX notyet */
169296341Sdelphij
170296341Sdelphij	/* sanity check */
171296341Sdelphij	if (!com_probe_subr(&csc->sc_regs)) {
172296341Sdelphij		aprint_error(": device problem. don't attach.\n");
173296341Sdelphij
174296341Sdelphij		/* stop clock XXX notyet */
175296341Sdelphij		return;
176160814Ssimon	}
177296341Sdelphij
178160814Ssimon	com_attach_subr(csc);
179296341Sdelphij
180296341Sdelphij	/* register interrupt handler */
181296341Sdelphij	hd64465_intr_establish(HD64465_UART, IST_LEVEL, IPL_TTY,
182296341Sdelphij	    comintr, self);
183296341Sdelphij}
184296341Sdelphij
185296341Sdelphijvoid
186296341Sdelphijhd64465uart_init(void)
187296341Sdelphij{
188296341Sdelphij
189296341Sdelphij	if (hd64465uart_chip.io_tag)
190296341Sdelphij		return;
191296341Sdelphij
192296341Sdelphij	hd64465uart_chip.io_tag = bus_space_create(
193296341Sdelphij		&hd64465uart_chip.__tag_body, "HD64465 UART I/O",
194296341Sdelphij		0xb0008000, 0); /* no extent */
195296341Sdelphij
196160814Ssimon	/* override bus_space_read_1, bus_space_write_1 */
197296341Sdelphij	hd64465uart_chip.io_tag->hbs_r_1 = hd64465uart_read_1;
198160814Ssimon	hd64465uart_chip.io_tag->hbs_w_1 = hd64465uart_write_1;
199296341Sdelphij}
200296341Sdelphij
201296341Sdelphijuint8_t
202296341Sdelphijhd64465uart_read_1(void *t, bus_space_handle_t h, bus_size_t ofs)
203296341Sdelphij{
204296341Sdelphij
205296341Sdelphij	return *(volatile uint8_t *)(h + (ofs << 1));
206296341Sdelphij}
207296341Sdelphij
208296341Sdelphijvoid
209296341Sdelphijhd64465uart_write_1(void *t, bus_space_handle_t h, bus_size_t ofs,
210296341Sdelphij    uint8_t val)
211296341Sdelphij{
212296341Sdelphij
213296341Sdelphij	*(volatile uint8_t *)(h + (ofs << 1)) = val;
214160814Ssimon}
215296341Sdelphij