1 /*        $NetBSD: gt_mainbus.c,v 1.18 2013/04/21 15:42:11 kiyohara Exp $       */
2 
3 /*
4  * Copyright (c) 2002 Wasabi Systems, Inc.
5  * All rights reserved.
6  *
7  * Written by Allen Briggs for Wasabi Systems, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed for the NetBSD Project by
20  *      Wasabi Systems, Inc.
21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22  *    or promote products derived from this software without specific prior
23  *    written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: gt_mainbus.c,v 1.18 2013/04/21 15:42:11 kiyohara Exp $");
40 
41 #include "opt_ev64260.h"
42 #include "opt_pci.h"
43 #include "pci.h"
44 
45 #include <sys/types.h>
46 #include <sys/param.h>
47 #include <sys/device.h>
48 #include <sys/errno.h>
49 #include <sys/extent.h>
50 
51 #define _POWERPC_BUS_DMA_PRIVATE
52 #include <sys/bus.h>
53 
54 #include "opt_pci.h"
55 #include <dev/pci/pcivar.h>
56 #include <dev/pci/pciconf.h>
57 
58 #include "opt_marvell.h"
59 #include <dev/marvell/gtreg.h>
60 #include <dev/marvell/gtvar.h>
61 #include <dev/marvell/gtintrreg.h>
62 #include <dev/marvell/gtpcireg.h>
63 #include <dev/marvell/gtpcivar.h>
64 #include <dev/marvell/marvellvar.h>
65 #include <dev/marvell/gtsdmareg.h>
66 #include <dev/marvell/gtmpscreg.h>
67 #ifdef MPSC_CONSOLE
68 #include <dev/marvell/gtmpscvar.h>
69 #endif
70 
71 #include <evbppc/ev64260/ev64260.h>
72 
73 #include <powerpc/pic/picvar.h>
74 
75 
76 static int gt_match(device_t, cfdata_t, void *);
77 static void gt_attach(device_t, device_t, void *);
78 
79 void gtpci_md_conf_interrupt(void *, int, int, int, int, int *);
80 int gtpci_md_conf_hook(void *, int, int, int, pcireg_t);
81 
82 CFATTACH_DECL_NEW(gt, sizeof(struct gt_softc), gt_match, gt_attach, NULL, NULL);
83 
84 struct gtpci_prot gtpci_prot = {
85           GTPCI_GT64260_ACBL_PCISWAP_NOSWAP       |
86           GTPCI_GT64260_ACBL_WBURST_8_QW                    |
87           GTPCI_GT64260_ACBL_RDMULPREFETCH        |
88           GTPCI_GT64260_ACBL_RDLINEPREFETCH       |
89           GTPCI_GT64260_ACBL_RDPREFETCH           |
90           GTPCI_GT64260_ACBL_PREFETCHEN,
91           0,
92 };
93 
94 int
gt_match(device_t parent,cfdata_t cf,void * aux)95 gt_match(device_t parent, cfdata_t cf, void *aux)
96 {
97           struct mainbus_attach_args *mba = aux;
98 
99           if (strcmp(mba->mba_name, "gt") != 0)
100                     return 0;
101 
102           return 1;
103 }
104 
105 void
gt_attach(device_t parent,device_t self,void * aux)106 gt_attach(device_t parent, device_t self, void *aux)
107 {
108           extern struct powerpc_bus_space ev64260_gt_bs_tag;
109           extern struct powerpc_bus_dma_tag ev64260_bus_dma_tag;
110           struct mainbus_attach_args *mba = aux;
111           struct gt_softc *sc = device_private(self);
112           uint32_t cpumstr, cr, r;
113 
114           sc->sc_dev = self;
115           sc->sc_addr = mba->mba_addr;
116           sc->sc_iot = &ev64260_gt_bs_tag;
117           sc->sc_dmat = &ev64260_bus_dma_tag;
118 
119 #ifdef MPSC_CONSOLE
120           {
121                     /* First, unmap already mapped console space. */
122                     gtmpsc_softc_t *gtmpsc = &gtmpsc_cn_softc;
123 
124                     bus_space_unmap(gtmpsc->sc_iot, gtmpsc->sc_mpsch, GTMPSC_SIZE);
125                     bus_space_unmap(gtmpsc->sc_iot, gtmpsc->sc_sdmah, GTSDMA_SIZE);
126           }
127 #endif
128           if (bus_space_map(sc->sc_iot, sc->sc_addr, GT_SIZE, 0, &sc->sc_ioh) !=
129               0) {
130                     aprint_error_dev(self, "registers map failed\n");
131                     return;
132           }
133 #ifdef MPSC_CONSOLE
134           {
135                     /* Next, remap console space. */
136                     gtmpsc_softc_t *gtmpsc = &gtmpsc_cn_softc;
137 
138                     if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
139                         GTMPSC_BASE(gtmpsc->sc_unit), GTMPSC_SIZE,
140                         &gtmpsc->sc_mpsch)) {
141                               aprint_error_dev(self, "Cannot map MPSC registers\n");
142                               return;
143                     }
144                     if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
145                         GTSDMA_BASE(gtmpsc->sc_unit), GTSDMA_SIZE,
146                         &gtmpsc->sc_sdmah)) {
147                               aprint_error_dev(self, "Cannot map SDMA registers\n");
148                               return;
149                     }
150           }
151 #endif
152 
153           /*
154            * Set MPSC Routing:
155            *        MR0 --> Serial Port 0
156            *        MR1 --> Serial Port 1
157            */
158           bus_space_write_4(sc->sc_iot, sc->sc_ioh, GTMPSC_MRR, GTMPSC_MRR_RES);
159 
160           /*
161            * RX and TX Clock Routing:
162            *        CRR0 --> BRG0
163            *        CRR1 --> BRG1
164            */
165           cr = GTMPSC_CRR(0, GTMPSC_CRR_BRG0) | GTMPSC_CRR(1, GTMPSC_CRR_BRG1);
166           bus_space_write_4(sc->sc_iot, sc->sc_ioh, GTMPSC_RCRR, cr);
167           bus_space_write_4(sc->sc_iot, sc->sc_ioh, GTMPSC_TCRR, cr);
168 
169           /*
170            * Setup Multi-Purpose Pins (MPP).
171            *   Change to GPP.
172            *     GPP 21 (DUART channel A intr)
173            *     GPP 22 (DUART channel B intr)
174            *     GPP 26 (RTC INT)
175            *     GPP 27 (PCI 0 INTA)
176            *     GPP 29 (PCI 1 INTA)
177            */
178 #define PIN2SHIFT(pin)        ((pin % 8) * 4)
179           r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GT_MPP_Control2);
180           r |= ((0xf << PIN2SHIFT(21)) | (0xf << PIN2SHIFT(22)));
181           bus_space_write_4(sc->sc_iot, sc->sc_ioh, GT_MPP_Control2, r);
182           r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GT_MPP_Control3);
183           r |= ((0xf << PIN2SHIFT(26)));
184           r |= ((0xf << PIN2SHIFT(27)) | (0xf << PIN2SHIFT(29)));
185           bus_space_write_4(sc->sc_iot, sc->sc_ioh, GT_MPP_Control3, r);
186 
187           /* Also configure GPP. */
188 #define GPP_EXTERNAL_INTERRUPS \
189               ((1 << 21) | (1 << 22) | (1 << 26) | (1 << 27) | (1 << 29))
190           r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GT_GPP_IO_Control);
191           r &= ~GPP_EXTERNAL_INTERRUPS;
192           bus_space_write_4(sc->sc_iot, sc->sc_ioh, GT_GPP_IO_Control, r);
193           r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GT_GPP_Level_Control);
194           r |= GPP_EXTERNAL_INTERRUPS;
195           bus_space_write_4(sc->sc_iot, sc->sc_ioh, GT_GPP_Level_Control, r);
196 
197           /* clear interrupts */
198           bus_space_write_4(sc->sc_iot, sc->sc_ioh, ICR_CIM_LO, 0);
199           bus_space_write_4(sc->sc_iot, sc->sc_ioh, ICR_CIM_HI, 0);
200           bus_space_write_4(sc->sc_iot, sc->sc_ioh, GT_GPP_Interrupt_Cause,
201               ~GPP_EXTERNAL_INTERRUPS);
202           bus_space_write_4(sc->sc_iot, sc->sc_ioh, GT_GPP_Interrupt_Mask,
203               GPP_EXTERNAL_INTERRUPS);
204 
205           discovery_pic->pic_cookie = sc;
206           intr_establish(IRQ_GPP7_0, IST_LEVEL, IPL_HIGH,
207               pic_handle_intr, discovery_gpp_pic[0]);
208           intr_establish(IRQ_GPP15_8, IST_LEVEL, IPL_HIGH,
209               pic_handle_intr, discovery_gpp_pic[1]);
210           intr_establish(IRQ_GPP23_16, IST_LEVEL, IPL_HIGH,
211               pic_handle_intr, discovery_gpp_pic[2]);
212           intr_establish(IRQ_GPP31_24, IST_LEVEL, IPL_HIGH,
213               pic_handle_intr, discovery_gpp_pic[3]);
214 
215           cpumstr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GT_CPU_Master_Ctl);
216           cpumstr &= ~(GT_CPUMstrCtl_CleanBlock|GT_CPUMstrCtl_FlushBlock);
217           bus_space_write_4(sc->sc_iot, sc->sc_ioh, GT_CPU_Master_Ctl, cpumstr);
218 
219           gt_attach_common(sc);
220 }
221 
222 
223 void
gtpci_md_conf_interrupt(void * v,int bus,int dev,int pin,int swiz,int * iline)224 gtpci_md_conf_interrupt(void *v, int bus, int dev, int pin, int swiz,
225                               int *iline)
226 {
227 #ifdef PCI_NETBSD_CONFIGURE
228           struct gtpci_softc *sc = v;
229 
230           *iline = (sc->sc_unit == 0 ? 27 : 29);
231 
232 #define IRQ_GPP_BASE          (discovery_pic->pic_numintrs);
233 
234           if (*iline != 0xff)
235                     *iline += IRQ_GPP_BASE;
236 #endif /* PCI_NETBSD_CONFIGURE */
237 }
238 
239 int
gtpci_md_conf_hook(void * v,int bus,int dev,int func,pcireg_t id)240 gtpci_md_conf_hook(void *v, int bus, int dev, int func, pcireg_t id)
241 {
242           struct gtpci_softc *sc = v;
243 
244           return gtpci_conf_hook(sc->sc_pc, bus, dev, func, id);
245 }
246 
247 
248 void *
marvell_intr_establish(int irq,int ipl,int (* func)(void *),void * arg)249 marvell_intr_establish(int irq, int ipl, int (*func)(void *), void *arg)
250 {
251 
252           /* pass through */
253           return intr_establish(irq, IST_LEVEL, ipl, func, arg);
254 }
255