source: rtems/bsps/powerpc/beatnik/marvell/gt.c @ 762fa62

5
Last change on this file since 762fa62 was 8266fb53, checked in by Sebastian Huber <sebastian.huber@…>, on 04/25/18 at 08:25:00

bsp/beatnik: Move source files to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 26.9 KB
Line 
1/*      $NetBSD: gt.c,v 1.5 2003/07/14 15:47:16 lukem Exp $     */
2
3/*
4 * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *      This product includes software developed for the NetBSD Project by
18 *      Allegro Networks, Inc., and Wasabi Systems, Inc.
19 * 4. The name of Allegro Networks, Inc. may not be used to endorse
20 *    or promote products derived from this software without specific prior
21 *    written permission.
22 * 5. The name of Wasabi Systems, Inc. may not be used to endorse
23 *    or promote products derived from this software without specific prior
24 *    written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY ALLEGRO NETWORKS, INC. AND
27 * WASABI SYSTEMS, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
28 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
29 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 * IN NO EVENT SHALL EITHER ALLEGRO NETWORKS, INC. OR WASABI SYSTEMS, INC.
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40/*
41 * gt.c -- GT system controller driver
42 */
43
44#include <sys/cdefs.h>
45__KERNEL_RCSID(0, "$NetBSD: gt.c,v 1.5 2003/07/14 15:47:16 lukem Exp $");
46
47#include "opt_marvell.h"
48
49#include <sys/param.h>
50#include <sys/types.h>
51#include <sys/cdefs.h>
52#include <sys/extent.h>
53#include <sys/device.h>
54#include <sys/kernel.h>
55#include <sys/malloc.h>
56
57#define _BUS_SPACE_PRIVATE
58#define _BUS_DMA_PRIVATE
59#include <machine/bus.h>
60
61#include <powerpc/spr.h>
62#include <powerpc/oea/hid.h>
63
64#include <dev/marvell/gtreg.h>
65#include <dev/marvell/gtintrreg.h>
66#include <dev/marvell/gtvar.h>
67#include <dev/marvell/gtethreg.h>
68
69#ifdef DEBUG
70#include <sys/systm.h>  /* for Debugger() */
71#endif
72
73#if ((GT_MPP_WATCHDOG & 0xf0f0f0f0) != 0)
74# error         /* unqualified: configuration botch! */
75#endif
76#if ((GT_MPP_WATCHDOG & GT_MPP_INTERRUPTS) != 0)
77# error         /* conflict: configuration botch! */
78#endif
79
80static void     gt_comm_intr_enb(struct gt_softc *);
81static void     gt_devbus_intr_enb(struct gt_softc *);
82#ifdef GT_ECC
83static void     gt_ecc_intr_enb(struct gt_softc *);
84#endif
85
86void gt_init_hostid (struct gt_softc *);
87void gt_init_interrupt (struct gt_softc *);
88static int gt_comm_intr (void *);
89
90void gt_watchdog_init(struct gt_softc *);
91void gt_watchdog_enable(void);
92void gt_watchdog_disable(void);
93void gt_watchdog_reset(void);
94
95extern struct cfdriver gt_cd;
96
97static int gtfound = 0;
98
99static struct gt_softc *gt_watchdog_sc = 0;
100static int gt_watchdog_state = 0;
101
102int
103gt_cfprint (void *aux, const char *pnp)
104{
105        struct gt_attach_args *ga = aux;
106
107        if (pnp) {
108                aprint_normal("%s at %s", ga->ga_name, pnp);
109        }
110
111        aprint_normal(" unit %d", ga->ga_unit);
112        return (UNCONF);
113}
114
115
116static int
117gt_cfsearch(struct device *parent, struct cfdata *cf, void *aux)
118{
119        struct gt_softc *gt = (struct gt_softc *) parent;
120        struct gt_attach_args ga;
121
122        ga.ga_name = cf->cf_name;
123        ga.ga_dmat = gt->gt_dmat;
124        ga.ga_memt = gt->gt_memt;
125        ga.ga_memh = gt->gt_memh;
126        ga.ga_unit = cf->cf_loc[GTCF_UNIT];
127
128        if (config_match(parent, cf, &ga) > 0)
129                config_attach(parent, cf, &ga, gt_cfprint);
130
131        return (0);
132}
133
134void
135gt_attach_common(struct gt_softc *gt)
136{
137        uint32_t cpucfg, cpumode, cpumstr;
138#ifdef DEBUG
139        uint32_t loaddr, hiaddr;
140#endif
141
142        gtfound = 1;
143
144        cpumode = gt_read(gt, GT_CPU_Mode);
145        aprint_normal(": id %d", GT_CPUMode_MultiGTID_GET(cpumode));
146        if (cpumode & GT_CPUMode_MultiGT)
147                aprint_normal (" (multi)");
148        switch (GT_CPUMode_CPUType_GET(cpumode)) {
149        case 4: aprint_normal(", 60x bus"); break;
150        case 5: aprint_normal(", MPX bus"); break;
151        default: aprint_normal(", %#x(?) bus", GT_CPUMode_CPUType_GET(cpumode)); break;
152        }
153
154        cpumstr = gt_read(gt, GT_CPU_Master_Ctl);
155        cpumstr &= ~(GT_CPUMstrCtl_CleanBlock|GT_CPUMstrCtl_FlushBlock);
156#if 0
157        cpumstr |= GT_CPUMstrCtl_CleanBlock|GT_CPUMstrCtl_FlushBlock;
158#endif
159        gt_write(gt, GT_CPU_Master_Ctl, cpumstr);
160
161        switch (cpumstr & (GT_CPUMstrCtl_CleanBlock|GT_CPUMstrCtl_FlushBlock)) {
162        case 0: break;
163        case GT_CPUMstrCtl_CleanBlock: aprint_normal(", snoop=clean"); break;
164        case GT_CPUMstrCtl_FlushBlock: aprint_normal(", snoop=flush"); break;
165        case GT_CPUMstrCtl_CleanBlock|GT_CPUMstrCtl_FlushBlock:
166                aprint_normal(", snoop=clean&flush"); break;
167        }
168        aprint_normal(" wdog=%#x,%#x\n",
169                gt_read(gt, GT_WDOG_Config),
170                gt_read(gt, GT_WDOG_Value));
171
172#if DEBUG
173        loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS0_Low_Decode));
174        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS0_High_Decode));
175        aprint_normal("%s:      scs[0]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
176
177        loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS1_Low_Decode));
178        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS1_High_Decode));
179        aprint_normal("%s:      scs[1]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
180
181        loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS2_Low_Decode));
182        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS2_High_Decode));
183        aprint_normal("%s:      scs[2]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
184
185        loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS3_Low_Decode));
186        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS3_High_Decode));
187        aprint_normal("%s:      scs[3]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
188
189        loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS0_Low_Decode));
190        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS0_High_Decode));
191        aprint_normal("%s:       cs[0]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
192
193        loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS1_Low_Decode));
194        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS1_High_Decode));
195        aprint_normal("%s:       cs[1]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
196
197        loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS2_Low_Decode));
198        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS2_High_Decode));
199        aprint_normal("%s:       cs[2]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
200
201        loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS3_Low_Decode));
202        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS3_High_Decode));
203        aprint_normal("%s:       cs[3]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
204
205        loaddr = GT_LowAddr_GET(gt_read(gt, GT_BootCS_Low_Decode));
206        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_BootCS_High_Decode));
207        aprint_normal("%s:      bootcs=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
208
209        loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_IO_Low_Decode));
210        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_IO_High_Decode));
211        aprint_normal("%s:      pci0io=%#10x-%#10x  ", gt->gt_dev.dv_xname, loaddr, hiaddr);
212
213        loaddr = gt_read(gt, GT_PCI0_IO_Remap);
214        aprint_normal("remap=%#010x\n", loaddr);
215
216        loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem0_Low_Decode));
217        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem0_High_Decode));
218        aprint_normal("%s:  pci0mem[0]=%#10x-%#10x  ", gt->gt_dev.dv_xname, loaddr, hiaddr);
219
220        loaddr = gt_read(gt, GT_PCI0_Mem0_Remap_Low);
221        hiaddr = gt_read(gt, GT_PCI0_Mem0_Remap_High);
222        aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
223
224        loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem1_Low_Decode));
225        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem1_High_Decode));
226        aprint_normal("%s:  pci0mem[1]=%#10x-%#10x  ", gt->gt_dev.dv_xname, loaddr, hiaddr);
227
228        loaddr = gt_read(gt, GT_PCI0_Mem1_Remap_Low);
229        hiaddr = gt_read(gt, GT_PCI0_Mem1_Remap_High);
230        aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
231
232        loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem2_Low_Decode));
233        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem2_High_Decode));
234        aprint_normal("%s:  pci0mem[2]=%#10x-%#10x  ", gt->gt_dev.dv_xname, loaddr, hiaddr);
235
236        loaddr = gt_read(gt, GT_PCI0_Mem2_Remap_Low);
237        hiaddr = gt_read(gt, GT_PCI0_Mem2_Remap_High);
238        aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
239
240        loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem3_Low_Decode));
241        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem3_High_Decode));
242        aprint_normal("%s:  pci0mem[3]=%#10x-%#10x  ", gt->gt_dev.dv_xname, loaddr, hiaddr);
243
244        loaddr = gt_read(gt, GT_PCI0_Mem3_Remap_Low);
245        hiaddr = gt_read(gt, GT_PCI0_Mem3_Remap_High);
246        aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
247
248        loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_IO_Low_Decode));
249        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_IO_High_Decode));
250        aprint_normal("%s:      pci1io=%#10x-%#10x  ", gt->gt_dev.dv_xname, loaddr, hiaddr);
251
252        loaddr = gt_read(gt, GT_PCI1_IO_Remap);
253        aprint_normal("remap=%#010x\n", loaddr);
254
255        loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem0_Low_Decode));
256        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem0_High_Decode));
257        aprint_normal("%s:  pci1mem[0]=%#10x-%#10x  ", gt->gt_dev.dv_xname, loaddr, hiaddr);
258
259        loaddr = gt_read(gt, GT_PCI1_Mem0_Remap_Low);
260        hiaddr = gt_read(gt, GT_PCI1_Mem0_Remap_High);
261        aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
262
263        loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem1_Low_Decode));
264        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem1_High_Decode));
265        aprint_normal("%s:  pci1mem[1]=%#10x-%#10x  ", gt->gt_dev.dv_xname, loaddr, hiaddr);
266
267        loaddr = gt_read(gt, GT_PCI1_Mem1_Remap_Low);
268        hiaddr = gt_read(gt, GT_PCI1_Mem1_Remap_High);
269        aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
270
271        loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem2_Low_Decode));
272        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem2_High_Decode));
273        aprint_normal("%s:  pci1mem[2]=%#10x-%#10x  ", gt->gt_dev.dv_xname, loaddr, hiaddr);
274
275        loaddr = gt_read(gt, GT_PCI1_Mem2_Remap_Low);
276        hiaddr = gt_read(gt, GT_PCI1_Mem2_Remap_High);
277        aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
278
279        loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem3_Low_Decode));
280        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem3_High_Decode));
281        aprint_normal("%s:  pci1mem[3]=%#10x-%#10x  ", gt->gt_dev.dv_xname, loaddr, hiaddr);
282
283        loaddr = gt_read(gt, GT_PCI1_Mem3_Remap_Low);
284        hiaddr = gt_read(gt, GT_PCI1_Mem3_Remap_High);
285        aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
286
287        loaddr = GT_LowAddr_GET(gt_read(gt, GT_Internal_Decode));
288        aprint_normal("%s:    internal=%#10x-%#10x\n", gt->gt_dev.dv_xname,
289                loaddr, loaddr+256*1024);
290
291        loaddr = GT_LowAddr_GET(gt_read(gt, GT_CPU0_Low_Decode));
292        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CPU0_High_Decode));
293        aprint_normal("%s:        cpu0=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
294
295        loaddr = GT_LowAddr_GET(gt_read(gt, GT_CPU1_Low_Decode));
296        hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CPU1_High_Decode));
297        aprint_normal("%s:        cpu1=%#10x-%#10x", gt->gt_dev.dv_xname, loaddr, hiaddr);
298#endif
299
300        aprint_normal("%s:", gt->gt_dev.dv_xname);
301
302        cpucfg = gt_read(gt, GT_CPU_Cfg);
303        cpucfg |= GT_CPUCfg_ConfSBDis;          /* per errata #46 */
304        cpucfg |= GT_CPUCfg_AACKDelay;          /* per restriction #18 */
305        gt_write(gt, GT_CPU_Cfg, cpucfg);
306        if (cpucfg & GT_CPUCfg_Pipeline)
307                aprint_normal(" pipeline");
308        if (cpucfg & GT_CPUCfg_AACKDelay)
309                aprint_normal(" aack-delay");
310        if (cpucfg & GT_CPUCfg_RdOOO)
311                aprint_normal(" read-ooo");
312        if (cpucfg & GT_CPUCfg_IOSBDis)
313                aprint_normal(" io-sb-dis");
314        if (cpucfg & GT_CPUCfg_ConfSBDis)
315                aprint_normal(" conf-sb-dis");
316        if (cpucfg & GT_CPUCfg_ClkSync)
317                aprint_normal(" clk-sync");
318        aprint_normal("\n");
319
320        gt_init_hostid(gt);
321
322        gt_watchdog_init(gt);
323
324        gt_init_interrupt(gt);
325
326#ifdef GT_ECC
327        gt_ecc_intr_enb(gt);
328#endif
329
330        gt_comm_intr_enb(gt);
331        gt_devbus_intr_enb(gt);
332
333        gt_watchdog_disable();
334        config_search(gt_cfsearch, &gt->gt_dev, NULL);
335        gt_watchdog_service();
336        gt_watchdog_enable();
337}
338
339void
340gt_init_hostid(struct gt_softc *gt)
341{
342
343        hostid = 1;     /* XXX: Used by i2c; needs work -- AKB */
344}
345
346void
347gt_init_interrupt(struct gt_softc *gt)
348{
349        u_int32_t mppirpts = GT_MPP_INTERRUPTS;         /* from config */
350        u_int32_t r;
351        u_int32_t mppbit;
352        u_int32_t mask;
353        u_int32_t mppsel;
354        u_int32_t regoff;
355
356        gt_write(gt, ICR_CIM_LO, 0);
357        gt_write(gt, ICR_CIM_HI, 0);
358
359        /*
360         * configure the GPP interrupts:
361         * - set the configured MPP pins in GPP mode
362         * - set the configured GPP pins to input, active low, interrupt enbl
363         */
364#ifdef DEBUG
365        printf("%s: mpp cfg ", gt->gt_dev.dv_xname);
366        for (regoff = GT_MPP_Control0; regoff <= GT_MPP_Control3; regoff += 4)
367                printf("%#x ", gt_read(gt, regoff));
368        printf(", mppirpts 0x%x\n", mppirpts);
369#endif
370        mppbit = 0x1;
371        for (regoff = GT_MPP_Control0; regoff <= GT_MPP_Control3; regoff += 4) {
372                mask = 0;
373                for (mppsel = 0xf; mppsel; mppsel <<= 4) {
374                        if (mppirpts & mppbit)
375                                mask |= mppsel;
376                        mppbit <<= 1;
377                }
378                if (mask) {
379                        r = gt_read(gt, regoff);
380                        r &= ~mask;
381                        gt_write(gt, regoff, r);
382                }
383        }
384
385        r = gt_read(gt, GT_GPP_IO_Control);
386        r &= ~mppirpts;
387        gt_write(gt, GT_GPP_IO_Control, r);
388
389        r = gt_read(gt, GT_GPP_Level_Control);
390        r |= mppirpts;
391        gt_write(gt, GT_GPP_Level_Control, r);
392
393        r = gt_read(gt, GT_GPP_Interrupt_Mask);
394        r |= mppirpts;
395        gt_write(gt, GT_GPP_Interrupt_Mask, r);
396}
397
398uint32_t
399gt_read_mpp (void)
400{
401        return gt_read((struct gt_softc *)gt_cd.cd_devs[0], GT_GPP_Value);
402}
403
404#if 0
405int
406gt_bs_extent_init(struct discovery_bus_space *bs, char *name)
407{
408        u_long start, end;
409        int i, j, error;
410
411        if (bs->bs_nregion == 0) {
412                bs->bs_extent = extent_create(name, 0xffffffffUL, 0xffffffffUL,
413                    M_DEVBUF, NULL, 0, EX_NOCOALESCE|EX_WAITOK);
414                KASSERT(bs->bs_extent != NULL);
415                return 0;
416        }
417        /*
418         * Find the top and bottoms of this bus space.
419         */
420        start = bs->bs_regions[0].br_start;
421        end = bs->bs_regions[0].br_end;
422#ifdef DEBUG
423        if (gtpci_debug > 1)
424                printf("gtpci_bs_extent_init: %s: region %d: %#lx-%#lx\n",
425                        name, 0, bs->bs_regions[0].br_start,
426                        bs->bs_regions[0].br_end);
427#endif
428        for (i = 1; i < bs->bs_nregion; i++) {
429                if (bs->bs_regions[i].br_start < start)
430                        start = bs->bs_regions[i].br_start;
431                if (bs->bs_regions[i].br_end > end)
432                        end = bs->bs_regions[i].br_end;
433#ifdef DEBUG
434                if (gtpci_debug > 1)
435                        printf("gtpci_bs_extent_init: %s: region %d:"
436                                " %#lx-%#lx\n",
437                                name, i, bs->bs_regions[i].br_start,
438                                bs->bs_regions[i].br_end);
439#endif
440        }
441        /*
442         * Now that we have the top and bottom limits of this
443         * bus space, create the extent map that will manage this
444         * space for us.
445         */
446#ifdef DEBUG
447        if (gtpci_debug > 1)
448                printf("gtpci_bs_extent_init: %s: create: %#lx-%#lx\n",
449                        name, start, end);
450#endif
451        bs->bs_extent = extent_create(name, start, end, M_DEVBUF,
452                NULL, 0, EX_NOCOALESCE|EX_WAITOK);
453        KASSERT(bs->bs_extent != NULL);
454
455        /* If there was more than one bus space region, then there
456         * might gaps in between them.  Allocate the gap so that
457         * they will not be legal addresses in the extent.
458         */
459        for (i = 0; i < bs->bs_nregion && bs->bs_nregion > 1; i++) {
460                /* Initial start is "infinity" and the inital end is
461                 * is the end of this bus region.
462                 */
463                start = ~0UL;
464                end = bs->bs_regions[i].br_end;
465                /* For each region, if it starts after this region but less
466                 * than the saved start, use its start address.  If the start
467                 * address is one past the end address, then we're done
468                 */
469                for (j = 0; j < bs->bs_nregion && start > end + 1; j++) {
470                        if (i == j)
471                                continue;
472                        if (bs->bs_regions[j].br_start > end &&
473                            bs->bs_regions[j].br_start < start)
474                                start = bs->bs_regions[j].br_start;
475                }
476                /*
477                 * If we found a gap, allocate it away.
478                 */
479                if (start != ~0UL && start != end + 1) {
480#ifdef DEBUG
481                        if (gtpci_debug > 1)
482                                printf("gtpci_bs_extent_init: %s: alloc(hole): %#lx-%#lx\n",
483                                        name, end + 1, start - 1);
484#endif
485                        error = extent_alloc_region(bs->bs_extent, end + 1,
486                                start - (end + 1), EX_NOWAIT);
487                        KASSERT(error == 0);
488                }
489        }
490        return 1;
491}
492#endif
493
494/*
495 * unknown board, enable everything
496 */
497# define GT_CommUnitIntr_DFLT   GT_CommUnitIntr_S0|GT_CommUnitIntr_S1 \
498                                |GT_CommUnitIntr_E0|GT_CommUnitIntr_E1 \
499                                |GT_CommUnitIntr_E2
500
501static const char * const gt_comm_subunit_name[8] = {
502        "ethernet 0",
503        "ethernet 1",
504        "ethernet 2",
505        "(reserved)",
506        "MPSC 0",
507        "MPSC 1",
508        "(reserved)",
509        "(sel)",
510};
511
512static int
513gt_comm_intr(void *arg)
514{
515        struct gt_softc *gt = (struct gt_softc *)arg;
516        u_int32_t cause;
517        u_int32_t addr;
518        unsigned int mask;
519        int i;
520
521        cause = gt_read(gt, GT_CommUnitIntr_Cause);
522        gt_write(gt, GT_CommUnitIntr_Cause, ~cause);
523        addr = gt_read(gt, GT_CommUnitIntr_ErrAddr);
524
525        printf("%s: Comm Unit irpt, cause %#x addr %#x\n",
526                gt->gt_dev.dv_xname, cause, addr);
527
528        cause &= GT_CommUnitIntr_DFLT;
529        if (cause == 0)
530                return 0;
531
532        mask = 0x7;
533        for (i=0; i<7; i++) {
534                if (cause & mask) {
535                        printf("%s: Comm Unit %s:", gt->gt_dev.dv_xname,
536                                gt_comm_subunit_name[i]);
537                        if (cause & 1)
538                                printf(" AddrMiss");
539                        if (cause & 2)
540                                printf(" AccProt");
541                        if (cause & 4)
542                                printf(" WrProt");
543                        printf("\n");
544                }
545                cause >>= 4;
546        }
547        return 1;
548}
549
550/*
551 * gt_comm_intr_init - enable GT-64260 Comm Unit interrupts
552 */
553static void
554gt_comm_intr_enb(struct gt_softc *gt)
555{
556        u_int32_t cause;
557
558        cause = gt_read(gt, GT_CommUnitIntr_Cause);
559        if (cause)
560                gt_write(gt, GT_CommUnitIntr_Cause, ~cause);
561        gt_write(gt, GT_CommUnitIntr_Mask, GT_CommUnitIntr_DFLT);
562        (void)gt_read(gt, GT_CommUnitIntr_ErrAddr);
563
564        intr_establish(IRQ_COMM, IST_LEVEL, IPL_GTERR, gt_comm_intr, gt);
565        printf("%s: Comm Unit irpt at %d\n", gt->gt_dev.dv_xname, IRQ_COMM);
566}
567
568#ifdef GT_ECC
569static char *gt_ecc_intr_str[4] = {
570        "(none)",
571        "single bit",
572        "double bit",
573        "(reserved)"
574};
575
576static int
577gt_ecc_intr(void *arg)
578{
579        struct gt_softc *gt = (struct gt_softc *)arg;
580        u_int32_t addr;
581        u_int32_t dlo;
582        u_int32_t dhi;
583        u_int32_t rec;
584        u_int32_t calc;
585        u_int32_t count;
586        int err;
587
588        count = gt_read(gt, GT_ECC_Count);
589        dlo   = gt_read(gt, GT_ECC_Data_Lo);
590        dhi   = gt_read(gt, GT_ECC_Data_Hi);
591        rec   = gt_read(gt, GT_ECC_Rec);
592        calc  = gt_read(gt, GT_ECC_Calc);
593        addr  = gt_read(gt, GT_ECC_Addr);       /* read last! */
594        gt_write(gt, GT_ECC_Addr, 0);           /* clear irpt */
595
596        err = addr & 0x3;
597
598        printf("%s: ECC error: %s: "
599                "addr %#x data %#x.%#x rec %#x calc %#x cnt %#x\n",
600                gt->gt_dev.dv_xname, gt_ecc_intr_str[err],
601                addr, dhi, dlo, rec, calc, count);
602
603        if (err == 2)
604                panic("ecc");
605
606        return (err == 1);
607}
608
609/*
610 * gt_ecc_intr_enb - enable GT-64260 ECC interrupts
611 */
612static void
613gt_ecc_intr_enb(struct gt_softc *gt)
614{
615        u_int32_t ctl;
616
617        ctl = gt_read(gt, GT_ECC_Ctl);
618        ctl |= 1 << 16;         /* XXX 1-bit threshold == 1 */
619        gt_write(gt, GT_ECC_Ctl, ctl);
620        (void)gt_read(gt, GT_ECC_Data_Lo);
621        (void)gt_read(gt, GT_ECC_Data_Hi);
622        (void)gt_read(gt, GT_ECC_Rec);
623        (void)gt_read(gt, GT_ECC_Calc);
624        (void)gt_read(gt, GT_ECC_Addr); /* read last! */
625        gt_write(gt, GT_ECC_Addr, 0);           /* clear irpt */
626
627        intr_establish(IRQ_ECC, IST_LEVEL, IPL_GTERR, gt_ecc_intr, gt);
628        printf("%s: ECC irpt at %d\n", gt->gt_dev.dv_xname, IRQ_ECC);
629}
630#endif  /* GT_ECC */
631
632
633#ifndef GT_MPP_WATCHDOG
634void
635gt_watchdog_init(struct gt_softc *gt)
636{
637        u_int32_t r;
638        unsigned int omsr;
639
640        omsr = extintr_disable();
641
642        printf("%s: watchdog", gt->gt_dev.dv_xname);
643
644        /*
645         * handle case where firmware started watchdog
646         */
647        r = gt_read(gt, GT_WDOG_Config);
648        printf(" status %#x,%#x:",
649                r, gt_read(gt, GT_WDOG_Value));
650        if ((r & 0x80000000) != 0) {
651                gt_watchdog_sc = gt;            /* enabled */
652                gt_watchdog_state = 1;
653                printf(" firmware-enabled\n");
654                gt_watchdog_service();
655                return;
656        } else {
657                printf(" firmware-disabled\n");
658        }
659
660        extintr_restore(omsr);
661}
662
663#else   /* GT_MPP_WATCHDOG */
664
665void
666gt_watchdog_init(struct gt_softc *gt)
667{
668        u_int32_t mpp_watchdog = GT_MPP_WATCHDOG;       /* from config */
669        u_int32_t r;
670        u_int32_t cfgbits;
671        u_int32_t mppbits;
672        u_int32_t mppmask=0;
673        u_int32_t regoff;
674        unsigned int omsr;
675
676        printf("%s: watchdog", gt->gt_dev.dv_xname);
677
678        if (mpp_watchdog == 0) {
679                printf(" not configured\n");
680                return;
681        }
682
683#if 0
684        if (afw_wdog_ctl == 1) {
685                printf(" admin disabled\n");
686                return;
687        }
688#endif
689
690        omsr = extintr_disable();
691
692        /*
693         * if firmware started watchdog, we disable and start
694         * from scratch to get it in a known state.
695         *
696         * on GT-64260A we always see 0xffffffff
697         * in both the GT_WDOG_Config_Enb and GT_WDOG_Value regsiters.
698         * Use AFW-supplied flag to determine run state.
699         */
700        r = gt_read(gt, GT_WDOG_Config);
701        if (r != ~0) {
702                if ((r & GT_WDOG_Config_Enb) != 0) {
703                        gt_write(gt, GT_WDOG_Config,
704                                (GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT));
705                        gt_write(gt, GT_WDOG_Config,
706                                (GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT));
707                }
708        } else {
709#if 0
710                if (afw_wdog_state == 1) {
711                        gt_write(gt, GT_WDOG_Config,
712                                (GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT));
713                        gt_write(gt, GT_WDOG_Config,
714                                (GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT));
715                }
716#endif
717        }
718
719        /*
720         * "the watchdog timer can be activated only after
721         * configuring two MPP pins to act as WDE and WDNMI"
722         */
723        mppbits = 0;
724        cfgbits = 0x3;
725        for (regoff = GT_MPP_Control0; regoff <= GT_MPP_Control3; regoff += 4) {
726                if ((mpp_watchdog & cfgbits) == cfgbits) {
727                        mppbits = 0x99;
728                        mppmask = 0xff;
729                        break;
730                }
731                cfgbits <<= 2;
732                if ((mpp_watchdog & cfgbits) == cfgbits) {
733                        mppbits = 0x9900;
734                        mppmask = 0xff00;
735                        break;
736                }
737                cfgbits <<= 6;  /* skip unqualified bits */
738        }
739        if (mppbits == 0) {
740                printf(" config error\n");
741                extintr_restore(omsr);
742                return;
743        }
744
745        r = gt_read(gt, regoff);
746        r &= ~mppmask;
747        r |= mppbits;
748        gt_write(gt, regoff, r);
749        printf(" mpp %#x %#x", regoff, mppbits);
750
751        gt_write(gt, GT_WDOG_Value, GT_WDOG_NMI_DFLT);
752
753        gt_write(gt, GT_WDOG_Config,
754                (GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT));
755        gt_write(gt, GT_WDOG_Config,
756                (GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT));
757
758
759        r = gt_read(gt, GT_WDOG_Config),
760        printf(" status %#x,%#x: %s",
761                r, gt_read(gt, GT_WDOG_Value),
762                ((r & GT_WDOG_Config_Enb) != 0) ? "enabled" : "botch");
763
764        if ((r & GT_WDOG_Config_Enb) != 0) {
765                register_t hid0;
766
767                gt_watchdog_sc = gt;            /* enabled */
768                gt_watchdog_state = 1;
769
770                /*
771                 * configure EMCP in HID0 in case it's not already set
772                 */
773                __asm __volatile("sync":::"memory");
774                hid0 = mfspr(SPR_HID0);
775                if ((hid0 & HID0_EMCP) == 0) {
776                        hid0 |= HID0_EMCP;
777                        __asm __volatile("sync":::"memory"); mtspr(SPR_HID0, hid0);
778                        __asm __volatile("sync":::"memory"); hid0 = mfspr(SPR_HID0);
779                        printf(", EMCP set");
780                }
781        }
782        printf("\n");
783
784        extintr_restore(omsr);
785}
786#endif  /* GT_MPP_WATCHDOG */
787
788#ifdef DEBUG
789u_int32_t hid0_print(void);
790u_int32_t
791hid0_print()
792{
793        u_int32_t hid0;
794        __asm __volatile("sync; mfspr %0,1008;" : "=r"(hid0)::"memory");
795        printf("hid0: %#x\n", hid0);
796        return hid0;
797}
798#endif
799
800void
801gt_watchdog_enable(void)
802{
803        struct gt_softc *gt;
804        unsigned int omsr;
805
806        omsr = extintr_disable();
807        gt = gt_watchdog_sc;
808        if ((gt != NULL) && (gt_watchdog_state == 0)) {
809                gt_watchdog_state = 1;
810
811                gt_write(gt, GT_WDOG_Config,
812                        (GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT));
813                gt_write(gt, GT_WDOG_Config,
814                        (GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT));
815        }
816        extintr_restore(omsr);
817}
818
819void
820gt_watchdog_disable(void)
821{
822        struct gt_softc *gt;
823        unsigned int omsr;
824
825        omsr = extintr_disable();
826        gt = gt_watchdog_sc;
827        if ((gt != NULL) && (gt_watchdog_state != 0)) {
828                gt_watchdog_state = 0;
829
830                gt_write(gt, GT_WDOG_Config,
831                        (GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT));
832                gt_write(gt, GT_WDOG_Config,
833                        (GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT));
834        }
835        extintr_restore(omsr);
836}
837
838#ifdef DEBUG
839int inhibit_watchdog_service = 0;
840#endif
841void
842gt_watchdog_service(void)
843{
844        struct gt_softc *gt = gt_watchdog_sc;
845
846        if ((gt == NULL) || (gt_watchdog_state == 0))
847                return;         /* not enabled */
848#ifdef DEBUG
849        if (inhibit_watchdog_service)
850                return;
851#endif
852       
853        gt_write(gt, GT_WDOG_Config,
854                (GT_WDOG_Config_Ctl2a | GT_WDOG_Preset_DFLT));
855        gt_write(gt, GT_WDOG_Config,
856                (GT_WDOG_Config_Ctl2b | GT_WDOG_Preset_DFLT));
857}
858
859/*
860 * gt_watchdog_reset - force a watchdog reset using Preset_VAL=0
861 */
862void
863gt_watchdog_reset()
864{
865        struct gt_softc *gt = gt_watchdog_sc;
866        u_int32_t r;
867
868        (void)extintr_disable();
869        r = gt_read(gt, GT_WDOG_Config);
870        gt_write(gt, GT_WDOG_Config, (GT_WDOG_Config_Ctl1a | 0));
871        gt_write(gt, GT_WDOG_Config, (GT_WDOG_Config_Ctl1b | 0));
872        if ((r & GT_WDOG_Config_Enb) != 0) {
873                /*
874                 * was enabled, we just toggled it off, toggle on again
875                 */
876                gt_write(gt, GT_WDOG_Config,
877                        (GT_WDOG_Config_Ctl1a | 0));
878                gt_write(gt, GT_WDOG_Config,
879                        (GT_WDOG_Config_Ctl1b | 0));
880        }
881        for(;;);
882}
883
884static int
885gt_devbus_intr(void *arg)
886{
887        struct gt_softc *gt = (struct gt_softc *)arg;
888        u_int32_t cause;
889        u_int32_t addr;
890
891        cause = gt_read(gt, GT_DEVBUS_ICAUSE);
892        addr = gt_read(gt, GT_DEVBUS_ERR_ADDR);
893        gt_write(gt, GT_DEVBUS_ICAUSE, 0);      /* clear irpt */
894
895        if (cause & GT_DEVBUS_DBurstErr) {
896                printf("%s: Device Bus error: burst violation",
897                        gt->gt_dev.dv_xname);
898                if ((cause & GT_DEVBUS_Sel) == 0)
899                        printf(", addr %#x", addr);
900                printf("\n");
901        }
902        if (cause & GT_DEVBUS_DRdyErr) {
903                printf("%s: Device Bus error: ready timer expired",
904                        gt->gt_dev.dv_xname);
905                if ((cause & GT_DEVBUS_Sel) != 0)
906                        printf(", addr %#x\n", addr);
907                printf("\n");
908        }
909
910        return (cause != 0);
911}
912
913/*
914 * gt_ecc_intr_enb - enable GT-64260 ECC interrupts
915 */
916static void
917gt_devbus_intr_enb(struct gt_softc *gt)
918{
919        gt_write(gt, GT_DEVBUS_IMASK,
920                GT_DEVBUS_DBurstErr|GT_DEVBUS_DRdyErr);
921        (void)gt_read(gt, GT_DEVBUS_ERR_ADDR);  /* clear addr */
922        gt_write(gt, GT_ECC_Addr, 0);           /* clear irpt */
923
924        intr_establish(IRQ_DEV, IST_LEVEL, IPL_GTERR, gt_devbus_intr, gt);
925        printf("%s: Device Bus Error irpt at %d\n",
926                gt->gt_dev.dv_xname, IRQ_DEV);
927}
928
929
930int
931gt_mii_read(
932        struct device *child,
933        struct device *parent,
934        int phy,
935        int reg)
936{
937        struct gt_softc * const gt = (struct gt_softc *) parent;
938        uint32_t data;
939        int count = 10000;
940
941        do {
942                DELAY(10);
943                data = gt_read(gt, ETH_ESMIR);
944        } while ((data & ETH_ESMIR_Busy) && count-- > 0);
945
946        if (count == 0) {
947                printf("%s: mii read for phy %d reg %d busied out\n",
948                        child->dv_xname, phy, reg);
949                return ETH_ESMIR_Value_GET(data);
950        }
951
952        gt_write(gt, ETH_ESMIR, ETH_ESMIR_READ(phy, reg));
953
954        count = 10000;
955        do {
956                DELAY(10);
957                data = gt_read(gt, ETH_ESMIR);
958        } while ((data & ETH_ESMIR_ReadValid) == 0 && count-- > 0);
959
960        if (count == 0)
961                printf("%s: mii read for phy %d reg %d timed out\n",
962                        child->dv_xname, phy, reg);
963#if defined(GTMIIDEBUG)
964        printf("%s: mii_read(%d, %d): %#x data %#x\n",
965                child->dv_xname, phy, reg,
966                data, ETH_ESMIR_Value_GET(data));
967#endif
968        return ETH_ESMIR_Value_GET(data);
969}
970
971void
972gt_mii_write (
973        struct device *child,
974        struct device *parent,
975        int phy, int reg,
976        int value)
977{
978        struct gt_softc * const gt = (struct gt_softc *) parent;
979        uint32_t data;
980        int count = 10000;
981
982        do {
983                DELAY(10);
984                data = gt_read(gt, ETH_ESMIR);
985        } while ((data & ETH_ESMIR_Busy) && count-- > 0);
986
987        if (count == 0) {
988                printf("%s: mii write for phy %d reg %d busied out (busy)\n",
989                        child->dv_xname, phy, reg);
990                return;
991        }
992
993        gt_write(gt, ETH_ESMIR,
994                 ETH_ESMIR_WRITE(phy, reg, value));
995
996        count = 10000;
997        do {
998                DELAY(10);
999                data = gt_read(gt, ETH_ESMIR);
1000        } while ((data & ETH_ESMIR_Busy) && count-- > 0);
1001
1002        if (count == 0)
1003                printf("%s: mii write for phy %d reg %d timed out\n",
1004                        child->dv_xname, phy, reg);
1005#if defined(GTMIIDEBUG)
1006        printf("%s: mii_write(%d, %d, %#x)\n",
1007                child->dv_xname, phy, reg, value);
1008#endif
1009}
1010
Note: See TracBrowser for help on using the repository browser.