summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/beatnik
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-25 10:25:00 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-25 10:30:30 +0200
commit8266fb53f9c1c19768314e77a91792f3f55312ab (patch)
treec815c760fbc723ca7b98c81f469a2a427637e460 /bsps/powerpc/beatnik
parentbsp/mvme3100: Move flashcfg.c to bsps (diff)
downloadrtems-8266fb53f9c1c19768314e77a91792f3f55312ab.tar.bz2
bsp/beatnik: Move source files to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'bsps/powerpc/beatnik')
-rw-r--r--bsps/powerpc/beatnik/flash/flashcfg.c182
-rw-r--r--bsps/powerpc/beatnik/marvell/discovery.c150
-rw-r--r--bsps/powerpc/beatnik/marvell/gt.c1010
-rw-r--r--bsps/powerpc/beatnik/marvell/gt_timer.c410
-rw-r--r--bsps/powerpc/beatnik/marvell/gti2c.c447
-rw-r--r--bsps/powerpc/beatnik/vme/vme_dma.c215
-rw-r--r--bsps/powerpc/beatnik/vme/vmeconfig.c303
7 files changed, 2717 insertions, 0 deletions
diff --git a/bsps/powerpc/beatnik/flash/flashcfg.c b/bsps/powerpc/beatnik/flash/flashcfg.c
new file mode 100644
index 0000000000..b5ba08f334
--- /dev/null
+++ b/bsps/powerpc/beatnik/flash/flashcfg.c
@@ -0,0 +1,182 @@
+/*
+ * Authorship
+ * ----------
+ * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
+ * created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * The 'beatnik' BSP was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+#include <bsp.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#define STATIC static
+
+#include <bsp/flashPgmPvt.h>
+
+/* MVME Board Specifica; board status reg. 2 where write-enable is controlled... */
+
+#define SYS_FLASHA_WP (1<<5)
+#define SYS_FBOOTB_WP (1<<3)
+#define SYS_FBA_WP_HDR (1<<2)
+#define SYS_FBOOTB_WP_HDR (1<<1)
+
+#define SYS_STATUS_2_REG (1)
+
+/* Forward Declarations */
+STATIC struct bankdesc *
+bankcheck(int bank, int quiet);
+
+static int
+flash_wp(int bank, int enbl);
+
+STATIC uint32_t
+read_us_timer(void);
+
+/* Global Variables */
+
+/* motload memory map */
+static struct bankdesc mvme5500Flash[] = {
+ { 0, 2 }, /* first entry gives number of entries */
+ { 0xf2000000, 0x08000000, 0x20000*2, 2, BSP_flash_vendor_intel, 0, 0, 0, },
+ { 0xff800000, 0x00800000, 0x20000*2, 2, BSP_flash_vendor_intel, 0, 0, 0, },
+};
+
+/* motload memory map */
+static struct bankdesc mvme6100Flash[] = {
+ { 0, 2 }, /* first entry gives number of entries */
+ { 0xf4000000, 0x04000000, 0x20000*2, 2, BSP_flash_vendor_intel, 0, 0, 0, },
+ { 0xf8000000, 0x04000000, 0x20000*2, 2, BSP_flash_vendor_intel, 0, 0, 0, },
+};
+
+struct flash_bsp_ops BSP_flashBspOps = {
+ bankcheck : bankcheck,
+ flash_wp : flash_wp,
+ read_us_timer: read_us_timer,
+};
+
+/* set (enbl:1), clear (enbl:0) or query (enbl:-1) write protection
+ *
+ * RETURNS 0 on success, nonzero on error.
+ */
+static int
+flash_wp(int bank, int enbl)
+{
+BSP_BoardType b;
+A8 p;
+unsigned char hwp = 0, swp;
+
+ /* validate 'bank' argument */
+ if ( !bankcheck( bank, 0 ) )
+ return -1;
+
+ switch ( (b=BSP_getBoardType()) ) {
+ default:
+ fprintf(stderr,"Unknown board type %i\n",b);
+ return -1;
+
+ case MVME5500:
+ /* bit enables both banks; no readback of jumper available */
+ p = (A8)(BSP_MV64x60_DEV1_BASE + SYS_STATUS_2_REG);
+ swp = SYS_FLASHA_WP;
+ break;
+
+ case MVME6100:
+ {
+
+ p = (A8)(BSP_MV64x60_DEV1_BASE + SYS_STATUS_2_REG);
+ if ( 0 == bank ) {
+ hwp = SYS_FBA_WP_HDR;
+ swp = SYS_FLASHA_WP;
+ } else {
+ hwp = SYS_FBOOTB_WP_HDR;
+ swp = SYS_FBOOTB_WP;
+ }
+ if ( enbl && (*p & hwp) ) {
+ fprintf(stderr,"HW write protection enabled (jumper)\n");
+ return -1;
+ }
+ }
+ break;
+ }
+ if ( -1 == enbl ) {
+ /* query */
+ return *p & (swp | hwp);
+ } else {
+ if ( enbl ) {
+ *p |= swp;
+ } else {
+ *p &= ~swp;
+ }
+ }
+ return 0;
+}
+
+/* Lookup bank description in table */
+STATIC struct bankdesc *
+bankcheck(int bank, int quiet)
+{
+struct bankdesc *b;
+ switch ( BSP_getBoardType() ) {
+ case MVME5500: b = mvme5500Flash; break;
+ case MVME6100: b = mvme6100Flash; break;
+ default:
+ fprintf(stderr,"Unknown/unsupported board type\n");
+ return 0;
+ }
+ if ( bank >= b->size || bank < 0 ) {
+ if ( !quiet )
+ fprintf(stderr,"Invalid flash bank #: %i; (too big)\n", bank);
+ return 0;
+ }
+ return b + bank + 1;
+}
+
+STATIC uint32_t read_us_timer(void)
+{
+uint32_t now, mhz;
+
+ /* we burn cycles anyways... */
+ mhz = BSP_bus_frequency/BSP_time_base_divisor/1000;
+
+ asm volatile("mftb %0":"=r"(now));
+
+ return now/mhz;
+}
diff --git a/bsps/powerpc/beatnik/marvell/discovery.c b/bsps/powerpc/beatnik/marvell/discovery.c
new file mode 100644
index 0000000000..1d84ac3a01
--- /dev/null
+++ b/bsps/powerpc/beatnik/marvell/discovery.c
@@ -0,0 +1,150 @@
+/*
+ * Acknowledgements:
+ * Valuable information was obtained from the following drivers
+ * netbsd: (C) Allegro Networks Inc; Wasabi Systems Inc.
+ * linux: (C) MontaVista, Software, Inc; Chris Zankel, Mark A. Greer.
+ * rtems: (C) Brookhaven National Laboratory; K. Feng
+ * but this implementation is original work by the author.
+ */
+
+/*
+ * Authorship
+ * ----------
+ * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
+ * created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * The 'beatnik' BSP was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+#include <rtems.h>
+#include <rtems/bspIo.h>
+#include <bsp.h>
+#include <bsp/gtreg.h>
+#include <bsp/pci.h>
+#include <stdint.h>
+
+#ifndef PCI_VENDOR_ID_MARVELL
+#define PCI_VENDOR_ID_MARVELL 0x11ab
+#endif
+
+#ifndef PCI_DEVICE_ID_MARVELL_GT64260
+#define PCI_DEVICE_ID_MARVELL_GT64260 0x6430
+#endif
+
+#ifndef PCI_DEVICE_ID_MARVELL_MV64360
+#define PCI_DEVICE_ID_MARVELL_MV64360 0x6460
+#endif
+
+#if 0
+#define MV64x60_PCI0_CONFIG_ADDR (BSP_MV64x60_BASE + 0xcf8)
+#define MV64x60_PCI0_CONFIG_DATA (BSP_MV64x60_BASE + 0xcfc)
+
+/* read from bus/slot/fn 0/0/0 */
+static unsigned long
+pci_early_config_read(int offset, int width)
+{
+ out_be32((uint32_t*) pci.pci_config_addr,
+ 0x80|(0<<8)|(PCI_DEVFN(0,0)<<16)|((offset&~3)<<24));
+ switch (width) {
+ default:
+ case 1:
+ return in_8((uint8_t*)pci.pci_config_data + (offset&3));
+ case 2:
+ return in_le16((uint16_t*)pci.pci_config_data + (offset&3));
+ case 4:
+ return in_le32((uint32_t *)pci.pci_config_data + (offset&3));
+ }
+}
+#endif
+
+DiscoveryVersion
+BSP_getDiscoveryVersion(int assertion)
+{
+static DiscoveryVersion rval = unknown;
+
+ if ( unknown ==rval ) {
+ unsigned char dc;
+ unsigned short ds;
+ /* this must work before and after the call to BSP_pciInitialize() --
+ * since the host bridge is at 0,0,0 it doesn't matter if the hosed
+ * access methods are installed or not (as a matter of fact this shouldn't
+ * matter for any device on hose 0)
+ */
+printk("config addr is %p\n", BSP_pci_configuration.pci_config_addr);
+printk("config data is %p\n", BSP_pci_configuration.pci_config_data);
+ pci_read_config_word(0,0,0,PCI_VENDOR_ID, &ds);
+ if ( PCI_VENDOR_ID_MARVELL != ds ) {
+ if ( assertion ) {
+ printk("Host bridge vendor id: 0x%04x\n",ds);
+ rtems_panic("Host bridge vendor @ pci(0,0,0) is not MARVELL");
+ }
+ else return unknown;
+ }
+ pci_read_config_word(0,0,0,PCI_DEVICE_ID, &ds);
+ pci_read_config_byte(0,0,0,PCI_REVISION_ID, &dc);
+ switch (ds) {
+ case PCI_DEVICE_ID_MARVELL_MV64360:
+ rval = MV_64360;
+ break;
+
+ case PCI_DEVICE_ID_MARVELL_GT64260:
+ switch (dc) {
+ default:
+ break;
+
+ case 0x10:
+ return (rval = GT_64260_A);
+
+ case 0x20:
+ return (rval = GT_64260_B);
+ }
+
+ default:
+ if ( assertion ) {
+ printk("Marvell device id 0x%04x, revision 0x%02x; check %s:%u\n",
+ ds, dc,
+ __FILE__,__LINE__);
+ rtems_panic("Unknown Marvell bridge or revision@ pci(0,0,0) is not MARVELL");
+ }
+ break;
+ }
+ }
+
+ return rval;
+}
diff --git a/bsps/powerpc/beatnik/marvell/gt.c b/bsps/powerpc/beatnik/marvell/gt.c
new file mode 100644
index 0000000000..c71b7cbdb3
--- /dev/null
+++ b/bsps/powerpc/beatnik/marvell/gt.c
@@ -0,0 +1,1010 @@
+/* $NetBSD: gt.c,v 1.5 2003/07/14 15:47:16 lukem Exp $ */
+
+/*
+ * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Allegro Networks, Inc., and Wasabi Systems, Inc.
+ * 4. The name of Allegro Networks, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * 5. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ALLEGRO NETWORKS, INC. AND
+ * WASABI SYSTEMS, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL EITHER ALLEGRO NETWORKS, INC. OR WASABI SYSTEMS, INC.
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * gt.c -- GT system controller driver
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: gt.c,v 1.5 2003/07/14 15:47:16 lukem Exp $");
+
+#include "opt_marvell.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/extent.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#define _BUS_SPACE_PRIVATE
+#define _BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <powerpc/spr.h>
+#include <powerpc/oea/hid.h>
+
+#include <dev/marvell/gtreg.h>
+#include <dev/marvell/gtintrreg.h>
+#include <dev/marvell/gtvar.h>
+#include <dev/marvell/gtethreg.h>
+
+#ifdef DEBUG
+#include <sys/systm.h> /* for Debugger() */
+#endif
+
+#if ((GT_MPP_WATCHDOG & 0xf0f0f0f0) != 0)
+# error /* unqualified: configuration botch! */
+#endif
+#if ((GT_MPP_WATCHDOG & GT_MPP_INTERRUPTS) != 0)
+# error /* conflict: configuration botch! */
+#endif
+
+static void gt_comm_intr_enb(struct gt_softc *);
+static void gt_devbus_intr_enb(struct gt_softc *);
+#ifdef GT_ECC
+static void gt_ecc_intr_enb(struct gt_softc *);
+#endif
+
+void gt_init_hostid (struct gt_softc *);
+void gt_init_interrupt (struct gt_softc *);
+static int gt_comm_intr (void *);
+
+void gt_watchdog_init(struct gt_softc *);
+void gt_watchdog_enable(void);
+void gt_watchdog_disable(void);
+void gt_watchdog_reset(void);
+
+extern struct cfdriver gt_cd;
+
+static int gtfound = 0;
+
+static struct gt_softc *gt_watchdog_sc = 0;
+static int gt_watchdog_state = 0;
+
+int
+gt_cfprint (void *aux, const char *pnp)
+{
+ struct gt_attach_args *ga = aux;
+
+ if (pnp) {
+ aprint_normal("%s at %s", ga->ga_name, pnp);
+ }
+
+ aprint_normal(" unit %d", ga->ga_unit);
+ return (UNCONF);
+}
+
+
+static int
+gt_cfsearch(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct gt_softc *gt = (struct gt_softc *) parent;
+ struct gt_attach_args ga;
+
+ ga.ga_name = cf->cf_name;
+ ga.ga_dmat = gt->gt_dmat;
+ ga.ga_memt = gt->gt_memt;
+ ga.ga_memh = gt->gt_memh;
+ ga.ga_unit = cf->cf_loc[GTCF_UNIT];
+
+ if (config_match(parent, cf, &ga) > 0)
+ config_attach(parent, cf, &ga, gt_cfprint);
+
+ return (0);
+}
+
+void
+gt_attach_common(struct gt_softc *gt)
+{
+ uint32_t cpucfg, cpumode, cpumstr;
+#ifdef DEBUG
+ uint32_t loaddr, hiaddr;
+#endif
+
+ gtfound = 1;
+
+ cpumode = gt_read(gt, GT_CPU_Mode);
+ aprint_normal(": id %d", GT_CPUMode_MultiGTID_GET(cpumode));
+ if (cpumode & GT_CPUMode_MultiGT)
+ aprint_normal (" (multi)");
+ switch (GT_CPUMode_CPUType_GET(cpumode)) {
+ case 4: aprint_normal(", 60x bus"); break;
+ case 5: aprint_normal(", MPX bus"); break;
+ default: aprint_normal(", %#x(?) bus", GT_CPUMode_CPUType_GET(cpumode)); break;
+ }
+
+ cpumstr = gt_read(gt, GT_CPU_Master_Ctl);
+ cpumstr &= ~(GT_CPUMstrCtl_CleanBlock|GT_CPUMstrCtl_FlushBlock);
+#if 0
+ cpumstr |= GT_CPUMstrCtl_CleanBlock|GT_CPUMstrCtl_FlushBlock;
+#endif
+ gt_write(gt, GT_CPU_Master_Ctl, cpumstr);
+
+ switch (cpumstr & (GT_CPUMstrCtl_CleanBlock|GT_CPUMstrCtl_FlushBlock)) {
+ case 0: break;
+ case GT_CPUMstrCtl_CleanBlock: aprint_normal(", snoop=clean"); break;
+ case GT_CPUMstrCtl_FlushBlock: aprint_normal(", snoop=flush"); break;
+ case GT_CPUMstrCtl_CleanBlock|GT_CPUMstrCtl_FlushBlock:
+ aprint_normal(", snoop=clean&flush"); break;
+ }
+ aprint_normal(" wdog=%#x,%#x\n",
+ gt_read(gt, GT_WDOG_Config),
+ gt_read(gt, GT_WDOG_Value));
+
+#if DEBUG
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS0_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS0_High_Decode));
+ aprint_normal("%s: scs[0]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS1_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS1_High_Decode));
+ aprint_normal("%s: scs[1]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS2_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS2_High_Decode));
+ aprint_normal("%s: scs[2]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_SCS3_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_SCS3_High_Decode));
+ aprint_normal("%s: scs[3]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS0_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS0_High_Decode));
+ aprint_normal("%s: cs[0]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS1_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS1_High_Decode));
+ aprint_normal("%s: cs[1]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS2_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS2_High_Decode));
+ aprint_normal("%s: cs[2]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_CS3_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CS3_High_Decode));
+ aprint_normal("%s: cs[3]=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_BootCS_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_BootCS_High_Decode));
+ aprint_normal("%s: bootcs=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_IO_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_IO_High_Decode));
+ aprint_normal("%s: pci0io=%#10x-%#10x ", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = gt_read(gt, GT_PCI0_IO_Remap);
+ aprint_normal("remap=%#010x\n", loaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem0_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem0_High_Decode));
+ aprint_normal("%s: pci0mem[0]=%#10x-%#10x ", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = gt_read(gt, GT_PCI0_Mem0_Remap_Low);
+ hiaddr = gt_read(gt, GT_PCI0_Mem0_Remap_High);
+ aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem1_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem1_High_Decode));
+ aprint_normal("%s: pci0mem[1]=%#10x-%#10x ", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = gt_read(gt, GT_PCI0_Mem1_Remap_Low);
+ hiaddr = gt_read(gt, GT_PCI0_Mem1_Remap_High);
+ aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem2_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem2_High_Decode));
+ aprint_normal("%s: pci0mem[2]=%#10x-%#10x ", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = gt_read(gt, GT_PCI0_Mem2_Remap_Low);
+ hiaddr = gt_read(gt, GT_PCI0_Mem2_Remap_High);
+ aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI0_Mem3_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI0_Mem3_High_Decode));
+ aprint_normal("%s: pci0mem[3]=%#10x-%#10x ", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = gt_read(gt, GT_PCI0_Mem3_Remap_Low);
+ hiaddr = gt_read(gt, GT_PCI0_Mem3_Remap_High);
+ aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_IO_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_IO_High_Decode));
+ aprint_normal("%s: pci1io=%#10x-%#10x ", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = gt_read(gt, GT_PCI1_IO_Remap);
+ aprint_normal("remap=%#010x\n", loaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem0_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem0_High_Decode));
+ aprint_normal("%s: pci1mem[0]=%#10x-%#10x ", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = gt_read(gt, GT_PCI1_Mem0_Remap_Low);
+ hiaddr = gt_read(gt, GT_PCI1_Mem0_Remap_High);
+ aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem1_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem1_High_Decode));
+ aprint_normal("%s: pci1mem[1]=%#10x-%#10x ", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = gt_read(gt, GT_PCI1_Mem1_Remap_Low);
+ hiaddr = gt_read(gt, GT_PCI1_Mem1_Remap_High);
+ aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem2_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem2_High_Decode));
+ aprint_normal("%s: pci1mem[2]=%#10x-%#10x ", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = gt_read(gt, GT_PCI1_Mem2_Remap_Low);
+ hiaddr = gt_read(gt, GT_PCI1_Mem2_Remap_High);
+ aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_PCI1_Mem3_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_PCI1_Mem3_High_Decode));
+ aprint_normal("%s: pci1mem[3]=%#10x-%#10x ", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = gt_read(gt, GT_PCI1_Mem3_Remap_Low);
+ hiaddr = gt_read(gt, GT_PCI1_Mem3_Remap_High);
+ aprint_normal("remap=%#010x.%#010x\n", hiaddr, loaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_Internal_Decode));
+ aprint_normal("%s: internal=%#10x-%#10x\n", gt->gt_dev.dv_xname,
+ loaddr, loaddr+256*1024);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_CPU0_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CPU0_High_Decode));
+ aprint_normal("%s: cpu0=%#10x-%#10x\n", gt->gt_dev.dv_xname, loaddr, hiaddr);
+
+ loaddr = GT_LowAddr_GET(gt_read(gt, GT_CPU1_Low_Decode));
+ hiaddr = GT_HighAddr_GET(gt_read(gt, GT_CPU1_High_Decode));
+ aprint_normal("%s: cpu1=%#10x-%#10x", gt->gt_dev.dv_xname, loaddr, hiaddr);
+#endif
+
+ aprint_normal("%s:", gt->gt_dev.dv_xname);
+
+ cpucfg = gt_read(gt, GT_CPU_Cfg);
+ cpucfg |= GT_CPUCfg_ConfSBDis; /* per errata #46 */
+ cpucfg |= GT_CPUCfg_AACKDelay; /* per restriction #18 */
+ gt_write(gt, GT_CPU_Cfg, cpucfg);
+ if (cpucfg & GT_CPUCfg_Pipeline)
+ aprint_normal(" pipeline");
+ if (cpucfg & GT_CPUCfg_AACKDelay)
+ aprint_normal(" aack-delay");
+ if (cpucfg & GT_CPUCfg_RdOOO)
+ aprint_normal(" read-ooo");
+ if (cpucfg & GT_CPUCfg_IOSBDis)
+ aprint_normal(" io-sb-dis");
+ if (cpucfg & GT_CPUCfg_ConfSBDis)
+ aprint_normal(" conf-sb-dis");
+ if (cpucfg & GT_CPUCfg_ClkSync)
+ aprint_normal(" clk-sync");
+ aprint_normal("\n");
+
+ gt_init_hostid(gt);
+
+ gt_watchdog_init(gt);
+
+ gt_init_interrupt(gt);
+
+#ifdef GT_ECC
+ gt_ecc_intr_enb(gt);
+#endif
+
+ gt_comm_intr_enb(gt);
+ gt_devbus_intr_enb(gt);
+
+ gt_watchdog_disable();
+ config_search(gt_cfsearch, &gt->gt_dev, NULL);
+ gt_watchdog_service();
+ gt_watchdog_enable();
+}
+
+void
+gt_init_hostid(struct gt_softc *gt)
+{
+
+ hostid = 1; /* XXX: Used by i2c; needs work -- AKB */
+}
+
+void
+gt_init_interrupt(struct gt_softc *gt)
+{
+ u_int32_t mppirpts = GT_MPP_INTERRUPTS; /* from config */
+ u_int32_t r;
+ u_int32_t mppbit;
+ u_int32_t mask;
+ u_int32_t mppsel;
+ u_int32_t regoff;
+
+ gt_write(gt, ICR_CIM_LO, 0);
+ gt_write(gt, ICR_CIM_HI, 0);
+
+ /*
+ * configure the GPP interrupts:
+ * - set the configured MPP pins in GPP mode
+ * - set the configured GPP pins to input, active low, interrupt enbl
+ */
+#ifdef DEBUG
+ printf("%s: mpp cfg ", gt->gt_dev.dv_xname);
+ for (regoff = GT_MPP_Control0; regoff <= GT_MPP_Control3; regoff += 4)
+ printf("%#x ", gt_read(gt, regoff));
+ printf(", mppirpts 0x%x\n", mppirpts);
+#endif
+ mppbit = 0x1;
+ for (regoff = GT_MPP_Control0; regoff <= GT_MPP_Control3; regoff += 4) {
+ mask = 0;
+ for (mppsel = 0xf; mppsel; mppsel <<= 4) {
+ if (mppirpts & mppbit)
+ mask |= mppsel;
+ mppbit <<= 1;
+ }
+ if (mask) {
+ r = gt_read(gt, regoff);
+ r &= ~mask;
+ gt_write(gt, regoff, r);
+ }
+ }
+
+ r = gt_read(gt, GT_GPP_IO_Control);
+ r &= ~mppirpts;
+ gt_write(gt, GT_GPP_IO_Control, r);
+
+ r = gt_read(gt, GT_GPP_Level_Control);
+ r |= mppirpts;
+ gt_write(gt, GT_GPP_Level_Control, r);
+
+ r = gt_read(gt, GT_GPP_Interrupt_Mask);
+ r |= mppirpts;
+ gt_write(gt, GT_GPP_Interrupt_Mask, r);
+}
+
+uint32_t
+gt_read_mpp (void)
+{
+ return gt_read((struct gt_softc *)gt_cd.cd_devs[0], GT_GPP_Value);
+}
+
+#if 0
+int
+gt_bs_extent_init(struct discovery_bus_space *bs, char *name)
+{
+ u_long start, end;
+ int i, j, error;
+
+ if (bs->bs_nregion == 0) {
+ bs->bs_extent = extent_create(name, 0xffffffffUL, 0xffffffffUL,
+ M_DEVBUF, NULL, 0, EX_NOCOALESCE|EX_WAITOK);
+ KASSERT(bs->bs_extent != NULL);
+ return 0;
+ }
+ /*
+ * Find the top and bottoms of this bus space.
+ */
+ start = bs->bs_regions[0].br_start;
+ end = bs->bs_regions[0].br_end;
+#ifdef DEBUG
+ if (gtpci_debug > 1)
+ printf("gtpci_bs_extent_init: %s: region %d: %#lx-%#lx\n",
+ name, 0, bs->bs_regions[0].br_start,
+ bs->bs_regions[0].br_end);
+#endif
+ for (i = 1; i < bs->bs_nregion; i++) {
+ if (bs->bs_regions[i].br_start < start)
+ start = bs->bs_regions[i].br_start;
+ if (bs->bs_regions[i].br_end > end)
+ end = bs->bs_regions[i].br_end;
+#ifdef DEBUG
+ if (gtpci_debug > 1)
+ printf("gtpci_bs_extent_init: %s: region %d:"
+ " %#lx-%#lx\n",
+ name, i, bs->bs_regions[i].br_start,
+ bs->bs_regions[i].br_end);
+#endif
+ }
+ /*
+ * Now that we have the top and bottom limits of this
+ * bus space, create the extent map that will manage this
+ * space for us.
+ */
+#ifdef DEBUG
+ if (gtpci_debug > 1)
+ printf("gtpci_bs_extent_init: %s: create: %#lx-%#lx\n",
+ name, start, end);
+#endif
+ bs->bs_extent = extent_create(name, start, end, M_DEVBUF,
+ NULL, 0, EX_NOCOALESCE|EX_WAITOK);
+ KASSERT(bs->bs_extent != NULL);
+
+ /* If there was more than one bus space region, then there
+ * might gaps in between them. Allocate the gap so that
+ * they will not be legal addresses in the extent.
+ */
+ for (i = 0; i < bs->bs_nregion && bs->bs_nregion > 1; i++) {
+ /* Initial start is "infinity" and the inital end is
+ * is the end of this bus region.
+ */
+ start = ~0UL;
+ end = bs->bs_regions[i].br_end;
+ /* For each region, if it starts after this region but less
+ * than the saved start, use its start address. If the start
+ * address is one past the end address, then we're done
+ */
+ for (j = 0; j < bs->bs_nregion && start > end + 1; j++) {
+ if (i == j)
+ continue;
+ if (bs->bs_regions[j].br_start > end &&
+ bs->bs_regions[j].br_start < start)
+ start = bs->bs_regions[j].br_start;
+ }
+ /*
+ * If we found a gap, allocate it away.
+ */
+ if (start != ~0UL && start != end + 1) {
+#ifdef DEBUG
+ if (gtpci_debug > 1)
+ printf("gtpci_bs_extent_init: %s: alloc(hole): %#lx-%#lx\n",
+ name, end + 1, start - 1);
+#endif
+ error = extent_alloc_region(bs->bs_extent, end + 1,
+ start - (end + 1), EX_NOWAIT);
+ KASSERT(error == 0);
+ }
+ }
+ return 1;
+}
+#endif
+
+/*
+ * unknown board, enable everything
+ */
+# define GT_CommUnitIntr_DFLT GT_CommUnitIntr_S0|GT_CommUnitIntr_S1 \
+ |GT_CommUnitIntr_E0|GT_CommUnitIntr_E1 \
+ |GT_CommUnitIntr_E2
+
+static const char * const gt_comm_subunit_name[8] = {
+ "ethernet 0",
+ "ethernet 1",
+ "ethernet 2",
+ "(reserved)",
+ "MPSC 0",
+ "MPSC 1",
+ "(reserved)",
+ "(sel)",
+};
+
+static int
+gt_comm_intr(void *arg)
+{
+ struct gt_softc *gt = (struct gt_softc *)arg;
+ u_int32_t cause;
+ u_int32_t addr;
+ unsigned int mask;
+ int i;
+
+ cause = gt_read(gt, GT_CommUnitIntr_Cause);
+ gt_write(gt, GT_CommUnitIntr_Cause, ~cause);
+ addr = gt_read(gt, GT_CommUnitIntr_ErrAddr);
+
+ printf("%s: Comm Unit irpt, cause %#x addr %#x\n",
+ gt->gt_dev.dv_xname, cause, addr);
+
+ cause &= GT_CommUnitIntr_DFLT;
+ if (cause == 0)
+ return 0;
+
+ mask = 0x7;
+ for (i=0; i<7; i++) {
+ if (cause & mask) {
+ printf("%s: Comm Unit %s:", gt->gt_dev.dv_xname,
+ gt_comm_subunit_name[i]);
+ if (cause & 1)
+ printf(" AddrMiss");
+ if (cause & 2)
+ printf(" AccProt");
+ if (cause & 4)
+ printf(" WrProt");
+ printf("\n");
+ }
+ cause >>= 4;
+ }
+ return 1;
+}
+
+/*
+ * gt_comm_intr_init - enable GT-64260 Comm Unit interrupts
+ */
+static void
+gt_comm_intr_enb(struct gt_softc *gt)
+{
+ u_int32_t cause;
+
+ cause = gt_read(gt, GT_CommUnitIntr_Cause);
+ if (cause)
+ gt_write(gt, GT_CommUnitIntr_Cause, ~cause);
+ gt_write(gt, GT_CommUnitIntr_Mask, GT_CommUnitIntr_DFLT);
+ (void)gt_read(gt, GT_CommUnitIntr_ErrAddr);
+
+ intr_establish(IRQ_COMM, IST_LEVEL, IPL_GTERR, gt_comm_intr, gt);
+ printf("%s: Comm Unit irpt at %d\n", gt->gt_dev.dv_xname, IRQ_COMM);
+}
+
+#ifdef GT_ECC
+static char *gt_ecc_intr_str[4] = {
+ "(none)",
+ "single bit",
+ "double bit",
+ "(reserved)"
+};
+
+static int
+gt_ecc_intr(void *arg)
+{
+ struct gt_softc *gt = (struct gt_softc *)arg;
+ u_int32_t addr;
+ u_int32_t dlo;
+ u_int32_t dhi;
+ u_int32_t rec;
+ u_int32_t calc;
+ u_int32_t count;
+ int err;
+
+ count = gt_read(gt, GT_ECC_Count);
+ dlo = gt_read(gt, GT_ECC_Data_Lo);
+ dhi = gt_read(gt, GT_ECC_Data_Hi);
+ rec = gt_read(gt, GT_ECC_Rec);
+ calc = gt_read(gt, GT_ECC_Calc);
+ addr = gt_read(gt, GT_ECC_Addr); /* read last! */
+ gt_write(gt, GT_ECC_Addr, 0); /* clear irpt */
+
+ err = addr & 0x3;
+
+ printf("%s: ECC error: %s: "
+ "addr %#x data %#x.%#x rec %#x calc %#x cnt %#x\n",
+ gt->gt_dev.dv_xname, gt_ecc_intr_str[err],
+ addr, dhi, dlo, rec, calc, count);
+
+ if (err == 2)
+ panic("ecc");
+
+ return (err == 1);
+}
+
+/*
+ * gt_ecc_intr_enb - enable GT-64260 ECC interrupts
+ */
+static void
+gt_ecc_intr_enb(struct gt_softc *gt)
+{
+ u_int32_t ctl;
+
+ ctl = gt_read(gt, GT_ECC_Ctl);
+ ctl |= 1 << 16; /* XXX 1-bit threshold == 1 */
+ gt_write(gt, GT_ECC_Ctl, ctl);
+ (void)gt_read(gt, GT_ECC_Data_Lo);
+ (void)gt_read(gt, GT_ECC_Data_Hi);
+ (void)gt_read(gt, GT_ECC_Rec);
+ (void)gt_read(gt, GT_ECC_Calc);
+ (void)gt_read(gt, GT_ECC_Addr); /* read last! */
+ gt_write(gt, GT_ECC_Addr, 0); /* clear irpt */
+
+ intr_establish(IRQ_ECC, IST_LEVEL, IPL_GTERR, gt_ecc_intr, gt);
+ printf("%s: ECC irpt at %d\n", gt->gt_dev.dv_xname, IRQ_ECC);
+}
+#endif /* GT_ECC */
+
+
+#ifndef GT_MPP_WATCHDOG
+void
+gt_watchdog_init(struct gt_softc *gt)
+{
+ u_int32_t r;
+ unsigned int omsr;
+
+ omsr = extintr_disable();
+
+ printf("%s: watchdog", gt->gt_dev.dv_xname);
+
+ /*
+ * handle case where firmware started watchdog
+ */
+ r = gt_read(gt, GT_WDOG_Config);
+ printf(" status %#x,%#x:",
+ r, gt_read(gt, GT_WDOG_Value));
+ if ((r & 0x80000000) != 0) {
+ gt_watchdog_sc = gt; /* enabled */
+ gt_watchdog_state = 1;
+ printf(" firmware-enabled\n");
+ gt_watchdog_service();
+ return;
+ } else {
+ printf(" firmware-disabled\n");
+ }
+
+ extintr_restore(omsr);
+}
+
+#else /* GT_MPP_WATCHDOG */
+
+void
+gt_watchdog_init(struct gt_softc *gt)
+{
+ u_int32_t mpp_watchdog = GT_MPP_WATCHDOG; /* from config */
+ u_int32_t r;
+ u_int32_t cfgbits;
+ u_int32_t mppbits;
+ u_int32_t mppmask=0;
+ u_int32_t regoff;
+ unsigned int omsr;
+
+ printf("%s: watchdog", gt->gt_dev.dv_xname);
+
+ if (mpp_watchdog == 0) {
+ printf(" not configured\n");
+ return;
+ }
+
+#if 0
+ if (afw_wdog_ctl == 1) {
+ printf(" admin disabled\n");
+ return;
+ }
+#endif
+
+ omsr = extintr_disable();
+
+ /*
+ * if firmware started watchdog, we disable and start
+ * from scratch to get it in a known state.
+ *
+ * on GT-64260A we always see 0xffffffff
+ * in both the GT_WDOG_Config_Enb and GT_WDOG_Value regsiters.
+ * Use AFW-supplied flag to determine run state.
+ */
+ r = gt_read(gt, GT_WDOG_Config);
+ if (r != ~0) {
+ if ((r & GT_WDOG_Config_Enb) != 0) {
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT));
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT));
+ }
+ } else {
+#if 0
+ if (afw_wdog_state == 1) {
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT));
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT));
+ }
+#endif
+ }
+
+ /*
+ * "the watchdog timer can be activated only after
+ * configuring two MPP pins to act as WDE and WDNMI"
+ */
+ mppbits = 0;
+ cfgbits = 0x3;
+ for (regoff = GT_MPP_Control0; regoff <= GT_MPP_Control3; regoff += 4) {
+ if ((mpp_watchdog & cfgbits) == cfgbits) {
+ mppbits = 0x99;
+ mppmask = 0xff;
+ break;
+ }
+ cfgbits <<= 2;
+ if ((mpp_watchdog & cfgbits) == cfgbits) {
+ mppbits = 0x9900;
+ mppmask = 0xff00;
+ break;
+ }
+ cfgbits <<= 6; /* skip unqualified bits */
+ }
+ if (mppbits == 0) {
+ printf(" config error\n");
+ extintr_restore(omsr);
+ return;
+ }
+
+ r = gt_read(gt, regoff);
+ r &= ~mppmask;
+ r |= mppbits;
+ gt_write(gt, regoff, r);
+ printf(" mpp %#x %#x", regoff, mppbits);
+
+ gt_write(gt, GT_WDOG_Value, GT_WDOG_NMI_DFLT);
+
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT));
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT));
+
+
+ r = gt_read(gt, GT_WDOG_Config),
+ printf(" status %#x,%#x: %s",
+ r, gt_read(gt, GT_WDOG_Value),
+ ((r & GT_WDOG_Config_Enb) != 0) ? "enabled" : "botch");
+
+ if ((r & GT_WDOG_Config_Enb) != 0) {
+ register_t hid0;
+
+ gt_watchdog_sc = gt; /* enabled */
+ gt_watchdog_state = 1;
+
+ /*
+ * configure EMCP in HID0 in case it's not already set
+ */
+ __asm __volatile("sync":::"memory");
+ hid0 = mfspr(SPR_HID0);
+ if ((hid0 & HID0_EMCP) == 0) {
+ hid0 |= HID0_EMCP;
+ __asm __volatile("sync":::"memory"); mtspr(SPR_HID0, hid0);
+ __asm __volatile("sync":::"memory"); hid0 = mfspr(SPR_HID0);
+ printf(", EMCP set");
+ }
+ }
+ printf("\n");
+
+ extintr_restore(omsr);
+}
+#endif /* GT_MPP_WATCHDOG */
+
+#ifdef DEBUG
+u_int32_t hid0_print(void);
+u_int32_t
+hid0_print()
+{
+ u_int32_t hid0;
+ __asm __volatile("sync; mfspr %0,1008;" : "=r"(hid0)::"memory");
+ printf("hid0: %#x\n", hid0);
+ return hid0;
+}
+#endif
+
+void
+gt_watchdog_enable(void)
+{
+ struct gt_softc *gt;
+ unsigned int omsr;
+
+ omsr = extintr_disable();
+ gt = gt_watchdog_sc;
+ if ((gt != NULL) && (gt_watchdog_state == 0)) {
+ gt_watchdog_state = 1;
+
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT));
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT));
+ }
+ extintr_restore(omsr);
+}
+
+void
+gt_watchdog_disable(void)
+{
+ struct gt_softc *gt;
+ unsigned int omsr;
+
+ omsr = extintr_disable();
+ gt = gt_watchdog_sc;
+ if ((gt != NULL) && (gt_watchdog_state != 0)) {
+ gt_watchdog_state = 0;
+
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1a | GT_WDOG_Preset_DFLT));
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1b | GT_WDOG_Preset_DFLT));
+ }
+ extintr_restore(omsr);
+}
+
+#ifdef DEBUG
+int inhibit_watchdog_service = 0;
+#endif
+void
+gt_watchdog_service(void)
+{
+ struct gt_softc *gt = gt_watchdog_sc;
+
+ if ((gt == NULL) || (gt_watchdog_state == 0))
+ return; /* not enabled */
+#ifdef DEBUG
+ if (inhibit_watchdog_service)
+ return;
+#endif
+
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl2a | GT_WDOG_Preset_DFLT));
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl2b | GT_WDOG_Preset_DFLT));
+}
+
+/*
+ * gt_watchdog_reset - force a watchdog reset using Preset_VAL=0
+ */
+void
+gt_watchdog_reset()
+{
+ struct gt_softc *gt = gt_watchdog_sc;
+ u_int32_t r;
+
+ (void)extintr_disable();
+ r = gt_read(gt, GT_WDOG_Config);
+ gt_write(gt, GT_WDOG_Config, (GT_WDOG_Config_Ctl1a | 0));
+ gt_write(gt, GT_WDOG_Config, (GT_WDOG_Config_Ctl1b | 0));
+ if ((r & GT_WDOG_Config_Enb) != 0) {
+ /*
+ * was enabled, we just toggled it off, toggle on again
+ */
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1a | 0));
+ gt_write(gt, GT_WDOG_Config,
+ (GT_WDOG_Config_Ctl1b | 0));
+ }
+ for(;;);
+}
+
+static int
+gt_devbus_intr(void *arg)
+{
+ struct gt_softc *gt = (struct gt_softc *)arg;
+ u_int32_t cause;
+ u_int32_t addr;
+
+ cause = gt_read(gt, GT_DEVBUS_ICAUSE);
+ addr = gt_read(gt, GT_DEVBUS_ERR_ADDR);
+ gt_write(gt, GT_DEVBUS_ICAUSE, 0); /* clear irpt */
+
+ if (cause & GT_DEVBUS_DBurstErr) {
+ printf("%s: Device Bus error: burst violation",
+ gt->gt_dev.dv_xname);
+ if ((cause & GT_DEVBUS_Sel) == 0)
+ printf(", addr %#x", addr);
+ printf("\n");
+ }
+ if (cause & GT_DEVBUS_DRdyErr) {
+ printf("%s: Device Bus error: ready timer expired",
+ gt->gt_dev.dv_xname);
+ if ((cause & GT_DEVBUS_Sel) != 0)
+ printf(", addr %#x\n", addr);
+ printf("\n");
+ }
+
+ return (cause != 0);
+}
+
+/*
+ * gt_ecc_intr_enb - enable GT-64260 ECC interrupts
+ */
+static void
+gt_devbus_intr_enb(struct gt_softc *gt)
+{
+ gt_write(gt, GT_DEVBUS_IMASK,
+ GT_DEVBUS_DBurstErr|GT_DEVBUS_DRdyErr);
+ (void)gt_read(gt, GT_DEVBUS_ERR_ADDR); /* clear addr */
+ gt_write(gt, GT_ECC_Addr, 0); /* clear irpt */
+
+ intr_establish(IRQ_DEV, IST_LEVEL, IPL_GTERR, gt_devbus_intr, gt);
+ printf("%s: Device Bus Error irpt at %d\n",
+ gt->gt_dev.dv_xname, IRQ_DEV);
+}
+
+
+int
+gt_mii_read(
+ struct device *child,
+ struct device *parent,
+ int phy,
+ int reg)
+{
+ struct gt_softc * const gt = (struct gt_softc *) parent;
+ uint32_t data;
+ int count = 10000;
+
+ do {
+ DELAY(10);
+ data = gt_read(gt, ETH_ESMIR);
+ } while ((data & ETH_ESMIR_Busy) && count-- > 0);
+
+ if (count == 0) {
+ printf("%s: mii read for phy %d reg %d busied out\n",
+ child->dv_xname, phy, reg);
+ return ETH_ESMIR_Value_GET(data);
+ }
+
+ gt_write(gt, ETH_ESMIR, ETH_ESMIR_READ(phy, reg));
+
+ count = 10000;
+ do {
+ DELAY(10);
+ data = gt_read(gt, ETH_ESMIR);
+ } while ((data & ETH_ESMIR_ReadValid) == 0 && count-- > 0);
+
+ if (count == 0)
+ printf("%s: mii read for phy %d reg %d timed out\n",
+ child->dv_xname, phy, reg);
+#if defined(GTMIIDEBUG)
+ printf("%s: mii_read(%d, %d): %#x data %#x\n",
+ child->dv_xname, phy, reg,
+ data, ETH_ESMIR_Value_GET(data));
+#endif
+ return ETH_ESMIR_Value_GET(data);
+}
+
+void
+gt_mii_write (
+ struct device *child,
+ struct device *parent,
+ int phy, int reg,
+ int value)
+{
+ struct gt_softc * const gt = (struct gt_softc *) parent;
+ uint32_t data;
+ int count = 10000;
+
+ do {
+ DELAY(10);
+ data = gt_read(gt, ETH_ESMIR);
+ } while ((data & ETH_ESMIR_Busy) && count-- > 0);
+
+ if (count == 0) {
+ printf("%s: mii write for phy %d reg %d busied out (busy)\n",
+ child->dv_xname, phy, reg);
+ return;
+ }
+
+ gt_write(gt, ETH_ESMIR,
+ ETH_ESMIR_WRITE(phy, reg, value));
+
+ count = 10000;
+ do {
+ DELAY(10);
+ data = gt_read(gt, ETH_ESMIR);
+ } while ((data & ETH_ESMIR_Busy) && count-- > 0);
+
+ if (count == 0)
+ printf("%s: mii write for phy %d reg %d timed out\n",
+ child->dv_xname, phy, reg);
+#if defined(GTMIIDEBUG)
+ printf("%s: mii_write(%d, %d, %#x)\n",
+ child->dv_xname, phy, reg, value);
+#endif
+}
+
diff --git a/bsps/powerpc/beatnik/marvell/gt_timer.c b/bsps/powerpc/beatnik/marvell/gt_timer.c
new file mode 100644
index 0000000000..fd6960ea54
--- /dev/null
+++ b/bsps/powerpc/beatnik/marvell/gt_timer.c
@@ -0,0 +1,410 @@
+/* Driver for discovery timers and watchdog */
+
+/*
+ * Acknowledgements:
+ * Valuable information was obtained from the following drivers
+ * netbsd: (C) Allegro Networks Inc; Wasabi Systems Inc.
+ * linux: (C) MontaVista, Software, Inc; Mark A. Greer.
+ * rtems: (C) Brookhaven National Laboratory; K. Feng
+ * but this implementation is original work by the author.
+ */
+
+/*
+ * Authorship
+ * ----------
+ * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
+ * created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * The 'beatnik' BSP was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+#include <rtems.h>
+#include <bsp/gtreg.h>
+#include <libcpu/io.h>
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <rtems/bspIo.h>
+
+#include <stdint.h>
+
+#include <bsp/gt_timer.h>
+
+#define DEBUG
+
+static inline uint32_t gt_rd(uint32_t off)
+{
+ return in_le32( (volatile uint32_t *)(BSP_MV64x60_BASE+off) );
+}
+
+static inline void gt_wr(uint32_t off, uint32_t val)
+{
+ out_le32( (volatile uint32_t *)(BSP_MV64x60_BASE+off), val);
+}
+
+static inline uint32_t gt_timer_bitmod(uint32_t off, uint32_t clr, uint32_t set)
+{
+ unsigned flags;
+ uint32_t rval;
+
+ rtems_interrupt_disable(flags);
+ rval = gt_rd( off );
+ gt_wr( off, (rval & ~clr) | set );
+ rtems_interrupt_enable(flags);
+ return rval;
+}
+
+#define GT_TIMER_MAX 3
+#define TIMER_ARGCHECK(t) do { if ((t)>GT_TIMER_MAX) return -1; } while (0)
+
+static struct {
+ void (*isr)(void *);
+ void *arg;
+} gt_timer_isrs[GT_TIMER_MAX+1] = {{0},};
+
+uint32_t BSP_timer_read(uint32_t timer)
+{
+ TIMER_ARGCHECK(timer);
+ return gt_rd(GT_TIMER_0 + (timer<<2));
+}
+
+int
+BSP_timer_start(uint32_t timer, uint32_t period)
+{
+ TIMER_ARGCHECK(timer);
+ gt_wr(GT_TIMER_0 + (timer<<2), period);
+ return 0;
+}
+
+int
+BSP_timer_stop(uint32_t timer)
+{
+ TIMER_ARGCHECK(timer);
+ /* disable, clear period, re-enable */
+ gt_timer_bitmod(GT_TIMER_0_3_Ctl, GT_TIMER_0_Ctl_Enb << (timer<<3), 0);
+ gt_wr(GT_TIMER_0 + (timer<<2), 0);
+ gt_timer_bitmod(GT_TIMER_0_3_Ctl, 0, GT_TIMER_0_Ctl_Enb << (timer<<3));
+ return 0;
+}
+
+int
+BSP_timer_setup(uint32_t timer, void (*isr)(void *arg), void *arg, int reload)
+{
+ TIMER_ARGCHECK(timer);
+ if ( isr && gt_timer_isrs[timer].isr )
+ return -1;
+
+ BSP_timer_stop(timer);
+ /* mask and clear */
+ gt_timer_bitmod(GT_TIMER_0_3_Intr_Msk, GT_TIMER_0_Intr<<timer, 0);
+ gt_timer_bitmod(GT_TIMER_0_3_Intr_Cse, GT_TIMER_0_Intr<<timer, 0);
+
+ /* set reload bit */
+ if ( reload )
+ gt_timer_bitmod(GT_TIMER_0_3_Ctl, 0, GT_TIMER_0_Ctl_Rld << (timer<<3));
+ else
+ gt_timer_bitmod(GT_TIMER_0_3_Ctl, GT_TIMER_0_Ctl_Rld << (timer<<3), 0);
+
+ asm volatile("":::"memory");
+
+ if ( isr ) {
+ gt_timer_isrs[timer].isr = isr;
+ gt_timer_isrs[timer].arg = arg;
+ asm volatile("":::"memory");
+ gt_timer_bitmod(GT_TIMER_0_3_Intr_Msk, 0, GT_TIMER_0_Intr<<timer);
+ } else {
+ gt_timer_isrs[timer].isr = 0;
+ gt_timer_isrs[timer].arg = 0;
+ }
+ return 0;
+}
+
+static void
+gt_timer_hdl(rtems_irq_hdl_param arg)
+{
+ int iarg = (int)arg;
+ int timer;
+ uint32_t bit;
+
+ for ( ; iarg; iarg >>= 4 ) {
+ timer = (iarg & 0xf)-1;
+ bit = GT_TIMER_0_Intr<<timer;
+ if ( gt_timer_bitmod(GT_TIMER_0_3_Intr_Cse, bit, 0) & bit ) {
+ /* cause was set */
+ if ( ! gt_timer_isrs[timer].isr ) {
+ printk("gt_timer: warning; no ISR connected but and IRQ happened (timer # %i)\n", timer);
+ /* mask */
+ gt_timer_bitmod(GT_TIMER_0_3_Intr_Msk, bit, 0);
+ } else {
+ gt_timer_isrs[timer].isr(gt_timer_isrs[timer].arg);
+ }
+ }
+ }
+}
+
+int
+BSP_timers_initialize(void)
+{
+ rtems_irq_connect_data xx = {0};
+ int i, ainc, arg;
+
+ xx.hdl = gt_timer_hdl;
+ xx.on = 0;
+ xx.off = 0;
+ xx.isOn = 0;
+
+ switch (BSP_getDiscoveryVersion(0)) {
+ case MV_64360:
+ i = 3;
+ ainc = 1;
+ arg = 4;
+ break;
+ default:
+ i = 1;
+ ainc = 0x0202;
+ arg = 0x0403;
+ break;
+ }
+
+ for ( ; i>=0; i--, arg-=ainc ) {
+ xx.name = BSP_IRQ_TIME0_1 + i;
+ xx.handle = (rtems_irq_hdl_param)arg;
+ if ( !BSP_install_rtems_irq_handler(&xx) )
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef DEBUG_MODULAR
+static int
+BSP_timers_uninstall(void)
+{
+ rtems_irq_connect_data xx = {0};
+ int i;
+
+ xx.hdl = gt_timer_hdl;
+ xx.on = 0;
+ xx.off = 0;
+ xx.isOn = 0;
+
+ for ( i=0; i<= GT_TIMER_MAX; i++ ) {
+ if ( BSP_timer_setup(i, 0, 0, 0) )
+ return -1;
+ }
+
+ switch (BSP_getDiscoveryVersion(0)) {
+ case MV_64360:
+ i = 3;
+ break;
+ default:
+ i = 1;
+ break;
+ }
+
+ for ( ; i >= 0; i-- ) {
+ xx.name = BSP_IRQ_TIME0_1 + i;
+ BSP_get_current_rtems_irq_handler(&xx);
+ if ( !BSP_remove_rtems_irq_handler(&xx) )
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+uint32_t
+BSP_timer_clock_get(uint32_t timer)
+{
+ return BSP_bus_frequency;
+}
+
+int BSP_timer_instances(void)
+{
+ return GT_TIMER_MAX + 1;
+}
+
+/* On a 64260A we can't read the status (on/off), apparently
+ * so we maintain it locally and assume the firmware has
+ * not enabled the dog initially...
+ */
+static uint32_t wdog_on = 0x00ffffff;
+
+static uint32_t rd_wdcnf(void)
+{
+ uint32_t cnf = gt_rd(GT_WDOG_Config);
+
+ /* BSD driver says that on the 64260A we always
+ * read 0xffffffff so we have to maintain the
+ * status locally (and hope we get the initial
+ * value right).
+ */
+ if ( ~0 == cnf )
+ cnf = wdog_on;
+ return cnf;
+}
+
+/* change on/off state assume caller has IRQs disabled */
+static void dog_toggle(uint32_t ctl)
+{
+ ctl &= ~( GT_WDOG_Config_Ctl1a | GT_WDOG_Config_Ctl1b \
+ | GT_WDOG_Config_Ctl2a | GT_WDOG_Config_Ctl2b);
+ gt_wr(GT_WDOG_Config, ctl | GT_WDOG_Config_Ctl1a);
+ gt_wr(GT_WDOG_Config, ctl | GT_WDOG_Config_Ctl1b);
+}
+
+static void dog_pet(uint32_t ctl)
+{
+ ctl &= ~( GT_WDOG_Config_Ctl1a | GT_WDOG_Config_Ctl1b \
+ | GT_WDOG_Config_Ctl2a | GT_WDOG_Config_Ctl2b);
+ gt_wr(GT_WDOG_Config, ctl | GT_WDOG_Config_Ctl2a);
+ gt_wr(GT_WDOG_Config, ctl | GT_WDOG_Config_Ctl2b);
+}
+
+
+/* Enable watchdog and set a timeout (in us)
+ * a timeout of 0xffffffff selects the old/existing
+ * timeout.
+ *
+ * RETURNS 0 on success
+ */
+int
+BSP_watchdog_enable(uint32_t timeout_us)
+{
+ unsigned long long x = timeout_us;
+ unsigned flags;
+ uint32_t ctl;
+
+ x *= BSP_bus_frequency;
+ x /= 256; /* there seems to be a prescaler */
+ x /= 1000000; /* us/s */
+
+ if ( x > (1<<24)-1 )
+ x = (1<<24)-1;
+
+ if ( 0xffffffff != timeout_us )
+ timeout_us = x;
+
+ rtems_interrupt_disable(flags);
+
+ ctl = rd_wdcnf();
+
+ /* if enabled, disable first */
+ if ( GT_WDOG_Config_Enb & ctl ) {
+ dog_toggle(ctl);
+ }
+ if ( 0xffffffff == timeout_us ) {
+ timeout_us = ctl & ((1<<24)-1);
+ dog_toggle(ctl);
+ dog_pet(ctl);
+ } else {
+ gt_wr(GT_WDOG_Config, timeout_us | GT_WDOG_Config_Ctl1a);
+ gt_wr(GT_WDOG_Config, timeout_us | GT_WDOG_Config_Ctl1b);
+ }
+
+ wdog_on = GT_WDOG_Config_Enb | timeout_us;
+
+ rtems_interrupt_enable(flags);
+ return 0;
+}
+
+/* Disable watchdog
+ * RETURNS 0 on success
+ */
+int BSP_watchdog_disable(void)
+{
+unsigned long flags;
+uint32_t ctl;
+
+ rtems_interrupt_disable(flags);
+
+ ctl = rd_wdcnf();
+
+ if ( (GT_WDOG_Config_Enb & ctl) ) {
+ dog_toggle(ctl);
+ wdog_on = ctl & ~(GT_WDOG_Config_Enb);
+ }
+
+ rtems_interrupt_enable(flags);
+ return 0;
+}
+
+/* Check status -- unfortunately there seems to be no way
+ * to read the running value...
+ *
+ * RETURNS nonzero if enabled/running, zero if disabled/stopped
+ */
+int BSP_watchdog_status(void)
+{
+ uint32_t ctl = rd_wdcnf();
+
+ /* report also the current period */
+ return GT_WDOG_Config_Enb & ctl ? ctl : 0;
+}
+
+/* Pet the watchdog (rearm to configured timeout)
+ * RETURNS: 0 on success, nonzero on failure (watchdog
+ * currently not running).
+ */
+int BSP_watchdog_pet(void)
+{
+ unsigned long flags;
+
+ if ( !wdog_on )
+ return -1;
+ rtems_interrupt_disable(flags);
+ dog_pet(rd_wdcnf());
+ rtems_interrupt_enable(flags);
+ return 0;
+}
+
+
+#ifdef DEBUG_MODULAR
+int
+_cexpModuleFinalize(void *unused)
+{
+ BSP_watchdog_disable();
+ return BSP_timers_uninstall();
+}
+
+void
+_cexpModuleInitialize(void *unused)
+{
+ BSP_timers_initialize();
+}
+#endif
diff --git a/bsps/powerpc/beatnik/marvell/gti2c.c b/bsps/powerpc/beatnik/marvell/gti2c.c
new file mode 100644
index 0000000000..c602bac5eb
--- /dev/null
+++ b/bsps/powerpc/beatnik/marvell/gti2c.c
@@ -0,0 +1,447 @@
+/* $NetBSD: gti2c.c,v 1.2 2005/02/27 00:27:21 perry Exp $ */
+
+/*
+ * Copyright (c) 2005 Brocade Communcations, inc.
+ * All rights reserved.
+ *
+ * Written by Matt Thomas for Brocade Communcations, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of Brocade Communications, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROCADE COMMUNICATIONS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL EITHER BROCADE COMMUNICATIONS, INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Fixed many things + ported to RTEMS by Till Straumann, 2005 */
+
+#include <stdio.h>
+#include <rtems.h>
+#include <libcpu/io.h>
+#include <sys/errno.h>
+#include <rtems/bspIo.h>
+#include <rtems/score/sysstate.h>
+#include <bsp/irq.h>
+#include <rtems/libi2c.h>
+
+#include <sys/cdefs.h>
+
+#include <bsp/gtintrreg.h>
+#include <bsp/gti2creg.h>
+#include <bsp/gti2c_busdrv.h>
+
+#define ENABLE_IRQ_AT_PIC_HACK /* workaround for a bad HW bug */
+#undef DEBUG
+
+#ifndef BSP_IRQ_MIN_PRIO
+#define BSP_IRQ_MIN_PRIO 1
+#endif
+
+struct gti2c_softc {
+ uint32_t sc_gt;
+ uint32_t sc_cntl;
+ int sc_inited;
+ rtems_id sc_sync;
+ int sc_irqs; /* statistics */
+};
+
+#ifdef DEBUG
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+typedef struct {
+ rtems_libi2c_bus_t bus_desc;
+ struct gti2c_softc pvt;
+} gti2c_desc_rec, *gti2c_desc;
+
+STATIC rtems_status_code
+gt_i2c_init(rtems_libi2c_bus_t *bh);
+STATIC rtems_status_code
+gt_i2c_send_start(rtems_libi2c_bus_t *bh);
+STATIC rtems_status_code
+gt_i2c_send_stop(rtems_libi2c_bus_t *bh);
+STATIC rtems_status_code
+gt_i2c_send_addr(rtems_libi2c_bus_t *bh, uint32_t addr, int rw);
+STATIC int
+gt_i2c_read_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len);
+STATIC int
+gt_i2c_write_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len);
+
+static rtems_libi2c_bus_ops_t myops = {
+ init: gt_i2c_init,
+ send_start: gt_i2c_send_start,
+ send_stop: gt_i2c_send_stop,
+ send_addr: gt_i2c_send_addr,
+ read_bytes: gt_i2c_read_bytes,
+ write_bytes: gt_i2c_write_bytes,
+};
+
+static gti2c_desc_rec my_bus_tbl = {
+ {
+ ops: &myops,
+ size: sizeof(my_bus_tbl),
+ },/* public fields */
+ {
+ sc_gt: BSP_MV64x60_BASE,
+ sc_cntl: I2C_Control_TWSIEn,
+ sc_inited: 0,
+ sc_sync: 0
+ } /* our private fields */
+};
+
+
+static inline uint32_t
+gt_read(uint32_t base, uint32_t off)
+{
+ return in_le32((volatile uint32_t*)(base+off));
+}
+
+static inline void
+gt_write(uint32_t base, uint32_t off, uint32_t val)
+{
+ out_le32((volatile uint32_t*)(base+off), val);
+}
+
+
+static inline void
+disable_irq(struct gti2c_softc *sc)
+{
+uint32_t v = gt_read(sc->sc_gt, I2C_REG_Control);
+ gt_write(sc->sc_gt, I2C_REG_Control, v & ~I2C_Control_IntEn);
+}
+
+
+static rtems_status_code
+gt_i2c_wait(struct gti2c_softc *sc, uint32_t control, uint32_t desired_status)
+{
+ uint32_t status;
+ rtems_status_code rval;
+
+ control |= I2C_Control_IntEn;
+
+ gt_write(sc->sc_gt, I2C_REG_Control, control | sc->sc_cntl);
+
+ if ( sc->sc_inited ) {
+
+#ifdef ENABLE_IRQ_AT_PIC_HACK
+ BSP_enable_irq_at_pic(BSP_IRQ_I2C);
+#endif
+
+ rval = rtems_semaphore_obtain(sc->sc_sync, RTEMS_WAIT, 100);
+
+ if ( RTEMS_SUCCESSFUL != rval )
+ return rval;
+ } else {
+ uint32_t then, now;
+
+ /* run in polling mode - useful during init */
+ if ( _System_state_Is_up(_System_state_Get()) ) {
+ printk("WARNING: gti2c running in polled mode -- should initialize properly!\n");
+ }
+
+ asm volatile("mftb %0":"=r"(then));
+
+ do {
+ asm volatile("mftb %0":"=r"(now));
+ /* poll timebase for .2 seconds assuming a bus clock of 100MHz */
+ if ( now - then > (uint32_t)100000000/4/5 )
+ return RTEMS_TIMEOUT;
+ } while ( ! (I2C_Control_IFlg & gt_read(sc->sc_gt, I2C_REG_Control)) );
+ }
+
+ status = gt_read(sc->sc_gt, I2C_REG_Status);
+
+ if ( status != desired_status && (status!=I2C_Status_ReStarted || desired_status!=I2C_Status_Started) )
+ return RTEMS_IO_ERROR;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+static void
+gt_i2c_intr(void *arg)
+{
+struct gti2c_softc * const sc = &my_bus_tbl.pvt;
+ uint32_t v;
+
+ v = gt_read(sc->sc_gt, I2C_REG_Control);
+ if ((v & I2C_Control_IFlg) == 0) {
+ printk("gt_i2c_intr: IRQ but IFlg not set??\n");
+ return;
+ }
+ gt_write(sc->sc_gt, I2C_REG_Control, v & ~(I2C_Control_IntEn));
+#if 0
+ gt_read(sc->sc_gt, I2C_REG_Control);
+ asm volatile("sync");
+/* This is how bad it is: after turning off the IntEn bit, the line
+ * still remains asserted! (shame on you.)
+ *
+ * The test below (on MVME6100; the MVME5500 has the same problem
+ * but the main cause register address is different; substitute
+ * 0xf100000c for 0xf1000c68 on a 5500).
+ *
+ * The skew was 101 TB ticks or ~3us (bus freq 133MHz) which
+ * really sucks.
+ *
+ * Therefore, we must disable the interrupt at the PIC
+ */
+{unsigned from,to;
+ asm volatile("mftb %0":"=r"(from));
+ while ( in_le32((volatile uint32_t*)0xf100000c) & 0x20 )
+ ;
+ asm volatile("mftb %0":"=r"(to));
+ printk("I2C IRQ remained asserted for %i TB ticks!\n",to-from);
+}
+#endif
+#ifdef ENABLE_IRQ_AT_PIC_HACK
+ BSP_disable_irq_at_pic(BSP_IRQ_I2C);
+#endif
+
+ sc->sc_irqs++;
+
+ rtems_semaphore_release(sc->sc_sync);
+}
+
+STATIC rtems_status_code
+gt_i2c_init(rtems_libi2c_bus_t *bh)
+{
+struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
+unsigned m,n,N;
+
+ disable_irq(sc);
+
+ /* reset */
+ gt_write(sc->sc_gt, I2C_REG_SoftReset, 0);
+ gt_write(sc->sc_gt, I2C_REG_SlaveAddr, 0);
+ gt_write(sc->sc_gt, I2C_REG_ExtSlaveAddr, 0);
+
+ /* Set baud rate; I don't know the details
+ * but have to assume that it has to fit into 7 bits
+ * (as indicated by some experiment)
+ */
+ n = 0, N=1<<n;
+ do {
+ n++, N<<=1;
+ /* increase 2^n until m becomes small enough */
+ m = BSP_bus_frequency / 10 / 62500 / N;
+ } while ( m > 16 );
+
+ /* n is at least 1 */
+ if ( n > 8 ) {
+ n = 8; m = 16; /* nothing else we can do */
+ }
+ if ( 0 == m )
+ m = 1; /* nothing we can do */
+
+ gt_write(sc->sc_gt, I2C_REG_BaudRate, I2C_BaudRate(m-1, n-1));
+
+ if ( !sc->sc_inited ) {
+
+ if ( _System_state_Is_up(_System_state_Get()) ) {
+ rtems_irq_connect_data ii = {
+ name: BSP_IRQ_I2C,
+ hdl: gt_i2c_intr,
+ on: 0,
+ off: 0,
+ isOn: 0
+ };
+ rtems_status_code err;
+ /* synchronization semaphore */
+ err = rtems_semaphore_create(
+ rtems_build_name('g','i','2','c'),
+ 0,
+ RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_LOCAL,
+ 0,
+ &sc->sc_sync);
+ if ( err ) {
+ sc->sc_sync = 0;
+ return err;
+ }
+ if ( !BSP_install_rtems_irq_handler(&ii) ) {
+ fprintf(stderr,"Unable to install interrupt handler\n");
+ rtems_semaphore_delete(sc->sc_sync);
+ return RTEMS_INTERNAL_ERROR;
+ }
+ BSP_irq_set_priority(BSP_IRQ_I2C, BSP_IRQ_MIN_PRIO);
+ sc->sc_inited = 1;
+ } else {
+ }
+ } else {
+ rtems_semaphore_flush(sc->sc_sync);
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+STATIC rtems_status_code
+gt_i2c_send_start(rtems_libi2c_bus_t *bh)
+{
+struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
+
+ return gt_i2c_wait(sc, I2C_Control_Start, I2C_Status_Started);
+}
+
+STATIC rtems_status_code
+gt_i2c_send_stop(rtems_libi2c_bus_t *bh)
+{
+struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
+uint32_t data;
+
+ data = gt_read(sc->sc_gt, I2C_REG_Status);
+ if ( I2C_Status_Started == data || I2C_Status_ReStarted == data ) {
+ /* According to the spec, a void message (start - stop sequence)
+ * is illegal and indeed, the chip plays bad tricks with us, i.e.,
+ * sometimes it hangs the bus so that it remains idle forever.
+ * so we have to address someone...
+ */
+ gt_i2c_send_addr(bh, /*just something... */ 8, 1);
+ data = gt_read(sc->sc_gt, I2C_REG_Status);
+ }
+
+ if ( I2C_Status_AddrReadAck == data ) {
+ /* Another thing: spec says that the master generates stop only after
+ * not acknowledging the last byte. Again, the chip doesn't like
+ * to be stopped in this condition - hence we just do it the favor
+ * and read a single byte...
+ */
+ gt_i2c_read_bytes(bh, (unsigned char *)&data, 1);
+ }
+
+ gt_write(sc->sc_gt, I2C_REG_Control, I2C_Control_Stop | sc->sc_cntl);
+
+ /* should we poll for idle? There seems to be in IRQ when this completes */
+ return RTEMS_SUCCESSFUL;
+}
+
+STATIC rtems_status_code
+gt_i2c_send_addr(rtems_libi2c_bus_t *bh, uint32_t addr, int rw)
+{
+struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
+uint32_t data, wanted_status;
+uint8_t read_mask = rw ? 1 : 0;
+rtems_status_code error;
+
+ if (read_mask) {
+ wanted_status = I2C_Status_AddrReadAck;
+ } else {
+ wanted_status = I2C_Status_AddrWriteAck;
+ }
+ /*
+ * First byte contains whether this xfer is a read or write.
+ */
+ data = read_mask;
+ if (addr > 0x7f) {
+ /*
+ * If this is a 10bit request, the first address byte is
+ * 0b11110<b9><b8><r/w>.
+ */
+ data |= 0xf0 | ((addr & 0x300) >> 7);
+ gt_write(sc->sc_gt, I2C_REG_Data, data);
+ error = gt_i2c_wait(sc, 0, wanted_status);
+ if (error)
+ return error;
+ /*
+ * The first address byte has been sent, now to send
+ * the second one.
+ */
+ if (read_mask) {
+ wanted_status = I2C_Status_2ndAddrReadAck;
+ } else {
+ wanted_status = I2C_Status_2ndAddrWriteAck;
+ }
+ data = (uint8_t) addr;
+ } else {
+ data |= (addr << 1);
+ }
+
+ gt_write(sc->sc_gt, I2C_REG_Data, data);
+ return gt_i2c_wait(sc, 0, wanted_status);
+}
+
+STATIC int
+gt_i2c_read_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len)
+{
+struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
+rtems_status_code error;
+register unsigned char *p=buf;
+
+ while ( len-- > 0 ) {
+ error = gt_i2c_wait(
+ sc,
+ len ? I2C_Control_ACK : 0,
+ len ? I2C_Status_MasterReadAck : I2C_Status_MasterReadNoAck);
+ if ( error ) {
+ return -error;
+ }
+ *p++ = gt_read(sc->sc_gt, I2C_REG_Data);
+ }
+
+ return p-buf;
+}
+
+STATIC int
+gt_i2c_write_bytes(rtems_libi2c_bus_t *bh, unsigned char *buf, int len)
+{
+struct gti2c_softc * const sc = &((gti2c_desc)bh)->pvt;
+int rval = 0;
+rtems_status_code error;
+
+ while ( len-- > 0 ) {
+ gt_write(sc->sc_gt, I2C_REG_Data, buf[rval]);
+ error = gt_i2c_wait(sc, 0, I2C_Status_MasterWriteAck);
+ if ( error ) {
+ return -error;
+ }
+ rval++;
+ }
+
+ return rval;
+}
+
+rtems_libi2c_bus_t *gt64260_i2c_bus_descriptor = &my_bus_tbl.bus_desc;
+
+#ifdef DEBUG_MODULAR
+
+void
+_cexpModuleInitialize(void *arg)
+{
+ gt_i2c_init(&gt64260_i2c_bus_descriptor->bus_desc);
+}
+
+int
+_cexpModuleFinalize(void * arg)
+{
+struct gti2c_softc * const sc = &gt64260_i2c_bus_descriptor->pvt;
+
+ rtems_irq_connect_data ii = {
+ name: BSP_IRQ_I2C,
+ hdl: gt_i2c_intr,
+ on: noop,
+ off: noop,
+ isOn: inoop
+ };
+
+ rtems_semaphore_delete(sc->sc_sync);
+
+ return !BSP_remove_rtems_irq_handler(&ii);
+}
+
+#endif
diff --git a/bsps/powerpc/beatnik/vme/vme_dma.c b/bsps/powerpc/beatnik/vme/vme_dma.c
new file mode 100644
index 0000000000..29ba3e6bfe
--- /dev/null
+++ b/bsps/powerpc/beatnik/vme/vme_dma.c
@@ -0,0 +1,215 @@
+/* Setup/glue to attach VME DMA driver to the beatnik BSP */
+
+/*
+ * Authorship
+ * ----------
+ * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
+ * created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * The 'beatnik' BSP was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/VME.h>
+#include <bsp/vmeTsi148.h>
+#include <bsp/vmeUniverse.h>
+#include <bsp/VMEDMA.h>
+#include <bsp/vmeTsi148DMA.h>
+#include <bsp/vmeUniverseDMA.h>
+#include <bsp/bspVmeDmaList.h>
+
+typedef struct DmaOpsRec_ {
+ int (*setup)(int, uint32_t, uint32_t, void *);
+ int (*start)(int, uint32_t, uint32_t, uint32_t);
+ uint32_t (*status)(int);
+ VMEDmaListClass listClass;
+} DmaOpsRec, *DmaOps;
+
+static DmaOpsRec universeOps = {
+ vmeUniverseDmaSetup,
+ vmeUniverseDmaStart,
+ vmeUniverseDmaStatus,
+ &vmeUniverseDmaListClass,
+};
+
+static DmaOpsRec tsiOps = {
+ vmeTsi148DmaSetup,
+ vmeTsi148DmaStart,
+ vmeTsi148DmaStatus,
+ &vmeTsi148DmaListClass,
+};
+
+static int setup(int a, uint32_t b, uint32_t c, void *d);
+static int start(int a, uint32_t b, uint32_t c, uint32_t d);
+static uint32_t status(int a);
+
+static DmaOpsRec jumpstartOps = {
+ setup,
+ start,
+ status,
+ 0
+};
+
+static DmaOps dmaOps = &jumpstartOps;
+
+static DmaOps selectOps()
+{
+ return (MVME6100 != BSP_getBoardType()) ?
+ &universeOps : &tsiOps;
+}
+
+static int
+setup(int a, uint32_t b, uint32_t c, void *d)
+{
+ return (dmaOps=selectOps())->setup(a,b,c,d);
+}
+
+static int
+start(int a, uint32_t b, uint32_t c, uint32_t d)
+{
+ return (dmaOps=selectOps())->start(a,b,c,d);
+}
+
+static uint32_t
+status(int a)
+{
+ return (dmaOps=selectOps())->status(a);
+}
+
+
+int
+BSP_VMEDmaSetup(int channel, uint32_t bus_mode, uint32_t xfer_mode, void *custom_setup)
+{
+ return dmaOps->setup(channel, bus_mode, xfer_mode, custom_setup);
+}
+
+int
+BSP_VMEDmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes)
+{
+ return dmaOps->start(channel, pci_addr, vme_addr, n_bytes);
+}
+
+uint32_t
+BSP_VMEDmaStatus(int channel)
+{
+ return dmaOps->status(channel);
+}
+
+BSP_VMEDmaListDescriptor
+BSP_VMEDmaListDescriptorSetup(
+ BSP_VMEDmaListDescriptor d,
+ uint32_t attr_mask,
+ uint32_t xfer_mode,
+ uint32_t pci_addr,
+ uint32_t vme_addr,
+ uint32_t n_bytes)
+{
+VMEDmaListClass pc;
+ if ( !d ) {
+ if ( ! (pc = dmaOps->listClass) ) {
+ pc = (dmaOps = selectOps())->listClass;
+ }
+ return BSP_VMEDmaListDescriptorNewTool(
+ pc,
+ attr_mask,
+ xfer_mode,
+ pci_addr,
+ vme_addr,
+ n_bytes);
+
+ }
+ return BSP_VMEDmaListDescriptorSetupTool(d, attr_mask, xfer_mode, pci_addr, vme_addr, n_bytes);
+}
+
+int
+BSP_VMEDmaListStart(int channel, BSP_VMEDmaListDescriptor list)
+{
+ return BSP_VMEDmaListDescriptorStartTool(0, channel, list);
+}
+
+/* NOT thread safe! */
+int
+BSP_VMEDmaInstallISR(int channel, BSP_VMEDmaIRQCallback cb, void *usr_arg)
+{
+int vec;
+BSP_VME_ISR_t curr;
+void *carg;
+
+ if ( MVME6100 != BSP_getBoardType() ) {
+ if ( channel != 0 )
+ return -1;
+
+ vec = UNIV_DMA_INT_VEC;
+
+ } else {
+ if ( channel < 0 || channel > 1 )
+ return -1;
+
+ vec = (channel ? TSI_DMA1_INT_VEC : TSI_DMA_INT_VEC );
+ }
+
+ curr = BSP_getVME_isr(vec, &carg);
+
+ if ( cb && curr ) {
+ /* IRQ currently in use */
+ return -1;
+ }
+
+ if ( !cb && !curr ) {
+ /* Allow uninstall if no handler is currently installed;
+ * just make sure IRQ is disabled
+ */
+ BSP_disableVME_int_lvl(vec);
+ return 0;
+ }
+
+ if ( cb ) {
+ if ( BSP_installVME_isr(vec, (BSP_VME_ISR_t)cb, usr_arg) )
+ return -4;
+ BSP_enableVME_int_lvl(vec);
+ } else {
+ BSP_disableVME_int_lvl(vec);
+ if ( BSP_removeVME_isr(vec, curr, carg) )
+ return -4;
+ }
+ return 0;
+}
diff --git a/bsps/powerpc/beatnik/vme/vmeconfig.c b/bsps/powerpc/beatnik/vme/vmeconfig.c
new file mode 100644
index 0000000000..383cfc4e96
--- /dev/null
+++ b/bsps/powerpc/beatnik/vme/vmeconfig.c
@@ -0,0 +1,303 @@
+/* Standard VME bridge configuration for MVME5500, MVME6100 */
+
+/*
+ * Authorship
+ * ----------
+ * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
+ * created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * The 'beatnik' BSP was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+#include <rtems.h>
+#include <rtems/bspIo.h>
+#include <bsp.h>
+#include <bsp/VME.h>
+#include <bsp/VMEConfig.h>
+#include <bsp/irq.h>
+#include <bsp/vmeUniverse.h>
+#define _VME_TSI148_DECLARE_SHOW_ROUTINES
+#include <bsp/vmeTsi148.h>
+#include <libcpu/bat.h>
+
+/* Use a weak alias for the VME configuration.
+ * This permits individual applications to override
+ * this routine.
+ * They may even create an 'empty'
+ *
+ * void BSP_vme_config(void) {}
+ *
+ * which will avoid linking in the Universe driver
+ * at all :-).
+ */
+
+void BSP_vme_config(void) __attribute__ (( weak, alias("__BSP_default_vme_config") ));
+
+typedef struct {
+ int (*xlate_adrs)(int, int, unsigned long, unsigned long, unsigned long *);
+ int (*install_isr)(unsigned long, BSP_VME_ISR_t, void *);
+ int (*remove_isr)(unsigned long, BSP_VME_ISR_t, void *);
+ BSP_VME_ISR_t (*get_isr)(unsigned long vector, void **);
+ int (*enable_int_lvl)(unsigned int);
+ int (*disable_int_lvl)(unsigned int);
+ int (*outbound_p_cfg)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
+ int (*inbound_p_cfg) (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
+ void (*outbound_p_show)(FILE*);
+ void (*inbound_p_show) (FILE*);
+ void (*reset_bus)(void);
+ int (*install_irq_mgr)(int, int, int, ...);
+} VMEOpsRec, *VMEOps;
+
+static VMEOpsRec uniOpsRec = {
+ xlate_adrs: vmeUniverseXlateAddr,
+ install_isr: vmeUniverseInstallISR,
+ remove_isr: vmeUniverseRemoveISR,
+ get_isr: vmeUniverseISRGet,
+ enable_int_lvl: vmeUniverseIntEnable,
+ disable_int_lvl: vmeUniverseIntDisable,
+ outbound_p_cfg: vmeUniverseMasterPortCfg,
+ inbound_p_cfg: vmeUniverseSlavePortCfg,
+ outbound_p_show: vmeUniverseMasterPortsShow,
+ inbound_p_show: vmeUniverseSlavePortsShow,
+ reset_bus: vmeUniverseResetBus,
+ install_irq_mgr: vmeUniverseInstallIrqMgrAlt,
+};
+
+static VMEOpsRec tsiOpsRec = {
+ xlate_adrs: vmeTsi148XlateAddr,
+ install_isr: vmeTsi148InstallISR,
+ remove_isr: vmeTsi148RemoveISR,
+ get_isr: vmeTsi148ISRGet,
+ enable_int_lvl: vmeTsi148IntEnable,
+ disable_int_lvl: vmeTsi148IntDisable,
+ outbound_p_cfg: vmeTsi148OutboundPortCfg,
+ inbound_p_cfg: vmeTsi148InboundPortCfg,
+ outbound_p_show: vmeTsi148OutboundPortsShow,
+ inbound_p_show: vmeTsi148InboundPortsShow,
+ reset_bus: vmeTsi148ResetBus,
+ install_irq_mgr: vmeTsi148InstallIrqMgrAlt,
+};
+
+static VMEOps theOps = 0;
+
+int
+BSP_vme2local_adrs(unsigned long am, unsigned long vmeaddr, unsigned long *plocaladdr)
+{
+int rval=theOps->xlate_adrs(1,0,am,vmeaddr,plocaladdr);
+ *plocaladdr+=PCI_MEM_BASE;
+ return rval;
+}
+
+int
+BSP_local2vme_adrs(unsigned long am, unsigned long localaddr, unsigned long *pvmeaddr)
+{
+ return theOps->xlate_adrs(0, 0, am,localaddr+PCI_DRAM_OFFSET,pvmeaddr);
+}
+
+int
+BSP_installVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *arg)
+{
+ return theOps->install_isr(vector, handler, arg);
+}
+
+int
+BSP_removeVME_isr(unsigned long vector, BSP_VME_ISR_t handler, void *arg)
+{
+ return theOps->remove_isr(vector, handler, arg);
+}
+
+/* retrieve the currently installed ISR for a given vector */
+BSP_VME_ISR_t
+BSP_getVME_isr(unsigned long vector, void **parg)
+{
+ return theOps->get_isr(vector, parg);
+}
+
+int
+BSP_enableVME_int_lvl(unsigned int level)
+{
+ return theOps->enable_int_lvl(level);
+}
+
+int
+BSP_disableVME_int_lvl(unsigned int level)
+{
+ return theOps->disable_int_lvl(level);
+}
+
+int
+BSP_VMEOutboundPortCfg(
+ unsigned long port,
+ unsigned long address_space,
+ unsigned long vme_address,
+ unsigned long pci_address,
+ unsigned long size)
+{
+ return theOps->outbound_p_cfg(port, address_space, vme_address, pci_address, size);
+}
+
+int
+BSP_VMEInboundPortCfg(
+ unsigned long port,
+ unsigned long address_space,
+ unsigned long vme_address,
+ unsigned long pci_address,
+ unsigned long size)
+{
+ return theOps->inbound_p_cfg(port, address_space, vme_address, pci_address, size);
+}
+
+void
+BSP_VMEOutboundPortsShow(FILE *f)
+{
+ theOps->outbound_p_show(f);
+}
+
+void
+BSP_VMEInboundPortsShow(FILE *f)
+{
+ theOps->inbound_p_show(f);
+}
+
+void
+BSP_VMEResetBus(void)
+{
+ theOps->reset_bus();
+}
+
+static unsigned short
+tsi_clear_errors(int quiet)
+{
+unsigned long v;
+unsigned short rval;
+ v = vmeTsi148ClearVMEBusErrors(0);
+
+ /* return bits 8..23 of VEAT; set bit 15 to make sure rval is nonzero on error */
+ rval = v ? ((v>>8) & 0xffff) | (1<<15) : 0;
+ return rval;
+}
+
+void
+__BSP_default_vme_config(void)
+{
+int err = 1;
+ if ( 0 == vmeUniverseInit() ) {
+ theOps = &uniOpsRec;
+ vmeUniverseReset();
+ } else if ( 0 == vmeTsi148Init() ) {
+ theOps = &tsiOpsRec;
+ vmeTsi148Reset();
+ _BSP_clear_vmebridge_errors = tsi_clear_errors;
+ } else
+ return; /* no VME bridge found chip */
+
+ /* map VME address ranges */
+ BSP_VMEOutboundPortCfg(
+ 0,
+ VME_AM_EXT_SUP_DATA,
+ _VME_A32_WIN0_ON_VME,
+ _VME_A32_WIN0_ON_PCI,
+ 0x0e000000
+ );
+ BSP_VMEOutboundPortCfg(
+ 1,
+ VME_AM_STD_SUP_DATA,
+ 0x00000000,
+ _VME_A24_ON_PCI,
+ 0x00ff0000);
+ BSP_VMEOutboundPortCfg(
+ 2,
+ VME_AM_SUP_SHORT_IO,
+ 0x00000000,
+ _VME_A16_ON_PCI,
+ 0x00010000);
+
+#ifdef _VME_CSR_ON_PCI
+ /* Map VME64 CSR */
+ BSP_VMEOutboundPortCfg(
+ 7,
+ VME_AM_CSR,
+ 0,
+ _VME_CSR_ON_PCI,
+ 0x01000000);
+#endif
+
+#ifdef _VME_DRAM_OFFSET
+ /* map our memory to VME */
+ BSP_VMEInboundPortCfg(
+ 0,
+ VME_AM_EXT_SUP_DATA | VME_AM_IS_MEMORY,
+ _VME_DRAM_OFFSET,
+ PCI_DRAM_OFFSET,
+ BSP_mem_size);
+#endif
+
+ /* stdio is not yet initialized; the driver will revert to printk */
+ BSP_VMEOutboundPortsShow(0);
+ BSP_VMEInboundPortsShow(0);
+
+ switch (BSP_getBoardType()) {
+ case MVME6100:
+ err = theOps->install_irq_mgr(
+ VMETSI148_IRQ_MGR_FLAG_SHARED,
+ 0, BSP_IRQ_GPP_0 + 20,
+ 1, BSP_IRQ_GPP_0 + 21,
+ 2, BSP_IRQ_GPP_0 + 22,
+ 3, BSP_IRQ_GPP_0 + 23,
+ -1);
+ break;
+
+ case MVME5500:
+ err = theOps->install_irq_mgr(
+ VMEUNIVERSE_IRQ_MGR_FLAG_SHARED |
+ VMEUNIVERSE_IRQ_MGR_FLAG_PW_WORKAROUND,
+ 0, BSP_IRQ_GPP_0 + 12,
+ 1, BSP_IRQ_GPP_0 + 13,
+ 2, BSP_IRQ_GPP_0 + 14,
+ 3, BSP_IRQ_GPP_0 + 15,
+ -1);
+ break;
+
+ default:
+ printk("WARNING: unknown board; ");
+ break;
+ }
+ if ( err )
+ printk("VME interrupt manager NOT INSTALLED (error: %i)\n", err);
+}