xref: /netbsd-src/sys/arch/sgimips/dev/pic.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$NetBSD: pic.c,v 1.19 2021/08/07 16:19:04 thorpej Exp $	 */
209d9a0fbSsekiya 
309d9a0fbSsekiya /*
409d9a0fbSsekiya  * Copyright (c) 2002 Steve Rumble
509d9a0fbSsekiya  * All rights reserved.
609d9a0fbSsekiya  *
709d9a0fbSsekiya  * Redistribution and use in source and binary forms, with or without
809d9a0fbSsekiya  * modification, are permitted provided that the following conditions
909d9a0fbSsekiya  * are met:
1009d9a0fbSsekiya  * 1. Redistributions of source code must retain the above copyright
1109d9a0fbSsekiya  *    notice, this list of conditions and the following disclaimer.
1209d9a0fbSsekiya  * 2. Redistributions in binary form must reproduce the above copyright
1309d9a0fbSsekiya  *    notice, this list of conditions and the following disclaimer in the
1409d9a0fbSsekiya  *    documentation and/or other materials provided with the distribution.
1509d9a0fbSsekiya  * 3. The name of the author may not be used to endorse or promote products
1609d9a0fbSsekiya  *    derived from this software without specific prior written permission.
1709d9a0fbSsekiya  *
1809d9a0fbSsekiya  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1909d9a0fbSsekiya  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2009d9a0fbSsekiya  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2109d9a0fbSsekiya  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2209d9a0fbSsekiya  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2309d9a0fbSsekiya  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2409d9a0fbSsekiya  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2509d9a0fbSsekiya  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2609d9a0fbSsekiya  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2709d9a0fbSsekiya  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2809d9a0fbSsekiya  */
2909d9a0fbSsekiya 
30451031bdSpooka #include <sys/cdefs.h>
31*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.19 2021/08/07 16:19:04 thorpej Exp $");
32451031bdSpooka 
3309d9a0fbSsekiya #include <sys/param.h>
3409d9a0fbSsekiya #include <sys/device.h>
3509d9a0fbSsekiya #include <sys/systm.h>
3609d9a0fbSsekiya 
3709d9a0fbSsekiya #include <machine/cpu.h>
3809d9a0fbSsekiya #include <machine/locore.h>
3909d9a0fbSsekiya #include <machine/autoconf.h>
40cf10107dSdyoung #include <sys/bus.h>
4109d9a0fbSsekiya #include <machine/machtype.h>
42ffc95bbeSsekiya #include <machine/sysconf.h>
4309d9a0fbSsekiya 
4409d9a0fbSsekiya #include <sgimips/dev/picreg.h>
4509d9a0fbSsekiya 
46a4d0bfd7Srumble #include <sgimips/gio/giovar.h>
47a4d0bfd7Srumble 
4809d9a0fbSsekiya #include "locators.h"
4909d9a0fbSsekiya 
5009d9a0fbSsekiya struct pic_softc {
5109d9a0fbSsekiya 	bus_space_tag_t		iot;
5209d9a0fbSsekiya 	bus_space_handle_t	ioh;
5309d9a0fbSsekiya };
5409d9a0fbSsekiya 
55cbab9cadSchs static int      pic_match(device_t, cfdata_t, void *);
56cbab9cadSchs static void     pic_attach(device_t, device_t, void *);
5709d9a0fbSsekiya static int      pic_print(void *, const char *);
580f58ff49Srumble static void	pic_bus_reset(void);
5923347d39Smatt static void	pic_bus_error(vaddr_t, uint32_t, uint32_t);
600f58ff49Srumble static void	pic_watchdog_enable(void);
610f58ff49Srumble static void	pic_watchdog_disable(void);
620f58ff49Srumble static void	pic_watchdog_tickle(void);
6309d9a0fbSsekiya 
64cbab9cadSchs CFATTACH_DECL_NEW(pic, 0,
6509d9a0fbSsekiya     pic_match, pic_attach, NULL, NULL);
6609d9a0fbSsekiya 
6709d9a0fbSsekiya struct pic_attach_args {
6809d9a0fbSsekiya 	const char	       *iaa_name;
6909d9a0fbSsekiya 
7009d9a0fbSsekiya 	bus_space_tag_t		iaa_st;
7109d9a0fbSsekiya 	bus_space_handle_t	iaa_sh;
7209d9a0fbSsekiya };
7309d9a0fbSsekiya 
74a4d0bfd7Srumble int pic_gio32_arb_config(int, uint32_t);
75a4d0bfd7Srumble 
7609d9a0fbSsekiya static struct pic_softc psc;
7709d9a0fbSsekiya 
7809d9a0fbSsekiya static int
pic_match(device_t parent,cfdata_t match,void * aux)79cbab9cadSchs pic_match(device_t parent, cfdata_t match, void *aux)
8009d9a0fbSsekiya {
8109d9a0fbSsekiya 	/*
8209d9a0fbSsekiya 	 * PIC exists on IP12 systems. It appears to be the immediate
8309d9a0fbSsekiya 	 * ancestor of the mc, for mips1 processors.
8409d9a0fbSsekiya 	 */
8588764f70Spooka 	if (mach_type == MACH_SGI_IP12)
8634267609Stsutsui 		return 1;
8788764f70Spooka 	else
8834267609Stsutsui 		return 0;
8909d9a0fbSsekiya }
9009d9a0fbSsekiya 
9109d9a0fbSsekiya static void
pic_attach(device_t parent,device_t self,void * aux)92cbab9cadSchs pic_attach(device_t parent, device_t self, void *aux)
9309d9a0fbSsekiya {
9434267609Stsutsui 	uint32_t reg;
9509d9a0fbSsekiya 	struct pic_attach_args iaa;
9609d9a0fbSsekiya 	struct mainbus_attach_args *ma = aux;
9709d9a0fbSsekiya 
98eb488f67Smacallan 	psc.iot = normal_memt;
99eb488f67Smacallan 	if (bus_space_map(psc.iot, ma->ma_addr, 0x20010,
10009d9a0fbSsekiya 			  BUS_SPACE_MAP_LINEAR, &psc.ioh))
10109d9a0fbSsekiya 		panic("pic_attach: could not allocate memory\n");
10209d9a0fbSsekiya 
103ffc95bbeSsekiya 	platform.bus_reset = pic_bus_reset;
10488764f70Spooka 	platform.watchdog_enable = pic_watchdog_enable;
10588764f70Spooka 	platform.watchdog_disable = pic_watchdog_disable;
10658a060c7Ssekiya 	platform.watchdog_reset = pic_watchdog_tickle;
107ffc95bbeSsekiya 
10809d9a0fbSsekiya 	reg = bus_space_read_4(psc.iot, psc.ioh, PIC_SYSID);
10909d9a0fbSsekiya 	reg = (reg >> PIC_SYSID_REVSHIFT) & PIC_SYSID_REVMASK;
11089a2f53dSpooka 	printf("\npic0: Revision %c", reg + 64);
11109d9a0fbSsekiya 
11209d9a0fbSsekiya 	/* enable refresh, set big-endian, memory parity, allow slave access */
11309d9a0fbSsekiya 	reg = bus_space_read_4(psc.iot, psc.ioh, PIC_CPUCTRL);
11409d9a0fbSsekiya 	reg |= (PIC_CPUCTRL_REFRESH | PIC_CPUCTRL_BIGENDIAN | PIC_CPUCTRL_MPR |
11509d9a0fbSsekiya 		PIC_CPUCTRL_SLAVE);
11609d9a0fbSsekiya 	bus_space_write_4(psc.iot, psc.ioh, PIC_CPUCTRL, reg);
11709d9a0fbSsekiya 
11809d9a0fbSsekiya 	/* query the mode register to see what's going on */
11909d9a0fbSsekiya 	reg = bus_space_read_4(psc.iot, psc.ioh, PIC_MODE);
12009d9a0fbSsekiya 	printf(": dblk (0x%x), iblk (0x%x)\n", reg & PIC_MODE_DBSIZ,
12109d9a0fbSsekiya 	       reg & PIC_MODE_IBSIZ);
12209d9a0fbSsekiya 
123c37efd2dSsekiya 	/* display the machine type, board revision */
124c37efd2dSsekiya 	printf("pic0: ");
125c37efd2dSsekiya 
126c37efd2dSsekiya 	switch (mach_subtype) {
127c37efd2dSsekiya 	case MACH_SGI_IP12_4D_3X:
128c37efd2dSsekiya 		printf("Personal Iris 4D/3x");
129c37efd2dSsekiya 		break;
130c37efd2dSsekiya 	case MACH_SGI_IP12_VIP12:
131c37efd2dSsekiya 		printf("VME IP12");
132c37efd2dSsekiya 		break;
133c37efd2dSsekiya 	case MACH_SGI_IP12_HP1:
134c37efd2dSsekiya 		printf("Indigo R3000");
135c37efd2dSsekiya 		break;
136c37efd2dSsekiya 	case MACH_SGI_IP12_HPLC:
137c37efd2dSsekiya 		printf("Hollywood Light");
138c37efd2dSsekiya 		break;
139c37efd2dSsekiya 	default:
140c37efd2dSsekiya 		printf("unknown machine");
141c37efd2dSsekiya 		break;
142c37efd2dSsekiya 	}
143c37efd2dSsekiya 	printf(", board revision %x\n", mach_boardrev);
144c37efd2dSsekiya 
1450f58ff49Srumble 	printf("pic0: ");
1460f58ff49Srumble 
14709d9a0fbSsekiya 	if (reg & PIC_MODE_NOCACHE)
1480f58ff49Srumble 		printf("cache disabled");
14909d9a0fbSsekiya 	else
1500f58ff49Srumble 		printf("cache enabled");
15109d9a0fbSsekiya 
15209d9a0fbSsekiya 	if (reg & PIC_MODE_ISTREAM)
1530f58ff49Srumble 		printf(", instr streaming");
15409d9a0fbSsekiya 
15509d9a0fbSsekiya 	if (reg & PIC_MODE_STOREPARTIAL)
1560f58ff49Srumble 		printf(", store partial");
15709d9a0fbSsekiya 
15809d9a0fbSsekiya 	if (reg & PIC_MODE_BUSDRIVE)
1590f58ff49Srumble 		printf(", bus drive");
16009d9a0fbSsekiya 
16109d9a0fbSsekiya 	/* gio32 allow master, real time devices */
16209d9a0fbSsekiya 	reg = bus_space_read_4(psc.iot, psc.ioh, PIC_GIO32ARB_SLOT0);
16309d9a0fbSsekiya 	reg &= ~(PIC_GIO32ARB_SLOT_SLAVE | PIC_GIO32ARB_SLOT_LONG);
16409d9a0fbSsekiya 	bus_space_write_4(psc.iot, psc.ioh, PIC_GIO32ARB_SLOT0, reg);
16509d9a0fbSsekiya 
16609d9a0fbSsekiya 	reg = bus_space_read_4(psc.iot, psc.ioh, PIC_GIO32ARB_SLOT1);
16709d9a0fbSsekiya 	reg &= ~(PIC_GIO32ARB_SLOT_SLAVE | PIC_GIO32ARB_SLOT_LONG);
16809d9a0fbSsekiya 	bus_space_write_4(psc.iot, psc.ioh, PIC_GIO32ARB_SLOT1, reg);
16909d9a0fbSsekiya 
17009d9a0fbSsekiya 	/* default gio32 burst time */
17109d9a0fbSsekiya 	bus_space_write_4(psc.iot, psc.ioh, PIC_GIO32ARB_BURST,
17209d9a0fbSsekiya 			  PIC_GIO32ARB_DEFBURST);
17309d9a0fbSsekiya 
17409d9a0fbSsekiya 	/* default gio32 delay time */
17509d9a0fbSsekiya 	bus_space_write_4(psc.iot, psc.ioh, PIC_GIO32ARB_DELAY,
17609d9a0fbSsekiya 			  PIC_GIO32ARB_DEFDELAY);
17709d9a0fbSsekiya 
17809d9a0fbSsekiya 	printf("\n");
17909d9a0fbSsekiya 
180ca581a2fSrumble 	platform.intr5 = pic_bus_error;
181ca581a2fSrumble 
1820f58ff49Srumble 	/*
1830f58ff49Srumble 	 * A GIO bus exists on all IP12's. However, Personal Iris
1840f58ff49Srumble 	 * machines use VME for their expansion bus.
1850f58ff49Srumble 	 */
18609d9a0fbSsekiya 	iaa.iaa_name = "gio";
187*c7fb772bSthorpej 	(void)config_found(self, (void *)&iaa, pic_print, CFARGS_NONE);
18809d9a0fbSsekiya 
1890f58ff49Srumble 	pic_watchdog_enable();
19009d9a0fbSsekiya }
19109d9a0fbSsekiya 
19209d9a0fbSsekiya 
19309d9a0fbSsekiya static int
pic_print(void * aux,const char * name)19409d9a0fbSsekiya pic_print(void *aux, const char *name)
19509d9a0fbSsekiya {
19609d9a0fbSsekiya 	struct pic_attach_args *iaa = aux;
19709d9a0fbSsekiya 
19809d9a0fbSsekiya 	if (name)
19909d9a0fbSsekiya 		aprint_normal("%s at %s", iaa->iaa_name, name);
20009d9a0fbSsekiya 
20134267609Stsutsui 	return UNCONF;
20209d9a0fbSsekiya }
20309d9a0fbSsekiya 
2040f58ff49Srumble static void
pic_bus_reset(void)20509d9a0fbSsekiya pic_bus_reset(void)
20609d9a0fbSsekiya {
20734267609Stsutsui 
20809d9a0fbSsekiya 	bus_space_write_4(psc.iot, psc.ioh, PIC_PARITY_ERROR, 0);
20909d9a0fbSsekiya }
21009d9a0fbSsekiya 
2110f58ff49Srumble static void
pic_bus_error(vaddr_t pc,uint32_t status,uint32_t ipending)21223347d39Smatt pic_bus_error(vaddr_t pc, uint32_t status, uint32_t ipending)
213ca581a2fSrumble {
214ca581a2fSrumble 
215ca581a2fSrumble 	printf("pic0: bus error\n");
216ca581a2fSrumble 	pic_bus_reset();
217ca581a2fSrumble }
218ca581a2fSrumble 
219ca581a2fSrumble static void
pic_watchdog_enable(void)2200f58ff49Srumble pic_watchdog_enable(void)
22109d9a0fbSsekiya {
22288764f70Spooka 	uint32_t reg;
22388764f70Spooka 
22488764f70Spooka 	reg = bus_space_read_4(psc.iot, psc.ioh, PIC_CPUCTRL);
22588764f70Spooka 	reg |= PIC_CPUCTRL_WDOG;
22688764f70Spooka 	bus_space_write_4(psc.iot, psc.ioh, PIC_CPUCTRL, reg);
22788764f70Spooka }
22888764f70Spooka 
2290f58ff49Srumble static void
pic_watchdog_disable(void)2300f58ff49Srumble pic_watchdog_disable(void)
23188764f70Spooka {
23288764f70Spooka 	uint32_t reg;
23309d9a0fbSsekiya 
234a674ac1bSpooka 	reg = bus_space_read_4(psc.iot, psc.ioh, PIC_CPUCTRL);
23588764f70Spooka 	reg &= ~(PIC_CPUCTRL_WDOG);
23688764f70Spooka 	bus_space_write_4(psc.iot, psc.ioh, PIC_CPUCTRL, reg);
23788764f70Spooka }
23888764f70Spooka 
2390f58ff49Srumble static void
pic_watchdog_tickle(void)2400f58ff49Srumble pic_watchdog_tickle(void)
24188764f70Spooka {
24288764f70Spooka 
2430f58ff49Srumble 	pic_watchdog_disable();
2440f58ff49Srumble 	pic_watchdog_enable();
24509d9a0fbSsekiya }
246a4d0bfd7Srumble 
247a4d0bfd7Srumble /* intended to be called from gio/gio.c only */
248a4d0bfd7Srumble int
pic_gio32_arb_config(int slot,uint32_t flags)249a4d0bfd7Srumble pic_gio32_arb_config(int slot, uint32_t flags)
250a4d0bfd7Srumble {
251a4d0bfd7Srumble 	uint32_t reg;
252a4d0bfd7Srumble 
253a4d0bfd7Srumble 	/* only Indigo machines have GIO expansion slots (XXX HPLC?) */
254a4d0bfd7Srumble 	if (mach_subtype != MACH_SGI_IP12_HP1 &&
255a4d0bfd7Srumble 	    mach_subtype != MACH_SGI_IP12_HPLC)
25634267609Stsutsui 		return EINVAL;
257a4d0bfd7Srumble 
258a4d0bfd7Srumble 	/* graphics slot is not valid on IP12 */
259a4d0bfd7Srumble 	if (slot != GIO_SLOT_EXP0 && slot != GIO_SLOT_EXP1)
26034267609Stsutsui 		return EINVAL;
261a4d0bfd7Srumble 
262a4d0bfd7Srumble 	reg = bus_space_read_4(psc.iot, psc.ioh, (slot == GIO_SLOT_EXP0) ?
263a4d0bfd7Srumble 	    PIC_GIO32ARB_SLOT0 : PIC_GIO32ARB_SLOT1);
264a4d0bfd7Srumble 
265a4d0bfd7Srumble 	if (flags & GIO_ARB_RT)
266a4d0bfd7Srumble 		reg &= ~PIC_GIO32ARB_SLOT_LONG;
267a4d0bfd7Srumble 
268a4d0bfd7Srumble 	if (flags & GIO_ARB_LB)
269a4d0bfd7Srumble 		reg |= PIC_GIO32ARB_SLOT_LONG;
270a4d0bfd7Srumble 
271a4d0bfd7Srumble 	if (flags & GIO_ARB_MST)
272a4d0bfd7Srumble 		reg &= ~PIC_GIO32ARB_SLOT_SLAVE;
273a4d0bfd7Srumble 
274a4d0bfd7Srumble 	if (flags & GIO_ARB_SLV)
275a4d0bfd7Srumble 		reg |= PIC_GIO32ARB_SLOT_SLAVE;
276a4d0bfd7Srumble 
277a4d0bfd7Srumble 	bus_space_write_4(psc.iot, psc.ioh, (slot == GIO_SLOT_EXP0) ?
278a4d0bfd7Srumble 	    PIC_GIO32ARB_SLOT0 : PIC_GIO32ARB_SLOT1, reg);
279a4d0bfd7Srumble 
28034267609Stsutsui 	return 0;
281a4d0bfd7Srumble }
282