i80321.c revision 1.1.2.4 1 /* $NetBSD: i80321.c,v 1.1.2.4 2002/08/01 02:41:20 nathanw Exp $ */
2
3 /*
4 * Copyright (c) 2002 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 /*
39 * Autoconfiguration support for the Intel i80321 I/O Processor.
40 */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/device.h>
45
46 #include <machine/bus.h>
47
48 #include <arm/xscale/i80321reg.h>
49 #include <arm/xscale/i80321var.h>
50
51 /*
52 * Statically-allocated bus_space stucture used to access the
53 * i80321's own registers.
54 */
55 struct bus_space i80321_bs_tag;
56
57 /*
58 * There can be only one i80321, so we keep a global pointer to
59 * the softc, so board-specific code can use features of the
60 * i80321 without having to have a handle on the softc itself.
61 */
62 struct i80321_softc *i80321_softc;
63
64 int i80321_iopxs_print(void *, const char *);
65 int i80321_pcibus_print(void *, const char *);
66
67 /* Built-in devices. */
68 static const struct iopxs_device {
69 const char *id_name;
70 bus_addr_t id_offset;
71 bus_size_t id_size;
72 } iopxs_devices[] = {
73 { "iopaau", VERDE_AAU_BASE, VERDE_AAU_SIZE },
74 { "iopdma", VERDE_DMA_BASE, VERDE_DMA_SIZE },
75 { "iopssp", VERDE_SSP_BASE, VERDE_SSP_SIZE },
76 { "iopwdog", 0, 0 },
77 { NULL, 0, 0 }
78 };
79
80 /*
81 * i80321_attach:
82 *
83 * Board-independent attach routine for the i80321.
84 */
85 void
86 i80321_attach(struct i80321_softc *sc)
87 {
88 struct pcibus_attach_args pba;
89 const struct iopxs_device *id;
90 struct iopxs_attach_args ia;
91 pcireg_t preg;
92
93 i80321_softc = sc;
94
95 /*
96 * Slice off some useful subregion handles.
97 */
98
99 if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
100 VERDE_ATU_SIZE, &sc->sc_atu_sh))
101 panic("%s: unable to subregion ATU registers\n",
102 sc->sc_dev.dv_xname);
103
104 /* We expect the Memory Controller to be already sliced off. */
105
106 /*
107 * Program the Inbound windows.
108 */
109 if (sc->sc_is_host) {
110 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
111 PCI_MAPREG_START, sc->sc_iwin[0].iwin_base_lo);
112 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
113 PCI_MAPREG_START + 0x04, sc->sc_iwin[0].iwin_base_hi);
114 }
115 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0,
116 (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0);
117 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0,
118 sc->sc_iwin[0].iwin_xlate);
119
120 if (sc->sc_is_host) {
121 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
122 PCI_MAPREG_START + 0x08, sc->sc_iwin[1].iwin_base_lo);
123 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
124 PCI_MAPREG_START + 0x0c, sc->sc_iwin[1].iwin_base_hi);
125 }
126 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1,
127 (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0);
128 /* no xlate for window 1 */
129
130 if (sc->sc_is_host) {
131 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
132 PCI_MAPREG_START + 0x10, sc->sc_iwin[2].iwin_base_lo);
133 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
134 PCI_MAPREG_START + 0x14, sc->sc_iwin[2].iwin_base_hi);
135 }
136 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2,
137 (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0);
138 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2,
139 sc->sc_iwin[2].iwin_xlate);
140
141 if (sc->sc_is_host) {
142 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
143 ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo);
144 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
145 ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi);
146 }
147 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3,
148 (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0);
149 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3,
150 sc->sc_iwin[3].iwin_xlate);
151
152 /*
153 * Mask (disable) the ATU interrupt sources.
154 * XXX May want to revisit this if we encounter
155 * XXX an application that wants it.
156 */
157 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
158 ATU_ATUIMR,
159 ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST|
160 ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM|
161 ATUIMR_PTAT|ATUIMR_PMPE);
162
163 /*
164 * Program the outbound windows.
165 */
166 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
167 ATU_OIOWTVR, sc->sc_ioout_xlate);
168
169 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
170 ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo);
171 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
172 ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi);
173
174 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
175 ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo);
176 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
177 ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi);
178
179 /*
180 * Set up the ATU configuration register. All we do
181 * right now is enable Outbound Windows.
182 */
183 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR,
184 ATUCR_OUT_EN);
185
186 /*
187 * Enable bus mastering, memory access, SERR, and parity
188 * checking on the ATU.
189 */
190 if (sc->sc_is_host) {
191 preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh,
192 PCI_COMMAND_STATUS_REG);
193 preg |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE |
194 PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE;
195 bus_space_write_4(sc->sc_st, sc->sc_atu_sh,
196 PCI_COMMAND_STATUS_REG, preg);
197 }
198
199 /* Initialize the bus space tags. */
200 i80321_io_bs_init(&sc->sc_pci_iot, sc);
201 i80321_mem_bs_init(&sc->sc_pci_memt, sc);
202
203 /* Initialize the PCI chipset tag. */
204 i80321_pci_init(&sc->sc_pci_chipset, sc);
205
206 /* Initialize the DMA tags. */
207 i80321_pci_dma_init(&sc->sc_pci_dmat, sc);
208 i80321_local_dma_init(&sc->sc_local_dmat, sc);
209
210 /*
211 * Attach all the IOP built-ins.
212 */
213 for (id = iopxs_devices; id->id_name != NULL; id++) {
214 ia.ia_name = id->id_name;
215 ia.ia_st = sc->sc_st;
216 ia.ia_sh = sc->sc_sh;
217 ia.ia_dmat = &sc->sc_local_dmat;
218 ia.ia_offset = id->id_offset;
219 ia.ia_size = id->id_size;
220
221 (void) config_found(&sc->sc_dev, &ia, i80321_iopxs_print);
222 }
223
224 /*
225 * Attach the PCI bus.
226 */
227 preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
228 preg = PCIXSR_BUSNO(preg);
229 if (preg == 0xff)
230 preg = 0;
231 pba.pba_busname = "pci";
232 pba.pba_iot = &sc->sc_pci_iot;
233 pba.pba_memt = &sc->sc_pci_memt;
234 pba.pba_dmat = &sc->sc_pci_dmat;
235 pba.pba_pc = &sc->sc_pci_chipset;
236 pba.pba_bus = preg;
237 pba.pba_bridgetag = NULL;
238 pba.pba_intrswiz = 0; /* XXX what if busno != 0? */
239 pba.pba_intrtag = 0;
240 pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED |
241 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY;
242 (void) config_found(&sc->sc_dev, &pba, i80321_pcibus_print);
243 }
244
245 /*
246 * i80321_iopxs_print:
247 *
248 * Autoconfiguration cfprint routine when attaching
249 * to the "iopxs" device.
250 */
251 int
252 i80321_iopxs_print(void *aux, const char *pnp)
253 {
254
255 return (QUIET);
256 }
257
258 /*
259 * i80321_pcibus_print:
260 *
261 * Autoconfiguration cfprint routine when attaching
262 * to the "pcibus" attribute.
263 */
264 int
265 i80321_pcibus_print(void *aux, const char *pnp)
266 {
267 struct pcibus_attach_args *pba = aux;
268
269 if (pnp)
270 printf("%s at %s", pba->pba_busname, pnp);
271
272 printf(" bus %d", pba->pba_bus);
273
274 return (UNCONF);
275 }
276