txcsbus.c revision 1.2 1 /* $NetBSD: txcsbus.c,v 1.2 1999/12/03 18:15:41 uch 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 int txcsbus_match __P((struct device*, struct cfdata*, void*));
48 void txcsbus_attach __P((struct device*, struct device*, void*));
49 int txcsbus_print __P((void*, const char*));
50 int txcsbus_search __P((struct device*, struct cfdata*, void*));
51
52 struct txcsbus_softc {
53 struct device sc_dev;
54 tx_chipset_tag_t sc_tc;
55 /* chip select space tag */
56 bus_space_tag_t sc_cst[TX39_MAXCS];
57 };
58
59 struct cfattach txcsbus_ca = {
60 sizeof(struct txcsbus_softc), txcsbus_match, txcsbus_attach
61 };
62
63 bus_space_tag_t __txcsbus_alloc_cstag __P((struct txcsbus_softc*,
64 struct cs_handle*));
65
66 int
67 txcsbus_match(parent, cf, aux)
68 struct device *parent;
69 struct cfdata *cf;
70 void *aux;
71 {
72 struct csbus_attach_args *cba = aux;
73 platid_mask_t mask;
74
75 if (strcmp(cba->cba_busname, cf->cf_driver->cd_name)) {
76 return 0;
77 }
78
79 if (cf->cf_loc[TXCSBUSIFCF_PLATFORM] ==
80 TXCSBUSIFCF_PLATFORM_DEFAULT) {
81 return 1;
82 }
83
84 mask = PLATID_DEREF(cf->cf_loc[TXCSBUSIFCF_PLATFORM]);
85 if (platid_match(&platid, &mask)) {
86 return 2;
87 }
88
89 return 0;
90 }
91
92 void
93 txcsbus_attach(parent, self, aux)
94 struct device *parent;
95 struct device *self;
96 void *aux;
97 {
98 struct csbus_attach_args *cba = aux;
99 struct txcsbus_softc *sc = (void*)self;
100
101 sc->sc_tc = cba->cba_tc;
102 printf("\n");
103
104 /*
105 * Attach external chip.
106 */
107 config_search(txcsbus_search, self, txcsbus_print);
108 }
109
110 int
111 txcsbus_print(aux, pnp)
112 void *aux;
113 const char *pnp;
114 {
115 return pnp ? QUIET : UNCONF;
116 }
117
118 int
119 txcsbus_search(parent, cf, aux)
120 struct device *parent;
121 struct cfdata *cf;
122 void *aux;
123 {
124 struct txcsbus_softc *sc = (void*)parent;
125 struct cs_attach_args ca;
126
127 ca.ca_tc = sc->sc_tc;
128
129 ca.ca_csreg.cs = cf->cf_loc[TXCSBUSCF_REGCS];
130 ca.ca_csreg.csbase = cf->cf_loc[TXCSBUSCF_REGCSBASE];
131 ca.ca_csreg.cssize = cf->cf_loc[TXCSBUSCF_REGCSSIZE];
132 ca.ca_csreg.cswidth = cf->cf_loc[TXCSBUSCF_REGCSWIDTH];
133
134 if (ca.ca_csreg.cs != TXCSBUSCF_REGCS_DEFAULT) {
135 ca.ca_csreg.cstag = __txcsbus_alloc_cstag(sc, &ca.ca_csreg);
136 }
137
138 ca.ca_csio.cs = cf->cf_loc[TXCSBUSCF_IOCS];
139 ca.ca_csio.csbase = cf->cf_loc[TXCSBUSCF_IOCSBASE];
140 ca.ca_csio.cssize = cf->cf_loc[TXCSBUSCF_IOCSSIZE];
141 ca.ca_csio.cswidth = cf->cf_loc[TXCSBUSCF_IOCSWIDTH];
142
143 if (ca.ca_csio.cs != TXCSBUSCF_IOCS_DEFAULT) {
144 ca.ca_csio.cstag = __txcsbus_alloc_cstag(sc, &ca.ca_csio);
145 }
146
147 ca.ca_csmem.cs = cf->cf_loc[TXCSBUSCF_MEMCS];
148 ca.ca_csmem.csbase = cf->cf_loc[TXCSBUSCF_MEMCSBASE];
149 ca.ca_csmem.cssize = cf->cf_loc[TXCSBUSCF_MEMCSSIZE];
150 ca.ca_csmem.cswidth = cf->cf_loc[TXCSBUSCF_MEMCSWIDTH];
151
152 if (ca.ca_csmem.cs != TXCSBUSCF_MEMCS_DEFAULT) {
153 ca.ca_csmem.cstag = __txcsbus_alloc_cstag(sc, &ca.ca_csmem);
154 }
155
156 ca.ca_irq1 = cf->cf_loc[TXCSBUSCF_IRQ1];
157 ca.ca_irq2 = cf->cf_loc[TXCSBUSCF_IRQ2];
158 ca.ca_irq3 = cf->cf_loc[TXCSBUSCF_IRQ3];
159
160 if ((*cf->cf_attach->ca_match)(parent, cf, &ca)) {
161 config_attach(parent, cf, &ca, txcsbus_print);
162 }
163
164 return 0;
165 }
166
167 bus_space_tag_t
168 __txcsbus_alloc_cstag(sc, csh)
169 struct txcsbus_softc *sc;
170 struct cs_handle *csh;
171 {
172 /* TX39 CS mapping. (nonconfigurationable) */
173 struct csmap {
174 char *cs_name;
175 paddr_t cs_addr;
176 psize_t cs_size;
177 } __csmap[] = {
178 [TX39_CS0] = {"CS0(ROM)" , TX39_SYSADDR_CS0 ,
179 TX39_SYSADDR_CS_SIZE},
180 [TX39_CS1] = {"CS1" , TX39_SYSADDR_CS1 ,
181 TX39_SYSADDR_CS_SIZE},
182 [TX39_CS2] = {"CS2" , TX39_SYSADDR_CS2 ,
183 TX39_SYSADDR_CS_SIZE},
184 [TX39_CS3] = {"CS3" , TX39_SYSADDR_CS3 ,
185 TX39_SYSADDR_CS_SIZE},
186 [TX39_MCS0] = {"MCS0" , TX39_SYSADDR_MCS0 ,
187 TX39_SYSADDR_MCS_SIZE},
188 [TX39_MCS1] = {"MCS1" , TX39_SYSADDR_MCS1 ,
189 TX39_SYSADDR_MCS_SIZE},
190 #ifdef TX391X
191 [TX39_MCS2] = {"MCS2" , TX39_SYSADDR_MCS2 ,
192 TX39_SYSADDR_MCS_SIZE},
193 [TX39_MCS3] = {"MCS3" , TX39_SYSADDR_MCS3 ,
194 TX39_SYSADDR_MCS_SIZE},
195 #endif /* TX391X */
196 [TX39_CARD1] = {"CARD1(io/attr)", TX39_SYSADDR_CARD1 ,
197 TX39_SYSADDR_CARD_SIZE},
198 [TX39_CARD2] = {"CARD2(io/attr)", TX39_SYSADDR_CARD2 ,
199 TX39_SYSADDR_CARD_SIZE},
200 [TX39_CARD1MEM] = {"CARD1(mem)" , TX39_SYSADDR_CARD1MEM ,
201 TX39_SYSADDR_CARD_SIZE},
202 [TX39_CARD2MEM] = {"CARD2(mem)" , TX39_SYSADDR_CARD2MEM ,
203 TX39_SYSADDR_CARD_SIZE},
204 };
205
206 tx_chipset_tag_t tc = sc->sc_tc;
207 int cs = csh->cs;
208 int width = csh->cswidth;
209 bus_space_tag_t iot;
210 txreg_t reg;
211
212 if (!TX39_ISCS(cs) && !TX39_ISMCS(cs) && !TX39_ISCARD(cs)) {
213 panic("txcsbus_alloc_tag: bogus chip select %d\n", cs);
214 }
215
216 printf("(%s)", __csmap[cs].cs_name);
217 /* Already setuped chip select */
218 if (sc->sc_cst[cs]) {
219 return sc->sc_cst[cs];
220 }
221
222 iot = hpcmips_alloc_bus_space_tag();
223 sc->sc_cst[cs] = iot;
224
225 iot->t_base = __csmap[cs].cs_addr;
226 iot->t_size = __csmap[cs].cs_size;
227 strcpy(iot->t_name , __csmap[cs].cs_name);
228
229 /* CS bus-width (configurationable) */
230 switch (width) {
231 default:
232 panic("txcsbus_alloc_tag: bogus bus width %d\n", width);
233
234 case 32:
235 if (TX39_ISCS(cs)) {
236 reg = tx_conf_read(tc, TX39_MEMCONFIG0_REG);
237 reg |= (1 << cs);
238 tx_conf_write(tc, TX39_MEMCONFIG0_REG, reg);
239 } else if(TX39_ISMCS(cs)) {
240 #ifdef TX391X
241 panic("txcsbus_alloc_tag: MCS is 16bit only");
242 #endif /* TX391X */
243 #ifdef TX392X
244 reg = tx_conf_read(tc, TX39_MEMCONFIG1_REG);
245 reg |= ((cs == TX39_MCS0) ?
246 TX39_MEMCONFIG1_MCS0_32 :
247 TX39_MEMCONFIG1_MCS1_32);
248 tx_conf_write(tc, TX39_MEMCONFIG1_REG, reg);
249 #endif /* TX392X */
250 }
251 break;
252
253 case 16:
254 if (TX39_ISCS(cs)) {
255 reg = tx_conf_read(tc, TX39_MEMCONFIG0_REG);
256 reg &= ~(1 << cs);
257 tx_conf_write(tc, TX39_MEMCONFIG0_REG, reg);
258 } else if(TX39_ISMCS(cs)) {
259 /* TX391X always 16bit port */
260 #ifdef TX392X
261 reg = tx_conf_read(tc, TX39_MEMCONFIG1_REG);
262 reg &= ~((cs == TX39_MCS0) ?
263 TX39_MEMCONFIG1_MCS0_32 :
264 TX39_MEMCONFIG1_MCS1_32);
265 tx_conf_write(tc, TX39_MEMCONFIG1_REG, reg);
266 #endif /* TX392X */
267 } else {
268 /* CARD io/attr or mem */
269 reg = tx_conf_read(tc, TX39_MEMCONFIG3_REG);
270
271 /* enable I/O access */
272 reg |= (cs == TX39_CARD1) ?
273 TX39_MEMCONFIG3_CARD1IOEN :
274 TX39_MEMCONFIG3_CARD2IOEN;
275 /* disable 8bit access */
276 #ifdef TX392X
277 reg &= ~((cs == TX39_CARD1) ?
278 TX39_MEMCONFIG3_CARD1_8SEL :
279 TX39_MEMCONFIG3_CARD2_8SEL);
280 #endif /* TX392X */
281 #ifdef TX391X
282 reg &= ~TX39_MEMCONFIG3_PORT8SEL;
283 #endif /* TX391X */
284 tx_conf_write(tc, TX39_MEMCONFIG3_REG, reg);
285 }
286 break;
287
288 case 8:
289 if (TX39_ISCARD(cs)) {
290 reg = tx_conf_read(tc, TX39_MEMCONFIG3_REG);
291
292 /* enable I/O access */
293 reg |= (cs == TX39_CARD1) ?
294 TX39_MEMCONFIG3_CARD1IOEN :
295 TX39_MEMCONFIG3_CARD2IOEN;
296 /* disable 8bit access */
297 #ifdef TX392X
298 reg |= (cs == TX39_CARD1) ?
299 TX39_MEMCONFIG3_CARD1_8SEL :
300 TX39_MEMCONFIG3_CARD2_8SEL;
301 #endif /* TX392X */
302 #ifdef TX391X
303 reg |= TX39_MEMCONFIG3_PORT8SEL;
304 #endif /* TX391X */
305 tx_conf_write(tc, TX39_MEMCONFIG3_REG, reg);
306
307 } else {
308 panic("__txcsbus_alloc_cstag: CS%d 8bit mode is"
309 "not allowed");
310 }
311 }
312
313 hpcmips_init_bus_space_extent(iot);
314 printf("\n");
315
316 return iot;
317 }
318