Home | History | Annotate | Line # | Download | only in podulebus
      1 /*	$NetBSD: amps.c,v 1.24 2025/01/02 16:09:32 andvar Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Mark Brinicombe of Causality Limited.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  *
     31  * Card driver and probe and attach functions to use generic 16550 com
     32  * driver for the Atomwide multiport serial podule
     33  */
     34 
     35 /*
     36  * Thanks to Martin Coulson, Atomwide, for providing the hardware
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 __KERNEL_RCSID(0, "$NetBSD: amps.c,v 1.24 2025/01/02 16:09:32 andvar Exp $");
     41 
     42 #include <sys/param.h>
     43 #include <sys/systm.h>
     44 #include <sys/ioctl.h>
     45 #include <sys/select.h>
     46 #include <sys/tty.h>
     47 #include <sys/proc.h>
     48 #include <sys/conf.h>
     49 #include <sys/file.h>
     50 #include <sys/uio.h>
     51 #include <sys/kernel.h>
     52 #include <sys/syslog.h>
     53 #include <sys/types.h>
     54 #include <sys/device.h>
     55 #include <sys/bus.h>
     56 
     57 #include <machine/intr.h>
     58 #include <machine/io.h>
     59 #include <acorn32/podulebus/podulebus.h>
     60 #include <acorn32/podulebus/ampsreg.h>
     61 #include <dev/ic/comreg.h>
     62 #include <dev/ic/comvar.h>
     63 #include <dev/podulebus/podules.h>
     64 
     65 #include "locators.h"
     66 
     67 /*
     68  * Atomwide Multi-port serial podule device.
     69  *
     70  * This probes and attaches the top level multi-port serial device to the
     71  * podulebus. It then configures the child com devices.
     72  */
     73 
     74 /*
     75  * Atomwide Multi-port serial card softc structure.
     76  *
     77  * Contains the device node, podule information and global information
     78  * required by the driver such as the card version and the interrupt mask.
     79  */
     80 
     81 struct amps_softc {
     82 	device_t		sc_dev;			/* device node */
     83 	podule_t 		*sc_podule;		/* Our podule info */
     84 	int 			sc_podule_number;	/* Our podule number */
     85 	bus_space_tag_t		sc_iot;			/* Bus tag */
     86 };
     87 
     88 int	amps_probe(device_t, cfdata_t, void *);
     89 void	amps_attach(device_t, device_t, void *);
     90 
     91 CFATTACH_DECL_NEW(amps, sizeof(struct amps_softc),
     92     amps_probe, amps_attach, NULL, NULL);
     93 
     94 int	amps_print(void *, const char *);
     95 void	amps_shutdown(void *);
     96 
     97 /*
     98  * Attach arguments for child devices.
     99  * Pass the podule details, the parent softc and the channel
    100  */
    101 
    102 struct amps_attach_args {
    103 	bus_space_tag_t aa_iot;			/* bus space tag */
    104 	unsigned int aa_base;			/* base address for port */
    105 	int aa_port;      			/* serial port number */
    106 	podulebus_intr_handle_t aa_irq;		/* IRQ number */
    107 };
    108 
    109 /*
    110  * Define prototypes for custom bus space functions.
    111  */
    112 
    113 /* Print function used during child config */
    114 
    115 int
    116 amps_print(void *aux, const char *name)
    117 {
    118 	struct amps_attach_args *aa = aux;
    119 
    120 	if (!name)
    121 		aprint_normal(", port %d", aa->aa_port);
    122 
    123 	return(QUIET);
    124 }
    125 
    126 /*
    127  * Card probe function
    128  *
    129  * Just match the manufacturer and podule ID's
    130  */
    131 
    132 int
    133 amps_probe(device_t parent, cfdata_t cf, void *aux)
    134 {
    135 	struct podule_attach_args *pa = aux;
    136 
    137 	return (pa->pa_product == PODULE_ATOMWIDE_SERIAL);
    138 }
    139 
    140 /*
    141  * Card attach function
    142  *
    143  * Identify the card version and configure any children.
    144  * Install a shutdown handler to kill interrupts on shutdown
    145  */
    146 
    147 void
    148 amps_attach(device_t parent, device_t self, void *aux)
    149 {
    150 	struct amps_softc *sc = device_private(self);
    151 	struct podule_attach_args *pa = aux;
    152 	struct amps_attach_args aa;
    153 
    154 	/* Note the podule number and validate */
    155 
    156 	if (pa->pa_podule_number == -1)
    157 		panic("Podule has disappeared !");
    158 
    159 	sc->sc_dev = self;
    160 	sc->sc_podule_number = pa->pa_podule_number;
    161 	sc->sc_podule = pa->pa_podule;
    162 	podules[sc->sc_podule_number].attached = 1;
    163 
    164 	sc->sc_iot = pa->pa_iot;
    165 
    166 	/* Install a clean up handler to make sure IRQ's are disabled */
    167 /*	if (shutdownhook_establish(amps_shutdown, (void *)sc) == NULL)
    168 		panic("%s: Cannot install shutdown handler", device_xname(self));*/
    169 
    170 	/* Set the interrupt info for this podule */
    171 
    172 /*	sc->sc_podule->irq_addr = pa->pa_podule->slow_base +;*/	/* XXX */
    173 /*	sc->sc_podule->irq_mask = ;*/
    174 
    175 	printf("\n");
    176 
    177 	/* Configure the children */
    178 
    179 	aa.aa_iot = sc->sc_iot;
    180 	aa.aa_base = pa->pa_podule->slow_base + AMPS_BASE_OFFSET;
    181 	aa.aa_base += MAX_AMPS_PORTS * AMPS_PORT_SPACING;
    182 	aa.aa_irq = pa->pa_podule->interrupt;
    183 	for (aa.aa_port = 0; aa.aa_port < MAX_AMPS_PORTS; ++aa.aa_port) {
    184 		aa.aa_base -= AMPS_PORT_SPACING;
    185 		config_found(self, &aa, amps_print, CFARGS_NONE);
    186 	}
    187 }
    188 
    189 /*
    190  * Card shutdown function
    191  *
    192  * Called via do_shutdown_hooks() during kernel shutdown.
    193  * Clear the cards's interrupt mask to stop any podule interrupts.
    194  */
    195 
    196 /*void
    197 amps_shutdown(void *arg)
    198 {
    199 }*/
    200 
    201 /*
    202  * Atomwide Multi-Port Serial probe and attach code for the com device.
    203  *
    204  * This provides a different pair of probe and attach functions
    205  * for attaching the com device (dev/ic/com.c) to the Atomwide serial card.
    206  */
    207 
    208 struct com_amps_softc {
    209 	struct	com_softc sc_com;	/* real "com" softc */
    210 	void	*sc_ih;			/* interrupt handler */
    211 	struct	evcnt sc_intrcnt;	/* interrupt count */
    212 };
    213 
    214 /* Prototypes for functions */
    215 
    216 static int  com_amps_probe   (device_t, cfdata_t , void *);
    217 static void com_amps_attach  (device_t, device_t, void *);
    218 
    219 /* device attach structure */
    220 
    221 CFATTACH_DECL_NEW(com_amps, sizeof(struct com_amps_softc),
    222 	com_amps_probe, com_amps_attach, NULL, NULL);
    223 
    224 /*
    225  * Controller probe function
    226  *
    227  * Map all the required I/O space for this channel, make sure interrupts
    228  * are disabled and probe the bus.
    229  */
    230 
    231 int
    232 com_amps_probe(device_t parent, cfdata_t cf, void *aux)
    233 {
    234 	bus_space_tag_t iot;
    235 	bus_space_handle_t ioh;
    236 	int iobase;
    237 	int rv = 1;
    238 	struct amps_attach_args *aa = aux;
    239 
    240 	iot = aa->aa_iot;
    241 	iobase = aa->aa_base;
    242 
    243 	/* if it's in use as console, it's there. */
    244 	if (!com_is_console(iot, iobase, 0)) {
    245 		if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) {
    246 			return 0;
    247 		}
    248 		/*
    249 		 * We don't use the generic comprobe1() function as it
    250 		 * is not good enough to identify which ports are present.
    251 		 *
    252 		 * Instead test for the presence of the scratch register
    253 		 */
    254 
    255 		bus_space_write_1(iot, ioh, com_scratch, 0x55);
    256 		bus_space_write_1(iot, ioh, com_ier, 0);
    257 		(void)bus_space_read_1(iot, ioh, com_data);
    258 		if (bus_space_read_1(iot, ioh, com_scratch) != 0x55)
    259 			rv = 0;
    260 		bus_space_write_1(iot, ioh, com_scratch, 0xaa);
    261 		bus_space_write_1(iot, ioh, com_ier, 0);
    262 		(void)bus_space_read_1(iot, ioh, com_data);
    263 		if (bus_space_read_1(iot, ioh, com_scratch) != 0xaa)
    264 			rv = 0;
    265 
    266 		bus_space_unmap(iot, ioh, COM_NPORTS);
    267 	}
    268 	return (rv);
    269 }
    270 
    271 /*
    272  * Controller attach function
    273  *
    274  * Map all the required I/O space for this port and attach the driver
    275  * The generic attach will probe and attach any device.
    276  * Install an interrupt handler and we are ready to rock.
    277  */
    278 
    279 void
    280 com_amps_attach(device_t parent, device_t self, void *aux)
    281 {
    282 	struct com_amps_softc *asc = device_private(self);
    283 	struct com_softc *sc = &asc->sc_com;
    284 	u_int iobase;
    285 	bus_space_tag_t iot;
    286 	bus_space_handle_t ioh;
    287 	struct amps_attach_args *aa = aux;
    288 
    289 	sc->sc_dev = self;
    290 	iot = aa->aa_iot;
    291 	iobase = aa->aa_base;
    292 
    293 	if (!com_is_console(iot, iobase, &ioh)
    294 	    && bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh))
    295 		panic("comattach: io mapping failed");
    296 	com_init_regs(&sc->sc_regs, iot, ioh, iobase);
    297 
    298 	sc->sc_frequency = AMPS_FREQ;
    299 	com_attach_subr(sc);
    300 
    301 	evcnt_attach_dynamic(&asc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
    302 	    device_xname(self), "intr");
    303 	asc->sc_ih = podulebus_irq_establish(aa->aa_irq, IPL_SERIAL, comintr,
    304 	    sc, &asc->sc_intrcnt);
    305 }
    306