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