Home | History | Annotate | Line # | Download | only in dev
      1 /*	$NetBSD: pcctwo_68k.c,v 1.12 2024/01/19 03:59:47 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Steve C. Woodford.
      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 
     32 /*
     33  * PCCchip2 and MCchip Mvme68k Front End Driver
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 __KERNEL_RCSID(0, "$NetBSD: pcctwo_68k.c,v 1.12 2024/01/19 03:59:47 thorpej Exp $");
     38 
     39 #include "opt_mvmeconf.h"
     40 
     41 #include <sys/param.h>
     42 #include <sys/kernel.h>
     43 #include <sys/systm.h>
     44 #include <sys/device.h>
     45 
     46 #include <machine/cpu.h>
     47 #include <machine/bus.h>
     48 
     49 #include <mvme68k/dev/mainbus.h>
     50 #include <mvme68k/mvme68k/isr.h>
     51 
     52 #include <dev/mvme/pcctworeg.h>
     53 #include <dev/mvme/pcctwovar.h>
     54 
     55 #include "ioconf.h"
     56 
     57 /*
     58  * Autoconfiguration stuff.
     59  */
     60 void pcctwoattach(device_t, device_t, void *);
     61 int pcctwomatch(device_t, cfdata_t, void *);
     62 
     63 CFATTACH_DECL_NEW(pcctwo, sizeof(struct pcctwo_softc),
     64     pcctwomatch, pcctwoattach, NULL, NULL);
     65 
     66 
     67 #if defined(MVME167) || defined(MVME177)
     68 /*
     69  * Devices that live on the PCCchip2, attached in this order.
     70  */
     71 static const struct pcctwo_device pcctwo_devices[] = {
     72 	{"clock", 0},
     73 	{"clmpcc", PCCTWO_SCC_OFF},
     74 	{"ie", PCCTWO_IE_OFF},
     75 	{"osiop", PCCTWO_NCRSC_OFF},
     76 	{"lpt", PCCTWO_LPT_OFF},
     77 	{NULL, 0}
     78 };
     79 
     80 static int pcctwo_vec2icsr_1x7[] = {
     81 	VEC2ICSR(PCC2REG_PRT_BUSY_ICSR,  PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR),
     82 	VEC2ICSR(PCC2REG_PRT_PE_ICSR,    PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR),
     83 	VEC2ICSR(PCC2REG_PRT_SEL_ICSR,   PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR),
     84 	VEC2ICSR(PCC2REG_PRT_FAULT_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR),
     85 	VEC2ICSR(PCC2REG_PRT_ACK_ICSR,   PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR),
     86 	VEC2ICSR(PCC2REG_SCSI_ICSR,      0),
     87 	VEC2ICSR(PCC2REG_ETH_ICSR,       PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR),
     88 	VEC2ICSR(PCC2REG_ETH_ICSR,       PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR),
     89 	VEC2ICSR(PCC2REG_TIMER2_ICSR,    PCCTWO_ICR_ICLR),
     90 	VEC2ICSR(PCC2REG_TIMER1_ICSR,    PCCTWO_ICR_ICLR),
     91 	VEC2ICSR(PCC2REG_GPIO_ICSR,      PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR),
     92 	-1,
     93 	VEC2ICSR(PCC2REG_SCC_RX_ICSR,    0),
     94 	VEC2ICSR(PCC2REG_SCC_MODEM_ICSR, 0),
     95 	VEC2ICSR(PCC2REG_SCC_TX_ICSR,    0),
     96 	VEC2ICSR(PCC2REG_SCC_RX_ICSR,    0)
     97 };
     98 #endif
     99 
    100 #if defined(MVME162) || defined(MVME172)
    101 /*
    102  * Devices that live on the MCchip, attached in this order.
    103  */
    104 static const struct pcctwo_device mcchip_devices[] = {
    105 	{"clock", 0},
    106 	{"zsc", MCCHIP_ZS0_OFF},
    107 	{"zsc", MCCHIP_ZS1_OFF},
    108 	{"ie", PCCTWO_IE_OFF},
    109 	{"osiop", PCCTWO_NCRSC_OFF},
    110 	{NULL, 0}
    111 };
    112 
    113 static int pcctwo_vec2icsr_1x2[] = {
    114 	-1,
    115 	-1,
    116 	-1,
    117 	VEC2ICSR(MCCHIPREG_TIMER4_ICSR, PCCTWO_ICR_ICLR),
    118 	VEC2ICSR(MCCHIPREG_TIMER3_ICSR, PCCTWO_ICR_ICLR),
    119 	VEC2ICSR(PCC2REG_SCSI_ICSR,     0),
    120 	VEC2ICSR(PCC2REG_ETH_ICSR,      PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR),
    121 	VEC2ICSR(PCC2REG_ETH_ICSR,      PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR),
    122 	VEC2ICSR(PCC2REG_TIMER2_ICSR,   PCCTWO_ICR_ICLR),
    123 	VEC2ICSR(PCC2REG_TIMER1_ICSR,   PCCTWO_ICR_ICLR),
    124 	-1,
    125 	VEC2ICSR(MCCHIPREG_PARERR_ICSR, PCCTWO_ICR_ICLR),
    126 	VEC2ICSR(MCCHIPREG_SCC_ICSR,    0),
    127 	VEC2ICSR(MCCHIPREG_SCC_ICSR,    0),
    128 	VEC2ICSR(MCCHIPREG_ABORT_ICSR,  PCCTWO_ICR_ICLR),
    129 	-1
    130 };
    131 
    132 static	int pcctwoabortintr(void *);
    133 void	pcctwosoftintrinit(void);
    134 static	int pcctwosoftintr(void *);
    135 #ifdef notyet
    136 static	void pcctwosoftintrassert(void);
    137 #endif
    138 #endif
    139 
    140 static void pcctwoisrlink(void *, int (*)(void *), void *,
    141 		int, int, struct evcnt *);
    142 static void pcctwoisrunlink(void *, int);
    143 static struct evcnt *pcctwoisrevcnt(void *, int);
    144 
    145 
    146 /* ARGSUSED */
    147 int
    148 pcctwomatch(device_t parent, cfdata_t cf, void *aux)
    149 {
    150 	struct mainbus_attach_args *ma;
    151 	bus_space_handle_t bh;
    152 	uint8_t cid;
    153 
    154 	ma = aux;
    155 
    156 	/* There can be only one. */
    157 	if (sys_pcctwo || strcmp(ma->ma_name, pcctwo_cd.cd_name))
    158 		return 0;
    159 
    160 	/*
    161 	 * Grab the Chip's ID
    162 	 */
    163 	bus_space_map(ma->ma_bust, PCCTWO_REG_OFF + ma->ma_offset,
    164 	    PCC2REG_SIZE, 0, &bh);
    165 	cid = bus_space_read_1(ma->ma_bust, bh, PCC2REG_CHIP_ID);
    166 	bus_space_unmap(ma->ma_bust, bh, PCC2REG_SIZE);
    167 
    168 #if defined(MVME167) || defined(MVME177)
    169 	if ((machineid == MVME_167 || machineid == MVME_177) &&
    170 	    cid == PCCTWO_CHIP_ID_PCC2)
    171 		return 1;
    172 #endif
    173 #if defined(MVME162) || defined(MVME172)
    174 	if ((machineid == MVME_162 || machineid == MVME_172) &&
    175 	    cid == PCCTWO_CHIP_ID_MCCHIP)
    176 		return 1;
    177 #endif
    178 
    179 	return 0;
    180 }
    181 
    182 /* ARGSUSED */
    183 void
    184 pcctwoattach(device_t parent, device_t self, void *aux)
    185 {
    186 	struct mainbus_attach_args *ma;
    187 	struct pcctwo_softc *sc;
    188 	const struct pcctwo_device *pd = NULL;
    189 	uint8_t cid;
    190 
    191 	sc = sys_pcctwo = device_private(self);
    192 	sc->sc_dev = self;
    193 	ma = aux;
    194 
    195 	/* Get a handle to the PCCChip2's registers */
    196 	sc->sc_bust = ma->ma_bust;
    197 	sc->sc_dmat = ma->ma_dmat;
    198 	bus_space_map(sc->sc_bust, PCCTWO_REG_OFF + ma->ma_offset,
    199 	    PCC2REG_SIZE, 0, &sc->sc_bush);
    200 
    201 	sc->sc_vecbase = PCCTWO_VECBASE;
    202 	sc->sc_isrlink = pcctwoisrlink;
    203 	sc->sc_isrevcnt = pcctwoisrevcnt;
    204 	sc->sc_isrunlink = pcctwoisrunlink;
    205 
    206 	cid = pcc2_reg_read(sc, PCC2REG_CHIP_ID);
    207 
    208 #if defined(MVME167) || defined(MVME177)
    209 	if (cid == PCCTWO_CHIP_ID_PCC2) {
    210 		pd = pcctwo_devices;
    211 		sc->sc_vec2icsr = pcctwo_vec2icsr_1x7;
    212 	}
    213 #endif
    214 #if defined(MVME162) || defined(MVME172)
    215 	if (cid == PCCTWO_CHIP_ID_MCCHIP) {
    216 		pd = mcchip_devices;
    217 		sc->sc_vec2icsr = pcctwo_vec2icsr_1x2;
    218 	}
    219 #endif
    220 
    221 	/* Finish initialisation in common code */
    222 	pcctwo_init(sc, pd, ma->ma_offset);
    223 
    224 #if defined(MVME162) || defined(MVME172)
    225 	if (cid == PCCTWO_CHIP_ID_MCCHIP) {
    226 		evcnt_attach_dynamic(&sc->sc_evcnt, EVCNT_TYPE_INTR,
    227 		    isrlink_evcnt(7), "nmi", "abort sw");
    228 		pcctwointr_establish(MCCHIPV_ABORT, pcctwoabortintr, 7, NULL,
    229 		    &sc->sc_evcnt);
    230 	}
    231 #endif
    232 }
    233 
    234 /* ARGSUSED */
    235 static void
    236 pcctwoisrlink(void *cookie, int (*fn)(void *), void *arg, int ipl, int vec,
    237     struct evcnt *evcnt)
    238 {
    239 
    240 	isrlink_vectored(fn, arg, ipl, vec, evcnt);
    241 }
    242 
    243 /* ARGSUSED */
    244 static void
    245 pcctwoisrunlink(void *cookie, int vec)
    246 {
    247 
    248 	isrunlink_vectored(vec);
    249 }
    250 
    251 /* ARGSUSED */
    252 static struct evcnt *
    253 pcctwoisrevcnt(void *cookie, int ipl)
    254 {
    255 
    256 	return isrlink_evcnt(ipl);
    257 }
    258 
    259 #if defined(MVME162) || defined(MVME172)
    260 static int
    261 pcctwoabortintr(void *frame)
    262 {
    263 
    264 	pcc2_reg_write(sys_pcctwo, MCCHIPREG_ABORT_ICSR, PCCTWO_ICR_ICLR |
    265 	    pcc2_reg_read(sys_pcctwo, MCCHIPREG_ABORT_ICSR));
    266 
    267 	return nmihand(frame);
    268 }
    269 
    270 void
    271 pcctwosoftintrinit(void)
    272 {
    273 
    274 	/*
    275 	 * Since the VMEChip2 is normally used to generate
    276 	 * software interrupts to the CPU, we have to deal
    277 	 * with 162/172 boards which have the "No VMEChip2"
    278 	 * build option.
    279 	 *
    280 	 * When such a board is found, the VMEChip2 probe code
    281 	 * calls this function to implement software interrupts
    282 	 * the hard way; using tick timer 4 ...
    283 	 */
    284 	pcctwointr_establish(MCCHIPV_TIMER4, pcctwosoftintr,
    285 	    1, sys_pcctwo, &sys_pcctwo->sc_evcnt);
    286 	pcc2_reg_write(sys_pcctwo, MCCHIPREG_TIMER4_CTRL, 0);
    287 	pcc2_reg_write32(sys_pcctwo, MCCHIPREG_TIMER4_COMP, 1);
    288 	pcc2_reg_write32(sys_pcctwo, MCCHIPREG_TIMER4_CNTR, 0);
    289 #ifdef notyet
    290 	_softintr_chipset_assert = pcctwosoftintrassert;
    291 #endif
    292 }
    293 
    294 static int
    295 pcctwosoftintr(void *arg)
    296 {
    297 	struct pcctwo_softc *sc = arg;
    298 
    299 	pcc2_reg_write32(sc, MCCHIPREG_TIMER4_CNTR, 0);
    300 	pcc2_reg_write(sc, MCCHIPREG_TIMER4_CTRL, 0);
    301 	pcc2_reg_write(sc, MCCHIPREG_TIMER4_ICSR,
    302 	    PCCTWO_ICR_ICLR | PCCTWO_ICR_IEN | 1);
    303 
    304 #ifdef notyet
    305 	softintr_dispatch();
    306 #endif
    307 
    308 	return 1;
    309 }
    310 
    311 #ifdef notyet
    312 static void
    313 pcctwosoftintrassert(void)
    314 {
    315 
    316 	/*
    317 	 * Schedule a timer interrupt to happen in ~1uS.
    318 	 * This is more than adequate on any available m68k platform
    319 	 * for simulating software interrupts.
    320 	 */
    321 	pcc2_reg_write(sys_pcctwo, MCCHIPREG_TIMER4_CTRL, PCCTWO_TT_CTRL_CEN);
    322 }
    323 #endif
    324 #endif
    325