1 /* $NetBSD: txcsbus.c,v 1.20 2005/12/11 12:17:34 christos Exp $ */
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: txcsbus.c,v 1.20 2005/12/11 12:17:34 christos Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/device.h>
39 #include <machine/intr.h>
40 #include <machine/bus.h>
41 #include <machine/bus_space_hpcmips.h>
43 #include <machine/platid.h>
44 #include <machine/platid_mask.h>
46 #include <hpcmips/tx/tx39var.h>
47 #include <hpcmips/tx/txcsbusvar.h>
48 #include <hpcmips/tx/tx39biuvar.h>
49 #include <hpcmips/tx/tx39biureg.h>
53 /* TX39 CS mapping. (nonconfigurationable) */
59 [TX39_CS0
] = {"CS0(ROM)" , TX39_SYSADDR_CS0
,
60 TX39_SYSADDR_CS_SIZE
},
61 [TX39_CS1
] = {"CS1" , TX39_SYSADDR_CS1
,
62 TX39_SYSADDR_CS_SIZE
},
63 [TX39_CS2
] = {"CS2" , TX39_SYSADDR_CS2
,
64 TX39_SYSADDR_CS_SIZE
},
65 [TX39_CS3
] = {"CS3" , TX39_SYSADDR_CS3
,
66 TX39_SYSADDR_CS_SIZE
},
67 [TX39_MCS0
] = {"MCS0" , TX39_SYSADDR_MCS0
,
68 TX39_SYSADDR_MCS_SIZE
},
69 [TX39_MCS1
] = {"MCS1" , TX39_SYSADDR_MCS1
,
70 TX39_SYSADDR_MCS_SIZE
},
72 [TX39_MCS2
] = {"MCS2" , TX39_SYSADDR_MCS2
,
73 TX39_SYSADDR_MCS_SIZE
},
74 [TX39_MCS3
] = {"MCS3" , TX39_SYSADDR_MCS3
,
75 TX39_SYSADDR_MCS_SIZE
},
77 [TX39_CARD1
] = {"CARD1(io/attr)", TX39_SYSADDR_CARD1
,
78 TX39_SYSADDR_CARD_SIZE
},
79 [TX39_CARD2
] = {"CARD2(io/attr)", TX39_SYSADDR_CARD2
,
80 TX39_SYSADDR_CARD_SIZE
},
81 [TX39_CARD1MEM
] = {"CARD1(mem)" , TX39_SYSADDR_CARD1MEM
,
82 TX39_SYSADDR_CARD_SIZE
},
83 [TX39_CARD2MEM
] = {"CARD2(mem)" , TX39_SYSADDR_CARD2MEM
,
84 TX39_SYSADDR_CARD_SIZE
},
85 [TX39_KUCS0
] = {"KUCS0" , TX39_SYSADDR_KUSEG_CS0
,
86 TX39_SYSADDR_KUCS_SIZE
},
87 [TX39_KUCS1
] = {"KUCS1" , TX39_SYSADDR_KUSEG_CS1
,
88 TX39_SYSADDR_KUCS_SIZE
},
89 [TX39_KUCS2
] = {"KUCS2" , TX39_SYSADDR_KUSEG_CS2
,
90 TX39_SYSADDR_KUCS_SIZE
},
91 [TX39_KUCS3
] = {"KUCS3" , TX39_SYSADDR_KUSEG_CS3
,
92 TX39_SYSADDR_KUCS_SIZE
},
95 int txcsbus_match(struct device
*, struct cfdata
*, void *);
96 void txcsbus_attach(struct device
*, struct device
*, void *);
97 int txcsbus_print(void *, const char *);
98 int txcsbus_search(struct device
*, struct cfdata
*,
101 struct txcsbus_softc
{
102 struct device sc_dev
;
103 tx_chipset_tag_t sc_tc
;
104 /* chip select space tag */
105 struct bus_space_tag_hpcmips
*sc_cst
[TX39_MAXCS
];
109 CFATTACH_DECL(txcsbus
, sizeof(struct txcsbus_softc
),
110 txcsbus_match
, txcsbus_attach
, NULL
, NULL
);
112 static bus_space_tag_t
__txcsbus_alloc_cstag(struct txcsbus_softc
*,
116 txcsbus_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
118 struct csbus_attach_args
*cba
= aux
;
121 if (strcmp(cba
->cba_busname
, cf
->cf_name
))
124 if (cf
->cf_loc
[TXCSBUSIFCF_PLATFORM
] == TXCSBUSIFCF_PLATFORM_DEFAULT
)
127 mask
= PLATID_DEREF(cf
->cf_loc
[TXCSBUSIFCF_PLATFORM
]);
128 if (platid_match(&platid
, &mask
))
135 txcsbus_attach(struct device
*parent
, struct device
*self
, void *aux
)
137 struct csbus_attach_args
*cba
= aux
;
138 struct txcsbus_softc
*sc
= (void*)self
;
140 sc
->sc_tc
= cba
->cba_tc
;
144 * Attach external chip.
146 /* higher priority devices attach first */
148 config_search_ia(txcsbus_search
, self
, "txcsbus", txcsbus_print
);
149 /* then, normal priority devices */
151 config_search_ia(txcsbus_search
, self
, "txcsbus", txcsbus_print
);
155 txcsbus_print(void *aux
, const char *pnp
)
157 #define PRINTIRQ(i) i, (i) / 32, (i) % 32
158 struct cs_attach_args
*ca
= aux
;
160 if (ca
->ca_csreg
.cs
!= TXCSBUSCF_REGCS_DEFAULT
) {
161 aprint_normal(" regcs %s %dbit %#x+%#x",
162 __csmap
[ca
->ca_csreg
.cs
].cs_name
,
163 ca
->ca_csreg
.cswidth
,
165 ca
->ca_csreg
.cssize
);
168 if (ca
->ca_csio
.cs
!= TXCSBUSCF_IOCS_DEFAULT
) {
169 aprint_normal(" iocs %s %dbit %#x+%#x",
170 __csmap
[ca
->ca_csio
.cs
].cs_name
,
176 if (ca
->ca_csmem
.cs
!= TXCSBUSCF_MEMCS_DEFAULT
) {
177 aprint_normal(" memcs %s %dbit %#x+%#x",
178 __csmap
[ca
->ca_csmem
.cs
].cs_name
,
179 ca
->ca_csmem
.cswidth
,
181 ca
->ca_csmem
.cssize
);
184 if (ca
->ca_irq1
!= TXCSBUSCF_IRQ1_DEFAULT
) {
185 aprint_normal(" irq1 %d(%d:%d)", PRINTIRQ(ca
->ca_irq1
));
188 if (ca
->ca_irq2
!= TXCSBUSCF_IRQ2_DEFAULT
) {
189 aprint_normal(" irq2 %d(%d:%d)", PRINTIRQ(ca
->ca_irq2
));
192 if (ca
->ca_irq3
!= TXCSBUSCF_IRQ3_DEFAULT
) {
193 aprint_normal(" irq3 %d(%d:%d)", PRINTIRQ(ca
->ca_irq3
));
200 txcsbus_search(struct device
*parent
, struct cfdata
*cf
,
201 const int *ldesc
, void *aux
)
203 struct txcsbus_softc
*sc
= (void*)parent
;
204 struct cs_attach_args ca
;
206 ca
.ca_tc
= sc
->sc_tc
;
208 ca
.ca_csreg
.cs
= cf
->cf_loc
[TXCSBUSCF_REGCS
];
209 ca
.ca_csreg
.csbase
= cf
->cf_loc
[TXCSBUSCF_REGCSBASE
];
210 ca
.ca_csreg
.cssize
= cf
->cf_loc
[TXCSBUSCF_REGCSSIZE
];
211 ca
.ca_csreg
.cswidth
= cf
->cf_loc
[TXCSBUSCF_REGCSWIDTH
];
213 if (ca
.ca_csreg
.cs
!= TXCSBUSCF_REGCS_DEFAULT
) {
214 ca
.ca_csreg
.cstag
= __txcsbus_alloc_cstag(sc
, &ca
.ca_csreg
);
217 ca
.ca_csio
.cs
= cf
->cf_loc
[TXCSBUSCF_IOCS
];
218 ca
.ca_csio
.csbase
= cf
->cf_loc
[TXCSBUSCF_IOCSBASE
];
219 ca
.ca_csio
.cssize
= cf
->cf_loc
[TXCSBUSCF_IOCSSIZE
];
220 ca
.ca_csio
.cswidth
= cf
->cf_loc
[TXCSBUSCF_IOCSWIDTH
];
222 if (ca
.ca_csio
.cs
!= TXCSBUSCF_IOCS_DEFAULT
) {
223 ca
.ca_csio
.cstag
= __txcsbus_alloc_cstag(sc
, &ca
.ca_csio
);
226 ca
.ca_csmem
.cs
= cf
->cf_loc
[TXCSBUSCF_MEMCS
];
227 ca
.ca_csmem
.csbase
= cf
->cf_loc
[TXCSBUSCF_MEMCSBASE
];
228 ca
.ca_csmem
.cssize
= cf
->cf_loc
[TXCSBUSCF_MEMCSSIZE
];
229 ca
.ca_csmem
.cswidth
= cf
->cf_loc
[TXCSBUSCF_MEMCSWIDTH
];
231 if (ca
.ca_csmem
.cs
!= TXCSBUSCF_MEMCS_DEFAULT
) {
232 ca
.ca_csmem
.cstag
= __txcsbus_alloc_cstag(sc
, &ca
.ca_csmem
);
235 ca
.ca_irq1
= cf
->cf_loc
[TXCSBUSCF_IRQ1
];
236 ca
.ca_irq2
= cf
->cf_loc
[TXCSBUSCF_IRQ2
];
237 ca
.ca_irq3
= cf
->cf_loc
[TXCSBUSCF_IRQ3
];
239 if (config_match(parent
, cf
, &ca
) == sc
->sc_pri
) {
240 config_attach(parent
, cf
, &ca
, txcsbus_print
);
247 __txcsbus_alloc_cstag(struct txcsbus_softc
*sc
, struct cs_handle
*csh
)
250 tx_chipset_tag_t tc
= sc
->sc_tc
;
252 int width
= csh
->cswidth
;
253 struct bus_space_tag_hpcmips
*iot
;
256 if (!TX39_ISCS(cs
) && !TX39_ISMCS(cs
) && !TX39_ISCARD(cs
) &&
258 panic("txcsbus_alloc_tag: bogus chip select %d", cs
);
261 /* Already setuped chip select */
262 if (sc
->sc_cst
[cs
]) {
263 return (&sc
->sc_cst
[cs
]->bst
);
266 iot
= hpcmips_alloc_bus_space_tag();
267 hpcmips_init_bus_space(iot
, hpcmips_system_bus_space_hpcmips(),
268 __csmap
[cs
].cs_name
, __csmap
[cs
].cs_addr
, __csmap
[cs
].cs_size
);
269 sc
->sc_cst
[cs
] = iot
;
271 /* CS bus-width (configurationable) */
274 panic("txcsbus_alloc_tag: bogus bus width %d", width
);
278 reg
= tx_conf_read(tc
, TX39_MEMCONFIG0_REG
);
280 tx_conf_write(tc
, TX39_MEMCONFIG0_REG
, reg
);
281 } else if(TX39_ISMCS(cs
)) {
283 panic("txcsbus_alloc_tag: MCS is 16bit only");
286 reg
= tx_conf_read(tc
, TX39_MEMCONFIG1_REG
);
287 reg
|= ((cs
== TX39_MCS0
) ?
288 TX39_MEMCONFIG1_MCS0_32
:
289 TX39_MEMCONFIG1_MCS1_32
);
290 tx_conf_write(tc
, TX39_MEMCONFIG1_REG
, reg
);
297 reg
= tx_conf_read(tc
, TX39_MEMCONFIG0_REG
);
299 tx_conf_write(tc
, TX39_MEMCONFIG0_REG
, reg
);
300 } else if(TX39_ISMCS(cs
)) {
301 /* TX391X always 16bit port */
303 reg
= tx_conf_read(tc
, TX39_MEMCONFIG1_REG
);
304 reg
&= ~((cs
== TX39_MCS0
) ?
305 TX39_MEMCONFIG1_MCS0_32
:
306 TX39_MEMCONFIG1_MCS1_32
);
307 tx_conf_write(tc
, TX39_MEMCONFIG1_REG
, reg
);
309 } else if (TX39_ISCARD(cs
)) {
310 /* CARD io/attr or mem */
311 reg
= tx_conf_read(tc
, TX39_MEMCONFIG3_REG
);
313 /* enable I/O access */
314 reg
|= (cs
== TX39_CARD1
) ?
315 TX39_MEMCONFIG3_CARD1IOEN
:
316 TX39_MEMCONFIG3_CARD2IOEN
;
317 /* disable 8bit access */
319 reg
&= ~((cs
== TX39_CARD1
) ?
320 TX39_MEMCONFIG3_CARD1_8SEL
:
321 TX39_MEMCONFIG3_CARD2_8SEL
);
324 reg
&= ~TX39_MEMCONFIG3_PORT8SEL
;
326 tx_conf_write(tc
, TX39_MEMCONFIG3_REG
, reg
);
331 if (TX39_ISCARD(cs
)) {
332 reg
= tx_conf_read(tc
, TX39_MEMCONFIG3_REG
);
334 /* enable I/O access */
335 reg
|= (cs
== TX39_CARD1
) ?
336 TX39_MEMCONFIG3_CARD1IOEN
:
337 TX39_MEMCONFIG3_CARD2IOEN
;
338 /* disable 8bit access */
340 reg
|= (cs
== TX39_CARD1
) ?
341 TX39_MEMCONFIG3_CARD1_8SEL
:
342 TX39_MEMCONFIG3_CARD2_8SEL
;
345 reg
|= TX39_MEMCONFIG3_PORT8SEL
;
347 tx_conf_write(tc
, TX39_MEMCONFIG3_REG
, reg
);
350 panic("__txcsbus_alloc_cstag: CS%d 8bit mode is"