oioc.c revision 1.1 1 1.1 rumble /* $NetBSD: oioc.c,v 1.1 2009/02/10 06:04:56 rumble Exp $ */
2 1.1 rumble
3 1.1 rumble /*
4 1.1 rumble * Copyright (c) 2009 Stephen M. Rumble
5 1.1 rumble * All rights reserved.
6 1.1 rumble *
7 1.1 rumble * Redistribution and use in source and binary forms, with or without
8 1.1 rumble * modification, are permitted provided that the following conditions
9 1.1 rumble * are met:
10 1.1 rumble * 1. Redistributions of source code must retain the above copyright
11 1.1 rumble * notice, this list of conditions and the following disclaimer.
12 1.1 rumble * 2. The name of the author may not be used to endorse or promote products
13 1.1 rumble * derived from this software without specific prior written permission.
14 1.1 rumble *
15 1.1 rumble * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 1.1 rumble * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 1.1 rumble * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 1.1 rumble * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 1.1 rumble * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 1.1 rumble * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 1.1 rumble * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 1.1 rumble * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 1.1 rumble * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 1.1 rumble * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 1.1 rumble */
26 1.1 rumble
27 1.1 rumble /*
28 1.1 rumble * IOC1/IOC2 chips on IP4 and IP6/IP10 machines. This interfaces the SCSI
29 1.1 rumble * and Ethernet controllers, performs DMA for the former, and does address
30 1.1 rumble * space translation for the latter (maps the lance memory space to physical
31 1.1 rumble * pages).
32 1.1 rumble *
33 1.1 rumble * 'I/O Controller' is a sufficiently generic name that SGI created another
34 1.1 rumble * one for IP24, which basically stuffed a bunch of miscellany on an ASIC.
35 1.1 rumble * So, we'll call ourselves 'Old IOC' and hope that there wasn't an even older
36 1.1 rumble * one.
37 1.1 rumble */
38 1.1 rumble
39 1.1 rumble #include <sys/cdefs.h>
40 1.1 rumble __KERNEL_RCSID(0, "$NetBSD: oioc.c,v 1.1 2009/02/10 06:04:56 rumble Exp $");
41 1.1 rumble
42 1.1 rumble #include <sys/param.h>
43 1.1 rumble #include <sys/device.h>
44 1.1 rumble
45 1.1 rumble #define _SGIMIPS_BUS_DMA_PRIVATE
46 1.1 rumble #include <machine/cpu.h>
47 1.1 rumble #include <machine/locore.h>
48 1.1 rumble #include <machine/autoconf.h>
49 1.1 rumble #include <machine/bus.h>
50 1.1 rumble #include <machine/machtype.h>
51 1.1 rumble #include <machine/sysconf.h>
52 1.1 rumble
53 1.1 rumble #include <sgimips/ioc/oiocreg.h>
54 1.1 rumble #include <sgimips/ioc/oiocvar.h>
55 1.1 rumble
56 1.1 rumble #include "locators.h"
57 1.1 rumble
58 1.1 rumble struct oioc_softc {
59 1.1 rumble struct device sc_dev;
60 1.1 rumble
61 1.1 rumble int sc_burst_dma;
62 1.1 rumble
63 1.1 rumble bus_space_tag_t sc_iot;
64 1.1 rumble bus_space_handle_t sc_ioh;
65 1.1 rumble };
66 1.1 rumble
67 1.1 rumble static int oioc_match(struct device *, struct cfdata *, void *);
68 1.1 rumble static void oioc_attach(struct device *, struct device *, void *);
69 1.1 rumble static int oioc_print(void *, const char *);
70 1.1 rumble
71 1.1 rumble CFATTACH_DECL(oioc, sizeof(struct oioc_softc),
72 1.1 rumble oioc_match, oioc_attach, NULL, NULL);
73 1.1 rumble
74 1.1 rumble struct oioc_device {
75 1.1 rumble const char *od_name;
76 1.1 rumble int od_irq;
77 1.1 rumble } oioc_devices[] = {
78 1.1 rumble { "oiocsc", 4 },
79 1.1 rumble { "le", 5 },
80 1.1 rumble { NULL, 0 }
81 1.1 rumble };
82 1.1 rumble
83 1.1 rumble static int
84 1.1 rumble oioc_match(struct device * parent, struct cfdata * match, void *aux)
85 1.1 rumble {
86 1.1 rumble
87 1.1 rumble switch(mach_type) {
88 1.1 rumble case MACH_SGI_IP4:
89 1.1 rumble case MACH_SGI_IP6 | MACH_SGI_IP10:
90 1.1 rumble return (1);
91 1.1 rumble }
92 1.1 rumble
93 1.1 rumble return (0);
94 1.1 rumble }
95 1.1 rumble
96 1.1 rumble static void
97 1.1 rumble oioc_attach(struct device * parent, struct device * self, void *aux)
98 1.1 rumble {
99 1.1 rumble struct oioc_softc *sc = (struct oioc_softc *)self;
100 1.1 rumble struct mainbus_attach_args *ma = aux;
101 1.1 rumble uint32_t reg1, reg2;
102 1.1 rumble int oiocrev, i;
103 1.1 rumble
104 1.1 rumble sc->sc_iot = SGIMIPS_BUS_SPACE_NORMAL;
105 1.1 rumble if (bus_space_map(sc->sc_iot, ma->ma_addr, 0,
106 1.1 rumble BUS_SPACE_MAP_LINEAR, &sc->sc_ioh))
107 1.1 rumble panic("oioc_attach: could not allocate memory\n");
108 1.1 rumble
109 1.1 rumble if (platform.badaddr((void *)MIPS_PHYS_TO_KSEG1(ma->ma_addr +
110 1.1 rumble OIOC2_CONFIG), 4))
111 1.1 rumble oiocrev = 1;
112 1.1 rumble else
113 1.1 rumble oiocrev = 2;
114 1.1 rumble
115 1.1 rumble printf("\noioc0: Old SGI IOC%d\n", oiocrev);
116 1.1 rumble
117 1.1 rumble if (oiocrev == 2) {
118 1.1 rumble char buf[64];
119 1.1 rumble
120 1.1 rumble /* Try to enable burst mode. If we can't, we can't... */
121 1.1 rumble reg1 = 12 << OIOC2_CONFIG_HIWAT_SHFT;
122 1.1 rumble reg1 |= OIOC2_CONFIG_BURST_MASK;
123 1.1 rumble bus_space_write_4(sc->sc_iot, sc->sc_ioh, OIOC2_CONFIG, reg1);
124 1.1 rumble DELAY(1000);
125 1.1 rumble reg2 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, OIOC2_CONFIG);
126 1.1 rumble if ((reg2 & (reg1 | OIOC2_CONFIG_NOSYNC_MASK)) == reg1)
127 1.1 rumble sc->sc_burst_dma = 1;
128 1.1 rumble
129 1.1 rumble snprintb(buf, sizeof(buf),
130 1.1 rumble "\177\020"
131 1.1 rumble "f\0\4HIWAT\0"
132 1.1 rumble "f\4\2ID\0"
133 1.1 rumble "b\6NOSYNC\0"
134 1.1 rumble "b\7BURST\0"
135 1.1 rumble "f\x8\7COUNT\0"
136 1.1 rumble "f\x10\6SCP\0"
137 1.1 rumble "f\x1c\4IOP\0\0",
138 1.1 rumble (u_quad_t)reg2 & 0xffffffff);
139 1.1 rumble printf("oioc0: %s\n", buf);
140 1.1 rumble }
141 1.1 rumble
142 1.1 rumble printf("oioc0: Burst DMA %ssupported\n",
143 1.1 rumble (sc->sc_burst_dma) ? "" : "not ");
144 1.1 rumble
145 1.1 rumble for (i = 0; oioc_devices[i].od_name != NULL; i++) {
146 1.1 rumble struct oioc_attach_args oa;
147 1.1 rumble
148 1.1 rumble oa.oa_name = oioc_devices[i].od_name;
149 1.1 rumble oa.oa_irq = oioc_devices[i].od_irq;
150 1.1 rumble oa.oa_burst_dma = sc->sc_burst_dma;
151 1.1 rumble oa.oa_st = SGIMIPS_BUS_SPACE_NORMAL;
152 1.1 rumble oa.oa_sh = sc->sc_ioh;
153 1.1 rumble oa.oa_dmat = &sgimips_default_bus_dma_tag;
154 1.1 rumble config_found_ia(self, "oioc", &oa, oioc_print);
155 1.1 rumble }
156 1.1 rumble }
157 1.1 rumble
158 1.1 rumble static int
159 1.1 rumble oioc_print(void *aux, const char *pnp)
160 1.1 rumble {
161 1.1 rumble struct oioc_attach_args *oa = aux;
162 1.1 rumble
163 1.1 rumble if (pnp)
164 1.1 rumble printf("%s at %s", oa->oa_name, pnp);
165 1.1 rumble
166 1.1 rumble return (UNCONF);
167 1.1 rumble }
168