1 /* $NetBSD: design_gsrd1.c,v 1.1.20.1 2007/05/28 20:01:42 freza Exp $ */
4 * Copyright (c) 2006 Jachym Holecek
7 * Written for DFC Design, s.r.o.
9 * Redistribution and use in source and binary forms, with or without
10 * 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.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: design_gsrd1.c,v 1.1.20.1 2007/05/28 20:01:42 freza Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/device.h>
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
41 #include <machine/cpu.h>
42 #include <machine/bus.h>
43 #include <machine/intr.h>
45 #include <powerpc/ibm4xx/dev/plbvar.h>
47 #include <evbppc/virtex/dev/xcvbusvar.h>
49 #include <evbppc/virtex/dev/xlcomreg.h>
50 #include <evbppc/virtex/dev/cdmacreg.h>
51 #include <evbppc/virtex/dev/temacreg.h>
52 #include <evbppc/virtex/dev/tftreg.h>
54 #include <evbppc/virtex/virtex.h>
55 #include <evbppc/virtex/dcr.h>
58 #define DCR_CDMAC_BASE 0x0140
59 #define DCR_XLCOM_BASE 0x0000
60 #define DCR_TEMAC_BASE 0x0030
61 #define DCR_LLFB_BASE 0x0080
63 #define CDMAC_TX0_STAT CDMAC_STAT_BASE(0)
64 #define CDMAC_RX0_STAT CDMAC_STAT_BASE(1)
65 #define CDMAC_TX1_STAT CDMAC_STAT_BASE(2)
66 #define CDMAC_RX1_STAT CDMAC_STAT_BASE(3)
68 #define CDMAC_TX0_BASE CDMAC_CTRL_BASE(0)
69 #define CDMAC_RX0_BASE CDMAC_CTRL_BASE(1)
70 #define CDMAC_TX1_BASE CDMAC_CTRL_BASE(2)
71 #define CDMAC_RX1_BASE CDMAC_CTRL_BASE(3)
73 #define CDMAC_INTR_LINE 2
76 #define IPL_CDMAC IPL_NET
77 #define splcdmac() splnet()
81 * CDMAC per-channel interrupt handler. CDMAC has only one interrupt signal
82 * shared by all channels on GSRD, so we have to dispatch channels manually.
84 * Note: we hardwire priority to IPL_NET, temac(4) is the only device that
85 * needs to service DMA interrupts anyway.
87 struct cdmac_intr_handle
{
88 void (*cih_func
)(void *);
92 static void *cdmac_ih
= NULL
; /* real CDMAC intr */
93 static struct cdmac_intr_handle
*cdmac_intrs
[CDMAC_NCHAN
];
97 * DCR bus space leaf access routines.
101 xlcom0_write_4(bus_space_tag_t t
, bus_space_handle_t h
, uint32_t addr
,
107 WCASE(DCR_XLCOM_BASE
, XLCOM_TX_FIFO
);
108 WCASE(DCR_XLCOM_BASE
, XLCOM_STAT
);
109 WCASE(DCR_XLCOM_BASE
, XLCOM_CNTL
);
115 xlcom0_read_4(bus_space_tag_t t
, bus_space_handle_t h
, uint32_t addr
)
122 RCASE(DCR_XLCOM_BASE
, XLCOM_RX_FIFO
);
123 RCASE(DCR_XLCOM_BASE
, XLCOM_STAT
);
124 RCASE(DCR_XLCOM_BASE
, XLCOM_CNTL
);
132 tft0_write_4(bus_space_tag_t t
, bus_space_handle_t h
, uint32_t addr
,
138 WCASE(DCR_LLFB_BASE
, TFT_CTRL
);
144 tft0_read_4(bus_space_tag_t t
, bus_space_handle_t h
, uint32_t addr
)
151 RCASE(DCR_LLFB_BASE
, TFT_CTRL
);
158 #define DOCHAN(op, channel) \
159 op(DCR_CDMAC_BASE, channel + CDMAC_NEXT); \
160 op(DCR_CDMAC_BASE, channel + CDMAC_CURADDR); \
161 op(DCR_CDMAC_BASE, channel + CDMAC_CURSIZE); \
162 op(DCR_CDMAC_BASE, channel + CDMAC_CURDESC)
165 cdmac0_write_4(bus_space_tag_t t
, bus_space_handle_t h
, uint32_t addr
,
171 WCASE(DCR_CDMAC_BASE
, CDMAC_INTR
);
172 WCASE(DCR_CDMAC_BASE
, CDMAC_TX0_STAT
);
173 WCASE(DCR_CDMAC_BASE
, CDMAC_RX0_STAT
);
174 WCASE(DCR_CDMAC_BASE
, CDMAC_TX1_STAT
);
175 WCASE(DCR_CDMAC_BASE
, CDMAC_RX1_STAT
);
176 DOCHAN(WCASE
, CDMAC_TX0_BASE
);
177 DOCHAN(WCASE
, CDMAC_RX0_BASE
);
178 DOCHAN(WCASE
, CDMAC_TX1_BASE
);
179 DOCHAN(WCASE
, CDMAC_RX1_BASE
);
185 cdmac0_read_4(bus_space_tag_t t
, bus_space_handle_t h
, uint32_t addr
)
192 RCASE(DCR_CDMAC_BASE
, CDMAC_INTR
);
193 RCASE(DCR_CDMAC_BASE
, CDMAC_TX0_STAT
);
194 RCASE(DCR_CDMAC_BASE
, CDMAC_RX0_STAT
);
195 RCASE(DCR_CDMAC_BASE
, CDMAC_TX1_STAT
);
196 RCASE(DCR_CDMAC_BASE
, CDMAC_RX1_STAT
);
197 DOCHAN(RCASE
, CDMAC_TX0_BASE
);
198 DOCHAN(RCASE
, CDMAC_RX0_BASE
);
199 DOCHAN(RCASE
, CDMAC_TX1_BASE
);
200 DOCHAN(RCASE
, CDMAC_RX1_BASE
);
210 temac0_write_4(bus_space_tag_t t
, bus_space_handle_t h
, uint32_t addr
,
216 WCASE(DCR_TEMAC_BASE
, TEMAC_RESET
);
221 static const struct powerpc_bus_space xlcom_bst
= {
222 DCR_BST_BODY(DCR_XLCOM_BASE
, xlcom0_read_4
, xlcom0_write_4
)
225 static const struct powerpc_bus_space cdmac_bst
= {
226 DCR_BST_BODY(DCR_CDMAC_BASE
, cdmac0_read_4
, cdmac0_write_4
)
229 static const struct powerpc_bus_space temac_bst
= {
230 DCR_BST_BODY(DCR_TEMAC_BASE
, NULL
, temac0_write_4
)
233 static const struct powerpc_bus_space tft_bst
= {
234 DCR_BST_BODY(DCR_LLFB_BASE
, tft0_read_4
, tft0_write_4
)
238 * Master device configuration table for GSRD design.
240 static const struct gsrddev
{
241 const char *gdv_name
;
242 const char *gdv_attr
;
243 bus_space_tag_t gdv_bst
;
249 { /* gsrd_devices[0] */
251 .gdv_attr
= "xcvbus",
252 .gdv_bst
= &xlcom_bst
,
258 { /* gsrd_devices[1] */
260 .gdv_attr
= "xcvbus",
261 .gdv_bst
= &temac_bst
,
267 { /* gsrd_devices[2] */
278 static struct ll_dmac
*
279 virtex_mpmc_mapdma(int n
, struct ll_dmac
*chan
)
284 chan
->dmac_iot
= &cdmac_bst
;
285 chan
->dmac_ctrl_addr
= CDMAC_CTRL_BASE(n
);
286 chan
->dmac_stat_addr
= CDMAC_STAT_BASE(n
);
293 cdmac_intr(void *arg
)
299 isr
= bus_space_read_4(&cdmac_bst
, 0, CDMAC_INTR
);
300 bus_space_write_4(&cdmac_bst
, 0, CDMAC_INTR
, isr
); /* ack */
302 for (i
= 0; i
< CDMAC_NCHAN
; i
++)
303 if (ISSET(isr
, CDMAC_CHAN_INTR(i
)) &&
304 cdmac_intrs
[i
] != NULL
) {
305 (cdmac_intrs
[i
]->cih_func
)(cdmac_intrs
[i
]->cih_arg
);
309 /* XXX: This happens all the time under load... bug? */
312 aprint_normal("WARNING: stray cdmac isr 0x%x\n", isr
);
323 virtex_autoconf(device_t self
, struct plb_attach_args
*paa
)
325 struct xcvbus_attach_args vaa
;
326 struct ll_dmac rx
, tx
;
329 /* Reset all CDMAC engines, disable interrupt. */
330 bus_space_write_4(&cdmac_bst
, 0, CDMAC_STAT_BASE(0), CDMAC_STAT_RESET
);
331 bus_space_write_4(&cdmac_bst
, 0, CDMAC_STAT_BASE(1), CDMAC_STAT_RESET
);
332 bus_space_write_4(&cdmac_bst
, 0, CDMAC_STAT_BASE(2), CDMAC_STAT_RESET
);
333 bus_space_write_4(&cdmac_bst
, 0, CDMAC_STAT_BASE(3), CDMAC_STAT_RESET
);
334 bus_space_write_4(&cdmac_bst
, 0, CDMAC_INTR
, 0);
336 vaa
.vaa_dmat
= paa
->plb_dmat
;
337 vaa
._vaa_is_dcr
= 1; /* XXX bst flag */
339 /* Attach all we have. */
340 for (i
= 0; i
< __arraycount(gsrd_devices
); i
++) {
341 const struct gsrddev
*g
= &gsrd_devices
[i
];
343 vaa
.vaa_name
= g
->gdv_name
;
344 vaa
.vaa_addr
= g
->gdv_addr
;
345 vaa
.vaa_intr
= g
->gdv_intr
;
346 vaa
.vaa_iot
= g
->gdv_bst
;
348 vaa
.vaa_rx_dmac
= virtex_mpmc_mapdma(g
->gdv_rx_dma
, &rx
);
349 vaa
.vaa_tx_dmac
= virtex_mpmc_mapdma(g
->gdv_tx_dma
, &tx
);
351 config_found_ia(self
, g
->gdv_attr
, &vaa
, xcvbus_print
);
354 /* Setup the dispatch handler. */
355 cdmac_ih
= intr_establish(CDMAC_INTR_LINE
, IST_LEVEL
, IPL_CDMAC
,
357 if (cdmac_ih
== NULL
)
358 panic("virtex_autoconf: could not establish cdmac intr");
360 /* Enable CDMAC interrupt. */
361 bus_space_write_4(&cdmac_bst
, 0, CDMAC_INTR
, ~CDMAC_INTR_MIE
);
362 bus_space_write_4(&cdmac_bst
, 0, CDMAC_INTR
, CDMAC_INTR_MIE
);
366 ll_dmac_intr_establish(int chan
, void (*func
)(void *), void *arg
)
368 struct cdmac_intr_handle
*ih
;
370 KASSERT(chan
> 0 && chan
< CDMAC_NCHAN
);
372 /* We only allow one handler per channel, somewhat arbitrarily. */
373 if (cdmac_intrs
[chan
] != NULL
)
376 ih
= malloc(sizeof(struct cdmac_intr_handle
), M_DEVBUF
,
377 cold
? M_NOWAIT
: M_WAITOK
);
384 return (cdmac_intrs
[chan
] = ih
);
388 ll_dmac_intr_disestablish(int chan
, void *handle
)
392 KASSERT(chan
> 0 && chan
< CDMAC_NCHAN
);
393 KASSERT(cdmac_intrs
[chan
] == handle
);
396 cdmac_intrs
[chan
] = NULL
;
399 free(handle
, M_DEVBUF
);
403 virtex_bus_space_tag(const char *xname
, bus_space_tag_t
*bst
)
405 if (strncmp(xname
, "xlcom", 5) == 0) {
414 virtex_machdep_init(vaddr_t endva
, vsize_t maxsz
, struct mem_region
*phys
,
415 struct mem_region
*avail
)
417 /* Nothing to do -- no memory-mapped devices. */
421 device_register(struct device
*dev
, void *aux
)
423 /* Nothing to do -- no property hacks needed. */