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