1*7433666eSthorpej /* $NetBSD: design_gsrd2.c,v 1.9 2023/12/20 14:18:37 thorpej Exp $ */
2e388b581Sfreza
3e388b581Sfreza /*
4e388b581Sfreza * Copyright (c) 2006 Jachym Holecek
5e388b581Sfreza * All rights reserved.
6e388b581Sfreza *
7e388b581Sfreza * Written for DFC Design, s.r.o.
8e388b581Sfreza *
9e388b581Sfreza * Redistribution and use in source and binary forms, with or without
10e388b581Sfreza * modification, are permitted provided that the following conditions
11e388b581Sfreza * are met:
12e388b581Sfreza *
13e388b581Sfreza * 1. Redistributions of source code must retain the above copyright
14e388b581Sfreza * notice, this list of conditions and the following disclaimer.
15e388b581Sfreza *
16e388b581Sfreza * 2. Redistributions in binary form must reproduce the above copyright
17e388b581Sfreza * notice, this list of conditions and the following disclaimer in the
18e388b581Sfreza * documentation and/or other materials provided with the distribution.
19e388b581Sfreza *
20e388b581Sfreza * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21e388b581Sfreza * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22e388b581Sfreza * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23e388b581Sfreza * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24e388b581Sfreza * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25e388b581Sfreza * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26e388b581Sfreza * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27e388b581Sfreza * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28e388b581Sfreza * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29e388b581Sfreza * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30e388b581Sfreza */
31e388b581Sfreza
32e388b581Sfreza #include "opt_virtex.h"
33e388b581Sfreza
34e388b581Sfreza #include <sys/cdefs.h>
35*7433666eSthorpej __KERNEL_RCSID(0, "$NetBSD: design_gsrd2.c,v 1.9 2023/12/20 14:18:37 thorpej Exp $");
36e388b581Sfreza
37e388b581Sfreza #include <sys/param.h>
38e388b581Sfreza #include <sys/systm.h>
39e388b581Sfreza #include <sys/device.h>
40e388b581Sfreza #include <sys/kernel.h>
41e388b581Sfreza #include <sys/extent.h>
4251a2be50Smatt #include <sys/cpu.h>
4351a2be50Smatt #include <sys/bus.h>
4451a2be50Smatt #include <sys/intr.h>
45e388b581Sfreza
46e388b581Sfreza #include <machine/powerpc.h>
47e388b581Sfreza
4851a2be50Smatt #include <powerpc/ibm4xx/cpu.h>
49331fcecaSrin #include <powerpc/ibm4xx/tlb.h>
50e388b581Sfreza #include <powerpc/ibm4xx/dev/plbvar.h>
51e388b581Sfreza
52e388b581Sfreza #include <evbppc/virtex/dev/xcvbusvar.h>
53e388b581Sfreza #include <evbppc/virtex/dev/cdmacreg.h>
54e388b581Sfreza #include <evbppc/virtex/dev/temacreg.h>
55e388b581Sfreza #include <evbppc/virtex/dev/tftreg.h>
56e388b581Sfreza
57e388b581Sfreza #include <evbppc/virtex/virtex.h>
58e388b581Sfreza #include <evbppc/virtex/dcr.h>
59e388b581Sfreza
60e388b581Sfreza
61e388b581Sfreza #define DCR_TEMAC_BASE 0x0030
62e388b581Sfreza #define DCR_TFT0_BASE 0x0082
63e388b581Sfreza #define DCR_TFT1_BASE 0x0086
64e388b581Sfreza #define DCR_CDMAC_BASE 0x0140
65e388b581Sfreza
66e388b581Sfreza #define OPB_BASE 0x80000000 /* below are offsets in opb */
67e388b581Sfreza #define OPB_XLCOM_BASE 0x010000
68e388b581Sfreza #define OPB_GPIO_BASE 0x020000
69e388b581Sfreza #define OPB_PSTWO0_BASE 0x040000
70e388b581Sfreza #define OPB_PSTWO1_BASE 0x041000
71e388b581Sfreza #define CDMAC_NCHAN 2 /* cdmac {Tx,Rx} */
72e388b581Sfreza #define CDMAC_INTR_LINE 0
73e388b581Sfreza
74e388b581Sfreza #define TFT_FB_BASE 0x3c00000
75e388b581Sfreza #define TFT_FB_SIZE (2*1024*1024)
76e388b581Sfreza
77e388b581Sfreza /*
78e388b581Sfreza * CDMAC per-channel interrupt handler. CDMAC has one interrupt signal
79e388b581Sfreza * per two channels on mpmc2, so we have to dispatch channels manually.
80e388b581Sfreza *
81e388b581Sfreza * Note: we hardwire priority to IPL_NET, temac(4) is the only device that
82e388b581Sfreza * needs to service DMA interrupts anyway.
83e388b581Sfreza */
84e388b581Sfreza typedef struct cdmac_intrhand {
85e388b581Sfreza void (*cih_func)(void *);
86e388b581Sfreza void *cih_arg;
87e388b581Sfreza } *cdmac_intrhand_t;
88e388b581Sfreza
89e388b581Sfreza /* Two instantiated channels, one logical interrupt per direction. */
90e388b581Sfreza static struct cdmac_intrhand cdmacintr[CDMAC_NCHAN];
91e388b581Sfreza static void *cdmac_ih;
92e388b581Sfreza
93e388b581Sfreza
94e388b581Sfreza /*
95e388b581Sfreza * DCR bus space leaf access routines.
96e388b581Sfreza */
97e388b581Sfreza
980ded96f5Srin #ifndef DESIGN_DFC
99e388b581Sfreza static void
tft0_write_4(bus_space_tag_t t,bus_space_handle_t h,uint32_t addr,uint32_t val)100e388b581Sfreza tft0_write_4(bus_space_tag_t t, bus_space_handle_t h, uint32_t addr,
101e388b581Sfreza uint32_t val)
102e388b581Sfreza {
103e388b581Sfreza addr += h;
104e388b581Sfreza
105e388b581Sfreza switch (addr) {
106e388b581Sfreza WCASE(DCR_TFT0_BASE, TFT_CTRL);
107e388b581Sfreza WCASE(DCR_TFT0_BASE, TFT_ADDR);
108e388b581Sfreza WDEAD(addr);
109e388b581Sfreza }
110e388b581Sfreza }
111e388b581Sfreza
112e388b581Sfreza static uint32_t
tft0_read_4(bus_space_tag_t t,bus_space_handle_t h,uint32_t addr)113e388b581Sfreza tft0_read_4(bus_space_tag_t t, bus_space_handle_t h, uint32_t addr)
114e388b581Sfreza {
115e388b581Sfreza uint32_t val;
116e388b581Sfreza
117e388b581Sfreza addr += h;
118e388b581Sfreza
119e388b581Sfreza switch (addr) {
120e388b581Sfreza RCASE(DCR_TFT0_BASE, TFT_CTRL);
121e388b581Sfreza RCASE(DCR_TFT0_BASE, TFT_ADDR);
122e388b581Sfreza RDEAD(addr);
123e388b581Sfreza }
124e388b581Sfreza
125e388b581Sfreza return (val);
126e388b581Sfreza }
1270ded96f5Srin #endif /* !DESIGN_DFC */
128e388b581Sfreza
129e388b581Sfreza static void
tft1_write_4(bus_space_tag_t t,bus_space_handle_t h,uint32_t addr,uint32_t val)130e388b581Sfreza tft1_write_4(bus_space_tag_t t, bus_space_handle_t h, uint32_t addr,
131e388b581Sfreza uint32_t val)
132e388b581Sfreza {
133e388b581Sfreza addr += h;
134e388b581Sfreza
135e388b581Sfreza switch (addr) {
136e388b581Sfreza WCASE(DCR_TFT1_BASE, TFT_CTRL);
137e388b581Sfreza WCASE(DCR_TFT0_BASE, TFT_ADDR);
138e388b581Sfreza WDEAD(addr);
139e388b581Sfreza }
140e388b581Sfreza }
141e388b581Sfreza
142e388b581Sfreza static uint32_t
tft1_read_4(bus_space_tag_t t,bus_space_handle_t h,uint32_t addr)143e388b581Sfreza tft1_read_4(bus_space_tag_t t, bus_space_handle_t h, uint32_t addr)
144e388b581Sfreza {
145e388b581Sfreza uint32_t val;
146e388b581Sfreza
147e388b581Sfreza addr += h;
148e388b581Sfreza
149e388b581Sfreza switch (addr) {
150e388b581Sfreza RCASE(DCR_TFT1_BASE, TFT_CTRL);
151e388b581Sfreza RCASE(DCR_TFT0_BASE, TFT_ADDR);
152e388b581Sfreza RDEAD(addr);
153e388b581Sfreza }
154e388b581Sfreza
155e388b581Sfreza return (val);
156e388b581Sfreza }
157e388b581Sfreza
158e388b581Sfreza #define DOCHAN(op, base, channel) \
159e388b581Sfreza op(base, channel + CDMAC_NEXT); \
160e388b581Sfreza op(base, channel + CDMAC_CURADDR); \
161e388b581Sfreza op(base, channel + CDMAC_CURSIZE); \
162e388b581Sfreza op(base, channel + CDMAC_CURDESC)
163e388b581Sfreza
164e388b581Sfreza static void
cdmac_write_4(bus_space_tag_t t,bus_space_handle_t h,uint32_t addr,uint32_t val)165e388b581Sfreza cdmac_write_4(bus_space_tag_t t, bus_space_handle_t h, uint32_t addr,
166e388b581Sfreza uint32_t val)
167e388b581Sfreza {
168e388b581Sfreza addr += h;
169e388b581Sfreza
170e388b581Sfreza switch (addr) {
171e388b581Sfreza WCASE(DCR_CDMAC_BASE, CDMAC_STAT_BASE(0)); /* Tx engine */
172e388b581Sfreza WCASE(DCR_CDMAC_BASE, CDMAC_STAT_BASE(1)); /* Rx engine */
173e388b581Sfreza WCASE(DCR_CDMAC_BASE, CDMAC_INTR);
174e388b581Sfreza DOCHAN(WCASE, DCR_CDMAC_BASE, CDMAC_CTRL_BASE(0));
175e388b581Sfreza DOCHAN(WCASE, DCR_CDMAC_BASE, CDMAC_CTRL_BASE(1));
176e388b581Sfreza WDEAD(addr);
177e388b581Sfreza }
178e388b581Sfreza }
179e388b581Sfreza
180e388b581Sfreza static uint32_t
cdmac_read_4(bus_space_tag_t t,bus_space_handle_t h,uint32_t addr)181e388b581Sfreza cdmac_read_4(bus_space_tag_t t, bus_space_handle_t h, uint32_t addr)
182e388b581Sfreza {
183e388b581Sfreza uint32_t val;
184e388b581Sfreza
185e388b581Sfreza addr += h;
186e388b581Sfreza
187e388b581Sfreza switch (addr) {
188e388b581Sfreza RCASE(DCR_CDMAC_BASE, CDMAC_STAT_BASE(0)); /* Tx engine */
189e388b581Sfreza RCASE(DCR_CDMAC_BASE, CDMAC_STAT_BASE(1)); /* Rx engine */
190e388b581Sfreza RCASE(DCR_CDMAC_BASE, CDMAC_INTR);
191e388b581Sfreza DOCHAN(RCASE, DCR_CDMAC_BASE, CDMAC_CTRL_BASE(0));
192e388b581Sfreza DOCHAN(RCASE, DCR_CDMAC_BASE, CDMAC_CTRL_BASE(1));
193e388b581Sfreza RDEAD(addr);
194e388b581Sfreza }
195e388b581Sfreza
196e388b581Sfreza return (val);
197e388b581Sfreza }
198e388b581Sfreza
199e388b581Sfreza #undef DOCHAN
200e388b581Sfreza
201e388b581Sfreza static void
temac_write_4(bus_space_tag_t t,bus_space_handle_t h,uint32_t addr,uint32_t val)202e388b581Sfreza temac_write_4(bus_space_tag_t t, bus_space_handle_t h, uint32_t addr,
203e388b581Sfreza uint32_t val)
204e388b581Sfreza {
205e388b581Sfreza addr += h;
206e388b581Sfreza
207e388b581Sfreza switch (addr) {
208e388b581Sfreza WCASE(DCR_TEMAC_BASE, TEMAC_RESET);
209e388b581Sfreza WDEAD(addr);
210e388b581Sfreza }
211e388b581Sfreza }
212e388b581Sfreza
213e388b581Sfreza static uint32_t
temac_read_4(bus_space_tag_t t,bus_space_handle_t h,uint32_t addr)214e388b581Sfreza temac_read_4(bus_space_tag_t t, bus_space_handle_t h, uint32_t addr)
215e388b581Sfreza {
216e388b581Sfreza uint32_t val;
217e388b581Sfreza
218e388b581Sfreza addr += h;
219e388b581Sfreza
220e388b581Sfreza switch (addr) {
221e388b581Sfreza RCASE(DCR_TEMAC_BASE, TEMAC_RESET);
222e388b581Sfreza RDEAD(addr);
223e388b581Sfreza }
224e388b581Sfreza
225e388b581Sfreza return (val);
226e388b581Sfreza }
227e388b581Sfreza
228e388b581Sfreza static const struct powerpc_bus_space cdmac_bst = {
229e388b581Sfreza DCR_BST_BODY(DCR_CDMAC_BASE, cdmac_read_4, cdmac_write_4)
230e388b581Sfreza };
231e388b581Sfreza
232e388b581Sfreza static const struct powerpc_bus_space temac_bst = {
233e388b581Sfreza DCR_BST_BODY(DCR_TEMAC_BASE, temac_read_4, temac_write_4)
234e388b581Sfreza };
235e388b581Sfreza
2360ded96f5Srin #ifndef DESIGN_DFC
237e388b581Sfreza static const struct powerpc_bus_space tft0_bst = {
238e388b581Sfreza DCR_BST_BODY(DCR_TFT0_BASE, tft0_read_4, tft0_write_4)
239e388b581Sfreza };
2400ded96f5Srin #endif
241e388b581Sfreza
242e388b581Sfreza static const struct powerpc_bus_space tft1_bst = {
243e388b581Sfreza DCR_BST_BODY(DCR_TFT1_BASE, tft1_read_4, tft1_write_4)
244e388b581Sfreza };
245e388b581Sfreza
246e388b581Sfreza static struct powerpc_bus_space opb_bst = {
247e388b581Sfreza .pbs_flags = _BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE,
248e388b581Sfreza .pbs_base = 0 /*OPB_BASE*/,
249e388b581Sfreza .pbs_offset = OPB_BASE,
250e388b581Sfreza };
251e388b581Sfreza
252e388b581Sfreza static char opb_extent_storage[EXTENT_FIXED_STORAGE_SIZE(8)] __aligned(8);
253e388b581Sfreza
254e388b581Sfreza /*
255e388b581Sfreza * Master device configuration table for GSRD2 design.
256e388b581Sfreza */
257e388b581Sfreza static const struct gsrddev {
258e388b581Sfreza const char *gdv_name;
259e388b581Sfreza const char *gdv_attr;
260e388b581Sfreza bus_space_tag_t gdv_bst;
261e388b581Sfreza bus_addr_t gdv_addr;
262e388b581Sfreza int gdv_intr;
263e388b581Sfreza int gdv_rx_dma;
264e388b581Sfreza int gdv_tx_dma;
265e388b581Sfreza int gdv_dcr; /* XXX bst flag */
266e388b581Sfreza } gsrd_devices[] = {
267e388b581Sfreza { /* gsrd_devices[0] */
268e388b581Sfreza .gdv_name = "xlcom",
269e388b581Sfreza .gdv_attr = "xcvbus",
270e388b581Sfreza .gdv_bst = &opb_bst,
271e388b581Sfreza .gdv_addr = OPB_XLCOM_BASE,
272e388b581Sfreza .gdv_intr = 2,
273e388b581Sfreza .gdv_rx_dma = -1,
274e388b581Sfreza .gdv_tx_dma = -1,
275e388b581Sfreza .gdv_dcr = 0,
276e388b581Sfreza },
277e388b581Sfreza { /* gsrd_devices[1] */
278e388b581Sfreza .gdv_name = "temac",
279e388b581Sfreza .gdv_attr = "xcvbus",
280e388b581Sfreza .gdv_bst = &temac_bst,
281e388b581Sfreza .gdv_addr = 0,
282e388b581Sfreza .gdv_intr = 1, /* unused MII intr */
283e388b581Sfreza .gdv_rx_dma = 1, /* cdmac Rx */
284e388b581Sfreza .gdv_tx_dma = 0, /* cdmac Tx */
285e388b581Sfreza .gdv_dcr = 1,
286e388b581Sfreza },
287e388b581Sfreza #ifndef DESIGN_DFC
288e388b581Sfreza { /* gsrd_devices[2] */
289e388b581Sfreza .gdv_name = "tft",
290e388b581Sfreza .gdv_attr = "plbus",
291e388b581Sfreza .gdv_bst = &tft0_bst,
292e388b581Sfreza .gdv_addr = 0,
293e388b581Sfreza .gdv_intr = -1,
294e388b581Sfreza .gdv_rx_dma = -1,
295e388b581Sfreza .gdv_tx_dma = -1,
296e388b581Sfreza .gdv_dcr = 1,
297e388b581Sfreza },
298e388b581Sfreza #endif
299e388b581Sfreza { /* gsrd_devices[2] */
300e388b581Sfreza .gdv_name = "tft",
301e388b581Sfreza .gdv_attr = "plbus",
302e388b581Sfreza .gdv_bst = &tft1_bst,
303e388b581Sfreza .gdv_addr = 0,
304e388b581Sfreza .gdv_intr = -1,
305e388b581Sfreza .gdv_rx_dma = -1,
306e388b581Sfreza .gdv_tx_dma = -1,
307e388b581Sfreza .gdv_dcr = 1,
308e388b581Sfreza },
309e388b581Sfreza #ifdef DESIGN_DFC
310e388b581Sfreza { /* gsrd_devices[3] */
311e388b581Sfreza .gdv_name = "pstwo",
312e388b581Sfreza .gdv_attr = "xcvbus",
313e388b581Sfreza .gdv_bst = &opb_bst,
314e388b581Sfreza .gdv_addr = OPB_PSTWO0_BASE,
315e388b581Sfreza .gdv_intr = 3,
316e388b581Sfreza .gdv_rx_dma = -1,
317e388b581Sfreza .gdv_tx_dma = -1,
318e388b581Sfreza .gdv_dcr = 0,
319e388b581Sfreza },
320e388b581Sfreza { /* gsrd_devices[4] */
321e388b581Sfreza .gdv_name = "pstwo",
322e388b581Sfreza .gdv_attr = "xcvbus",
323e388b581Sfreza .gdv_bst = &opb_bst,
324e388b581Sfreza .gdv_addr = OPB_PSTWO1_BASE,
325e388b581Sfreza .gdv_intr = 4,
326e388b581Sfreza .gdv_rx_dma = -1,
327e388b581Sfreza .gdv_tx_dma = -1,
328e388b581Sfreza .gdv_dcr = 0,
329e388b581Sfreza },
330e388b581Sfreza #endif
331e388b581Sfreza };
332e388b581Sfreza
333e388b581Sfreza static struct ll_dmac *
virtex_mpmc_mapdma(int idx,struct ll_dmac * chan)334e388b581Sfreza virtex_mpmc_mapdma(int idx, struct ll_dmac *chan)
335e388b581Sfreza {
336e388b581Sfreza if (idx == -1)
337e388b581Sfreza return (NULL);
338e388b581Sfreza
339e388b581Sfreza KASSERT(idx >= 0 && idx < CDMAC_NCHAN);
340e388b581Sfreza
341e388b581Sfreza chan->dmac_iot = &cdmac_bst;
342e388b581Sfreza chan->dmac_ctrl_addr = CDMAC_CTRL_BASE(idx);
343e388b581Sfreza chan->dmac_stat_addr = CDMAC_STAT_BASE(idx);
344e388b581Sfreza chan->dmac_chan = idx;
345e388b581Sfreza
346e388b581Sfreza return (chan);
347e388b581Sfreza }
348e388b581Sfreza
349e388b581Sfreza static int
cdmac_intr(void * arg)350e388b581Sfreza cdmac_intr(void *arg)
351e388b581Sfreza {
352e388b581Sfreza uint32_t isr;
353e388b581Sfreza int did = 0;
354e388b581Sfreza
355e388b581Sfreza isr = bus_space_read_4(&cdmac_bst, 0, CDMAC_INTR);
356e388b581Sfreza
357e388b581Sfreza if (ISSET(isr, CDMAC_INTR_TX0) && cdmacintr[0].cih_func) {
358e388b581Sfreza (cdmacintr[0].cih_func)(cdmacintr[0].cih_arg);
359e388b581Sfreza did++;
360e388b581Sfreza }
361e388b581Sfreza if (ISSET(isr, CDMAC_INTR_RX0) && cdmacintr[1].cih_func) {
362e388b581Sfreza (cdmacintr[1].cih_func)(cdmacintr[1].cih_arg);
363e388b581Sfreza did++;
364e388b581Sfreza }
365e388b581Sfreza
366e388b581Sfreza bus_space_write_4(&cdmac_bst, 0, CDMAC_INTR, isr); /* ack */
367e388b581Sfreza
368e388b581Sfreza /* XXX This still happens all the time under load. */
369e388b581Sfreza #if 0
370e388b581Sfreza if (did == 0)
371e388b581Sfreza aprint_normal("WARNING: stray cdmac isr 0x%x\n", isr);
372e388b581Sfreza #endif
373e388b581Sfreza return (0);
374e388b581Sfreza }
375e388b581Sfreza
376e388b581Sfreza /*
377e388b581Sfreza * Public interface.
378e388b581Sfreza */
379e388b581Sfreza
380e388b581Sfreza void
virtex_autoconf(device_t self,struct plb_attach_args * paa)381e388b581Sfreza virtex_autoconf(device_t self, struct plb_attach_args *paa)
382e388b581Sfreza {
383e388b581Sfreza
384e388b581Sfreza struct xcvbus_attach_args vaa;
385e388b581Sfreza struct ll_dmac rx, tx;
386e388b581Sfreza int i;
387e388b581Sfreza
388e388b581Sfreza /* Reset DMA channels. */
389e388b581Sfreza bus_space_write_4(&cdmac_bst, 0, CDMAC_STAT_BASE(0), CDMAC_STAT_RESET);
390e388b581Sfreza bus_space_write_4(&cdmac_bst, 0, CDMAC_STAT_BASE(1), CDMAC_STAT_RESET);
391e388b581Sfreza bus_space_write_4(&cdmac_bst, 0, CDMAC_INTR, 0);
392e388b581Sfreza
393e388b581Sfreza vaa.vaa_dmat = paa->plb_dmat;
394e388b581Sfreza
395e388b581Sfreza for (i = 0; i < __arraycount(gsrd_devices); i++) {
396e388b581Sfreza const struct gsrddev *g = &gsrd_devices[i];
397e388b581Sfreza
398e388b581Sfreza vaa._vaa_is_dcr = g->gdv_dcr; /* XXX bst flag */
399e388b581Sfreza vaa.vaa_name = g->gdv_name;
400e388b581Sfreza vaa.vaa_addr = g->gdv_addr;
401e388b581Sfreza vaa.vaa_intr = g->gdv_intr;
402e388b581Sfreza vaa.vaa_iot = g->gdv_bst;
403e388b581Sfreza
404e388b581Sfreza vaa.vaa_rx_dmac = virtex_mpmc_mapdma(g->gdv_rx_dma, &rx);
405e388b581Sfreza vaa.vaa_tx_dmac = virtex_mpmc_mapdma(g->gdv_tx_dma, &tx);
406e388b581Sfreza
4072685996bSthorpej config_found(self, &vaa, xcvbus_print,
408c7fb772bSthorpej CFARGS(.iattr = g->gdv_attr));
409e388b581Sfreza }
410e388b581Sfreza
411e388b581Sfreza /* Setup the dispatch handler. */
412e388b581Sfreza cdmac_ih = intr_establish(CDMAC_INTR_LINE, IST_LEVEL, IPL_NET,
413e388b581Sfreza cdmac_intr, NULL);
414e388b581Sfreza if (cdmac_ih == NULL)
415e388b581Sfreza panic("virtex_mpmc_done: could not establish cdmac intr");
416e388b581Sfreza
417e388b581Sfreza /* Clear (XXX?) and enable interrupts. */
418e388b581Sfreza bus_space_write_4(&cdmac_bst, 0, CDMAC_INTR, ~CDMAC_INTR_MIE);
419e388b581Sfreza bus_space_write_4(&cdmac_bst, 0, CDMAC_INTR, CDMAC_INTR_MIE);
420e388b581Sfreza }
421e388b581Sfreza
422e388b581Sfreza void *
ll_dmac_intr_establish(int chan,void (* handler)(void *),void * arg)423e388b581Sfreza ll_dmac_intr_establish(int chan, void (*handler)(void *), void *arg)
424e388b581Sfreza {
425e388b581Sfreza KASSERT(chan >= 0 && chan < CDMAC_NCHAN);
426e388b581Sfreza KASSERT(cdmacintr[chan].cih_func == NULL);
427e388b581Sfreza KASSERT(cdmacintr[chan].cih_arg == NULL);
428e388b581Sfreza
429e388b581Sfreza cdmacintr[chan].cih_func = handler;
430e388b581Sfreza cdmacintr[chan].cih_arg = arg;
431e388b581Sfreza
432e388b581Sfreza return (&cdmacintr[chan]);
433e388b581Sfreza }
434e388b581Sfreza
435e388b581Sfreza void
ll_dmac_intr_disestablish(int chan,void * handle)436e388b581Sfreza ll_dmac_intr_disestablish(int chan, void *handle)
437e388b581Sfreza {
438e388b581Sfreza int s;
439e388b581Sfreza
440e388b581Sfreza KASSERT(chan >= 0 && chan < CDMAC_NCHAN);
441e388b581Sfreza KASSERT(&cdmacintr[chan] == handle);
442e388b581Sfreza
443e388b581Sfreza s = splnet();
444e388b581Sfreza cdmacintr[chan].cih_func = NULL;
445e388b581Sfreza cdmacintr[chan].cih_arg = NULL;
446e388b581Sfreza splx(s);
447e388b581Sfreza }
448e388b581Sfreza
449e388b581Sfreza int
virtex_bus_space_tag(const char * xname,bus_space_tag_t * bst)450d974db0aSgarbled virtex_bus_space_tag(const char *xname, bus_space_tag_t *bst)
451e388b581Sfreza {
452e388b581Sfreza if (strncmp(xname, "xlcom", 5) == 0) {
453e388b581Sfreza *bst = &opb_bst;
454e388b581Sfreza return (0);
455e388b581Sfreza }
456e388b581Sfreza
457e388b581Sfreza return (ENODEV);
458e388b581Sfreza }
459e388b581Sfreza
460e388b581Sfreza void
virtex_machdep_init(vaddr_t endva,vsize_t maxsz,struct mem_region * phys,struct mem_region * avail)461e388b581Sfreza virtex_machdep_init(vaddr_t endva, vsize_t maxsz, struct mem_region *phys,
462e388b581Sfreza struct mem_region *avail)
463e388b581Sfreza {
464e388b581Sfreza ppc4xx_tlb_reserve(OPB_BASE, endva, maxsz, TLB_I | TLB_G);
465e388b581Sfreza endva += maxsz;
466e388b581Sfreza
467e388b581Sfreza opb_bst.pbs_limit = maxsz;
468e388b581Sfreza
469e388b581Sfreza if (bus_space_init(&opb_bst, "opbtag", opb_extent_storage,
470e388b581Sfreza sizeof(opb_extent_storage)))
471e388b581Sfreza panic("virtex_machdep_init: failed to initialize opb_bst");
472e388b581Sfreza
473e388b581Sfreza /*
474e388b581Sfreza * The TFT controller is broken, we can't change FB address.
475e388b581Sfreza * Hardwire it at predefined base address, create uncached
476e388b581Sfreza * mapping.
477e388b581Sfreza */
478e388b581Sfreza
479e388b581Sfreza avail[0].size = TFT_FB_BASE - avail[0].start;
480e388b581Sfreza ppc4xx_tlb_reserve(TFT_FB_BASE, endva, TFT_FB_SIZE, TLB_I | TLB_G);
481e388b581Sfreza }
482e388b581Sfreza
483e388b581Sfreza void
device_register(device_t dev,void * aux)48451a2be50Smatt device_register(device_t dev, void *aux)
485e388b581Sfreza {
486e388b581Sfreza prop_number_t pn;
487e388b581Sfreza void *fb;
488e388b581Sfreza
489e388b581Sfreza if (strncmp(device_xname(dev), "tft0", 4) == 0) {
490e388b581Sfreza fb = ppc4xx_tlb_mapiodev(TFT_FB_BASE, TFT_FB_SIZE);
491e388b581Sfreza if (fb == NULL)
492e388b581Sfreza panic("device_register: framebuffer mapping gone!\n");
493e388b581Sfreza
494e388b581Sfreza pn = prop_number_create_unsigned_integer(TFT_FB_BASE);
495e388b581Sfreza if (pn == NULL) {
496e388b581Sfreza printf("WARNING: could not allocate virtex-tft-pa\n");
497e388b581Sfreza return ;
498e388b581Sfreza }
499e388b581Sfreza if (prop_dictionary_set(device_properties(dev),
5008b3bae62Sthorpej "virtex-tft-pa", pn) != true)
501e388b581Sfreza printf("WARNING: could not set virtex-tft-pa\n");
502e388b581Sfreza prop_object_release(pn);
503e388b581Sfreza
504e388b581Sfreza pn = prop_number_create_unsigned_integer((uintptr_t)fb);
505e388b581Sfreza if (pn == NULL) {
506e388b581Sfreza printf("WARNING: could not allocate virtex-tft-va\n");
507e388b581Sfreza return ;
508e388b581Sfreza }
509e388b581Sfreza if (prop_dictionary_set(device_properties(dev),
5108b3bae62Sthorpej "virtex-tft-va", pn) != true)
511e388b581Sfreza printf("WARNING: could not set virtex-tft-va\n");
512e388b581Sfreza prop_object_release(pn);
513e388b581Sfreza }
514e388b581Sfreza }
515