gt.c revision 1.21.2.1 1 1.21.2.1 uebayasi /* $NetBSD: gt.c,v 1.21.2.1 2010/04/30 14:43:27 uebayasi Exp $ */
2 1.1 matt
3 1.1 matt /*
4 1.1 matt * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.
5 1.1 matt * All rights reserved.
6 1.1 matt *
7 1.1 matt * Redistribution and use in source and binary forms, with or without
8 1.1 matt * modification, are permitted provided that the following conditions
9 1.1 matt * are met:
10 1.1 matt * 1. Redistributions of source code must retain the above copyright
11 1.1 matt * notice, this list of conditions and the following disclaimer.
12 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 matt * notice, this list of conditions and the following disclaimer in the
14 1.1 matt * documentation and/or other materials provided with the distribution.
15 1.1 matt * 3. All advertising materials mentioning features or use of this software
16 1.1 matt * must display the following acknowledgement:
17 1.1 matt * This product includes software developed for the NetBSD Project by
18 1.1 matt * Allegro Networks, Inc., and Wasabi Systems, Inc.
19 1.1 matt * 4. The name of Allegro Networks, Inc. may not be used to endorse
20 1.1 matt * or promote products derived from this software without specific prior
21 1.1 matt * written permission.
22 1.1 matt * 5. The name of Wasabi Systems, Inc. may not be used to endorse
23 1.1 matt * or promote products derived from this software without specific prior
24 1.1 matt * written permission.
25 1.1 matt *
26 1.1 matt * THIS SOFTWARE IS PROVIDED BY ALLEGRO NETWORKS, INC. AND
27 1.1 matt * WASABI SYSTEMS, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
28 1.1 matt * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
29 1.1 matt * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 1.1 matt * IN NO EVENT SHALL EITHER ALLEGRO NETWORKS, INC. OR WASABI SYSTEMS, INC.
31 1.1 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 1.1 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 1.1 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 1.1 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 1.1 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 1.1 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 1.1 matt * POSSIBILITY OF SUCH DAMAGE.
38 1.1 matt */
39 1.1 matt
40 1.1 matt /*
41 1.1 matt * gt.c -- GT system controller driver
42 1.1 matt */
43 1.5 lukem
44 1.5 lukem #include <sys/cdefs.h>
45 1.21.2.1 uebayasi __KERNEL_RCSID(0, "$NetBSD: gt.c,v 1.21.2.1 2010/04/30 14:43:27 uebayasi Exp $");
46 1.1 matt
47 1.1 matt #include "opt_marvell.h"
48 1.21.2.1 uebayasi #include "gtmpsc.h"
49 1.8 jmc #include "locators.h"
50 1.1 matt
51 1.1 matt #include <sys/param.h>
52 1.21.2.1 uebayasi #include <sys/bus.h>
53 1.1 matt #include <sys/device.h>
54 1.1 matt #include <sys/kernel.h>
55 1.21.2.1 uebayasi #include <sys/types.h>
56 1.1 matt
57 1.1 matt #include <dev/marvell/gtintrreg.h>
58 1.21.2.1 uebayasi #include <dev/marvell/gtsdmareg.h>
59 1.21.2.1 uebayasi #if NGTMPSC > 0
60 1.21.2.1 uebayasi #include <dev/marvell/gtmpscreg.h>
61 1.21.2.1 uebayasi #include <dev/marvell/gtmpscvar.h>
62 1.21.2.1 uebayasi #endif
63 1.21.2.1 uebayasi #include <dev/marvell/gtpcireg.h>
64 1.21.2.1 uebayasi #include <dev/marvell/gtreg.h>
65 1.1 matt #include <dev/marvell/gtvar.h>
66 1.21.2.1 uebayasi #include <dev/marvell/marvellreg.h>
67 1.21.2.1 uebayasi #include <dev/marvell/marvellvar.h>
68 1.21.2.1 uebayasi
69 1.21.2.1 uebayasi #include <dev/pci/pcireg.h>
70 1.1 matt
71 1.1 matt #ifdef DEBUG
72 1.1 matt #include <sys/systm.h> /* for Debugger() */
73 1.1 matt #endif
74 1.1 matt
75 1.1 matt #if ((GT_MPP_WATCHDOG & 0xf0f0f0f0) != 0)
76 1.1 matt # error /* unqualified: configuration botch! */
77 1.1 matt #endif
78 1.1 matt
79 1.21.2.1 uebayasi #define gt_read(sc,r) bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (r))
80 1.21.2.1 uebayasi #define gt_write(sc,r,v) bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (r), (v))
81 1.21.2.1 uebayasi
82 1.21.2.1 uebayasi
83 1.21.2.1 uebayasi static int gt_cfprint(void *, const char *);
84 1.21.2.1 uebayasi static int gt_cfsearch(device_t, cfdata_t, const int *, void *);
85 1.21.2.1 uebayasi static void gt_attach_peripherals(struct gt_softc *);
86 1.21.2.1 uebayasi
87 1.21.2.1 uebayasi #ifdef GT_DEVBUS
88 1.21.2.1 uebayasi static int gt_devbus_intr(void *);
89 1.3 matt static void gt_devbus_intr_enb(struct gt_softc *);
90 1.21.2.1 uebayasi #endif
91 1.1 matt #ifdef GT_ECC
92 1.21.2.1 uebayasi static int gt_ecc_intr(void *);
93 1.3 matt static void gt_ecc_intr_enb(struct gt_softc *);
94 1.1 matt #endif
95 1.21.2.1 uebayasi #if NGTMPSC > 0
96 1.21.2.1 uebayasi static void gt_sdma_intr_enb(struct gt_softc *);
97 1.21.2.1 uebayasi #endif
98 1.21.2.1 uebayasi #ifdef GT_COMM
99 1.21.2.1 uebayasi static int gt_comm_intr(void *);
100 1.21.2.1 uebayasi static void gt_comm_intr_enb(struct gt_softc *);
101 1.21.2.1 uebayasi #endif
102 1.21.2.1 uebayasi
103 1.1 matt
104 1.21.2.1 uebayasi #ifdef GT_WATCHDOG
105 1.21.2.1 uebayasi static void gt_watchdog_init(struct gt_softc *);
106 1.21.2.1 uebayasi static void gt_watchdog_enable(struct gt_softc *);
107 1.21.2.1 uebayasi #ifndef GT_MPP_WATCHDOG
108 1.21.2.1 uebayasi static void gt_watchdog_disable(struct gt_softc *);
109 1.21.2.1 uebayasi #endif
110 1.6 matt
111 1.21.2.1 uebayasi static struct gt_softc *gt_watchdog_sc = NULL;
112 1.21.2.1 uebayasi static int gt_watchdog_state = 0;
113 1.21.2.1 uebayasi #endif
114 1.1 matt
115 1.1 matt
116 1.21.2.1 uebayasi #define OFFSET_DEFAULT GTCF_OFFSET_DEFAULT
117 1.21.2.1 uebayasi #define IRQ_DEFAULT GTCF_IRQ_DEFAULT
118 1.21.2.1 uebayasi static const struct gt_dev {
119 1.21.2.1 uebayasi int model;
120 1.21.2.1 uebayasi const char *name;
121 1.21.2.1 uebayasi int unit;
122 1.21.2.1 uebayasi bus_size_t offset;
123 1.21.2.1 uebayasi int irq;
124 1.21.2.1 uebayasi } gt_devs[] = {
125 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "gfec", 0, 0x0000, IRQ_DEFAULT },
126 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "gtidmac", 0, 0x0000, 4 /*...7 */ },
127 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "gtmpsc", 0, 0x8000, 40 },
128 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "gtmpsc", 1, 0x9000, 42 },
129 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "gtpci", 0, OFFSET_DEFAULT, IRQ_DEFAULT },
130 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "gtpci", 1, OFFSET_DEFAULT, IRQ_DEFAULT },
131 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "gttwsi", 0, 0xc000, 37 },
132 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "obio", 0, OFFSET_DEFAULT, IRQ_DEFAULT },
133 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "obio", 1, OFFSET_DEFAULT, IRQ_DEFAULT },
134 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "obio", 2, OFFSET_DEFAULT, IRQ_DEFAULT },
135 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "obio", 3, OFFSET_DEFAULT, IRQ_DEFAULT },
136 1.21.2.1 uebayasi { MARVELL_DISCOVERY, "obio", 4, OFFSET_DEFAULT, IRQ_DEFAULT },
137 1.21.2.1 uebayasi
138 1.21.2.1 uebayasi { MARVELL_DISCOVERY_II, "gtidmac", 0, 0x0000, 4 /*...7 */ },
139 1.21.2.1 uebayasi { MARVELL_DISCOVERY_II, "gtmpsc", 0, 0x8000, 40 },
140 1.21.2.1 uebayasi { MARVELL_DISCOVERY_II, "gtmpsc", 1, 0x9000, 42 },
141 1.21.2.1 uebayasi { MARVELL_DISCOVERY_II, "gtpci", 0, OFFSET_DEFAULT, IRQ_DEFAULT },
142 1.21.2.1 uebayasi { MARVELL_DISCOVERY_II, "gtpci", 1, OFFSET_DEFAULT, IRQ_DEFAULT },
143 1.21.2.1 uebayasi { MARVELL_DISCOVERY_II, "gttwsi", 0, 0xc000, 37 },
144 1.21.2.1 uebayasi { MARVELL_DISCOVERY_II, "mvgbec", 0, 0x0000, IRQ_DEFAULT },
145 1.1 matt
146 1.21.2.1 uebayasi #if 0
147 1.21.2.1 uebayasi { MARVELL_DISCOVERY_III,"gtidmac", 0, 0x0000, 4 /*...7 */ },
148 1.21.2.1 uebayasi { MARVELL_DISCOVERY_III,"gtmpsc", 0, 0x8000, 40 },
149 1.21.2.1 uebayasi { MARVELL_DISCOVERY_III,"gtmpsc", 1, 0x9000, 42 },
150 1.21.2.1 uebayasi { MARVELL_DISCOVERY_III,"gtpci", 0, OFFSET_DEFAULT, IRQ_DEFAULT },
151 1.21.2.1 uebayasi { MARVELL_DISCOVERY_III,"gtpci", 1, OFFSET_DEFAULT, IRQ_DEFAULT },
152 1.21.2.1 uebayasi { MARVELL_DISCOVERY_III,"gttwsi", 0, 0xc000, 37 },
153 1.21.2.1 uebayasi { MARVELL_DISCOVERY_III,"mvgbec", 0, 0x0000, IRQ_DEFAULT },
154 1.21.2.1 uebayasi #endif
155 1.21.2.1 uebayasi };
156 1.1 matt
157 1.1 matt
158 1.21.2.1 uebayasi static int
159 1.21.2.1 uebayasi gt_cfprint(void *aux, const char *pnp)
160 1.1 matt {
161 1.21.2.1 uebayasi struct marvell_attach_args *mva = aux;
162 1.1 matt
163 1.21.2.1 uebayasi if (pnp)
164 1.21.2.1 uebayasi aprint_normal("%s at %s unit %d",
165 1.21.2.1 uebayasi mva->mva_name, pnp, mva->mva_unit);
166 1.21.2.1 uebayasi else {
167 1.21.2.1 uebayasi if (mva->mva_unit != GTCF_UNIT_DEFAULT)
168 1.21.2.1 uebayasi aprint_normal(" unit %d", mva->mva_unit);
169 1.21.2.1 uebayasi if (mva->mva_offset != GTCF_OFFSET_DEFAULT) {
170 1.21.2.1 uebayasi aprint_normal(" offset 0x%04x", mva->mva_offset);
171 1.21.2.1 uebayasi if (mva->mva_size > 0)
172 1.21.2.1 uebayasi aprint_normal("-0x%04x",
173 1.21.2.1 uebayasi mva->mva_offset + mva->mva_size - 1);
174 1.21.2.1 uebayasi }
175 1.21.2.1 uebayasi if (mva->mva_irq != GTCF_IRQ_DEFAULT)
176 1.21.2.1 uebayasi aprint_normal(" irq %d", mva->mva_irq);
177 1.1 matt }
178 1.1 matt
179 1.21.2.1 uebayasi return UNCONF;
180 1.1 matt }
181 1.1 matt
182 1.1 matt
183 1.21.2.1 uebayasi /* ARGSUSED */
184 1.1 matt static int
185 1.21.2.1 uebayasi gt_cfsearch(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
186 1.1 matt {
187 1.21.2.1 uebayasi struct marvell_attach_args *mva = aux;
188 1.21.2.1 uebayasi
189 1.21.2.1 uebayasi if (cf->cf_loc[GTCF_IRQ] != GTCF_IRQ_DEFAULT)
190 1.21.2.1 uebayasi mva->mva_irq = cf->cf_loc[GTCF_IRQ];
191 1.1 matt
192 1.21.2.1 uebayasi return config_match(parent, cf, aux);
193 1.21.2.1 uebayasi }
194 1.21.2.1 uebayasi
195 1.21.2.1 uebayasi static void
196 1.21.2.1 uebayasi gt_attach_peripherals(struct gt_softc *sc)
197 1.21.2.1 uebayasi {
198 1.21.2.1 uebayasi struct marvell_attach_args mva;
199 1.21.2.1 uebayasi int i;
200 1.1 matt
201 1.21.2.1 uebayasi for (i = 0; i < __arraycount(gt_devs); i++) {
202 1.21.2.1 uebayasi if (gt_devs[i].model != sc->sc_model)
203 1.21.2.1 uebayasi continue;
204 1.21.2.1 uebayasi
205 1.21.2.1 uebayasi mva.mva_name = gt_devs[i].name;
206 1.21.2.1 uebayasi mva.mva_model = sc->sc_model;
207 1.21.2.1 uebayasi mva.mva_revision = sc->sc_rev;
208 1.21.2.1 uebayasi mva.mva_iot = sc->sc_iot;
209 1.21.2.1 uebayasi mva.mva_ioh = sc->sc_ioh;
210 1.21.2.1 uebayasi mva.mva_unit = gt_devs[i].unit;
211 1.21.2.1 uebayasi mva.mva_addr = sc->sc_addr;
212 1.21.2.1 uebayasi mva.mva_offset = gt_devs[i].offset;
213 1.21.2.1 uebayasi mva.mva_size = 0;
214 1.21.2.1 uebayasi mva.mva_dmat = sc->sc_dmat;
215 1.21.2.1 uebayasi mva.mva_irq = gt_devs[i].irq;
216 1.1 matt
217 1.21.2.1 uebayasi config_found_sm_loc(sc->sc_dev, "gt", NULL, &mva,
218 1.21.2.1 uebayasi gt_cfprint, gt_cfsearch);
219 1.21.2.1 uebayasi }
220 1.1 matt }
221 1.1 matt
222 1.1 matt void
223 1.1 matt gt_attach_common(struct gt_softc *gt)
224 1.1 matt {
225 1.1 matt uint32_t cpucfg, cpumode, cpumstr;
226 1.1 matt #ifdef DEBUG
227 1.1 matt uint32_t loaddr, hiaddr;
228 1.1 matt #endif
229 1.1 matt
230 1.21.2.1 uebayasi gt_write(gt, GTPCI_CA(0), PCI_ID_REG);
231 1.21.2.1 uebayasi gt->sc_model = PCI_PRODUCT(gt_read(gt, GTPCI_CD(0)));
232 1.21.2.1 uebayasi gt_write(gt, GTPCI_CA(0), PCI_CLASS_REG);
233 1.21.2.1 uebayasi gt->sc_rev = PCI_REVISION(gt_read(gt, GTPCI_CD(0)));
234 1.21.2.1 uebayasi
235 1.21.2.1 uebayasi aprint_naive("\n");
236 1.21.2.1 uebayasi switch (gt->sc_model) {
237 1.21.2.1 uebayasi case MARVELL_DISCOVERY:
238 1.21.2.1 uebayasi aprint_normal(": GT-6426x%c Discovery\n",
239 1.21.2.1 uebayasi (gt->sc_rev == MARVELL_DISCOVERY_REVA) ? 'A' : 'B');
240 1.21.2.1 uebayasi break;
241 1.21.2.1 uebayasi case MARVELL_DISCOVERY_II:
242 1.21.2.1 uebayasi aprint_normal(": MV6436x Discovery II\n");
243 1.21.2.1 uebayasi break;
244 1.21.2.1 uebayasi
245 1.21.2.1 uebayasi #if 0
246 1.21.2.1 uebayasi case MARVELL_DISCOVERY_III:
247 1.21.2.1 uebayasi case MARVELL_DISCOVERY_LT:
248 1.21.2.1 uebayasi case MARVELL_DISCOVERY_V:
249 1.21.2.1 uebayasi case MARVELL_DISCOVERY_VI:
250 1.21.2.1 uebayasi #endif
251 1.21.2.1 uebayasi
252 1.21.2.1 uebayasi default:
253 1.21.2.1 uebayasi aprint_normal(": type unknown\n"); break;
254 1.21.2.1 uebayasi }
255 1.1 matt
256 1.3 matt cpumode = gt_read(gt, GT_CPU_Mode);
257 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev,
258 1.21.2.1 uebayasi "id %d", GT_CPUMode_MultiGTID_GET(cpumode));
259 1.1 matt if (cpumode & GT_CPUMode_MultiGT)
260 1.3 matt aprint_normal (" (multi)");
261 1.1 matt switch (GT_CPUMode_CPUType_GET(cpumode)) {
262 1.3 matt case 4: aprint_normal(", 60x bus"); break;
263 1.3 matt case 5: aprint_normal(", MPX bus"); break;
264 1.21.2.1 uebayasi
265 1.21.2.1 uebayasi default:
266 1.21.2.1 uebayasi aprint_normal(", %#x(?) bus", GT_CPUMode_CPUType_GET(cpumode));
267 1.21.2.1 uebayasi break;
268 1.1 matt }
269 1.1 matt
270 1.3 matt cpumstr = gt_read(gt, GT_CPU_Master_Ctl);
271 1.1 matt switch (cpumstr & (GT_CPUMstrCtl_CleanBlock|GT_CPUMstrCtl_FlushBlock)) {
272 1.1 matt case 0: break;
273 1.3 matt case GT_CPUMstrCtl_CleanBlock: aprint_normal(", snoop=clean"); break;
274 1.3 matt case GT_CPUMstrCtl_FlushBlock: aprint_normal(", snoop=flush"); break;
275 1.1 matt case GT_CPUMstrCtl_CleanBlock|GT_CPUMstrCtl_FlushBlock:
276 1.3 matt aprint_normal(", snoop=clean&flush"); break;
277 1.1 matt }
278 1.3 matt aprint_normal(" wdog=%#x,%#x\n",
279 1.21.2.1 uebayasi gt_read(gt, GT_WDOG_Config),
280 1.21.2.1 uebayasi gt_read(gt, GT_WDOG_Value));
281 1.1 matt
282 1.1 matt #if DEBUG
283 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS0_Low_Decode));
284 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS0_High_Decode));
285 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " scs[0]=%#10x-%#10x\n",
286 1.21.2.1 uebayasi loaddr, hiaddr);
287 1.3 matt
288 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS1_Low_Decode));
289 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS1_High_Decode));
290 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " scs[1]=%#10x-%#10x\n",
291 1.21.2.1 uebayasi loaddr, hiaddr);
292 1.3 matt
293 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS2_Low_Decode));
294 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS2_High_Decode));
295 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " scs[2]=%#10x-%#10x\n",
296 1.21.2.1 uebayasi loaddr, hiaddr);
297 1.3 matt
298 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS3_Low_Decode));
299 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS3_High_Decode));
300 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " scs[3]=%#10x-%#10x\n",
301 1.21.2.1 uebayasi loaddr, hiaddr);
302 1.3 matt
303 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS0_Low_Decode));
304 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS0_High_Decode));
305 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " cs[0]=%#10x-%#10x\n",
306 1.21.2.1 uebayasi loaddr, hiaddr);
307 1.3 matt
308 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS1_Low_Decode));
309 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS1_High_Decode));
310 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " cs[1]=%#10x-%#10x\n",
311 1.21.2.1 uebayasi loaddr, hiaddr);
312 1.3 matt
313 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS2_Low_Decode));
314 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS2_High_Decode));
315 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " cs[2]=%#10x-%#10x\n",
316 1.21.2.1 uebayasi loaddr, hiaddr);
317 1.3 matt
318 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS3_Low_Decode));
319 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS3_High_Decode));
320 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " cs[3]=%#10x-%#10x\n",
321 1.21.2.1 uebayasi loaddr, hiaddr);
322 1.3 matt
323 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_BootCS_Low_Decode));
324 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_BootCS_High_Decode));
325 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " bootcs=%#10x-%#10x\n",
326 1.21.2.1 uebayasi loaddr, hiaddr);
327 1.3 matt
328 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_IO_Low_Decode));
329 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_IO_High_Decode));
330 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " pci0io=%#10x-%#10x ",
331 1.21.2.1 uebayasi loaddr, hiaddr);
332 1.3 matt
333 1.3 matt loaddr = gt_read(gt, GT_PCI0_IO_Remap);
334 1.3 matt aprint_normal("remap=%#010x\n", loaddr);
335 1.3 matt
336 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem0_Low_Decode));
337 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem0_High_Decode));
338 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " pci0mem[0]=%#10x-%#10x ",
339 1.21.2.1 uebayasi loaddr, hiaddr);
340 1.3 matt
341 1.3 matt loaddr = gt_read(gt, GT_PCI0_Mem0_Remap_Low);
342 1.3 matt hiaddr = gt_read(gt, GT_PCI0_Mem0_Remap_High);
343 1.3 matt aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
344 1.3 matt
345 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem1_Low_Decode));
346 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem1_High_Decode));
347 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " pci0mem[1]=%#10x-%#10x ",
348 1.21.2.1 uebayasi loaddr, hiaddr);
349 1.3 matt
350 1.3 matt loaddr = gt_read(gt, GT_PCI0_Mem1_Remap_Low);
351 1.3 matt hiaddr = gt_read(gt, GT_PCI0_Mem1_Remap_High);
352 1.3 matt aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
353 1.3 matt
354 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem2_Low_Decode));
355 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem2_High_Decode));
356 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " pci0mem[2]=%#10x-%#10x ",
357 1.21.2.1 uebayasi loaddr, hiaddr);
358 1.3 matt
359 1.3 matt loaddr = gt_read(gt, GT_PCI0_Mem2_Remap_Low);
360 1.3 matt hiaddr = gt_read(gt, GT_PCI0_Mem2_Remap_High);
361 1.3 matt aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
362 1.3 matt
363 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem3_Low_Decode));
364 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem3_High_Decode));
365 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " pci0mem[3]=%#10x-%#10x ",
366 1.21.2.1 uebayasi loaddr, hiaddr);
367 1.3 matt
368 1.3 matt loaddr = gt_read(gt, GT_PCI0_Mem3_Remap_Low);
369 1.3 matt hiaddr = gt_read(gt, GT_PCI0_Mem3_Remap_High);
370 1.3 matt aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
371 1.3 matt
372 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_IO_Low_Decode));
373 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_IO_High_Decode));
374 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " pci1io=%#10x-%#10x ",
375 1.21.2.1 uebayasi loaddr, hiaddr);
376 1.3 matt
377 1.3 matt loaddr = gt_read(gt, GT_PCI1_IO_Remap);
378 1.3 matt aprint_normal("remap=%#010x\n", loaddr);
379 1.3 matt
380 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem0_Low_Decode));
381 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem0_High_Decode));
382 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " pci1mem[0]=%#10x-%#10x ",
383 1.21.2.1 uebayasi loaddr, hiaddr);
384 1.3 matt
385 1.3 matt loaddr = gt_read(gt, GT_PCI1_Mem0_Remap_Low);
386 1.3 matt hiaddr = gt_read(gt, GT_PCI1_Mem0_Remap_High);
387 1.3 matt aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
388 1.3 matt
389 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem1_Low_Decode));
390 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem1_High_Decode));
391 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " pci1mem[1]=%#10x-%#10x ",
392 1.21.2.1 uebayasi loaddr, hiaddr);
393 1.3 matt
394 1.3 matt loaddr = gt_read(gt, GT_PCI1_Mem1_Remap_Low);
395 1.3 matt hiaddr = gt_read(gt, GT_PCI1_Mem1_Remap_High);
396 1.3 matt aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
397 1.3 matt
398 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem2_Low_Decode));
399 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem2_High_Decode));
400 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " pci1mem[2]=%#10x-%#10x ",
401 1.21.2.1 uebayasi loaddr, hiaddr);
402 1.3 matt
403 1.3 matt loaddr = gt_read(gt, GT_PCI1_Mem2_Remap_Low);
404 1.3 matt hiaddr = gt_read(gt, GT_PCI1_Mem2_Remap_High);
405 1.3 matt aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
406 1.3 matt
407 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem3_Low_Decode));
408 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem3_High_Decode));
409 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " pci1mem[3]=%#10x-%#10x ",
410 1.21.2.1 uebayasi loaddr, hiaddr);
411 1.3 matt
412 1.3 matt loaddr = gt_read(gt, GT_PCI1_Mem3_Remap_Low);
413 1.3 matt hiaddr = gt_read(gt, GT_PCI1_Mem3_Remap_High);
414 1.3 matt aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
415 1.1 matt
416 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_Internal_Decode));
417 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " internal=%#10x-%#10x\n",
418 1.21.2.1 uebayasi loaddr, loaddr + 256 * 1024);
419 1.1 matt
420 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_CPU0_Low_Decode));
421 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CPU0_High_Decode));
422 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " cpu0=%#10x-%#10x\n",
423 1.21.2.1 uebayasi loaddr, hiaddr);
424 1.1 matt
425 1.3 matt loaddr = GT_LowAddr_GET(gt_read(gt, GT_CPU1_Low_Decode));
426 1.3 matt hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CPU1_High_Decode));
427 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, " cpu1=%#10x-%#10x",
428 1.21.2.1 uebayasi loaddr, hiaddr);
429 1.1 matt #endif
430 1.1 matt
431 1.21.2.1 uebayasi aprint_normal("%s:", device_xname(gt->sc_dev));
432 1.1 matt
433 1.3 matt cpucfg = gt_read(gt, GT_CPU_Cfg);
434 1.1 matt cpucfg |= GT_CPUCfg_ConfSBDis; /* per errata #46 */
435 1.1 matt cpucfg |= GT_CPUCfg_AACKDelay; /* per restriction #18 */
436 1.3 matt gt_write(gt, GT_CPU_Cfg, cpucfg);
437 1.1 matt if (cpucfg & GT_CPUCfg_Pipeline)
438 1.3 matt aprint_normal(" pipeline");
439 1.1 matt if (cpucfg & GT_CPUCfg_AACKDelay)
440 1.3 matt aprint_normal(" aack-delay");
441 1.1 matt if (cpucfg & GT_CPUCfg_RdOOO)
442 1.3 matt aprint_normal(" read-ooo");
443 1.1 matt if (cpucfg & GT_CPUCfg_IOSBDis)
444 1.3 matt aprint_normal(" io-sb-dis");
445 1.1 matt if (cpucfg & GT_CPUCfg_ConfSBDis)
446 1.3 matt aprint_normal(" conf-sb-dis");
447 1.1 matt if (cpucfg & GT_CPUCfg_ClkSync)
448 1.3 matt aprint_normal(" clk-sync");
449 1.3 matt aprint_normal("\n");
450 1.1 matt
451 1.21.2.1 uebayasi #ifdef GT_WATCHDOG
452 1.1 matt gt_watchdog_init(gt);
453 1.21.2.1 uebayasi #endif
454 1.1 matt
455 1.21.2.1 uebayasi #ifdef GT_DEVBUS
456 1.21.2.1 uebayasi gt_devbus_intr_enb(gt);
457 1.21.2.1 uebayasi #endif
458 1.1 matt #ifdef GT_ECC
459 1.1 matt gt_ecc_intr_enb(gt);
460 1.1 matt #endif
461 1.21.2.1 uebayasi #if NGTMPSC > 0
462 1.21.2.1 uebayasi gt_sdma_intr_enb(gt);
463 1.21.2.1 uebayasi #endif
464 1.21.2.1 uebayasi #ifdef GT_COMM
465 1.1 matt gt_comm_intr_enb(gt);
466 1.21.2.1 uebayasi #endif
467 1.21.2.1 uebayasi
468 1.21.2.1 uebayasi gt_attach_peripherals(gt);
469 1.1 matt
470 1.21.2.1 uebayasi #ifdef GT_WATCHDOG
471 1.1 matt gt_watchdog_service();
472 1.21.2.1 uebayasi gt_watchdog_enable(gt);
473 1.21.2.1 uebayasi #endif
474 1.1 matt }
475 1.1 matt
476 1.21.2.1 uebayasi
477 1.21.2.1 uebayasi #ifdef GT_DEVBUS
478 1.21.2.1 uebayasi static int
479 1.21.2.1 uebayasi gt_devbus_intr(void *arg)
480 1.1 matt {
481 1.21.2.1 uebayasi struct gt_softc *gt = (struct gt_softc *)arg;
482 1.21.2.1 uebayasi u_int32_t cause;
483 1.21.2.1 uebayasi u_int32_t addr;
484 1.1 matt
485 1.21.2.1 uebayasi cause = gt_read(gt, GT_DEVBUS_ICAUSE);
486 1.21.2.1 uebayasi addr = gt_read(gt, GT_DEVBUS_ERR_ADDR);
487 1.21.2.1 uebayasi gt_write(gt, GT_DEVBUS_ICAUSE, 0); /* clear intr */
488 1.21.2.1 uebayasi
489 1.21.2.1 uebayasi if (cause & GT_DEVBUS_DBurstErr) {
490 1.21.2.1 uebayasi aprint_error_dev(gt->sc_dev,
491 1.21.2.1 uebayasi "Device Bus error: burst violation");
492 1.21.2.1 uebayasi if ((cause & GT_DEVBUS_Sel) == 0)
493 1.21.2.1 uebayasi aprint_error(", addr %#x", addr);
494 1.21.2.1 uebayasi aprint_error("\n");
495 1.21.2.1 uebayasi }
496 1.21.2.1 uebayasi if (cause & GT_DEVBUS_DRdyErr) {
497 1.21.2.1 uebayasi aprint_error_dev(gt->sc_dev,
498 1.21.2.1 uebayasi "Device Bus error: ready timer expired");
499 1.21.2.1 uebayasi if ((cause & GT_DEVBUS_Sel) != 0)
500 1.21.2.1 uebayasi aprint_error(", addr %#x\n", addr);
501 1.21.2.1 uebayasi aprint_error("\n");
502 1.21.2.1 uebayasi }
503 1.21.2.1 uebayasi
504 1.21.2.1 uebayasi return cause != 0;
505 1.1 matt }
506 1.1 matt
507 1.21.2.1 uebayasi /*
508 1.21.2.1 uebayasi * gt_devbus_intr_enb - enable GT-64260 Device Bus interrupts
509 1.21.2.1 uebayasi */
510 1.21.2.1 uebayasi static void
511 1.21.2.1 uebayasi gt_devbus_intr_enb(struct gt_softc *gt)
512 1.1 matt {
513 1.21.2.1 uebayasi gt_write(gt, GT_DEVBUS_IMASK,
514 1.21.2.1 uebayasi GT_DEVBUS_DBurstErr|GT_DEVBUS_DRdyErr);
515 1.21.2.1 uebayasi (void)gt_read(gt, GT_DEVBUS_ERR_ADDR); /* clear addr */
516 1.21.2.1 uebayasi gt_write(gt, GT_DEVBUS_ICAUSE, 0); /* clear intr */
517 1.1 matt
518 1.21.2.1 uebayasi (void)marvell_intr_establish(IRQ_DEV, IPL_VM, gt_devbus_intr, gt);
519 1.21.2.1 uebayasi }
520 1.21.2.1 uebayasi #endif /* GT_DEVBUS */
521 1.1 matt
522 1.21.2.1 uebayasi #ifdef GT_ECC
523 1.21.2.1 uebayasi const static char *gt_ecc_intr_str[4] = {
524 1.21.2.1 uebayasi "(none)",
525 1.21.2.1 uebayasi "single bit",
526 1.21.2.1 uebayasi "double bit",
527 1.21.2.1 uebayasi "(reserved)"
528 1.21.2.1 uebayasi };
529 1.21.2.1 uebayasi
530 1.21.2.1 uebayasi static int
531 1.21.2.1 uebayasi gt_ecc_intr(void *arg)
532 1.21.2.1 uebayasi {
533 1.21.2.1 uebayasi struct gt_softc *gt = (struct gt_softc *)arg;
534 1.21.2.1 uebayasi uint32_t addr, dlo, dhi, rec, calc, count;
535 1.21.2.1 uebayasi int err;
536 1.21.2.1 uebayasi
537 1.21.2.1 uebayasi count = gt_read(gt, GT_ECC_Count);
538 1.21.2.1 uebayasi dlo = gt_read(gt, GT_ECC_Data_Lo);
539 1.21.2.1 uebayasi dhi = gt_read(gt, GT_ECC_Data_Hi);
540 1.21.2.1 uebayasi rec = gt_read(gt, GT_ECC_Rec);
541 1.21.2.1 uebayasi calc = gt_read(gt, GT_ECC_Calc);
542 1.21.2.1 uebayasi addr = gt_read(gt, GT_ECC_Addr); /* read last! */
543 1.21.2.1 uebayasi gt_write(gt, GT_ECC_Addr, 0); /* clear intr */
544 1.21.2.1 uebayasi
545 1.21.2.1 uebayasi err = addr & 0x3;
546 1.21.2.1 uebayasi
547 1.21.2.1 uebayasi aprint_error_dev(gt->sc_dev,
548 1.21.2.1 uebayasi "ECC error: %s: addr %#x data %#x.%#x rec %#x calc %#x cnt %#x\n",
549 1.21.2.1 uebayasi gt_ecc_intr_str[err], addr, dhi, dlo, rec, calc, count);
550 1.21.2.1 uebayasi
551 1.21.2.1 uebayasi if (err == 2)
552 1.21.2.1 uebayasi panic("ecc");
553 1.1 matt
554 1.21.2.1 uebayasi return err == 1;
555 1.1 matt }
556 1.1 matt
557 1.21.2.1 uebayasi /*
558 1.21.2.1 uebayasi * gt_ecc_intr_enb - enable GT-64260 ECC interrupts
559 1.21.2.1 uebayasi */
560 1.21.2.1 uebayasi static void
561 1.21.2.1 uebayasi gt_ecc_intr_enb(struct gt_softc *gt)
562 1.1 matt {
563 1.21.2.1 uebayasi uint32_t ctl;
564 1.21.2.1 uebayasi
565 1.21.2.1 uebayasi ctl = gt_read(gt, GT_ECC_Ctl);
566 1.21.2.1 uebayasi ctl |= 1 << 16; /* XXX 1-bit threshold == 1 */
567 1.21.2.1 uebayasi gt_write(gt, GT_ECC_Ctl, ctl);
568 1.21.2.1 uebayasi (void)gt_read(gt, GT_ECC_Data_Lo);
569 1.21.2.1 uebayasi (void)gt_read(gt, GT_ECC_Data_Hi);
570 1.21.2.1 uebayasi (void)gt_read(gt, GT_ECC_Rec);
571 1.21.2.1 uebayasi (void)gt_read(gt, GT_ECC_Calc);
572 1.21.2.1 uebayasi (void)gt_read(gt, GT_ECC_Addr); /* read last! */
573 1.21.2.1 uebayasi gt_write(gt, GT_ECC_Addr, 0); /* clear intr */
574 1.21.2.1 uebayasi
575 1.21.2.1 uebayasi (void)marvell_intr_establish(IRQ_ECC, IPL_VM, gt_ecc_intr, gt);
576 1.1 matt }
577 1.21.2.1 uebayasi #endif /* GT_ECC */
578 1.1 matt
579 1.21.2.1 uebayasi #if NGTMPSC > 0
580 1.21.2.1 uebayasi /*
581 1.21.2.1 uebayasi * gt_sdma_intr_enb - enable GT-64260 SDMA interrupts
582 1.21.2.1 uebayasi */
583 1.21.2.1 uebayasi static void
584 1.21.2.1 uebayasi gt_sdma_intr_enb(struct gt_softc *gt)
585 1.1 matt {
586 1.1 matt
587 1.21.2.1 uebayasi (void)marvell_intr_establish(IRQ_SDMA, IPL_SERIAL, gtmpsc_intr, gt);
588 1.1 matt }
589 1.1 matt #endif
590 1.1 matt
591 1.21.2.1 uebayasi #ifdef GT_COMM
592 1.1 matt /*
593 1.1 matt * unknown board, enable everything
594 1.1 matt */
595 1.21.2.1 uebayasi # define GT_CommUnitIntr_DFLT \
596 1.21.2.1 uebayasi GT_CommUnitIntr_S0 |\
597 1.21.2.1 uebayasi GT_CommUnitIntr_S1 |\
598 1.21.2.1 uebayasi GT_CommUnitIntr_E0 |\
599 1.21.2.1 uebayasi GT_CommUnitIntr_E1 |\
600 1.21.2.1 uebayasi GT_CommUnitIntr_E2
601 1.1 matt
602 1.1 matt static const char * const gt_comm_subunit_name[8] = {
603 1.1 matt "ethernet 0",
604 1.1 matt "ethernet 1",
605 1.1 matt "ethernet 2",
606 1.1 matt "(reserved)",
607 1.1 matt "MPSC 0",
608 1.1 matt "MPSC 1",
609 1.1 matt "(reserved)",
610 1.1 matt "(sel)",
611 1.1 matt };
612 1.1 matt
613 1.1 matt static int
614 1.1 matt gt_comm_intr(void *arg)
615 1.1 matt {
616 1.1 matt struct gt_softc *gt = (struct gt_softc *)arg;
617 1.21.2.1 uebayasi uint32_t cause, addr;
618 1.1 matt unsigned int mask;
619 1.1 matt int i;
620 1.1 matt
621 1.3 matt cause = gt_read(gt, GT_CommUnitIntr_Cause);
622 1.3 matt gt_write(gt, GT_CommUnitIntr_Cause, ~cause);
623 1.3 matt addr = gt_read(gt, GT_CommUnitIntr_ErrAddr);
624 1.1 matt
625 1.21.2.1 uebayasi aprint_error_dev(gt->sc_dev,
626 1.21.2.1 uebayasi "Communications Unit Controller interrupt, cause %#x addr %#x\n",
627 1.21.2.1 uebayasi cause, addr);
628 1.1 matt
629 1.1 matt cause &= GT_CommUnitIntr_DFLT;
630 1.1 matt if (cause == 0)
631 1.1 matt return 0;
632 1.3 matt
633 1.1 matt mask = 0x7;
634 1.1 matt for (i=0; i<7; i++) {
635 1.1 matt if (cause & mask) {
636 1.21.2.1 uebayasi printf("%s: Comm Unit %s:", device_xname(gt->sc_dev),
637 1.1 matt gt_comm_subunit_name[i]);
638 1.9 perry if (cause & 1)
639 1.1 matt printf(" AddrMiss");
640 1.9 perry if (cause & 2)
641 1.1 matt printf(" AccProt");
642 1.9 perry if (cause & 4)
643 1.1 matt printf(" WrProt");
644 1.1 matt printf("\n");
645 1.1 matt }
646 1.1 matt cause >>= 4;
647 1.1 matt }
648 1.1 matt return 1;
649 1.1 matt }
650 1.1 matt
651 1.1 matt /*
652 1.1 matt * gt_comm_intr_init - enable GT-64260 Comm Unit interrupts
653 1.1 matt */
654 1.1 matt static void
655 1.1 matt gt_comm_intr_enb(struct gt_softc *gt)
656 1.1 matt {
657 1.21.2.1 uebayasi uint32_t cause;
658 1.1 matt
659 1.3 matt cause = gt_read(gt, GT_CommUnitIntr_Cause);
660 1.1 matt if (cause)
661 1.3 matt gt_write(gt, GT_CommUnitIntr_Cause, ~cause);
662 1.3 matt gt_write(gt, GT_CommUnitIntr_Mask, GT_CommUnitIntr_DFLT);
663 1.3 matt (void)gt_read(gt, GT_CommUnitIntr_ErrAddr);
664 1.1 matt
665 1.21.2.1 uebayasi (void)marvell_intr_establish(IRQ_COMM, IPL_VM, gt_comm_intr, gt);
666 1.1 matt }
667 1.21.2.1 uebayasi #endif /* GT_COMM */
668 1.1 matt
669 1.1 matt
670 1.21.2.1 uebayasi #ifdef GT_WATCHDOG
671 1.1 matt #ifndef GT_MPP_WATCHDOG
672 1.21.2.1 uebayasi static void
673 1.3 matt gt_watchdog_init(struct gt_softc *gt)
674 1.1 matt {
675 1.1 matt u_int32_t r;
676 1.1 matt
677 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, "watchdog");
678 1.1 matt
679 1.1 matt /*
680 1.1 matt * handle case where firmware started watchdog
681 1.1 matt */
682 1.3 matt r = gt_read(gt, GT_WDOG_Config);
683 1.21.2.1 uebayasi aprint_normal(" status %#x,%#x:", r, gt_read(gt, GT_WDOG_Value));
684 1.1 matt if ((r & 0x80000000) != 0) {
685 1.3 matt gt_watchdog_sc = gt; /* enabled */
686 1.1 matt gt_watchdog_state = 1;
687 1.21.2.1 uebayasi aprint_normal(" firmware-enabled\n");
688 1.21.2.1 uebayasi gt_watchdog_disable(gt);
689 1.21.2.1 uebayasi } else
690 1.21.2.1 uebayasi aprint_normal(" firmware-disabled\n");
691 1.1 matt }
692 1.1 matt
693 1.21.2.1 uebayasi #elif GT_MPP_WATCHDOG == 0
694 1.1 matt
695 1.21.2.1 uebayasi static void
696 1.3 matt gt_watchdog_init(struct gt_softc *gt)
697 1.1 matt {
698 1.1 matt
699 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, "watchdog not configured\n");
700 1.21.2.1 uebayasi return;
701 1.21.2.1 uebayasi }
702 1.1 matt
703 1.21.2.1 uebayasi #else /* GT_MPP_WATCHDOG > 0 */
704 1.1 matt
705 1.21.2.1 uebayasi static void
706 1.21.2.1 uebayasi gt_watchdog_init(struct gt_softc *gt)
707 1.21.2.1 uebayasi {
708 1.21.2.1 uebayasi u_int32_t mpp_watchdog = GT_MPP_WATCHDOG; /* from config */
709 1.21.2.1 uebayasi u_int32_t cfgbits, mppbits, mppmask, regoff, r;
710 1.1 matt
711 1.21.2.1 uebayasi mppmask = 0;
712 1.21.2.1 uebayasi
713 1.21.2.1 uebayasi aprint_normal_dev(gt->sc_dev, "watchdog");
714 1.1 matt
715 1.1 matt /*
716 1.1 matt * if firmware started watchdog, we disable and start
717 1.1 matt * from scratch to get it in a known state.
718 1.1 matt *
719 1.1 matt * on GT-64260A we always see 0xffffffff
720 1.1 matt * in both the GT_WDOG_Config_Enb and GT_WDOG_Value regsiters.
721 1.1 matt */
722 1.3 matt r = gt_read(gt, GT_WDOG_Config);
723 1.1 matt if (r != ~0) {
724 1.1 matt if ((r & GT_WDOG_Config_Enb) != 0) {
725 1.3 matt gt_write(gt, GT_WDOG_Config,
726 1.21.2.1 uebayasi GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT);
727 1.3 matt gt_write(gt, GT_WDOG_Config,
728 1.21.2.1 uebayasi GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT);
729 1.1 matt }
730 1.1 matt }
731 1.1 matt
732 1.1 matt /*
733 1.1 matt * "the watchdog timer can be activated only after
734 1.1 matt * configuring two MPP pins to act as WDE and WDNMI"
735 1.1 matt */
736 1.1 matt mppbits = 0;
737 1.1 matt cfgbits = 0x3;
738 1.1 matt for (regoff = GT_MPP_Control0; regoff <= GT_MPP_Control3; regoff += 4) {
739 1.1 matt if ((mpp_watchdog & cfgbits) == cfgbits) {
740 1.1 matt mppbits = 0x99;
741 1.1 matt mppmask = 0xff;
742 1.1 matt break;
743 1.1 matt }
744 1.1 matt cfgbits <<= 2;
745 1.1 matt if ((mpp_watchdog & cfgbits) == cfgbits) {
746 1.1 matt mppbits = 0x9900;
747 1.1 matt mppmask = 0xff00;
748 1.1 matt break;
749 1.1 matt }
750 1.1 matt cfgbits <<= 6; /* skip unqualified bits */
751 1.1 matt }
752 1.1 matt if (mppbits == 0) {
753 1.21.2.1 uebayasi aprint_error(" config error\n");
754 1.1 matt return;
755 1.1 matt }
756 1.1 matt
757 1.3 matt r = gt_read(gt, regoff);
758 1.1 matt r &= ~mppmask;
759 1.1 matt r |= mppbits;
760 1.3 matt gt_write(gt, regoff, r);
761 1.21.2.1 uebayasi aprint_normal(" mpp %#x %#x", regoff, mppbits);
762 1.1 matt
763 1.3 matt gt_write(gt, GT_WDOG_Value, GT_WDOG_NMI_DFLT);
764 1.1 matt
765 1.21.2.1 uebayasi gt_write(gt, GT_WDOG_Config, GT_WDOG_Config_Ctl1a|GT_WDOG_Preset_DFLT);
766 1.21.2.1 uebayasi gt_write(gt, GT_WDOG_Config, GT_WDOG_Config_Ctl1b|GT_WDOG_Preset_DFLT);
767 1.1 matt
768 1.3 matt r = gt_read(gt, GT_WDOG_Config),
769 1.21.2.1 uebayasi aprint_normal(" status %#x,%#x: %s\n",
770 1.21.2.1 uebayasi r, gt_read(gt, GT_WDOG_Value),
771 1.21.2.1 uebayasi ((r & GT_WDOG_Config_Enb) != 0) ? "enabled" : "botch");
772 1.1 matt }
773 1.1 matt #endif /* GT_MPP_WATCHDOG */
774 1.1 matt
775 1.21.2.1 uebayasi static void
776 1.21.2.1 uebayasi gt_watchdog_enable(struct gt_softc *gt)
777 1.1 matt {
778 1.1 matt
779 1.21.2.1 uebayasi if (gt_watchdog_state == 0) {
780 1.1 matt gt_watchdog_state = 1;
781 1.1 matt
782 1.3 matt gt_write(gt, GT_WDOG_Config,
783 1.21.2.1 uebayasi GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT);
784 1.3 matt gt_write(gt, GT_WDOG_Config,
785 1.21.2.1 uebayasi GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT);
786 1.1 matt }
787 1.1 matt }
788 1.1 matt
789 1.21.2.1 uebayasi #ifndef GT_MPP_WATCHDOG
790 1.21.2.1 uebayasi static void
791 1.21.2.1 uebayasi gt_watchdog_disable(struct gt_softc *gt)
792 1.1 matt {
793 1.1 matt
794 1.21.2.1 uebayasi if (gt_watchdog_state != 0) {
795 1.1 matt gt_watchdog_state = 0;
796 1.1 matt
797 1.3 matt gt_write(gt, GT_WDOG_Config,
798 1.21.2.1 uebayasi GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT);
799 1.3 matt gt_write(gt, GT_WDOG_Config,
800 1.21.2.1 uebayasi GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT);
801 1.1 matt }
802 1.1 matt }
803 1.21.2.1 uebayasi #endif
804 1.21.2.1 uebayasi
805 1.21.2.1 uebayasi /*
806 1.21.2.1 uebayasi * XXXX: gt_watchdog_service/reset functions need mutex lock...
807 1.21.2.1 uebayasi */
808 1.1 matt
809 1.1 matt #ifdef DEBUG
810 1.1 matt int inhibit_watchdog_service = 0;
811 1.1 matt #endif
812 1.1 matt void
813 1.1 matt gt_watchdog_service(void)
814 1.1 matt {
815 1.3 matt struct gt_softc *gt = gt_watchdog_sc;
816 1.1 matt
817 1.3 matt if ((gt == NULL) || (gt_watchdog_state == 0))
818 1.1 matt return; /* not enabled */
819 1.1 matt #ifdef DEBUG
820 1.1 matt if (inhibit_watchdog_service)
821 1.1 matt return;
822 1.1 matt #endif
823 1.9 perry
824 1.21.2.1 uebayasi gt_write(gt, GT_WDOG_Config, GT_WDOG_Config_Ctl2a|GT_WDOG_Preset_DFLT);
825 1.21.2.1 uebayasi gt_write(gt, GT_WDOG_Config, GT_WDOG_Config_Ctl2b|GT_WDOG_Preset_DFLT);
826 1.1 matt }
827 1.1 matt
828 1.1 matt /*
829 1.1 matt * gt_watchdog_reset - force a watchdog reset using Preset_VAL=0
830 1.1 matt */
831 1.1 matt void
832 1.19 cegger gt_watchdog_reset(void)
833 1.1 matt {
834 1.3 matt struct gt_softc *gt = gt_watchdog_sc;
835 1.1 matt u_int32_t r;
836 1.1 matt
837 1.3 matt r = gt_read(gt, GT_WDOG_Config);
838 1.21.2.1 uebayasi gt_write(gt, GT_WDOG_Config, GT_WDOG_Config_Ctl1a);
839 1.21.2.1 uebayasi gt_write(gt, GT_WDOG_Config, GT_WDOG_Config_Ctl1b);
840 1.1 matt if ((r & GT_WDOG_Config_Enb) != 0) {
841 1.1 matt /*
842 1.1 matt * was enabled, we just toggled it off, toggle on again
843 1.1 matt */
844 1.21.2.1 uebayasi gt_write(gt, GT_WDOG_Config, GT_WDOG_Config_Ctl1a);
845 1.21.2.1 uebayasi gt_write(gt, GT_WDOG_Config, GT_WDOG_Config_Ctl1b);
846 1.1 matt }
847 1.1 matt for(;;);
848 1.1 matt }
849 1.21.2.1 uebayasi #endif
850 1.1 matt
851 1.1 matt
852 1.1 matt int
853 1.21.2.1 uebayasi marvell_winparams_by_tag(device_t dev, int tag, int *target, int *attr,
854 1.21.2.1 uebayasi uint64_t *base, uint32_t *size)
855 1.1 matt {
856 1.21.2.1 uebayasi static const struct {
857 1.21.2.1 uebayasi int tag;
858 1.21.2.1 uebayasi uint32_t attribute;
859 1.21.2.1 uebayasi uint32_t basereg;
860 1.21.2.1 uebayasi uint32_t sizereg;
861 1.21.2.1 uebayasi } tagtbl[] = {
862 1.21.2.1 uebayasi { MARVELL_TAG_SDRAM_CS0, MARVELL_ATTR_SDRAM_CS0,
863 1.21.2.1 uebayasi GT_SCS0_Low_Decode, GT_SCS0_High_Decode },
864 1.21.2.1 uebayasi { MARVELL_TAG_SDRAM_CS1, MARVELL_ATTR_SDRAM_CS1,
865 1.21.2.1 uebayasi GT_SCS1_Low_Decode, GT_SCS1_High_Decode },
866 1.21.2.1 uebayasi { MARVELL_TAG_SDRAM_CS2, MARVELL_ATTR_SDRAM_CS2,
867 1.21.2.1 uebayasi GT_SCS2_Low_Decode, GT_SCS2_High_Decode },
868 1.21.2.1 uebayasi { MARVELL_TAG_SDRAM_CS3, MARVELL_ATTR_SDRAM_CS3,
869 1.21.2.1 uebayasi GT_SCS3_Low_Decode, GT_SCS3_High_Decode },
870 1.21.2.1 uebayasi
871 1.21.2.1 uebayasi { MARVELL_TAG_UNDEFINED, 0, 0 }
872 1.21.2.1 uebayasi };
873 1.21.2.1 uebayasi struct gt_softc *sc = device_private(dev);
874 1.21.2.1 uebayasi int i;
875 1.1 matt
876 1.21.2.1 uebayasi for (i = 0; tagtbl[i].tag != MARVELL_TAG_UNDEFINED; i++)
877 1.21.2.1 uebayasi if (tag == tagtbl[i].tag)
878 1.21.2.1 uebayasi break;
879 1.21.2.1 uebayasi if (tagtbl[i].tag == MARVELL_TAG_UNDEFINED)
880 1.21.2.1 uebayasi return -1;
881 1.1 matt
882 1.21.2.1 uebayasi if (target != NULL)
883 1.21.2.1 uebayasi *target = 0;
884 1.21.2.1 uebayasi if (attr != NULL)
885 1.21.2.1 uebayasi *attr = tagtbl[i].attribute;
886 1.21.2.1 uebayasi if (base != NULL)
887 1.21.2.1 uebayasi *base = gt_read(sc, tagtbl[i].basereg) <<
888 1.21.2.1 uebayasi (sc->sc_model == MARVELL_DISCOVERY ? 20 : 16);
889 1.21.2.1 uebayasi if (size != NULL) {
890 1.21.2.1 uebayasi const uint32_t s = gt_read(sc, tagtbl[i].sizereg);
891 1.21.2.1 uebayasi
892 1.21.2.1 uebayasi if (s != 0)
893 1.21.2.1 uebayasi *size = (s + 1) <<
894 1.21.2.1 uebayasi (sc->sc_model == MARVELL_DISCOVERY ? 20 : 16);
895 1.21.2.1 uebayasi else
896 1.21.2.1 uebayasi *size = 0;
897 1.1 matt }
898 1.1 matt
899 1.21.2.1 uebayasi return 0;
900 1.6 matt }
901