xref: /openbsd-src/sys/arch/macppc/pci/macobio.c (revision 89ed722c33692ad18452b9d394c650f8adc43407)
1*89ed722cSmpi /*	$OpenBSD: macobio.c,v 1.23 2022/03/13 12:33:01 mpi Exp $	*/
2a3667f10Sdrahn /*	$NetBSD: obio.c,v 1.6 1999/05/01 10:36:08 tsubai Exp $	*/
3a3667f10Sdrahn 
4a3667f10Sdrahn /*-
5a3667f10Sdrahn  * Copyright (C) 1998	Internet Research Institute, Inc.
6a3667f10Sdrahn  * All rights reserved.
7a3667f10Sdrahn  *
8a3667f10Sdrahn  * Redistribution and use in source and binary forms, with or without
9a3667f10Sdrahn  * modification, are permitted provided that the following conditions
10a3667f10Sdrahn  * are met:
11a3667f10Sdrahn  * 1. Redistributions of source code must retain the above copyright
12a3667f10Sdrahn  *    notice, this list of conditions and the following disclaimer.
13a3667f10Sdrahn  * 2. Redistributions in binary form must reproduce the above copyright
14a3667f10Sdrahn  *    notice, this list of conditions and the following disclaimer in the
15a3667f10Sdrahn  *    documentation and/or other materials provided with the distribution.
16a3667f10Sdrahn  * 3. All advertising materials mentioning features or use of this software
17a3667f10Sdrahn  *    must display the following acknowledgement:
18a3667f10Sdrahn  *	This product includes software developed by
19a3667f10Sdrahn  *	Internet Research Institute, Inc.
20a3667f10Sdrahn  * 4. The name of the author may not be used to endorse or promote products
21a3667f10Sdrahn  *    derived from this software without specific prior written permission.
22a3667f10Sdrahn  *
23a3667f10Sdrahn  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24a3667f10Sdrahn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25a3667f10Sdrahn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26a3667f10Sdrahn  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27a3667f10Sdrahn  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28a3667f10Sdrahn  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29a3667f10Sdrahn  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30a3667f10Sdrahn  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31a3667f10Sdrahn  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32a3667f10Sdrahn  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33a3667f10Sdrahn  */
34a3667f10Sdrahn 
35a3667f10Sdrahn #include <sys/param.h>
36a3667f10Sdrahn #include <sys/systm.h>
37a3667f10Sdrahn #include <sys/kernel.h>
38a3667f10Sdrahn #include <sys/device.h>
39a3667f10Sdrahn 
40a3667f10Sdrahn #include <dev/pci/pcivar.h>
41a3667f10Sdrahn #include <dev/pci/pcidevs.h>
42a3667f10Sdrahn 
43a3667f10Sdrahn #include <dev/ofw/openfirm.h>
44a3667f10Sdrahn 
45a3667f10Sdrahn #include <machine/bus.h>
46a3667f10Sdrahn #include <machine/autoconf.h>
4739dd359fSmpi #include <macppc/pci/macobio.h>
48a3667f10Sdrahn 
49c4071fd1Smillert void macobio_attach(struct device *, struct device *, void *);
50c4071fd1Smillert int macobio_match(struct device *, void *, void *);
51c4071fd1Smillert int macobio_print(void *, const char *);
52601244bbSdrahn void macobio_modem_power(int enable);
53601244bbSdrahn 
54a3667f10Sdrahn struct macobio_softc {
55a3667f10Sdrahn 	struct device sc_dev;
56a3667f10Sdrahn 	int sc_node;
57a3667f10Sdrahn 	struct ppc_bus_space sc_membus_space;
583851afa1Sdrahn 	int	sc_id; /* copy of the PCI pa_id */
593851afa1Sdrahn 	u_int8_t *obiomem;
60a3667f10Sdrahn };
61a3667f10Sdrahn struct cfdriver macobio_cd = {
62a3667f10Sdrahn 	NULL, "macobio", DV_DULL,
63a3667f10Sdrahn };
64a3667f10Sdrahn 
65a3667f10Sdrahn 
66*89ed722cSmpi const struct cfattach macobio_ca = {
67a3667f10Sdrahn 	sizeof(struct macobio_softc), macobio_match, macobio_attach
68a3667f10Sdrahn };
69a3667f10Sdrahn 
70a3667f10Sdrahn int
macobio_match(struct device * parent,void * cf,void * aux)71601244bbSdrahn macobio_match(struct device *parent, void *cf, void *aux)
72a3667f10Sdrahn {
73a3667f10Sdrahn 	struct pci_attach_args *pa = aux;
74a3667f10Sdrahn 
75a3667f10Sdrahn 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_APPLE)
76a3667f10Sdrahn 		switch (PCI_PRODUCT(pa->pa_id)) {
77a3667f10Sdrahn 
78a3667f10Sdrahn 		case PCI_PRODUCT_APPLE_GC:
79a3667f10Sdrahn 		case PCI_PRODUCT_APPLE_OHARE:
80a3667f10Sdrahn 		case PCI_PRODUCT_APPLE_HEATHROW:
81a3667f10Sdrahn 		case PCI_PRODUCT_APPLE_PADDINGTON:
82a3667f10Sdrahn 		case PCI_PRODUCT_APPLE_KEYLARGO:
8382c22bccStdeval 		case PCI_PRODUCT_APPLE_INTREPID:
84a3667f10Sdrahn 		case PCI_PRODUCT_APPLE_PANGEA_MACIO:
8581bf92f6Skettenis 		case PCI_PRODUCT_APPLE_SHASTA:
86a119b60fSbrad 		case PCI_PRODUCT_APPLE_K2_MACIO:
87a3667f10Sdrahn 			return 1;
88a3667f10Sdrahn 		}
89a3667f10Sdrahn 
90a3667f10Sdrahn 	return 0;
91a3667f10Sdrahn }
92a3667f10Sdrahn 
93a3667f10Sdrahn #define HEATHROW_FCR_OFFSET 0x38
94a3667f10Sdrahn u_int32_t *heathrow_FCR = NULL;
95a3667f10Sdrahn 
96a3667f10Sdrahn /*
97a3667f10Sdrahn  * Attach all the sub-devices we can find
98a3667f10Sdrahn  */
99a3667f10Sdrahn void
macobio_attach(struct device * parent,struct device * self,void * aux)100601244bbSdrahn macobio_attach(struct device *parent, struct device *self, void *aux)
101a3667f10Sdrahn {
102a3667f10Sdrahn 	struct macobio_softc *sc = (struct macobio_softc *)self;
103a3667f10Sdrahn 	struct pci_attach_args *pa = aux;
104a3667f10Sdrahn 	struct confargs ca;
105a3667f10Sdrahn 	int node, child, namelen;
106a3667f10Sdrahn 	u_int32_t reg[20];
107a3667f10Sdrahn 	int32_t intr[8];
108a3667f10Sdrahn 	char name[32];
109a3667f10Sdrahn 	int need_interrupt_controller = 0;
110a3667f10Sdrahn 
1113851afa1Sdrahn 	sc->sc_id = pa->pa_id; /* save of type for later */
1123851afa1Sdrahn 
113a3667f10Sdrahn 	switch (PCI_PRODUCT(pa->pa_id)) {
114a3667f10Sdrahn 
115a3667f10Sdrahn 	/* XXX should not use name */
116a3667f10Sdrahn 	case PCI_PRODUCT_APPLE_GC:
117a3667f10Sdrahn 		node = OF_finddevice("/bandit/gc");
118a3667f10Sdrahn 		need_interrupt_controller = 1;
119a3667f10Sdrahn 		break;
120a3667f10Sdrahn 
121a3667f10Sdrahn 	case PCI_PRODUCT_APPLE_OHARE:
122a3667f10Sdrahn 		node = OF_finddevice("/bandit/ohare");
123a3667f10Sdrahn 		need_interrupt_controller = 1;
124a3667f10Sdrahn 		break;
125a3667f10Sdrahn 
126a3667f10Sdrahn 	case PCI_PRODUCT_APPLE_HEATHROW:
127a3667f10Sdrahn 	case PCI_PRODUCT_APPLE_PADDINGTON:
128a3667f10Sdrahn 		node = OF_finddevice("mac-io");
129a3667f10Sdrahn 		if (node == -1)
130a3667f10Sdrahn 			node = OF_finddevice("/pci/mac-io");
1316a1aaa0fSderaadt 		if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg))
1326a1aaa0fSderaadt 			== (sizeof (reg[0]) * 5))
1336a1aaa0fSderaadt 		{
134a3667f10Sdrahn 			/* always ??? */
135a3667f10Sdrahn 			heathrow_FCR = mapiodev(reg[2] + HEATHROW_FCR_OFFSET,
136a3667f10Sdrahn 			    4);
137a3667f10Sdrahn 		}
138a3667f10Sdrahn 		break;
139a3667f10Sdrahn 	case PCI_PRODUCT_APPLE_KEYLARGO:
14082c22bccStdeval 	case PCI_PRODUCT_APPLE_INTREPID:
141a3667f10Sdrahn 	case PCI_PRODUCT_APPLE_PANGEA_MACIO:
14281bf92f6Skettenis 	case PCI_PRODUCT_APPLE_SHASTA:
143a119b60fSbrad 	case PCI_PRODUCT_APPLE_K2_MACIO:
144a3667f10Sdrahn 		node = OF_finddevice("mac-io");
145a3667f10Sdrahn 		if (node == -1)
146a3667f10Sdrahn 			node = OF_finddevice("/pci/mac-io");
1476a1aaa0fSderaadt 		if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg))
1486a1aaa0fSderaadt 		    == (sizeof (reg[0]) * 5))
1493851afa1Sdrahn 			 sc->obiomem = mapiodev(reg[2], 0x100);
150a3667f10Sdrahn 		break;
151a3667f10Sdrahn 	default:
152a3667f10Sdrahn 		printf(": unknown macobio controller\n");
153a3667f10Sdrahn 		return;
154a3667f10Sdrahn 	}
155a3667f10Sdrahn 	sc->sc_node = node;
156a3667f10Sdrahn 
157a3667f10Sdrahn 	if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg)) < 12)
158a3667f10Sdrahn 		return;
159a3667f10Sdrahn 
160a3667f10Sdrahn 	ca.ca_baseaddr = reg[2];
161a3667f10Sdrahn 
162a3667f10Sdrahn 	sc->sc_membus_space.bus_base = ca.ca_baseaddr;
163a3667f10Sdrahn 
164a3667f10Sdrahn 	ca.ca_iot = &sc->sc_membus_space;
165c9b17401Smickey 	ca.ca_dmat = pa->pa_dmat;
166a3667f10Sdrahn 
167a3667f10Sdrahn 	printf("\n");
168a3667f10Sdrahn 
169a3667f10Sdrahn 	/*
170a3667f10Sdrahn 	 * This might be a hack, but it makes the interrupt controller
171a3667f10Sdrahn 	 * attach as expected if a device node existed in the OF tree.
172a3667f10Sdrahn 	 */
173a3667f10Sdrahn 	if (need_interrupt_controller) {
174a3667f10Sdrahn 		/* force attachment of legacy interrupt controllers */
175a3667f10Sdrahn 		ca.ca_name = "legacy-interrupt-controller";
176a3667f10Sdrahn 		ca.ca_node = 0;
177a3667f10Sdrahn 
178a3667f10Sdrahn 		ca.ca_nreg  = 0;
179a3667f10Sdrahn 		ca.ca_nintr = 0;
180a3667f10Sdrahn 
18184b94647Smiod 		ca.ca_reg = NULL;
18284b94647Smiod 		ca.ca_intr = NULL;
183a3667f10Sdrahn 
184a3667f10Sdrahn 		config_found(self, &ca, macobio_print);
185a3667f10Sdrahn 	}
186a3667f10Sdrahn 
187a3667f10Sdrahn 	for (child = OF_child(node); child; child = OF_peer(child)) {
188a3667f10Sdrahn 		namelen = OF_getprop(child, "name", name, sizeof(name));
189a3667f10Sdrahn 		if (namelen < 0)
190a3667f10Sdrahn 			continue;
191a3667f10Sdrahn 		if (namelen >= sizeof(name))
192a3667f10Sdrahn 			continue;
193a3667f10Sdrahn 
194a3667f10Sdrahn 		name[namelen] = 0;
195a3667f10Sdrahn 		ca.ca_name = name;
196a3667f10Sdrahn 		ca.ca_node = child;
197a3667f10Sdrahn 
198a3667f10Sdrahn 		ca.ca_nreg  = OF_getprop(child, "reg", reg, sizeof(reg));
199a3667f10Sdrahn 		ca.ca_nintr = OF_getprop(child, "AAPL,interrupts", intr,
200a3667f10Sdrahn 				sizeof(intr));
201a3667f10Sdrahn 		if (ca.ca_nintr == -1)
202a3667f10Sdrahn 			ca.ca_nintr = OF_getprop(child, "interrupts", intr,
203a3667f10Sdrahn 					sizeof(intr));
204a3667f10Sdrahn 
205a3667f10Sdrahn 		ca.ca_reg = reg;
206a3667f10Sdrahn 		ca.ca_intr = intr;
207a3667f10Sdrahn 
208a3667f10Sdrahn 		config_found(self, &ca, macobio_print);
209a3667f10Sdrahn 	}
210a3667f10Sdrahn }
211a3667f10Sdrahn 
212a3667f10Sdrahn int
macobio_print(void * aux,const char * macobio)213601244bbSdrahn macobio_print(void *aux, const char *macobio)
214a3667f10Sdrahn {
215a3667f10Sdrahn 	struct confargs *ca = aux;
216a3667f10Sdrahn 
217a3667f10Sdrahn 	if (macobio)
218f93ad0cbSkettenis 		printf("\"%s\" at %s", ca->ca_name, macobio);
219a3667f10Sdrahn 
220a3667f10Sdrahn 	if (ca->ca_nreg > 0)
221a3667f10Sdrahn 		printf(" offset 0x%x", ca->ca_reg[0]);
222a3667f10Sdrahn 
223a3667f10Sdrahn 	return UNCONF;
224a3667f10Sdrahn }
225a3667f10Sdrahn 
226a3667f10Sdrahn void *
mac_intr_establish(void * lcv,int irq,int type,int level,int (* ih_fun)(void *),void * ih_arg,const char * name)227601244bbSdrahn mac_intr_establish(void * lcv, int irq, int type, int level,
228c03b1b92Smk     int (*ih_fun)(void *), void *ih_arg, const char *name)
229a3667f10Sdrahn {
2300030dec3Smpi 	return (*intr_establish_func)(lcv, irq, type, level, ih_fun,
231a3667f10Sdrahn 	    ih_arg, name);
232a3667f10Sdrahn }
233a3667f10Sdrahn void
mac_intr_disestablish(void * lcp,void * arg)234601244bbSdrahn mac_intr_disestablish(void *lcp, void *arg)
235a3667f10Sdrahn {
2360030dec3Smpi 	(*intr_disestablish_func)(lcp, arg);
237a3667f10Sdrahn }
2383851afa1Sdrahn 
23941ebe004Sdrahn void
macobio_enable(int offset,u_int32_t bits)24039dd359fSmpi macobio_enable(int offset, u_int32_t bits)
24141ebe004Sdrahn {
24241ebe004Sdrahn 	struct macobio_softc *sc = macobio_cd.cd_devs[0];
24341ebe004Sdrahn 	if (sc->obiomem == 0)
24441ebe004Sdrahn 		return;
24541ebe004Sdrahn 
24641ebe004Sdrahn 	bits |=  in32rb(sc->obiomem + offset);
24741ebe004Sdrahn 	out32rb(sc->obiomem + offset, bits);
24841ebe004Sdrahn }
24941ebe004Sdrahn void
macobio_disable(int offset,u_int32_t bits)25039dd359fSmpi macobio_disable(int offset, u_int32_t bits)
25141ebe004Sdrahn {
25241ebe004Sdrahn 	struct macobio_softc *sc = macobio_cd.cd_devs[0];
25341ebe004Sdrahn 	if (sc->obiomem == 0)
25441ebe004Sdrahn 		return;
25541ebe004Sdrahn 
25641ebe004Sdrahn 	bits =  in32rb(sc->obiomem + offset) & ~bits;
25741ebe004Sdrahn 	out32rb(sc->obiomem + offset, bits);
25841ebe004Sdrahn }
25941ebe004Sdrahn 
260e3423c0fSmpi uint8_t
macobio_read(int offset)26139dd359fSmpi macobio_read(int offset)
26241ebe004Sdrahn {
26341ebe004Sdrahn 	struct macobio_softc *sc = macobio_cd.cd_devs[0];
26441ebe004Sdrahn 	if (sc->obiomem == 0)
26541ebe004Sdrahn 		return -1;
26641ebe004Sdrahn 
267e3423c0fSmpi 	return in8rb(sc->obiomem + offset);
26841ebe004Sdrahn }
26941ebe004Sdrahn 
2703851afa1Sdrahn void
macobio_write(int offset,uint8_t bits)271e3423c0fSmpi macobio_write(int offset, uint8_t bits)
27239dd359fSmpi {
27339dd359fSmpi 	struct macobio_softc *sc = macobio_cd.cd_devs[0];
27439dd359fSmpi 	if (sc->obiomem == 0)
27539dd359fSmpi 		return;
27639dd359fSmpi 
277e3423c0fSmpi 	out8rb(sc->obiomem + offset, bits);
27839dd359fSmpi }
27939dd359fSmpi 
28039dd359fSmpi void
macobio_modem_power(int enable)2813851afa1Sdrahn macobio_modem_power(int enable)
2823851afa1Sdrahn {
2833851afa1Sdrahn 	u_int32_t val;
2843851afa1Sdrahn 	struct macobio_softc *sc = macobio_cd.cd_devs[0];
28582c22bccStdeval 	if (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_KEYLARGO ||
28682c22bccStdeval 	    PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_INTREPID) {
2873851afa1Sdrahn 		val = in32rb(sc->obiomem + 0x40);
2883851afa1Sdrahn 		if (enable)
2893851afa1Sdrahn 			val = val & ~((u_int32_t)1<<25);
2903851afa1Sdrahn 		else
2913851afa1Sdrahn 			val = val | ((u_int32_t)1<<25);
2923851afa1Sdrahn 		out32rb(sc->obiomem + 0x40, val);
2933851afa1Sdrahn 	}
2943851afa1Sdrahn 	if (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_PANGEA_MACIO) {
2953851afa1Sdrahn 		if (enable) {
2963851afa1Sdrahn 			/* set reset */
2973851afa1Sdrahn 			out8(sc->obiomem + 0x006a + 0x03, 0x04);
2983851afa1Sdrahn 			/* power modem on */
2993851afa1Sdrahn 			out8(sc->obiomem + 0x006a + 0x02, 0x04);
3003851afa1Sdrahn 			/* unset reset */
3013851afa1Sdrahn 			out8(sc->obiomem + 0x006a + 0x03, 0x05);
3023851afa1Sdrahn 		}  else {
3033851afa1Sdrahn 			/* disable it how? */
3043851afa1Sdrahn 		}
3053851afa1Sdrahn 	}
3063851afa1Sdrahn }
307