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