1 /* $OpenBSD: macobio.c,v 1.23 2022/03/13 12:33:01 mpi Exp $ */
2 /* $NetBSD: obio.c,v 1.6 1999/05/01 10:36:08 tsubai Exp $ */
3
4 /*-
5 * Copyright (C) 1998 Internet Research Institute, Inc.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by
19 * Internet Research Institute, Inc.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/device.h>
39
40 #include <dev/pci/pcivar.h>
41 #include <dev/pci/pcidevs.h>
42
43 #include <dev/ofw/openfirm.h>
44
45 #include <machine/bus.h>
46 #include <machine/autoconf.h>
47 #include <macppc/pci/macobio.h>
48
49 void macobio_attach(struct device *, struct device *, void *);
50 int macobio_match(struct device *, void *, void *);
51 int macobio_print(void *, const char *);
52 void macobio_modem_power(int enable);
53
54 struct macobio_softc {
55 struct device sc_dev;
56 int sc_node;
57 struct ppc_bus_space sc_membus_space;
58 int sc_id; /* copy of the PCI pa_id */
59 u_int8_t *obiomem;
60 };
61 struct cfdriver macobio_cd = {
62 NULL, "macobio", DV_DULL,
63 };
64
65
66 const struct cfattach macobio_ca = {
67 sizeof(struct macobio_softc), macobio_match, macobio_attach
68 };
69
70 int
macobio_match(struct device * parent,void * cf,void * aux)71 macobio_match(struct device *parent, void *cf, void *aux)
72 {
73 struct pci_attach_args *pa = aux;
74
75 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_APPLE)
76 switch (PCI_PRODUCT(pa->pa_id)) {
77
78 case PCI_PRODUCT_APPLE_GC:
79 case PCI_PRODUCT_APPLE_OHARE:
80 case PCI_PRODUCT_APPLE_HEATHROW:
81 case PCI_PRODUCT_APPLE_PADDINGTON:
82 case PCI_PRODUCT_APPLE_KEYLARGO:
83 case PCI_PRODUCT_APPLE_INTREPID:
84 case PCI_PRODUCT_APPLE_PANGEA_MACIO:
85 case PCI_PRODUCT_APPLE_SHASTA:
86 case PCI_PRODUCT_APPLE_K2_MACIO:
87 return 1;
88 }
89
90 return 0;
91 }
92
93 #define HEATHROW_FCR_OFFSET 0x38
94 u_int32_t *heathrow_FCR = NULL;
95
96 /*
97 * Attach all the sub-devices we can find
98 */
99 void
macobio_attach(struct device * parent,struct device * self,void * aux)100 macobio_attach(struct device *parent, struct device *self, void *aux)
101 {
102 struct macobio_softc *sc = (struct macobio_softc *)self;
103 struct pci_attach_args *pa = aux;
104 struct confargs ca;
105 int node, child, namelen;
106 u_int32_t reg[20];
107 int32_t intr[8];
108 char name[32];
109 int need_interrupt_controller = 0;
110
111 sc->sc_id = pa->pa_id; /* save of type for later */
112
113 switch (PCI_PRODUCT(pa->pa_id)) {
114
115 /* XXX should not use name */
116 case PCI_PRODUCT_APPLE_GC:
117 node = OF_finddevice("/bandit/gc");
118 need_interrupt_controller = 1;
119 break;
120
121 case PCI_PRODUCT_APPLE_OHARE:
122 node = OF_finddevice("/bandit/ohare");
123 need_interrupt_controller = 1;
124 break;
125
126 case PCI_PRODUCT_APPLE_HEATHROW:
127 case PCI_PRODUCT_APPLE_PADDINGTON:
128 node = OF_finddevice("mac-io");
129 if (node == -1)
130 node = OF_finddevice("/pci/mac-io");
131 if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg))
132 == (sizeof (reg[0]) * 5))
133 {
134 /* always ??? */
135 heathrow_FCR = mapiodev(reg[2] + HEATHROW_FCR_OFFSET,
136 4);
137 }
138 break;
139 case PCI_PRODUCT_APPLE_KEYLARGO:
140 case PCI_PRODUCT_APPLE_INTREPID:
141 case PCI_PRODUCT_APPLE_PANGEA_MACIO:
142 case PCI_PRODUCT_APPLE_SHASTA:
143 case PCI_PRODUCT_APPLE_K2_MACIO:
144 node = OF_finddevice("mac-io");
145 if (node == -1)
146 node = OF_finddevice("/pci/mac-io");
147 if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg))
148 == (sizeof (reg[0]) * 5))
149 sc->obiomem = mapiodev(reg[2], 0x100);
150 break;
151 default:
152 printf(": unknown macobio controller\n");
153 return;
154 }
155 sc->sc_node = node;
156
157 if (OF_getprop(node, "assigned-addresses", reg, sizeof(reg)) < 12)
158 return;
159
160 ca.ca_baseaddr = reg[2];
161
162 sc->sc_membus_space.bus_base = ca.ca_baseaddr;
163
164 ca.ca_iot = &sc->sc_membus_space;
165 ca.ca_dmat = pa->pa_dmat;
166
167 printf("\n");
168
169 /*
170 * This might be a hack, but it makes the interrupt controller
171 * attach as expected if a device node existed in the OF tree.
172 */
173 if (need_interrupt_controller) {
174 /* force attachment of legacy interrupt controllers */
175 ca.ca_name = "legacy-interrupt-controller";
176 ca.ca_node = 0;
177
178 ca.ca_nreg = 0;
179 ca.ca_nintr = 0;
180
181 ca.ca_reg = NULL;
182 ca.ca_intr = NULL;
183
184 config_found(self, &ca, macobio_print);
185 }
186
187 for (child = OF_child(node); child; child = OF_peer(child)) {
188 namelen = OF_getprop(child, "name", name, sizeof(name));
189 if (namelen < 0)
190 continue;
191 if (namelen >= sizeof(name))
192 continue;
193
194 name[namelen] = 0;
195 ca.ca_name = name;
196 ca.ca_node = child;
197
198 ca.ca_nreg = OF_getprop(child, "reg", reg, sizeof(reg));
199 ca.ca_nintr = OF_getprop(child, "AAPL,interrupts", intr,
200 sizeof(intr));
201 if (ca.ca_nintr == -1)
202 ca.ca_nintr = OF_getprop(child, "interrupts", intr,
203 sizeof(intr));
204
205 ca.ca_reg = reg;
206 ca.ca_intr = intr;
207
208 config_found(self, &ca, macobio_print);
209 }
210 }
211
212 int
macobio_print(void * aux,const char * macobio)213 macobio_print(void *aux, const char *macobio)
214 {
215 struct confargs *ca = aux;
216
217 if (macobio)
218 printf("\"%s\" at %s", ca->ca_name, macobio);
219
220 if (ca->ca_nreg > 0)
221 printf(" offset 0x%x", ca->ca_reg[0]);
222
223 return UNCONF;
224 }
225
226 void *
mac_intr_establish(void * lcv,int irq,int type,int level,int (* ih_fun)(void *),void * ih_arg,const char * name)227 mac_intr_establish(void * lcv, int irq, int type, int level,
228 int (*ih_fun)(void *), void *ih_arg, const char *name)
229 {
230 return (*intr_establish_func)(lcv, irq, type, level, ih_fun,
231 ih_arg, name);
232 }
233 void
mac_intr_disestablish(void * lcp,void * arg)234 mac_intr_disestablish(void *lcp, void *arg)
235 {
236 (*intr_disestablish_func)(lcp, arg);
237 }
238
239 void
macobio_enable(int offset,u_int32_t bits)240 macobio_enable(int offset, u_int32_t bits)
241 {
242 struct macobio_softc *sc = macobio_cd.cd_devs[0];
243 if (sc->obiomem == 0)
244 return;
245
246 bits |= in32rb(sc->obiomem + offset);
247 out32rb(sc->obiomem + offset, bits);
248 }
249 void
macobio_disable(int offset,u_int32_t bits)250 macobio_disable(int offset, u_int32_t bits)
251 {
252 struct macobio_softc *sc = macobio_cd.cd_devs[0];
253 if (sc->obiomem == 0)
254 return;
255
256 bits = in32rb(sc->obiomem + offset) & ~bits;
257 out32rb(sc->obiomem + offset, bits);
258 }
259
260 uint8_t
macobio_read(int offset)261 macobio_read(int offset)
262 {
263 struct macobio_softc *sc = macobio_cd.cd_devs[0];
264 if (sc->obiomem == 0)
265 return -1;
266
267 return in8rb(sc->obiomem + offset);
268 }
269
270 void
macobio_write(int offset,uint8_t bits)271 macobio_write(int offset, uint8_t bits)
272 {
273 struct macobio_softc *sc = macobio_cd.cd_devs[0];
274 if (sc->obiomem == 0)
275 return;
276
277 out8rb(sc->obiomem + offset, bits);
278 }
279
280 void
macobio_modem_power(int enable)281 macobio_modem_power(int enable)
282 {
283 u_int32_t val;
284 struct macobio_softc *sc = macobio_cd.cd_devs[0];
285 if (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_KEYLARGO ||
286 PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_INTREPID) {
287 val = in32rb(sc->obiomem + 0x40);
288 if (enable)
289 val = val & ~((u_int32_t)1<<25);
290 else
291 val = val | ((u_int32_t)1<<25);
292 out32rb(sc->obiomem + 0x40, val);
293 }
294 if (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_APPLE_PANGEA_MACIO) {
295 if (enable) {
296 /* set reset */
297 out8(sc->obiomem + 0x006a + 0x03, 0x04);
298 /* power modem on */
299 out8(sc->obiomem + 0x006a + 0x02, 0x04);
300 /* unset reset */
301 out8(sc->obiomem + 0x006a + 0x03, 0x05);
302 } else {
303 /* disable it how? */
304 }
305 }
306 }
307