txcsbus.c revision 1.4 1 /* $NetBSD: txcsbus.c,v 1.4 2000/08/18 07:33:14 sato Exp $ */
2
3 /*
4 * Copyright (c) 1999, by UCHIYAMA Yasushi
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. The name of the developer may NOT be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28 #include "opt_tx39_debug.h"
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/device.h>
33
34 #include <machine/bus.h>
35 #include <machine/intr.h>
36
37 #include <machine/platid.h>
38 #include <machine/platid_mask.h>
39
40 #include <hpcmips/tx/tx39var.h>
41 #include <hpcmips/tx/txcsbusvar.h>
42 #include <hpcmips/tx/tx39biuvar.h>
43 #include <hpcmips/tx/tx39biureg.h>
44
45 #include "locators.h"
46
47 /* TX39 CS mapping. (nonconfigurationable) */
48 const struct csmap {
49 char *cs_name;
50 paddr_t cs_addr;
51 psize_t cs_size;
52 } __csmap[] = {
53 [TX39_CS0] = {"CS0(ROM)" , TX39_SYSADDR_CS0 ,
54 TX39_SYSADDR_CS_SIZE},
55 [TX39_CS1] = {"CS1" , TX39_SYSADDR_CS1 ,
56 TX39_SYSADDR_CS_SIZE},
57 [TX39_CS2] = {"CS2" , TX39_SYSADDR_CS2 ,
58 TX39_SYSADDR_CS_SIZE},
59 [TX39_CS3] = {"CS3" , TX39_SYSADDR_CS3 ,
60 TX39_SYSADDR_CS_SIZE},
61 [TX39_MCS0] = {"MCS0" , TX39_SYSADDR_MCS0 ,
62 TX39_SYSADDR_MCS_SIZE},
63 [TX39_MCS1] = {"MCS1" , TX39_SYSADDR_MCS1 ,
64 TX39_SYSADDR_MCS_SIZE},
65 #ifdef TX391X
66 [TX39_MCS2] = {"MCS2" , TX39_SYSADDR_MCS2 ,
67 TX39_SYSADDR_MCS_SIZE},
68 [TX39_MCS3] = {"MCS3" , TX39_SYSADDR_MCS3 ,
69 TX39_SYSADDR_MCS_SIZE},
70 #endif /* TX391X */
71 [TX39_CARD1] = {"CARD1(io/attr)", TX39_SYSADDR_CARD1 ,
72 TX39_SYSADDR_CARD_SIZE},
73 [TX39_CARD2] = {"CARD2(io/attr)", TX39_SYSADDR_CARD2 ,
74 TX39_SYSADDR_CARD_SIZE},
75 [TX39_CARD1MEM] = {"CARD1(mem)" , TX39_SYSADDR_CARD1MEM ,
76 TX39_SYSADDR_CARD_SIZE},
77 [TX39_CARD2MEM] = {"CARD2(mem)" , TX39_SYSADDR_CARD2MEM ,
78 TX39_SYSADDR_CARD_SIZE},
79 };
80
81 int txcsbus_match __P((struct device*, struct cfdata*, void*));
82 void txcsbus_attach __P((struct device*, struct device*, void*));
83 int txcsbus_print __P((void*, const char*));
84 int txcsbus_search __P((struct device*, struct cfdata*, void*));
85
86 struct txcsbus_softc {
87 struct device sc_dev;
88 tx_chipset_tag_t sc_tc;
89 /* chip select space tag */
90 bus_space_tag_t sc_cst[TX39_MAXCS];
91 };
92
93 struct cfattach txcsbus_ca = {
94 sizeof(struct txcsbus_softc), txcsbus_match, txcsbus_attach
95 };
96
97 bus_space_tag_t __txcsbus_alloc_cstag __P((struct txcsbus_softc*,
98 struct cs_handle*));
99
100 int
101 txcsbus_match(parent, cf, aux)
102 struct device *parent;
103 struct cfdata *cf;
104 void *aux;
105 {
106 struct csbus_attach_args *cba = aux;
107 platid_mask_t mask;
108
109 if (strcmp(cba->cba_busname, cf->cf_driver->cd_name)) {
110 return 0;
111 }
112
113 if (cf->cf_loc[TXCSBUSIFCF_PLATFORM] ==
114 TXCSBUSIFCF_PLATFORM_DEFAULT) {
115 return 1;
116 }
117
118 mask = PLATID_DEREF(cf->cf_loc[TXCSBUSIFCF_PLATFORM]);
119 if (platid_match(&platid, &mask)) {
120 return 2;
121 }
122
123 return 0;
124 }
125
126 void
127 txcsbus_attach(parent, self, aux)
128 struct device *parent;
129 struct device *self;
130 void *aux;
131 {
132 struct csbus_attach_args *cba = aux;
133 struct txcsbus_softc *sc = (void*)self;
134
135 sc->sc_tc = cba->cba_tc;
136 printf("\n");
137
138 /*
139 * Attach external chip.
140 */
141 config_search(txcsbus_search, self, txcsbus_print);
142 }
143
144 int
145 txcsbus_print(aux, pnp)
146 void *aux;
147 const char *pnp;
148 {
149 #define PRINTIRQ(i) i, (i) / 32, (i) % 32
150 struct cs_attach_args *ca = aux;
151
152 if (ca->ca_csreg.cs != TXCSBUSCF_REGCS_DEFAULT) {
153 printf(" regcs %s %dbit %#x+%#x",
154 __csmap[ca->ca_csreg.cs].cs_name,
155 ca->ca_csreg.cswidth,
156 ca->ca_csreg.csbase,
157 ca->ca_csreg.cssize);
158 }
159
160 if (ca->ca_csio.cs != TXCSBUSCF_IOCS_DEFAULT) {
161 printf(" iocs %s %dbit %#x+%#x",
162 __csmap[ca->ca_csio.cs].cs_name,
163 ca->ca_csio.cswidth,
164 ca->ca_csio.csbase,
165 ca->ca_csio.cssize);
166 }
167
168 if (ca->ca_csmem.cs != TXCSBUSCF_MEMCS_DEFAULT) {
169 printf(" memcs %s %dbit %#x+%#x",
170 __csmap[ca->ca_csmem.cs].cs_name,
171 ca->ca_csmem.cswidth,
172 ca->ca_csmem.csbase,
173 ca->ca_csmem.cssize);
174 }
175
176 if (ca->ca_irq1 != TXCSBUSCF_IRQ1_DEFAULT) {
177 printf(" irq1 %d(%d:%d)", PRINTIRQ(ca->ca_irq1));
178 }
179
180 if (ca->ca_irq2 != TXCSBUSCF_IRQ2_DEFAULT) {
181 printf(" irq2 %d(%d:%d)", PRINTIRQ(ca->ca_irq2));
182 }
183
184 if (ca->ca_irq3 != TXCSBUSCF_IRQ3_DEFAULT) {
185 printf(" irq3 %d(%d:%d)", PRINTIRQ(ca->ca_irq3));
186 }
187
188 return UNCONF;
189 }
190
191 int
192 txcsbus_search(parent, cf, aux)
193 struct device *parent;
194 struct cfdata *cf;
195 void *aux;
196 {
197 struct txcsbus_softc *sc = (void*)parent;
198 struct cs_attach_args ca;
199
200 ca.ca_tc = sc->sc_tc;
201
202 ca.ca_csreg.cs = cf->cf_loc[TXCSBUSCF_REGCS];
203 ca.ca_csreg.csbase = cf->cf_loc[TXCSBUSCF_REGCSBASE];
204 ca.ca_csreg.cssize = cf->cf_loc[TXCSBUSCF_REGCSSIZE];
205 ca.ca_csreg.cswidth = cf->cf_loc[TXCSBUSCF_REGCSWIDTH];
206
207 if (ca.ca_csreg.cs != TXCSBUSCF_REGCS_DEFAULT) {
208 ca.ca_csreg.cstag = __txcsbus_alloc_cstag(sc, &ca.ca_csreg);
209 }
210
211 ca.ca_csio.cs = cf->cf_loc[TXCSBUSCF_IOCS];
212 ca.ca_csio.csbase = cf->cf_loc[TXCSBUSCF_IOCSBASE];
213 ca.ca_csio.cssize = cf->cf_loc[TXCSBUSCF_IOCSSIZE];
214 ca.ca_csio.cswidth = cf->cf_loc[TXCSBUSCF_IOCSWIDTH];
215
216 if (ca.ca_csio.cs != TXCSBUSCF_IOCS_DEFAULT) {
217 ca.ca_csio.cstag = __txcsbus_alloc_cstag(sc, &ca.ca_csio);
218 }
219
220 ca.ca_csmem.cs = cf->cf_loc[TXCSBUSCF_MEMCS];
221 ca.ca_csmem.csbase = cf->cf_loc[TXCSBUSCF_MEMCSBASE];
222 ca.ca_csmem.cssize = cf->cf_loc[TXCSBUSCF_MEMCSSIZE];
223 ca.ca_csmem.cswidth = cf->cf_loc[TXCSBUSCF_MEMCSWIDTH];
224
225 if (ca.ca_csmem.cs != TXCSBUSCF_MEMCS_DEFAULT) {
226 ca.ca_csmem.cstag = __txcsbus_alloc_cstag(sc, &ca.ca_csmem);
227 }
228
229 ca.ca_irq1 = cf->cf_loc[TXCSBUSCF_IRQ1];
230 ca.ca_irq2 = cf->cf_loc[TXCSBUSCF_IRQ2];
231 ca.ca_irq3 = cf->cf_loc[TXCSBUSCF_IRQ3];
232
233 if ((*cf->cf_attach->ca_match)(parent, cf, &ca)) {
234 config_attach(parent, cf, &ca, txcsbus_print);
235 }
236
237 return 0;
238 }
239
240 bus_space_tag_t
241 __txcsbus_alloc_cstag(sc, csh)
242 struct txcsbus_softc *sc;
243 struct cs_handle *csh;
244 {
245
246 tx_chipset_tag_t tc = sc->sc_tc;
247 int cs = csh->cs;
248 int width = csh->cswidth;
249 bus_space_tag_t iot;
250 txreg_t reg;
251
252 if (!TX39_ISCS(cs) && !TX39_ISMCS(cs) && !TX39_ISCARD(cs)) {
253 panic("txcsbus_alloc_tag: bogus chip select %d\n", cs);
254 }
255
256 /* Already setuped chip select */
257 if (sc->sc_cst[cs]) {
258 return sc->sc_cst[cs];
259 }
260
261 iot = hpcmips_alloc_bus_space_tag();
262 sc->sc_cst[cs] = iot;
263
264 iot->t_base = __csmap[cs].cs_addr;
265 iot->t_size = __csmap[cs].cs_size;
266 strcpy(iot->t_name , __csmap[cs].cs_name);
267
268 /* CS bus-width (configurationable) */
269 switch (width) {
270 default:
271 panic("txcsbus_alloc_tag: bogus bus width %d\n", width);
272
273 case 32:
274 if (TX39_ISCS(cs)) {
275 reg = tx_conf_read(tc, TX39_MEMCONFIG0_REG);
276 reg |= (1 << cs);
277 tx_conf_write(tc, TX39_MEMCONFIG0_REG, reg);
278 } else if(TX39_ISMCS(cs)) {
279 #ifdef TX391X
280 panic("txcsbus_alloc_tag: MCS is 16bit only");
281 #endif /* TX391X */
282 #ifdef TX392X
283 reg = tx_conf_read(tc, TX39_MEMCONFIG1_REG);
284 reg |= ((cs == TX39_MCS0) ?
285 TX39_MEMCONFIG1_MCS0_32 :
286 TX39_MEMCONFIG1_MCS1_32);
287 tx_conf_write(tc, TX39_MEMCONFIG1_REG, reg);
288 #endif /* TX392X */
289 }
290 break;
291
292 case 16:
293 if (TX39_ISCS(cs)) {
294 reg = tx_conf_read(tc, TX39_MEMCONFIG0_REG);
295 reg &= ~(1 << cs);
296 tx_conf_write(tc, TX39_MEMCONFIG0_REG, reg);
297 } else if(TX39_ISMCS(cs)) {
298 /* TX391X always 16bit port */
299 #ifdef TX392X
300 reg = tx_conf_read(tc, TX39_MEMCONFIG1_REG);
301 reg &= ~((cs == TX39_MCS0) ?
302 TX39_MEMCONFIG1_MCS0_32 :
303 TX39_MEMCONFIG1_MCS1_32);
304 tx_conf_write(tc, TX39_MEMCONFIG1_REG, reg);
305 #endif /* TX392X */
306 } else {
307 /* CARD io/attr or mem */
308 reg = tx_conf_read(tc, TX39_MEMCONFIG3_REG);
309
310 /* enable I/O access */
311 reg |= (cs == TX39_CARD1) ?
312 TX39_MEMCONFIG3_CARD1IOEN :
313 TX39_MEMCONFIG3_CARD2IOEN;
314 /* disable 8bit access */
315 #ifdef TX392X
316 reg &= ~((cs == TX39_CARD1) ?
317 TX39_MEMCONFIG3_CARD1_8SEL :
318 TX39_MEMCONFIG3_CARD2_8SEL);
319 #endif /* TX392X */
320 #ifdef TX391X
321 reg &= ~TX39_MEMCONFIG3_PORT8SEL;
322 #endif /* TX391X */
323 tx_conf_write(tc, TX39_MEMCONFIG3_REG, reg);
324 }
325 break;
326
327 case 8:
328 if (TX39_ISCARD(cs)) {
329 reg = tx_conf_read(tc, TX39_MEMCONFIG3_REG);
330
331 /* enable I/O access */
332 reg |= (cs == TX39_CARD1) ?
333 TX39_MEMCONFIG3_CARD1IOEN :
334 TX39_MEMCONFIG3_CARD2IOEN;
335 /* disable 8bit access */
336 #ifdef TX392X
337 reg |= (cs == TX39_CARD1) ?
338 TX39_MEMCONFIG3_CARD1_8SEL :
339 TX39_MEMCONFIG3_CARD2_8SEL;
340 #endif /* TX392X */
341 #ifdef TX391X
342 reg |= TX39_MEMCONFIG3_PORT8SEL;
343 #endif /* TX391X */
344 tx_conf_write(tc, TX39_MEMCONFIG3_REG, reg);
345
346 } else {
347 panic("__txcsbus_alloc_cstag: CS%d 8bit mode is"
348 "not allowed", cs);
349 }
350 }
351
352 hpcmips_init_bus_space_extent(iot);
353
354 return iot;
355 }
356