diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/boot/common/ns16550.c linux-2.6.14.mod/arch/ppc/boot/common/ns16550.c --- linux-2.6.14.orig/arch/ppc/boot/common/ns16550.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/boot/common/ns16550.c 2006-02-02 17:22:11.000000000 -0700 @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "nonstdio.h" @@ -15,6 +16,16 @@ extern unsigned long ISA_io; +#ifdef CONFIG_MVME3100 + +#define SERIAL_PORT_DFNS \ + { 0, MVME3100_BASE_BAUD / 16, 0, \ + MPC85xx_IRQ_DUART, \ + (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ + iomem_base: (u8 *)MPC85XX_0_SERIAL, \ + io_type: SERIAL_IO_MEM}, +#endif + static struct serial_state rs_table[RS_TABLE_SIZE] = { SERIAL_PORT_DFNS /* Defined in */ }; @@ -46,6 +57,7 @@ /* Base baud.. */ base_baud = rs_table[chan].baud_base; +#ifndef CONFIG_MVME3100 /* save the LCR */ lcr = inb(com_port + (UART_LCR << shift)); /* Access baud rate */ @@ -74,6 +86,7 @@ } /* Clear & enable FIFOs */ outb(com_port + (UART_FCR << shift), 0x07); +#endif return (com_port); } diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/boot/common/util.S linux-2.6.14.mod/arch/ppc/boot/common/util.S --- linux-2.6.14.orig/arch/ppc/boot/common/util.S 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/boot/common/util.S 2005-11-16 10:40:20.000000000 -0700 @@ -254,6 +254,11 @@ addi r3,r3,0x10 # Increment by one cache line cmplw cr0,r3,r4 # Are we at the end yet? blt 1b # No, keep flushing and invalidating +#elif CONFIG_FSL_BOOKE + mfspr r3,SPRN_L1CSR1 + ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR + mtspr SPRN_L1CSR1,r3 + isync #else /* Enable, invalidate and then disable the L1 icache/dcache. */ li r3,0 diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/boot/simple/embed_config.c linux-2.6.14.mod/arch/ppc/boot/simple/embed_config.c --- linux-2.6.14.orig/arch/ppc/boot/simple/embed_config.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/boot/simple/embed_config.c 2005-11-16 10:40:20.000000000 -0700 @@ -18,6 +18,9 @@ #include #include #endif +#ifdef CONFIG_MVME3100 +#include +#endif #ifdef CONFIG_40x #include #endif @@ -370,6 +373,24 @@ } #endif /* BSEIP */ +#ifdef CONFIG_MVME3100 + +void +embed_config(bd_t **bdp) +{ + bd_t *bd; + bd = &bdinfo; + + memcpy(bd, *bdp, sizeof(bd_t)); + bd->bi_intfreq *= 1000000; + bd->bi_busfreq *= 1000000; + *bdp = bd; + + return; +} + +#endif /* CONFIG_MVME3100 */ + #ifdef CONFIG_FADS /* Build a board information structure for the FADS. */ diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/boot/simple/head.S linux-2.6.14.mod/arch/ppc/boot/simple/head.S --- linux-2.6.14.orig/arch/ppc/boot/simple/head.S 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/boot/simple/head.S 2005-11-16 10:40:20.000000000 -0700 @@ -57,7 +57,7 @@ isync #endif -#if defined(CONFIG_MBX) || defined(CONFIG_RPX8260) || defined(CONFIG_PPC_PREP) +#if defined(CONFIG_MBX) || defined(CONFIG_RPX8260) || defined(CONFIG_PPC_PREP) || defined(CONFIG_MVME3100) mr r29,r3 /* On the MBX860, r3 is the board info pointer. * On the RPXSUPER, r3 points to the NVRAM * configuration keys. @@ -120,7 +120,7 @@ mtspr SPRN_DER,r4 #endif -#if defined(CONFIG_MBX) || defined(CONFIG_RPX8260) || defined(CONFIG_PPC_PREP) +#if defined(CONFIG_MBX) || defined(CONFIG_RPX8260) || defined(CONFIG_PPC_PREP) || defined(CONFIG_MVME3100) mr r4,r29 /* put the board info pointer where the relocate * routine will find it */ diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/boot/simple/Makefile linux-2.6.14.mod/arch/ppc/boot/simple/Makefile --- linux-2.6.14.orig/arch/ppc/boot/simple/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/boot/simple/Makefile 2006-01-20 16:58:39.000000000 -0700 @@ -110,11 +110,14 @@ # kconfig 'feature', only one of these will ever be 'y' at a time. # The rest will be unset. -motorola := $(CONFIG_MVME5100)$(CONFIG_PRPMC750) \ -$(CONFIG_PRPMC800)$(CONFIG_LOPEC)$(CONFIG_PPLUS) +motorola := $(CONFIG_MCPN765)$(CONFIG_MVME5100)$(CONFIG_PRPMC750) \ +$(CONFIG_PRPMC800)$(CONFIG_LOPEC)$(CONFIG_PPLUS)$(CONFIG_MVME6100) \ +$(CONFIG_MCP905)$(CONFIG_MVME3100)$(CONFIG_MVME5500) motorola := $(strip $(motorola)) zimage-$(motorola) := zImage-PPLUS + extra.o-$(CONFIG_MVME6100) := misc-mvme6100.o + extra.o-$(CONFIG_MCP905) := misc-mcp905.o zimageinitrd-$(motorola) := zImage.initrd-PPLUS end-$(motorola) := pplus @@ -145,7 +148,6 @@ end-$(CONFIG_LITE5200) := lite5200 cacheflag-$(CONFIG_LITE5200) := -include $(clear_L2_L3) - # SMP images should have a '.smp' suffix. end-$(CONFIG_SMP) := $(end-y).smp @@ -165,6 +167,7 @@ boot-$(CONFIG_40x) += embed_config.o boot-$(CONFIG_8xx) += embed_config.o boot-$(CONFIG_8260) += embed_config.o +boot-$(CONFIG_MVME3100) += embed_config.o boot-$(CONFIG_BSEIP) += iic.o boot-$(CONFIG_MBX) += iic.o pci.o qspan_pci.o boot-$(CONFIG_MV64X60) += misc-mv64x60.o @@ -245,8 +248,8 @@ $(images)/zImage-PPLUS: $(obj)/zvmlinux $(MKPREP) $(MKBUGBOOT) $(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.$(end-y) - $(MKBUGBOOT) $(obj)/zvmlinux $(images)/zImage.bugboot +# $(MKBUGBOOT) $(obj)/zvmlinux $(images)/zImage.bugboot $(images)/zImage.initrd-PPLUS: $(obj)/zvmlinux.initrd $(MKPREP) $(MKBUGBOOT) $(MKPREP) -pbp $(obj)/zvmlinux.initrd $(images)/zImage.initrd.$(end-y) - $(MKBUGBOOT) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.bugboot +# $(MKBUGBOOT) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.bugboot diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/boot/simple/misc-embedded.c linux-2.6.14.mod/arch/ppc/boot/simple/misc-embedded.c --- linux-2.6.14.orig/arch/ppc/boot/simple/misc-embedded.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/boot/simple/misc-embedded.c 2005-11-16 10:40:20.000000000 -0700 @@ -19,10 +19,20 @@ #include #elif defined(CONFIG_8260) #include +#elif defined(CONFIG_85xx) +#include #endif #include "nonstdio.h" +#define MVME3100_SYSTEM_CONTROL_REG 0xE2000001 +#define MVME3100_BOARD_RESET 0xA0 + +static inline void out_8(volatile unsigned char *addr, int val) +{ + __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +} + /* The linker tells us where the image is. */ extern char __image_begin, __image_end; extern char __ramdisk_begin, __ramdisk_end; @@ -86,6 +96,7 @@ int timer = 0, zimage_size; unsigned long initrd_size; + /* First, capture the embedded board information. Then * initialize the serial console port. */ @@ -133,6 +144,42 @@ puts(" "); puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t))); puts("\n"); +#if 0 + puts("immr base: "); puthex((unsigned long)bp->bi_immr_base); + puts("\n"); + puts("baud rate: "); puthex((unsigned long)bp->bi_baudrate); + puts("\n"); + puts("mem size: "); puthex((unsigned long)bp->bi_memsize); + puts("\n"); + puts("int freq: "); puthex((unsigned long)bp->bi_intfreq); + puts("\n"); + puts("bus freq: "); puthex((unsigned long)bp->bi_busfreq); + puts("\n"); + puts("eth0 : "); + puthex((unsigned long)bp->bi_enetaddr[0]); + puthex((unsigned long)bp->bi_enetaddr[1]); + puthex((unsigned long)bp->bi_enetaddr[2]); + puthex((unsigned long)bp->bi_enetaddr[3]); + puthex((unsigned long)bp->bi_enetaddr[4]); + puthex((unsigned long)bp->bi_enetaddr[5]); + puts("\n"); + puts("eth1 : "); + puthex((unsigned long)bp->bi_enet1addr[0]); + puthex((unsigned long)bp->bi_enet1addr[1]); + puthex((unsigned long)bp->bi_enet1addr[2]); + puthex((unsigned long)bp->bi_enet1addr[3]); + puthex((unsigned long)bp->bi_enet1addr[4]); + puthex((unsigned long)bp->bi_enet1addr[5]); + puts("\n"); + puts("eth2 : "); + puthex((unsigned long)bp->bi_enet2addr[0]); + puthex((unsigned long)bp->bi_enet2addr[1]); + puthex((unsigned long)bp->bi_enet2addr[2]); + puthex((unsigned long)bp->bi_enet2addr[3]); + puthex((unsigned long)bp->bi_enet2addr[4]); + puthex((unsigned long)bp->bi_enet2addr[5]); + puts("\n"); +#endif } /* @@ -214,6 +261,7 @@ puts("\nUncompressing Linux..."); gunzip(0, 0x400000, zimage_start, &zimage_size); +// out_8((char *)MVME3100_SYSTEM_CONTROL_REG, MVME3100_BOARD_RESET); flush_instruction_cache(); puts("done.\n"); { diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/boot/simple/misc-mcp905.S linux-2.6.14.mod/arch/ppc/boot/simple/misc-mcp905.S --- linux-2.6.14.orig/arch/ppc/boot/simple/misc-mcp905.S 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/boot/simple/misc-mcp905.S 2006-01-26 12:06:57.000000000 -0700 @@ -0,0 +1,68 @@ +/* + * arch/ppc/boot/simple/misc-mcp905.S + * + * Host bridge init code for the MCP905 board + * + * Ajit Prem + * Based on code written by Rabeeh Khoury - rabeeh@galileo.co.il + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include + +#include "../../platforms/mcp905.h" + +#define MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port) (0x2680 + (port<<10)) + +#define _64K 0x00010000 + + .globl mcp905_init +mcp905_init: + li r20,0 + li r23,16 + + + /* stack in cache - cache touch and invalidate first 2MByte */ + /* R24 = 2MByte */ + lis r24, 0x0020 + /* R25 = 0 (the counter */ + lis r25,0x0 + /* R26 = 0x80000000 - BAT offset mapping physical memory at offset 0x0 - cacheable */ + lis r26,0x8000 + +1: dcbf r26,r25 + icbi r26,r25 + addi r25,r25,32 + cmplw r25,r24 + ble 1b + + /* Stop GigE Rx DMA engines */ + addis r25,0,MCP905_BRIDGE_REG_BASE@h + ori r25,r25,MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0) + addis r26,0,0 + ori r26,r26,0xff00 + stwbrx r26,0,(r25) + sync + + addis r25,0,MCP905_BRIDGE_REG_BASE@h + ori r25,r25,MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1) + addis r26,0,0 + ori r26,r26,0xff00 + stwbrx r26,0,(r25) + sync + + addis r25,0,MCP905_BRIDGE_REG_BASE@h + ori r25,r25,MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2) + addis r26,0,0 + ori r26,r26,0xff00 + stwbrx r26,0,(r25) + sync + + blr diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/boot/simple/misc-mvme6100.S linux-2.6.14.mod/arch/ppc/boot/simple/misc-mvme6100.S --- linux-2.6.14.orig/arch/ppc/boot/simple/misc-mvme6100.S 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/boot/simple/misc-mvme6100.S 2006-01-26 12:07:09.000000000 -0700 @@ -0,0 +1,68 @@ +/* + * arch/ppc/boot/simple/misc-mvme6100.S + * + * Host bridge init code for the MVME6100 board + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include + +#include "../../platforms/mvme6100.h" + +#define MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port) (0x2680 + (port<<10)) + +#define _64K 0x00010000 + + .globl mvme6100_init +mvme6100_init: + li r20,0 + li r23,16 + + + /* stack in cache - cache touch and invalidate first 2MByte */ + /* R24 = 2MByte */ + lis r24, 0x0020 + /* R25 = 0 (the counter */ + lis r25,0x0 + /* R26 = 0x80000000 - BAT offset mapping physical memory at offset 0x0 - cacheable */ + lis r26,0x8000 + +1: dcbf r26,r25 + icbi r26,r25 + addi r25,r25,32 + cmplw r25,r24 + ble 1b + + /* Stop GigE Rx DMA engines */ + addis r25,0,MVME6100_BRIDGE_REG_BASE@h + ori r25,r25,MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0) + addis r26,0,0 + ori r26,r26,0xff00 + stwbrx r26,0,(r25) + sync + + addis r25,0,MVME6100_BRIDGE_REG_BASE@h + ori r25,r25,MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1) + addis r26,0,0 + ori r26,r26,0xff00 + stwbrx r26,0,(r25) + sync + + addis r25,0,MVME6100_BRIDGE_REG_BASE@h + ori r25,r25,MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2) + addis r26,0,0 + ori r26,r26,0xff00 + stwbrx r26,0,(r25) + sync + + blr + + diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/configs/mcp905_defconfig linux-2.6.14.mod/arch/ppc/configs/mcp905_defconfig --- linux-2.6.14.orig/arch/ppc/configs/mcp905_defconfig 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/configs/mcp905_defconfig 2006-04-10 16:20:42.000000000 -0700 @@ -0,0 +1,1200 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.14 +# Mon Apr 10 16:16:23 2006 +# +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y + +# +# Processor +# +CONFIG_6xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +# CONFIG_E500 is not set +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +# CONFIG_TAU is not set +# CONFIG_KEXEC is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_PPC_GEN550=y +CONFIG_PPC_STD_MMU=y +# CONFIG_NOT_COHERENT_CACHE is not set + +# +# Platform options +# +# CONFIG_PPC_MULTIPLATFORM is not set +# CONFIG_APUS is not set +# CONFIG_KATANA is not set +# CONFIG_WILLOW is not set +# CONFIG_CPCI690 is not set +# CONFIG_POWERPMC250 is not set +# CONFIG_CHESTNUT is not set +# CONFIG_SPRUCE is not set +# CONFIG_HDPU is not set +# CONFIG_EV64260 is not set +# CONFIG_LOPEC is not set +# CONFIG_MVME5100 is not set +# CONFIG_MVME5500 is not set +# CONFIG_MVME6100 is not set +CONFIG_MCP905=y +# CONFIG_PPLUS is not set +# CONFIG_PRPMC750 is not set +# CONFIG_PRPMC800 is not set +# CONFIG_SANDPOINT is not set +# CONFIG_RADSTONE_PPC7D is not set +# CONFIG_PAL4 is not set +# CONFIG_GEMINI is not set +# CONFIG_EST8260 is not set +# CONFIG_SBC82xx is not set +# CONFIG_SBS8260 is not set +# CONFIG_RPX8260 is not set +# CONFIG_TQM8260 is not set +# CONFIG_ADS8272 is not set +# CONFIG_PQ2FADS is not set +# CONFIG_LITE5200 is not set +# CONFIG_MPC834x_SYS is not set +# CONFIG_EV64360 is not set +CONFIG_MV64360=y +CONFIG_MV64X60=y + +# +# Set bridge options +# +CONFIG_MV64X60_BASE=0xf1000000 +CONFIG_MV64X60_NEW_BASE=0xf1000000 +# CONFIG_MV64X60_USE_SRAM is not set +# CONFIG_SMP is not set +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_BKL=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/sda2" +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Advanced setup +# +CONFIG_ADVANCED_OPTIONS=y +# CONFIG_HIGHMEM_START_BOOL is not set +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE_BOOL=y +CONFIG_LOWMEM_SIZE=0x40000000 +CONFIG_KERNEL_START_BOOL=y +CONFIG_KERNEL_START=0x90000000 +# CONFIG_TASK_SIZE_BOOL is not set +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD_BOOL=y +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_NETLINK is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +# CONFIG_MTD_CFI_I1 is not set +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +CONFIG_MTD_ROM=y +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PLATRAM is not set +CONFIG_MTD_MCP905=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_LBD=y +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +CONFIG_SCSI_SATA=y +# CONFIG_SCSI_SATA_AHCI is not set +# CONFIG_SCSI_SATA_SVW is not set +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_MV is not set +# CONFIG_SCSI_SATA_NV is not set +CONFIG_SCSI_PATA_PDC2027X=y +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_QSTOR is not set +# CONFIG_SCSI_SATA_SX4 is not set +# CONFIG_SCSI_SATA_SIL is not set +# CONFIG_SCSI_SATA_SIS is not set +# CONFIG_SCSI_SATA_ULI is not set +# CONFIG_SCSI_SATA_VIA is not set +# CONFIG_SCSI_SATA_VITESSE is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA24XX is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +CONFIG_TULIP=y +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +CONFIG_TULIP_NAPI=y +CONFIG_TULIP_NAPI_HW_MITIGATION=y +# CONFIG_DE4X5 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +# CONFIG_ULI526X is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_MV643XX_ETH=y +CONFIG_MV643XX_ETH_0=y +CONFIG_MV643XX_ETH_1=y +CONFIG_MV643XX_ETH_2=y + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MPSC is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_NVRAM_M48TXXX=y +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_MPC is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_MV64XXX=y + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_DS1375 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +CONFIG_SENSORS_DS1621=y +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +CONFIG_MV64360_IDMA=y + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# SN Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_KGDB is not set +CONFIG_XMON=y +# CONFIG_BDI_SWITCH is not set +# CONFIG_SERIAL_TEXT_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/configs/mvme3100_defconfig linux-2.6.14.mod/arch/ppc/configs/mvme3100_defconfig --- linux-2.6.14.orig/arch/ppc/configs/mvme3100_defconfig 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/configs/mvme3100_defconfig 2006-02-16 13:09:54.000000000 -0700 @@ -0,0 +1,1309 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.14 +# Tue Feb 14 17:07:49 2006 +# +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y + +# +# Processor +# +# CONFIG_6xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_E500=y +CONFIG_BOOKE=y +CONFIG_FSL_BOOKE=y +# CONFIG_PHYS_64BIT is not set +CONFIG_SPE=y +CONFIG_MATH_EMULATION=y +# CONFIG_KEXEC is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_EMBEDDEDBOOT=y +CONFIG_PPC_GEN550=y +CONFIG_85xx=y +CONFIG_PPC_INDIRECT_PCI_BE=y + +# +# Freescale 85xx options +# +# CONFIG_MPC8540_ADS is not set +# CONFIG_MPC8548_CDS is not set +# CONFIG_MPC8555_CDS is not set +# CONFIG_MPC8560_ADS is not set +# CONFIG_SBC8560 is not set +# CONFIG_STX_GP3 is not set +CONFIG_MVME3100=y +CONFIG_MPC8540=y + +# +# Platform options +# +CONFIG_UBOOT=y +CONFIG_MVME3100_ENABLE_DDR_ERRORS=y +CONFIG_MVME3100_ENABLE_L2_ERRORS=y +CONFIG_MVME3100_ENABLE_PCI_ERRORS=y +CONFIG_MVME3100_TICK_TIMERS=y +CONFIG_MPC85xx_DMA=y +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/sda2" +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Advanced setup +# +CONFIG_ADVANCED_OPTIONS=y +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE_BOOL=y +CONFIG_LOWMEM_SIZE=0x40000000 +CONFIG_KERNEL_START_BOOL=y +CONFIG_KERNEL_START=0xa0000000 +# CONFIG_TASK_SIZE_BOOL is not set +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD_BOOL=y +CONFIG_BOOT_LOAD=0x00400000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_NETLINK is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +# CONFIG_MTD_CFI_I1 is not set +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_AMDSTD_RETRY=0 +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +CONFIG_MTD_ROM=y +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set +CONFIG_MTD_MVME3100=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +CONFIG_SCSI_SATA=y +# CONFIG_SCSI_SATA_AHCI is not set +# CONFIG_SCSI_SATA_SVW is not set +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_MV is not set +# CONFIG_SCSI_SATA_NV is not set +CONFIG_SCSI_PATA_PDC2027X=y +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_QSTOR is not set +# CONFIG_SCSI_SATA_SX4 is not set +# CONFIG_SCSI_SATA_SIL is not set +# CONFIG_SCSI_SATA_SIS is not set +# CONFIG_SCSI_SATA_ULI is not set +# CONFIG_SCSI_SATA_VIA is not set +CONFIG_SCSI_SATA_VITESSE=y +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA24XX is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +CONFIG_TULIP=y +CONFIG_TULIP_MWI=y +# CONFIG_TULIP_MMIO is not set +CONFIG_TULIP_NAPI=y +CONFIG_TULIP_NAPI_HW_MITIGATION=y +# CONFIG_DE4X5 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +# CONFIG_ULI526X is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +CONFIG_EEPRO100=y +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +CONFIG_GFAR_NAPI=y + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=5 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_BOOKE_WDT=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# VME Bridge devices +# +CONFIG_VME_BRIDGE=y + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_DS1375=y +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +CONFIG_SENSORS_DS1621=y +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set +CONFIG_USB_EHCI_ROOT_HUB_TT=y +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +CONFIG_USB_STORAGE_DPCM=y +# CONFIG_USB_STORAGE_USBAT is not set +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# SN Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_FS is not set +# CONFIG_KGDB is not set +# CONFIG_XMON is not set +CONFIG_BDI_SWITCH=y +# CONFIG_SERIAL_TEXT_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/configs/mvme5500_defconfig linux-2.6.14.mod/arch/ppc/configs/mvme5500_defconfig --- linux-2.6.14.orig/arch/ppc/configs/mvme5500_defconfig 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/configs/mvme5500_defconfig 2006-04-10 16:20:57.000000000 -0700 @@ -0,0 +1,1205 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.14 +# Mon Apr 10 14:55:34 2006 +# +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y + +# +# Processor +# +CONFIG_6xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +# CONFIG_E500 is not set +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +# CONFIG_TAU is not set +# CONFIG_KEXEC is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_PPC_GEN550=y +CONFIG_PPC_STD_MMU=y +# CONFIG_NOT_COHERENT_CACHE is not set + +# +# Platform options +# +# CONFIG_PPC_MULTIPLATFORM is not set +# CONFIG_APUS is not set +# CONFIG_KATANA is not set +# CONFIG_WILLOW is not set +# CONFIG_CPCI690 is not set +# CONFIG_POWERPMC250 is not set +# CONFIG_CHESTNUT is not set +# CONFIG_SPRUCE is not set +# CONFIG_HDPU is not set +# CONFIG_EV64260 is not set +# CONFIG_LOPEC is not set +# CONFIG_MVME5100 is not set +CONFIG_MVME5500=y +# CONFIG_MVME6100 is not set +# CONFIG_MCP905 is not set +# CONFIG_PPLUS is not set +# CONFIG_PRPMC750 is not set +# CONFIG_PRPMC800 is not set +# CONFIG_SANDPOINT is not set +# CONFIG_RADSTONE_PPC7D is not set +# CONFIG_PAL4 is not set +# CONFIG_GEMINI is not set +# CONFIG_EST8260 is not set +# CONFIG_SBC82xx is not set +# CONFIG_SBS8260 is not set +# CONFIG_RPX8260 is not set +# CONFIG_TQM8260 is not set +# CONFIG_ADS8272 is not set +# CONFIG_PQ2FADS is not set +# CONFIG_LITE5200 is not set +# CONFIG_MPC834x_SYS is not set +# CONFIG_EV64360 is not set +CONFIG_GT64260=y +CONFIG_MV64X60=y + +# +# Set bridge options +# +CONFIG_MV64X60_BASE=0xf1000000 +CONFIG_MV64X60_NEW_BASE=0xf1000000 +# CONFIG_MV64X60_USE_SRAM is not set +# CONFIG_SMP is not set +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_BKL=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/sda2" +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Advanced setup +# +CONFIG_ADVANCED_OPTIONS=y +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE_BOOL=y +CONFIG_LOWMEM_SIZE=0x40000000 +CONFIG_KERNEL_START_BOOL=y +CONFIG_KERNEL_START=0xa0000000 +# CONFIG_TASK_SIZE_BOOL is not set +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD_BOOL=y +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_NETLINK is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +# CONFIG_MTD_CFI_I1 is not set +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +CONFIG_MTD_ROM=y +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PLATRAM is not set +CONFIG_MTD_MVME5500=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_LBD=y +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +CONFIG_SCSI_SATA=y +# CONFIG_SCSI_SATA_AHCI is not set +# CONFIG_SCSI_SATA_SVW is not set +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_MV is not set +# CONFIG_SCSI_SATA_NV is not set +CONFIG_SCSI_PATA_PDC2027X=y +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_QSTOR is not set +# CONFIG_SCSI_SATA_SX4 is not set +# CONFIG_SCSI_SATA_SIL is not set +# CONFIG_SCSI_SATA_SIS is not set +# CONFIG_SCSI_SATA_ULI is not set +# CONFIG_SCSI_SATA_VIA is not set +# CONFIG_SCSI_SATA_VITESSE is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA24XX is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_GT64260_ETH=y +CONFIG_GT64260_ETH_0=y +CONFIG_GT64260_ETH_0_MACADDR="0001AF12C9E0" +# CONFIG_GT64260_ETH_1 is not set +# CONFIG_GT64260_ETH_2 is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +CONFIG_TULIP=y +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +CONFIG_TULIP_NAPI=y +CONFIG_TULIP_NAPI_HW_MITIGATION=y +# CONFIG_DE4X5 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +# CONFIG_ULI526X is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MPSC is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_SDD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_NVRAM_M48TXXX=y +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# VME Bridge devices +# +CONFIG_VME_BRIDGE=y + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_MPC is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_MV64XXX=y +CONFIG_I2C_GT64260=y + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_DS1375 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +CONFIG_SENSORS_DS1621=y +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# SN Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_KGDB is not set +CONFIG_XMON=y +# CONFIG_BDI_SWITCH is not set +# CONFIG_SERIAL_TEXT_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/configs/mvme6100_defconfig linux-2.6.14.mod/arch/ppc/configs/mvme6100_defconfig --- linux-2.6.14.orig/arch/ppc/configs/mvme6100_defconfig 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/configs/mvme6100_defconfig 2006-04-10 16:21:06.000000000 -0700 @@ -0,0 +1,1206 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.14 +# Mon Apr 10 15:04:17 2006 +# +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y + +# +# Processor +# +CONFIG_6xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +# CONFIG_E500 is not set +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +# CONFIG_TAU is not set +# CONFIG_KEXEC is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_PPC_GEN550=y +CONFIG_PPC_STD_MMU=y +# CONFIG_NOT_COHERENT_CACHE is not set + +# +# Platform options +# +# CONFIG_PPC_MULTIPLATFORM is not set +# CONFIG_APUS is not set +# CONFIG_KATANA is not set +# CONFIG_WILLOW is not set +# CONFIG_CPCI690 is not set +# CONFIG_POWERPMC250 is not set +# CONFIG_CHESTNUT is not set +# CONFIG_SPRUCE is not set +# CONFIG_HDPU is not set +# CONFIG_EV64260 is not set +# CONFIG_LOPEC is not set +# CONFIG_MVME5100 is not set +# CONFIG_MVME5500 is not set +CONFIG_MVME6100=y +# CONFIG_MCP905 is not set +# CONFIG_PPLUS is not set +# CONFIG_PRPMC750 is not set +# CONFIG_PRPMC800 is not set +# CONFIG_SANDPOINT is not set +# CONFIG_RADSTONE_PPC7D is not set +# CONFIG_PAL4 is not set +# CONFIG_GEMINI is not set +# CONFIG_EST8260 is not set +# CONFIG_SBC82xx is not set +# CONFIG_SBS8260 is not set +# CONFIG_RPX8260 is not set +# CONFIG_TQM8260 is not set +# CONFIG_ADS8272 is not set +# CONFIG_PQ2FADS is not set +# CONFIG_LITE5200 is not set +# CONFIG_MPC834x_SYS is not set +# CONFIG_EV64360 is not set +CONFIG_MV64360=y +CONFIG_MV64X60=y + +# +# Set bridge options +# +CONFIG_MV64X60_BASE=0xf1000000 +CONFIG_MV64X60_NEW_BASE=0xf1000000 +# CONFIG_MV64X60_USE_SRAM is not set +# CONFIG_SMP is not set +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_BKL=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/sda2" +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Advanced setup +# +CONFIG_ADVANCED_OPTIONS=y +# CONFIG_HIGHMEM_START_BOOL is not set +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE_BOOL=y +CONFIG_LOWMEM_SIZE=0x40000000 +CONFIG_KERNEL_START_BOOL=y +CONFIG_KERNEL_START=0x90000000 +# CONFIG_TASK_SIZE_BOOL is not set +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD_BOOL=y +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_NETLINK is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +# CONFIG_MTD_CFI_I1 is not set +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +CONFIG_MTD_ROM=y +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PLATRAM is not set +CONFIG_MTD_MVME6100=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_LBD=y +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +CONFIG_SCSI_SATA=y +# CONFIG_SCSI_SATA_AHCI is not set +# CONFIG_SCSI_SATA_SVW is not set +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_MV is not set +# CONFIG_SCSI_SATA_NV is not set +CONFIG_SCSI_PATA_PDC2027X=y +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_QSTOR is not set +# CONFIG_SCSI_SATA_SX4 is not set +# CONFIG_SCSI_SATA_SIL is not set +# CONFIG_SCSI_SATA_SIS is not set +# CONFIG_SCSI_SATA_ULI is not set +# CONFIG_SCSI_SATA_VIA is not set +# CONFIG_SCSI_SATA_VITESSE is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA24XX is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +CONFIG_TULIP=y +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +CONFIG_TULIP_NAPI=y +CONFIG_TULIP_NAPI_HW_MITIGATION=y +# CONFIG_DE4X5 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +# CONFIG_ULI526X is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_MV643XX_ETH=y +CONFIG_MV643XX_ETH_0=y +CONFIG_MV643XX_ETH_1=y +# CONFIG_MV643XX_ETH_2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MPSC is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_SDD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_NVRAM_M48TXXX=y +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# VME Bridge devices +# +CONFIG_VME_BRIDGE=y + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_MPC is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_MV64XXX=y + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_DS1375 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +CONFIG_SENSORS_DS1621=y +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +CONFIG_MV64360_IDMA=y + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# SN Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_KGDB is not set +CONFIG_XMON=y +# CONFIG_BDI_SWITCH is not set +# CONFIG_SERIAL_TEXT_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/Kconfig linux-2.6.14.mod/arch/ppc/Kconfig --- linux-2.6.14.orig/arch/ppc/Kconfig 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/Kconfig 2006-01-26 12:05:53.000000000 -0700 @@ -592,6 +592,15 @@ config MVME5100 bool "Motorola-MVME5100" +config MVME5500 + bool "Motorola-MVME5500" + +config MVME6100 + bool "Motorola-MVME6100" + +config MCP905 + bool "Motorola-MCP905" + config PPLUS bool "Motorola-PowerPlus" @@ -704,9 +713,14 @@ config EMBEDDEDBOOT bool - depends on 8xx || 8260 + depends on 8xx || 8260 || MVME3100 default y +config UBOOT + bool + depends on MVME3100 + default y + config PPC_MPC52xx bool @@ -774,9 +788,9 @@ config PPC_GEN550 bool depends on SANDPOINT || SPRUCE || PPLUS || \ - PRPMC750 || PRPMC800 || LOPEC || \ + PRPMC750 || PRPMC800 || LOPEC || MVME6100 || MCP905 || \ (EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \ - 83xx + 83xx || MVME5500 default y config FORCE @@ -786,12 +800,12 @@ config GT64260 bool - depends on EV64260 || CPCI690 + depends on EV64260 || CPCI690 || MVME5500 default y config MV64360 # Really MV64360 & MV64460 bool - depends on CHESTNUT || KATANA || RADSTONE_PPC7D || HDPU || EV64360 + depends on CHESTNUT || KATANA || RADSTONE_PPC7D || HDPU || EV64360 || MVME6100 || MCP905 default y config MV64X60 @@ -826,6 +840,10 @@ If the current base address of the bridge's registers is not where you want it, set this value to the address that you want it moved to. +config MV64X60_USE_SRAM + bool "Use MV64X60 integrated SRAM for ethernet descriptors" + default n + endmenu config NONMONARCH_SUPPORT @@ -842,6 +860,31 @@ depends on 6xx && (LOPEC || SANDPOINT) default y +config MVME3100_ENABLE_DDR_ERRORS + bool "Enable DDR Error Reporting" + depends on MVME3100 + default y + +config MVME3100_ENABLE_L2_ERRORS + bool "Enable L2 Error Reporting" + depends on MVME3100 + default y + +config MVME3100_ENABLE_PCI_ERRORS + bool "Enable PCI Error Reporting" + depends on MVME3100 + default y + +config MVME3100_TICK_TIMERS + bool "Enable support for the Tick Timers on the MVME3100" + depends on MVME3100 + default y + +config MPC85xx_DMA + bool "Enable support for DMA on MPC85XX based boards" + depends on 85xx + default y + config MPC10X_BRIDGE bool depends on POWERPMC250 || LOPEC || SANDPOINT diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/Makefile linux-2.6.14.mod/arch/ppc/Makefile --- linux-2.6.14.orig/arch/ppc/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/Makefile 2006-01-26 12:06:23.000000000 -0700 @@ -26,6 +26,10 @@ AFLAGS += -Iarch/$(ARCH) CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \ -ffixed-r2 -mmultiple + +# No AltiVec instruction when building kernel +CFLAGS += $(call cc-option, -mno-altivec) + CPP = $(CC) -E $(CFLAGS) # Temporary hack until we have migrated to asm-powerpc LINUXINCLUDE += -Iarch/$(ARCH)/include diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/mm/fault.c linux-2.6.14.mod/arch/ppc/mm/fault.c --- linux-2.6.14.orig/arch/ppc/mm/fault.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/mm/fault.c 2006-01-24 12:16:11.000000000 -0700 @@ -336,7 +336,7 @@ die("kernel access of bad area", regs, sig); } -#ifdef CONFIG_8xx +#if defined(CONFIG_8xx) || defined(CONFIG_GT64260_ETH) /* The pgtable.h claims some functions generically exist, but I * can't find them...... diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/oprofile/backtrace.c linux-2.6.14.mod/arch/ppc/oprofile/backtrace.c --- linux-2.6.14.orig/arch/ppc/oprofile/backtrace.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/oprofile/backtrace.c 2005-11-16 10:40:20.000000000 -0700 @@ -0,0 +1,121 @@ +/* + * PPC 32 oprofile support + * Based on PPC64 oprofile backtrace support + * Copyright (C) 2005 Brian Rogan , IBM + * + * Copyright (C) Freescale Semiconductor, Inc 2005 + * + * Author: Andy Fleming + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include + +static unsigned int user_putsp32(unsigned int sp, int *is_first) +{ + unsigned int stack_frame[2], rv; + unsigned long t = sp; + + /* If the page isn't accessible, then we've done all that we can do, + * a partial stack trace is better than none. + */ + rv = __copy_from_user_inatomic(stack_frame, (void *)t, + sizeof(stack_frame)); + if (rv != 0) { + /* The most likely reason for this is that we returned -EFAULT, + * which means that we've done all that we can do from interrupt + * context. All other errors though are equally valid reasons to + * abort our backtrace. */ + return 0; + } + + /* SVR4 compliant executables have the Link Register offset by 4 bytes + * from the beginning of the stack page */ + if (!*is_first) { + oprofile_add_trace(stack_frame[1]); + } else { + *is_first = 0; + } + + /* Sanity check to make sure that the previous stack frame is actually above + * us in memory, like we would expect it to be from the PPC spec. + * + * The last stack pointer is always at offset 0 from the beginning of the + * stack frame. + */ + rv = stack_frame[0]; + if (rv > sp) { + return rv; + } else { + return 0; + } +} + +static int validate_sp(unsigned long sp) +{ + unsigned long prev_sp; + unsigned long stack_top; + + prev_sp = (unsigned long)(current->thread_info + 1); + stack_top = (unsigned long)current->thread_info + THREAD_SIZE; + + if (sp > prev_sp && sp < stack_top && (sp & 3) == 0) + return 1; + + return 0; +} + +static unsigned long kernel_putsp32(unsigned long sp, int *is_first) +{ + unsigned long *stack_frame = (unsigned long *)sp; + unsigned long rv; + + if (!validate_sp(sp)) { + return 0; + } + if (!*is_first) { + /* Same as before LR is offset 4 bytes from the beginning */ + oprofile_add_trace(stack_frame[1]); + } else { + *is_first = 0; + } + + rv = stack_frame[0]; + if (rv > sp) { + return rv; + } else { + return 0; + } +} + +void op_ppc32_backtrace(struct pt_regs *const regs, unsigned int depth) +{ + unsigned long cursp = regs->gpr[1]; + int first_frame = 1; + + if (!user_mode(regs)) { + unsigned long sp = cursp; + while (depth--) { + sp = kernel_putsp32(sp, &first_frame); + if (!sp) { + break; + } + } + return; + } else { + unsigned long sp = cursp; + while (depth--) { + sp = user_putsp32(sp, &first_frame); + if (!sp) { + break; + } + } + } +} diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/oprofile/Makefile linux-2.6.14.mod/arch/ppc/oprofile/Makefile --- linux-2.6.14.orig/arch/ppc/oprofile/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/oprofile/Makefile 2005-11-16 10:40:20.000000000 -0700 @@ -6,7 +6,7 @@ oprofilefs.o oprofile_stats.o \ timer_int.o ) -oprofile-y := $(DRIVER_OBJS) common.o +oprofile-y := $(DRIVER_OBJS) common.o backtrace.o ifeq ($(CONFIG_FSL_BOOKE),y) oprofile-y += op_model_fsl_booke.o diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/85xx/cache.S linux-2.6.14.mod/arch/ppc/platforms/85xx/cache.S --- linux-2.6.14.orig/arch/ppc/platforms/85xx/cache.S 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/85xx/cache.S 2005-11-16 10:40:20.000000000 -0700 @@ -0,0 +1,121 @@ +#include +#include +#include + + .text + + + .globl e500_enable_l1_data +e500_enable_l1_data: + addis r3,r0,0x0000 /* add CE */ + ori r3,r3,0x0001 /* add CE */ + sync /* synchronize */ + isync /* synchronize */ + mtspr 1010,r3 /* store L1CSR0 register */ + isync /* synchronize */ + sync /* synchronize */ + blr /* return to caller */ + + + .globl e500_disable_l1_data +e500_disable_l1_data: + /* + * read 512K to force castouts + */ + addis r3,r0,0x0000 + ori r3,r3,0x0000 + addis r4,r0,0x0008 + ori r4,r4,0x0000 +e500_disable_l1: + lwz r5,0(r3) + addi r3,r3,0x20 + cmp 0,0,r3,r4 + bne e500_disable_l1 + + sync + addis r3,r0,0x0000 /* add CE */ + ori r3,r3,0x0001 /* add CE */ + isync /* synchronize */ + sync /* synchronize */ + mfspr r4,1010 /* load spr1010 register */ + sync /* synchronize */ + andc r4,r4,r3 /* clear bit (disable cache) */ + ori r4,r4,2 /* set bit (invalidate cache) */ + sync /* synchronize */ + mtspr 1010,r4 /* store spr1010 register */ + sync /* synchronize */ + blr /* return to caller */ + + + .globl e500_invalidate_l1_data +e500_invalidate_l1_data: + addi r3,r0,0x0002 /* add CFI */ + isync /* synchronize */ + mfspr r4,1010 /* load L1CSR0 register */ + isync /* synchronize */ + or r4,r4,r3 /* set bit (invalidate cache) */ + sync /* synchronize */ + isync /* synchronize */ + mtspr 1010,r4 /* store L1CSR0 register */ + isync /* synchronize */ + sync /* synchronize */ + blr /* return to caller */ + + .globl e500_flush_l1_data +e500_flush_l1_data: + /* + * No flush assist from HW, so just read 512K to force castouts + */ + addis r3,r0,0x0000 + ori r3,r3,0x0000 + addis r4,r0,0x0008 + ori r4,r4,0x0000 +e500_flush_l1: + lwz r5,0(r3) + addi r3,r3,0x20 + cmp 0,0,r3,r4 + bne e500_flush_l1 + sync + b e500_invalidate_l1_data /* return through invalidate routine */ + + .globl e500_enable_l1_inst +e500_enable_l1_inst: + addis r3,r0,0x0000 /* add CE */ + ori r3,r3,0x0001 /* add CE */ + sync /* synchronize */ + isync /* synchronize */ + mtspr 1011,r3 /* store L1CSR1 register */ + isync /* synchronize */ + sync /* synchronize */ + blr /* return to caller */ + + + .globl e500_disable_l1_inst +e500_disable_l1_inst: + addis r3,r0,0x0000 /* add ICE */ + ori r3,r3,0x0001 /* add ICE */ + isync /* synchronize */ + sync /* synchronize */ + mfspr r4,1011 /* load spr1011 register */ + sync /* synchronize */ + andc r4,r4,r3 /* clear bit (disable cache) */ + ori r4,r4,2 /* set bit (invalidate cache) */ + sync /* synchronize */ + mtspr 1011,r4 /* store spr1011 register */ + sync /* synchronize */ + blr /* return to caller */ + + .globl e500_invalidate_l1_inst +e500_invalidate_l1_inst: + addi r3,r0,0x0002 /* add ICFI */ + isync /* synchronize */ + mfspr r4,1011 /* load L1CSR1 register */ + isync /* synchronize */ + or r4,r4,r3 /* set bit (invalidate cache) */ + sync /* synchronize */ + isync /* synchronize */ + mtspr 1011,r4 /* store L1CSR1 register */ + isync /* synchronize */ + sync /* synchronize */ + blr /* return to caller */ + diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/85xx/Kconfig linux-2.6.14.mod/arch/ppc/platforms/85xx/Kconfig --- linux-2.6.14.orig/arch/ppc/platforms/85xx/Kconfig 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/85xx/Kconfig 2005-11-16 10:40:20.000000000 -0700 @@ -48,6 +48,11 @@ This option enables support for the Silicon Turnkey Express GP3 board. +config MVME3100 + bool "Motorola Embedded Communications and Computing Group 8540 MVME3100" + help + This option enables support for the Motorola ECCG 8540 MVME3100 board + endchoice # It's often necessary to know the specific 85xx processor type. @@ -55,7 +60,7 @@ # don't need to ask more redundant questions. config MPC8540 bool - depends on MPC8540_ADS + depends on MPC8540_ADS || MVME3100 default y config MPC8548 diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/85xx/Makefile linux-2.6.14.mod/arch/ppc/platforms/85xx/Makefile --- linux-2.6.14.orig/arch/ppc/platforms/85xx/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/85xx/Makefile 2005-11-16 10:40:20.000000000 -0700 @@ -6,4 +6,6 @@ obj-$(CONFIG_MPC8555_CDS) += mpc85xx_cds_common.o obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads_common.o mpc8560_ads.o obj-$(CONFIG_SBC8560) += sbc85xx.o sbc8560.o +obj-$(CONFIG_MVME3100) += mvme3100.o cache.o +obj-$(CONFIG_MVME3100_TICK_TIMERS) += mvme3100_timer.o obj-$(CONFIG_STX_GP3) += stx_gp3.o diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/85xx/mvme3100.c linux-2.6.14.mod/arch/ppc/platforms/85xx/mvme3100.c --- linux-2.6.14.orig/arch/ppc/platforms/85xx/mvme3100.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/85xx/mvme3100.c 2006-06-06 15:24:31.000000000 -0700 @@ -0,0 +1,1112 @@ +/* + * arch/ppc/platforms/85xx/mvme3100.c + * + * MVME3100 board specific routines + * + * Author: Ajit Prem + * + * Copyright 2004-2006 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for linux/serial_core.h */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern void e500_enable_l1_data(void); +extern void e500_enable_l1_inst(void); + +#define L2_ERR_REGS_OFFSET 0x20E20 +#define L2_ERR_REGS_SIZE 0x3C + +#define L2_CAPT_DATA_HI 0x20E20 +#define L2_CAPT_DATA_LO 0x20E24 +#define L2_CAPT_ECC 0x20E28 +#define L2_ERR_DET 0x20E40 +#define L2_ERR_DIS 0x20E44 +#define L2_ERR_INT_EN 0x20E48 +#define L2_ERR_ATTR 0x20E4C +#define L2_ERR_ADDR 0x20E50 +#define L2_ERR_CTL 0x20E58 + +static u8 *l2_err_regs; +#ifdef CONFIG_MVME3100_ENABLE_L2_ERRORS +static irqreturn_t mvme3100_l2cache_err_handler(int irq, void *dev_id, + struct pt_regs *regs); +#endif + +#ifdef CONFIG_MVME3100_ENABLE_DDR_ERRORS + +#define DDR_ERR_REGS_OFFSET 0x2E00 +#define DDR_ERR_REGS_SIZE 0x5C + +#define DDR_CAPT_DATA_HI 0x2E20 +#define DDR_CAPT_DATA_LO 0x2E24 +#define DDR_CAPT_ECC 0x2E28 +#define DDR_ERR_DET 0x2E40 +#define DDR_ERR_DIS 0x2E44 +#define DDR_ERR_INT_EN 0x2E48 +#define DDR_CAPT_ATTR 0x2E4C +#define DDR_CAPT_ADDR 0x2E50 +#define DDR_ERR_SBE 0x2E58 + +static u8 *ddr_err_regs; +static irqreturn_t mvme3100_ddr_err_handler(int irq, void *dev_id, + struct pt_regs *regs); + +#endif + +#ifdef CONFIG_MVME3100_ENABLE_PCI_ERRORS + +#define PCI_ERR_REGS_OFFSET 0x8E00 +#define PCI_ERR_REGS_SIZE 0x28 + +#define PCI_ERR_DET 0x8E00 +#define PCI_ERR_CAP_DIS 0x8E04 +#define PCI_ERR_INT_EN 0x8E08 +#define PCI_ERR_ATTR 0x8E0C +#define PCI_ERR_ADDR 0x8E10 +#define PCI_ERR_EXT_ADDR 0x8E14 +#define PCI_ERR_DL 0x8E18 +#define PCI_ERR_DH 0x8E1C +#define PCI_GAS_TIMR 0x8E20 +#define PCI_PCIX_TIMR 0x8E24 + +static int pci_errors; +static u8 *pci_err_regs; +static irqreturn_t mvme3100_pci_err_handler(int irq, void *dev_id, + struct pt_regs *regs); + +#endif + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +extern unsigned long total_memory; /* in mm/init */ + +#ifdef CONFIG_VME_BRIDGE_BOOTMEM +void *vme_driver_bootmem; +unsigned int vme_bootmem_size; +#endif + +unsigned char __res[sizeof(bd_t)]; + +/* Internal interrupts are all Level Sensitive, and Positive Polarity */ + +static u_char mvme3100_openpic_initsenses[] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 0: VME 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: VME 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: VME2/sATA */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: VME3/UART */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 4: PMCSpan/PMC/USB */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PMCSPAN/PMC */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 6: PMCSPAN/PMC */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 7: PMCSPAN/PMC */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 8: ABORT */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 9: Temp Sensor */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 10: PHY */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 11: DS1375 Alm */ +}; + +int mvme3100_show_cpuinfo(struct seq_file *m) +{ + uint pvid, svid, phid1; + uint memsize = total_memory; + uint ifreq, bfreq; + u8 *reg_addr, *reg_block; + u8 *l2cache_addr; + bd_t *binfo = (bd_t *) __res; + u8 reg_value; + u32 reg32_value; + u32 l1csr0, l1csr1, l2ctl; + char buff[16] = ""; + + pvid = mfspr(SPRN_PVR); + svid = mfspr(SPRN_SVR); + + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); + + switch (pvid & 0xffff0000) { + case PVR_8540: + seq_printf(m, "Machine\t\t: MVME3100\n"); + break; + default: + seq_printf(m, "Machine\t\t: unknown\n"); + break; + } + ifreq = BINFO_INTFREQ; + bfreq = BINFO_BUSFREQ; + seq_printf(m, "int freq\t: %u.%.6u MHz\n", ifreq / 1000000, + ifreq % 1000000); + seq_printf(m, "bus freq\t: %u.%.6u MHz\n", bfreq / 1000000, + bfreq % 1000000); + seq_printf(m, "PVR\t\t: 0x%x\n", pvid); + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + seq_printf(m, "HID0\t\t: 0x%08x\n", mfspr(SPRN_HID0)); + seq_printf(m, "HID1\t\t: 0x%08x\n", mfspr(SPRN_HID1)); + seq_printf(m, "CCSR Base\t: 0x%08lx\n", BINFO_IMMR_BASE); + + /* Display cpu Pll setting */ + phid1 = mfspr(SPRN_HID1); + seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the cache settings */ + seq_printf(m, "\nCache Settings:\n"); + l1csr0 = mfspr(SPRN_L1CSR0); + seq_printf(m, "L1CSR0 (L1 D-cache)\t: 0x%08x (%s)\n", l1csr0, + (l1csr0 & 1) ? "on" : "off"); + l1csr1 = mfspr(SPRN_L1CSR1); + seq_printf(m, "L1CSR1 (L1 I-cache)\t: 0x%08x (%s)\n", l1csr1, + (l1csr1 & 1) ? "on" : "off"); + seq_printf(m, "L1CFG0\t\t\t: 0x%08x\n", mfspr(SPRN_L1CFG0)); + seq_printf(m, "L1CFG1\t\t\t: 0x%08x\n", mfspr(SPRN_L1CFG1)); + + l2cache_addr = ioremap(binfo->bi_immr_base + 0x20000, 4); + l2ctl = swab32(readl(l2cache_addr)); + seq_printf(m, "L2CTL (L2 cache)\t: 0x%x (%s)\n", l2ctl, + (l2ctl & 0x80000000) ? "on" : "off"); + iounmap(l2cache_addr); + + seq_printf(m, "\nBOARD INFORMATION:\n"); + reg_block = ioremap(MVME3100_SYSTEM_STATUS_REG, 16); + reg_addr = reg_block; + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t\t: %d MB\n", memsize / (1024 * 1024)); + + /* System Status Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "Safe Start Status\t: %s\n", + ((reg_value & MVME3100_SAFE_START) ? + "Safe ENV settings used" : "NVRAM ENV settings used")); + seq_printf(m, "Abort Status\t\t: %s\n", + ((reg_value & MVME3100_ABORT_STATUS) ? + "Abort Switch Asserted" : "Abort Switch Not Asserted")); + switch (reg_value & MVME3100_BOARD_TYPE_MASK) { + case MVME3100_BOARD_TYPE_PRPMC: + sprintf(buff, "PrPMC"); + break; + case MVME3100_BOARD_TYPE_VME: + sprintf(buff, "VME"); + break; + default: + sprintf(buff, "Unknown"); + break; + } + seq_printf(m, "Board Type\t\t: %s\n", buff); + + /* System Control Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "EEPROM WP Status\t: %s\n", + ((reg_value & MVME3100_EEPROM_WP) ? + "EEPROM Write Protected" : "EEPROM Not Write Protected")); + seq_printf(m, "DS1621 Thermostat\t: %s\n", + ((reg_value & MVME3100_TSTAT_MASK) ? + "Interrupt Disabled" : "Interrupt Enabled")); + + /* Status Indicator Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "Board Fail LED\t\t: %s\n", + ((reg_value & MVME3100_BRD_FAIL_LED) ? "Lit" : "Not Lit")); + seq_printf(m, "USR1 LED\t\t: %s\n", + ((reg_value & MVME3100_USR1_LED) ? "Lit" : "Not Lit")); + seq_printf(m, "USR2 LED\t\t: %s\n", + ((reg_value & MVME3100_USR2_LED) ? "Lit" : "Not Lit")); + seq_printf(m, "USR3 LED\t\t: %s\n", + ((reg_value & MVME3100_USR3_LED) ? "Lit" : "Not Lit")); + + /* Flash Control/Status Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "Flash Map Select\t: %s\n", + ((reg_value & MVME3100_FLASH_MAP_SELECT) ? + "Boot Block A Mapped to Highest Address" : + "Flash Memory Map Controlled by Flash Boot Block Select")); + seq_printf(m, "Flash Write Protect SW\t: %s\n", + ((reg_value & MVME3100_FLASH_WP_SW) ? + "Write Protected" : "Not Write Protected")); + seq_printf(m, "Flash Write Protect HW\t: %s\n", + ((reg_value & MVME3100_FLASH_WP_HW) ? + "Write Protected" : "Not Write Protected")); + seq_printf(m, "Flash Boot Block Select\t: %s\n", + ((reg_value & MVME3100_FLASH_BLK_SEL) ? + "Boot Block B Selected" : "Boot Block A Selected")); + seq_printf(m, "Flash Ready Status\t: %s\n", + ((reg_value & MVME3100_FLASH_RDY) ? + "Bit Set" : "Bit Not Set")); + + /* PCI Bus A Status Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "PCI Bus A 64 Bit\t: %s\n", + ((reg_value & MVME3100_PCI_BUS_A_64B) ? + "64 Bit Enabled" : "32 Bit Mode")); + seq_printf(m, "PCI Bus A PCI-X\t\t: %s\n", + ((reg_value & MVME3100_PCI_BUS_A_PCIX) ? + "PCI-X Mode" : "PCI Mode")); + switch (reg_value & MVME3100_PCI_BUS_A_SPD_MASK) { + case MVME3100_PCI_BUS_A_SPD_133: + sprintf(buff, "133 MHz"); + break; + case MVME3100_PCI_BUS_A_SPD_100: + sprintf(buff, "100 MHz"); + break; + case MVME3100_PCI_BUS_A_SPD_66: + sprintf(buff, "66 MHz"); + break; + case MVME3100_PCI_BUS_A_SPD_33: + default: + sprintf(buff, "33 MHz"); + break; + } + seq_printf(m, "PCI Bus A Speed\t\t: %s\n", buff); + + /* PCI Bus B Status Register */ + reg_value = readb(reg_addr++); + if (reg_value & MVME3100_PCI_BUS_B_3_3V_VIO) { + seq_printf(m, "PCI Bus B 3.3V VIO\t: %s\n", + "Configured for 3.3V VIO"); + }; + if (reg_value & MVME3100_PCI_BUS_B_5_0V_VIO) { + seq_printf(m, "PCI Bus B 5.0V VIO\t: %s\n", + "Configured for 5.0V VIO"); + }; + seq_printf(m, "PCI Bus B ERDY2\t\t: %d\n", + ((reg_value & MVME3100_PCI_BUS_B_ERDY2) ? 1 : 0)); + seq_printf(m, "PCI Bus B ERDY1\t\t: %d\n", + ((reg_value & MVME3100_PCI_BUS_B_ERDY1) ? 1 : 0)); + seq_printf(m, "PCI Bus B 64 Bit\t: %s\n", + ((reg_value & MVME3100_PCI_BUS_B_64B) ? + "64 Bit Enabled" : "32 Bit Mode")); + seq_printf(m, "PCI Bus B PCI-X\t\t: %s\n", + ((reg_value & MVME3100_PCI_BUS_B_PCIX) ? + "PCI-X Mode" : "PCI Mode")); + switch (reg_value & MVME3100_PCI_BUS_B_SPD_MASK) { + case MVME3100_PCI_BUS_B_SPD_133: + sprintf(buff, "133 MHz"); + break; + case MVME3100_PCI_BUS_B_SPD_100: + sprintf(buff, "100 MHz"); + break; + case MVME3100_PCI_BUS_B_SPD_66: + sprintf(buff, "66 MHz"); + break; + case MVME3100_PCI_BUS_B_SPD_33: + default: + sprintf(buff, "33 MHz"); + break; + } + seq_printf(m, "PCI Bus B Speed\t\t: %s\n", buff); + + /* PCI Bus C Status Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "PCI Bus C 64 Bit\t: %s\n", + ((reg_value & MVME3100_PCI_BUS_C_64B) ? + "64 Bit Enabled" : "32 Bit Mode")); + seq_printf(m, "PCI Bus C PCI-X\t\t: %s\n", + ((reg_value & MVME3100_PCI_BUS_C_PCIX) ? + "PCI-X Mode" : "PCI Mode")); + switch (reg_value & MVME3100_PCI_BUS_C_SPD_MASK) { + case MVME3100_PCI_BUS_C_SPD_133: + sprintf(buff, "133 MHz"); + break; + case MVME3100_PCI_BUS_C_SPD_100: + sprintf(buff, "100 MHz"); + break; + case MVME3100_PCI_BUS_C_SPD_66: + sprintf(buff, "66 MHz"); + break; + case MVME3100_PCI_BUS_C_SPD_33: + default: + sprintf(buff, "33 MHz"); + break; + } + seq_printf(m, "PCI Bus C Speed\t\t: %s\n", buff); + + /* Interrupt Detect Register */ + reg_value = readb(reg_addr++); + + if (reg_value & MVME3100_FEC_PHY_INTERRUPT) { + seq_printf(m, "FEC PHY Interrupt\t: %s\n", "Asserted"); + }; + if (reg_value & MVME3100_TSEC2_PHY_INTERRUPT) { + seq_printf(m, "TSEC2 PHY Interrupt\t: %s\n", "Asserted"); + }; + if (reg_value & MVME3100_TSEC1_PHY_INTERRUPT) { + seq_printf(m, "TSEC1 PHY Interrupt\t: %s\n", "Asserted"); + }; + + /* Presence Detect Register */ + reg_value = readb(reg_addr++); + + seq_printf(m, "PMCSPAN\t\t\t: %s\n", + ((reg_value & MVME3100_PMCSPAN_PRESENT) ? + "PMCSPAN Installed" : "PMCSPAN Not Installed")); + seq_printf(m, "PMC Site 2\t\t: %s\n", + ((reg_value & MVME3100_PMC2_PRESENT) ? + "PMC Module Installed" : "PMC Module Not Installed")); + seq_printf(m, "PMC Site 1\t\t: %s\n", + ((reg_value & MVME3100_PMC1_PRESENT) ? + "PMC Module Installed" : "PMC Module Not Installed")); + + /* PLD Revision Register */ + reg_value = readb(reg_addr++); + + seq_printf(m, "PLD Revision\t\t: 0x%x\n", reg_value); + + /* PLD Date Code Register */ + reg_addr++; + reg_addr++; + reg32_value = readl((u32 *) reg_addr); + seq_printf(m, "PLD Date Code\t\t: 0x%08x\n", + (((reg32_value & 0x000000ffU) << 24) | + ((reg32_value & 0x0000ff00U) << 8) | + ((reg32_value & 0x00ff0000U) >> 8) | + ((reg32_value & 0xff000000U) >> 24))); + + iounmap(reg_block); + + return 0; +} + +void __init mvme3100_init_IRQ(void) +{ + /* Determine the Physical Address of the OpenPIC regs */ + phys_addr_t OpenPIC_PAddr = BINFO_IMMR_BASE + MPC85xx_OPENPIC_OFFSET; + + OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE); + OpenPIC_InitSenses = mvme3100_openpic_initsenses; + OpenPIC_NumInitSenses = sizeof(mvme3100_openpic_initsenses); + + /* Skip reserved space and internal sources */ + openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200); + /* Map PIC IRQs 0-11 */ + openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000); + + openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET); + + return; +} + +int mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {MPC85xx_IRQ_EXT0, MPC85xx_IRQ_EXT1, MPC85xx_IRQ_EXT2, MPC85xx_IRQ_EXT3}, /* IDSEL 1 - TSI148 */ + {MPC85xx_IRQ_EXT4, MPC85xx_IRQ_EXT5, MPC85xx_IRQ_EXT6, MPC85xx_IRQ_EXT7}, /* IDSEL 2 - PCI6520-1 */ + {MPC85xx_IRQ_EXT4, MPC85xx_IRQ_EXT5, MPC85xx_IRQ_EXT6, MPC85xx_IRQ_EXT7}, /* IDSEL 3 - PCI6520-2 */ + {MPC85xx_IRQ_EXT2, 0, 0, 0}, /* IDSEL 4 - GD31244 SATA */ + {0, 0, 0, 0}, /* IDSEL 5 */ + {0, 0, 0, 0}, /* IDSEL 6 */ + {0, 0, 0, 0}, /* IDSEL 7 */ + {0, 0, 0, 0}, /* IDSEL 8 */ + {0, 0, 0, 0}, /* IDSEL 9 */ + {0, 0, 0, 0}, /* IDSEL 10 */ + {0, 0, 0, 0}, /* IDSEL 11 */ + {0, 0, 0, 0}, /* IDSEL 12 */ + {0, 0, 0, 0}, /* IDSEL 13 */ + {0, 0, 0, 0}, /* IDSEL 14 */ + {0, 0, 0, 0}, /* IDSEL 15 */ + {0, 0, 0, 0}, /* IDSEL 16 */ + {MPC85xx_IRQ_EXT0, MPC85xx_IRQ_EXT1, MPC85xx_IRQ_EXT2, MPC85xx_IRQ_EXT3}, /* IDSEL 17 - TSI148 */ + {MPC85xx_IRQ_EXT4, MPC85xx_IRQ_EXT5, MPC85xx_IRQ_EXT6, MPC85xx_IRQ_EXT7}, /* IDSEL 18 - PCI6520-1 */ + {MPC85xx_IRQ_EXT4, MPC85xx_IRQ_EXT5, MPC85xx_IRQ_EXT6, MPC85xx_IRQ_EXT7}, /* IDSEL 19 - PCI6520-2 */ + {MPC85xx_IRQ_EXT2, 0, 0, 0}, /* IDSEL 20 - GD31244 SATA */ + }; + + const long min_idsel = 1, max_idsel = 20, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + +int mpc85xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + else + return PCIBIOS_SUCCESSFUL; +} + +static void __init mvme3100_pci_fixups(void) +{ + struct pci_dev *dev = NULL; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + /* Update all devices' cache line size */ + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, + L1_CACHE_LINE_SIZE >> 2); + } + + if ((dev = pci_find_device(PCI_VENDOR_ID_NEC, + PCI_DEVICE_ID_NEC_USB, NULL))) { + /* Set System Clock to 48MHz oscillator in EXT2 register */ + pci_write_config_byte(dev, 0xe4, 0x20); + } + + if ((dev = pci_find_device(PCI_VENDOR_ID_DEC, + PCI_DEVICE_ID_DEC_21150, NULL))) { + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80); + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x80); + } + + if ((dev = pci_find_device(PCI_VENDOR_ID_DEC, + PCI_DEVICE_ID_DEC_21152, NULL))) { + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80); + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x80); + } +#ifdef CONFIG_MVME3100_ENABLE_DDR_ERRORS + if (request_irq(MPC85xx_IRQ_DDR, mvme3100_ddr_err_handler, + SA_INTERRUPT, "DDR Error", 0) < 0) { + printk(KERN_ERR "Cannot install DDR error handler\n"); + return; + } + + writel(swab32(0xD), + ddr_err_regs + DDR_ERR_INT_EN - DDR_ERR_REGS_OFFSET); +#endif + +#ifdef CONFIG_MVME3100_ENABLE_L2_ERRORS + if (request_irq(MPC85xx_IRQ_L2CACHE, mvme3100_l2cache_err_handler, + SA_INTERRUPT, "L2 Cache Error", 0) < 0) { + printk(KERN_ERR "Cannot install L2 cache error handler\n"); + return; + } + + writel(swab32(0x1D), l2_err_regs + L2_ERR_INT_EN - L2_ERR_REGS_OFFSET); +#endif + +#ifdef CONFIG_MVME3100_ENABLE_PCI_ERRORS + if (request_irq(MPC85xx_IRQ_PCI1, mvme3100_pci_err_handler, + SA_INTERRUPT, "PCI Error", 0) < 0) { + printk(KERN_ERR "Cannot install PCI error handler\n"); + return; + } + + writel(swab32(0x7FF), + pci_err_regs + PCI_ERR_INT_EN - PCI_ERR_REGS_OFFSET); +#endif +} + +static void mvme3100_restart(char *cmd) +{ + volatile ulong i = 10000000; + u8 *system_control_reg_addr; + + local_irq_disable(); + system_control_reg_addr = ioremap(MVME3100_SYSTEM_CONTROL_REG, 1); + writeb(MVME3100_BOARD_RESET, system_control_reg_addr); + + while (i-- > 0) ; + panic("restart failed\n"); +} + +#ifdef CONFIG_MVME3100_ENABLE_DDR_ERRORS + +static irqreturn_t mvme3100_ddr_err_handler(int irq, void *dev_id, + struct pt_regs *regs) +{ + u32 err_addr, data_hi, data_lo, ecc, err_attr, err_det, sbe_count; + + /* Collect error information from the error registers */ + err_addr = readl(ddr_err_regs + DDR_CAPT_ADDR - DDR_ERR_REGS_OFFSET); + data_hi = readl(ddr_err_regs + DDR_CAPT_DATA_HI - DDR_ERR_REGS_OFFSET); + data_lo = readl(ddr_err_regs + DDR_CAPT_DATA_LO - DDR_ERR_REGS_OFFSET); + err_attr = readl(ddr_err_regs + DDR_CAPT_ATTR - DDR_ERR_REGS_OFFSET); + ecc = readl(ddr_err_regs + DDR_CAPT_ECC - DDR_ERR_REGS_OFFSET); + sbe_count = readl(ddr_err_regs + DDR_ERR_SBE - DDR_ERR_REGS_OFFSET); + err_det = readl(ddr_err_regs + DDR_ERR_DET - DDR_ERR_REGS_OFFSET); + + /* Clear interrupt cause and capture registers */ + writel(err_det, ddr_err_regs + DDR_ERR_DET - DDR_ERR_REGS_OFFSET); + writel(sbe_count & ~(swab32(0xFFFF)), + ddr_err_regs + DDR_ERR_SBE - DDR_ERR_REGS_OFFSET); + writel(0, ddr_err_regs + DDR_CAPT_DATA_HI - DDR_ERR_REGS_OFFSET); + writel(0, ddr_err_regs + DDR_CAPT_DATA_LO - DDR_ERR_REGS_OFFSET); + + /* Display error information */ + printk(KERN_ERR "DDR Error!\n"); + printk(KERN_ERR "DDR ERROR DETECT REG 0x%08x\n", swab32(err_det)); + printk(KERN_ERR "DDR ERROR ADDRESS CAPTURE REG 0x%08x\n", + swab32(err_addr)); + printk(KERN_ERR "DDR ERROR DATA HIGH CAPTURE REG 0x%08x\n", + swab32(data_hi)); + printk(KERN_ERR "DDR ERROR DATA LOW CAPTURE REG 0x%08x\n", + swab32(data_lo)); + printk(KERN_ERR "DDR ERROR ATTRIBUTES CAPTURE REG 0x%08x\n", + swab32(err_attr)); + printk(KERN_ERR "DDR ERROR SYNDROME REG 0x%08x\n", swab32(ecc)); + printk(KERN_ERR "DDR ERROR SBE REG 0x%08x\n", swab32(sbe_count)); + + return IRQ_HANDLED; +} + +#endif + +#ifdef CONFIG_MVME3100_ENABLE_L2_ERRORS + +static irqreturn_t mvme3100_l2cache_err_handler(int irq, void *dev_id, + struct pt_regs *regs) +{ + u32 err_addr, data_hi, data_lo, ecc, err_attr, err_det; + + /* Collect error information from the error registers */ + err_det = readl(l2_err_regs + L2_ERR_DET - L2_ERR_REGS_OFFSET); + err_attr = readl(l2_err_regs + L2_ERR_ATTR - L2_ERR_REGS_OFFSET); + err_addr = readl(l2_err_regs + L2_ERR_ADDR - L2_ERR_REGS_OFFSET); + data_hi = readl(l2_err_regs + L2_CAPT_DATA_HI - L2_ERR_REGS_OFFSET); + data_lo = readl(l2_err_regs + L2_CAPT_DATA_LO - L2_ERR_REGS_OFFSET); + ecc = readl(l2_err_regs + L2_CAPT_ECC - L2_ERR_REGS_OFFSET); + + /* Clear interrupt cause and capture registers */ + writel(err_det, l2_err_regs + L2_ERR_DET - L2_ERR_REGS_OFFSET); + writel(0, l2_err_regs + L2_ERR_ATTR - L2_ERR_REGS_OFFSET); + writel(0, l2_err_regs + L2_ERR_ADDR - L2_ERR_REGS_OFFSET); + writel(0, l2_err_regs + L2_CAPT_DATA_HI - L2_ERR_REGS_OFFSET); + writel(0, l2_err_regs + L2_CAPT_DATA_LO - L2_ERR_REGS_OFFSET); + writel(0, l2_err_regs + L2_CAPT_ECC - L2_ERR_REGS_OFFSET); + + /* Display error information */ + printk(KERN_ERR "L2 Cache Error!\n"); + printk(KERN_ERR "L2 ERROR DETECT REG 0x%08x\n", swab32(err_det)); + printk(KERN_ERR "L2 ERROR ADDRESS CAPTURE REG 0x%08x\n", + swab32(err_addr)); + printk(KERN_ERR "L2 ERROR DATA HIGH CAPTURE REG 0x%08x\n", + swab32(data_hi)); + printk(KERN_ERR "L2 ERROR DATA LOW CAPTURE REG 0x%08x\n", + swab32(data_lo)); + printk(KERN_ERR "L2 ERROR ATTRIBUTES CAPTURE REG 0x%08x\n", + swab32(err_attr)); + printk(KERN_ERR "L2 ERROR SYNDROME REG 0x%08x\n", swab32(ecc)); + + return IRQ_HANDLED; +} + +#endif + +#ifdef CONFIG_MVME3100_ENABLE_PCI_ERRORS + +static irqreturn_t mvme3100_pci_err_handler(int irq, void *dev_id, + struct pt_regs *regs) +{ + u32 err_addr, data_hi, data_lo, err_attr, err_ext_addr, err_det; + u32 gas_timr, pcix_timr; + u16 pci_status; + + /* Collect error information from the error registers */ + err_det = readl(pci_err_regs + PCI_ERR_DET - PCI_ERR_REGS_OFFSET); + err_addr = readl(pci_err_regs + PCI_ERR_ADDR - PCI_ERR_REGS_OFFSET); + err_ext_addr = + readl(pci_err_regs + PCI_ERR_EXT_ADDR - PCI_ERR_REGS_OFFSET); + err_attr = readl(pci_err_regs + PCI_ERR_ATTR - PCI_ERR_REGS_OFFSET); + data_lo = readl(pci_err_regs + PCI_ERR_DL - PCI_ERR_REGS_OFFSET); + data_hi = readl(pci_err_regs + PCI_ERR_DH - PCI_ERR_REGS_OFFSET); + gas_timr = readl(pci_err_regs + PCI_GAS_TIMR - PCI_ERR_REGS_OFFSET); + pcix_timr = readl(pci_err_regs + PCI_PCIX_TIMR - PCI_ERR_REGS_OFFSET); +// pci_bus_read_config_word(0, 0, PCI_STATUS, &pci_status); + early_read_config_word(0, 0, 0, PCI_STATUS, &pci_status); + + /* Clear interrupt cause and capture registers */ +// writel(err_det, pci_err_regs + PCI_ERR_DET - PCI_ERR_REGS_OFFSET); + writel(0xFFFFFFFF, pci_err_regs + PCI_ERR_DET - PCI_ERR_REGS_OFFSET); + writel(0, pci_err_regs + PCI_ERR_ADDR - PCI_ERR_REGS_OFFSET); + writel(0, pci_err_regs + PCI_ERR_EXT_ADDR - PCI_ERR_REGS_OFFSET); + writel(0, pci_err_regs + PCI_ERR_ATTR - PCI_ERR_REGS_OFFSET); + writel(0, pci_err_regs + PCI_ERR_DL - PCI_ERR_REGS_OFFSET); + writel(0, pci_err_regs + PCI_ERR_DH - PCI_ERR_REGS_OFFSET); + if (pci_status & PCI_STATUS_PARITY) { + pci_status &= ~PCI_STATUS_PARITY; +// pci_bus_write_config_word(0, 0, PCI_STATUS, pci_status); + early_write_config_word(0, 0, 0, PCI_STATUS, pci_status); + } + + /* Display error information */ + if (pci_errors != 0) { + printk(KERN_ERR "PCI Error!\n"); + printk(KERN_ERR "PCI ERROR DETECT REG 0x%08x\n", + swab32(err_det)); + printk(KERN_ERR "PCI ERROR ADDRESS REG 0x%08x\n", + swab32(err_addr)); + printk(KERN_ERR "PCI ERROR EXT ADDRESS REG 0x%08x\n", + swab32(err_ext_addr)); + printk(KERN_ERR "PCI ERROR ATTRIBUTES REG 0x%08x\n", + swab32(err_attr)); + printk(KERN_ERR "PCI ERROR DATA HIGH REG 0x%08x\n", + swab32(data_hi)); + printk(KERN_ERR "PCI ERROR DATA LOW REG 0x%08x\n", + swab32(data_lo)); + printk(KERN_ERR "PCI STATUS REG 0x%04x\n", swab16(pci_status)); + printk(KERN_ERR "PCI GASKET TIMER REG 0x%08x\n", + swab32(gas_timr)); + printk(KERN_ERR "PCI PCIX TIMER REG 0x%08x\n", + swab32(pcix_timr)); + } + pci_errors++; + + return IRQ_HANDLED; +} + +#endif + +static void mvme3100_init_caches(void) +{ + u8 *l2_ctl_addr; + bd_t *binfo = (bd_t *) __res; + + l2_err_regs = ioremap(binfo->bi_immr_base + L2_ERR_REGS_OFFSET, + L2_ERR_REGS_SIZE); + + l2_ctl_addr = ioremap(binfo->bi_immr_base + 0x20000, 4); + + /* L1 inst, L1 data, and L2 are disabled at this point */ + + e500_enable_l1_inst(); + e500_enable_l1_data(); + asm volatile ("eieio"); + asm volatile ("isync"); + writel(0, l2_ctl_addr); + readl(l2_ctl_addr); + asm volatile ("eieio"); + writel(0x00030048, l2_ctl_addr); + readl(l2_ctl_addr); + asm volatile ("eieio"); + /* Enable L2 error detection */ + writel(0, l2_err_regs + L2_ERR_DIS - L2_ERR_REGS_OFFSET); + readl(l2_ctl_addr); + asm volatile ("eieio"); + /* Clear any logged L2 errors */ + writel(0x1D000080, l2_err_regs + L2_ERR_DET - L2_ERR_REGS_OFFSET); + readl(l2_ctl_addr); + asm volatile ("eieio"); + /* Enable L2 */ + writel(0x00070088, l2_ctl_addr); + readl(l2_ctl_addr); + asm volatile ("eieio"); + + printk + ("L2 cache enabled (256K cache, no memory-mapped SRAM). L2CTL reg: 0x%x\n", + swab32(readl(l2_ctl_addr))); + + iounmap(l2_ctl_addr); + + return; +} + +static void mvme3100_misc_init(void) +{ + u8 *reg_addr; + u8 reg_value; + u32 sbe_count; + bd_t *binfo = (bd_t *) __res; + +#ifdef CONFIG_MVME3100_ENABLE_DDR_ERRORS + /* Enable DDR error reporting */ + ddr_err_regs = ioremap(binfo->bi_immr_base + DDR_ERR_REGS_OFFSET, + DDR_ERR_REGS_SIZE); + + writel(0, ddr_err_regs + DDR_ERR_DIS - DDR_ERR_REGS_OFFSET); + /* Clear logged DDR errors */ + writel(swab32(0x8000000D), + ddr_err_regs + DDR_ERR_DET - DDR_ERR_REGS_OFFSET); + /* Set single-bit error threshold */ + sbe_count = readl(ddr_err_regs + DDR_ERR_SBE - DDR_ERR_REGS_OFFSET); + sbe_count = swab32(sbe_count) & 0xFF00FFFF; + sbe_count |= 0x00100000; + writel(swab32(sbe_count), + ddr_err_regs + DDR_ERR_SBE - DDR_ERR_REGS_OFFSET); +#endif + +#ifdef CONFIG_MVME3100_ENABLE_PCI_ERRORS + /* Enable PCI error reporting */ + pci_err_regs = ioremap(binfo->bi_immr_base + PCI_ERR_REGS_OFFSET, + PCI_ERR_REGS_SIZE); + writel(0, pci_err_regs + PCI_ERR_CAP_DIS - PCI_ERR_REGS_OFFSET); +#endif + + reg_addr = ioremap(MVME3100_SYSTEM_CONTROL_REG, 3); + + /* Mask FEC PHY interrupts */ + reg_value = readb(reg_addr); + reg_value |= MVME3100_FEC_PHY_MASK; + writeb(reg_value, reg_addr); + + /* Turn off Board Fail LED */ + reg_value = readb(++reg_addr); + reg_value &= ~MVME3100_BRD_FAIL_LED; + writeb(reg_value, reg_addr); + + /* Turn off SW flash write-protect */ + reg_value = readb(++reg_addr); + reg_value &= ~MVME3100_FLASH_WP_SW; + writeb(reg_value, reg_addr); + + iounmap(reg_addr); + return; +} + +#ifdef CONFIG_SERIAL_8250 +static void __init mvme3100_early_serial_map(void) +{ +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + struct uart_port serial_req; +#endif + bd_t *binfo = (bd_t *) __res; + struct plat_serial8250_port *pdata; + + mpc85xx_early_serial_map(); + + pdata = (struct plat_serial8250_port *)ppc_sys_get_pdata(MPC85xx_DUART); + pdata[1].uartclk = binfo->bi_busfreq; + pdata[1].membase = ioremap(pdata[1].mapbase, 0x1000); + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + memset(&serial_req, 0, sizeof(serial_req)); + serial_req.uartclk = binfo->bi_busfreq; + serial_req.line = 1; + serial_req.irq = 99; + serial_req.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + + serial_req.iotype = SERIAL_IO_MEM; + serial_req.mapbase = pdata[1].mapbase; + serial_req.membase = pdata[1].membase; + serial_req.regshift = 0; + + gen550_init(1, &serial_req); +#endif + pdata[2].uartclk = binfo->bi_busfreq; + pdata[2].membase = ioremap(pdata[2].mapbase, 0x1000); + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + serial_req.line = 2; + serial_req.mapbase = pdata[2].mapbase; + serial_req.membase = pdata[2].membase; + + gen550_init(2, &serial_req); +#endif + + pdata[3].uartclk = binfo->bi_busfreq; + pdata[3].membase = ioremap(pdata[3].mapbase, 0x1000); + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + serial_req.line = 3; + serial_req.mapbase = pdata[3].mapbase; + serial_req.membase = pdata[3].membase; + + gen550_init(3, &serial_req); +#endif + + pdata[4].uartclk = binfo->bi_busfreq; + pdata[4].membase = ioremap(pdata[4].mapbase, 0x1000); + +#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) + serial_req.line = 4; + serial_req.mapbase = pdata[4].mapbase; + serial_req.membase = pdata[4].membase; + + gen550_init(4, &serial_req); +#endif + +} +#endif + +/* + * Setup the architecture + */ +static void __init mvme3100_setup_arch(void) +{ + bd_t *binfo = (bd_t *) __res; + unsigned int freq; + struct gianfar_platform_data *pdata; + + if (ppc_md.progress) + ppc_md.progress("mvme3100_setup_arch(): enter", 0); + + /* get the core frequency */ + freq = BINFO_INTFREQ; + + mvme3100_init_caches(); + + /* Set loops_per_jiffy to a half-way reasonable value, + for use until calibrate_delay gets called. */ + loops_per_jiffy = freq / HZ; + + /* setup PCI host bridges */ + mpc85xx_setup_hose(); + +#ifdef CONFIG_SERIAL_8250 + mvme3100_early_serial_map(); +#endif + +#ifdef CONFIG_SERIAL_TEXT_DEBUG + /* Invalidate the entry we stole earlier. The serial ports + * should be properly mapped */ + invalidate_tlbcam_entry(num_tlbcam_entries - 1); +#endif + + /* setup the board related information for the enet controllers */ + pdata = + (struct gianfar_platform_data *)ppc_sys_get_pdata(MPC85xx_TSEC1); + if (pdata) { + pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; + pdata->interruptPHY = MPC85xx_IRQ_EXT10; + pdata->phyid = 1; + /* fixup phy address */ + pdata->phy_reg_addr += binfo->bi_immr_base; + memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); + } + + pdata = + (struct gianfar_platform_data *)ppc_sys_get_pdata(MPC85xx_TSEC2); + if (pdata) { + pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; + pdata->interruptPHY = MPC85xx_IRQ_EXT10; + pdata->phyid = 2; + /* fixup phy address */ + pdata->phy_reg_addr += binfo->bi_immr_base; + memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); + } + + pdata = (struct gianfar_platform_data *)ppc_sys_get_pdata(MPC85xx_FEC); + if (pdata) { + pdata->board_flags = 0; +// pdata->interruptPHY = MPC85xx_IRQ_EXT10; + pdata->phyid = 3; + /* fixup phy address */ + pdata->phy_reg_addr += binfo->bi_immr_base; + memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); + } +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_SDA2; +#endif + +#ifdef CONFIG_VME_BRIDGE_BOOTMEM + vme_bootmem_size = CONFIG_VME_BRIDGE_BOOTMEM_SIZE * 1024 * 1024; + + if (vme_bootmem_size > (total_memory / 2)) { + printk(KERN_WARNING "BOOTMEM Size Requested: 0x%x Total Memory 0x%lx\n", vme_bootmem_size, total_memory); + printk(KERN_WARNING "BOOTMEM Size requested has been capped at half the total memory\n"); + vme_bootmem_size = total_memory / 2; + } + vme_driver_bootmem = __alloc_bootmem(vme_bootmem_size, 0x10000, 0); + if (!vme_driver_bootmem) { + printk(KERN_WARNING "Unable to obtain boot memory for VME\n"); + vme_bootmem_size = 0; + } else { + printk(KERN_INFO "0x%x of boot memory reserved for setup of VME inbound window 7\n", vme_bootmem_size); + } +#endif + + mvme3100_misc_init(); + + if (ppc_md.progress) + ppc_md.progress("mvme3100_setup_arch(): exit", 0); +} + +#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1375) +extern ulong ds1375_get_rtc_time(void); +extern int ds1375_set_rtc_time(ulong); + +static int __init mvme3100_rtc_hookup(void) +{ + struct timespec tv; + + ppc_md.get_rtc_time = ds1375_get_rtc_time; + ppc_md.set_rtc_time = ds1375_set_rtc_time; +#if 0 + ppc_md.nvram_read_val = ds1375_read_val; + ppc_md.nvram_write_val = ds1375_write_val; +#endif + tv.tv_nsec = 0; + tv.tv_sec = (ppc_md.get_rtc_time) (); + do_settimeofday(&tv); + + return 0; +} + +late_initcall(mvme3100_rtc_hookup); + +#endif + +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + + /* parse_bootinfo must always be called first */ + parse_bootinfo(find_bootinfo()); + + /* + * If we were passed in a board information, copy it into the + * residual data area. + */ + if (r3) { + memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t)); + } +#ifdef CONFIG_SERIAL_TEXT_DEBUG + { + bd_t *binfo = (bd_t *) __res; + struct uart_port p; + + /* Use the last TLB entry to map CCSRBAR to allow access to UART regs */ + settlbcam(num_tlbcam_entries - 1, BINFO_IMMR_BASE, + BINFO_IMMR_BASE, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0); + + memset(&p, 0, sizeof(p)); + p.iotype = SERIAL_IO_MEM; + p.membase = (void *)binfo->bi_immr_base + MPC85xx_UART0_OFFSET; + p.uartclk = binfo->bi_busfreq; + + gen550_init(0, &p); + } +#endif + +#if defined(CONFIG_BLK_DEV_INITRD) + /* + * If the init RAM disk has been configured in, and there's a valid + * starting address for it, set it up. + */ + if (r4) { + initrd_start = r4 + KERNELBASE; + initrd_end = r5 + KERNELBASE; + } +#endif /* CONFIG_BLK_DEV_INITRD */ + + /* Copy the kernel command line arguments to a safe place. */ + + if (r6) { + *(char *)(r7 + KERNELBASE) = 0; + strcpy(cmd_line, (char *)(r6 + KERNELBASE)); + } + + identify_ppc_sys_by_id(mfspr(SPRN_SVR)); + +#ifdef CONFIG_VME_BRIDGE + { + extern void vmemod_setup_options(char *); + + vmemod_setup_options(cmd_line); + + + } +#endif + ppc_md.setup_arch = mvme3100_setup_arch; + ppc_md.show_cpuinfo = mvme3100_show_cpuinfo; + + ppc_md.init_IRQ = mvme3100_init_IRQ; + ppc_md.get_irq = openpic_get_irq; + + ppc_md.restart = mvme3100_restart; + ppc_md.power_off = mpc85xx_power_off; + ppc_md.halt = mpc85xx_halt; + + ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory; + + ppc_md.time_init = NULL; + ppc_md.set_rtc_time = NULL; + ppc_md.get_rtc_time = NULL; + ppc_md.nvram_read_val = NULL; + ppc_md.nvram_write_val = NULL; + + ppc_md.calibrate_decr = mpc85xx_calibrate_decr; + + ppc_md.pcibios_fixup = mvme3100_pci_fixups; + +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) + ppc_md.progress = gen550_progress; +#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB) + ppc_md.early_serial_map = mvme3100_early_serial_map; +#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */ + + if (ppc_md.progress) + ppc_md.progress("mvme3100_init(): exit", 0); + + return; +} diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/85xx/mvme3100.h linux-2.6.14.mod/arch/ppc/platforms/85xx/mvme3100.h --- linux-2.6.14.orig/arch/ppc/platforms/85xx/mvme3100.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/85xx/mvme3100.h 2006-02-16 13:10:50.000000000 -0700 @@ -0,0 +1,155 @@ +/* + * arch/ppc/platforms/85xx/mvme3100.h + * + * MVME3100 board definitions + * + * Ajit Prem + * + * Copyright 2004-2006 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MACH_MVME3100_H__ +#define __MACH_MVME3100_H__ + +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_UBOOT + +#define BINFO_INTFREQ 833333333 +#define BINFO_BUSFREQ 333333333 +#define BINFO_IMMR_BASE 0xe1000000 +#define BINFO_MEMSIZE 0x20000000 +#define BINFO_BAUDRATE 9600 + +#endif + +#define BOARD_CCSRBAR ((uint)0xe1000000) + +/* PCI interrupt controller */ +#define PIRQA MPC85xx_IRQ_EXT1 +#define PIRQB MPC85xx_IRQ_EXT2 +#define PIRQC MPC85xx_IRQ_EXT3 +#define PIRQD MPC85xx_IRQ_EXT4 + +#define MPC85XX_PCI1_LOWER_IO 0x00000000 +#define MPC85XX_PCI1_UPPER_IO 0x00ffffff + +#define MPC85XX_PCI1_LOWER_MEM 0x80000000 +#define MPC85XX_PCI1_UPPER_MEM 0xdfffffff + +#define MPC85XX_PCI1_IO_BASE 0xe0000000 +#define MPC85XX_PCI1_MEM_OFFSET 0x00000000 + +#define MPC85XX_PCI1_IO_SIZE 0x01000000 + +/* Flash */ +#define MVME3100_FLASH_BASE_128M 0xf8000000 +#define MVME3100_FLASH_SIZE_128M 0x08000000 + +#define MVME3100_FLASH_BASE_64M 0xfc000000 +#define MVME3100_FLASH_SIZE_64M 0x04000000 + +/* System Control and Status Registers */ +#define MVME3100_SYSTEM_STATUS_REG 0xE2000000 +#define MVME3100_SYSTEM_CONTROL_REG 0xE2000001 +#define MVME3100_STATUS_INDICATOR_REG 0xE2000002 +#define MVME3100_FLASH_CTRL_STAT_REG 0xE2000003 +#define MVME3100_PCI_BUS_A_STATUS_REG 0xE2000004 +#define MVME3100_PCI_BUS_B_STATUS_REG 0xE2000005 +#define MVME3100_PCI_BUS_C_STATUS_REG 0xE2000006 +#define MVME3100_INTERRUPT_DETECT_REG 0xE2000007 +#define MVME3100_PRESENCE_DETECT_REG 0xE2000008 +#define MVME3100_PLD_REVISION_REG 0xE2000009 +#define MVME3100_PLD_DATE_CODE_REG 0xE200000C + +/* System Status Register */ +#define MVME3100_SAFE_START 0x10 +#define MVME3100_ABORT_STATUS 0x08 +#define MVME3100_BOARD_TYPE_MASK 0x03 +#define MVME3100_BOARD_TYPE_PRPMC 0x01 +#define MVME3100_BOARD_TYPE_VME 0x00 + +/* System Control Register */ +#define MVME3100_BOARD_RESET 0xA0 +#define MVME3100_FEC_PHY_MASK 0x04 +#define MVME3100_EEPROM_WP 0x02 +#define MVME3100_TSTAT_MASK 0x01 + +/* Status Indicator Register */ +#define MVME3100_BRD_FAIL_LED 0x01 +#define MVME3100_USR1_LED 0x02 +#define MVME3100_USR2_LED 0x04 +#define MVME3100_USR3_LED 0x08 + +/* Flash Control/Status Register */ +#define MVME3100_FLASH_MAP_SELECT 0x10 +#define MVME3100_FLASH_WP_SW 0x08 +#define MVME3100_FLASH_WP_HW 0x04 +#define MVME3100_FLASH_BLK_SEL 0x02 +#define MVME3100_FLASH_RDY 0x01 + +/* PCI Bus A Status Register */ +#define MVME3100_PCI_BUS_A_64B 0x08 +#define MVME3100_PCI_BUS_A_PCIX 0x04 +#define MVME3100_PCI_BUS_A_SPD_MASK 0x03 +#define MVME3100_PCI_BUS_A_SPD_133 0x03 +#define MVME3100_PCI_BUS_A_SPD_100 0x02 +#define MVME3100_PCI_BUS_A_SPD_66 0x01 +#define MVME3100_PCI_BUS_A_SPD_33 0x00 + +/* PCI Bus B Status Register */ +#define MVME3100_PCI_BUS_B_3_3V_VIO 0x80 +#define MVME3100_PCI_BUS_B_5_0V_VIO 0x40 +#define MVME3100_PCI_BUS_B_ERDY2 0x20 +#define MVME3100_PCI_BUS_B_ERDY1 0x10 +#define MVME3100_PCI_BUS_B_64B 0x08 +#define MVME3100_PCI_BUS_B_PCIX 0x04 +#define MVME3100_PCI_BUS_B_SPD_MASK 0x03 +#define MVME3100_PCI_BUS_B_SPD_133 0x03 +#define MVME3100_PCI_BUS_B_SPD_100 0x02 +#define MVME3100_PCI_BUS_B_SPD_66 0x01 +#define MVME3100_PCI_BUS_B_SPD_33 0x00 + +/* PCI Bus C Status Register */ +#define MVME3100_PCI_BUS_C_64B 0x08 +#define MVME3100_PCI_BUS_C_PCIX 0x04 +#define MVME3100_PCI_BUS_C_SPD_MASK 0x03 +#define MVME3100_PCI_BUS_C_SPD_133 0x03 +#define MVME3100_PCI_BUS_C_SPD_100 0x02 +#define MVME3100_PCI_BUS_C_SPD_66 0x01 +#define MVME3100_PCI_BUS_C_SPD_33 0x00 + +/* Interrupt Detect Register */ +#define MVME3100_FEC_PHY_INTERRUPT 0x04 +#define MVME3100_TSEC2_PHY_INTERRUPT 0x02 +#define MVME3100_TSEC1_PHY_INTERRUPT 0x01 + +/* Presence Detect Register */ +#define MVME3100_PMCSPAN_PRESENT 0x04 +#define MVME3100_PMC2_PRESENT 0x02 +#define MVME3100_PMC1_PRESENT 0x01 + +#define MVME3100_BASE_BAUD 1843200 +#define QUART_BASE_BAUD (MVME3100_BASE_BAUD / 16) +#define MVME3100_UART_SIZE 0x8 + +#define MVME3100_SERIAL_1 0xE2011000U +#define MVME3100_SERIAL_2 0xE2012000U +#define MVME3100_SERIAL_3 0xE2013000U +#define MVME3100_SERIAL_4 0xE2014000U + +#define MVME3100_IDE_INT0 MPC85xx_IRQ_EXT2 +#define MVME3100_SERIAL_IRQ MPC85xx_IRQ_EXT3 + +#endif /* __MACH_MVME3100_H__ */ diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/85xx/mvme3100_timer.c linux-2.6.14.mod/arch/ppc/platforms/85xx/mvme3100_timer.c --- linux-2.6.14.orig/arch/ppc/platforms/85xx/mvme3100_timer.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/85xx/mvme3100_timer.c 2006-02-16 13:15:09.000000000 -0700 @@ -0,0 +1,402 @@ +/* + * arch/ppc/platforms/85xx/mvme3100_timer.c + * + * MVME3100 Tick Timers Support + * + * Author: Ajit Prem + * + * Copyright 2005-2006 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "mvme3100.h" +#include + +#define MVME3100_TICK_TIMER_BASE 0xE2020000 +#define MVME3100_TICK_TIMER_BLOCK_SIZE 0x4C + +#define MVME3100_TICK_TIMER_PRESCALER_REG_OFFSET 0x0 +#define MVME3100_TICK_TIMER_CONTROL_REG_OFFSET 0x10 +#define MVME3100_TICK_TIMER_COMPARE_REG_OFFSET 0x14 +#define MVME3100_TICK_TIMER_COUNTER_REG_OFFSET 0x18 + +#define MVME3100_TICK_TIMER_ENC 0x00000001 +#define MVME3100_TICK_TIMER_COC 0x00000002 +#define MVME3100_TICK_TIMER_COVF 0x00000004 +#define MVME3100_TICK_TIMER_OVF 0x000000F0 +#define MVME3100_TICK_TIMER_ENINT 0x00000100 +#define MVME3100_TICK_TIMER_CINT 0x00000200 +#define MVME3100_TICK_TIMER_INTS 0x00000400 + +#define MIN_MICROSECONDS 10000 +#define MAX_TICKS 0xFFFFFFFF + +struct mvme3100_timer_t { + mvme3100_timer_f func; + void *func_data; + int started; + int periodic; + ulong period; + ulong ticks; +}; + +#define ALL_MSG "mvme3100_timer: " + +#ifdef MVME3100_TIMER_DEBUG +int mvme3100_timer_debug = MVME3100_TIMER_DEBUG; +MODULE_PARM(mvme3100_timer_debug, "i"); +#define DEBUG(n, fmt, args...) if (mvme3100_timer_debug>(n)) printk(KERN_INFO ALL_MSG fmt, ## args) +static const char *version = "mvme3100_timer.c 1.0.0 (Ajit Prem)"; +#else +#define DEBUG(n, fmt, args...) +#endif + +static struct mvme3100_timer_t mvme3100_timer[4]; +static u8 *mvme3100_timer_base; +static u32 clk_out = 1; /* Ticks per microsecond */ +static int mvme3100_timer_irq = MPC85xx_IRQ_EXT1; +static spinlock_t mvme3100_timer_lock = SPIN_LOCK_UNLOCKED; + +static irqreturn_t mvme3100_timer_int_handler(int irq, void *data, + struct pt_regs *regs) +{ + struct mvme3100_timer_t *info = data; + mvme3100_timer_f func; + void *func_data; + int timer_number; + u32 ctrl_reg; + + for (timer_number = 0; timer_number <= 3; timer_number++) { + if (swab32(readl(mvme3100_timer_base + + (timer_number + + 1) * + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET)) & + MVME3100_TICK_TIMER_INTS) { + info = &mvme3100_timer[timer_number]; + func_data = info->func_data; + func = info->func; + if (info->func) { + func(func_data); + } + + if (!info->periodic) { + mvme3100_timer_stop(timer_number); + } else { + ctrl_reg = swab32(readl(mvme3100_timer_base + + ((timer_number + + 1) * + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET))); + ctrl_reg &= ~MVME3100_TICK_TIMER_ENC; + ctrl_reg = + MVME3100_TICK_TIMER_COVF | + MVME3100_TICK_TIMER_CINT; + writel(swab32(ctrl_reg), + mvme3100_timer_base + + ((timer_number + + 1) * + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET)); + writel(0, + mvme3100_timer_base + + ((timer_number + + 1) * + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET) + + + (MVME3100_TICK_TIMER_COUNTER_REG_OFFSET - + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET)); + DEBUG(1, + ("Timer %d Counter 0x%x Compare 0x%x\n", + timer_number, + swab32(readl + (mvme3100_timer_base + + ((timer_number + + 1) * + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET) + + + (MVME3100_TICK_TIMER_COUNTER_REG_OFFSET + - + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET))), + swab32(readl + (mvme3100_timer_base + + ((timer_number + + 1) * + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET) + + + (MVME3100_TICK_TIMER_COMPARE_REG_OFFSET + - + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET))))); + writel(swab32 + (MVME3100_TICK_TIMER_ENC | + MVME3100_TICK_TIMER_COC | + MVME3100_TICK_TIMER_ENINT), + mvme3100_timer_base + + ((timer_number + + 1) * + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET)); + } + } + } + + return IRQ_HANDLED; +} + +/* + * Stop the timer + */ +EXPORT_SYMBOL(mvme3100_timer_stop); +int mvme3100_timer_stop(int timer_number) +{ + u32 reset_value; + unsigned long flags; + + if ((timer_number < 0) || (timer_number > 3)) + return -EINVAL; + + spin_lock_irqsave(&mvme3100_timer_lock, flags); + reset_value = swab32(readl(mvme3100_timer_base + + ((timer_number + + 1) * + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET))); + reset_value &= ~MVME3100_TICK_TIMER_ENC; + reset_value &= ~MVME3100_TICK_TIMER_ENINT; + reset_value = MVME3100_TICK_TIMER_COVF | MVME3100_TICK_TIMER_CINT; + writel(swab32(reset_value), + mvme3100_timer_base + + ((timer_number + 1) * MVME3100_TICK_TIMER_CONTROL_REG_OFFSET)); + writel(0, mvme3100_timer_base + + ((timer_number + 1) * MVME3100_TICK_TIMER_CONTROL_REG_OFFSET) + + (MVME3100_TICK_TIMER_COUNTER_REG_OFFSET - + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET)); + writel(0xffffffff, mvme3100_timer_base + + ((timer_number + 1) * MVME3100_TICK_TIMER_CONTROL_REG_OFFSET) + + (MVME3100_TICK_TIMER_COMPARE_REG_OFFSET - + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET)); + mvme3100_timer[timer_number].func = NULL; + mvme3100_timer[timer_number].func_data = NULL; + mvme3100_timer[timer_number].started = 0; + mvme3100_timer[timer_number].periodic = 0; + mvme3100_timer[timer_number].period = 0; + mvme3100_timer[timer_number].ticks = 0xFFFFFFFF; + spin_unlock_irqrestore(&mvme3100_timer_lock, flags); + + return 0; +} + +/* + * Start the timer + */ +EXPORT_SYMBOL(mvme3100_timer_start); +int mvme3100_timer_start(int timer_number, unsigned long microseconds, + mvme3100_timer_f func, void *func_data, int periodic) +{ + int res = 0; + unsigned long flags; + unsigned long ticks; + + printk(KERN_INFO + "mvme3100_timer: start_timer: num %d microseconds 0x%lx periodic %d\n", + timer_number, microseconds, periodic); + if ((timer_number < 0) || (timer_number > 3)) + return -EINVAL; + if ((microseconds < MIN_MICROSECONDS) || + (microseconds > MAX_TICKS / clk_out)) + return -EINVAL; + if (func == NULL) + return -EINVAL; + if (mvme3100_timer[timer_number].started == 1) + return -EBUSY; + if ((res = mvme3100_timer_stop(timer_number)) < 0) + return res; + ticks = microseconds * clk_out; + spin_lock_irqsave(&mvme3100_timer_lock, flags); + mvme3100_timer[timer_number].started = 1; + mvme3100_timer[timer_number].func = func; + mvme3100_timer[timer_number].func_data = func_data; + mvme3100_timer[timer_number].periodic = periodic; + mvme3100_timer[timer_number].period = microseconds; + mvme3100_timer[timer_number].ticks = ticks; + writel(swab32(ticks), mvme3100_timer_base + + ((timer_number + 1) * MVME3100_TICK_TIMER_CONTROL_REG_OFFSET) + + (MVME3100_TICK_TIMER_COMPARE_REG_OFFSET - + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET)); + writel(0, mvme3100_timer_base + + ((timer_number + 1) * MVME3100_TICK_TIMER_CONTROL_REG_OFFSET) + + (MVME3100_TICK_TIMER_COUNTER_REG_OFFSET - + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET)); + writel(swab32(MVME3100_TICK_TIMER_ENC | MVME3100_TICK_TIMER_COC | + MVME3100_TICK_TIMER_ENINT), + mvme3100_timer_base + + ((timer_number + 1) * MVME3100_TICK_TIMER_CONTROL_REG_OFFSET)); + spin_unlock_irqrestore(&mvme3100_timer_lock, flags); + + return 0; +} + +/* + * Get the timer resolution, in microseconds/tick + */ +EXPORT_SYMBOL(mvme3100_timer_get_resolution); +unsigned long mvme3100_timer_get_resolution(void) +{ + u32 prescaler_adjust; + + /* + * Prescaler_adjust = 256 - CLKIN/CLKOUT + * CLKIN = 25 MHz + */ + + prescaler_adjust = readl(mvme3100_timer_base + + MVME3100_TICK_TIMER_PRESCALER_REG_OFFSET); + return (25 / (256 - prescaler_adjust)); +} + +/* + * Set the timer resolution, in ticks/microsecond + */ +EXPORT_SYMBOL(mvme3100_timer_set_resolution); +int mvme3100_timer_set_resolution(unsigned long ticks) +{ + u32 prescaler_adjust; + int i; + unsigned long flags; + + /* + * Prescaler_adjust = 256 - CLKIN/CLKOUT + * CLKIN = 25 MHz + */ + + if ((ticks < MIN_TICKS_PER_MICROSECOND) || + (ticks > MAX_TICKS_PER_MICROSECOND)) + return -EINVAL; + + clk_out = ticks; + prescaler_adjust = 256 - (25 / clk_out); + + spin_lock_irqsave(&mvme3100_timer_lock, flags); + for (i = 0; i <= 3; i++) { + if (mvme3100_timer[i].started == 1) { + spin_unlock_irqrestore(&mvme3100_timer_lock, flags); + return -EBUSY; + } + } + + writel(prescaler_adjust, mvme3100_timer_base + + MVME3100_TICK_TIMER_PRESCALER_REG_OFFSET); + spin_unlock_irqrestore(&mvme3100_timer_lock, flags); + + return 0; +} + +/* + * Get the timer value, in ticks + */ +EXPORT_SYMBOL(mvme3100_timer_get_ticks); +unsigned long mvme3100_timer_get_ticks(int timer_number) +{ + if ((timer_number < 0) || (timer_number > 3)) + return -EINVAL; + + return swab32(readl(mvme3100_timer_base + + ((timer_number + + 1) * MVME3100_TICK_TIMER_CONTROL_REG_OFFSET) + + (MVME3100_TICK_TIMER_COUNTER_REG_OFFSET - + MVME3100_TICK_TIMER_CONTROL_REG_OFFSET))); +} + +#ifdef CONFIG_PROC_FS + +static int +mvme3100_timer_proc_read(char *buf, char **start, off_t off, int len, int *eof, + void *data) +{ + int i; + + len = 0; + len += + sprintf(buf + len, + "\nTimer Active Periodic Period(ticks) Period(microseconds)\n"); + len += + sprintf(buf + len, + "_____ ______ ________ _____________ ____________________\n"); + for (i = 0; i <= 3; i++) { + len += + sprintf(buf + len, + "#%d %c %c 0x%08lx %ld\n", + i + 1, + ((mvme3100_timer[i].started == 1) ? 'y' : 'n'), + ((mvme3100_timer[i].periodic == 1) ? 'y' : 'n'), + ((mvme3100_timer[i].periodic == + 1) ? mvme3100_timer[i].ticks : 0), + ((mvme3100_timer[i].periodic == + 1) ? mvme3100_timer[i].period : 0)); + } + return len; +} + +#endif /* CONFIG_PROC_FS */ + +static __init int mvme3100_timer_init(void) +{ + int res = 0; + int i; + + printk(KERN_INFO "mvme3100-timer: MVME3100 Tick Timers\n"); + + mvme3100_timer_base = (u8 *) ioremap(MVME3100_TICK_TIMER_BASE, + MVME3100_TICK_TIMER_BLOCK_SIZE); + if (mvme3100_timer_base == NULL) + return -ENOMEM; + + for (i = 0; i <= 3; i++) { + mvme3100_timer[i].func = NULL; + mvme3100_timer[i].func_data = NULL; + mvme3100_timer[i].started = 0; + mvme3100_timer[i].periodic = 0; + mvme3100_timer[i].period = 0; + mvme3100_timer[i].ticks = 0; + } + res = request_irq(mvme3100_timer_irq, mvme3100_timer_int_handler, + SA_INTERRUPT | SA_SHIRQ, + "MVME3100 Tick Timers", &mvme3100_timer[0]); + if (res < 0) { + printk(KERN_ERR "MVME3100 Timer: Can't allocate IRQ %d.\n", + mvme3100_timer_irq); + return res; + } +#ifdef CONFIG_PROC_FS + create_proc_read_entry("mvme3100_timers", 0, NULL, + mvme3100_timer_proc_read, NULL); +#endif + return 0; +} + +static __exit void mvme3100_timer_exit(void) +{ + int timer_number; + + for (timer_number = 0; timer_number <= 3; timer_number++) { + mvme3100_timer_stop(timer_number); + } + free_irq(mvme3100_timer_irq, &mvme3100_timer[0]); + iounmap(mvme3100_timer_base); +} + +MODULE_LICENSE("GPL"); + +MODULE_AUTHOR("Ajit Prem "); +MODULE_DESCRIPTION("MVME3100 Tick Timer driver"); + +module_init(mvme3100_timer_init); +module_exit(mvme3100_timer_exit); diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/Makefile linux-2.6.14.mod/arch/ppc/platforms/Makefile --- linux-2.6.14.orig/arch/ppc/platforms/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/Makefile 2006-01-20 16:57:41.000000000 -0700 @@ -31,6 +31,10 @@ obj-$(CONFIG_KATANA) += katana.o obj-$(CONFIG_HDPU) += hdpu.o obj-$(CONFIG_MVME5100) += mvme5100.o +obj-$(CONFIG_MVME5500) += mvme5500.o +obj-$(CONFIG_MVME6100) += mvme6100.o +obj-$(CONFIG_MCP905) += mcp905.o + obj-$(CONFIG_PAL4) += pal4_setup.o pal4_pci.o obj-$(CONFIG_POWERPMC250) += powerpmc250.o obj-$(CONFIG_PPLUS) += pplus.o diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/mcp905.c linux-2.6.14.mod/arch/ppc/platforms/mcp905.c --- linux-2.6.14.orig/arch/ppc/platforms/mcp905.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/mcp905.c 2006-03-14 14:36:09.000000000 -0700 @@ -0,0 +1,817 @@ +/* + * mcp905.c + * + * Board setup routines for the Motorola MCP905 Board. + * + * Author: Ajit Prem + * + * Copyright 2003-2006 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mcp905.h" + +extern void _set_L3CR(unsigned long); +extern char cmd_line[]; +extern unsigned long total_memory; + +extern void gen550_progress(char *, unsigned short); +extern void gen550_init(int, struct uart_port *); + +static unsigned long mcp905_find_end_of_memory(void); + +static struct mv64x60_handle bh; +static void __iomem *sram_base; + +TODC_ALLOC(); + +/* + * Motorola MCP905 Board PCI interrupt routing. + */ +static int __init +mcp905_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + struct pci_controller *hose = (struct pci_controller *)(dev->sysdata); + + if (hose->index == 0) { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {82, 83, 82, 83}, /* IDSEL 4 - PMC 2 IDSEL */ + {83, 82, 83, 82}, /* IDSEL 5 - PMC 2 IDSELB */ + + }; + + const long min_idsel = 4, max_idsel = 5, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } else { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {80, 81, 80, 81}, /* IDSEL 4 - 16 - PMC 1 IDSEL */ + {80, 81, 80, 81}, /* IDSEL 5 - PMC 1 IDSELB */ + {81, 0, 0, 0}, /* IDSEL 6 - PCI646U2 IDE */ + {80, 0, 0, 0}, /* IDSEL 7 - 21555 Bridge */ + }; + + const long min_idsel = 4, max_idsel = 7, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } +} + +#define SET_PCI_COMMAND_INVALIDATE + +#ifdef SET_PCI_COMMAND_INVALIDATE +static void __init set_pci_command_invalidate(void) +{ + struct pci_dev *dev = NULL; + u16 val; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + pci_read_config_word(dev, PCI_COMMAND, &val); + val |= PCI_COMMAND_INVALIDATE; + pci_write_config_word(dev, PCI_COMMAND, val); + } +} +#endif + +static void __init mcp905_pci_fixups(void) +{ +#ifdef SET_PCI_COMMAND_INVALIDATE + set_pci_command_invalidate(); +#endif +} + +static void __init mcp905_setup_bridge(void) +{ + struct mv64x60_setup_info si; + int i; + + memset(&si, 0, sizeof(si)); + + si.phys_reg_base = CONFIG_MV64X60_NEW_BASE; + + si.pci_0.enable_bus = 1; + + si.pci_0.pci_io.cpu_base = MCP905_PCI_0_IO_START_PROC; + si.pci_0.pci_io.pci_base_hi = 0; + si.pci_0.pci_io.pci_base_lo = MCP905_PCI_0_IO_START; + si.pci_0.pci_io.size = MCP905_PCI_0_IO_SIZE; + si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; + + si.pci_0.pci_mem[0].cpu_base = MCP905_PCI_0_MEM_START_PROC; + si.pci_0.pci_mem[0].pci_base_hi = 0; + si.pci_0.pci_mem[0].pci_base_lo = MCP905_PCI_0_MEM_START; + si.pci_0.pci_mem[0].size = MCP905_PCI_0_MEM_SIZE; + si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; + + si.pci_0.pci_cmd_bits = 0; + si.pci_0.latency_timer = 0x80; + + si.pci_1.enable_bus = 1; + + si.pci_1.pci_io.cpu_base = MCP905_PCI_1_IO_START_PROC; + si.pci_1.pci_io.pci_base_hi = 0; + si.pci_1.pci_io.pci_base_lo = MCP905_PCI_1_IO_START; + si.pci_1.pci_io.size = MCP905_PCI_1_IO_SIZE; + si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; + + si.pci_1.pci_mem[0].cpu_base = MCP905_PCI_1_MEM_START_PROC; + si.pci_1.pci_mem[0].pci_base_hi = 0; + si.pci_1.pci_mem[0].pci_base_lo = MCP905_PCI_1_MEM_START; + si.pci_1.pci_mem[0].size = MCP905_PCI_1_MEM_SIZE; + si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; + + si.pci_1.pci_cmd_bits = 0; + si.pci_1.latency_timer = 0x80; + for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) { +#if defined(CONFIG_NOT_COHERENT_CACHE) + si.cpu_prot_options[i] = 0; + si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; + si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; + si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; + + si.pci_1.acc_cntl_options[i] = + MV64360_PCI_ACC_CNTL_SNOOP_NONE | + MV64360_PCI_ACC_CNTL_SWAP_NONE | + MV64360_PCI_ACC_CNTL_MBURST_128_BYTES | + MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; +#else + si.cpu_prot_options[i] = 0; + + si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB; + si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB; + si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB; + + si.pci_0.acc_cntl_options[i] = + MV64360_PCI_ACC_CNTL_SNOOP_WB | + MV64360_PCI_ACC_CNTL_SWAP_NONE | + MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | + MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES; + + si.pci_1.acc_cntl_options[i] = + MV64360_PCI_ACC_CNTL_SNOOP_WB | + MV64360_PCI_ACC_CNTL_SWAP_NONE | + MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | + MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES; +#endif + } + + if (mv64x60_init(&bh, &si)) + printk(KERN_WARNING "Bridge initialization failed.\n"); + + pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */ + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mcp905_map_irq; + ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; + + mv64x60_set_bus(&bh, 0, 0); + bh.hose_a->first_busno = 0; + bh.hose_a->last_busno = 0xff; + bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0); + + bh.hose_b->first_busno = bh.hose_a->last_busno + 1; + mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno); + bh.hose_b->last_busno = 0xff; + bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, + bh.hose_b->first_busno); + + return; +} + +/* Bridge & platform setup routines */ +void __init mcp905_intr_setup(void) +{ + if (ppc_md.progress) + ppc_md.progress("mcp905_intr_setup: enter", 0); + + /* MPP 7 */ + mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_0, + BIT28 | BIT29 | BIT30 | BIT31); + /* MPP 16-23 */ + mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_2, 0xffffffff); + + /* + * Define GPP 7, 16-23 interrupt polarity as active low + * input signal and level triggered + */ + mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, + BIT7 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | + BIT22 | BIT23); + mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, + BIT5 | BIT7 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | + BIT21 | BIT22 | BIT23); + + /* Config GPP interrupt controller to respond to level trigger */ + + mv64x60_set_bits(&bh, MV64x60_COMM_ARBITER_CNTL, (1 << 10)); + + /* Erratum FEr PCI-#8 */ + mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1 << 5) | (1 << 9)); + mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1 << 5) | (1 << 9)); + + /* + * Dismiss and then enable interrupt on GPP interrupt cause + * for CPU #0 + */ + mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, + ~(BIT7 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | + BIT21 | BIT22 | BIT23)); + + mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, + BIT7 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | + BIT21 | BIT22 | BIT23); + + /* + * Dismiss and then enable interrupt on CPU #0 high cause reg + * BIT26 summarizes GPP interrupts 16-23 (Need MPP 16-23) + * BIT24 summarizes GPP interrupts 0-7 (Need MPP 7) + */ + mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, BIT26 | BIT24); + + if (ppc_md.progress) + ppc_md.progress("mcp905_intr_setup: exit", 0); +} + +void __init mcp905_setup_peripherals(void) +{ + int bank_b_boot; + u8 *bankp; + u32 boot_bank_base; + u32 boot_bank_size; + u32 cs0_bank_base; + u32 cs0_bank_size; + + if (ppc_md.progress) + ppc_md.progress("mcp905_setup_peripherals: enter", 0); + + bankp = ioremap(MCP905_BOARD_STATUS_REG_1, 1); + bank_b_boot = readb(bankp) & MCP905_BOARD_BANK_SEL_MASK; + if (bank_b_boot) { + cs0_bank_base = MCP905_BANK_A_FLASH_BASE; + cs0_bank_size = MCP905_BANK_A_FLASH_SIZE; + boot_bank_base = MCP905_BANK_B_FLASH_BASE; + boot_bank_size = MCP905_BANK_B_FLASH_SIZE; + } else { + cs0_bank_base = MCP905_BANK_B_FLASH_BASE; + cs0_bank_size = MCP905_BANK_B_FLASH_SIZE; + boot_bank_base = MCP905_BANK_A_FLASH_BASE; + boot_bank_size = MCP905_BANK_A_FLASH_SIZE; + } + + /* Set up windows for flash banks */ + mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, + boot_bank_base, boot_bank_size, 0); + bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); + + mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, + cs0_bank_base, cs0_bank_size, 0); + bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN); + + mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, + MCP905_DEVICE_CS1_BASE, MCP905_DEVICE_CS1_SIZE, + 0); + bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); + + /* Disable unused windows */ + mv64x60_write(&bh, MV64x60_CPU2DEV_2_BASE, 0); + mv64x60_write(&bh, MV64x60_CPU2DEV_2_SIZE, 0); + mv64x60_write(&bh, MV64x60_CPU2DEV_3_BASE, 0); + mv64x60_write(&bh, MV64x60_CPU2DEV_3_SIZE, 0); + + /* Set up internal SRAM window */ + mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, + MCP905_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, + 0); + bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); + sram_base = ioremap(MCP905_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE); + + /* Set up Enet->SRAM window */ + mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN, + MCP905_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, + 0x2); + bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN); + + /* Give enet r/w access to memory region */ + mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_0, (0x3 << (4 << 1))); + mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_1, (0x3 << (4 << 1))); + mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_2, (0x3 << (4 << 1))); + + mv64x60_clr_bits(&bh, MV64x60_PCI0_PCI_DECODE_CNTL, (1 << 3)); + mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3)); + /* Turn off timer/counters */ + mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, + ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24))); + + /* Only 1 CPU */ + mv64x60_set_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1 << 9)); + +#if defined(CONFIG_NOT_COHERENT_CACHE) + mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x00160000); +#else + mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2); +#endif + + /* + * Set the SRAM to 0. Note that this may generate parity errors on + * internal data path in SRAM since it is the first time accessing it + * (if firmware hasn't done it already). + */ + memset(sram_base, 0, MV64360_SRAM_SIZE); + + /* set up PCI interrupt controller */ + mcp905_intr_setup(); + + if (ppc_md.progress) + ppc_md.progress("mcp905_setup_peripherals: exit", 0); +} + +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) +static void __init mcp905_early_serial_map(void) +{ + struct uart_port serial_req; + + memset(&serial_req, 0, sizeof(serial_req)); + serial_req.uartclk = MCP905_BASE_BAUD; + serial_req.irq = MCP905_UART_0_IRQ; + serial_req.line = 0; + serial_req.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + serial_req.iotype = SERIAL_IO_MEM; + serial_req.membase = (u_char *) MCP905_SERIAL_0; + serial_req.regshift = 0; + + gen550_init(0, &serial_req); + + if (early_serial_setup(&serial_req) != 0) { + printk("Early serial init of port 0 failed\n"); + } + + /* Assume early_serial_setup() doesn't modify serial_req */ + serial_req.line = 1; + serial_req.irq = MCP905_UART_1_IRQ; + serial_req.membase = (u_char *) MCP905_SERIAL_1; + + gen550_init(1, &serial_req); + + if (early_serial_setup(&serial_req) != 0) { + printk("Early serial init of port 1 failed\n"); + } +} +#endif + +static void __init mcp905_init_caches(void) +{ + uint val; + + /* Enable L2 and L3 caches (if 745x) */ + val = _get_L2CR(); + val |= L2CR_L2E; + _set_L2CR(val); + + val = _get_L3CR(); + val |= L3CR_L3E; + _set_L3CR(val); + +#if 0 + val = mfspr(HID1); + val &= ~HID0_EBD; + mtspr(HID1, val); + asm volatile ("isync"); + asm volatile ("sync"); +#endif +} + +static void __init mcp905_misc_init(void) +{ + u8 *status_reg_2_addr; + u8 status_reg_2; + + status_reg_2_addr = ioremap(MCP905_BOARD_STATUS_REG_2, 1); + status_reg_2 = readb(status_reg_2_addr); + status_reg_2 &= ~MCP905_BOARD_FAIL_MASK; + status_reg_2 &= ~MCP905_BOARD_FLASH_WP_MASK; + writeb(status_reg_2, status_reg_2_addr); + iounmap(status_reg_2_addr); + + return; +} + +static void __init mcp905_setup_arch(void) +{ + if (ppc_md.progress) + ppc_md.progress("mcp905_setup_arch: enter", 0); + + loops_per_jiffy = 50000000 / HZ; + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_SDA2; +#endif + + mcp905_init_caches(); + + if (ppc_md.progress) + ppc_md.progress("mcp905_setup_arch: find_bridges", 0); + + mcp905_setup_bridge(); + + if (ppc_md.progress) + ppc_md.progress("mcp905_setup_arch: find_bridges done", 0); + + mcp905_setup_peripherals(); + + TODC_INIT(TODC_TYPE_MK48T37, 0, 0, + ioremap(MCP905_TODC_BASE, MCP905_TODC_SIZE), 8); + + mcp905_misc_init(); + + printk("Motorola Computer Group MCP905 Board\n"); + printk("MCP905 port (C) 2002-2006 Motorola, Inc.\n"); + + if (ppc_md.progress) + ppc_md.progress("mcp905_setup_arch: exit", 0); + + return; +} + +/* + * Set BAT 3 to map 0xf0000000 to end of physical memory space. + */ +static __inline__ void mcp905_set_bat(void) +{ + mb(); + mtspr(SPRN_DBAT1U, 0xf0001ffe); + mtspr(SPRN_DBAT1L, 0xf000002a); + mb(); + + return; +} + +unsigned long __init mcp905_find_end_of_memory(void) +{ + return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE, + MV64x60_TYPE_MV64360); +} + +static void __init mcp905_map_io(void) +{ + io_block_mapping(0xf1000000, 0xf1000000, 0x01000000, _PAGE_IO); + io_block_mapping(MCP905_INTERNAL_SRAM_BASE, + MCP905_INTERNAL_SRAM_BASE, + MCP905_INTERNAL_SRAM_SIZE, _PAGE_IO); +} + +static void mcp905_restart(char *cmd) +{ + volatile ulong i = 10000000; + u8 *status_reg_3_addr; + + local_irq_disable(); + status_reg_3_addr = ioremap(MCP905_BOARD_STATUS_REG_3, 1); + writeb(MCP905_BOARD_RESET_MASK, status_reg_3_addr); + + while (i-- > 0) ; + panic("restart failed\n"); +} + +static void mcp905_halt(void) +{ + local_irq_disable(); + while (1) ; + /* NOT REACHED */ +} + +static void mcp905_power_off(void) +{ + mcp905_halt(); + /* NOT REACHED */ +} + +static int mcp905_show_cpuinfo(struct seq_file *m) +{ + uint tmp; + uint memsize = total_memory; + u8 reg_value; + u8 *reg_addr, *reg_block; + unsigned char mcp905_geo_bits; + + seq_printf(m, "vendor\t\t: Motorola\n"); + seq_printf(m, "machine\t\t: MCP905\n"); + tmp = mfspr(SPRN_PVR); + seq_printf(m, "PVID\t\t: 0x%x, vendor: %s\n", + tmp, (tmp & (1 << 15) ? "IBM" : "Motorola")); + tmp = mfspr(SPRN_HID0); + seq_printf(m, "HID0\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_HID1); + seq_printf(m, "HID1\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_MSSCR0); + seq_printf(m, "MSSCR0\t\t: 0x%08x, Bus Mode: %s\n", + tmp, ((((tmp & 0x00030000) >> 16) == 0) ? "60X" : "MPX")); + tmp = mfspr(SPRN_MSSSR0); + seq_printf(m, "MSSSR0\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_L2CR); + seq_printf(m, "L2CR\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_L3CR); + seq_printf(m, "L3CR\t\t: 0x%08x\n", tmp); + + seq_printf(m, "\nBOARD INFORMATION:\n\n"); + reg_block = ioremap(MCP905_BOARD_STATUS_REG_1, 8); + reg_addr = reg_block; + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t\t: %d MB\n", memsize / (1024 * 1024)); + + /* System Status Register 1 */ + reg_value = readb(reg_addr++); + seq_printf(m, "Reference Clock\t\t: %s\n", + ((reg_value & MCP905_BOARD_REF_CLOCK) ? + "Bit Set" : "Bit Not Set")); + seq_printf(m, "Flash Boot Block Select\t: %s\n", + ((reg_value & MCP905_BOARD_BANK_SEL_MASK) ? + "Flash 1 is the boot bank" : "Flash 0 is the boot bank")); + seq_printf(m, "Safe Start Status\t: %s\n", + ((reg_value & MCP905_BOARD_SAFE_START) ? + "Safe ENV settings used" : "NVRAM ENV settings used")); + seq_printf(m, "ABORT Status\t\t: %s\n", + ((reg_value & MCP905_BOARD_ABORT_STATUS) ? + "ABORT Switch Not Asserted" : "ABORT Switch Asserted")); + seq_printf(m, "Flash Busy\t\t: %s\n", + ((reg_value & MCP905_BOARD_FLASH_BUSY) ? + "Bit Set" : "Bit Not Set")); + seq_printf(m, "SROM Init Status\t: %s\n", + ((reg_value & MCP905_BOARD_SROM_INIT) ? + "MV64360 SROM Init Enabled" : + "MV64360 SROM Init Disabled")); + + /* System Status Register 2 */ + reg_value = readb(reg_addr++); + seq_printf(m, "Board Fail LED\t\t: %s\n", + ((reg_value & MCP905_BOARD_FAIL_MASK) ? + "LED Lit" : "LED Not Lit")); + seq_printf(m, "EEPROM WP Status\t: %s\n", + ((reg_value & MCP905_BOARD_EEPROM_WP_MASK) ? + "EEPROM Write Protected" : + "EEPROM Not SW Write Protected")); + seq_printf(m, "Flash WP Status\t\t: %s\n", + ((reg_value & MCP905_BOARD_FLASH_WP_MASK) ? + "Flash Write Protected" : "Flash Not Write Protected")); + seq_printf(m, "DS1621 Thermostat\t: %s\n", + ((reg_value & MCP905_BOARD_TSTAT_MASK) ? + "Interrupt Disabled" : "Interrupt Enabled")); + + /* System Status Register 2 */ + reg_value = readb(reg_addr++); + seq_printf(m, "ABORT Mask\t\t: %s\n", + ((reg_value & MCP905_BOARD_ABORT_MASK) ? + "ABORT Interrupt Masked" : "ABORT Interrupt Not Masked")); + + /* Geographic Address Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "Geographic Register\t: 0x%x\n", reg_value); + mcp905_geo_bits = reg_value & MCP905_BOARD_GEO_ADDR_MASK; + seq_printf(m, "Board in Slot\t\t: %d\n", mcp905_geo_bits); + + /* Presence Detect Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "Transition Module\t: %s\n", + ((reg_value & MCP905_BOARD_TM_PRESENT) ? + "Not Installed" : "Installed")); + seq_printf(m, "EREADY2\t\t\t: %s\n", + ((reg_value & MCP905_BOARD_EREADY2) ? + "PMC Slot 2 Ready for Enumeration" : + "PMC Slot 2 Not Ready for Enumeration")); + seq_printf(m, "EREADY1\t\t\t: %s\n", + ((reg_value & MCP905_BOARD_EREADY1) ? + "PMC Slot 1 Ready for Enumeration" : + "PMC Slot 1 Not Ready for Enumeration")); + seq_printf(m, "PMC2\t\t\t: %s\n", + ((reg_value & MCP905_BOARD_PMC2) ? + "Not Installed" : "Installed")); + seq_printf(m, "PMC1\t\t\t: %s\n", + ((reg_value & MCP905_BOARD_PMC1) ? + "Not Installed" : "Installed")); + + /* Configuration Header Switch */ + reg_value = readb(reg_addr++); + seq_printf(m, "Configuration Bits\t: 0x%x\n", reg_value); + + /* TBEN Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "TBEN0\t\t\t: %s\n", + ((reg_value & MCP905_BOARD_TBEN0) ? + "TBEN pin driven high" : "TBEN pin driven low")); + + /* Hole */ + reg_value = readb(reg_addr++); + + /* Interrupt Status Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "Thermostat Int Status\t: %s\n", + ((reg_value & MCP905_BOARD_TSTAT_INT) ? + "Interrupt NOT Asserted" : "Interrupt Asserted")); + + iounmap(reg_block); + + return 0; +} + +static void __init mcp905_fixup_eth_pdata(struct platform_device *pdev) +{ + struct mv643xx_eth_platform_data *eth_pd; + static u16 phy_addr[] = { + MCP905_ETH0_PHY_ADDR, + MCP905_ETH1_PHY_ADDR, + MCP905_ETH2_PHY_ADDR, + }; + + eth_pd = pdev->dev.platform_data; + eth_pd->force_phy_addr = 1; + eth_pd->phy_addr = phy_addr[pdev->id]; + eth_pd->tx_queue_size = MCP905_ETH_TX_QUEUE_SIZE; + eth_pd->rx_queue_size = MCP905_ETH_RX_QUEUE_SIZE; +#ifdef CONFIG_MV64X60_USE_SRAM + if (pdev->id == 0) { + eth_pd->rx_sram_addr = MCP905_INTERNAL_SRAM_BASE; + eth_pd->rx_sram_size = 16000; + eth_pd->tx_sram_addr = MCP905_INTERNAL_SRAM_BASE + 16000; + eth_pd->tx_sram_size = 16000; + } else if (pdev->id == 1) { + eth_pd->rx_sram_addr = MCP905_INTERNAL_SRAM_BASE + 32000; + eth_pd->rx_sram_size = 16000; + eth_pd->tx_sram_addr = MCP905_INTERNAL_SRAM_BASE + 48000; + eth_pd->tx_sram_size = 16000; + } else { + eth_pd->rx_sram_addr = MCP905_INTERNAL_SRAM_BASE + 64000; + eth_pd->rx_sram_size = 16000; + eth_pd->tx_sram_addr = MCP905_INTERNAL_SRAM_BASE + 80000; + eth_pd->tx_sram_size = 16000; + } +#endif +} +static int __init mcp905_platform_notify(struct device *dev) +{ + static struct { + char *bus_id; + void ((*rtn) (struct platform_device * pdev)); + } dev_map[] = { + {MV643XX_ETH_NAME ".0", mcp905_fixup_eth_pdata}, + {MV643XX_ETH_NAME ".1", mcp905_fixup_eth_pdata}, + {MV643XX_ETH_NAME ".2", mcp905_fixup_eth_pdata}, + }; + struct platform_device *pdev; + int i; + + if (dev && dev->bus_id) + for (i = 0; i < ARRAY_SIZE(dev_map); i++) + if (!strncmp(dev->bus_id, dev_map[i].bus_id, + BUS_ID_SIZE)) { + + pdev = container_of(dev, + struct platform_device, + dev); + dev_map[i].rtn(pdev); + } + return 0; +} + +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) +static void __init +mcp905_ide_init_hwif_ports(hw_regs_t * hw, unsigned long data_port, + unsigned long ctrl_port, int *irq) +{ + unsigned long reg = data_port; + int i; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg++; + } + if (ctrl_port) + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + else + hw->io_ports[IDE_CONTROL_OFFSET] = + hw->io_ports[IDE_DATA_OFFSET] + 0x206; + + if (irq != NULL) + *irq = hw->irq; +} + +#endif + +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + parse_bootinfo(find_bootinfo()); + + mcp905_set_bat(); + +#ifdef CONFIG_BLK_DEV_INITRD + if (r4) { + initrd_start = r4 + KERNELBASE; + initrd_end = r5 + KERNELBASE; + } +#endif + + /* Copy cmd_line parameters */ + if (r6 && (((char *)r6) != '\0')) { + *(char *)(r7 + KERNELBASE) = 0; + strcpy(cmd_line, (char *)(r6 + KERNELBASE)); + } + + isa_io_base = MCP905_PCI_0_IO_BASE_ADDR_PROC; + isa_mem_base = MCP905_ISA_MEM_BASE; + pci_dram_offset = MCP905_PCI_DRAM_OFFSET; + + ppc_md.setup_arch = mcp905_setup_arch; + ppc_md.show_cpuinfo = mcp905_show_cpuinfo; + ppc_md.init_IRQ = mv64360_init_irq; + ppc_md.get_irq = mv64360_get_irq; + ppc_md.init = NULL; + + ppc_md.restart = mcp905_restart; + ppc_md.power_off = mcp905_power_off; + ppc_md.halt = mcp905_halt; + + ppc_md.find_end_of_memory = mcp905_find_end_of_memory; + ppc_md.setup_io_mappings = mcp905_map_io; + + ppc_md.time_init = todc_time_init; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + ppc_md.calibrate_decr = todc_calibrate_decr; + + ppc_md.nvram_read_val = todc_direct_read_val; + ppc_md.nvram_write_val = todc_direct_write_val; + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pcibios_fixup = mcp905_pci_fixups; + +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) + mcp905_early_serial_map(); +#endif + +#ifdef CONFIG_SERIAL_TEXT_DEBUG + ppc_md.progress = gen550_progress; /* Device module UART */ +#endif + + platform_notify = mcp905_platform_notify; + +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) + ppc_ide_md.ide_init_hwif = mcp905_ide_init_hwif_ports; +#endif + + return; +} diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/mcp905.h linux-2.6.14.mod/arch/ppc/platforms/mcp905.h --- linux-2.6.14.orig/arch/ppc/platforms/mcp905.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/mcp905.h 2006-03-14 13:35:36.000000000 -0700 @@ -0,0 +1,228 @@ +/* + * mcp905.h + * + * Definitions for the MCP905 Board. + * + * Author: Ajit Prem (Ajit.Prem@motorola.com) + * + * Copyright 2003-2006 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/* + * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to + * PCI I/O space and 4 windows from the CPU bus to PCI MEM space. + * We'll only use one PCI MEM window on each PCI bus. + * + * This is the CPU physical memory map (windows must be at least 1MB and start + * on a boundary that is a multiple of the window size): + * + * 0x80000000-0xcfffffff - + * 0xd0000000-0xdfffffff - PCI 0 MEM + * 0xe0000000-0xefffffff - PCI 1 MEM + * 0xf0000000-0xf07fffff - PCI 0 I/O + * 0xf0800000-0xf08fffff - PCI 1 I/O + * 0xf0900000-0xf0ffffff - + * 0xf1000000-0xf10fffff - MV64360 Registers + * 0xf1100000-0xf110ffff - MV64360 Device 1 Bus Registers + * 0xf1110000-0xf1117fff - TODC chip on device module + * 0xf1120000-0xf1120fff - COM1 UART on device module + * 0xf1121000-0xf1121fff - COM2 UART on device module + * 0xf1122000-0xf1f2ffff - + * 0xf1130000-0xf113ffff - Zircon BMC on device module + * 0xf1140000-0xf1ffffff - + * 0xf2000000-0xf3ffffff - Bank A Flash + * 0xf4000000-0xfefbffff - + * 0xfefc0000-0xfeffffff - Internal SRAM + * 0xff000000-0xff7fffff - + * 0xff800000-0xffffffff - Bank B Flash + */ + +#ifndef __MCP905_H +#define __MCP905_H + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +/* + * CPU Physical Memory Map setup. + */ +#define MCP905_BANK_B_FLASH_BASE 0xff800000 /* Bank B */ +#define MCP905_BANK_A_FLASH_BASE 0xf2000000 /* Bank A */ +#define MCP905_BRIDGE_REG_BASE 0xf1000000 +#define MCP905_DEVICE_CS1_BASE 0xf1100000 +#define MCP905_TODC_BASE 0xf1110000 +#define MCP905_UART_BASE 0xf1120000 +#define MCP905_BMC_BASE 0xf1130000 +#define MCP905_INTERNAL_SRAM_BASE 0xfefc0000 + +#define MCP905_BANK_B_FLASH_SIZE 0x00800000 /* 8MB Bank B FLASH */ +#define MCP905_BANK_A_FLASH_SIZE 0x02000000 /* 32MB (Max) Bank A FLASH */ +#define MCP905_DEVICE_CS1_SIZE 0x00100000 /* 1MB */ +#define MCP905_INTERNAL_SRAM_SIZE _256K /* 256KByte internal SRAM */ +#define MCP905_TODC_SIZE 0x00008000 /* 32KB for TODC */ + +#define MCP905_UART_SIZE_ACTUAL 0x00001000 /* 4K per UART */ +#define MCP905_UART_SIZE 0x8 + +#define MCP905_NVRAM_BASE_ADDRESS 0xf1110000U +#define MCP905_NVRAM_SIZE 0x8000 + +#define MCP905_PCI_DRAM_OFFSET 0x00000000 +#define MCP905_ISA_MEM_BASE 0x00000000 + +/* MCP905 board register addresses. */ +#define MCP905_BOARD_STATUS_REG_1 0xf1100000 +#define MCP905_BOARD_STATUS_REG_2 0xf1100001 +#define MCP905_BOARD_STATUS_REG_3 0xf1100002 +#define MCP905_BOARD_GEO_ADDR_REG 0xf1100003 +#define MCP905_BOARD_PRESENCE_REG 0xf1100004 +#define MCP905_BOARD_SW_READ_REG 0xf1100005 +#define MCP905_BOARD_TBEN_REG 0xf1100006 +#define MCP905_BOARD_INT_STATUS_REG 0xf1100008 + +/* Status Register 1 */ +#define MCP905_BOARD_REF_CLOCK 0x80 +#define MCP905_BOARD_BANK_SEL_MASK 0x40 +#define MCP905_BOARD_SAFE_START 0x20 +#define MCP905_BOARD_ABORT_STATUS 0x10 +#define MCP905_BOARD_FLASH_BUSY 0x08 +#define MCP905_BOARD_SROM_INIT 0x02 + +/* Status Register 2 */ +#define MCP905_BOARD_FAIL_MASK 0x80 +#define MCP905_BOARD_EEPROM_WP_MASK 0x40 +#define MCP905_BOARD_FLASH_WP_MASK 0x20 +#define MCP905_BOARD_TSTAT_MASK 0x10 + +/* Status Register 3 */ +#define MCP905_BOARD_RESET_MASK 0x80 +#define MCP905_BOARD_PCI0_RESET_MASK 0x01 +#define MCP905_BOARD_PCI1_RESET_MASK 0x02 +#define MCP905_BOARD_ABORT_MASK 0x08 + +/* Geographic Address Register */ +#define MCP905_BOARD_GEO_ADDR_MASK 0x1f + +/* Presence Detect Register */ +#define MCP905_BOARD_TM_PRESENT 0x10 +#define MCP905_BOARD_EREADY2 0x08 +#define MCP905_BOARD_EREADY1 0x04 +#define MCP905_BOARD_PMC2 0x02 +#define MCP905_BOARD_PMC1 0x01 + +/* TBEN register */ +#define MCP905_BOARD_TBEN0 0x01 + +/* Interrupt Status Register */ +#define MCP905_BOARD_TSTAT_INT 0x10 + +/* Memory Map */ +#define MCP905_PCI_0_MEM_SIZE 0x10000000U +#define MCP905_PCI_0_IO_SIZE 0x00800000U + +#define MCP905_PCI_1_MEM_SIZE 0x10000000U +#define MCP905_PCI_1_IO_SIZE 0x00800000U + +#define MCP905_PCI_0_MEM_BASE_ADDR_PROC 0xd0000000U /* CPU Address */ +#define MCP905_PCI_0_IO_BASE_ADDR_PROC 0xf0000000U +#define MCP905_PCI_1_MEM_BASE_ADDR_PROC 0xe0000000U /* CPU Address */ +#define MCP905_PCI_1_IO_BASE_ADDR_PROC 0xf0800000U + +#define MCP905_PCI_0_MEM_BASE_ADDR 0xd0000000U /* PCI Address */ +#define MCP905_PCI_0_IO_BASE_ADDR 0x00000000U +#define MCP905_PCI_1_MEM_BASE_ADDR 0xe0000000U /* PCI Address */ +#define MCP905_PCI_1_IO_BASE_ADDR 0x00800000U + +/* PCI Bus 0 Definitions */ + +/* Processor Physical addresses */ +#define MCP905_PCI_0_MEM_START_PROC MCP905_PCI_0_MEM_BASE_ADDR_PROC +#define MCP905_PCI_0_MEM_END_PROC (MCP905_PCI_0_MEM_START_PROC + \ + MCP905_PCI_0_MEM_SIZE - 1) +#define MCP905_PCI_0_IO_START_PROC MCP905_PCI_0_IO_BASE_ADDR_PROC +#define MCP905_PCI_0_IO_END_PROC (MCP905_PCI_0_IO_START_PROC + \ + MCP905_PCI_0_IO_SIZE - 1) + +/* PCI 0 MEM address */ +#define MCP905_PCI_0_MEM_START MCP905_PCI_0_MEM_BASE_ADDR +#define MCP905_PCI_0_MEM_END (MCP905_PCI_0_MEM_START + \ + MCP905_PCI_0_MEM_SIZE - 1) + +/* PCI 0 I/O address */ +#define MCP905_PCI_0_IO_START MCP905_PCI_0_IO_BASE_ADDR +#define MCP905_PCI_0_IO_END (MCP905_PCI_0_IO_START + \ + MCP905_PCI_0_IO_SIZE - 1) + +/* PCI Bus 1 Definitions */ + +/* Processor Physical addresses */ +#define MCP905_PCI_1_MEM_START_PROC MCP905_PCI_1_MEM_BASE_ADDR_PROC +#define MCP905_PCI_1_MEM_END_PROC (MCP905_PCI_1_MEM_START_PROC + \ + MCP905_PCI_1_MEM_SIZE - 1) +#define MCP905_PCI_1_IO_START_PROC MCP905_PCI_1_IO_BASE_ADDR_PROC +#define MCP905_PCI_1_IO_END_PROC (MCP905_PCI_1_IO_START_PROC + \ + MCP905_PCI_1_IO_SIZE - 1) + +/* PCI 1 MEM address */ +#define MCP905_PCI_1_MEM_START MCP905_PCI_1_MEM_BASE_ADDR +#define MCP905_PCI_1_MEM_END (MCP905_PCI_1_MEM_START + \ + MCP905_PCI_1_MEM_SIZE - 1) + +/* PCI 1 I/O address */ +#define MCP905_PCI_1_IO_START MCP905_PCI_1_IO_BASE_ADDR +#define MCP905_PCI_1_IO_END (MCP905_PCI_1_IO_START + \ + MCP905_PCI_1_IO_SIZE - 1) + +#define MCP905_UART_0_IRQ 64 +#define MCP905_UART_1_IRQ 64 + +#define MCP905_UART_BASE 0xf1120000 + +/* + * Serial driver setup. + */ +#define MCP905_SERIAL_0 MCP905_UART_BASE +#define MCP905_SERIAL_1 MCP905_UART_BASE +0x1000 + +#define MCP905_BASE_BAUD 1843200 +#define BASE_BAUD (MCP905_BASE_BAUD / 16) + +#ifdef CONFIG_SERIAL_MANY_PORTS +#define RS_TABLE_SIZE 64 +#else +#define RS_TABLE_SIZE 2 +#endif + +#ifdef CONFIG_SERIAL_DETECT_IRQ +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) +#else +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) +#endif + +#define STD_SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, MCP905_SERIAL_0, MCP905_UART_0_IRQ, STD_COM_FLAGS, /* ttyS0 */ \ + iomem_base: (u8 *)MCP905_SERIAL_0, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MCP905_SERIAL_1, MCP905_UART_1_IRQ, STD_COM_FLAGS, /* ttyS1 */ \ + iomem_base: (u8 *)MCP905_SERIAL_1, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM }, + +#define SERIAL_PORT_DFNS \ + STD_SERIAL_PORT_DFNS + +#define MCP905_ETH0_PHY_ADDR 1 +#define MCP905_ETH1_PHY_ADDR 2 +#define MCP905_ETH2_PHY_ADDR 3 + +#define MCP905_ETH_TX_QUEUE_SIZE 800 +#define MCP905_ETH_RX_QUEUE_SIZE 400 + +#endif /* __MCP905_H */ diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/mvme5500.c linux-2.6.14.mod/arch/ppc/platforms/mvme5500.c --- linux-2.6.14.orig/arch/ppc/platforms/mvme5500.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/mvme5500.c 2006-06-06 15:23:47.000000000 -0700 @@ -0,0 +1,738 @@ +/* + * mvme5500.c + * + * Board setup routines for the Motorola MVME5500 Board. + * + * Author: Ajit Prem (Ajit.Prem@motorola.com) + * + * Copyright 2003-2006 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "mvme5500.h" + +extern void _set_L3CR(unsigned long); +extern char cmd_line[]; +extern unsigned long total_memory; /* in mm/init */ + +static struct mv64x60_handle bh; + +#ifdef CONFIG_VME_BRIDGE_BOOTMEM +void *vme_driver_bootmem; +unsigned int vme_bootmem_size; +#endif + +extern void gen550_progress(char *, unsigned short); +extern void gen550_init(int, struct uart_port *); + +/* + * Motorola MVME5500 Board PCI interrupt routing. + */ +static int __init +mvme5500_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + struct pci_controller *hose = (struct pci_controller *)(dev->sysdata); + + if (hose->index == 0) { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {75, 0, 0, 0}, /* IDSEL 1 - IPMC */ + {0, 0, 0, 0}, /* IDSEL 2 - */ + {0, 0, 0, 0}, /* IDSEL 3 - */ + {0, 0, 0, 0}, /* IDSEL 4 - */ + {0, 0, 0, 0}, /* IDSEL 5 - */ + {72, 73, 74, 75}, /* IDSEL 6 - PMC Slot 0 */ + {0, 0, 0, 0}, /* IDSEL 7 - */ + {0, 0, 0, 0}, /* IDSEL 8 - */ + {0, 0, 0, 0}, /* IDSEL 9 - */ + {76, 77, 78, 79}, /* IDSEL 10 - VME */ + }; + + const long min_idsel = 1, max_idsel = 10, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } else { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {0, 0, 0, 0}, /* IDSEL 4 */ + {0, 0, 0, 0}, /* IDSEL 5 */ + {80, 81, 82, 83}, /* IDSEL 6 - PMC Slot 1 */ + {0, 0, 0, 0}, /* IDSEL 7 - Unused Slot 1 */ + {0, 0, 0, 0}, /* IDSEL 8 - Unused Slot 1 */ + {0, 0, 0, 0}, /* IDSEL 9 - Unused Slot 1 */ + {84, 0, 0, 0}, /* IDSEL 10 - Gb Ethernet */ + }; + + const long min_idsel = 4, max_idsel = 10, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } +} + +static void __init mvme5500_setup_peripherals(void) +{ + mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, + MVME5500_BANK_A_FLASH_BASE, + MVME5500_BANK_A_FLASH_SIZE, 0); + bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); + + mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, + MVME5500_BANK_B_FLASH_BASE, + MVME5500_BANK_B_FLASH_SIZE, 0); + bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN); + + mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, + MVME5500_TODC_BASE, MVME5500_TODC_SIZE, 0); + bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); + +#if 0 + mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN, + MVME5500_UART_BASE, MVME5500_UART_SIZE, 0); + bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN); +#endif + + mv64x60_clr_bits(&bh, MV64x60_CPU_CONFIG, + ((1 << 12) | (1 << 28) | (1 << 29))); + mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1 << 27)); + + mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1 << 23)); + + mv64x60_set_bits(&bh, MV64x60_PCI0_PCI_DECODE_CNTL, + ((1 << 0) | (1 << 3))); + mv64x60_set_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, + ((1 << 0) | (1 << 3))); + + /* + * Enabling of PCI internal-vs-external arbitration + * is a platform- and errata-dependent decision. + */ + if (bh.type == MV64x60_TYPE_GT64260A) { + mv64x60_set_bits(&bh, MV64x60_PCI0_ARBITER_CNTL, (1 << 31)); + mv64x60_set_bits(&bh, MV64x60_PCI1_ARBITER_CNTL, (1 << 31)); + mv64x60_set_bits(&bh, MV64x60_COMM_ARBITER_CNTL, (1 << 10)); + } + + mv64x60_set_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1 << 9)); /* Only 1 cpu */ + /* + * Turn off timer/counters. Not turning off watchdog timer because + * can't read its reg on the 64260A so don't know if we'll be enabling + * or disabling. + */ + mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, + ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24))); + mv64x60_clr_bits(&bh, GT64260_TIMR_CNTR_4_7_CNTL, + ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24))); + + /* + * The EV-64260-BP uses several Multi-Purpose Pins (MPP) on the 64260 + * bridge as interrupt inputs (via the General Purpose Ports (GPP) + * register). Need to route the MPP inputs to the GPP and set the + * polarity correctly. + * + */ + + /* MPP Control 0 + * MPP funct MPP programming Usage + * 0 GPP[0] MPPCTL0[3:0] SERIAL_0/SERIAL_1 interrupt + * 1 GPP[1] MPPCTL0[7:4] Not used + * 2 GPP[2] MPPCTL0[11:8] Abort switch + * 3 GPP[3] MPPCTL0[15:12] RTC/Thermostat + * 4 GPP[4] MPPCTL0[19:16] Not used + * 5 GPP[5] MPPCTL0[23:20] Not used + * 6 GPP[6] MPPCTL0[27:24] Watchdog timer WDNMI + * 7 GPP[7] MPPCTL0[31:28] LXT971A MDINT + */ + + mv64x60_write(&bh, MV64x60_MPP_CNTL_0, 0x00000000); + + /* MPP Control 1 + * MPP funct MPP programming + * 8 GPP[8] MPPCTL1[3:0] PMC 1 INTA + * 9 GPP[9] MPPCTL1[7:4] PMC 1 INTB + * 10 GPP[10] MPPCTL1[11:8] PMC 1 INTC + * 11 GPP[11] MPPCTL1[15:12] PMC 1 INTD + * 12 GPP[12] MPPCTL1[19:16] VME VLINT0 + * 13 GPP[13] MPPCTL1[23:20] VME VLINT1 + * 14 GPP[14] MPPCTL1[27:24] VME VLINT2 + * 15 GPP[15] MPPCTL1[31:28] VME VLINT3 + */ + + mv64x60_write(&bh, MV64x60_MPP_CNTL_1, 0x00000000); + + /* MPP Control 2 + * MPP funct MPP programming Usage + * 16 GPP[16] MPPCTL2[3:0] PMC 2 INTA + * 17 GPP[17] MPPCTL2[7:4] PMC 2 INTB + * 18 GPP[18] MPPCTL2[11:8] PMC 2 INTC + * 19 GPP[19] MPPCTL2[15:12] PMC 2 INTD + * 20 GPP[20] MPPCTL2[19:16] 82544 INT + * 21 GPP[21] MPPCTL2[23:20] Not used + * 22 GPP[22] MPPCTL2[27:24] Not used + * 23 GPP[23] MPPCTL2[31:28] Not used + */ + + mv64x60_write(&bh, MV64x60_MPP_CNTL_2, 0x00000000); + + /* MPP Control 3 + * MPP funct MPP programming Usage + * 24 GPP[24] MPPCTL3[3:0] Watch dog timer WDNMI ***OUTPUT*** + * 25 GPP[25] MPPCTL3[7:4] Watch dog timer WDE ***OUTPUT*** + * 26 GPP[26] MPPCTL3[11:8] SROM InitAct + * 27 GPP[27] MPPCTL3[15:12] Not used + * 28 GPP[28] MPPCTL3[19:16] Not used + * 29 GPP[29] MPPCTL3[23:20] Optional external PPC bus arbiter BG1 OUT + * 30 GPP[30] MPPCTL3[27:24] unused + * 31 GPP[31] MPPCTL3[31:28] unused + */ + /* do not enable watch dog timer interrupts */ + + mv64x60_write(&bh, MV64x60_MPP_CNTL_3, 0x00000000); + +#define GPP_EXTERNAL_INTERRUPTS \ + (1<<7) | (1<<8) | (1<<9) | (1<<10) | \ + (1<<11) | (1<<12) | (1<<13) | (1<<14) | \ + (1<<15) | (1<<16) | (1<<17) | (1<<18) | \ + (1<<19) | (1<<20) + + /* Set interrupt active levels */ + mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, GPP_EXTERNAL_INTERRUPTS); + mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, GPP_EXTERNAL_INTERRUPTS); +// mv64x60_write(&bh, MV64x60_GPP_LEVEL_CNTL, 0x081fffcc); + + /* Clear any pending interrupts for these inputs and enable them. */ + mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~GPP_EXTERNAL_INTERRUPTS); + mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, GPP_EXTERNAL_INTERRUPTS); + + return; +} + +static void __init mvme5500_misc_init(void) +{ + u8 *status_reg_2_addr; + u8 status_reg_2; + + status_reg_2_addr = ioremap(MVME5500_BOARD_STATUS_REG_2, 1); + status_reg_2 = readb(status_reg_2_addr); + status_reg_2 &= ~MVME5500_BOARD_FAIL_MASK; + status_reg_2 &= ~MVME5500_BOARD_FLASH_WP_MASK; + writeb(status_reg_2, status_reg_2_addr); + iounmap(status_reg_2_addr); + + return; +} + +static void __init mvme5500_setup_bridge(void) +{ + struct mv64x60_setup_info si; + int i; + + memset(&si, 0, sizeof(si)); + + si.phys_reg_base = CONFIG_MV64X60_NEW_BASE; + + si.pci_0.enable_bus = 1; + si.pci_0.pci_io.cpu_base = MVME5500_PCI_0_IO_START_PROC; + si.pci_0.pci_io.pci_base_hi = 0; + si.pci_0.pci_io.pci_base_lo = MVME5500_PCI_0_IO_START; + si.pci_0.pci_io.size = MVME5500_PCI_0_IO_SIZE; + si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; + + si.pci_0.pci_mem[0].cpu_base = MVME5500_PCI_0_MEM_START_PROC; + si.pci_0.pci_mem[0].pci_base_hi = 0; + si.pci_0.pci_mem[0].pci_base_lo = MVME5500_PCI_0_MEM_START; + si.pci_0.pci_mem[0].size = MVME5500_PCI_0_MEM_SIZE; + si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; + si.pci_0.pci_cmd_bits = 0; + si.pci_0.latency_timer = 0x80; + + si.pci_1.enable_bus = 1; + si.pci_1.pci_io.cpu_base = MVME5500_PCI_1_IO_START_PROC; + si.pci_1.pci_io.pci_base_hi = 0; + si.pci_1.pci_io.pci_base_lo = MVME5500_PCI_1_IO_START; + si.pci_1.pci_io.size = MVME5500_PCI_1_IO_SIZE; + si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; + si.pci_1.pci_mem[0].cpu_base = MVME5500_PCI_1_MEM_START_PROC; + si.pci_1.pci_mem[0].pci_base_hi = 0; + si.pci_1.pci_mem[0].pci_base_lo = MVME5500_PCI_1_MEM_START; + si.pci_1.pci_mem[0].size = MVME5500_PCI_1_MEM_SIZE; + si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; + si.pci_1.pci_cmd_bits = 0; + si.pci_1.latency_timer = 0x80; + + for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) { + si.cpu_prot_options[i] = 0; + si.cpu_snoop_options[i] = GT64260_CPU_SNOOP_WB; + si.pci_0.acc_cntl_options[i] = + GT64260_PCI_ACC_CNTL_DREADEN | + GT64260_PCI_ACC_CNTL_RDPREFETCH | + GT64260_PCI_ACC_CNTL_RDLINEPREFETCH | + GT64260_PCI_ACC_CNTL_RDMULPREFETCH | + GT64260_PCI_ACC_CNTL_SWAP_NONE | + GT64260_PCI_ACC_CNTL_MBURST_32_BTYES; + si.pci_0.snoop_options[i] = GT64260_PCI_SNOOP_WB; + si.pci_1.acc_cntl_options[i] = + GT64260_PCI_ACC_CNTL_DREADEN | + GT64260_PCI_ACC_CNTL_RDPREFETCH | + GT64260_PCI_ACC_CNTL_RDLINEPREFETCH | + GT64260_PCI_ACC_CNTL_RDMULPREFETCH | + GT64260_PCI_ACC_CNTL_SWAP_NONE | + GT64260_PCI_ACC_CNTL_MBURST_32_BTYES; + si.pci_1.snoop_options[i] = GT64260_PCI_SNOOP_WB; + } + + /* Lookup PCI host bridges */ + if (mv64x60_init(&bh, &si)) + printk(KERN_ERR "Bridge initialization failed.\n"); + + pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */ + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mvme5500_map_irq; + ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; + + mv64x60_set_bus(&bh, 0, 0); + bh.hose_a->first_busno = 0; + bh.hose_a->last_busno = 0xff; + bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0); + + bh.hose_b->first_busno = bh.hose_a->last_busno + 1; + mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno); + bh.hose_b->last_busno = 0xff; + bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, + bh.hose_b->first_busno); + + return; +} + +static void __init mvme5500_init_caches(void) +{ + uint val; + + /* Enable L2 and L3 caches (if 745x) */ + val = _get_L2CR(); + val |= L2CR_L2E; + _set_L2CR(val); + + val = _get_L3CR(); + val |= L3CR_L3E; + _set_L3CR(val); +// _set_L3CR(0xdf026040); +} + +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) +static void __init mvme5500_early_serial_map(void) +{ + struct uart_port serial_req; + + memset(&serial_req, 0, sizeof(serial_req)); + serial_req.uartclk = MVME5500_BASE_BAUD; + serial_req.line = 0; + serial_req.irq = MVME5500_UART_0_IRQ; + serial_req.flags = STD_COM_FLAGS; + serial_req.iotype = SERIAL_IO_MEM; + serial_req.membase = (char *)MVME5500_SERIAL_0; + serial_req.regshift = 0; + + gen550_init(0, &serial_req); + + if (early_serial_setup(&serial_req) != 0) + printk("Early serial init of port 0 failed\n"); + + /* Assume early_serial_setup() doesn't modify serial_req */ + serial_req.line = 1; + serial_req.irq = MVME5500_UART_1_IRQ; + serial_req.membase = (char *)MVME5500_SERIAL_1; + + gen550_init(1, &serial_req); + + if (early_serial_setup(&serial_req) != 0) + printk("Early serial init of port 1 failed\n"); + +} +#endif + +TODC_ALLOC(); + +static void __init mvme5500_setup_arch(void) +{ + +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) + mvme5500_early_serial_map(); +#endif + + if (ppc_md.progress) + ppc_md.progress("mvme5500_setup_arch: enter", 0); + + loops_per_jiffy = 50000000 / HZ; + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_SDA2; +#endif + +#ifdef CONFIG_VME_BRIDGE_BOOTMEM + + vme_bootmem_size = CONFIG_VME_BRIDGE_BOOTMEM_SIZE * 1024 * 1024; + + if (vme_bootmem_size > (total_memory / 2)) { + printk(KERN_WARNING "BOOTMEM Size Requested: 0x%x Total Memory 0x%lx\n", vme_bootmem_size, total_memory); + printk(KERN_WARNING "BOOTMEM Size requested has been capped at half the total memory\n"); + vme_bootmem_size = total_memory / 2; + } + vme_driver_bootmem = __alloc_bootmem(vme_bootmem_size, 0x10000, 0); + if (!vme_driver_bootmem) { + printk(KERN_WARNING "Unable to obtain boot memory for VME\n"); + vme_bootmem_size = 0; + } else { + printk(KERN_INFO "0x%x of boot memory reserved for setup of VME inbound window 7\n", vme_bootmem_size); + } +#endif + + mvme5500_init_caches(); + + if (ppc_md.progress) + ppc_md.progress("mvme5500_setup_arch: find_bridges", 0); + + mvme5500_setup_bridge(); + + if (ppc_md.progress) + ppc_md.progress("mvme5500_setup_arch: find_bridges done", 0); + + if (ppc_md.progress) + ppc_md.progress("mvme5500_setup_arch: setup_peripherals", 0); + + mvme5500_setup_peripherals(); + + if (ppc_md.progress) + ppc_md.progress("mvme5500_setup_arch: setup_peripherals done", + 0); + + TODC_INIT(TODC_TYPE_MK48T37, 0, 0, MVME5500_TODC_BASE, 8); + + mvme5500_misc_init(); + + printk("Motorola Computer Group MVME5500 Board\n"); + printk("MVME5500 port (C) 2003-2006 Motorola, Inc.\n"); + + if (ppc_md.progress) + ppc_md.progress("mvme5500_setup_arch: exit", 0); + + return; +} + +static void __init mvme5500_init_irq(void) +{ + + if (ppc_md.progress) + ppc_md.progress("mvme5500_init_irq: enter", 0); + + gt64260_init_irq(); + + irq_desc[64].status |= IRQ_LEVEL; + irq_desc[66].status |= IRQ_LEVEL; + irq_desc[67].status |= IRQ_LEVEL; + irq_desc[70].status |= IRQ_LEVEL; + irq_desc[71].status |= IRQ_LEVEL; + irq_desc[72].status |= IRQ_LEVEL; + irq_desc[73].status |= IRQ_LEVEL; + irq_desc[74].status |= IRQ_LEVEL; + irq_desc[75].status |= IRQ_LEVEL; + irq_desc[76].status |= IRQ_LEVEL; + irq_desc[77].status |= IRQ_LEVEL; + irq_desc[78].status |= IRQ_LEVEL; + irq_desc[79].status |= IRQ_LEVEL; + irq_desc[80].status |= IRQ_LEVEL; + irq_desc[81].status |= IRQ_LEVEL; + irq_desc[82].status |= IRQ_LEVEL; + irq_desc[83].status |= IRQ_LEVEL; + irq_desc[84].status |= IRQ_LEVEL; + + if (ppc_md.progress) + ppc_md.progress("mvme5500_init_irq: exit", 0); +} + +/* + * Set BAT 3 to map 0xf0000000 to end of physical memory space. + */ +static __inline__ void mvme5500_set_bat(void) +{ + mb(); + mtspr(SPRN_DBAT1U, 0xf0001ffe); + mtspr(SPRN_DBAT1L, 0xf000002a); + mb(); +} + +unsigned long __init mvme5500_find_end_of_memory(void) +{ + return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE, + MV64x60_TYPE_GT64260A); +} + +static void __init mvme5500_map_io(void) +{ + io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); + ioremap_base = 0xf0000000; +} + +static void mvme5500_restart(char *cmd) +{ + volatile ulong i = 10000000; + u8 *status_reg_3_addr; + + local_irq_disable(); + status_reg_3_addr = ioremap(MVME5500_BOARD_STATUS_REG_3, 1); + writeb(MVME5500_BOARD_RESET_MASK, status_reg_3_addr); + + while (i-- > 0) ; + panic("restart failed\n"); +} + +static void mvme5500_halt(void) +{ + local_irq_disable(); + while (1) ; + /* NOTREACHED */ +} + +static void mvme5500_power_off(void) +{ + mvme5500_halt(); + /* NOTREACHED */ +} + +static int mvme5500_show_cpuinfo(struct seq_file *m) +{ + uint tmp; + uint memsize = total_memory; + u8 reg_value; + u8 *reg_addr, *reg_block; + + seq_printf(m, "vendor\t\t: Motorola\n"); + seq_printf(m, "machine\t\t: MVME5500\n"); + tmp = mfspr(SPRN_PVR); + seq_printf(m, "PVID\t\t: 0x%x, vendor: %s\n", + tmp, (tmp & (1 << 15) ? "IBM" : "Motorola")); + tmp = mfspr(SPRN_HID0); + seq_printf(m, "HID0\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_HID1); + seq_printf(m, "HID1\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_MSSCR0); + seq_printf(m, "MSSCR0\t\t: 0x%08x, Bus Mode: %s\n", + tmp, ((((tmp & 0x00030000) >> 16) == 0) ? "60X" : "MPX")); + tmp = mfspr(SPRN_MSSSR0); + seq_printf(m, "MSSSR0\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_L2CR); + seq_printf(m, "L2CR\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_L3CR); + seq_printf(m, "L3CR\t\t: 0x%08x\n", tmp); + + seq_printf(m, "\nBOARD INFORMATION:\n\n"); + reg_block = ioremap(MVME5500_BOARD_STATUS_REG_1, 8); + reg_addr = reg_block; + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t\t: %d MB\n", memsize / (1024 * 1024)); + + /* System Status Register 1 */ + reg_value = readb(reg_addr++); + seq_printf(m, "Reference Clock\t\t: %s\n", + ((reg_value & MVME5500_BOARD_REF_CLOCK) ? + "Bit Set" : "Bit Not Set")); + seq_printf(m, "Flash Boot Block Select\t: %s\n", + ((reg_value & MVME5500_BOARD_BANK_SEL_MASK) ? + "Flash 1 is the boot bank" : "Flash 0 is the boot bank")); + seq_printf(m, "Safe Start Status\t: %s\n", + ((reg_value & MVME5500_BOARD_SAFE_START) ? + "Safe ENV settings used" : "NVRAM ENV settings used")); + seq_printf(m, "Abort Status\t\t: %s\n", + ((reg_value & MVME5500_BOARD_ABORT_STATUS) ? + "Abort Switch Not Asserted" : "Abort Switch Asserted")); + seq_printf(m, "Flash Busy\t\t: %s\n", + ((reg_value & MVME5500_BOARD_FLASH_BUSY) ? + "Bit Set" : "Bit Not Set")); + seq_printf(m, "Fuse Status\t\t: %s\n", + ((reg_value & MVME5500_BOARD_FUSE_STAT) ? + "Fuses Functional" : "A fuse is open")); + + /* System Status Register 2 */ + reg_value = readb(reg_addr++); + seq_printf(m, "Board Fail LED\t\t: %s\n", + ((reg_value & MVME5500_BOARD_FAIL_MASK) ? + "LED Lit" : "LED Not Lit")); + seq_printf(m, "EEPROM WP Status\t: %s\n", + ((reg_value & MVME5500_BOARD_EEPROM_WP_MASK) ? + "EEPROM Write Protected" : "EEPROM Not Write Protected")); + seq_printf(m, "Flash WP Status\t\t: %s\n", + ((reg_value & MVME5500_BOARD_FLASH_WP_MASK) ? + "Flash Write Protected" : "Flash Not Write Protected")); + seq_printf(m, "DS1621 Thermostat\t: %s\n", + ((reg_value & MVME5500_BOARD_TSTAT_MASK) ? + "Interrupt Disabled" : "Interrupt Enabled")); + seq_printf(m, "PCI-C Bus Speed\t\t: %s\n", + ((reg_value & MVME5500_BOARD_PCIC_M66EN) ? + "66 MHz" : "33 MHz")); + seq_printf(m, "PCI-B Bus Speed\t\t: %s\n", + ((reg_value & MVME5500_BOARD_PCIB_M66EN) ? + "66 MHz" : "33 MHz")); + seq_printf(m, "PCI-A Bus Speed\t\t: %s\n", + ((reg_value & MVME5500_BOARD_PCIA_M66EN) ? + "66 MHz" : "33 MHz")); + + /* System Status Register 3 */ + reg_value = readb(reg_addr++); + seq_printf(m, "ABORT Int Mask\t\t: %s\n", + ((reg_value & MVME5500_BOARD_ABORT_INT_MASK) ? + "Interrupt Masked" : "Interrupt Not Masked")); + + /* Presence Detect Register */ + reg_value = readb(reg_addr++); + reg_value = readb(reg_addr++); + seq_printf(m, "EREADY1\t\t\t: %s\n", + ((reg_value & MVME5500_BOARD_EREADY1) ? + "PMC Slot 2 Ready for Enumeration" : + "PMC Slot 2 Not Ready for Enumeration")); + seq_printf(m, "EREADY0\t\t\t: %s\n", + ((reg_value & MVME5500_BOARD_EREADY0) ? + "PMC Slot 1 Ready for Enumeration" : + "PMC Slot 1 Not Ready for Enumeration")); + seq_printf(m, "PMCSPAN\t\t\t: %s\n", + ((reg_value & MVME5500_BOARD_PMCSPAN) ? + "Not Installed" : "Installed")); + seq_printf(m, "PMC2\t\t\t: %s\n", + ((reg_value & MVME5500_BOARD_PMC2) ? + "Not Installed" : "Installed")); + seq_printf(m, "PMC1\t\t\t: %s\n", + ((reg_value & MVME5500_BOARD_PMC1) ? + "Not Installed" : "Installed")); + + /* Configuration Header Switch */ + reg_value = readb(reg_addr++); + seq_printf(m, "Configuration Bits\t: 0x%x\n", reg_value); + + /* TBEN Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "TBEN0\t\t\t: %s\n", + ((reg_value & MVME5500_BOARD_TBEN0) ? + "TBEN pin driven high" : "TBEN pin driven low")); + + /* Geographic Address Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "Geographic Register\t: 0x%x\n", reg_value); + + iounmap(reg_block); + + return 0; +} + +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + parse_bootinfo(find_bootinfo()); + + mvme5500_set_bat(); + +#ifdef CONFIG_BLK_DEV_INITRD + if (r4) { + initrd_start = r4 + KERNELBASE; + initrd_end = r5 + KERNELBASE; + } +#endif + + /* Copy cmd_line parameters */ + if (r6 && (((char *)r6) != '\0')) { + *(char *)(r7 + KERNELBASE) = 0; + strcpy(cmd_line, (char *)(r6 + KERNELBASE)); + } + + isa_io_base = MVME5500_PCI_0_IO_BASE_ADDR_PROC; + isa_mem_base = MVME5500_ISA_MEM_BASE; + pci_dram_offset = MVME5500_PCI_DRAM_OFFSET; + +#ifdef CONFIG_VME_BRIDGE + { + extern void vmemod_setup_options(char *); + + vmemod_setup_options(cmd_line); + } +#endif + + ppc_md.setup_arch = mvme5500_setup_arch; + ppc_md.show_cpuinfo = mvme5500_show_cpuinfo; + ppc_md.init_IRQ = mvme5500_init_irq; + ppc_md.get_irq = gt64260_get_irq; + ppc_md.init = NULL; + + ppc_md.restart = mvme5500_restart; + ppc_md.power_off = mvme5500_power_off; + ppc_md.halt = mvme5500_halt; + + ppc_md.find_end_of_memory = mvme5500_find_end_of_memory; + ppc_md.setup_io_mappings = mvme5500_map_io; + + ppc_md.time_init = todc_time_init; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + ppc_md.calibrate_decr = todc_calibrate_decr; + + ppc_md.nvram_read_val = todc_direct_read_val; + ppc_md.nvram_write_val = todc_direct_write_val; + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pcibios_fixup = NULL; + +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) + mvme5500_early_serial_map(); +#endif + +#ifdef CONFIG_SERIAL_TEXT_DEBUG + ppc_md.progress = gen550_progress; +#endif + +// platform_notify = mvme5500_platform_notify; + platform_notify = NULL; + + return; +} diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/mvme5500.h linux-2.6.14.mod/arch/ppc/platforms/mvme5500.h --- linux-2.6.14.orig/arch/ppc/platforms/mvme5500.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/mvme5500.h 2006-07-06 11:49:01.000000000 -0700 @@ -0,0 +1,214 @@ +/* + * mvme5500.h + * + * Definitions for the MVME5500 Board. + * + * Author: Ajit Prem + * + * Copyright 2003-2006 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/* + * The GT64260 has 2 PCI buses each with 1 window from the CPU bus to + * PCI I/O space and 4 windows from the CPU bus to PCI MEM space. + * We'll only use one PCI MEM window on each PCI bus. + * + * This is the CPU physical memory map (windows must be at least 1MB and start + * on a boundary that is a multiple of the window size): + * + * 0x80000000-0xdfffffff - PCI 0 MEM + * 0xe0000000-0xefffffff - PCI 1 MEM + * 0xf0000000-0xf07fffff - PCI 0 I/O + * 0xf0800000-0xf08fffff - PCI 1 I/O + * 0xf0900000-0xf0ffffff - + * 0xf1000000-0xf10fffff - GT64260 Registers + * 0xf1100000-0xf110ffff - GT64260 Device 1 Bus Registers + * 0xf1110000-0xf1117fff - TODC chip on device module + * 0xf1120000-0xf1120fff - COM1 UART on device module + * 0xf1121000-0xf1121fff - COM2 UART on device module + * 0xf1122000-0xf1ffffff - + * 0xf2000000-0xf3ffffff - Bank A Flash + * 0xf4000000-0xfefbffff - + * 0xfefc0000-0xfeffffff - Internal SRAM + * 0xff800000-0xffffffff - Bank B FLASH + */ + +#ifndef __MVME5500_H +#define __MVME5500_H + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +/* + * CPU Physical Memory Map setup. + */ +#define MVME5500_BRIDGE_REG_BASE 0xf1000000 +#define MVME5500_TODC_BASE 0xf1110000 +#define MVME5500_UART_BASE 0xf1120000 +#define MVME5500_BANK_A_FLASH_BASE 0xf2000000 +#define MVME5500_INTERNAL_SRAM_BASE 0xfefc0000 +#define MVME5500_BANK_B_FLASH_BASE 0xff800000 + +#define MVME5500_BANK_B_FLASH_SIZE 0x00800000 /* 8MB soldered FLASH */ +#define MVME5500_BANK_A_FLASH_SIZE 0x02000000 /* 32MB socketed FLASH */ +#define MVME5500_TODC_SIZE_ACTUAL 0x00008000 /* 32KB for TODC */ +#define MVME5500_UART_SIZE_ACTUAL 0x00001000 /* 4K per UART */ + +#define MVME5500_INTERNAL_SRAM_SIZE 0x40000 /* 256K */ + +#define MVME5500_TODC_SIZE MVME5500_TODC_SIZE_ACTUAL + +#define MVME5500_NVRAM_BASE_ADDRESS 0xf1110000U +#define MVME5500_NVRAM_SIZE 0x8000 + +#define MVME5500_PCI_DRAM_OFFSET 0x00000000 +#define MVME5500_ISA_MEM_BASE 0x00000000 + +#define MVME5500_PCI_0_MEM_SIZE 0x60000000U +#define MVME5500_PCI_0_IO_SIZE 0x00800000U + +#define MVME5500_PCI_1_MEM_SIZE 0x10000000U +#define MVME5500_PCI_1_IO_SIZE 0x00800000U + +#define MVME5500_PCI_0_MEM_BASE_ADDR_PROC 0x80000000U /* CPU Address */ +#define MVME5500_PCI_1_MEM_BASE_ADDR_PROC 0xe0000000U /* CPU Address */ +#define MVME5500_PCI_0_IO_BASE_ADDR_PROC 0xf0000000U +#define MVME5500_PCI_1_IO_BASE_ADDR_PROC 0xf0800000U + +#define MVME5500_PCI_0_MEM_BASE_ADDR 0x80000000U /* PCI Address */ +#define MVME5500_PCI_1_MEM_BASE_ADDR 0xe0000000U /* PCI Address */ +#define MVME5500_PCI_0_IO_BASE_ADDR 0x00000000U +#define MVME5500_PCI_1_IO_BASE_ADDR 0x00800000U + +/* PCI Bus 0 Definitions */ + +/* Processor Physical addresses */ +#define MVME5500_PCI_0_MEM_START_PROC MVME5500_PCI_0_MEM_BASE_ADDR_PROC +#define MVME5500_PCI_0_MEM_END_PROC (MVME5500_PCI_0_MEM_START_PROC + \ + MVME5500_PCI_0_MEM_SIZE - 1) + +#define MVME5500_PCI_0_IO_START_PROC MVME5500_PCI_0_IO_BASE_ADDR_PROC +#define MVME5500_PCI_0_IO_END_PROC (MVME5500_PCI_0_IO_START_PROC + \ + MVME5500_PCI_0_IO_SIZE - 1) + +/* PCI 0 MEM address */ +#define MVME5500_PCI_0_MEM_START MVME5500_PCI_0_MEM_BASE_ADDR +#define MVME5500_PCI_0_MEM_END (MVME5500_PCI_0_MEM_START + \ + MVME5500_PCI_0_MEM_SIZE - 1) + +/* PCI 0 I/O address */ +#define MVME5500_PCI_0_IO_START MVME5500_PCI_0_IO_BASE_ADDR +#define MVME5500_PCI_0_IO_END (MVME5500_PCI_0_IO_START + \ + MVME5500_PCI_0_IO_SIZE - 1) + +/* + * PCI Bus 1 Definitions + */ +/* Processor Physical addresses */ +#define MVME5500_PCI_1_MEM_START_PROC MVME5500_PCI_1_MEM_BASE_ADDR_PROC +#define MVME5500_PCI_1_MEM_END_PROC (MVME5500_PCI_1_MEM_START_PROC + \ + MVME5500_PCI_1_MEM_SIZE - 1) +#define MVME5500_PCI_1_IO_START_PROC MVME5500_PCI_1_IO_BASE_ADDR_PROC +#define MVME5500_PCI_1_IO_END_PROC (MVME5500_PCI_1_IO_START_PROC + \ + MVME5500_PCI_1_IO_SIZE - 1) + +/* PCI 1 MEM address */ +#define MVME5500_PCI_1_MEM_START MVME5500_PCI_1_MEM_BASE_ADDR +#define MVME5500_PCI_1_MEM_END (MVME5500_PCI_1_MEM_START + \ + MVME5500_PCI_1_MEM_SIZE - 1) + +/* PCI 1 I/O address */ +#define MVME5500_PCI_1_IO_START MVME5500_PCI_1_IO_BASE_ADDR +#define MVME5500_PCI_1_IO_END (MVME5500_PCI_1_IO_START + \ + MVME5500_PCI_1_IO_SIZE - 1) + +#define MVME5500_UART_0_IRQ 64 +#define MVME5500_UART_1_IRQ 64 + +#define MVME5500_UART_BASE 0xf1120000 +#define MVME5500_UART_SIZE 0x8 + +/* MVME5500 board register addresses. */ +#define MVME5500_BOARD_STATUS_REG_1 0xf1100000 +#define MVME5500_BOARD_STATUS_REG_2 0xf1100001 +#define MVME5500_BOARD_STATUS_REG_3 0xf1100002 +#define MVME5500_BOARD_PRESENCE_REG 0xf1100004 +#define MVME5500_BOARD_SW_READ_REG 0xf1100005 +#define MVME5500_BOARD_TBEN_REG 0xf1100006 +#define MVME5500_BOARD_GEO_ADDR_REG 0xf1100007 + +/* Status Register 1 */ +#define MVME5500_BOARD_REF_CLOCK 0x80 +#define MVME5500_BOARD_BANK_SEL_MASK 0x40 +#define MVME5500_BOARD_SAFE_START 0x20 +#define MVME5500_BOARD_ABORT_STATUS 0x10 +#define MVME5500_BOARD_FLASH_BUSY 0x08 +#define MVME5500_BOARD_FUSE_STAT 0x04 + +/* Status Register 2 */ +#define MVME5500_BOARD_FAIL_MASK 0x80 +#define MVME5500_BOARD_EEPROM_WP_MASK 0x40 +#define MVME5500_BOARD_FLASH_WP_MASK 0x20 +#define MVME5500_BOARD_TSTAT_MASK 0x10 +#define MVME5500_BOARD_PCIC_M66EN 0x04 +#define MVME5500_BOARD_PCIB_M66EN 0x02 +#define MVME5500_BOARD_PCIA_M66EN 0x01 + +/* Status Register 3 */ +#define MVME5500_BOARD_RESET_MASK 0x80 +#define MVME5500_BOARD_ABORT_INT_MASK 0x40 + +/* Presence Detect Register */ +#define MVME5500_BOARD_EREADY1 0x10 +#define MVME5500_BOARD_EREADY0 0x08 +#define MVME5500_BOARD_PMCSPAN 0x04 +#define MVME5500_BOARD_PMC2 0x02 +#define MVME5500_BOARD_PMC1 0x01 + +/* TBEN register */ +#define MVME5500_BOARD_TBEN0 0x01 + +/* Geographic address register */ +#define MVME5500_BOARD_GEO_ADDR_MASK 0x1f + +/* + * Serial driver setup. + */ +#define MVME5500_SERIAL_0 MVME5500_UART_BASE +#define MVME5500_SERIAL_1 MVME5500_UART_BASE + 0x1000 + +#define MVME5500_BASE_BAUD 1843200 +#define BASE_BAUD (MVME5500_BASE_BAUD / 16) + +#ifdef CONFIG_SERIAL_MANY_PORTS +#define RS_TABLE_SIZE 64 +#else +#define RS_TABLE_SIZE 2 +#endif + +#ifdef CONFIG_SERIAL_DETECT_IRQ +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) +#else +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) +#endif + +/* Required for bootloader's ns16550.c code */ +#define STD_SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, MVME5500_SERIAL_0, 64, STD_COM_FLAGS, /* ttyS0 */ \ + iomem_base: (u8 *)MVME5500_SERIAL_0, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MVME5500_SERIAL_1, 64, STD_COM_FLAGS, \ + iomem_base: (u8 *)MVME5500_SERIAL_1, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM }, + +#define SERIAL_PORT_DFNS STD_SERIAL_PORT_DFNS + +#endif /* __MVME5500_H */ diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/mvme6100.c linux-2.6.14.mod/arch/ppc/platforms/mvme6100.c --- linux-2.6.14.orig/arch/ppc/platforms/mvme6100.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/mvme6100.c 2006-06-06 15:24:10.000000000 -0700 @@ -0,0 +1,873 @@ +/* + * mvme6100.c + * + * Board setup routines for the Motorola MVME6100 Board. + * + * Author: Ajit Prem + * + * Copyright 2003-2006 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mvme6100.h" + +extern void _set_L3CR(unsigned long); +extern char cmd_line[]; +extern unsigned long total_memory; +extern int i8259_pic_irq_offset; + +extern void gen550_progres(char *, unsigned short); +extern void gen550_init(int, struct uart_port *); + +static unsigned long mvme6100_find_end_of_memory(void); +static irqreturn_t mvme6100_i8259_intr(int irq, void *dev_id, + struct pt_regs *regs); + +static struct mv64x60_handle bh; +static void __iomem *sram_base; + +#ifdef CONFIG_VME_BRIDGE_BOOTMEM +void *vme_driver_bootmem; +unsigned int vme_bootmem_size; +#endif + +TODC_ALLOC(); + +/* + * Motorola MVME6100 Board PCI interrupt routing. + */ +static int __init +mvme6100_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + struct pci_controller *hose = (struct pci_controller *)(dev->sysdata); + + if (hose->index == 0) { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {84, 85, 86, 87}, /* IDSEL 5 - VME Bridge ASIC */ + {86, 87, 84, 85}, /* IDSEL 6 - PMC Span Bridge */ + }; + + const long min_idsel = 5, max_idsel = 6, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } else { + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {80, 81, 82, 83}, /* IDSEL 4 - PMC Slot 0 */ + {81, 82, 83, 80}, /* IDSEL 5 - PMC Slot 0, Secondary PCI Agent, IPMC */ + {82, 83, 80, 81}, /* IDSEL 6 - PMC Slot 1 */ + {83, 80, 81, 82}, /* IDSEL 7 - PMC Slot 1, Secondary PCI Agent */ + }; + + const long min_idsel = 4, max_idsel = 7, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; + } +} + +static void __init mvme6100_pci_fixups(void) +{ + struct pci_dev *dev; + unsigned short short_reg; + + if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + PCI_DEVICE_ID_WINBOND_83C553, NULL))) { + /* Clear PCI Interrupt Routing Control Register. */ + short_reg = 0x0000; + pci_write_config_word(dev, 0x44, short_reg); + + /* Setup 8259 interrupts + * Done here as an IPMC may or may not be present + */ + outb(inb(0x04d0) | 0x00, 0x4d0); /* IRQ 0->7 are edge */ + outb(inb(0x04d1) | 0x0a, 0x4d1); /* IRQ 9/11 are level */ + + request_region(0x20, 0x20, "pic1"); + request_region(0xa0, 0x20, "pic2"); + } + if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + PCI_DEVICE_ID_WINBOND_82C105, dev))) { + /* + * Disable both channels + */ + pci_write_config_dword(dev, 0x40, 0x0); + } + +} + +static void __init mvme6100_setup_bridge(void) +{ + struct mv64x60_setup_info si; + int i; + + memset(&si, 0, sizeof(si)); + + si.phys_reg_base = CONFIG_MV64X60_NEW_BASE; + + si.pci_0.enable_bus = 1; + + si.pci_0.pci_io.cpu_base = MVME6100_PCI_0_IO_START_PROC; + si.pci_0.pci_io.pci_base_hi = 0; + si.pci_0.pci_io.pci_base_lo = MVME6100_PCI_0_IO_START; + si.pci_0.pci_io.size = MVME6100_PCI_0_IO_SIZE; + si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; + + si.pci_0.pci_mem[0].cpu_base = MVME6100_PCI_0_MEM_START_PROC; + si.pci_0.pci_mem[0].pci_base_hi = 0; + si.pci_0.pci_mem[0].pci_base_lo = MVME6100_PCI_0_MEM_START; + si.pci_0.pci_mem[0].size = MVME6100_PCI_0_MEM_SIZE; + si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; + + si.pci_0.pci_cmd_bits = 0; + si.pci_0.latency_timer = 0x80; + + si.pci_1.enable_bus = 1; + + si.pci_1.pci_io.cpu_base = MVME6100_PCI_1_IO_START_PROC; + si.pci_1.pci_io.pci_base_hi = 0; + si.pci_1.pci_io.pci_base_lo = MVME6100_PCI_1_IO_START; + si.pci_1.pci_io.size = MVME6100_PCI_1_IO_SIZE; + si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; + + si.pci_1.pci_mem[0].cpu_base = MVME6100_PCI_1_MEM_START_PROC; + si.pci_1.pci_mem[0].pci_base_hi = 0; + si.pci_1.pci_mem[0].pci_base_lo = MVME6100_PCI_1_MEM_START; + si.pci_1.pci_mem[0].size = MVME6100_PCI_1_MEM_SIZE; + si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; + + si.pci_1.pci_cmd_bits = 0; + si.pci_1.latency_timer = 0x80; + + for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) { +#if defined(CONFIG_NOT_COHERENT_CACHE) + si.cpu_prot_options[i] = 0; + si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; + si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; + si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; + + si.pci_1.acc_cntl_options[i] = + MV64360_PCI_ACC_CNTL_SNOOP_NONE | + MV64360_PCI_ACC_CNTL_SWAP_NONE | + MV64360_PCI_ACC_CNTL_MBURST_128_BYTES | + MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; +#else + si.cpu_prot_options[i] = 0; + + si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB; + si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB; + si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB; + + si.pci_0.acc_cntl_options[i] = + MV64360_PCI_ACC_CNTL_SNOOP_WB | + MV64360_PCI_ACC_CNTL_SWAP_NONE | + MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | + MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES; + + si.pci_1.acc_cntl_options[i] = + MV64360_PCI_ACC_CNTL_SNOOP_WB | + MV64360_PCI_ACC_CNTL_SWAP_NONE | + MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | + MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES; +#endif + } + + if (mv64x60_init(&bh, &si)) + printk(KERN_WARNING "Bridge initialization failed.\n"); + + pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */ + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mvme6100_map_irq; + ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; + + mv64x60_set_bus(&bh, 0, 0); + bh.hose_a->first_busno = 0; + bh.hose_a->last_busno = 0xff; + bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0); + + bh.hose_b->first_busno = bh.hose_a->last_busno + 1; + mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno); + bh.hose_b->last_busno = 0xff; + bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, + bh.hose_b->first_busno); + + return; +} + +static struct irqaction mvme6100_i8259_irqaction = { + .handler = mvme6100_i8259_intr, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "i8259 cascade", +}; + +/* Bridge & platform setup routines */ +void __init mvme6100_intr_setup(void) +{ + if (ppc_md.progress) + ppc_md.progress("mvme6100_intr_setup: enter", 0); + + /* MPP 5 */ + mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_0, + BIT20 | BIT21 | BIT22 | BIT23); + /* MPP 7 */ + mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_0, + BIT28 | BIT29 | BIT30 | BIT31); + /* MPP 16-23 */ + mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_2, 0xffffffff); + + /* GPP 5 is active high */ + mv64x60_clr_bits(&bh, MV64x60_GPP_LEVEL_CNTL, BIT5); + /* + * Define GPP 7, 16-23 interrupt polarity as active low + * input signal and level triggered + */ + mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, + BIT7 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | + BIT22 | BIT23); + mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, + BIT5 | BIT7 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | + BIT21 | BIT22 | BIT23); + + /* Config GPP interrupt controller to respond to level trigger */ + + mv64x60_set_bits(&bh, MV64x60_COMM_ARBITER_CNTL, (1 << 10)); + + /* Erratum FEr PCI-#8 */ + mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1 << 5) | (1 << 9)); + mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1 << 5) | (1 << 9)); + + /* + * Dismiss and then enable interrupt on GPP interrupt cause + * for CPU #0 + */ + mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, + ~(BIT5 | BIT7 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | + BIT21 | BIT22 | BIT23)); + + mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, + BIT5 | BIT7 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | + BIT21 | BIT22 | BIT23); + + /* + * Dismiss and then enable interrupt on CPU #0 high cause reg + * BIT26 summarizes GPP interrupts 16-23 (Need MPP 16-23) + * BIT24 summarizes GPP interrupts 0-7 (Need MPP 7) + */ + mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, BIT26 | BIT24); + + if (ppc_md.progress) + ppc_md.progress("mvme6100_intr_setup: exit", 0); +} + +void __init mvme6100_setup_peripherals(void) +{ + int bank_b_boot; + u8 *bankp; + u32 boot_bank_base; + u32 boot_bank_size; + u32 cs0_bank_base; + u32 cs0_bank_size; + + if (ppc_md.progress) + ppc_md.progress("mvme6100_setup_peripherals: enter", 0); + + bankp = ioremap(MVME6100_BOARD_STATUS_REG_1, 1); + bank_b_boot = readb(bankp) & MVME6100_BOARD_BANK_SEL_MASK; + if (bank_b_boot) { + cs0_bank_base = MVME6100_BANK_A_FLASH_BASE; + cs0_bank_size = MVME6100_BANK_A_FLASH_SIZE; + boot_bank_base = MVME6100_BANK_B_FLASH_BASE; + boot_bank_size = MVME6100_BANK_B_FLASH_SIZE; + } else { + cs0_bank_base = MVME6100_BANK_B_FLASH_BASE; + cs0_bank_size = MVME6100_BANK_B_FLASH_SIZE; + boot_bank_base = MVME6100_BANK_A_FLASH_BASE; + boot_bank_size = MVME6100_BANK_A_FLASH_SIZE; + } + + /* Set up windows for flash banks */ + mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, + boot_bank_base, boot_bank_size, 0); + bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); + + mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, + cs0_bank_base, cs0_bank_size, 0); + bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN); + + mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, + MVME6100_DEVICE_CS1_BASE, + MVME6100_DEVICE_CS1_SIZE, 0); + + /* Disable unused windows */ + mv64x60_write(&bh, MV64x60_CPU2DEV_2_BASE, 0); + mv64x60_write(&bh, MV64x60_CPU2DEV_2_SIZE, 0); + mv64x60_write(&bh, MV64x60_CPU2DEV_3_BASE, 0); + mv64x60_write(&bh, MV64x60_CPU2DEV_3_SIZE, 0); + + /* Set up internal SRAM window */ + mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, + MVME6100_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, + 0); + bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); + sram_base = ioremap(MVME6100_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE); + + /* Set up Enet->SRAM window */ + mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN, + MVME6100_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, + 0x2); + bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN); + + /* Give enet r/w access to memory region */ + mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_0, (0x3 << (4 << 1))); + mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_1, (0x3 << (4 << 1))); + mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_2, (0x3 << (4 << 1))); + + mv64x60_clr_bits(&bh, MV64x60_PCI0_PCI_DECODE_CNTL, (1 << 3)); + mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3)); + /* Turn off timer/counters */ + mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, + ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24))); + + /* Only 1 CPU */ + mv64x60_set_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1 << 9)); + +#if defined(CONFIG_NOT_COHERENT_CACHE) + mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x00160000); +#else + mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2); +#endif + + /* + * Set the SRAM to 0. Note that this may generate parity errors on + * internal data path in SRAM since it is the first time accessing it + * (if firmware hasn't done it already). + */ + memset(sram_base, 0, MV64360_SRAM_SIZE); + + /* set up PCI interrupt controller */ + mvme6100_intr_setup(); + + if (ppc_md.progress) + ppc_md.progress("mvme6100_setup_peripherals: exit", 0); +} + +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) +static void __init mvme6100_early_serial_map(void) +{ + struct uart_port serial_req; + + memset(&serial_req, 0, sizeof(serial_req)); + serial_req.uartclk = MVME6100_BASE_BAUD; + serial_req.irq = MVME6100_UART_0_IRQ; + serial_req.line = 0; + serial_req.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + serial_req.iotype = SERIAL_IO_MEM; + serial_req.membase = (u_char *) MVME6100_SERIAL_0; + serial_req.regshift = 0; + + gen550_init(0, &serial_req); + + if (early_serial_setup(&serial_req) != 0) { + printk("Early serial init of port 0 failed\n"); + } + + /* Assume early_serial_setup() doesn't modify serial_req */ + serial_req.line = 1; + serial_req.irq = MVME6100_UART_1_IRQ; + serial_req.membase = (u_char *) MVME6100_SERIAL_1; + + gen550_init(1, &serial_req); + + if (early_serial_setup(&serial_req) != 0) { + printk("Early serial init of port 1 failed\n"); + } +} +#endif + +static void __init mvme6100_init_caches(void) +{ + uint val; + + /* Enable L2 and L3 caches (if 745x) */ + val = _get_L2CR(); + val |= L2CR_L2E; + _set_L2CR(val); + + val = _get_L3CR(); + val |= L3CR_L3E; + _set_L3CR(val); +} + +static void __init mvme6100_misc_init(void) +{ + u8 *status_reg_2_addr; + u8 status_reg_2; + + status_reg_2_addr = ioremap(MVME6100_BOARD_STATUS_REG_2, 1); + status_reg_2 = readb(status_reg_2_addr); + status_reg_2 &= ~MVME6100_BOARD_FAIL_MASK; + status_reg_2 &= ~MVME6100_BOARD_FLASH0_SW_WP_MASK; + writeb(status_reg_2, status_reg_2_addr); + iounmap(status_reg_2_addr); + + return; +} + +static void __init mvme6100_setup_arch(void) +{ + if (ppc_md.progress) + ppc_md.progress("mvme6100_setup_arch: enter", 0); + + loops_per_jiffy = 50000000 / HZ; + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_SDA2; +#endif + +#ifdef CONFIG_VME_BRIDGE_BOOTMEM + vme_bootmem_size = CONFIG_VME_BRIDGE_BOOTMEM_SIZE * 1024 * 1024; + + if (vme_bootmem_size > (total_memory / 2)) { + printk(KERN_WARNING "BOOTMEM Size Requested: 0x%x Total Memory 0x%lx\n", vme_bootmem_size, total_memory); + printk(KERN_WARNING "BOOTMEM Size requested has been capped at half the total memory\n"); + vme_bootmem_size = total_memory / 2; + } + vme_driver_bootmem = __alloc_bootmem(vme_bootmem_size, 0x10000, 0); + if (!vme_driver_bootmem) { + printk(KERN_WARNING "Unable to obtain boot memory for VME\n"); + vme_bootmem_size = 0; + } else { + printk(KERN_INFO "0x%x of boot memory reserved for setup of VME inbound window 7\n", vme_bootmem_size); + } +#endif + + mvme6100_init_caches(); + + if (ppc_md.progress) + ppc_md.progress("mvme6100_setup_arch: find_bridges", 0); + + mvme6100_setup_bridge(); + + if (ppc_md.progress) + ppc_md.progress("mvme6100_setup_arch: find_bridges done", 0); + + mvme6100_setup_peripherals(); + + TODC_INIT(TODC_TYPE_MK48T37, 0, 0, + ioremap(MVME6100_TODC_BASE, MVME6100_TODC_SIZE), 8); + + mvme6100_misc_init(); + + printk("Motorola Computer Group MVME6100 Board\n"); + printk("MVME6100 port (C) 2003-2006 Motorola, Inc.\n"); + + if (ppc_md.progress) + ppc_md.progress("mvme6100_setup_arch: exit", 0); + + return; +} + +static void __init mvme6100_init_irq(void) +{ + int i; + + i8259_pic_irq_offset = 96; + mv64360_init_irq(); + + for (i = 96; (i < (96 + NUM_8259_INTERRUPTS)); i++) + irq_desc[i].handler = &i8259_pic; + + irq_desc[105].status |= IRQ_LEVEL; + i8259_init(0xf1000cb4); + + /* Hook up i8259 interrupt which is connected to GPP5 */ + if (setup_irq(MV64x60_IRQ_GPP5, &mvme6100_i8259_irqaction)) + printk("Unable to get IRQ %d for cascade\n", MV64x60_IRQ_GPP5); + +} + +static irqreturn_t mvme6100_i8259_intr(int irq, void *dev_id, + struct pt_regs *regs) +{ + u32 temp = mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE); + + if (temp & (1 << 5)) { + i8259_irq(regs); + mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, temp & (~(1 << 5))); + (void)mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE); + (void)mv64x60_read(&bh, MV64x60_GPP_INTR_MASK); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static int mvme6100_get_irq(struct pt_regs *regs) +{ + int irq; + + irq = mv64360_get_irq(regs); + if (irq == MV64x60_IRQ_GPP5) { + u32 temp; + + temp = mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE); + irq = 96 + i8259_irq(regs); + mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, temp & (~(1 << 5))); + (void)mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE); + (void)mv64x60_read(&bh, MV64x60_GPP_INTR_MASK); + } + return irq; +} + +unsigned long __init mvme6100_find_end_of_memory(void) +{ + return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE, + MV64x60_TYPE_MV64360); +} + +/* + * Set BAT 3 to map 0xf0000000 to end of physical memory space. + */ +static __inline__ void mvme6100_set_bat(void) +{ + mb(); + mtspr(SPRN_DBAT1U, 0xf0001ffe); + mtspr(SPRN_DBAT1L, 0xf000002a); + mb(); + + return; +} + +static void __init mvme6100_map_io(void) +{ + io_block_mapping(0xf1000000, 0xf1000000, 0x01000000, _PAGE_IO); + io_block_mapping(MVME6100_INTERNAL_SRAM_BASE, + MVME6100_INTERNAL_SRAM_BASE, + MVME6100_INTERNAL_SRAM_SIZE, _PAGE_IO); +} + +static void mvme6100_restart(char *cmd) +{ + volatile ulong i = 10000000; + u8 *status_reg_3_addr; + + local_irq_disable(); + status_reg_3_addr = ioremap(MVME6100_BOARD_STATUS_REG_3, 1); + writeb(MVME6100_BOARD_RESET_MASK, status_reg_3_addr); + + while (i-- > 0) ; + panic("restart failed\n"); +} + +static void mvme6100_halt(void) +{ + local_irq_disable(); + while (1) ; + /* NOTREACHED */ +} + +static void mvme6100_power_off(void) +{ + mvme6100_halt(); + /* NOTREACHED */ +} + +static int mvme6100_show_cpuinfo(struct seq_file *m) +{ + uint tmp; + uint memsize = total_memory; + u8 reg_value; + u8 *reg_addr, *reg_block; + + seq_printf(m, "vendor\t\t: Motorola\n"); + seq_printf(m, "machine\t\t: MVME6100\n"); + tmp = mfspr(SPRN_PVR); + seq_printf(m, "PVID\t\t: 0x%x, vendor: %s\n", + tmp, (tmp & (1 << 15) ? "IBM" : "Motorola")); + tmp = mfspr(SPRN_HID0); + seq_printf(m, "HID0\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_HID1); + seq_printf(m, "HID1\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_MSSCR0); + seq_printf(m, "MSSCR0\t\t: 0x%08x, Bus Mode: %s\n", + tmp, ((((tmp & 0x00030000) >> 16) == 0) ? "60X" : "MPX")); + tmp = mfspr(SPRN_MSSSR0); + seq_printf(m, "MSSSR0\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_L2CR); + seq_printf(m, "L2CR\t\t: 0x%08x\n", tmp); + tmp = mfspr(SPRN_L3CR); + seq_printf(m, "L3CR\t\t: 0x%08x\n", tmp); + + seq_printf(m, "\nBOARD INFORMATION:\n\n"); + reg_block = ioremap(MVME6100_BOARD_STATUS_REG_1, 8); + reg_addr = reg_block; + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t\t: %d MB\n", memsize / (1024 * 1024)); + + /* System Status Register 1 */ + reg_value = readb(reg_addr++); + seq_printf(m, "Reference Clock\t\t: %s\n", + ((reg_value & MVME6100_BOARD_REF_CLOCK) ? + "Bit Set" : "Bit Not Set")); + seq_printf(m, "Flash Boot Block Select\t: %s\n", + ((reg_value & MVME6100_BOARD_BANK_SEL_MASK) ? + "Flash 1 is the boot bank" : "Flash 0 is the boot bank")); + seq_printf(m, "Safe Start Status\t: %s\n", + ((reg_value & MVME6100_BOARD_SAFE_START) ? + "Safe ENV settings used" : "NVRAM ENV settings used")); + seq_printf(m, "Abort Status\t\t: %s\n", + ((reg_value & MVME6100_BOARD_ABORT_STATUS) ? + "Abort Switch Not Asserted" : "Abort Switch Asserted")); + seq_printf(m, "Flash Busy\t\t: %s\n", + ((reg_value & MVME6100_BOARD_FLASH_BUSY) ? + "Bit Set" : "Bit Not Set")); + seq_printf(m, "Fuse Status\t\t: %s\n", + ((reg_value & MVME6100_BOARD_FUSE_STAT) ? + "Fuses Functional" : "A fuse is open")); + seq_printf(m, "SROM Init Status\t: %s\n", + ((reg_value & MVME6100_BOARD_SROM_INIT) ? + "MV64360 SROM Init Enabled" : + "MV64360 SROM Init Disabled")); + + reg_value = readb(reg_addr++); + seq_printf(m, "Board Fail LED\t\t: %s\n", + ((reg_value & MVME6100_BOARD_FAIL_MASK) ? + "LED Lit" : "LED Not Lit")); + seq_printf(m, "Flash0 SW WP Status\t: %s\n", + ((reg_value & MVME6100_BOARD_FLASH0_SW_WP_MASK) ? + "Flash0 Write Protected" : + "Flash0 Not SW Write Protected")); + seq_printf(m, "DS1621 Thermostat\t: %s\n", + ((reg_value & MVME6100_BOARD_TSTAT_MASK) ? + "Interrupt Disabled" : "Interrupt Enabled")); + seq_printf(m, "Flash1 Boot SW WP Status: %s\n", + ((reg_value & MVME6100_BOARD_FLASH1_BOOT_SW_WP_MASK) ? + "Flash1 Boot SW Write Protected" : + "Flash1 Boot Not SW Write Protected")); + seq_printf(m, "Flash0 HW WP Status\t: %s\n", + ((reg_value & MVME6100_BOARD_FLASH0_HW_WP_MASK) ? + "Flash0 HW Write Protected" : + "Flash0 Not HW Write Protected")); + seq_printf(m, "Flash1 Boot HW WP Status: %s\n", + ((reg_value & MVME6100_BOARD_FLASH1_BOOT_HW_WP_MASK) ? + "Flash1 Boot HW Write Protected" : + "Flash1 Boot Not HW Write Protected")); + + /* Presence Detect Register */ + reg_value = readb(reg_addr++); + reg_value = readb(reg_addr++); + seq_printf(m, "EREADY1\t\t\t: %s\n", + ((reg_value & MVME6100_BOARD_EREADY1) ? + "PMC Slot 2 Ready for Enumeration" : + "PMC Slot 2 Not Ready for Enumeration")); + seq_printf(m, "EREADY0\t\t\t: %s\n", + ((reg_value & MVME6100_BOARD_EREADY0) ? + "PMC Slot 1 Ready for Enumeration" : + "PMC Slot 1 Not Ready for Enumeration")); + seq_printf(m, "PMCSPAN\t\t\t: %s\n", + ((reg_value & MVME6100_BOARD_PMCSPAN) ? + "Not Installed" : "Installed")); + seq_printf(m, "PMC2\t\t\t: %s\n", + ((reg_value & MVME6100_BOARD_PMC2) ? + "Not Installed" : "Installed")); + seq_printf(m, "PMC1\t\t\t: %s\n", + ((reg_value & MVME6100_BOARD_PMC1) ? + "Not Installed" : "Installed")); + + /* Configuration Header Switch */ + reg_value = readb(reg_addr++); + seq_printf(m, "Configuration Bits\t: 0x%x\n", reg_value); + + /* TBEN Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "TBEN0\t\t\t: %s\n", + ((reg_value & MVME6100_BOARD_TBEN0) ? + "TBEN pin driven high" : "TBEN pin driven low")); + + /* Geographic Address Register */ + reg_value = readb(reg_addr++); + seq_printf(m, "Geographic Register\t: 0x%x\n", reg_value); + + iounmap(reg_block); + + return 0; +} + +static void __init mvme6100_fixup_eth_pdata(struct platform_device *pdev) +{ + struct mv643xx_eth_platform_data *eth_pd; + static u16 phy_addr[] = { + MVME6100_ETH0_PHY_ADDR, + MVME6100_ETH1_PHY_ADDR, + }; + + eth_pd = pdev->dev.platform_data; + eth_pd->force_phy_addr = 1; + eth_pd->phy_addr = phy_addr[pdev->id]; + eth_pd->tx_queue_size = MVME6100_ETH_TX_QUEUE_SIZE; + eth_pd->rx_queue_size = MVME6100_ETH_RX_QUEUE_SIZE; +#ifdef CONFIG_MV64X60_USE_SRAM + if (pdev->id == 0) { + eth_pd->rx_sram_addr = MVME6100_INTERNAL_SRAM_BASE; + eth_pd->rx_sram_size = 16000; + eth_pd->tx_sram_addr = MVME6100_INTERNAL_SRAM_BASE + 16000; + eth_pd->tx_sram_size = 48000; + } else { + eth_pd->rx_sram_addr = MVME6100_INTERNAL_SRAM_BASE + 64000; + eth_pd->rx_sram_size = 16000; + eth_pd->tx_sram_addr = MVME6100_INTERNAL_SRAM_BASE + 80000; + eth_pd->tx_sram_size = 48000; + } +#endif +} + +static int __init mvme6100_platform_notify(struct device *dev) +{ + static struct { + char *bus_id; + void ((*rtn) (struct platform_device * pdev)); + } dev_map[] = { + { + MV643XX_ETH_NAME ".0", mvme6100_fixup_eth_pdata}, { + MV643XX_ETH_NAME ".1", mvme6100_fixup_eth_pdata},}; + struct platform_device *pdev; + int i; + + if (dev && dev->bus_id) + for (i = 0; i < ARRAY_SIZE(dev_map); i++) + if (!strncmp(dev->bus_id, dev_map[i].bus_id, + BUS_ID_SIZE)) { + + pdev = container_of(dev, + struct platform_device, + dev); + dev_map[i].rtn(pdev); + } + return 0; +} + +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + + parse_bootinfo(find_bootinfo()); + + mvme6100_set_bat(); + +#ifdef CONFIG_BLK_DEV_INITRD + if (r4) { + initrd_start = r4 + KERNELBASE; + initrd_end = r5 + KERNELBASE; + } +#endif + + /* Copy cmd_line parameters */ + if (r6 && (((char *)r6) != '\0')) { + *(char *)(r7 + KERNELBASE) = 0; + strcpy(cmd_line, (char *)(r6 + KERNELBASE)); + } + + isa_mem_base = MVME6100_ISA_MEM_BASE; + pci_dram_offset = MVME6100_PCI_DRAM_OFFSET; + +#ifdef CONFIG_VME_BRIDGE + { + extern void vmemod_setup_options(char *); + + vmemod_setup_options(cmd_line); + } +#endif + + ppc_md.setup_arch = mvme6100_setup_arch; + ppc_md.show_cpuinfo = mvme6100_show_cpuinfo; + ppc_md.init_IRQ = mvme6100_init_irq; + ppc_md.get_irq = mvme6100_get_irq; + + ppc_md.restart = mvme6100_restart; + ppc_md.power_off = mvme6100_power_off; + ppc_md.halt = mvme6100_halt; + + ppc_md.find_end_of_memory = mvme6100_find_end_of_memory; + ppc_md.setup_io_mappings = mvme6100_map_io; + + ppc_md.time_init = todc_time_init; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + ppc_md.calibrate_decr = todc_calibrate_decr; + + ppc_md.nvram_read_val = todc_direct_read_val; + ppc_md.nvram_write_val = todc_direct_write_val; + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pcibios_fixup = mvme6100_pci_fixups; + +#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) + mvme6100_early_serial_map(); +#endif + +#ifdef CONFIG_SERIAL_TEXT_DEBUG + ppc_md.progress = gen550_progress; +#endif + + platform_notify = mvme6100_platform_notify; +} diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/platforms/mvme6100.h linux-2.6.14.mod/arch/ppc/platforms/mvme6100.h --- linux-2.6.14.orig/arch/ppc/platforms/mvme6100.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/platforms/mvme6100.h 2006-03-09 12:34:24.000000000 -0700 @@ -0,0 +1,236 @@ +/* + * mvme6100.h + * + * Definitions for the MVME6100 Board. + * + * Author: Ajit Prem (Ajit.Prem@motorola.com) + * + * Copyright 2003-2006 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/* + * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to + * PCI I/O space and 4 windows from the CPU bus to PCI MEM space. + * We'll only use one PCI MEM window on each PCI bus. + * + * This is the CPU physical memory map (windows must be at least 1MB and start + * on a boundary that is a multiple of the window size): + * + * 0xc0000000-0xdfffffff - PCI 0 MEM + * 0xe0000000-0xefffffff - PCI 1 MEM + * 0xf0800000-0xf08fffff - PCI 0 I/O + * 0xf0000000-0xf07fffff - PCI 1 I/O + * 0xf0900000-0xf0ffffff - + * 0xf1000000-0xf10fffff - MV64360 Registers + * 0xf1100000-0xf110ffff - MV64360 Device 1 Bus Registers + * 0xf1110000-0xf1117fff - TODC chip on device module + * 0xf1120000-0xf1120fff - COM1 UART on device module + * 0xf1121000-0xf1121fff - COM2 UART on device module + * 0xf1122000-0xf3ffffff - + * 0xf4000000-0xf7ffffff - Bank A Flash + * 0xf8000000-0xfbffffff - Bank B Flash + * 0xfefc0000-0xfeffffff - Integrated SRAM + */ + +#ifndef __MVME6100_H +#define __MVME6100_H + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +/* + * CPU Physical Memory Map setup. + */ +#define MVME6100_BANK_B_FLASH_BASE 0xf8000000 /* Bank B */ +#define MVME6100_BANK_A_FLASH_BASE 0xf4000000 /* Bank A */ +#define MVME6100_BRIDGE_REG_BASE 0xf1000000 +#define MVME6100_DEVICE_CS1_BASE 0xf1100000 +#define MVME6100_TODC_BASE 0xf1110000 +#define MVME6100_UART_BASE 0xf1120000 +#define MVME6100_INTERNAL_SRAM_BASE 0xfefc0000 + +#define MVME6100_BANK_B_FLASH_SIZE 0x04000000 /* 64MB Bank B FLASH */ +#define MVME6100_BANK_A_FLASH_SIZE 0x04000000 /* 64MB (Max) Bank A FLASH */ +#define MVME6100_DEVICE_CS1_SIZE_ACTUAL 0x00100000 /* 1MB */ +#define MVME6100_INTERNAL_SRAM_SIZE _256K /* 256KByte internal SRAM */ +#define MVME6100_UART_SIZE_ACTUAL 0x00001000 /* 4K per UART */ +#define MVME6100_TODC_SIZE_ACTUAL 0x00008000 /* 32KB for TODC */ + +#define MVME6100_DEVICE_CS1_SIZE MAX(MV64360_WINDOW_SIZE_MIN, \ + MVME6100_DEVICE_CS1_SIZE_ACTUAL) + +#define MVME6100_UART_SIZE 0x8 +#define MVME6100_TODC_SIZE MVME6100_TODC_SIZE_ACTUAL + +#define MVME6100_NVRAM_BASE_ADDRESS 0xf1110000U +#define MVME6100_NVRAM_SIZE 0x8000 + +#define MVME6100_PCI_DRAM_OFFSET 0x00000000 +#define MVME6100_ISA_MEM_BASE 0x00000000 + +#define _IO_BASE isa_io_base +#define _ISA_MEM_BASE isa_mem_base +#define PCI_DRAM_OFFSET pci_dram_offset + +/* MVME6100 board register addresses. */ +#define MVME6100_BOARD_STATUS_REG_1 0xf1100000 +#define MVME6100_BOARD_STATUS_REG_2 0xf1100001 +#define MVME6100_BOARD_STATUS_REG_3 0xf1100002 +#define MVME6100_BOARD_PRESENCE_REG 0xf1100004 +#define MVME6100_BOARD_SW_READ_REG 0xf1100005 +#define MVME6100_BOARD_TBEN_REG 0xf1100006 +#define MVME6100_BOARD_GEO_ADDR_REG 0xf1100007 + +/* Status Register 1 */ +#define MVME6100_BOARD_REF_CLOCK 0x80 +#define MVME6100_BOARD_BANK_SEL_MASK 0x40 +#define MVME6100_BOARD_SAFE_START 0x20 +#define MVME6100_BOARD_ABORT_STATUS 0x10 +#define MVME6100_BOARD_FLASH_BUSY 0x08 +#define MVME6100_BOARD_FUSE_STAT 0x04 +#define MVME6100_BOARD_SROM_INIT 0x02 + +/* Status Register 2 */ +#define MVME6100_BOARD_FAIL_MASK 0x80 +#define MVME6100_BOARD_FLASH0_SW_WP_MASK 0x20 +#define MVME6100_BOARD_TSTAT_MASK 0x10 +#define MVME6100_BOARD_FLASH1_BOOT_SW_WP_MASK 0x08 +#define MVME6100_BOARD_FLASH0_HW_WP_MASK 0x04 +#define MVME6100_BOARD_FLASH1_BOOT_HW_WP_MASK 0x02 + +/* Status Register 3 */ +#define MVME6100_BOARD_RESET_MASK 0x80 +#define MVME6100_BOARD_PCI0_RESET_MASK 0x01 +#define MVME6100_BOARD_PCI1_RESET_MASK 0x02 + +/* Presence Detect Register */ +#define MVME6100_BOARD_EREADY1 0x10 +#define MVME6100_BOARD_EREADY0 0x08 +#define MVME6100_BOARD_PMCSPAN 0x04 +#define MVME6100_BOARD_PMC2 0x02 +#define MVME6100_BOARD_PMC1 0x01 + +/* TBEN register */ +#define MVME6100_BOARD_TBEN0 0x01 + +/* Geographic Address Register 6 */ +#define MVME6100_BOARD_GEO_ADDR_MASK 0x1f + +/* Memory Map */ +#define MVME6100_PCI_0_MEM_SIZE 0x20000000U +#define MVME6100_PCI_0_IO_SIZE 0x00800000U + +#define MVME6100_PCI_1_MEM_SIZE 0x10000000U +#define MVME6100_PCI_1_IO_SIZE 0x00800000U + +#define MVME6100_PCI_0_MEM_BASE_ADDR_PROC 0xc0000000U /* CPU Address */ +#define MVME6100_PCI_0_IO_BASE_ADDR_PROC 0xf0000000U +#define MVME6100_PCI_1_MEM_BASE_ADDR_PROC 0xe0000000U /* CPU Address */ +#define MVME6100_PCI_1_IO_BASE_ADDR_PROC 0xf0800000U + +#define MVME6100_PCI_0_MEM_BASE_ADDR 0xc0000000U /* PCI Address */ +#define MVME6100_PCI_0_IO_BASE_ADDR 0x00000000U +#define MVME6100_PCI_1_MEM_BASE_ADDR 0xe0000000U /* PCI Address */ +#define MVME6100_PCI_1_IO_BASE_ADDR 0x00800000U + +/* PCI Bus 0 Definitions */ + +/* Processor Physical addresses */ +#define MVME6100_PCI_0_MEM_START_PROC MVME6100_PCI_0_MEM_BASE_ADDR_PROC +#define MVME6100_PCI_0_MEM_END_PROC (MVME6100_PCI_0_MEM_START_PROC + \ + MVME6100_PCI_0_MEM_SIZE - 1) +#define MVME6100_PCI_0_IO_START_PROC MVME6100_PCI_0_IO_BASE_ADDR_PROC +#define MVME6100_PCI_0_IO_END_PROC (MVME6100_PCI_0_IO_START_PROC + \ + MVME6100_PCI_0_IO_SIZE - 1) + +/* PCI 0 MEM address */ +#define MVME6100_PCI_0_MEM_START MVME6100_PCI_0_MEM_BASE_ADDR +#define MVME6100_PCI_0_MEM_END (MVME6100_PCI_0_MEM_START + \ + MVME6100_PCI_0_MEM_SIZE - 1) + +/* PCI 0 I/O address */ +#define MVME6100_PCI_0_IO_START MVME6100_PCI_0_IO_BASE_ADDR +#define MVME6100_PCI_0_IO_END (MVME6100_PCI_0_IO_START + \ + MVME6100_PCI_0_IO_SIZE - 1) + +/* PCI Bus 1 Definitions */ + +/* Processor Physical addresses */ +#define MVME6100_PCI_1_MEM_START_PROC MVME6100_PCI_1_MEM_BASE_ADDR_PROC +#define MVME6100_PCI_1_MEM_END_PROC (MVME6100_PCI_1_MEM_START_PROC + \ + MVME6100_PCI_1_MEM_SIZE - 1) +#define MVME6100_PCI_1_IO_START_PROC MVME6100_PCI_1_IO_BASE_ADDR_PROC +#define MVME6100_PCI_1_IO_END_PROC (MVME6100_PCI_1_IO_START_PROC + \ + MVME6100_PCI_1_IO_SIZE - 1) + +/* PCI 1 MEM address */ +#define MVME6100_PCI_1_MEM_START MVME6100_PCI_1_MEM_BASE_ADDR +#define MVME6100_PCI_1_MEM_END (MVME6100_PCI_1_MEM_START + \ + MVME6100_PCI_1_MEM_SIZE - 1) + +/* PCI 1 I/O address */ +#define MVME6100_PCI_1_IO_START MVME6100_PCI_1_IO_BASE_ADDR +#define MVME6100_PCI_1_IO_END (MVME6100_PCI_1_IO_START + \ + MVME6100_PCI_1_IO_SIZE - 1) + +#define MVME6100_SERIAL_0 MVME6100_UART_BASE +#define MVME6100_SERIAL_1 MVME6100_UART_BASE +0x1000 + +#define MVME6100_SERIAL_2 MVME6100_PCI_1_IO_BASE_ADDR_PROC + 0x03f8 +#define MVME6100_SERIAL_3 MVME6100_PCI_1_IO_BASE_ADDR_PROC + 0x02f8 + +#define MVME6100_UART_0_IRQ 64 +#define MVME6100_UART_1_IRQ 64 +#define MVME6100_UART_2_IRQ 100 +#define MVME6100_UART_3_IRQ 99 + +#define MVME6100_BASE_BAUD 1843200 +#define BASE_BAUD (MVME6100_BASE_BAUD / 16) + +#ifdef CONFIG_SERIAL_MANY_PORTS +#define RS_TABLE_SIZE 64 +#else +#define RS_TABLE_SIZE 4 +#endif + +#ifdef CONFIG_SERIAL_DETECT_IRQ +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) +#else +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) +#endif + +/* Required for bootloader's ns16550.c code */ +#define STD_SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, MVME6100_SERIAL_0, MVME6100_UART_0_IRQ, STD_COM_FLAGS, /* ttyS0 */ \ + iomem_base: (u8 *)MVME6100_SERIAL_0, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MVME6100_SERIAL_1, MVME6100_UART_1_IRQ, STD_COM_FLAGS, /* ttyS1 */ \ + iomem_base: (u8 *)MVME6100_SERIAL_1, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MVME6100_SERIAL_2, MVME6100_UART_2_IRQ, STD_COM_FLAGS, /* ttyS2 */ \ + iomem_base: (u8 *)MVME6100_SERIAL_2, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MVME6100_SERIAL_3, MVME6100_UART_3_IRQ, STD_COM_FLAGS, /* ttyS3 */ \ + iomem_base: (u8 *)MVME6100_SERIAL_3, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM }, + +#define SERIAL_PORT_DFNS STD_SERIAL_PORT_DFNS + +#define MVME6100_ETH0_PHY_ADDR 1 +#define MVME6100_ETH1_PHY_ADDR 2 +#define MVME6100_ETH2_PHY_ADDR 3 + +#define MVME6100_ETH_TX_QUEUE_SIZE 800 +#define MVME6100_ETH_RX_QUEUE_SIZE 400 + +#endif /* __MVME6100_H */ diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/syslib/gen550_dbg.c linux-2.6.14.mod/arch/ppc/syslib/gen550_dbg.c --- linux-2.6.14.orig/arch/ppc/syslib/gen550_dbg.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/syslib/gen550_dbg.c 2005-11-16 10:40:20.000000000 -0700 @@ -90,6 +90,7 @@ /* How far apart the registers are. */ shift = rs_table[chan].iomem_reg_shift; +#if !(defined(CONFIG_MVME3100)) /* save the LCR */ lcr = serial_inb(com_port + (UART_LCR << shift)); @@ -121,6 +122,7 @@ /* Clear & enable FIFOs */ serial_outb(com_port + (UART_FCR << shift), 0x07); } +#endif return (com_port); } diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/syslib/Makefile linux-2.6.14.mod/arch/ppc/syslib/Makefile --- linux-2.6.14.orig/arch/ppc/syslib/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/syslib/Makefile 2006-01-20 16:56:40.000000000 -0700 @@ -60,6 +60,15 @@ obj-$(CONFIG_MVME5100) += open_pic.o todc_time.o indirect_pci.o \ pci_auto.o hawk_common.o obj-$(CONFIG_MVME5100_IPMC761_PRESENT) += i8259.o +obj-$(CONFIG_MVME5500) += mv64x60.o gt64260_pic.o \ + pci_auto.o todc_time.o \ + indirect_pci.o i8259.o +obj-$(CONFIG_MVME6100) += mv64x60.o mv64360_pic.o \ + pci_auto.o todc_time.o \ + indirect_pci.o i8259.o +obj-$(CONFIG_MCP905) += mv64x60.o mv64360_pic.o \ + pci_auto.o todc_time.o indirect_pci.o + obj-$(CONFIG_OCOTEA) += indirect_pci.o pci_auto.o todc_time.o obj-$(CONFIG_PAL4) += cpc700_pic.o obj-$(CONFIG_POWERPMC250) += pci_auto.o @@ -97,6 +106,7 @@ ifeq ($(CONFIG_85xx),y) obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o endif +obj-$(CONFIG_MPC85xx_DMA) += mpc85xx_dma.o obj-$(CONFIG_83xx) += ipic.o ppc83xx_setup.o ppc_sys.o \ mpc83xx_sys.o mpc83xx_devices.o ifeq ($(CONFIG_83xx),y) diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/syslib/mpc85xx_devices.c linux-2.6.14.mod/arch/ppc/syslib/mpc85xx_devices.c --- linux-2.6.14.orig/arch/ppc/syslib/mpc85xx_devices.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/syslib/mpc85xx_devices.c 2006-02-06 11:28:54.000000000 -0700 @@ -95,12 +95,39 @@ .iotype = UPIO_MEM, .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ, }, +#ifndef CONFIG_MVME3100 [1] = { .mapbase = 0x4600, .irq = MPC85xx_IRQ_DUART, .iotype = UPIO_MEM, .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ, }, +#else + [1] = { + .mapbase = 0xE2011000U, + .irq = MPC85xx_IRQ_EXT3, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ, + }, + [2] = { + .mapbase = 0xE2012000U, + .irq = MPC85xx_IRQ_EXT3, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ, + }, + [3] = { + .mapbase = 0xE2013000U, + .irq = MPC85xx_IRQ_EXT3, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ, + }, + [4] = { + .mapbase = 0xE2014000U, + .irq = MPC85xx_IRQ_EXT3, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ, + }, +#endif { }, }; diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/syslib/mpc85xx_dma.c linux-2.6.14.mod/arch/ppc/syslib/mpc85xx_dma.c --- linux-2.6.14.orig/arch/ppc/syslib/mpc85xx_dma.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/syslib/mpc85xx_dma.c 2006-02-16 13:12:14.000000000 -0700 @@ -0,0 +1,549 @@ +/* + * MPC85xx DMA Support + * + * Author: Ajit Prem + * Copyright 2005-2006 Motorola Inc. + * + * Based on work done by Jason McMullan + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#undef DMA_DEBUG + +#ifdef DMA_DEBUG +# ifndef assert +# define assert(x) do { if (!(x)) { printk("KERNEL: assertion (" #x ") failed at " __FILE__ "(%d):%s\n", __LINE__, __FUNCTION__); \ + } } while (0) +# endif +# define DPRINTK(x, a...) printk(x , ## a) +#else +# ifndef assert +# define assert(x) do { /**/ } while (0) +# endif +# define DPRINTK(x, a...) do { /**/ } while (0) +#endif + +/* DMA Registers(0x2_1000-0x2_1FFF) */ + +struct ccsr_dma { + /* Skip first 256 bytes */ + /* 0x21100 - DMA */ + struct { + uint32_t mr; /* 0x00 - DMA 0 Mode Register */ + uint32_t sr; /* 0x04 - DMA 0 Status Register + */ + uint8_t res2[4]; + uint32_t clndar; /* 0x2110c - DMA 0 Current Link Descriptor Address Register */ + uint32_t satr; /* 0x10 - DMA 0 Source Attributes Register */ + uint32_t sar; /* 0x14 - DMA 0 Source Address Register */ + uint32_t datr; /* 0x18 - DMA 0 Destination Attributes Register */ + uint32_t dar; /* 0x1c - DMA 0 Destination Address Register */ + uint32_t bcr; /* 0x20 - DMA 0 Byte Count Register */ + uint8_t res3[4]; + uint32_t nlndar; /* 0x28 - DMA 0 Next Link Descriptor Address Register */ + uint8_t res4[8]; + uint32_t clabdar; /* 0x34 - DMA 0 Current List - Alternate Base Descriptor Address Register */ + uint8_t res5[4]; + uint32_t nlsdar; /* 0x3c - DMA 0 Next List Descriptor Address Register */ + uint32_t ssr; /* 0x40 - DMA 0 Source Stride Register */ + uint32_t dsr; /* 0x44 - DMA 0 Destination Stride Register */ + uint8_t res6[56]; + } dma[4]; + uint32_t dgsr; /* 0x21300 - DMA General Status Register */ +}; + +struct mpc85xx_dma_chain { + dma_addr_t link_pa; + struct mpc85xx_dma_desc *link; + int max; + int len; +}; + +struct mpc85xx_dma_channel { + mpc85xx_dma_f func; + void *data; + struct mpc85xx_dma_chain *chain; +} mpc85xx_dma_info[4]; + +struct semaphore mpc85xx_dma_lock; +static struct ccsr_dma *dma_addr; + +#define DMA_R(channel,reg) (dma_addr->dma[channel].reg) +#define DMA_W(channel,reg,val) do { DPRINTK(KERN_INFO "DMA %d.%s = 0x%.*x\n",channel, #reg, sizeof(DMA_R(channel,reg)) * 2, val); DMA_R(channel,reg)=val; } while (0) +#define DMA_RMW(channel,reg,op,val) do { DMA_W(channel,reg,DMA_R(channel,reg) op val); } while (0) + +static irqreturn_t mpc85xx_dma_irq(int irq, void *data, struct pt_regs *regs) +{ + struct mpc85xx_dma_channel *info; + int channel, i; + int event = 0; + uint32_t status, handled = 0; + + /* The irq can be one of four channels */ + channel = irq - MPC85xx_IRQ_DMA0; + assert(channel >= 0 && channel < 4); + + status = DMA_R(channel, sr); + DPRINTK("DMA%d: IRQ, status=0x%.2x (%d.sr)\n", + channel, status, channel); + + i = 0; + while (status & MPC85xx_SR_CB) { + status = DMA_R(channel, sr); + i++; + } + if (i > 0) + DPRINTK("DMA%d: Polled status %d times while busy\n", + channel, i); + + if (status & MPC85xx_SR_CH) { + DPRINTK("DMA%d: Channel halted\n", channel); + handled |= MPC85xx_SR_CH; + event = MPC85xx_DMA_EVENT_HALTED; + + } else if (status & (MPC85xx_SR_TE | MPC85xx_SR_PE)) { + if (status & MPC85xx_SR_TE) + DPRINTK("DMA%d: Transfer error\n", channel); + if (status & MPC85xx_SR_PE) + DPRINTK("DMA%d: Programming Error\n", channel); + handled |= (status & (MPC85xx_SR_TE | MPC85xx_SR_PE)); + event = MPC85xx_DMA_EVENT_ERROR; + } else if (status & + (MPC85xx_SR_EOSI | MPC85xx_SR_EOLSI | MPC85xx_SR_EOLNI)) { + handled |= + status & (MPC85xx_SR_EOSI | MPC85xx_SR_EOLSI | + MPC85xx_SR_EOLNI); + event = MPC85xx_DMA_EVENT_DONE; + } + + DPRINTK("DMA%d: status 0x%.2x, handled 0x%.2x, event %d\n", + channel, status, handled, event); + + if (status & MPC85xx_SR_CB) { + printk("DMA%d: Crazy busy: status=0x%.2x\n", channel, status); + for (;;) ; + } + + if ((status & ~handled) != 0 || event == MPC85xx_DMA_EVENT_ERROR) { + DPRINTK("status = %.8x handled=%.8x\n", status, handled); + DPRINTK("DGSR =%.8x\n", dma_addr->dgsr); + DPRINTK(" mr=%.8x\n", DMA_R(channel, mr)); + DPRINTK(" sr=%.8x\n", DMA_R(channel, sr)); + DPRINTK("clndar=%.8x\n", DMA_R(channel, clndar)); + DPRINTK(" satr=%.8x\n", DMA_R(channel, satr)); + DPRINTK(" sar=%.8x\n", DMA_R(channel, sar)); + DPRINTK(" datr=%.8x\n", DMA_R(channel, datr)); + DPRINTK(" dar=%.8x\n", DMA_R(channel, dar)); + DPRINTK(" bcr=%.8x\n", DMA_R(channel, bcr)); + DPRINTK("nlndar=%.8x\n", DMA_R(channel, nlndar)); + DPRINTK("clbdar=%.8x\n", DMA_R(channel, clabdar)); + DPRINTK("nlsdar=%.8x\n", DMA_R(channel, nlsdar)); + DPRINTK(" ssr=%.8x\n", DMA_R(channel, ssr)); + DPRINTK(" dsr=%.8x\n", DMA_R(channel, dsr)); + } + + info = &mpc85xx_dma_info[channel]; + if (info->func != NULL) { + DPRINTK("DMA%d: Calling event function 0x%p(0x%p)\n", channel, + info->func, info->data); + info->func(channel, event, info->data); + } + + DMA_R(channel, sr) |= handled; + DMA_R(channel, sr) &= ~handled; + DMA_W(channel, mr, 0); + dma_addr->dgsr |= dma_addr->dgsr; + + DPRINTK("DMA%d: status now 0x%.2x\n", channel, DMA_R(channel, sr)); + + return IRQ_HANDLED; +} + +/* + * Remove any flags that we don't want the user to be able to set + */ +static inline int clean_flags(int flags) +{ + flags &= ~(MPC85xx_MR_SWSM | + MPC85xx_MR_SRW | + MPC85xx_MR_XFE | + MPC85xx_MR_EOSIE | + MPC85xx_MR_EOLNIE | + MPC85xx_MR_EOLSIE | + MPC85xx_MR_EIE | + MPC85xx_MR_CA | + MPC85xx_MR_CTM | + MPC85xx_MR_CDSM | + MPC85xx_MR_CC | + MPC85xx_MR_CS); + return flags; +} + +EXPORT_SYMBOL(mpc85xx_dma_xfer); +int mpc85xx_dma_xfer(int channel, int flags, phys_addr_t dst, phys_addr_t src, + size_t bytes) +{ + flags = clean_flags(flags); + + /* Direct mode */ + flags |= MPC85xx_MR_CTM | MPC85xx_MR_EIE | MPC85xx_MR_EOSIE; + + if (bytes & ~MPC85xx_BCR_MASK) + return -EINVAL; + + if (mpc85xx_dma_busy(channel)) + return -EBUSY; + + /* Assert that we aren't busy */ + assert((DMA_R(channel, sr) & MPC85xx_SR_CB) == 0); + + if (src > 0xf0000000UL) { + /* Read, don't snoop local proc */ + DMA_W(channel, satr, MPC85xx_SATR_SREADTYPE_L_NO_SNOOP); + } else { + /* Read, snoop local proc */ + DMA_W(channel, satr, MPC85xx_SATR_SREADTYPE_L_SNOOP); + } + + if (dst > 0xf0000000UL) { + /* Write, don't snoop local proc */ + DMA_W(channel, datr, MPC85xx_DATR_DWRITETYPE_L_NO_SNOOP); + } else { + /* Write, don't snoop local proc */ + DMA_W(channel, datr, MPC85xx_DATR_DWRITETYPE_L_SNOOP); + } + DMA_W(channel, bcr, bytes); + DMA_W(channel, sar, src); + DMA_W(channel, dar, dst); + + /* If using external start, no need to set CS outselves */ + if ((flags & MPC85xx_MR_EMS_EN) == 0) + flags |= MPC85xx_MR_CS; + + DMA_W(channel, mr, flags); + wmb(); + + return 0; +} + +EXPORT_SYMBOL(mpc85xx_dma_chain_xfer); +int mpc85xx_dma_chain_xfer(int channel, int flags, + struct mpc85xx_dma_chain *chain) +{ + /* Chains must be 32-byte aligned */ + if (chain == NULL) + return -EINVAL; + + if (chain->len == 0) + return -EINVAL; + + if (mpc85xx_dma_busy(channel)) + return -EBUSY; + + /* Chain mode */ + flags = clean_flags(flags); + + flags |= MPC85xx_MR_EIE | MPC85xx_MR_EOLNIE; + + DPRINTK(KERN_INFO + "DMA chain: channel %d at 0x%p, flags=0x%x, chain=0x%p\n", + channel, &dma_addr->dma[channel], flags, chain); + { + int i; + for (i = 0; i < chain->len; i++) { + DPRINTK(KERN_INFO "chain[%d] vaddr 0x%p paddr 0x%.8x\n", + i, + &chain->link[i], + chain->link_pa + i * sizeof(chain->link[0])); + DPRINTK(KERN_INFO " satr 0x%.8x\n", + chain->link[i].satr); + DPRINTK(KERN_INFO " sar 0x%.8x\n", + chain->link[i].sar); + DPRINTK(KERN_INFO " datr 0x%.8x\n", + chain->link[i].datr); + DPRINTK(KERN_INFO " dar 0x%.8x\n", + chain->link[i].dar); + DPRINTK(KERN_INFO " nlndar 0x%.8x\n", + chain->link[i].nlndar); + DPRINTK(KERN_INFO " bcr 0x%.8x\n", + chain->link[i].bcr); + } + } + + __dma_sync(&chain->link[0], sizeof(chain->link[0]) * chain->len, + PCI_DMA_TODEVICE); + + /* Assert that we aren't busy */ + assert((DMA_R(channel, sr) & MPC85xx_SR_CB) == 0); + + /* Point to the first link in the chain */ + DMA_W(channel, clndar, chain->link_pa); + + /* If using external start, no need to set CS outselves */ + if ((flags & MPC85xx_MR_EMS_EN) == 0) { + flags |= MPC85xx_MR_CS; + DMA_W(channel, mr, flags & ~MPC85xx_MR_CS); + } + + DMA_W(channel, mr, flags); + + return (0); +} + +EXPORT_SYMBOL(mpc85xx_dma_abort); +void mpc85xx_dma_abort(int channel) +{ + DMA_RMW(channel, mr, |, MPC85xx_MR_CA); +} + +EXPORT_SYMBOL(mpc85xx_dma_halt); +void mpc85xx_dma_halt(int channel) +{ + DMA_W(channel, nlndar, 0); +} + +EXPORT_SYMBOL(mpc85xx_dma_busy); +int mpc85xx_dma_busy(int channel) +{ + return (dma_addr->dma[channel].sr & MPC85xx_SR_CB) ? 1 : 0; +} + + +EXPORT_SYMBOL(mpc85xx_dma_chain_alloc); +struct mpc85xx_dma_chain *mpc85xx_dma_chain_alloc(int links) +{ + struct mpc85xx_dma_chain *chain; + + if (links < 0) + return NULL; + + chain = kmalloc(sizeof(*chain), GFP_KERNEL); + if (chain == NULL) + return NULL; + + chain->link = (struct mpc85xx_dma_desc *) + dma_alloc_coherent(NULL, + sizeof (struct mpc85xx_dma_desc) * links, + (dma_addr_t *) &chain-> link_pa, + GFP_DMA); + if (chain->link == NULL) { + printk(KERN_ERR "mpc85xx_dma: Unable to obtain dma region\n"); + return NULL; + } + + chain->max = links; + chain->len = 0; + + return chain; +} + +EXPORT_SYMBOL(mpc85xx_dma_chain_clear); +void mpc85xx_dma_chain_clear(struct mpc85xx_dma_chain *chain) +{ + if (chain == NULL) + return; + + chain->len = 0; +} + +EXPORT_SYMBOL(mpc85xx_dma_chain_free); +void mpc85xx_dma_chain_free(struct mpc85xx_dma_chain *chain) +{ + if (chain == NULL) + return; + + dma_free_coherent(NULL, + sizeof(struct mpc85xx_dma_desc) * chain->max, + (void *)chain->link, (dma_addr_t) chain->link_pa); + kfree(chain); +} + +EXPORT_SYMBOL(mpc85xx_dma_chain_append); +int mpc85xx_dma_chain_append(struct mpc85xx_dma_chain *chain, + phys_addr_t dst_addr, + phys_addr_t src_addr, size_t len_in_bytes) +{ + struct mpc85xx_dma_desc *desc; + + if (chain == NULL) + return -EINVAL; + + if (len_in_bytes & ~MPC85xx_DMA_BYTE_MASK) + return -EINVAL; + + if (chain->len >= chain->max) { + printk(KERN_WARNING + "mpc85xx_dma_chain_append: Can't append to full chain %p\n", + chain); + return -ENOMEM; + } + + desc = &chain->link[chain->len]; + memset(desc, 0, sizeof(*desc)); + desc->bcr = len_in_bytes; + if (src_addr > 0xf0000000UL) { + desc->satr = MPC85xx_SATR_SREADTYPE_L_NO_SNOOP; /* Read, snoop local proc */ + } else { + desc->satr = MPC85xx_SATR_SREADTYPE_L_SNOOP; /* Read, snoop local proc */ + } + if (dst_addr > 0xf0000000UL) { + desc->datr = MPC85xx_DATR_DWRITETYPE_L_NO_SNOOP; /* Write, snoop local proc */ + } else { + desc->datr = MPC85xx_DATR_DWRITETYPE_L_SNOOP; /* Write, snoop local proc */ + } + desc->sar = src_addr; + desc->dar = dst_addr; + desc->nlndar = MPC85xx_NLNDAR_EOLND | MPC85xx_NLNDAR_NDEOSIE; + if (chain->len > 0) { + chain->link[chain->len - 1].nlndar = + chain->link_pa + + ((chain->len) * (sizeof(struct mpc85xx_dma_desc))); + } + + chain->len++; + + return 0; +} + +EXPORT_SYMBOL(mpc85xx_dma_chain_ring); +int mpc85xx_dma_chain_ring(struct mpc85xx_dma_chain *chain) +{ + if (chain == NULL) + return -EINVAL; + + if (chain->len == 0) + return -EINVAL; + + chain->link[chain->len - 1].nlndar = chain->link_pa; + + return 0; +} + +EXPORT_SYMBOL(mpc85xx_dma_request); +int mpc85xx_dma_request(int channel, const char *name, mpc85xx_dma_f func, + void *data) +{ + if (channel < 0 || channel >= 4) + return -EINVAL; + + if (data == NULL) + return -EINVAL; + + down(&mpc85xx_dma_lock); + + if (mpc85xx_dma_info[channel].data != NULL) { + up(&mpc85xx_dma_lock); + return -EBUSY; + } + + /* We use the 'wmb()' so we don't have to use + * spin_lock_irqsave/restore here, as the IRQ + * only checks .func + */ + mpc85xx_dma_info[channel].chain = NULL; + mpc85xx_dma_info[channel].data = data; + wmb(); + mpc85xx_dma_info[channel].func = func; + wmb(); + + up(&mpc85xx_dma_lock); + + return 0; +} + +EXPORT_SYMBOL(mpc85xx_dma_free); +void mpc85xx_dma_free(int channel, void *data) +{ + down(&mpc85xx_dma_lock); + + if (mpc85xx_dma_info[channel].data != data) { + printk(KERN_WARNING + "mpc85xx_dma_free: Channel %d not in use, or already freed\n", + channel); + goto done; + } + + /* We use the 'wmb()' so we don't have to use + * spin_lock_irqsave/restore here, as the IRQ + * only checks .func + */ + mpc85xx_dma_info[channel].func = NULL; + wmb(); + mpc85xx_dma_info[channel].data = NULL; + + kfree(mpc85xx_dma_info[channel].chain); + mpc85xx_dma_info[channel].chain = NULL; + +done: + up(&mpc85xx_dma_lock); +} + +char *dma_names[4] = { + "DMA Channel 0", + "DMA Channel 1", + "DMA Channel 2", + "DMA Channel 3" +}; + +static int __init mpc85xx_dma_init(void) +{ + int i, err; + bd_t *binfo = (bd_t *) __res; + + dma_addr = ioremap(binfo->bi_immr_base + 0x21000 + 256, 0x204); + + if (!dma_addr) { + printk("mpc85xx_dma: Unable to ioremap\n"); + return -ENODEV; + } + init_MUTEX(&mpc85xx_dma_lock); + + for (i = 0; i < 4; i++) { + DMA_W(i, mr, 0); + } + + for (i = 0; i < 4; i++) { + err = + request_irq(MPC85xx_IRQ_DMA0 + i, mpc85xx_dma_irq, 0, + dma_names[i], dma_names[i]); + if (err < 0) { + for (i--; i >= 0; i--) + free_irq(MPC85xx_IRQ_DMA0 + i, dma_names[i]); + return err; + } + } + + printk(KERN_INFO "MPC85xx DMA Engine (4 channels available)\n"); + + return 0; +} + +static void __exit mpc85xx_dma_exit(void) +{ + int i; + + for (i = 0; i < 4; i++) + free_irq(MPC85xx_IRQ_DMA0 + i, dma_names[i]); +} + +module_init(mpc85xx_dma_init); +module_exit(mpc85xx_dma_exit); diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/syslib/mv64x60.c linux-2.6.14.mod/arch/ppc/syslib/mv64x60.c --- linux-2.6.14.orig/arch/ppc/syslib/mv64x60.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/syslib/mv64x60.c 2006-02-21 18:18:21.000000000 -0700 @@ -312,7 +312,7 @@ }; #endif -#ifdef CONFIG_MV643XX_ETH +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) static struct resource mv64x60_eth_shared_resources[] = { [0] = { .name = "ethernet shared base", @@ -455,7 +455,7 @@ &mpsc0_device, &mpsc1_device, #endif -#ifdef CONFIG_MV643XX_ETH +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) &mv64x60_eth_shared_device, #endif #ifdef CONFIG_MV643XX_ETH_0 @@ -508,7 +508,7 @@ return -1; } - bh->ci->disable_all_windows(bh, si); +// bh->ci->disable_all_windows(bh, si); mv64x60_get_mem_windows(bh, mem_windows); mv64x60_config_cpu2mem_windows(bh, si, mem_windows); @@ -527,7 +527,6 @@ bh->io_base_a = (u32)ioremap(si->pci_0.pci_io.cpu_base, si->pci_0.pci_io.size); isa_io_base = bh->io_base_a; - mv64x60_alloc_hose(bh, MV64x60_PCI0_CONFIG_ADDR, MV64x60_PCI0_CONFIG_DATA, &bh->hose_a); mv64x60_config_resources(bh->hose_a, &si->pci_0, bh->io_base_a); @@ -552,7 +551,6 @@ bh->ci->set_pci2regs_window(bh, bh->hose_b, 1, si->phys_reg_base); } - bh->ci->chip_specific_init(bh, si); mv64x60_pd_fixup(bh, mv64x60_pd_devs, ARRAY_SIZE(mv64x60_pd_devs)); diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/syslib/ppc85xx_setup.c linux-2.6.14.mod/arch/ppc/syslib/ppc85xx_setup.c --- linux-2.6.14.orig/arch/ppc/syslib/ppc85xx_setup.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/syslib/ppc85xx_setup.c 2006-02-02 17:26:53.000000000 -0700 @@ -97,9 +97,11 @@ gen550_init(0, &serial_req); #endif +#ifndef CONFIG_MVME3100 + pdata[1].uartclk = binfo->bi_busfreq; pdata[1].mapbase += binfo->bi_immr_base; - pdata[1].membase = ioremap(pdata[1].mapbase, MPC85xx_UART0_SIZE); + pdata[1].membase = ioremap(pdata[1].mapbase, MPC85xx_UART1_SIZE); #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) /* Assume gen550_init() doesn't modify serial_req */ @@ -108,6 +110,9 @@ gen550_init(1, &serial_req); #endif + +#endif + } #endif diff -u --new-file --recursive linux-2.6.14.orig/arch/ppc/syslib/ppc85xx_setup.h linux-2.6.14.mod/arch/ppc/syslib/ppc85xx_setup.h --- linux-2.6.14.orig/arch/ppc/syslib/ppc85xx_setup.h 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/arch/ppc/syslib/ppc85xx_setup.h 2006-02-02 17:27:17.000000000 -0700 @@ -43,15 +43,23 @@ #define PCIX_STATUS 0x64 /* Serial Config */ +#define MPC85XX_0_SERIAL (CCSRBAR + 0x4500) +#define MPC85XX_1_SERIAL (CCSRBAR + 0x4600) + #ifdef CONFIG_SERIAL_MANY_PORTS #define RS_TABLE_SIZE 64 #else +#ifndef CONFIG_MVME3100 #define RS_TABLE_SIZE 2 +#else +#define RS_TABLE_SIZE 5 #endif - +#endif + #ifndef BASE_BAUD #define BASE_BAUD 115200 #endif + /* Offset of CPM register space */ #define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) diff -u --new-file --recursive linux-2.6.14.orig/CREDITS linux-2.6.14.mod/CREDITS --- linux-2.6.14.orig/CREDITS 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/CREDITS 2005-11-16 10:40:21.000000000 -0700 @@ -2692,6 +2692,20 @@ E: fpotter@cirpack.com D: Some PCI kernel support +N: Ajit Prem +E: ajit.prem@motorola.com +D: Added support for the MCP805 +D: Added support for the MCP820 +D: Added support for the MCP905 +D: Added support for the MVME5500 +D: Added support for the MVME6100 +D: Added support for the MVME3100 +D: Added support for the PrPMC880 +D: Miscellaneous mods to support the boards above +S: 2900 South Diablo Way, DW278 +S: Tempe, Arizona 85282 +S: USA + N: Rui Prior E: rprior@inescn.pt D: ATM device driver for NICStAR based cards diff -u --new-file --recursive linux-2.6.14.orig/drivers/char/Kconfig linux-2.6.14.mod/drivers/char/Kconfig --- linux-2.6.14.orig/drivers/char/Kconfig 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/char/Kconfig 2006-05-05 11:22:02.000000000 -0700 @@ -659,9 +659,22 @@ If unsure, say N. +config NVRAM_M48TXXX + tristate "/dev/nvram_m48txxx support" + depends on (MVME5500 || MVME6100 || MCP905) + ---help--- + If you say Y here and create a character special file /dev/nvram + with major number 10 and minor number 144 using mknod ("man mknod"), + you get read and write access to the 32K bytes of non-volatile + memory in the M48TXXX which is used on some embedded boards. + If you have one of these boards, say Y. + + To compile this driver as a module, choose M here: the + module will be called nvram. + config NVRAM tristate "/dev/nvram support" - depends on ATARI || X86 || X86_64 || ARM || GENERIC_NVRAM + depends on (ATARI || X86 || X86_64 || ARM || GENERIC_NVRAM) && !NVRAM_M48TXXX ---help--- If you say Y here and create a character special file /dev/nvram with major number 10 and minor number 144 using mknod ("man mknod"), diff -u --new-file --recursive linux-2.6.14.orig/drivers/char/Makefile linux-2.6.14.mod/drivers/char/Makefile --- linux-2.6.14.orig/drivers/char/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/char/Makefile 2006-02-21 13:59:08.000000000 -0700 @@ -70,6 +70,7 @@ else obj-$(CONFIG_NVRAM) += nvram.o endif +obj-$(CONFIG_NVRAM_M48TXXX) += nvram_m48txxx.o obj-$(CONFIG_TOSHIBA) += toshiba.o obj-$(CONFIG_I8K) += i8k.o obj-$(CONFIG_DS1620) += ds1620.o diff -u --new-file --recursive linux-2.6.14.orig/drivers/char/nvram_m48txxx.c linux-2.6.14.mod/drivers/char/nvram_m48txxx.c --- linux-2.6.14.orig/drivers/char/nvram_m48txxx.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/char/nvram_m48txxx.c 2006-03-27 16:32:46.000000000 -0700 @@ -0,0 +1,330 @@ +/* + * nvram.c: NVRAM driver for the M48T37V used on Motorola's + * MCP805/MCP820/MCP905/MVME5500/MVME6100 boards + * + * Ajit Prem, (Ajit.Prem@motorola.com). + * + * Copyright 2003-2006 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_MCP805 +#include +#endif +#ifdef CONFIG_MCP820 +#include +#endif +#ifdef CONFIG_MCP905 +#include +#endif +#ifdef CONFIG_MVME5500 +#include +#endif +#ifdef CONFIG_MVME6100 +#include +#endif + + +static ulong nvram_base; +static uint nvram_size = 0x8000 - 16; +static uint nvram_low_protect = 0x1400; +static uint nvram_high_protect = 0x7600; + + +module_param(nvram_base, ulong, 0); +module_param(nvram_size, uint, 0); +module_param(nvram_low_protect, uint, 0); +module_param(nvram_high_protect, uint, 0); + +#define ALL_MSG "nvram: " + +#undef NVRAM_DEBUG + +#ifdef NVRAM_DEBUG +int nvram_debug = NVRAM_DEBUG; +MODULE_PARM(nvram_debug, "i"); +#define DEBUG(n, fmt, args...) if (nvram_debug>(n)) printk(KERN_INFO ALL_MSG fmt, ## args) +static const char *version = "nvram.c 1.0.2"; +#else +#define DEBUG(n, fmt, args...) +#endif + +struct nvram_dev_t { + u_int size; + u_int base; + u8 *virt; +}; + + +static struct nvram_dev_t nvram; +static unsigned long open_for_write; + +static int +nvram_open(struct inode *inode, struct file *file) +{ + DEBUG(1, "open()\n"); + + if ((file->f_flags & O_ACCMODE) != O_RDONLY) { + if (test_and_set_bit(0, &open_for_write)) + return -EBUSY; + } + + return 0; +} /* nvram_open */ + + +static int +nvram_release(struct inode *inode, struct file *file) +{ + DEBUG(1, "release()\n"); + + if ((file->f_flags & O_ACCMODE) != O_RDONLY) + clear_bit(0, &open_for_write); + + return 0; +} /* nvram_release */ + +static ssize_t +nvram_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + unsigned long p; + unsigned long i, odd; + u_int tmpw; + u_short tmps; + u_char tmpc; + + DEBUG(1, "read(pos 0x%lx, count 0x%lx)\n", (u_long) p, (u_long) count); + + if (!access_ok(VERIFY_WRITE, buf, count)) + return -EFAULT; + + p = *ppos; + if (p < 0 || p > nvram.size || count < 0) + return -EINVAL; + + if (count > nvram.size - p) + count = nvram.size - p; + + odd = count & 3; + count &= ~3; + + for (i = 0; i < count; i += 4, p += 4, buf +=4) { + tmpw = readl(nvram.virt + p); + if (__put_user(swab32(tmpw), (u_int *)buf)) + return -EFAULT; + } + + if (odd & 2) { + tmps = readw(nvram.virt + p); + if (__put_user(swab16(tmps), (u_short *) buf)) + return -EFAULT; + p += 2; + buf += 2; + } + + if (odd & 1) { + tmpc = readb(nvram.virt + p); + if (__put_user(tmpc, (u_char *) buf)) + return -EFAULT; + } + + + *ppos += count + odd; + return count + odd; +} /* nvram_read */ + + +static ssize_t +nvram_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +{ + unsigned long p; + unsigned long i, odd; + u_int tmpw; + u_short tmps; + u_char tmpc; + + DEBUG(1, "write(0x%lx, 0x%lx)\n", (u_long) p, (u_long) count); + + if (!access_ok(VERIFY_READ, buf, count)) + return -EFAULT; + + p = *ppos; + if (p < 0 || p >= nvram.size || count < 0) + return -EINVAL; + + if ((p < nvram_low_protect) || (p >= nvram_high_protect)) { + printk(KERN_INFO + "nvram: Attempt to write to offset 0x%lu which is in a write protected area\n", + p); + return -EPERM; + } + + if (p + count > nvram.size) { + count = nvram.size - p; + } + + if (p + count > nvram_high_protect) { + printk(KERN_INFO + "nvram: Attempt to write beyond nvram_high_protect. Offset 0x%lu, Count 0x%x\n", + p, count); + count = nvram_high_protect - p; + } + + odd = count & 3; + count &= ~3; + + for (i = 0; i < count; i += 4, p += 4, buf +=4) { + if (__get_user(tmpw, (u_int *)buf)) + return -EFAULT; + writel(swab32(tmpw), nvram.virt + p); + } + + if (odd & 2) { + if (__get_user(tmps, (u_short *) buf)) + return -EFAULT; + writew(swab16(tmps), nvram.virt + p); + p += 2; + buf += 2; + } + + if (odd & 1) { + if (__get_user(tmpc, (u_char *) buf)) + return -EFAULT; + writeb(tmpc, nvram.virt + p); + } + + *ppos += count + odd; + + return count + odd; + +} /* nvram_write */ + +static long long +nvram_llseek(struct file *file, long long offset, int origin) +{ + DEBUG(1, "llseek(offset 0x%lx origin 0x%x)\n", (u_long) offset, origin); + + switch (origin) { + case 0: + break; + case 1: + offset += file->f_pos; + break; + case 2: + offset += nvram.size; + break; + default: + return -EINVAL; + } + if (offset < 0 || offset > nvram.size) + return -EINVAL; + + file->f_pos = offset; + return file->f_pos; +} /* nvram_llseek */ + + +static struct file_operations nvram_fops = { + .owner = THIS_MODULE, + .open = nvram_open, + .release = nvram_release, + .read = nvram_read, + .write = nvram_write, + .llseek = nvram_llseek, +}; + +static struct miscdevice nvram_miscdev = { + .minor = NVRAM_MINOR, + .name = "nvram", + .fops = &nvram_fops, +}; + + + +static int __init +nvram_m48txxx_init(void) +{ + int ret; + + DEBUG(0, "%s\n", version); + +#if defined(CONFIG_MCP805) + nvram.base = MCP805_NVRAM_BASE_ADDRESS; + nvram.size = MCP805_NVRAM_SIZE - 16; /* exclude RTC and watchdog */ +#elif defined(CONFIG_MCP820) + nvram.base = MCP820_NVRAM_BASE_ADDRESS; + nvram.size = MCP820_NVRAM_SIZE - 16; /* exclude RTC and watchdog */ +#elif defined(CONFIG_MCP905) + nvram_base = MCP905_NVRAM_BASE_ADDRESS; + nvram.size = MCP905_NVRAM_SIZE - 16; /* exclude RTC and watchdog */ +#elif defined(CONFIG_MVME5500) + nvram_base = MVME5500_NVRAM_BASE_ADDRESS; + nvram.size = MVME5500_NVRAM_SIZE - 16; /* exclude RTC and watchdog */ +#elif defined(CONFIG_MVME6100) + nvram_base = MVME6100_NVRAM_BASE_ADDRESS; + nvram.size = MVME6100_NVRAM_SIZE - 16; /* exclude RTC and watchdog */ +#else + return -ENODEV; +#endif + if (nvram.base == 0) { + if (nvram_base == 0) { + return -ENODEV; + } else { + nvram.base = nvram_base; + nvram.size = nvram_size; + } + } + + if ((nvram_low_protect < 0) || (nvram_low_protect > nvram_high_protect) || + (nvram_high_protect > nvram_size)) { + printk(KERN_INFO "nvram: Bad module parameters\n"); + return -ENODEV; + } + DEBUG(0, "base: 0x%x size: 0x%x low_protect_offset: 0x%x high_protect_offset 0x%x\n", + nvram.base, nvram.size, nvram_low_protect, nvram_high_protect); + + nvram.virt = ioremap(nvram.base, nvram.size); + + /* Set up character device for user mode clients */ + ret = misc_register(&nvram_miscdev); + if (ret) { + printk (KERN_ERR "Cannot register miscdev on minor=%d (err=%d)\n", NVRAM_MINOR, ret); + iounmap(nvram.virt); + return ret; + } + + return 0; +} + + +static void __exit +nvram_m48txxx_exit(void) +{ + DEBUG(0, "exiting\n"); + iounmap(nvram.virt); + misc_deregister(&nvram_miscdev); + return; +} + +module_init(nvram_m48txxx_init); +module_exit(nvram_m48txxx_exit); + +MODULE_AUTHOR("Ajit Prem "); +MODULE_DESCRIPTION("M48TXXX NVRAM Driver"); +MODULE_LICENSE("GPL"); diff -u --new-file --recursive linux-2.6.14.orig/drivers/hwmon/ds1621.c linux-2.6.14.mod/drivers/hwmon/ds1621.c --- linux-2.6.14.orig/drivers/hwmon/ds1621.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/hwmon/ds1621.c 2006-03-14 13:37:27.000000000 -0700 @@ -6,6 +6,9 @@ Ported to Linux 2.6 by Aurelien Jarno with the help of Jean Delvare + Added board specific interrupt support for the MVME3100, MVME5500, + MVME6100, and MCP905 boards (Ajit Prem #include #include +#include #include #include -#include "lm75.h" +#ifdef CONFIG_MVME3100 +#include +#endif +#ifdef CONFIG_MVME5500 +#include +#endif +#ifdef CONFIG_MVME6100 +#include +#endif +#ifdef CONFIG_MCP905 +#include +#endif +#include + /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, @@ -36,7 +53,7 @@ /* Insmod parameters */ I2C_CLIENT_INSMOD_1(ds1621); -static int polarity = -1; +static int polarity = 0; module_param(polarity, int, 0); MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low"); @@ -44,6 +61,8 @@ /* Config register used for detection */ /* 7 6 5 4 3 2 1 0 */ /* |Done|THF |TLF |NVB | X | X |POL |1SHOT| */ +#define DS1621_REG_CONFIG_MASK 0x0C +#define DS1621_REG_CONFIG_VAL 0x0C #define DS1621_REG_CONFIG_NVB 0x10 #define DS1621_REG_CONFIG_POLARITY 0x02 #define DS1621_REG_CONFIG_1SHOT 0x01 @@ -51,9 +70,15 @@ /* The DS1621 registers */ #define DS1621_REG_TEMP 0xAA /* word, RO */ +#define DS1621_REG_TEMP_OVER 0xA1 /* word, RW */ +#define DS1621_REG_TEMP_HYST 0xA2 /* word, RW */ +#if 0 #define DS1621_REG_TEMP_MIN 0xA1 /* word, RW */ #define DS1621_REG_TEMP_MAX 0xA2 /* word, RW */ +#endif #define DS1621_REG_CONF 0xAC /* byte, RW */ +#define DS1621_REG_TEMP_COUNTER 0xA8 /* byte, RO */ +#define DS1621_REG_TEMP_SLOPE 0xA9 /* byte, RO */ #define DS1621_COM_START 0xEE /* no data */ #define DS1621_COM_STOP 0x22 /* no data */ @@ -65,8 +90,15 @@ variants. Note that you should be a bit careful with which arguments these macros are called: arguments may be evaluated more than once. Fixing this is just not worth it. */ +#define TEMP_FROM_REG(val) ((((val & 0x7fff) >> 7) * 5) + \ + ((val & 0x8000)?-1280:0)) +#define TEMP_TO_REG(val) (SENSORS_LIMIT((val<0 ? (0x200+((val)/5))<<7 : \ + (((val) + 2) / 5) << 7),0,0xffff)) #define ALARMS_FROM_REG(val) ((val) & \ (DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW)) +#define ITEMP_FROM_REG(val) ((((val & 0x7fff) >> 8)) + \ + ((val & 0x8000)?-1280:0)) + /* Each client has this additional data */ struct ds1621_data { @@ -76,8 +108,13 @@ char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ - u16 temp, temp_min, temp_max; /* Register values, word */ + u16 temp, temp_over, temp_hyst; /* Register values, word */ u8 conf; /* Register encoding, combined */ + char enable; /* !=0 if we're expected to restart the conversion */ + u8 temp_int, temp_counter, temp_slope; /* Register values, byte */ +#if defined(CONFIG_MVME3100) || defined(CONFIG_MVME5500) || defined(CONFIG_MVME6100) || defined(CONFIG_MCP905) + struct work_struct ds1621_task; +#endif }; static int ds1621_attach_adapter(struct i2c_adapter *adapter); @@ -102,7 +139,8 @@ the usual practice. */ static int ds1621_read_value(struct i2c_client *client, u8 reg) { - if (reg == DS1621_REG_CONF) + if ((reg == DS1621_REG_CONF) || (reg == DS1621_REG_TEMP_COUNTER) + || (reg == DS1621_REG_TEMP_SLOPE)) return i2c_smbus_read_byte_data(client, reg); else return swab16(i2c_smbus_read_word_data(client, reg)); @@ -113,15 +151,101 @@ the usual practice. */ static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value) { - if (reg == DS1621_REG_CONF) - return i2c_smbus_write_byte_data(client, reg, value); - else - return i2c_smbus_write_word_data(client, reg, swab16(value)); + if ( (reg == DS1621_COM_START) || (reg == DS1621_COM_STOP) ) + return i2c_smbus_write_byte(client, reg); + else + if ((reg == DS1621_REG_CONF) || (reg == DS1621_REG_TEMP_COUNTER) + || (reg == DS1621_REG_TEMP_SLOPE)) + return i2c_smbus_write_byte_data(client, reg, value); + else + return i2c_smbus_write_word_data(client, reg, swab16(value)); +} + +#ifdef CONFIG_MVME3100 + +#define DS1621_INTERRUPT MPC85xx_IRQ_EXT9 +#define BOARD_TSTAT_MASK MVME3100_TSTAT_MASK +#define BOARD_TSTAT_REG MVME3100_SYSTEM_CONTROL_REG + +#endif + +#ifdef CONFIG_MVME5500 + +#define DS1621_INTERRUPT 67 +#define BOARD_TSTAT_MASK MVME5500_BOARD_TSTAT_MASK +#define BOARD_TSTAT_REG MVME5500_BOARD_STATUS_REG_2 + +#endif + +#ifdef CONFIG_MVME6100 + +#define DS1621_INTERRUPT 67 +#define BOARD_TSTAT_MASK MVME6100_BOARD_TSTAT_MASK +#define BOARD_TSTAT_REG MVME6100_BOARD_STATUS_REG_2 + +#endif + +#ifdef CONFIG_MCP905 + +#define DS1621_INTERRUPT 67 +#define BOARD_TSTAT_MASK MCP905_BOARD_TSTAT_MASK +#define BOARD_TSTAT_REG MCP905_BOARD_STATUS_REG_2 + +#endif + +#if defined(CONFIG_MVME3100) || defined(CONFIG_MVME5500) || defined(CONFIG_MVME6100) || defined(CONFIG_MCP905) + +static u8* control_reg_mapped_addr; +static int control_reg_mapped; + +static void ds1621_task(void *dev_id) +{ + s32 conf; + struct i2c_client *client = (struct i2c_client *)dev_id; + struct ds1621_data *data; + + data = ds1621_update_client(&client->dev); + + printk(KERN_ERR "ds1621: the current temperature is %d C\n", TEMP_FROM_REG(data->temp)/10); + printk(KERN_ERR "ds1621: the high temperature trip register (TH) is set to %d C\n", TEMP_FROM_REG(data->temp_over)/10); + printk(KERN_ERR "ds1621: the low temperature trigger register (TL) is set to %d C\n", TEMP_FROM_REG(data->temp_hyst)/10); + + if ((conf = i2c_smbus_read_byte_data(client,DS1621_REG_CONF)) < 0) { + dev_warn(&client->dev, "Cannot read DS1621_REG_CONF\n"); + return; + } + printk(KERN_ERR "The ds1621 config register is: 0x%x\n", conf); + return; +} + + +static irqreturn_t ds1621_int_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + u16 value; + struct i2c_client *client = (struct i2c_client *)dev_id; + struct ds1621_data *data = i2c_get_clientdata(client); + + printk(KERN_ERR "ds1621: Interrupt!\n"); + printk(KERN_ERR "Masking off ds1621 interrupt.\n"); + + value = readb(control_reg_mapped_addr); + value |= BOARD_TSTAT_MASK; + writeb(value, control_reg_mapped_addr); + + schedule_work(&data->ds1621_task); + + return IRQ_HANDLED; } + +#endif static void ds1621_init_client(struct i2c_client *client) { int reg = ds1621_read_value(client, DS1621_REG_CONF); + struct ds1621_data *data = i2c_get_clientdata(client); + int result; + int value; + /* switch to continuous conversion mode */ reg &= ~ DS1621_REG_CONFIG_1SHOT; @@ -135,18 +259,56 @@ /* start conversion */ i2c_smbus_write_byte(client, DS1621_COM_START); +#if defined(CONFIG_MVME3100) || defined(CONFIG_MVME5500) || defined(CONFIG_MVME6100) || defined(CONFIG_MCP905) + INIT_WORK(&data->ds1621_task, ds1621_task, (void *)client); + + result = request_irq(DS1621_INTERRUPT, ds1621_int_handler, + 0, "ds1621", client); + if (result) { + printk(KERN_ERR "ds1621: Cannot get irq %d\n", DS1621_INTERRUPT); + return; + } + + /* Unmask ds1621 temperature sensor thermostat output */ + control_reg_mapped_addr = ioremap(BOARD_TSTAT_REG, 1); + control_reg_mapped = 1; + value = readb(control_reg_mapped_addr); + value &= ~BOARD_TSTAT_MASK; + writeb(value, control_reg_mapped_addr); +#endif } #define show(value) \ static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct ds1621_data *data = ds1621_update_client(dev); \ - return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value)); \ + if (!(data->conf & DS1621_REG_CONFIG_DONE) || \ + (data->temp_counter > data->temp_slope) || \ + (data->temp_slope == 0)) { \ + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value));\ + } else \ + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)*10);\ +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct ds1621_data *data = ds1621_update_client(dev); + int result; + + if (!(data->conf & DS1621_REG_CONFIG_DONE) || + (data->temp_counter > data->temp_slope) || + (data->temp_slope == 0)) { + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp)); + } else { + result = data->temp_int * 100 - 25 + + ((data->temp_slope - data->temp_counter) * + 100 / data->temp_slope); + return sprintf(buf, "%d\n", result); + } } -show(temp); -show(temp_min); -show(temp_max); +show(temp_over); +show(temp_hyst); #define set_temp(suffix, value, reg) \ static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \ @@ -154,7 +316,7 @@ { \ struct i2c_client *client = to_i2c_client(dev); \ struct ds1621_data *data = ds1621_update_client(dev); \ - u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \ + u16 val = TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \ \ down(&data->update_lock); \ data->value = val; \ @@ -163,8 +325,8 @@ return count; \ } -set_temp(min, temp_min, DS1621_REG_TEMP_MIN); -set_temp(max, temp_max, DS1621_REG_TEMP_MAX); +set_temp(over, temp_over, DS1621_REG_TEMP_OVER); +set_temp(hyst, temp_hyst, DS1621_REG_TEMP_HYST); static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) { @@ -172,11 +334,119 @@ return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->conf)); } +static ssize_t show_continuous(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct ds1621_data *data = ds1621_update_client(dev); + + return sprintf(buf, "%d\n", !(data->conf & DS1621_REG_CONFIG_1SHOT)); +} + +static ssize_t set_continuous(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ds1621_data *data = ds1621_update_client(dev); + ulong value; + + value = simple_strtoul(buf, NULL, 10); + if (value == 1) + ds1621_write_value(client, DS1621_REG_CONF, + data->conf & ~DS1621_REG_CONFIG_1SHOT); + else + ds1621_write_value(client, DS1621_REG_CONF, + data->conf | DS1621_REG_CONFIG_1SHOT); + return count; +} + +static ssize_t show_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct ds1621_data *data = ds1621_update_client(dev); + + return sprintf(buf, "%d\n", !(data->conf & DS1621_REG_CONFIG_DONE)); +} + +static ssize_t set_enable(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) + +{ + struct i2c_client *client = to_i2c_client(dev); + struct ds1621_data *data = i2c_get_clientdata(client); + ulong value; + + value = simple_strtoul(buf, NULL, 10); + if (value == 1) { + ds1621_write_value(client, DS1621_COM_START, 0); + data->enable = 1; + } else { + ds1621_write_value(client, DS1621_COM_STOP, 0); + data->enable = 0; + } + return count; \ +} + +static ssize_t show_polarity(struct device *dev, struct device_attribute *attr, +char *buf) +{ + struct ds1621_data *data = ds1621_update_client(dev); + + return sprintf(buf, "%d\n", !(!(data->conf & DS1621_REG_CONFIG_POLARITY))); +} + +static ssize_t set_polarity(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ds1621_data *data = i2c_get_clientdata(client); + ulong value; + + value = simple_strtoul(buf, NULL, 10); + if (value == 1) + ds1621_write_value(client, DS1621_REG_CONF, + data->conf | DS1621_REG_CONFIG_POLARITY); + else + ds1621_write_value(client, DS1621_REG_CONF, + data->conf & ~DS1621_REG_CONFIG_POLARITY); + return count; \ +} + +#if defined(CONFIG_MVME3100) || defined(CONFIG_MVME5500) || defined(CONFIG_MVME6100) || defined(CONFIG_MCP905) + +static ssize_t show_irq_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + u8 cr; + + cr = readb(control_reg_mapped_addr); + return sprintf(buf, "%d\n", (!(cr & BOARD_TSTAT_MASK))); +} + +static ssize_t set_irq_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) + +{ + ulong value; + u8 cr; + + value = simple_strtoul(buf, NULL, 10); + cr = readb(control_reg_mapped_addr); + if (value == 1) { + cr &= ~BOARD_TSTAT_MASK; + } else { + cr |= BOARD_TSTAT_MASK; + } + writeb(cr, control_reg_mapped_addr); + return count; +} + +static DEVICE_ATTR(irq_enable, S_IWUSR | S_IRUGO, show_irq_enable, set_irq_enable); + +#endif + static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static DEVICE_ATTR(continuous, S_IWUSR | S_IRUGO, show_continuous, set_continuous); +static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, show_enable, set_enable); +static DEVICE_ATTR(polarity, S_IWUSR | S_IRUGO, show_polarity, set_polarity); static DEVICE_ATTR(temp1_input, S_IRUGO , show_temp, NULL); -static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO , show_temp_min, set_temp_min); -static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); - +static DEVICE_ATTR(temp1_over, S_IWUSR | S_IRUGO , show_temp_over, set_temp_over); +static DEVICE_ATTR(temp1_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); static int ds1621_attach_adapter(struct i2c_adapter *adapter) { @@ -226,10 +496,10 @@ temp = ds1621_read_value(new_client, DS1621_REG_TEMP); if (temp & 0x007f) goto exit_free; - temp = ds1621_read_value(new_client, DS1621_REG_TEMP_MIN); + temp = ds1621_read_value(new_client, DS1621_REG_TEMP_OVER); if (temp & 0x007f) goto exit_free; - temp = ds1621_read_value(new_client, DS1621_REG_TEMP_MAX); + temp = ds1621_read_value(new_client, DS1621_REG_TEMP_HYST); if (temp & 0x007f) goto exit_free; } @@ -259,8 +529,16 @@ device_create_file(&new_client->dev, &dev_attr_alarms); device_create_file(&new_client->dev, &dev_attr_temp1_input); - device_create_file(&new_client->dev, &dev_attr_temp1_min); - device_create_file(&new_client->dev, &dev_attr_temp1_max); + device_create_file(&new_client->dev, &dev_attr_temp1_over); + device_create_file(&new_client->dev, &dev_attr_temp1_hyst); + device_create_file(&new_client->dev, &dev_attr_continuous); + device_create_file(&new_client->dev, &dev_attr_enable); + device_create_file(&new_client->dev, &dev_attr_polarity); +#if defined(CONFIG_MVME3100) || defined(CONFIG_MVME5500) || defined(CONFIG_MVME6100) || defined(CONFIG_MCP905) + device_create_file(&new_client->dev, &dev_attr_irq_enable); +#endif + data = ds1621_update_client(&new_client->dev); + printk("ds1621: the current temperature is %d C\n", TEMP_FROM_REG(data->temp)/10); return 0; @@ -278,12 +556,26 @@ { struct ds1621_data *data = i2c_get_clientdata(client); int err; + u8 value; hwmon_device_unregister(data->class_dev); if ((err = i2c_detach_client(client))) return err; +#if defined(CONFIG_MVME3100) || defined(CONFIG_MVME5500) || defined(CONFIG_MVME6100) || defined(CONFIG_MCP905) + if (control_reg_mapped) { + /* Mask DS1621 temperature sensor thermostat output */ + value = readb(control_reg_mapped_addr); + value |= BOARD_TSTAT_MASK; + writeb(value, control_reg_mapped_addr); + iounmap(control_reg_mapped_addr); + control_reg_mapped = 0; + } + free_irq(DS1621_INTERRUPT, client); + flush_scheduled_work(); +#endif + kfree(data); return 0; @@ -307,16 +599,29 @@ data->temp = ds1621_read_value(client, DS1621_REG_TEMP); - data->temp_min = ds1621_read_value(client, - DS1621_REG_TEMP_MIN); - data->temp_max = ds1621_read_value(client, - DS1621_REG_TEMP_MAX); + data->temp_over = ds1621_read_value(client, + DS1621_REG_TEMP_OVER); + data->temp_hyst= ds1621_read_value(client, + DS1621_REG_TEMP_HYST); + + /* wait for the DONE bit before reading extended values */ + + if (data->conf & DS1621_REG_CONFIG_DONE) { + data->temp_counter = ds1621_read_value(client, + DS1621_REG_TEMP_COUNTER); + data->temp_slope = ds1621_read_value(client, + DS1621_REG_TEMP_SLOPE); + data->temp_int = ITEMP_FROM_REG(data->temp); + /* restart the conversion */ + if (data->enable) + ds1621_write_value(client, DS1621_COM_START, 0); } + /* reset alarms if necessary */ new_conf = data->conf; - if (data->temp < data->temp_min) + if (data->temp < data->temp_over) new_conf &= ~DS1621_ALARM_TEMP_LOW; - if (data->temp > data->temp_max) + if (data->temp > data->temp_hyst) new_conf &= ~DS1621_ALARM_TEMP_HIGH; if (data->conf != new_conf) ds1621_write_value(client, DS1621_REG_CONF, diff -u --new-file --recursive linux-2.6.14.orig/drivers/i2c/busses/i2c-gt64260.c linux-2.6.14.mod/drivers/i2c/busses/i2c-gt64260.c --- linux-2.6.14.orig/drivers/i2c/busses/i2c-gt64260.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/i2c/busses/i2c-gt64260.c 2006-02-16 13:13:09.000000000 -0700 @@ -0,0 +1,1118 @@ +/* + * I2C driver for GT64260, mostly for Vital Product access. + * + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mot_vpd.h" + +#define VERSION "1.0.1" + +static int __init gt64260_i2c_init(void); + +/* I2C Srom defintions */ +static int deviceType = 1; +static unsigned int deviceAddress = 0xA8; +static unsigned int baudRate = 0x2C; + +/* + * Discovery I2C controller registers + */ + +#define DISCOVERY_I2C_SLAVE_ADDR 0xC000 +#define DISCOVERY_I2C_DATA_REG 0xC004 +#define DISCOVERY_I2C_CONTROL_REG 0xC008 +#define DISCOVERY_I2C_STATUS_REG 0xC00C +#define DISCOVERY_I2C_EXTSLAVE_ADDR 0xC010 +#define DISCOVERY_I2C_RESET_REG 0xC01C + +/* + * Discovery I2C controller register structure template + */ + +typedef struct i2cDiscovery { + unsigned int slaveAddr; /* 0xC000 - slave address */ + unsigned int data; /* 0xC004 - data */ + unsigned int control; /* 0xC008 - control */ + unsigned int status; /* 0xC00C - status */ + unsigned int extSlaveAddr; /* 0xC010 - extended slave address */ + unsigned int reserved[2]; /* 0xC014 - 0xC018 */ + unsigned int reset; /* 0xC01C - reset */ +} i2cDiscovery_t; + +/* + * DISCOVERY_I2C_CONTROL_REG bits + */ + +#define DISCOVERY_I2C_CONTROL_REG_ACK (1<<2) +#define DISCOVERY_I2C_CONTROL_REG_INTFLG (1<<3) +#define DISCOVERY_I2C_CONTROL_REG_STOP (1<<4) +#define DISCOVERY_I2C_CONTROL_REG_START (1<<5) +#define DISCOVERY_I2C_CONTROL_REG_ENABLE (1<<6) +#define DISCOVERY_I2C_CONTROL_REG_INTENABLE (1<<7) + +/* + * DISCOVERY_I2C_STATUS_REG bits + */ +#define DISCOVERY_I2C_STATUS_BUSERR 0x00 +#define DISCOVERY_I2C_STATUS_STARTTX 0x08 +#define DISCOVERY_I2C_STATUS_REPEATSTARTX 0x10 +#define DISCOVERY_I2C_STATUS_ADDRWRITEACK 0x18 +#define DISCOVERY_I2C_STATUS_ADDRWRITENACK 0x20 +#define DISCOVERY_I2C_STATUS_MSTDATAWRITEACK 0x28 +#define DISCOVERY_I2C_STATUS_MSTDATAWRITENACK 0x30 +#define DISCOVERY_I2C_STATUS_MSTLOSTARB 0x38 +#define DISCOVERY_I2C_STATUS_ADDRREADACK 0x40 +#define DISCOVERY_I2C_STATUS_ADDRREADNACK 0x48 +#define DISCOVERY_I2C_STATUS_MSTDATARECVACK 0x50 +#define DISCOVERY_I2C_STATUS_MSTDATARECVNACK 0x58 +#define DISCOVERY_I2C_STATUS_SLVADDRRECACK 0x60 +#define DISCOVERY_I2C_STATUS_MSTLOSTARBADDR 0x68 +#define DISCOVERY_I2C_STATUS_GENCALLRECVACK 0x70 +#define DISCOVERY_I2C_STATUS_MSTLOSTARBADDRGC 0x78 +#define DISCOVERY_I2C_STATUS_SLVRECWDATAACK 0x80 +#define DISCOVERY_I2C_STATUS_SLVRECWDATANACK 0x88 +#define DISCOVERY_I2C_STATUS_SLVRECWDATAACKGC 0x90 +#define DISCOVERY_I2C_STATUS_SLVRECWDATANACKGC 0x98 +#define DISCOVERY_I2C_STATUS_SLVRECSTOP 0xA0 +#define DISCOVERY_I2C_STATUS_SLVRECADDRACK 0xA8 +#define DISCOVERY_I2C_STATUS_MSTLOSTARBADDRtx 0xB0 +#define DISCOVERY_I2C_STATUS_SLVTXRDATAACK 0xB8 +#define DISCOVERY_I2C_STATUS_SLVTXRDATANACK 0xC0 +#define DISCOVERY_I2C_STATUS_SLVTXLASTDATAACK 0xC8 +#define DISCOVERY_I2C_STATUS_SECADDRWTXACK 0xD0 +#define DISCOVERY_I2C_STATUS_SECADDRWTXNACK 0xD8 +#define DISCOVERY_I2C_STATUS_SECADDRRTXACK 0xE0 +#define DISCOVERY_I2C_STATUS_SECADDRRTXNACK 0xE8 +#define DISCOVERY_I2C_STATUS_NOSTATUS 0xF8 + +/* + * command identifiers + */ +#define I2C_READOP 0 /* read operation */ +#define I2C_WRITOP 1 /* write operation */ +#define I2C_FRMTOP 2 /* format operation */ +#define I2C_CHCKOP 3 /* check operation */ + +/* + * routine call macros + */ +#define I2C_CYCLE_ACKIN i2cCycleDiscoveryAckIn(pI2cDiscovery) +#define I2C_CYCLE_ACKOUT i2cCycleDiscoveryAckOut(pI2cDiscovery) +#define I2C_CYCLE_READ(ad) i2cCycleDiscoveryRead(pI2cDiscovery,ad) +#define I2C_CYCLE_START i2cCycleDiscoveryStart(pI2cDiscovery) +#define I2C_CYCLE_STOP i2cCycleDiscoveryStop(pI2cDiscovery) +#define I2C_CYCLE_WRITE(wd) i2cCycleDiscoveryWrite(pI2cDiscovery,wd) +#define I2C_KNOWN_STATE i2cCycleDiscoveryKnownState(pI2cDiscovery) + +#define I2C_BYTE_ADDRESS(address,offset) (((address)>>(offset*8))&0xff) + +#define I2C_DEVICE_TYPE_EEPROM 0 /* 1-byte address/index */ +#define I2C_DEVICE_TYPE_EEPROM_AB2 1 /* 2-byte address/index */ +#define I2C_DEVICE_TYPE_EEPROM_AB3 2 /* 3-byte address/index */ + +/* + * error codes + */ + +#define I2C_ERROR_CYCLE_START 1 /* start cycle */ +#define I2C_ERROR_CYCLE_STOP 2 /* stop cycle */ +#define I2C_ERROR_CYCLE_READ 3 /* read cycle */ +#define I2C_ERROR_CYCLE_WRITE 4 /* write cycle */ +#define I2C_ERROR_CYCLE_ACKIN 5 /* acknowledge in cycle */ +#define I2C_ERROR_CYCLE_ACKOUT 6 /* acknowledge out cycle */ +#define I2C_ERROR_KNOWN_STATE 7 /* known state */ + +int gt64260_i2cMacGet(char *ptr, int index); + +/* + * global data + */ + +static int I2cInitFlag; + +static unsigned int i2cAddressMunge(unsigned int deviceAddress, + unsigned int byteOffset); +static unsigned int i2cAddressMunge(unsigned int deviceAddress, + unsigned int byteOffset); +static int i2cCycleDiscoveryStart(i2cDiscovery_t * pI2cDiscovery); +static int i2cCycleDiscoveryStop(i2cDiscovery_t * pI2cDiscovery); +static int i2cCycleDiscoveryRead(i2cDiscovery_t * pI2cDiscovery, + unsigned char *DataBuf); +static int i2cCycleDiscoveryWrite(i2cDiscovery_t * pI2cDiscovery, + unsigned int writeData); +static int i2cCycleDiscoveryAckIn(i2cDiscovery_t * pI2cDiscovery); +static int i2cCycleDiscoveryKnownState(i2cDiscovery_t * pI2cDiscovery); +static int i2cIntFlagRead(i2cDiscovery_t * pI2cDiscovery); +static int i2cDoOpLowLevel(int cmd, char *palVpdBBBuffer); +static unsigned char *vpdGetPacket(vpdHeader_t * pVpdHeader, + unsigned int vpdSromSize, + unsigned int vpdPid, + unsigned char *pVpdPacket); + +static int i2cReadFlag; +static i2cDiscovery_t *pI2cDiscovery = (i2cDiscovery_t *) (0xf1000000 + 0xC000); + +/* + * i2cCycleDiscoveryStart - perform I2C "start" cycle + * description: + * This function's purpose is to perform an I2C start cycle. + * call: + * argument #1 = pointer to controller device + * return: + * zero = operation successful + * non-zero = operation failed + */ + +static int i2cCycleDiscoveryStart(i2cDiscovery_t * pI2cDiscovery) +{ + unsigned int timeOutCount; + unsigned int statusReg; + unsigned int data = 0; + + /* + * init the I2C interface, if needed. + */ + i2cCycleDiscoveryKnownState(pI2cDiscovery); + + /* + * START OF NORMAL DRIVER CODE + */ + data |= (DISCOVERY_I2C_CONTROL_REG_START | + DISCOVERY_I2C_CONTROL_REG_ENABLE); + writel(data, &pI2cDiscovery->control); + udelay(1000); + + /* + * verify the INT FLAG bit in the CONTROL register is set + * before checking the STATUS register. + */ + if (i2cIntFlagRead(pI2cDiscovery)) { + i2cCycleDiscoveryStop(pI2cDiscovery); + return (1); /* indicates an ERROR occurred */ + } + + /* + * check for completion of START sequence + */ + for (timeOutCount = 10; timeOutCount; timeOutCount--) { + statusReg = readl(&pI2cDiscovery->status); +#ifdef DISCO_I2C_DRV_DEBUG + printf("START: status reg = 0x%04X\r\n", statusReg); +#endif + if ((statusReg == DISCOVERY_I2C_STATUS_STARTTX) || + (statusReg == DISCOVERY_I2C_STATUS_REPEATSTARTX)) { + break; + } + udelay(1000); + } + + /* + * if we timedout without notification of a completed START cycle, + * bailout and return with an ERROR status. + */ + if (!timeOutCount) { + i2cCycleDiscoveryStop(pI2cDiscovery); + return (-1); + } + + return (0); +} + +/* + * i2cCycleDiscoveryStop - perform I2C "stop" cycle + * description: + * This function's purpose is to perform an I2C stop cycle. + * call: + * argument #1 = pointer to controller device + * return: + * zero = operation successful + * non-zero = operation failed + */ +static int i2cCycleDiscoveryStop(i2cDiscovery_t * pI2cDiscovery) +{ + unsigned int controlReg; + + /* + * set the STOP bit. This does not cause a STOP + * bus transaction until the INT FLAG has been + * cleared. The INT FLAG can be cleared after the + * interrupt flag bit has been set in the control register. + */ + controlReg = readl(&pI2cDiscovery->control); + controlReg |= (DISCOVERY_I2C_CONTROL_REG_STOP); + writel(controlReg, &pI2cDiscovery->control); + udelay(1000); + + /* + * verify the INT FLAG bit in the CONTROL register is set + * before trying to clear it. + */ + if (i2cIntFlagRead(pI2cDiscovery)) { + i2cCycleDiscoveryStop(pI2cDiscovery); + return (1); /* indicates an ERROR occurred */ + } + + /* + * clear the INT FLAG, but do NOT turn off the interface + * by clearing the control register. A STOP will be transmitted + * on the bus 'after' the INT FLAG has been cleared... + */ + controlReg = readl(&pI2cDiscovery->control); + controlReg &= (~DISCOVERY_I2C_CONTROL_REG_INTFLG); + writel(controlReg, &pI2cDiscovery->control); + udelay(1000); + + return (0); +} + +/* + * i2cCycleDiscoveryRead - perform I2C "read" cycle + * description: + * This function's purpose is to perform an I2C read cycle. + * call: + * argument #1 = pointer to controller device + * argument #2 = pointer to read data buffer + * return: + * zero = operation successful + * non-zero = operation failed + */ + +static int +i2cCycleDiscoveryRead(i2cDiscovery_t * pI2cDiscovery, unsigned char *DataBuf) +{ + unsigned int statusReg; + unsigned int timeOutCount; + + /* + * clear the INT FLAG by writing the ACK and ENABLE bits. + */ + writel((DISCOVERY_I2C_CONTROL_REG_ACK | + DISCOVERY_I2C_CONTROL_REG_ENABLE), &pI2cDiscovery->control); + udelay(1000); + + /* + * verify the INT FLAG bit in the CONTROL register is set + * before checking the STATUS register. + */ + if (i2cIntFlagRead(pI2cDiscovery)) { + i2cCycleDiscoveryStop(pI2cDiscovery); + return (1); /* indicates an ERROR occurred */ + } + + /* + * check for READ status of ACK. + */ + for (timeOutCount = 10; timeOutCount; timeOutCount--) { + statusReg = readl(&pI2cDiscovery->status); + +/* + printk("READ: status reg = 0x%04X\r\n", statusReg); +*/ + if ((statusReg == DISCOVERY_I2C_STATUS_MSTDATARECVACK) || + (statusReg == DISCOVERY_I2C_STATUS_ADDRWRITENACK)) { + /* + * get the data requested by the user + */ + *DataBuf = readl(&pI2cDiscovery->data); + udelay(1000); + writel(DISCOVERY_I2C_CONTROL_REG_ENABLE, + &pI2cDiscovery->control); + udelay(1000); + break; + } + udelay(1000); + } + + /* + * if we timedout without notification of a completed READ cycle, + * bailout and return with an ERROR status. + */ + if (!timeOutCount) { + i2cCycleDiscoveryStop(pI2cDiscovery); + return (-1); + } + + /* + * if we get here, then we have good data + */ + return (0); +} + +/* + * i2cCycleDiscoveryWrite - perform I2C "write" cycle + * description: + * This function's purpose is to perform an I2C write cycle. + * call: + * argument #1 = pointer to controller device + * argument #2 = write data + * return: + * zero = operation successful + * non-zero = operation failed + */ + +static int +i2cCycleDiscoveryWrite(i2cDiscovery_t * pI2cDiscovery, unsigned int writeData) +{ + unsigned int statusReg; + unsigned int timeOutCount; + + /* + * write the data into the I2C data register, + * then clear the INT FLAG to drive the data onto the bus. + */ + writel(writeData, &pI2cDiscovery->data); + writel(0, &pI2cDiscovery->control); + udelay(1000); + + /* + * verify the INT FLAG bit in the CONTROL register is set + * before checking the STATUS register. + */ + if (i2cIntFlagRead(pI2cDiscovery)) { + i2cCycleDiscoveryStop(pI2cDiscovery); + return (1); /* indicates an ERROR occurred */ + } + + for (timeOutCount = 10; timeOutCount; timeOutCount--) { + udelay(1000); + statusReg = readl(&pI2cDiscovery->status); + + if (statusReg == DISCOVERY_I2C_STATUS_ADDRWRITENACK) { + /* + * no device at the specified address is responding, + * so generate a STOP and return with a status ERROR. + */ + i2cCycleDiscoveryStop(pI2cDiscovery); + return (1); + } + + if ((statusReg == DISCOVERY_I2C_STATUS_ADDRWRITEACK) || + (statusReg == DISCOVERY_I2C_STATUS_MSTDATAWRITEACK) || + (statusReg == DISCOVERY_I2C_STATUS_ADDRREADACK)) { + break; + } + + /* + * since we haven't received the correct status, keep trying + * until the loop count has expired. + */ + udelay(1000); + } + + /* + * if we timedout without notification of a completed WRITE cycle, + * bailout and return with an ERROR status. + */ + if (!timeOutCount) { + i2cCycleDiscoveryStop(pI2cDiscovery); + return (-1); + } + + return (0); +} + +/* + * i2cCycleDiscoveryAckIn - perform I2C "acknowledge-in" cycle + * description: + * This function's purpose is to perform an I2C acknowledge-in + * cycle. + * call: + * argument #1 = pointer to controller device + * return: + * zero = operation successful + * non-zero = operation failed + */ + +static int i2cCycleDiscoveryAckIn(i2cDiscovery_t * pI2cDiscovery) +{ + return (0); +} + +/* + * i2cCycleDiscoveryKnownState - initialize the I2C bus to a known state + * description: + * This function's purpose is to initialize the I2C bus to a + * known state. This can be called after an error has been + * determined, or to recover from a unstable state. + * call: + * argument #1 = pointer to controller device + * return: + * zero = operation successful + * non-zero = operation failed + */ + +static int i2cCycleDiscoveryKnownState(i2cDiscovery_t * pI2cDiscovery) +{ + + /* + * DEVICE INIT CODE + * The following code runs only once. it's purpose is to + * initialize the I2C interface based on the external clock + * of the processor. + */ + if (I2cInitFlag == 0) { + writel(0, &pI2cDiscovery->reset); + udelay(1000); + + writel(baudRate, &pI2cDiscovery->status); + udelay(1000); + + writel((DISCOVERY_I2C_CONTROL_REG_ACK | + DISCOVERY_I2C_CONTROL_REG_ENABLE), + &pI2cDiscovery->control); + udelay(4000); + I2cInitFlag = 1; + } + + return (0); +} + +/* + * i2cIntFlagRead - checks the control register for an interrupt. + * description: + * This function's purpose is to read the CONTROL register + * of the Discovery device checking for the INT FLAG to + * be set. + * call: + * argument #1 = pointer to controller device + * return: + * zero = INT FLAG bit is set + * non-zero = INT FLAG bit is NOT set + */ + +static int i2cIntFlagRead(i2cDiscovery_t * pI2cDiscovery) +{ + unsigned int status; + unsigned int timeOutCount; + + for (timeOutCount = 10; timeOutCount; timeOutCount--) { + status = readl(&pI2cDiscovery->control); + if (status & DISCOVERY_I2C_CONTROL_REG_INTFLG) { + return (0); + } else { + continue; + } + udelay(1000); + } + + /* + * if we reach this point, then the INT FLAG did not get set. + * return with a value not equal to 0, as an indication of ERROR. + */ + return (1); +} + +/* + * i2cDoOpLowLevel - i2c do operation (low level) + * description: + * This function's purpose is to execute the operation as specified + * by the passed command packet. Currently, the only device types + * that are recognized are EEPROM types. + * call: + * argument #1 = pointer to command packet + * argument #2 = controller type + * argument #3 = controller identifier + * argument #4 = device address + * argument #5 = device type + * argument #6 = pointer to device access routines + * return: + * zero = okay + * non-zero = failure + */ + +static int i2cDoOpLowLevel(int cmd, char *palVpdBBBuffer) +{ + int byteCount; /* byte counter */ + int statusVariable = 0; /* local status variable */ + unsigned long flags; /* interrupt lock key */ + + unsigned char *pWriteData; /* pointer to write data buffer */ + + /* + * read operation (EEPROM type devices), for each byte + * perform the random read operation + */ + if (cmd == I2C_READOP) { + + if (i2cReadFlag) + return (0); + /* + * read the specified number of bytes from the EEPROM + */ + statusVariable = 0; + for (byteCount = 0; byteCount < VPD_BLOCK_SIZE; byteCount++) { + if (byteCount == 0) { + if (I2C_KNOWN_STATE) { + statusVariable = I2C_ERROR_KNOWN_STATE; + break; + } + } + + /* + * lock (disable) interrupts from taking place + */ + local_irq_save(flags); + + if (deviceType == I2C_DEVICE_TYPE_EEPROM) { + if (I2C_CYCLE_START) { + statusVariable = I2C_ERROR_CYCLE_START; + break; + } + + if (I2C_CYCLE_WRITE + (i2cAddressMunge(deviceAddress, byteCount))) + { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE(byteCount)) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_START) { + statusVariable = I2C_ERROR_CYCLE_START; + break; + } + + if (I2C_CYCLE_WRITE + (i2cAddressMunge + (deviceAddress | 0x01, byteCount))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + } + + if (deviceType == I2C_DEVICE_TYPE_EEPROM_AB2) { + if (I2C_CYCLE_START) { + statusVariable = I2C_ERROR_CYCLE_START; + break; + } + + if (I2C_CYCLE_WRITE(deviceAddress)) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE + (I2C_BYTE_ADDRESS(byteCount, 1))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE + (I2C_BYTE_ADDRESS(byteCount, 0))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_START) { + statusVariable = I2C_ERROR_CYCLE_START; + break; + } + + if (I2C_CYCLE_WRITE(deviceAddress | 0x01)) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + } + + if (deviceType == I2C_DEVICE_TYPE_EEPROM_AB3) { + if (I2C_CYCLE_START) { + statusVariable = I2C_ERROR_CYCLE_START; + break; + } + + if (I2C_CYCLE_WRITE(deviceAddress)) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE + (I2C_BYTE_ADDRESS(byteCount, 2))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE + (I2C_BYTE_ADDRESS(byteCount, 1))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE + (I2C_BYTE_ADDRESS(byteCount, 0))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_START) { + statusVariable = I2C_ERROR_CYCLE_START; + break; + } + + if (I2C_CYCLE_WRITE(deviceAddress | 0x01)) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + } + + if (I2C_CYCLE_READ(palVpdBBBuffer + byteCount)) { + statusVariable = I2C_ERROR_CYCLE_READ; + break; + } + + if (I2C_CYCLE_STOP) { + statusVariable = I2C_ERROR_CYCLE_STOP; + break; + } + + /* + * unlock (enable) interrupts + */ + local_irq_restore(flags); + } + + /* + * leave the I2C bus in a known state + */ + I2C_KNOWN_STATE; + + /* + * update the caller's command packet with status of + * the operation + */ + i2cReadFlag = 1; + + return (0); + } + + /* + * write operation (EEPROM type devices), for each byte + * perform the byte write operation, a delay must be + * exercised following each byte write + */ + if (cmd == I2C_WRITOP) { + /* + * initialize pointer to caller's write data buffer + */ + pWriteData = (unsigned char *)palVpdBBBuffer; + + /* + * write the specified number of bytes from the EEPROM + */ + statusVariable = 0; + for (byteCount = 0; byteCount < VPD_BLOCK_SIZE; byteCount++) { + if (byteCount == 0) { + if (I2C_KNOWN_STATE) { + statusVariable = I2C_ERROR_KNOWN_STATE; + break; + } + } + + /* + * lock (disable) interrupts from taking place + */ + local_irq_save(flags); + + if (deviceType == I2C_DEVICE_TYPE_EEPROM) { + if (I2C_CYCLE_START) { + statusVariable = I2C_ERROR_CYCLE_START; + break; + } + + if (I2C_CYCLE_WRITE + (i2cAddressMunge(deviceAddress, byteCount))) + { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE(byteCount)) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + } + + if (deviceType == I2C_DEVICE_TYPE_EEPROM_AB2) { + if (I2C_CYCLE_START) { + statusVariable = I2C_ERROR_CYCLE_START; + break; + } + + if (I2C_CYCLE_WRITE(deviceAddress)) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE + (I2C_BYTE_ADDRESS(byteCount, 1))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE + (I2C_BYTE_ADDRESS(byteCount, 0))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + } + + if (deviceType == I2C_DEVICE_TYPE_EEPROM_AB3) { + if (I2C_CYCLE_START) { + statusVariable = I2C_ERROR_CYCLE_START; + break; + } + + if (I2C_CYCLE_WRITE(deviceAddress)) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE + (I2C_BYTE_ADDRESS(byteCount, 2))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE + (I2C_BYTE_ADDRESS(byteCount, 1))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_WRITE + (I2C_BYTE_ADDRESS(byteCount, 0))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + } + + if (I2C_CYCLE_WRITE(*(pWriteData + byteCount))) { + statusVariable = I2C_ERROR_CYCLE_WRITE; + break; + } + + if (I2C_CYCLE_ACKIN) { + statusVariable = I2C_ERROR_CYCLE_ACKIN; + break; + } + + if (I2C_CYCLE_STOP) { + statusVariable = I2C_ERROR_CYCLE_STOP; + break; + } + + /* + * unlock (enable) interrupts + */ + local_irq_restore(flags); + + /* + * delay for at least 10ms to allow EEPROM to complete + * the write cycle (internal operation) + */ + udelay(10 * 1000); + } + + /* + * leave the I2C bus in a known state + */ + I2C_KNOWN_STATE; + + /* + * update the caller's command packet with status of + * the operation + */ + return (statusVariable); + } + + return (statusVariable); +} + +static unsigned int +i2cAddressMunge(unsigned int deviceAddress, unsigned int byteOffset) +{ + return (deviceAddress | ((byteOffset & 0x700) >> 7)); +} + +int gt64260_i2cMacGet(char *ptr, int index) +{ + long indexVariable; + vpdEthernet_t *pVpdPacket; + + i2cDoOpLowLevel(I2C_READOP, palVpdBBBuffer); + + pVpdPacket = (vpdEthernet_t *) 0; + + for (indexVariable = 0; indexVariable <= index; indexVariable++) { + pVpdPacket = (vpdEthernet_t *) vpdGetPacket((vpdHeader_t + *) ((unsigned char + *) + &palVpdBBBuffer + [0]), + VPD_BLOCK_SIZE, + VPD_PID_EA, + (char *)pVpdPacket); + + if (pVpdPacket == 0) + return (-1); + if (pVpdPacket->instanceNum == index) + break; + } + memcpy(ptr, pVpdPacket->address, 6); + return (0); +} + +/* + * vpdGetPacket - vpd get packet + * description: + * This function's purpose is to retrieve a pointer (into the + * passed buffer) to the specified VPD packet. The optional + * previous VPD packet pointer argument allows for the retrieval + * of packets which have the same identifier. + * call: + * argument #1 = pointer to VPD header + * argument #2 = VPD SROM size in bytes + * argument #3 = VPD packet identifier + * argument #4 = pointer to previous VPD packet, or null pointer + * return: + * zero = error: termination, out-of-bounds, or not-found + * non-zero = pointer to the specified packet + */ + +static unsigned char *vpdGetPacket(vpdHeader_t * pVpdHeader, + unsigned int vpdSromSize, + unsigned int vpdPid, + unsigned char *pVpdPacket) +{ + unsigned int sromOffset; + unsigned int vpdPidLocal; + + unsigned char *pVpdBuffer; + + /* + * assign buffer pointer to the first packet of scan + */ + if (pVpdPacket == (unsigned char *)0) { + /* + * assign pointer to the first packet (skip over header) + */ + pVpdBuffer = (unsigned char *)pVpdHeader + sizeof(vpdHeader_t); + } else { + /* + * verify the packet pointer is real (in bounds to the buffer) + */ + sromOffset = + (unsigned int)pVpdPacket - (unsigned int)pVpdHeader; + if (sromOffset >= vpdSromSize) { + return ((unsigned char *)0); + } + + /* + * move pointer past the previously processed packet (i.e., to the + * next packet) + */ + pVpdBuffer = + pVpdPacket + *(pVpdPacket + VPD_PHDR_OFFSET_SIZE) + + VPD_PHDR_SIZE; + + /* + * verify the size of the SROM was not exceeded + */ + sromOffset = + (unsigned int)pVpdBuffer - (unsigned int)pVpdHeader; + if (sromOffset >= vpdSromSize) { + return ((unsigned char *)0); + } + } + + /* + * scan VPD buffer for the desired packet + */ + for (;;) { + /* + * retrieve packet identifier + */ + vpdPidLocal = (unsigned int)*(pVpdBuffer + VPD_PHDR_OFFSET_ID); + + /* + * check for termination packet + */ + if (vpdPidLocal == VPD_PID_TERM) { + break; + } + + /* + * does the packet identifier match?, if so, return pointer + * to packet and exit + */ + if (vpdPid == vpdPidLocal) { + return (pVpdBuffer); + } + + /* + * move pointer to the next packet + */ + pVpdBuffer = + pVpdBuffer + *(pVpdBuffer + VPD_PHDR_OFFSET_SIZE) + + VPD_PHDR_SIZE; + + /* + * verify the size of the SROM was not exceeded + */ + sromOffset = + (unsigned int)pVpdBuffer - (unsigned int)pVpdHeader; + if (sromOffset >= vpdSromSize) { + break; + } + } + + return ((unsigned char *)0); +} + +static int __init gt64260_i2c_init(void) +{ + return (0); +} + +static void __exit gt64260_i2c_exit(void) +{ + return; +} + +module_init(gt64260_i2c_init); +module_exit(gt64260_i2c_exit); + +MODULE_LICENSE("GPL"); diff -u --new-file --recursive linux-2.6.14.orig/drivers/i2c/busses/i2c-mpc.c linux-2.6.14.mod/drivers/i2c/busses/i2c-mpc.c --- linux-2.6.14.orig/drivers/i2c/busses/i2c-mpc.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/i2c/busses/i2c-mpc.c 2006-04-20 15:43:19.000000000 -0700 @@ -113,11 +113,21 @@ if (!(x & CSR_MCF)) { pr_debug("I2C: unfinished\n"); + + /* reset the controller if the bus is still busy */ + if (x & CSR_MBB) + writeccr(i2c, 0); + return -EIO; } if (x & CSR_MAL) { pr_debug("I2C: MAL\n"); + + /* reset the controller if the bus is still busy */ + if (x & CSR_MBB) + writeccr(i2c, 0); + return -EIO; } @@ -158,7 +168,7 @@ static int mpc_write(struct mpc_i2c *i2c, int target, const u8 * data, int length, int restart) { - int i; + int i, ret; unsigned timeout = i2c->adap.timeout; u32 flags = restart ? CCR_RSTA : 0; @@ -170,15 +180,17 @@ /* Write target byte */ writeb((target << 1), i2c->base + MPC_I2C_DR); - if (i2c_wait(i2c, timeout, 1) < 0) - return -1; + ret = i2c_wait(i2c, timeout, 1); + if (ret < 0) + return ret; for (i = 0; i < length; i++) { /* Write data byte */ writeb(data[i], i2c->base + MPC_I2C_DR); - if (i2c_wait(i2c, timeout, 1) < 0) - return -1; + ret = i2c_wait(i2c, timeout, 1); + if (ret < 0) + return ret; } return 0; @@ -188,7 +200,7 @@ u8 * data, int length, int restart) { unsigned timeout = i2c->adap.timeout; - int i; + int i, ret; u32 flags = restart ? CCR_RSTA : 0; /* Start with MEN */ @@ -199,8 +211,9 @@ /* Write target address byte - this time with the read flag set */ writeb((target << 1) | 1, i2c->base + MPC_I2C_DR); - if (i2c_wait(i2c, timeout, 1) < 0) - return -1; + ret = i2c_wait(i2c, timeout, 1); + if (ret < 0) + return ret; if (length) { if (length == 1) @@ -212,8 +225,9 @@ } for (i = 0; i < length; i++) { - if (i2c_wait(i2c, timeout, 0) < 0) - return -1; + ret = i2c_wait(i2c, timeout, 0); + if (ret < 0) + return ret; /* Generate txack on next to last byte */ if (i == length - 2) @@ -244,8 +258,13 @@ return -EINTR; } if (time_after(jiffies, orig_jiffies + HZ)) { - pr_debug("I2C: timeout\n"); - return -EIO; + writeccr(i2c, 0); + + /* try one more time before we error */ + if (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) { + pr_debug("I2C: timeout\n"); + return -EIO; + } } schedule(); } @@ -321,6 +340,7 @@ goto fail_irq; } + writeccr(i2c, 0); mpc_i2c_setclock(i2c); dev_set_drvdata(device, i2c); diff -u --new-file --recursive linux-2.6.14.orig/drivers/i2c/busses/i2c-mpc.h linux-2.6.14.mod/drivers/i2c/busses/i2c-mpc.h --- linux-2.6.14.orig/drivers/i2c/busses/i2c-mpc.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/i2c/busses/i2c-mpc.h 2005-11-16 10:40:21.000000000 -0700 @@ -0,0 +1,127 @@ +/* + * i2c-mpc.h + * non-CPM I2C driver for the Motorola MPC85xx, MPC824x, and MPC107 + * Derived from Wolfgang Denk's MPC8240 I2C driver, and IBM 4xx I2C driver + * + * (C) Copyright 2002,2003, 2004 Motorola Inc + * Authors: Xianghua Xiao, Andy Fleming + * + * Maintainer: Kumar Gala (galak@motorola.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MPC_I2C_H +#define __MPC_I2C_H + +#include +#include + + +/* Timeout for waiting for the bus (seconds) */ +#define MPC_TIMEOUT 50 + +/* retries value for the adapter. */ +#define MPC_RETRIES 3 + +/* Number of seconds to wait for an interrupt */ +#define MPC_INT_TIMEOUT 5 + +/* Mask for writing the entire register in I2C */ +#define MPC_I2C_FULLREG 0xff + +/* Default Clock Speed */ +#define MPC_I2C_CLKSPD 0x31 + +/* Default DFSR value */ +#define MPC_I2C_DFSR 0x10 + +/* Masks of which bits get set when writing + * to the register (ADR or FDR) */ +#define MPC_I2CADR_MASK 0xFE +#define MPC_I2CFDR_MASK 0x3F + +/* Bits for the CR */ +#define MPC_I2CCR_MEN 0x80 /* Enable */ +#define MPC_I2CCR_MIEN 0x40 /* Interrupt Enable */ +#define MPC_I2CCR_MSTA 0x20 /* Start Bit */ +#define MPC_I2CCR_MTX 0x10 /* Transmit bit */ +#define MPC_I2CCR_TXAK 0x08 /* TX Acknowledge */ +#define MPC_I2CCR_RSTA 0x04 /* Restart bit */ +#define MPC_I2CCR_BCST 0x01 /* Broadcast */ + +/* Bits for the SR */ +#define MPC_I2CSR_MCF 0x80 /* Transfer Pending */ +#define MPC_I2CSR_MAAS 0x40 /* Master/Slave */ +#define MPC_I2CSR_MBB 0x20 /* Bus Busy */ +#define MPC_I2CSR_MAL 0x10 /* Arbitration Lost */ +#define MPC_I2CSR_BCSTM 0x08 /* Broadcast */ +#define MPC_I2CSR_SRW 0x04 /* */ +#define MPC_I2CSR_MIF 0x02 /* Interrupt */ +#define MPC_I2CSR_RXAK 0x01 /* RX Acknowledged */ + +/* Data Register Mask */ +#define MPC_I2CDR_DATA 0xFF + +/* DFSRR default value */ +#define MPC_I2CDFSRR 0x3F + +/* Linux I2C values */ +#define I2C_ALGO_MPC 0x140000 /* Algorithm */ +#define I2C_HW_MPC 0x00 /* Adapter */ + +/* I2C address when addressed as a slave */ +#define I2C_MPC_ADDR 0xfe + +/* Init value for the CR */ +#define MPC_I2CCR_INIT (MPC_I2CCR_MEN | \ + MPC_I2CCR_MSTA| \ + MPC_I2CCR_MTX | \ + MPC_I2CCR_RSTA) + +/* I2C Registers */ +struct mpc_i2c { + u8 i2cadr; /* 0x000 - I2C Address Register */ + u8 res1[3]; + u8 i2cfdr; /* 0x004 - I2C Frequency Divider Register */ + u8 res2[3]; + u8 i2ccr; /* 0x008 - I2C Control Register */ + u8 res3[3]; + u8 i2csr; /* 0x00c - I2C Status Register */ + u8 res4[3]; + u8 i2cdr; /* 0x010 - I2C Data Register */ + u8 res5[3]; + u8 i2cdfsrr; /* 0x014 - I2C Digital Filtering Sampling Rate Register */ + u8 res6[3]; +}; + +struct mpc_i2c_private { + struct i2c_adapter adap; + volatile struct mpc_i2c *regs; + wait_queue_head_t i2c_waitq; + int index; /* device number */ + int irq; /* IRQ number */ + int poll; /* polling mode if == 0 */ + int pending; /* Interrupt occurred */ + u32 flags; /* features this device supports */ + + /* Write and read function pointers for writing + * device registers */ + void (*write)(volatile u8 *addr, u8 value, u8 mask); + u8 (*read)(volatile u8 *addr); +}; + + +#endif diff -u --new-file --recursive linux-2.6.14.orig/drivers/i2c/busses/Kconfig linux-2.6.14.mod/drivers/i2c/busses/Kconfig --- linux-2.6.14.orig/drivers/i2c/busses/Kconfig 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/i2c/busses/Kconfig 2006-01-24 12:19:08.000000000 -0700 @@ -519,4 +519,11 @@ This driver can also be built as a module. If so, the module will be called i2c-mv64xxx. +config I2C_GT64260 + bool "Marvell GT64260 I2C early support" + depends on MVME5500 && GT64260_ETH + help + Early use I2C driver to read GT64260 ETH MAC address. Say yes if + you want to use the GT64260 10/100 port on an MVME5500. + endmenu diff -u --new-file --recursive linux-2.6.14.orig/drivers/i2c/busses/Makefile linux-2.6.14.mod/drivers/i2c/busses/Makefile --- linux-2.6.14.orig/drivers/i2c/busses/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/i2c/busses/Makefile 2006-01-24 12:19:19.000000000 -0700 @@ -43,6 +43,7 @@ obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o +obj-$(CONFIG_I2C_GT64260) += i2c-gt64260.o ifeq ($(CONFIG_I2C_DEBUG_BUS),y) EXTRA_CFLAGS += -DDEBUG diff -u --new-file --recursive linux-2.6.14.orig/drivers/i2c/busses/mot_vpd.h linux-2.6.14.mod/drivers/i2c/busses/mot_vpd.h --- linux-2.6.14.orig/drivers/i2c/busses/mot_vpd.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/i2c/busses/mot_vpd.h 2006-02-16 13:13:30.000000000 -0700 @@ -0,0 +1,248 @@ +/* + * Description: + * Vital Product Data (VPD) Header-Module for ECC boards + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + + +#ifndef __mot_vpd_h +#define __mot_vpd_h + +#define VPD_BLOCK_SIZE 512 /* size of VPD data block */ +unsigned char palVpdBBBuffer[VPD_BLOCK_SIZE]; + +#define GET_VPD_BLOCK 0 /* IOCTL */ + +/* + * packet identifiers + * + * 0x00 - 0x19 these packet id's are in use or reserved + * 0x1a - 0xfd reserved for future packet definition + * 0xFE re-defined packet, set a packet ID to this to have packet + * ignored. + * 0xff termination packet + */ + +#define VPD_PID_GI 0x00 /* guaranteed illegal */ +#define VPD_PID_PID 0x01 /* product identifier (ASCII) */ +#define VPD_PID_FAN 0x02 /* factory assembly-number (ASCII) */ +#define VPD_PID_SN 0x03 /* serial-number (ASCII) */ +#define VPD_PID_PCO 0x04 /* product configuration options (binary) */ +#define VPD_PID_ICS 0x05 /* internal clock speed in HZ (integer) */ +#define VPD_PID_ECS 0x06 /* external clock speed in HZ (integer) */ +#define VPD_PID_RCS 0x07 /* reference clock speed in HZ (integer) */ +#define VPD_PID_EA 0x08 /* ethernet address (binary) */ +#define VPD_PID_MT 0x09 /* microprocessor type (ASCII) */ +#define VPD_PID_CRC 0x0A /* EEPROM CRC (integer) */ +#define VPD_PID_FMC 0x0B /* FLASH memory configuration (binary) */ +#define VPD_PID_VLSI 0x0C /* VLSI revisions/versions (binary) */ +#define VPD_PID_PCS 0x0D /* host PCI-bus clock speed (integer) */ +#define VPD_PID_L2C 0x0E /* l2 cache configuration (binary) */ +#define VPD_PID_VPDR 0x0F /* VPD revision (binary) */ +#define VPD_PID_BCC 0x10 /* board component configuration (binary) */ +#define VPD_PID_L3C 0x19 /* external L3 cache */ +#define VPD_PID_TERM 0xFF /* termination */ + +/* + * VPD structure (format) + */ + +#define VPD_EYE_SIZE 8 /* eyecatcher size */ + +typedef struct vpdHeader { + unsigned char eyeCatcher[VPD_EYE_SIZE]; /* eyecatcher - "MOTOROLA" */ + unsigned char size[2]; /* size of EEPROM */ +} vpdHeader_t; + +/* + * packet tuple structure (format) + */ + +typedef struct vpdPacket { + unsigned char identifier; /* identifier (PIDs above) */ + unsigned char size; /* size of the following data area */ + unsigned char data[1]; /* data (size is dependent upon PID) */ +} vpdPacket_t; + +/* + * packet header definitions + */ + +#define VPD_PHDR_OFFSET_ID 0 /* offset to identifier */ +#define VPD_PHDR_OFFSET_SIZE 1 /* offset to size */ + +#define VPD_PHDR_SIZE 2 /* size of header */ + +/* + * overall structure + */ + +typedef struct vpd { + vpdHeader_t header; /* header */ + vpdPacket_t packets[1]; /* data */ +} vpd_t; + +/* + * clock packet struct + */ + +typedef struct vpdClk{ + unsigned char packetID; + unsigned char dataSize; + unsigned char clk[4]; /* Compiler alignment doesn't allow UINT here */ + unsigned char processor; /* This stores a binary encoding + * indicating which processors this + * packet is used for: + * 0x1 :1st processor + * 0x2 :2nd processor + * 0x4 :3rd processor + * 0x8 :4th processor + * etc. + */ +} vpdClk_t; + +#define sizeof_VPD_CLK 4 /* Used to get the correct size of a structure. */ + +/* + * CRC packet struct + */ + +typedef struct vpdCrc { + unsigned char packetId; + unsigned char dataSize; + unsigned char crc[4]; /* Compiler alignment doesn't allow UINT here */ +} vpdCrc_t; + +#define sizeof_VPD_CRC 4 /* Used to get the correct size of a sturcture. */ + +/* + * Flash packet struct + */ + +typedef struct vpdFlash { + unsigned char packetId; + unsigned char dataSize; + unsigned char vendorID[2]; + unsigned char deviceID[2]; + unsigned char devWidth; + unsigned char numDevices; + unsigned char numColumns; + unsigned char columnWidth; + unsigned char writeWidth; + unsigned char bankNum; + unsigned char accessSpeed; + unsigned char bankSize; +} vpdFlash_t; + +/* + * L2 cache packet struct + */ + +typedef struct vpdL2Cache { + unsigned char packetId; + unsigned char dataSize; + unsigned char vendorID[2]; + unsigned char deviceID[2]; + unsigned char devWidth; + unsigned char numDevices; + unsigned char numColumns; + unsigned char columnWidth; + unsigned char cacheType; + unsigned char processor; /* This stores a binary encoding + * indicating which processors this + * cache packet is used for: + * 0x1 :1st processor + * 0x2 :2nd processor + * 0x4 :3rd processor + * 0x8 :4th processor + * etc. + */ + unsigned char operationMode; + unsigned char errorType; /* data/tag error detection type + * 0:none 1:parity 2:ecc + */ + unsigned char cacheSize; + unsigned char cacheSettings; + unsigned char coreRatio; +} vpdL2cache_t; + +/* + * revision packet struct + */ + +typedef struct vpdRevision { + unsigned char packetId; + unsigned char dataSize; + unsigned char vpdType; + unsigned char archRev; + unsigned char buildRev; + unsigned char reasonCode; +} vpdRevision_t; + +/* + * ethernet packet struct + */ + +typedef struct vpdEthernet { + unsigned char packetId; + unsigned char dataSize; + unsigned char address[6]; + unsigned char instanceNum; +} vpdEthernet_t; + +/* + * L3 cache packet struct + * This structure contains elements which could change when the + * L3-specific board artwork or the SRAM devices are changed. + */ + +typedef struct vpdL3Cache { + unsigned char packetId; + unsigned char dataSize; + unsigned char processor; /* This stores a binary encoding + * indicating which processors this + * cache packet is used for: + * 0x1 :1st processor + * 0x2 :2nd processor + * 0x4 :3rd processor + * 0x8 :4th processor + * etc. + */ + unsigned char cacheSize; /* 0x0 = 1Mb, 0x1 = 2Mb */ + unsigned char clockDividerRatio; /* core to cache clock ratio + * 0:/6 (value 0 == divide by 6) + * 1:reserved 2:/2 3:/2.5 + * 4:/3 5:/3.5 6:/4 7:/5 + */ + unsigned char cksp; /* cache clock sample point + * 0: 2 clocks, 1: 3 clocks + * 2: 4 clocks, 3: 5 clocks + */ + unsigned char psp; /* processor clock sample point + * values 0 thru 5 indicate the clock + * the sample should occur in. values + * 6 and 7 are reserved. + */ + unsigned char spo; /* sample point override + * 0:disabled, 1:enabled + */ + unsigned char nirca; /* SRAM clock control + * 0:special timing disabled + * 1:special timing enabled + */ + unsigned char sramType; /* 0:DDR, 1:late-write, + * 2:reserved, 3:PB2 SRAM + */ + unsigned char dataErrCk; /* data bus error detection type + * 0:none 1:parity + */ + unsigned char addrErrCk; /* address bus error detection type + * 0:none 1:parity + */ +} vpdL3Cache_t; + +#endif /* __mot_vpd_h */ diff -u --new-file --recursive linux-2.6.14.orig/drivers/i2c/chips/ds1375.c linux-2.6.14.mod/drivers/i2c/chips/ds1375.c --- linux-2.6.14.orig/drivers/i2c/chips/ds1375.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/i2c/chips/ds1375.c 2006-02-16 13:13:53.000000000 -0700 @@ -0,0 +1,388 @@ +/* + * drivers/i2c/chips/ds1375.c + * + * I2C client/driver for the Maxim/Dallas DS1375 Real-Time Clock + * + * Author: Ajit Prem + * + * Copyright 2005-2006 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DS1375_SECONDS_REGISTER 0x00 +#define DS1375_MINUTES_REGISTER 0x01 +#define DS1375_HOURS_REGISTER 0x02 +#define DS1375_DAY_REGISTER 0x03 +#define DS1375_DATE_REGISTER 0x04 +#define DS1375_MONTH_REGISTER 0x05 +#define DS1375_YEAR_REGISTER 0x06 +#define DS1375_CENTURY_REGISTER 0x05 +#define DS1375_CONTROL_REGISTER 0x0E +#define DS1375_STATUS_REGISTER 0x0F + +#define DS1375_12HOUR_MODE_FLAG 0x40 +#define DS1375_PM_HOUR_FLAG 0x20 + +#define DS1375_CLOCK_ENABLE 0x80 + +#define DS1375_NVRAM_OFFSET 0x10 +#define DS1375_MIN_NVRAM_ADDRESS 0x10 +#define DS1375_MAX_NVRAM_ADDRESS 0x1f +#define DS1375_NVRAM_SIZE 0x10 + +#define DS1375_DRV_NAME "ds1375" + +static DECLARE_MUTEX(ds1375_mutex); + +static struct i2c_driver ds1375_driver; +static struct i2c_client *save_client; + +static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD_1(ds1375); + +struct ds1375_data { + struct i2c_client client; + int sysctl_id; +}; + +static inline int ds1375_read(struct i2c_client *client, u8 reg, u8 * value) +{ + s32 tmp = i2c_smbus_read_byte_data(client, reg); + + if (tmp < 0) + return -EIO; + + *value = tmp; + + return 0; +} + +static ulong ds1375_read_rtc(void) +{ + u8 yr, month, mday, wday, hours, minutes, seconds; + u8 temp; + unsigned int year; + + if (ds1375_read(save_client, DS1375_SECONDS_REGISTER, &seconds) < 0) { + dev_warn(&save_client->dev, "RTC read error SECOND register\n"); + return 0; + } + if (ds1375_read(save_client, DS1375_MINUTES_REGISTER, &minutes) < 0) { + dev_warn(&save_client->dev, "RTC read error MINUTE register\n"); + return 0; + } + if (ds1375_read(save_client, DS1375_HOURS_REGISTER, &hours) < 0) { + dev_warn(&save_client->dev, "RTC read error HOUR register\n"); + return 0; + } + if (ds1375_read(save_client, DS1375_DAY_REGISTER, &wday) < 0) { + dev_warn(&save_client->dev, "RTC read error DAY register\n"); + return 0; + } + if (ds1375_read(save_client, DS1375_DATE_REGISTER, &mday) < 0) { + dev_warn(&save_client->dev, "RTC read error DATE register\n"); + return 0; + } + if (ds1375_read(save_client, DS1375_MONTH_REGISTER, &month) < 0) { + dev_warn(&save_client->dev, "RTC read error MONTH register\n"); + return 0; + } + if (ds1375_read(save_client, DS1375_YEAR_REGISTER, &yr) < 0) { + dev_warn(&save_client->dev, "RTC read error YEAR register\n"); + return 0; + } + + dev_dbg(&save_client->dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n", + __FUNCTION__, seconds, minutes, hours, wday, mday, month, yr); + + seconds = BCD2BIN(seconds); + minutes = BCD2BIN(minutes); + hours = hours & 0x3f; + hours = BCD2BIN(hours); + wday = BCD2BIN(wday) - 1; + mday = BCD2BIN(mday); + temp = month; + month = month & 0x7f; + month = BCD2BIN(month); + year = BCD2BIN(yr); + if (temp & 0x80) + year += 100; + year += 1900; + + dev_dbg(&save_client->dev, "%s: secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + __FUNCTION__, seconds, minutes, hours, mday, month, year, wday); + + return (mktime(year, month, mday, hours, minutes, seconds)); +} + +static void ds1375_write_rtc(ulong time) +{ + struct rtc_time tm; + s32 buf[7]; + u32 year; + + to_tm(time, &tm); + + dev_dbg(&save_client->dev, "%s: secs=%d, mins=%d, hours=%d, " + "mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__, + tm.tm_sec, tm.tm_min, tm.tm_hour, + tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday); + + buf[0] = BIN2BCD(tm.tm_sec); + buf[1] = BIN2BCD(tm.tm_min); + buf[2] = BIN2BCD(tm.tm_hour); + buf[3] = BIN2BCD(tm.tm_wday) + 1; + buf[4] = BIN2BCD(tm.tm_mday); + buf[5] = BIN2BCD(tm.tm_mon); + year = tm.tm_year - 1900; + if (year >= 100) { + year -= 100; + buf[5] |= (1 << 7); + } + buf[6] = BIN2BCD(year); + + i2c_smbus_write_byte_data(save_client, DS1375_SECONDS_REGISTER, buf[0]); + i2c_smbus_write_byte_data(save_client, DS1375_MINUTES_REGISTER, buf[1]); + i2c_smbus_write_byte_data(save_client, DS1375_HOURS_REGISTER, buf[2]); + i2c_smbus_write_byte_data(save_client, DS1375_DAY_REGISTER, buf[3]); + i2c_smbus_write_byte_data(save_client, DS1375_DATE_REGISTER, buf[4]); + i2c_smbus_write_byte_data(save_client, DS1375_MONTH_REGISTER, buf[5]); + i2c_smbus_write_byte_data(save_client, DS1375_YEAR_REGISTER, buf[6]); + + return; +} + +ulong ds1375_get_rtc_time(void) +{ + ulong t1, t2; + int limit = 10; /* arbitrary retry limit */ + + down(&ds1375_mutex); + + /* + * Since the reads are being performed one byte at a time using + * the SMBus vs a 4-byte i2c transfer, there is a chance that a + * carry will occur during the read. To detect this, 2 reads are + * performed and compared. + */ + do { + t1 = ds1375_read_rtc(); + t2 = ds1375_read_rtc(); + } while (t1 != t2 && limit--); + + up(&ds1375_mutex); + + if (t1 != t2) { + dev_warn(&save_client->dev, + "Cannot get consistent time from RTC chip\n"); + t1 = 0; + } + + return t1; +} + +static void ds1375_set_tlet(ulong arg) +{ + ulong t1, t2; + int limit = 10; /* arbitrary retry limit */ + + t1 = *(ulong *) arg; + + down(&ds1375_mutex); + + /* + * Since the writes are being performed one byte at a time using + * the SMBus vs a 4-byte i2c transfer, there is a chance that a + * carry will occur during the write. To detect this, the write + * value is read back and compared. + */ + do { + ds1375_write_rtc(t1); + t2 = ds1375_read_rtc(); + } while (t1 != t2 && limit--); + + up(&ds1375_mutex); + + if (t1 != t2) + dev_warn(&save_client->dev, + "Cannot confirm time set from RTC chip\n"); +} + +static ulong new_time; + +DECLARE_TASKLET_DISABLED(ds1375_tasklet, ds1375_set_tlet, (ulong) & new_time); + +int ds1375_set_rtc_time(ulong nowtime) +{ + new_time = nowtime; + + if (in_interrupt()) + tasklet_schedule(&ds1375_tasklet); + else + ds1375_set_tlet((ulong) & new_time); + + return 0; +} + +static void ds1375_init_client(struct i2c_client *client) +{ + s32 val; + + /* Enable clock */ + val = 0x84; + i2c_smbus_write_byte_data(client, DS1375_CONTROL_REGISTER, val); + + /* Clear status */ + val = 0; + i2c_smbus_write_byte_data(client, DS1375_STATUS_REGISTER, val); + + /* Ensure that device is set in 24-hour mode */ + val = i2c_smbus_read_byte_data(client, DS1375_HOURS_REGISTER); + if ((val >= 0) && (val & (1 << 6))) + i2c_smbus_write_byte_data(client, DS1375_HOURS_REGISTER, + val & 0x3f); +} + +/* + ***************************************************************************** + * + * Driver Interface + * + ***************************************************************************** + */ +static int ds1375_detect(struct i2c_adapter *adap, int addr, int kind) +{ + struct i2c_client *client; + struct ds1375_data *data; + int rc = 0; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_I2C)) + return 0; + + if (!(data = kmalloc(sizeof(struct ds1375_data), GFP_KERNEL))) { + return -ENOMEM; + } + memset(data, 0, sizeof(struct ds1375_data)); + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = addr; + client->adapter = adap; + client->driver = &ds1375_driver; + strlcpy(client->name, DS1375_DRV_NAME, I2C_NAME_SIZE); + client->flags = 0; + + /* + * Now we do the remaining detection. A negative kind means that + * the driver was loaded with no force parameter (default), so we + * must both detect and identify the chip. A zero kind means that + * the driver was loaded with the force parameter, the detection + * step shall be skipped. A positive kind means that the driver + * was loaded with the force parameter and a given kind of chip is + * requested, so both the detection and the identification steps + * are skipped. + * + * For detection, we read registers that are most likely to cause + * detection failure, i.e. those that have more bits with fixed + * or reserved values. + */ + + /* Default to an DS1375 if forced */ + if (kind == 0) + kind = ds1375; + + if (kind < 0) { + u8 data; + + /* Check for a valid day register value */ + if ((ds1375_read(client, DS1375_DAY_REGISTER, &data) < 0) || + (data == 0) || (data & 0xf8)) + goto exit_free; + + /* Check for a valid date register value */ + if ((ds1375_read(client, DS1375_DATE_REGISTER, &data) < 0) || + (data == 0) || (data & 0xc0) || ((data & 0x0f) > 9) || + (data >= 0x32)) + goto exit_free; + + /* Check for a valid month register value */ + if ((ds1375_read(client, DS1375_MONTH_REGISTER, &data) < 0) || + (data == 0) || (data & 0x60) || ((data & 0x0f) > 9) || + ((data >= 0x13) && (data <= 0x19))) + goto exit_free; + + kind = ds1375; + } + + if ((rc = i2c_attach_client(client)) != 0) + goto exit_free; + + save_client = client; + + ds1375_init_client(client); + + return 0; + + exit_free: + kfree(data); + return rc; +} + +static int ds1375_attach(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, ds1375_detect); +} + +static int ds1375_detach(struct i2c_client *client) +{ + int rc; + + if ((rc = i2c_detach_client(client)) == 0) { + kfree(i2c_get_clientdata(client)); + tasklet_kill(&ds1375_tasklet); + } + return rc; +} + +static struct i2c_driver ds1375_driver = { + .owner = THIS_MODULE, + .name = DS1375_DRV_NAME, + .id = I2C_DRIVERID_DS1375, + .flags = I2C_DF_NOTIFY, + .attach_adapter = ds1375_attach, + .detach_client = ds1375_detach, +}; + +static int __init ds1375_init(void) +{ + return i2c_add_driver(&ds1375_driver); +} + +static void __exit ds1375_exit(void) +{ + i2c_del_driver(&ds1375_driver); +} + +module_init(ds1375_init); +module_exit(ds1375_exit); + +MODULE_AUTHOR("Ajit Prem "); +MODULE_DESCRIPTION("Maxim/Dallas DS1375 RTC I2C Client Driver"); +MODULE_LICENSE("GPL"); diff -u --new-file --recursive linux-2.6.14.orig/drivers/i2c/chips/Kconfig linux-2.6.14.mod/drivers/i2c/chips/Kconfig --- linux-2.6.14.orig/drivers/i2c/chips/Kconfig 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/i2c/chips/Kconfig 2006-02-06 11:25:31.000000000 -0700 @@ -25,6 +25,16 @@ This driver can also be built as a module. If so, the module will be called ds1374. +config SENSORS_DS1375 + tristate "Maxim/Dallas Semiconductor DS1375 Real Time Clock" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for the Dallas Semiconductor + DS1375 real-time clock chip. + + This driver can also be built as a module. If so, the module + will be called ds1375. + config SENSORS_EEPROM tristate "EEPROM reader" depends on I2C && EXPERIMENTAL diff -u --new-file --recursive linux-2.6.14.orig/drivers/i2c/chips/Makefile linux-2.6.14.mod/drivers/i2c/chips/Makefile --- linux-2.6.14.orig/drivers/i2c/chips/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/i2c/chips/Makefile 2006-02-06 11:25:48.000000000 -0700 @@ -4,6 +4,7 @@ obj-$(CONFIG_SENSORS_DS1337) += ds1337.o obj-$(CONFIG_SENSORS_DS1374) += ds1374.o +obj-$(CONFIG_SENSORS_DS1375) += ds1375.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o obj-$(CONFIG_SENSORS_MAX6875) += max6875.o obj-$(CONFIG_SENSORS_M41T00) += m41t00.o diff -u --new-file --recursive linux-2.6.14.orig/drivers/Kconfig linux-2.6.14.mod/drivers/Kconfig --- linux-2.6.14.orig/drivers/Kconfig 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/Kconfig 2005-11-16 10:40:21.000000000 -0700 @@ -42,6 +42,8 @@ source "drivers/char/Kconfig" +source "drivers/vme/Kconfig" + source "drivers/i2c/Kconfig" source "drivers/w1/Kconfig" diff -u --new-file --recursive linux-2.6.14.orig/drivers/Makefile linux-2.6.14.mod/drivers/Makefile --- linux-2.6.14.orig/drivers/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/Makefile 2005-11-16 10:40:21.000000000 -0700 @@ -52,6 +52,7 @@ obj-$(CONFIG_GAMEPORT) += input/gameport/ obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_I2O) += message/ +obj-$(CONFIG_VME_BRIDGE) += vme/ obj-$(CONFIG_I2C) += i2c/ obj-$(CONFIG_W1) += w1/ obj-$(CONFIG_HWMON) += hwmon/ diff -u --new-file --recursive linux-2.6.14.orig/drivers/misc/Kconfig linux-2.6.14.mod/drivers/misc/Kconfig --- linux-2.6.14.orig/drivers/misc/Kconfig 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/misc/Kconfig 2006-03-09 12:21:46.000000000 -0700 @@ -28,5 +28,18 @@ If unsure, say N. +config MV64360_IDMA + tristate "Device driver for the Marvell MV64360 IDMA controller" + depends on MV64360 + ---help--- + This option enables driver support for the Marvell MV64360 IDMA + controller. This driver uses a dynamic major number. The dynamic + major number claimed by this driver can be determined by checking + the major number associated with the mv64360_dma device in + /proc/devices. Minor numbers 0..3 are used for the 4 IDMA channels. + + If your board uses the Marvell MV64360 controller (like Motorola's + MVME6100 or MCP905 boards), say Y, otherwise, say N. + endmenu diff -u --new-file --recursive linux-2.6.14.orig/drivers/misc/Makefile linux-2.6.14.mod/drivers/misc/Makefile --- linux-2.6.14.orig/drivers/misc/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/misc/Makefile 2006-03-09 12:21:58.000000000 -0700 @@ -5,3 +5,4 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/ obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ +obj-$(CONFIG_MV64360_IDMA) += mv64360_idma/ diff -u --new-file --recursive linux-2.6.14.orig/drivers/misc/mv64360_idma/Makefile linux-2.6.14.mod/drivers/misc/mv64360_idma/Makefile --- linux-2.6.14.orig/drivers/misc/mv64360_idma/Makefile 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/misc/mv64360_idma/Makefile 2006-03-07 16:32:37.000000000 -0700 @@ -0,0 +1,5 @@ +# +# Makefile for the Marvell MV64360 IDMA driver +# + +obj-$(CONFIG_MV64360_IDMA) += mv64360_dma.o diff -u --new-file --recursive linux-2.6.14.orig/drivers/misc/mv64360_idma/mv64360_dma.c linux-2.6.14.mod/drivers/misc/mv64360_idma/mv64360_dma.c --- linux-2.6.14.orig/drivers/misc/mv64360_idma/mv64360_dma.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/misc/mv64360_idma/mv64360_dma.c 2006-03-07 17:11:47.000000000 -0700 @@ -0,0 +1,1683 @@ +/* + * mv64360_dma.c: Linux driver for the Marvel MV64360 IDMA controller. + * + * Author: Ajit Prem, (Ajit.Prem@motorola.com). + * Copyright 2003-2006 Motorola + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +/* + +The MV64360 DMA driver provides support to initialize, configure, +start, pause, resume, abort and retrieve status of DMA operations +on a per channel basis. Only block mode is supported. + +The arbiter setup routine may be invoked if a custom channel priority +weighting is desired. It is not necessary to program the DMA channel +arbiter unless something other than the default weighting is needed. The +default is balanced equally across all channels. + +To start DMA for a particular channel, the user-space app has to: +-- open the appropriate dma channel (/dev/mv64360_dma_x where 0<=x<=3) + +-- Setup the dma parameters and invoke ioctl(MV64360_DMA_SETUP). + The DMA parameter setup involves providing either the source or + destination address (one of which is expected to be a device address), + the byte account, and other transfer attributes. On the call, the + driver will allocate a kernel buffer for either the source or + destination address (based on the transfer attributes) and allow the + user-space application to mmap() the buffer. + + For SRAM to device DMA, the source buffer is a kernel allocated buffer + that the user-app can mmap(), populate, and then issue an + ioctl(MV64360_DMA_START) to have the driver start the DMA. + + For device to SRAM DMA, the destination buffer is a kernel allocated + buffer that the user-app can mmap(). + +-- Start DMA with ioctl(MV64360_DMA_START) + +-- A read() has to be issued on the device to wait for DMA completion + (alternatively, select() can also be used). + +-- Status can be checked with ioctl(MV64360_DMA_STATUS) + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_BIGPHYS_AREA +#include +#endif + +#include "mv64360_dma.h" +#include "mv64360_dma_interface.h" + +#define DRV_NAME "mv64360_dma" +#define DRV_VERSION "2.0.0" + +#define ALL_MSG "mv64360_dma: " + +#ifdef DMA_DEBUG +int dma_debug = DMA_DEBUG; +MODULE_PARM(dma_debug, "i"); + +#define DEBUG(n, fmt, args...) if (dma_debug>(n)) printk(KERN_INFO ALL_MSG fmt, ## args) +#else +#define DEBUG(n, fmt, args...) +#endif + +#define IDMA_REG_SIZE sizeof(u32) +#define IDMA_CHAN_IS_ACTIVE(_X_) (((_X_) & IDMA_CNTL_CHAN_ACTIVE_MASK) == \ + IDMA_CNTL_CHAN_ACTIVE_MASK) +#define MV_REG_WRITE_PUSH(offset,data) \ +{ \ +*(volatile unsigned int *) (mv64360_base + offset) = cpu_to_le32(data); \ +le32_to_cpu(*(volatile unsigned int *) (mv64360_base + offset)); \ +} + +/* + * The following structure defines the control elements for a given DMA + * channel. The register address offsets are used to conveniently access a + * particular channel's DMA descriptor and control registers. + */ + +struct mv64360_dma_cntl_t { + + /* channel number */ + u32 chan; + + /* offset of DMA byte count register */ + u32 byte_count_reg_offset; + + /* offset of DMA source address register */ + u32 source_addr_reg_offset; + + /* offset of DMA destination address register */ + u32 dest_reg_offset; + + /* offset of the next desc ptr register */ + u32 next_desc_ptr_reg_offset; + + /* offset of the current desc ptr register */ + u32 curr_desc_ptr_reg_offset; + + /* offset of the channel control register */ + u32 chan_cntl_low_reg_offset; + + /* offset of the channel control register */ + u32 chan_cntl_high_reg_offset; + + /* offset of window access control register */ + u32 chan_access_prot_offset; + + /* DMA completion status */ + int dma_complete; + + /* DMA error select code */ + u32 error_select; + + /* address causing the error */ + u32 error_addr; + + /* address of DMA buffer in kernel space */ + char *dma_src_buffer; + + /* address handed to device */ + dma_addr_t dma_src_handle; + + /* address of DMA destination buffer */ + char *dma_dest_buffer; + + /* address handed to device */ + dma_addr_t dma_dest_handle; + + /* size of DMA buffer in pages */ + int dma_buffer_npages; + + /* size of DMA buffer in bytes */ + size_t dma_buffer_size; + + /* byte count passed in by user. The computed dma_buffer_size may + be greater as it is a multiple of the PAGE_SIZE */ + size_t byte_count; + + /* attributes for current transfer */ + struct dma_attributes_t dma_attributes; + + /* semaphore used to serialize dma requests on the channel */ + struct semaphore dma_available; + + /* used to signal that a started DMA operation is complete */ + wait_queue_head_t readywait; + + /* spin lock for synchronizing with ISR */ + spinlock_t dma_lock; + + /* A timer whose function will abort a started DMA transaction + if it hasn't completed by a specific time */ + struct timer_list dma_device_timer; + + /* Indicates the dma_device_timer has been started */ + int dma_timer_pending; +}; + +#ifdef CONFIG_MV64X60_NEW_BASE +static unsigned int mv64360_reg_base = CONFIG_MV64X60_NEW_BASE; +#else +static unsigned int mv64360_reg_base = 0xf1000000; +#endif + +static unsigned int mv64360_base; + +static struct mv64360_dma_cntl_t mv64360_dma_cntl[IDMA_CHANNEL_COUNT]; +static int dma_device_open[IDMA_CHANNEL_COUNT]; + +static int is_initialized; + +static int major_dev; +static struct class *mv64360_dma_class; + +static DECLARE_WAIT_QUEUE_HEAD(dma_wait); + +static ssize_t mv64360_dma_read(struct file *file, char *buf, + size_t count, loff_t * ppos); +static ssize_t mv64360_dma_write(struct file *file, const char *buf, + size_t count, loff_t * ppos); +static unsigned int mv64360_dma_poll(struct file *file, + struct poll_table_struct *poll_table); +static int mv64360_dma_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +static int mv64360_dma_mmap(struct file *file, struct vm_area_struct *vma); +static int mv64360_dma_open(struct inode *inode, struct file *file); +static int mv64360_dma_release(struct inode *inode, struct file *file); + +static int mv64360_dma_arbiter_setup(unsigned int *arb_slice); +static int mv64360_dma_abort(struct mv64360_dma_cntl_t *dma_chan_cntl); +static int mv64360_dma_pause(struct mv64360_dma_cntl_t *dma_chan_cntl); +static int mv64360_dma_resume(struct mv64360_dma_cntl_t *dma_chan_cntl); + +#define MV_REG_READ(offset) le32_to_cpu(* (volatile unsigned int *) (mv64360_base + offset)) + +/****************************************************************************** +* +* mv64360_init_addr_windows - Initialize address decoding windows. +* +* This routine initializes the DMA address decoding windows to +* cover the system address map. DRAM addresses, PCI I/O and PCI memory +* addresses on both PCI buses are mapped for DMA access. +* A decoding window is configured for each DRAM bank that is enabled. +* All DRAM windows are configured for write back (WB) coherency. +* DRAM bank base addresses and sizes are obtained from the +* corresponding CPU interface registers, then programmed into +* DMA base address and size registers. PCI windows are configured for +* non-byte swapping transfers. All configured windows are enabled upon return. +* +* Note that base addresses and sizes are read from previously configured +* CPU IF registers. The base address values from these registers are 20 bits +* wide. The upper four address bits are ignored. It is not expected to have +* any addresses high enough to use these ignored bits. Only the next (upper) +* 16 address bits are used since all DMA windows must be 64K aligned. +* +* RETURNS: N/A +*/ + +static void mv64360_init_addr_windows(void) +{ + u32 dma_base_enable = 0; + u32 base_addr_enable = 0; + u32 base_addr = 0; + u32 size = 0; + u32 base_addr_val = 0; + base_addr_enable = MV_REG_READ(MV64360_CPU_BAR_ENABLE); + + /* Configure window for DRAM CS0 */ + if (!(base_addr_enable & MV64360_BASE_ADDR_ENABLE_CS_0_MASK)) { + base_addr = + MV_REG_READ(MV64x60_CPU2MEM_0_BASE) << + IDMA_CPUIF_ADDR_SHIFT_INDEX; + size = + MV_REG_READ(MV64x60_CPU2MEM_0_SIZE) << IDMA_WINDOW_SIZE_BIT; + base_addr_val = + IDMA_BASE_ADDR_TARGET_DRAM | IDMA_BASE_ADDR_DRAM_BANK_CS0 | + IDMA_BASE_ADDR_COHERENCY_WB | (base_addr & + IDMA_BASE_ADDR_BASE_MASK); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_0_BASE, base_addr_val); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_0_SIZE, + size & IDMA_WINDOW_SIZE_MASK); + + /* Enable Window 0 */ + dma_base_enable = MV_REG_READ(MV64360_IDMA2MEM_BAR_ENABLE); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_BAR_ENABLE, + ~IDMA_BASE_ADDR_ENABLE_WIN0 & + dma_base_enable); + } + + /* Configure window for DRAM CS1 */ + if (!(base_addr_enable & MV64360_BASE_ADDR_ENABLE_CS_1_MASK)) { + base_addr = + MV_REG_READ(MV64x60_CPU2MEM_1_BASE) << + IDMA_CPUIF_ADDR_SHIFT_INDEX; + size = + MV_REG_READ(MV64x60_CPU2MEM_1_SIZE) << IDMA_WINDOW_SIZE_BIT; + base_addr_val = + IDMA_BASE_ADDR_TARGET_DRAM | IDMA_BASE_ADDR_DRAM_BANK_CS1 | + IDMA_BASE_ADDR_COHERENCY_WB | (base_addr & + IDMA_BASE_ADDR_BASE_MASK); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_1_BASE, base_addr_val); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_1_SIZE, + size & IDMA_WINDOW_SIZE_MASK); + + /* Enable Window 1 */ + dma_base_enable = MV_REG_READ(MV64360_IDMA2MEM_BAR_ENABLE); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_BAR_ENABLE, + ~IDMA_BASE_ADDR_ENABLE_WIN1 & + dma_base_enable); + } + + /* Configure window for DRAM CS2 */ + if (!(base_addr_enable & MV64360_BASE_ADDR_ENABLE_CS_2_MASK)) { + base_addr = + MV_REG_READ(MV64x60_CPU2MEM_2_BASE) << + IDMA_CPUIF_ADDR_SHIFT_INDEX; + size = + MV_REG_READ(MV64x60_CPU2MEM_2_SIZE) << IDMA_WINDOW_SIZE_BIT; + base_addr_val = + IDMA_BASE_ADDR_TARGET_DRAM | IDMA_BASE_ADDR_DRAM_BANK_CS2 | + IDMA_BASE_ADDR_COHERENCY_WB | (base_addr & + IDMA_BASE_ADDR_BASE_MASK); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_2_BASE, base_addr_val); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_2_SIZE, + size & IDMA_WINDOW_SIZE_MASK); + + /* Enable Window 2 */ + dma_base_enable = MV_REG_READ(MV64360_IDMA2MEM_BAR_ENABLE); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_BAR_ENABLE, + ~IDMA_BASE_ADDR_ENABLE_WIN2 & + dma_base_enable); + } + + /* Configure window for DRAM CS3 */ + if (!(base_addr_enable & MV64360_BASE_ADDR_ENABLE_CS_3_MASK)) { + base_addr = + MV_REG_READ(MV64x60_CPU2MEM_3_BASE) << + IDMA_CPUIF_ADDR_SHIFT_INDEX; + size = + MV_REG_READ(MV64x60_CPU2MEM_3_SIZE) << IDMA_WINDOW_SIZE_BIT; + base_addr_val = + IDMA_BASE_ADDR_TARGET_DRAM | IDMA_BASE_ADDR_DRAM_BANK_CS3 | + IDMA_BASE_ADDR_COHERENCY_WB | (base_addr & + IDMA_BASE_ADDR_BASE_MASK); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_3_BASE, base_addr_val); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_3_SIZE, + size & IDMA_WINDOW_SIZE_MASK); + + /* Enable Window 3 */ + dma_base_enable = MV_REG_READ(MV64360_IDMA2MEM_BAR_ENABLE); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_BAR_ENABLE, + ~IDMA_BASE_ADDR_ENABLE_WIN3 & + dma_base_enable); + } + + /* Configure window for PCI Bus 0 I/O */ + base_addr = + MV_REG_READ(MV64x60_CPU2PCI0_IO_BASE) << + IDMA_CPUIF_ADDR_SHIFT_INDEX; + size = MV_REG_READ(MV64x60_CPU2PCI0_IO_SIZE) << IDMA_WINDOW_SIZE_BIT; + base_addr_val = + IDMA_BASE_ADDR_TARGET_PCI0 | IDMA_BASE_ADDR_PCI_NO_SWAP | + IDMA_BASE_ADDR_PCI_REQ64_SIZE | (base_addr & + IDMA_BASE_ADDR_BASE_MASK); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_4_BASE, base_addr_val); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_4_SIZE, + size & IDMA_WINDOW_SIZE_MASK); + + /* Configure window for PCI Bus 1 I/O */ + base_addr = + MV_REG_READ(MV64x60_CPU2PCI1_IO_BASE) << + IDMA_CPUIF_ADDR_SHIFT_INDEX; + size = MV_REG_READ(MV64x60_CPU2PCI1_IO_SIZE) << IDMA_WINDOW_SIZE_BIT; + base_addr_val = + IDMA_BASE_ADDR_TARGET_PCI1 | IDMA_BASE_ADDR_PCI_NO_SWAP | + IDMA_BASE_ADDR_PCI_REQ64_SIZE | (base_addr & + IDMA_BASE_ADDR_BASE_MASK); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_5_BASE, base_addr_val); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_5_SIZE, + size & IDMA_WINDOW_SIZE_MASK); + + /* Configure window for PCI Bus 0 memory */ + base_addr = + MV_REG_READ(MV64x60_CPU2PCI0_MEM_0_BASE) << + IDMA_CPUIF_ADDR_SHIFT_INDEX; + size = MV_REG_READ(MV64x60_CPU2PCI0_MEM_0_SIZE) << IDMA_WINDOW_SIZE_BIT; + base_addr_val = + IDMA_BASE_ADDR_TARGET_PCI0 | IDMA_BASE_ADDR_PCI_NO_SWAP | + IDMA_BASE_ADDR_PCI_MEM_SEL | IDMA_BASE_ADDR_PCI_REQ64_SIZE | + (base_addr & IDMA_BASE_ADDR_BASE_MASK); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_6_BASE, base_addr_val); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_6_SIZE, + size & IDMA_WINDOW_SIZE_MASK); + + /* Configure window for PCI Bus 1 memory */ + base_addr = + MV_REG_READ(MV64x60_CPU2PCI1_MEM_0_BASE) << + IDMA_CPUIF_ADDR_SHIFT_INDEX; + size = MV_REG_READ(MV64x60_CPU2PCI1_MEM_0_SIZE) << IDMA_WINDOW_SIZE_BIT; + base_addr_val = + IDMA_BASE_ADDR_TARGET_PCI0 | IDMA_BASE_ADDR_PCI_NO_SWAP | + IDMA_BASE_ADDR_PCI_MEM_SEL | IDMA_BASE_ADDR_PCI_REQ64_SIZE | + (base_addr & IDMA_BASE_ADDR_BASE_MASK); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_7_BASE, base_addr_val); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_7_SIZE, + size & IDMA_WINDOW_SIZE_MASK); + + /* Enable Windows 4,5,6,7 */ + dma_base_enable = MV_REG_READ(MV64360_IDMA2MEM_BAR_ENABLE); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_BAR_ENABLE, + dma_base_enable & ~(IDMA_BASE_ADDR_ENABLE_WIN4 + | + IDMA_BASE_ADDR_ENABLE_WIN5 + | + IDMA_BASE_ADDR_ENABLE_WIN6 + | IDMA_BASE_ADDR_ENABLE_WIN7)); +} + +/************************************************************************** +* +* mv64360_dma_int_handler - Handle a normal completion interrupt. +* +* This function handles a normal DMA completion interrupt for a particular +* channel. The interrupt is verified to have occurred and the channel +* status set to OK to indicate successful completion. +* +* The interrupt is cleared by writing a zero to the appropriate channel +* completion bit in the interrupt cause register. Other channel's bits are +* written as ones to preserve their state (writing a one has no effect). +* +* RETURNS: N/A +*/ + +static irqreturn_t +mv64360_dma_int_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + struct mv64360_dma_cntl_t *dma_chan_cntl = dev_id; + u32 int_cause = 0xFFFFFFFF; + u32 completion_mask = 0; + u32 error_mask = 0; + u32 error_code = 0; + u32 chan; + u32 temp; + + chan = dma_chan_cntl->chan; + DEBUG(1, "interrupt cntl 0x%p channel %d\n", dma_chan_cntl, chan); + completion_mask = IDMA_INT_CAUSE_DMA_COMPL_MASK << + (IDMA_INT_CAUSE_CHAN1_BIT * chan); + error_mask = IDMA_INT_CAUSE_CHAN_ERR_MASK << + (IDMA_INT_CAUSE_CHAN1_BIT * chan); + temp = MV_REG_READ(MV64x60_IDMA_0_3_INTR_CAUSE); + error_code = temp & error_mask; + + DEBUG(1, + "completion mask 0x%x error_mask 0x%x cause 0x%x error_code 0x%x\n", + completion_mask, error_mask, temp, error_code); + /* Check channel to be sure interrupt actually occurred */ + if ((MV_REG_READ(MV64x60_IDMA_0_3_INTR_CAUSE) & completion_mask) != 0) { + if (error_code == 0) { + dma_chan_cntl->dma_complete = 0; + } else { + dma_chan_cntl->dma_complete = 1; + } + + /* + * Write out cleared interrupt field to clear the completion + * interrupt for the given channel only. + */ + int_cause &= ~completion_mask; + MV_REG_WRITE_PUSH(MV64x60_IDMA_0_3_INTR_CAUSE, int_cause); + } + wake_up(&dma_chan_cntl->readywait); + return IRQ_HANDLED; +} + +/************************************************************************** +* +* mv64360_dma_err_int_handler - Handle an error interrupt. +* +* This function handles a DMA error interrupt. Since the interrupt is shared +* across all channels, all channels must be checked for an error status by +* examining the error bits in the interrupt cause register. If the error +* code is not zero, dma_complete is set to FALSE and the code is saved for +* that channel. If the error select register matches the error code, the +* error address is also saved for that channel. +* +* After checking all channels, the interrupts are cleared by writing +* zeros to the all of the interrupting channels' error bits in the +* interrupt cause register. Other channel's bits are written as ones +* to preserve their state (writing a one has no effect). +* +* RETURNS: N/A +*/ + +static irqreturn_t +mv64360_dma_err_int_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + u32 chan = 0; + struct mv64360_dma_cntl_t *dma_chan_cntl = NULL; + u32 error_mask = 0; + u32 error_code = 0; + u32 error_chan = 0; + u32 error_cause = 0xFFFFFFFF; + + DEBUG(0, "dma_err_int:\n"); + /* Check each channel error interrupt group */ + for (chan = 0; chan < IDMA_CHANNEL_COUNT; ++chan) { + dma_chan_cntl = &mv64360_dma_cntl[chan]; + error_mask = IDMA_INT_CAUSE_CHAN_MASK << + (IDMA_INT_CAUSE_CHAN1_BIT * chan); + error_code = + MV_REG_READ(MV64x60_IDMA_0_3_INTR_CAUSE) & error_mask; + + /* + * If the error code is not zero record the error status for the + * channel. Save the error address if one is available for the + * given error on the interrupting channel. Bits 3 & 4 of the + * error select code contain the erroring channel number. This + * should match the channel in the interrupt cause register for + * the error address to be meaningful. + */ + if (error_code != 0) { + dma_chan_cntl->dma_complete = 2; + dma_chan_cntl->error_select = + MV_REG_READ(MV64x60_IDMA_0_3_ERROR_SELECT); + error_chan = + (dma_chan_cntl-> + error_select & IDMA_ERROR_SEL_CHAN_MASK) >> + IDMA_ERROR_SEL_CHAN_BIT; + if (chan == error_chan) { + dma_chan_cntl->error_addr = + MV_REG_READ(MV64x60_IDMA_0_3_ERROR_ADDR); + } else { + dma_chan_cntl->error_addr = 0; + } + DEBUG(0, + "dma_err_int: chan 0x%x select 0x%x addr 0x%x\n", + error_chan, dma_chan_cntl->error_select, + dma_chan_cntl->error_addr); + + /* Clear the error interrupt field */ + error_cause &= ~error_mask; + + } + } + + /* Write out cleared interrupt fields to clear the interrupts */ + MV_REG_WRITE_PUSH(MV64x60_IDMA_0_3_INTR_CAUSE, error_cause); + wake_up(&dma_chan_cntl->readywait); + return IRQ_HANDLED; +} + +/****************************************************************************** +* +* mv64360_dma_init - Initialize DMA and attach DMA Interrupt Handler. +* +* This function configures the DMA driver for all available DMA channels. +* The driver tracks information on each channel independently. Each channel +* control structure is set up to allow easy indexing by channel from the +* driver routines. Register defaults are also initialized. +* +* Eight address decoding windows are also configured and enabled +* via this routine. Four are used to cover the DRAM addresses, one per bank. +* If a bank is not enabled, then no window is configured for it. +* Two are used for PCI I/O addresses on each PCI bus. Two are used for PCI +* memory addresses on each PCI bus. An interrupt handler is connected to +* each DMA completion interrupt number. A different handler is connected +* to the DMA error interrupt. This routine must be called once for DMA +* capability to be properly initialized before any other driver routine +* is called. +* +* RETURNS: 0 if initialization succeeded or non-zero if an error occurred. +*/ + +static int mv64360_dma_init(void) +{ + u32 chan = 0; + struct mv64360_dma_cntl_t *dma_chan_cntl = NULL; + u32 dma_cntl_val = 0; + int status = 0; + unsigned int arb_slice_default[] = { + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + }; + + /* Set all unused registers to defaults */ + MV_REG_WRITE_PUSH(MV64360_DMA_HEADERS_RETARGET_CONTROL, 0x00); + MV_REG_WRITE_PUSH(MV64360_DMA_HEADERS_RETARGET_BASE, 0x00); + MV_REG_WRITE_PUSH(MV64x60_IDMA_0_3_XBAR_TO, + IDMA_CROSSBAR_TIMEOUT_PRESET | + IDMA_CROSSBAR_TIMEOUT_DISABLE); + + /* Ensure all interrupts are cleared and windows are disabled */ + MV_REG_WRITE_PUSH(MV64x60_IDMA_0_3_INTR_CAUSE, 0x00); + MV_REG_WRITE_PUSH(MV64x60_IDMA_0_3_INTR_MASK, 0x00); + MV_REG_WRITE_PUSH(MV64360_IDMA2MEM_BAR_ENABLE, + IDMA_BASE_ADDR_ENABLE_WIN_MASK); + dma_cntl_val = + IDMA_CNTL_DBURST_LIMIT_32B | IDMA_CNTL_SBURST_LIMIT_32B | + IDMA_CNTL_BLOCK_MODE | IDMA_CNTL_NON_CHAIN_MODE | + IDMA_CNTL_END_OF_XFER_HALT | IDMA_CNTL_DESC_16MB; + + /* Initialize the DMA control array for all channels */ + while (chan < IDMA_CHANNEL_COUNT && status == 0) { + dma_chan_cntl = &mv64360_dma_cntl[chan]; + dma_chan_cntl->chan = chan; + dma_chan_cntl->byte_count_reg_offset = + MV64360_DMA_CHANNEL0_BYTE_COUNT + (chan * IDMA_REG_SIZE); + dma_chan_cntl->source_addr_reg_offset = + MV64360_DMA_CHANNEL0_SOURCE_ADDR + (chan * IDMA_REG_SIZE); + dma_chan_cntl->dest_reg_offset = + MV64360_DMA_CHANNEL0_DESTINATION_ADDR + + (chan * IDMA_REG_SIZE); + dma_chan_cntl->next_desc_ptr_reg_offset = + MV64360_DMA_CHANNEL0_NEXT_DESCRIPTOR_POINTER + + (chan * IDMA_REG_SIZE); + dma_chan_cntl->curr_desc_ptr_reg_offset = + MV64360_DMA_CHANNEL0_CURRENT_DESCRIPTOR_POINTER + + (chan * IDMA_REG_SIZE); + dma_chan_cntl->chan_cntl_low_reg_offset = + MV64360_DMA_CHANNEL0_CONTROL + (chan * IDMA_REG_SIZE); + dma_chan_cntl->chan_cntl_high_reg_offset = + MV64360_DMA_CHANNEL0_CONTROL_HIGH + (chan * IDMA_REG_SIZE); + dma_chan_cntl->chan_access_prot_offset = + MV64360_DMA_CHANNEL0_ACCESS_PROTECTION_REG + + (chan * IDMA_REG_SIZE); + + /* Clear the error and status information */ + dma_chan_cntl->dma_complete = 0; + dma_chan_cntl->error_select = 0; + dma_chan_cntl->error_addr = 0; + MV_REG_READ(MV64x60_IDMA_0_3_ERROR_ADDR); + MV_REG_READ(MV64x60_IDMA_0_3_ERROR_SELECT); + MV_REG_WRITE_PUSH(MV64x60_IDMA_0_3_ERROR_ADDR, 0); + MV_REG_WRITE_PUSH(MV64x60_IDMA_0_3_ERROR_SELECT, 0); + + /* Initialize the fixed control settings and defaults */ + MV_REG_WRITE_PUSH(dma_chan_cntl-> + chan_cntl_low_reg_offset, dma_cntl_val); + MV_REG_WRITE_PUSH(dma_chan_cntl->chan_cntl_high_reg_offset, + 0x00); + MV_REG_WRITE_PUSH(dma_chan_cntl->chan_access_prot_offset, + IDMA_CHAN_ACCESS_FULL_WIN_ALL); + MV_REG_WRITE_PUSH(dma_chan_cntl->byte_count_reg_offset, 0); + MV_REG_WRITE_PUSH(dma_chan_cntl->source_addr_reg_offset, 0x00); + MV_REG_WRITE_PUSH(dma_chan_cntl->dest_reg_offset, 0x00); + MV_REG_WRITE_PUSH(dma_chan_cntl->curr_desc_ptr_reg_offset, + 0x00); + MV_REG_WRITE_PUSH(dma_chan_cntl->next_desc_ptr_reg_offset, + 0x00); + MV_REG_WRITE_PUSH(MV64360_DMA_HIGH_ADDR_REMAP_REG0 + + (chan * IDMA_REG_SIZE), 0x00); + + /* Connect the same int handler to each interrupt number */ + status = + request_irq(IDMA_CHAN0_COMPLETION_INT + chan, + mv64360_dma_int_handler, SA_INTERRUPT, + "MV64360 IDMA", &mv64360_dma_cntl[chan]); + if (status != 0) { + printk(KERN_ERR + "Cannot get irq for MV64360 DMA channel %d\n", + chan); + return status; + } + ++chan; + } + + /* + * If status is okay, connect the DMA error interrupt and initialize + * the DMA base address decoding windows and arbiter. + */ + if (status == 0) { + status = + request_irq(IDMA_ERROR_INT, + mv64360_dma_err_int_handler, SA_INTERRUPT, + "MV64360 IDMA error", NULL); + if (status != 0) { + printk(KERN_ERR + "Cannot get irq for MV64360_dma_err_int\n"); + return (status); + } + mv64360_init_addr_windows(); + status = mv64360_dma_arbiter_setup(arb_slice_default); + } + is_initialized = (status == 0); + return (status); +} + +/****************************************************************************** +* +* mv64360_dma_start - Configure and start the DMA controller. +* +* This function sets up the DMA controller for a block mode DMA transfer. +* Then interrupts for the given channel are enabled and the transfer +* is initiated. +* +* The user has two options for being notified of the completion of a DMA +* transaction. One is to use a blocking read() on the device; the other is +* to use select(). +* After being notified of completion, an ioctl(MV64360_DMA_STATUS) can be +* used to get additional status information. +* +* RETURNS: +* 0 is returned if the channel started successfully. +* non-zero is returned if the driver is not initialized, or the +* channel is invalid, or the dma_desc reference is null, or the +* channel is already active and busy. +*/ + +static int +mv64360_dma_start(struct mv64360_dma_cntl_t *dma_chan_cntl, + struct dma_descriptor_t *dma_desc) +{ + int chan = dma_chan_cntl->chan; + u32 cntl_reg = 0; + int status = 0; + + if (is_initialized && dma_desc != NULL) { + down(&dma_chan_cntl->dma_available); + + /* Make sure channel is not active and byte count is legal */ + cntl_reg = MV_REG_READ(dma_chan_cntl->chan_cntl_low_reg_offset); + if (!IDMA_CHAN_IS_ACTIVE(cntl_reg) && + dma_chan_cntl->byte_count <= + IDMA_DESC_16MB_BYTE_COUNT_MASK) { + + /* Set the configuration options */ + cntl_reg &= ~IDMA_CNTL_HOLD_SRC_ADDR; + cntl_reg &= ~IDMA_CNTL_HOLD_DEST_ADDR; + + if (dma_chan_cntl->dma_attributes.hold_source_addr) { + cntl_reg |= IDMA_CNTL_HOLD_SRC_ADDR; + } + if (dma_chan_cntl->dma_attributes.hold_dest_addr) { + cntl_reg |= IDMA_CNTL_HOLD_DEST_ADDR; + } + + /* Set the descriptor registers */ + MV_REG_WRITE_PUSH(dma_chan_cntl-> + byte_count_reg_offset, + dma_chan_cntl->byte_count & + IDMA_DESC_16MB_BYTE_COUNT_MASK); + MV_REG_WRITE_PUSH(dma_chan_cntl->source_addr_reg_offset, + dma_desc->source_addr); + MV_REG_WRITE_PUSH(dma_chan_cntl->dest_reg_offset, + dma_desc->dest_addr); + MV_REG_WRITE_PUSH(dma_chan_cntl-> + next_desc_ptr_reg_offset, 0); + MV_REG_WRITE_PUSH(dma_chan_cntl-> + curr_desc_ptr_reg_offset, + (u32) dma_desc); + + dma_chan_cntl->dma_complete = -1; + dma_chan_cntl->error_select = 0; + dma_chan_cntl->error_addr = 0; + + /* Unmask/enable all of the channel's interrupts */ + MV_REG_WRITE_PUSH(MV64x60_IDMA_0_3_INTR_MASK, + MV_REG_READ + (MV64x60_IDMA_0_3_INTR_MASK) | + (IDMA_INT_MASK_CHAN_MASK << + (IDMA_INT_MASK_CHAN1_BIT * chan))); + + /* Start the transfer */ + cntl_reg |= IDMA_CNTL_CHAN_ENABLE; + MV_REG_WRITE_PUSH(dma_chan_cntl-> + chan_cntl_low_reg_offset, cntl_reg); + } else { + status = -1; + } + /* Release the device instance semaphore. */ + up(&dma_chan_cntl->dma_available); + } else { + status = -1; + } + return (status); +} + +/****************************************************************************** +* +* mv64360_dma_status - Read and return DMA status. +* +* For the given channel, provide the following DMA status information: +* +* The saved DMA Error Code Value; +* The saved DMA Error Address associated with the error code; +* DMA Current Source Address Register; +* DMA Current Destination Address Register; +* DMA Current Next Descriptor Register; +* DMA Channel Control Register; +* +* The status information is placed into a DMA status +* structure referenced by dma_status along with a DMA completion status +* summary of either OK or ERROR. +* +* If status is obtained while DMA is in progress, the status +* summary will be ERROR with a zero error code and null error address. +* If DMA status is OK, the DMA transfer completed successfully. If status +* is ERROR with a non-zero error code, the transfer stopped due to the +* indicated error. If available, the offending address for the error +* is also returned. +* +* RETURNS: +* OK is returned if the dma_status is valid. +* ERROR is returned if the driver is not initialized, or the +* channel is invalid or the dma_status reference is null. The +* dma_status contents will not be valid. +*/ + +static int +mv64360_dma_status(struct mv64360_dma_cntl_t *dma_chan_cntl, + struct dma_status_t *dma_status) +{ + int chan; + int status = 0; + + chan = dma_chan_cntl->chan; + if (is_initialized && chan < IDMA_CHANNEL_COUNT && dma_status != NULL) { + dma_status->dma_complete = dma_chan_cntl->dma_complete; + dma_status->dma_error_code = dma_chan_cntl->error_select; + dma_status->dma_error_addr = dma_chan_cntl->error_addr; + dma_status->cur_source_addr = + MV_REG_READ(dma_chan_cntl->source_addr_reg_offset); + dma_status->cur_dest_addr = + MV_REG_READ(dma_chan_cntl->dest_reg_offset); + dma_status->cur_next_desc = + MV_REG_READ(dma_chan_cntl->next_desc_ptr_reg_offset); + dma_status->chan_cntl_low = + MV_REG_READ(dma_chan_cntl->chan_cntl_low_reg_offset); + } else { + status = -1; + } + return (status); +} + +/****************************************************************************** +* +* mv64360_dma_abort - Initiate an abort of the current DMA operation. +* +* For the given valid channel, if the channel is active, the channel's +* abort bit is set in its control register. The function waits for the +* abort to complete before returning. +* +* RETURNS: +* OK is returned if abort succeeded. +* ERROR is returned if the driver is not initialized or the +* channel number is invalid or should the abort fail. +*/ +static int mv64360_dma_abort(struct mv64360_dma_cntl_t *dma_chan_cntl) +{ + int chan; + u32 cntl_reg = 0; + int status = 0; + u32 ms_wait = 2; /* HZ wait for abort time */ + + chan = dma_chan_cntl->chan; + DEBUG(1, "dma_abort: channel %d\n", chan); + if (is_initialized && chan < IDMA_CHANNEL_COUNT) { + down(&dma_chan_cntl->dma_available); + cntl_reg = MV_REG_READ(dma_chan_cntl->chan_cntl_low_reg_offset); + DEBUG(1, "dma_abort: cntl_reg 0x%x\n", cntl_reg); + if ((cntl_reg & IDMA_CNTL_CHAN_ACTIVE_MASK) == + IDMA_CNTL_CHAN_ACTIVE_MASK) { + cntl_reg |= IDMA_CNTL_CHAN_ABORT; + MV_REG_WRITE_PUSH(dma_chan_cntl-> + chan_cntl_low_reg_offset, cntl_reg); + + /* Wait for abort to complete */ + while ((MV_REG_READ + (dma_chan_cntl->chan_cntl_low_reg_offset) & + IDMA_CNTL_CHAN_ABORT) && ms_wait > 0) { + DEBUG(1, "dma_abort: ms_wait %d\n", ms_wait); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + --ms_wait; + } + if (ms_wait == 0) { + /* + * Channel became inactive prior to abort + * command or abort could not complete. + */ + status = -1; + } + } else { + /* Channel not active */ + status = -1; + } + up(&dma_chan_cntl->dma_available); + } else { + /* Driver not initialized or invalid parameter */ + status = -1; + } + DEBUG(1, "dma_abort: status %d\n", status); + return (status); +} + +/****************************************************************************** +* +* mv64360_dma_pause - Initiate a pause of the current DMA operation. +* +* For the given valid channel, if the channel is busy, reset the activate +* bit in the channel's control register to pause the channel. Monitor the +* channel active bit in the channel's control register until it resets. The +* channel will pause after completing the current transfer burst in progress. +* +* RETURNS: +* OK is returned if pause succeeded. +* ERROR is returned if the driver is not initialized, or the channel +* is invalid, or the channel was not active. +*/ +static int mv64360_dma_pause(struct mv64360_dma_cntl_t *dma_chan_cntl) +{ + u32 cntl_reg = 0; + int status = 0; + int chan; + u32 ms_wait = 2; /* HZ wait for abort time */ + + chan = dma_chan_cntl->chan; + DEBUG(1, "dma_pause: channel %d\n", chan); + if (is_initialized && chan < IDMA_CHANNEL_COUNT) { + down(&dma_chan_cntl->dma_available); + cntl_reg = MV_REG_READ(dma_chan_cntl->chan_cntl_low_reg_offset); + + /* If the channel is active, pause the channel */ + if (IDMA_CHAN_IS_ACTIVE(cntl_reg)) { + cntl_reg &= ~IDMA_CNTL_CHAN_ENABLE; + MV_REG_WRITE_PUSH(dma_chan_cntl-> + chan_cntl_low_reg_offset, cntl_reg); + + /* Wait for channel to pause */ + while (IDMA_CHAN_IS_ACTIVE + (MV_REG_READ(dma_chan_cntl-> + chan_cntl_low_reg_offset)) + && ms_wait > 0) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + --ms_wait; + } + if (ms_wait == 0) { + /* Channel did not become inactive */ + status = -1; + } + } else { + /* Channel already stopped */ + status = -1; + } + up(&dma_chan_cntl->dma_available); + } else { + /* Driver not initialized or invalid parameter */ + status = -1; + } + return (status); +} + +/****************************************************************************** +* +* mv64360_dma_resume - Resume a previously paused DMA operation. +* +* For a given valid channel, verify that the channel is not active and that +* there are bytes remaining to transfer (a non-zero byte count). If so, write +* the channel activate bit out to the channel's control register. The +* channel will continue the transfer. +* +* RETURNS: +* OK is returned if the resume succeeded. +* ERROR is returned if the driver is not initialized, or the channel +* is invalid, or the channel is not paused (i.e. inactive with a +* a non-zero byte count descriptor register). +*/ +static int mv64360_dma_resume(struct mv64360_dma_cntl_t *dma_chan_cntl) +{ + u32 cntl_reg = 0; + u32 byte_count = 0; + int chan; + int status = 0; + + chan = dma_chan_cntl->chan; + DEBUG(1, "dma_resume channel %d\n", chan); + if (is_initialized && chan < IDMA_CHANNEL_COUNT) { + down(&dma_chan_cntl->dma_available); + cntl_reg = MV_REG_READ(dma_chan_cntl->chan_cntl_low_reg_offset); + byte_count = MV_REG_READ(dma_chan_cntl->byte_count_reg_offset); + + /* If the channel is not active and bytes remain for transfer, + resume the channel */ + if (!IDMA_CHAN_IS_ACTIVE(cntl_reg) && byte_count > 0) { + cntl_reg |= IDMA_CNTL_CHAN_ENABLE; + MV_REG_WRITE_PUSH(dma_chan_cntl-> + chan_cntl_low_reg_offset, cntl_reg); + } else { + status = -1; + } + up(&dma_chan_cntl->dma_available); + } else { + status = -1; + } + return (status); +} + +/****************************************************************************** +* +* mv64360_dma_arbiter_setup - Custom program channel arbitration weighting. +* +* This function accepts an array of IDMA_ARBITER_SLICE_COUNT elements. Each +* element represents an arbiter time slice. The value of each element is a +* DMA channel number assigned to the slice. The default arbiter configuration +* provides equal weighting to all channels at reset. The default arbSlice +* array of channel numbers looks like this: +* +* arb_slice_default[] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 } +* +* Replacing channel numbers provides a custom weighting. Those channels +* that occupy more slices receive proportionately more running time when other +* channels are active simultaneously. A null array reference will have no +* effect and results in an ERROR return status. If a channel number is not +* a valid channel an ERROR status is returned with no action taken. +* +* RETURNS: +* OK when arbiter has been successfully programmed. +* Error if arbSlice array is null or any channel is invalid. +*/ + +static int mv64360_dma_arbiter_setup(unsigned int *arb_slice) +{ + u32 slice = 0; + u32 arb_cntl = 0; + int status = 0; + + if (arb_slice != NULL) { + + /* Validate the channel number in each entry slice */ + while (status == 0 && slice < IDMA_ARBITER_SLICE_COUNT) { + if (arb_slice[slice] < IDMA_CHANNEL_COUNT) { + ++slice; + } else { + status = -1; + } + } + + /* Program the arbiter */ + if (status == 0) { + for (slice = 0; slice < IDMA_ARBITER_SLICE_COUNT; + ++slice) { + arb_cntl |= (arb_slice[slice] & + IDMA_ARBITER_SLICE_MASK) << + (slice * IDMA_ARBITER_1_BIT); + } + MV_REG_WRITE_PUSH(MV64x60_IDMA_0_3_ARBITER_CNTL, + arb_cntl); + } + } else { + status = -1; + } + return (status); +} + +static unsigned int mv64360_dma_poll(struct file *file, poll_table * wait) +{ + unsigned int retval = 0; + struct mv64360_dma_cntl_t *p; + + p = file->private_data; + if (!p) + return 0; + + poll_wait(file, &p->readywait, wait); + + if (p->dma_complete >= 0) + retval = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM; + + return retval; +} + +static int mv64360_dma_open(struct inode *inode, struct file *file) +{ + unsigned int minor = MINOR(inode->i_rdev); + struct mv64360_dma_cntl_t *p; + + DEBUG(1, "open minor %d\n", minor); + if (minor >= IDMA_CHANNEL_COUNT) + return -ENODEV; + + if (dma_device_open[minor]) + return -EBUSY; + dma_device_open[minor]++; + + file->private_data = &mv64360_dma_cntl[minor]; + p = file->private_data; + p->dma_src_buffer = NULL; + p->dma_dest_buffer = NULL; + p->dma_complete = 0; + p->error_select = 0; + p->error_addr = 0; + p->dma_buffer_npages = 0; + p->dma_buffer_size = 0; + p->byte_count = 0; + p->dma_attributes.flags = 0; + p->dma_attributes.hold_source_addr = 0; + p->dma_attributes.hold_dest_addr = 0; + p->dma_timer_pending = 0; + init_MUTEX(&p->dma_available); + init_waitqueue_head(&p->readywait); + DEBUG(2, "open: device open count %d\n", dma_device_open[minor]); + return 0; +} + +static int mv64360_dma_release(struct inode *inode, struct file *file) +{ + unsigned int minor = MINOR(inode->i_rdev); + struct mv64360_dma_cntl_t *p; + struct page *page, *pend; + int retval = 0; + + DEBUG(1, "release minor %d\n", minor); + if (minor >= IDMA_CHANNEL_COUNT) { + printk(KERN_ERR + "mv64360_dma: unknown device (minor %d) closed\n", + minor); + retval = -ENODEV; + } + p = file->private_data; + if (p->dma_src_buffer) { + if (p->dma_attributes.flags != FIXED_SOURCE) { + pend = + virt_to_page(p->dma_src_buffer + + p->dma_buffer_size - 1); + for (page = virt_to_page(p->dma_src_buffer); + page <= pend; page++) + ClearPageReserved(page); +#ifdef CONFIG_BIGPHYS_AREA + bigphysarea_free_pages((caddr_t) (p->dma_src_buffer)); +#else + pci_free_consistent(NULL, p->dma_buffer_size, + p->dma_src_buffer, + p->dma_src_handle); +#endif + } + p->dma_src_buffer = NULL; + } + if (p->dma_dest_buffer) { + if (p->dma_attributes.flags != FIXED_DESTINATION) { + pend = + virt_to_page(p->dma_dest_buffer + + p->dma_buffer_size - 1); + for (page = virt_to_page(p->dma_dest_buffer); + page <= pend; page++) + ClearPageReserved(page); +#ifdef CONFIG_BIGPHYS_AREA + bigphysarea_free_pages((caddr_t) (p->dma_dest_buffer)); +#else + pci_free_consistent(NULL, p->dma_buffer_size, + p->dma_dest_buffer, + p->dma_dest_handle); +#endif + } + p->dma_dest_buffer = NULL; + } + file->private_data = NULL; + dma_device_open[minor]--; + DEBUG(2, "close: device open count %d\n", dma_device_open[minor]); + return (retval); +} + +static ssize_t +mv64360_dma_read(struct file *file, char *buf, size_t count, loff_t * ppos) +{ + int retval = 0; + struct mv64360_dma_cntl_t *p; + int data; + unsigned long flags; + DECLARE_WAITQUEUE(wait, current); + + p = file->private_data; + if (!p) + return -EINVAL; + add_wait_queue(&p->readywait, &wait); + + spin_lock_irqsave(&p->dma_lock, flags); + data = p->dma_complete; + spin_unlock_irqrestore(&p->dma_lock, flags); + while (data < 0) { + set_current_state(TASK_INTERRUPTIBLE); + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + break; + } + if (signal_pending(current)) { + retval = -EINTR; + break; + } + schedule(); + spin_lock_irqsave(&p->dma_lock, flags); + data = p->dma_complete; + spin_unlock_irqrestore(&p->dma_lock, flags); + } + remove_wait_queue(&p->readywait, &wait); + set_current_state(TASK_RUNNING); + if (retval == 0) { + int status; + + status = data; + copy_to_user(buf, &status, sizeof(status)); + retval = sizeof(status); + } + DEBUG(1, "read: retval 0x%x\n", retval); + return retval; +} + +static ssize_t +mv64360_dma_write(struct file *file, const char *buf, size_t count, + loff_t * ppos) +{ + return 0; +} + +static int mv64360_dma_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned long offset; + struct mv64360_dma_cntl_t *p; + int retval; + + DEBUG(1, "mmap: minor %d\n", MINOR(file->f_dentry->d_inode->i_rdev)); + + if ((!file) || (!vma)) + return -ENXIO; + if (vma->vm_pgoff) + return -EINVAL; /* want no offset */ + + p = file->private_data; + if (!p) + return -EINVAL; + + if ((p->dma_attributes.flags == 0) || + (p->dma_src_buffer == NULL) || (p->dma_dest_buffer == NULL)) + return -EINVAL; + + if (vma->vm_end - vma->vm_start > p->dma_buffer_size) { + /* An attempt to map beyond the end of the buffer */ + printk(KERN_ERR + "mv64360_dma_mmap: INVALID. " + "Start at 0x%08lx end 0x%08lx\n", + vma->vm_start, vma->vm_end); + return (-EINVAL); + } + + if (p->dma_attributes.flags == FIXED_DESTINATION) { + offset = virt_to_phys(p->dma_src_buffer); + } else { + offset = virt_to_phys(p->dma_dest_buffer); + } + + retval = io_remap_pfn_range(vma, + vma->vm_start, + offset >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + DEBUG(1, "mmap: start 0x%lx end 0x%lx offset 0x%lx\n", + vma->vm_start, vma->vm_end, offset); + if (retval) { + printk(KERN_WARNING "mv64360_mmap: remap_pfn_range failed"); + return (-EAGAIN); + } + return 0; +} + +static int +mv64360_dma_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + unsigned int minor = MINOR(inode->i_rdev); + int retval; + struct mv64360_dma_cntl_t *p; + + DEBUG(1, "ioctl(%x, %lx)\n", cmd, arg); + if (minor >= IDMA_CHANNEL_COUNT) { + printk(KERN_ERR + "mv64360_dma: unknown device (minor %d) ioctl\n", minor); + return -ENODEV; + } + + /* Permission check */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + p = file->private_data; + switch (cmd) { + case MV64360_DMA_SETUP: + { + struct dma_setup_t dma_setup; + int needed_pages; + struct page *page, *pend; + + copy_from_user(&dma_setup, + (char *)arg, sizeof(dma_setup)); + /* Argument check */ + if ((dma_setup.dma_descriptor.source_addr == 0) && + (dma_setup.dma_descriptor.dest_addr == 0)) { + DEBUG(0, + "dma setup invalid 1: source addr 0x%x dest addr 0x%x\n", + dma_setup.dma_descriptor.source_addr, + dma_setup.dma_descriptor.dest_addr); + return -EINVAL; + } + if ((dma_setup.dma_descriptor.source_addr != 0) && + (dma_setup.dma_descriptor.dest_addr != 0)) { + DEBUG(0, + "dma setup invalid 2: source addr 0x%x dest addr 0x%x\n", + dma_setup.dma_descriptor.source_addr, + dma_setup.dma_descriptor.dest_addr); + return -EINVAL; + } + if ((dma_setup.dma_descriptor.dest_addr != 0) && + (dma_setup.dma_descriptor.source_addr != 0)) { + DEBUG(0, + "dma setup invalid 3: source addr 0x%x dest addr 0x%x\n", + dma_setup.dma_descriptor.source_addr, + dma_setup.dma_descriptor.dest_addr); + return -EINVAL; + } + if (dma_setup.dma_descriptor.byte_count <= 0) { + DEBUG(0, + "dma setup invalid 4: source addr 0x%x dest addr 0x%x\n", + dma_setup.dma_descriptor.source_addr, + dma_setup.dma_descriptor.dest_addr); + return -EINVAL; + } + p->byte_count = dma_setup.dma_descriptor.byte_count; + needed_pages = ((p->byte_count - 1) / PAGE_SIZE) + 1; + if (dma_setup.dma_descriptor.dest_addr != 0) { + /* Dest address specified => alloc source buffer */ + if (dma_setup.dma_descriptor.dest_addr <= + __pa(high_memory)) { + DEBUG(0, + "dma setup invalid 5: source addr 0x%x dest addr 0x%x\n", + dma_setup.dma_descriptor. + source_addr, + dma_setup.dma_descriptor. + dest_addr); + return -EINVAL; + } + if (p->dma_src_buffer) { + if (needed_pages != + p->dma_buffer_npages) { + /* Mismatch; allocate new */ + pend = + virt_to_page(p-> + dma_src_buffer + + + (needed_pages * + PAGE_SIZE) - + 1); + for (page = + virt_to_page(p-> + dma_src_buffer); + page <= pend; page++) + ClearPageReserved(page); +#ifdef CONFIG_BIGPHYS_AREA + bigphysarea_free_pages((caddr_t) + (p-> + dma_src_buffer)); + p->dma_src_buffer = (char *) + bigphysarea_alloc_pages + (needed_pages, 0, + GFP_KERNEL); +#else + pci_free_consistent(NULL, + needed_pages + * PAGE_SIZE, + p-> + dma_src_buffer, + p-> + dma_src_handle); + if (! + (p->dma_src_buffer = + (char *) + pci_alloc_consistent(NULL, + needed_pages + * + PAGE_SIZE, + &p-> + dma_src_handle))) + return -ENOMEM; +#endif + } + } else { +#ifdef CONFIG_BIGPHYS_AREA + p->dma_src_buffer = + (char *)bigphysarea_alloc_pages + (needed_pages, 0, GFP_KERNEL); +#else + if (!(p->dma_src_buffer = + (char *)pci_alloc_consistent + (NULL, needed_pages * PAGE_SIZE, + &p->dma_src_handle))) + return -ENOMEM; +#endif + } + pend = + virt_to_page(p->dma_src_buffer + + (needed_pages * PAGE_SIZE) - + 1); + for (page = virt_to_page(p->dma_src_buffer); + page <= pend; page++) + SetPageReserved(page); + + p->dma_dest_buffer = + (char *)dma_setup.dma_descriptor.dest_addr; + p->dma_attributes.flags = FIXED_DESTINATION; + } else { + /* Source address specified => alloc dest buffer */ + if (dma_setup.dma_descriptor.source_addr <= + __pa(high_memory)) { + DEBUG(0, + "dma setup invalid 6: source addr 0x%x dest addr 0x%x\n", + dma_setup.dma_descriptor. + source_addr, + dma_setup.dma_descriptor. + dest_addr); + return -EINVAL; + } + if (p->dma_dest_buffer) { + if (needed_pages != + p->dma_buffer_npages) { + /* Mismatch; allocate new */ + pend = + virt_to_page(p-> + dma_dest_buffer + + + (needed_pages * + PAGE_SIZE) - + 1); + for (page = + virt_to_page(p-> + dma_dest_buffer); + page <= pend; page++) + ClearPageReserved(page); +#ifdef CONFIG_BIGPHYS_AREA + bigphysarea_free_pages((caddr_t) + (p-> + dma_dest_buffer)); + p->dma_dest_buffer = (char *) + bigphysarea_alloc_pages + (needed_pages, 0, + GFP_KERNEL); +#else + pci_free_consistent(NULL, + needed_pages + * PAGE_SIZE, + p-> + dma_dest_buffer, + p-> + dma_dest_handle); + if (! + (p->dma_dest_buffer = + (char *) + pci_alloc_consistent(NULL, + needed_pages + * + PAGE_SIZE, + &p-> + dma_dest_handle))) + return -ENOMEM; +#endif + } + } else { +#ifdef CONFIG_BIGPHYS_AREA + p->dma_dest_buffer = + (char *)bigphysarea_alloc_pages + (needed_pages, 0, GFP_KERNEL); +#else + if (!(p->dma_dest_buffer = + (char *)pci_alloc_consistent + (NULL, needed_pages * PAGE_SIZE, + &p->dma_dest_handle))) + return -ENOMEM; +#endif + } + pend = + virt_to_page(p->dma_dest_buffer + + (needed_pages * PAGE_SIZE) - + 1); + for (page = virt_to_page(p->dma_dest_buffer); + page <= pend; page++) + SetPageReserved(page); + p->dma_src_buffer = + (char *)dma_setup.dma_descriptor. + source_addr; + p->dma_attributes.flags = FIXED_SOURCE; + } + p->dma_buffer_npages = needed_pages; + p->dma_buffer_size = PAGE_SIZE * needed_pages; + if ((p->dma_src_buffer == NULL) + || (p->dma_dest_buffer == NULL)) { + p->byte_count = 0; + p->dma_buffer_size = 0; + return -ENOMEM; + } + + DEBUG(1, + "setup: src 0x%p dest 0x%p count 0x%x pages 0x%x\n", + p->dma_src_buffer, p->dma_dest_buffer, + p->byte_count, needed_pages); + + p->dma_attributes.hold_source_addr = + dma_setup.dma_attributes.hold_source_addr; + p->dma_attributes.hold_dest_addr = + dma_setup.dma_attributes.hold_dest_addr; + + break; + } + + case MV64360_DMA_START: + { + struct dma_descriptor_t dma_descriptor; + + /* Check whether setup is complete */ + if ((p->byte_count == 0) || + (p->dma_src_buffer == NULL) || + (p->dma_dest_buffer == NULL)) + return -EINVAL; + + dma_descriptor.byte_count = p->byte_count; + if (p->dma_attributes.flags == FIXED_SOURCE) { + dma_descriptor.source_addr = + (unsigned int)p->dma_src_buffer; + } else { +#ifdef CONFIG_BIGPHYS_AREA + dma_descriptor.source_addr = + (unsigned + int)(virt_to_phys(p->dma_src_buffer)); +#else + dma_descriptor.source_addr = p->dma_src_handle; +#endif + } + if (p->dma_attributes.flags == FIXED_DESTINATION) { + dma_descriptor.dest_addr = + (unsigned int)p->dma_dest_buffer; + } else { +#ifdef CONFIG_BIGPHYS_AREA + dma_descriptor.dest_addr = + (unsigned + int)(virt_to_phys(p->dma_dest_buffer)); +#else + dma_descriptor.dest_addr = p->dma_dest_handle; +#endif + } + DEBUG(1, "dma_start: src 0x%x dest 0x%x count 0x%x\n", + dma_descriptor.source_addr, + dma_descriptor.dest_addr, + dma_descriptor.byte_count); + + retval = mv64360_dma_start(p, &dma_descriptor); + + return (retval); + break; + } + case MV64360_DMA_ABORT: + { + retval = mv64360_dma_abort(p); + return (retval); + break; + } + case MV64360_DMA_STATUS: + { + struct dma_status_t dma_status; + + mv64360_dma_status(p, &dma_status); + copy_to_user((char *)arg, &dma_status, + sizeof(dma_status)); + break; + } + case MV64360_DMA_PAUSE: + { + retval = mv64360_dma_pause(p); + return (retval); + break; + } + case MV64360_DMA_RESUME: + { + retval = mv64360_dma_resume(p); + return (retval); + break; + } + case MV64360_DMA_ARBITER_SETUP: + { + struct dma_arbiter_setup_t dma_arbiter; + + copy_from_user(&dma_arbiter, + (char *)arg, sizeof(dma_arbiter)); + retval = mv64360_dma_arbiter_setup((unsigned int *) + &dma_arbiter.values); + return (retval); + break; + } + default: + return -EINVAL; + break; + } + return 0; + +} /* mv64360_dma_ioctl */ + +static struct file_operations mv64360_dma_fops = { + .owner = THIS_MODULE, + .open = mv64360_dma_open, + .release = mv64360_dma_release, + .read = mv64360_dma_read, + .write = mv64360_dma_write, + .mmap = mv64360_dma_mmap, + .ioctl = mv64360_dma_ioctl, + .poll = mv64360_dma_poll, +}; + +static int __init mv64360_dma_init_module(void) +{ + int status; + + printk(KERN_INFO DRV_NAME " version " DRV_VERSION "\n"); + + mv64360_base = (unsigned int)ioremap(mv64360_reg_base, 0x10000); + + /* Set up character device for user mode clients */ + major_dev = register_chrdev(0, "mv64360_dma", &mv64360_dma_fops); + if (major_dev == 0) { + printk(KERN_NOTICE + "mv64360_dma: Unable to find a free device # for " + "the MV64360 IDMA driver\n"); + iounmap((void *)mv64360_base); + return -1; + + } + status = mv64360_dma_init(); + + if (status != 0) + return -ENODEV; + + mv64360_dma_class = class_create(THIS_MODULE, "mv64360_dma"); + class_device_create(mv64360_dma_class, MKDEV(major_dev, 0), NULL, + "mv64360_dma_0"); + devfs_mk_cdev(MKDEV(major_dev, 0), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "mv64360_dma_0"); + + class_device_create(mv64360_dma_class, MKDEV(major_dev, 1), NULL, + "mv64360_dma_1"); + devfs_mk_cdev(MKDEV(major_dev, 1), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "mv64360_dma_1"); + + class_device_create(mv64360_dma_class, MKDEV(major_dev, 2), NULL, + "mv64360_dma_2"); + devfs_mk_cdev(MKDEV(major_dev, 2), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "mv64360_dma_2"); + + class_device_create(mv64360_dma_class, MKDEV(major_dev, 3), NULL, + "mv64360_dma_3"); + devfs_mk_cdev(MKDEV(major_dev, 3), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "mv64360_dma_3"); + + return 0; + +} /* mv64360_dma_init_module */ + +static void __exit mv64360_dma_cleanup_module(void) +{ + int chan; + + DEBUG(0, "exiting\n"); + + free_irq(IDMA_ERROR_INT, NULL); + for (chan = 0; chan < IDMA_CHANNEL_COUNT; chan++) { + free_irq(IDMA_CHAN0_COMPLETION_INT + chan, + &mv64360_dma_cntl[chan]); + } + + unregister_chrdev(major_dev, "mv64360_dma"); + iounmap((void *)mv64360_base); + + devfs_remove("mv64360_dma_0"); + class_device_destroy(mv64360_dma_class, MKDEV(major_dev, 0)); + + devfs_remove("mv64360_dma_1"); + class_device_destroy(mv64360_dma_class, MKDEV(major_dev, 1)); + + devfs_remove("mv64360_dma_2"); + class_device_destroy(mv64360_dma_class, MKDEV(major_dev, 2)); + + devfs_remove("mv64360_dma_3"); + class_device_destroy(mv64360_dma_class, MKDEV(major_dev, 3)); + + class_destroy(mv64360_dma_class); +} /* mv64360_dma_cleanup_module */ + +module_init(mv64360_dma_init_module); +module_exit(mv64360_dma_cleanup_module); + +MODULE_AUTHOR("Ajit Prem"); +MODULE_DESCRIPTION("Driver for the Marvell MV64360 IDMA controller"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(version); diff -u --new-file --recursive linux-2.6.14.orig/drivers/misc/mv64360_idma/mv64360_dma.h linux-2.6.14.mod/drivers/misc/mv64360_idma/mv64360_dma.h --- linux-2.6.14.orig/drivers/misc/mv64360_idma/mv64360_dma.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/misc/mv64360_idma/mv64360_dma.h 2006-03-07 16:29:10.000000000 -0700 @@ -0,0 +1,473 @@ +/* + +mv64360_dma.h + +DESCRIPTION +This file contains the MV64360 DMA register bit definitions, masks, and +typical values. Register offsets are defined in the main MV64360 header file. + +*/ + +#ifndef __MV64360_DMA_H +#define __MV64360_DMA_H + +/* Maximum counts */ + +#define IDMA_CHANNEL_COUNT 4 +#define IDMA_ARBITER_SLICE_COUNT 16 + +/* Main Interrupt Cause definitions for DMA */ + +#define IDMA_ERROR_INT 2 + +#define IDMA_CHAN0_COMPLETION_INT 4 +#define IDMA_CHAN1_COMPLETION_INT 5 +#define IDMA_CHAN2_COMPLETION_INT 6 +#define IDMA_CHAN3_COMPLETION_INT 7 + +/* + * IDMA Base Address Register Bit Definitions. + * + * Note that the same attribute bits have different meanings based + * on the target bit values. + */ + +#define IDMA_BASE_ADDR_TARGET_MASK 0x0000000F +#define IDMA_BASE_ADDR_TARGET_BIT 0x0 + +#define IDMA_BASE_ADDR_TARGET_DRAM 0x0 +#define IDMA_BASE_ADDR_TARGET_DEVICE 0x1 +#define IDMA_BASE_ADDR_TARGET_SRAM 0x2 +#define IDMA_BASE_ADDR_TARGET_60X 0x2 +#define IDMA_BASE_ADDR_TARGET_PCI0 0x3 +#define IDMA_BASE_ADDR_TARGET_PCI1 0x4 + +#define IDMA_BASE_ADDR_ATTRIBUTE_BIT 8 +#define IDMA_BASE_ADDR_ATTRIBUTE_MASK (0xFF << IDMA_BASE_ADDR_ATTRIBUTE_BIT) + +#define IDMA_BASE_ADDR_DRAM_BANK_BIT IDMA_BASE_ADDR_ATTRIBUTE_BIT +#define IDMA_BASE_ADDR_DRAM_BANK_MASK (0xF << IDMA_BASE_ADDR_DRAM_BANK_BIT) + +#define IDMA_BASE_ADDR_DRAM_BANK_CS0 (0xE << IDMA_BASE_ADDR_DRAM_BANK_BIT) +#define IDMA_BASE_ADDR_DRAM_BANK_CS1 (0xD << IDMA_BASE_ADDR_DRAM_BANK_BIT) +#define IDMA_BASE_ADDR_DRAM_BANK_CS2 (0xB << IDMA_BASE_ADDR_DRAM_BANK_BIT) +#define IDMA_BASE_ADDR_DRAM_BANK_CS3 (0x7 << IDMA_BASE_ADDR_DRAM_BANK_BIT) + +#define IDMA_BASE_ADDR_COHERNECY_BIT 12 +#define IDMA_BASE_ADDR_COHERENCY_MASK (0x3 << IDMA_BASE_ADDR_COHERNECY_BIT) + +#define IDMA_BASE_ADDR_COHERENCY_WT (0x1 << IDMA_BASE_ADDR_COHERNECY_BIT) +#define IDMA_BASE_ADDR_COHERENCY_WB (0x2 << IDMA_BASE_ADDR_COHERNECY_BIT) +#define IDMA_BASE_ADDR_COHERENCY_NONE (~IDMA_BASE_ADDR_COHERENCY_MASK) + +#define IDMA_BASE_ADDR_DEVICE_BUS_BIT IDMA_BASE_ADDR_ATTRIBUTE_BIT +#define IDMA_BASE_ADDR_DEVICE_BUS_MASK (0x1F << IDMA_BASE_ADDR_DEVICE_BUS_BIT) + +#define IDMA_BASE_ADDR_DEVICE_CS0 (0x1E << IDMA_BASE_ADDR_DEVICE_BUS_BIT) +#define IDMA_BASE_ADDR_DEVICE_CS1 (0x1D << IDMA_BASE_ADDR_DEVICE_BUS_BIT) +#define IDMA_BASE_ADDR_DEVICE_CS2 (0x1B << IDMA_BASE_ADDR_DEVICE_BUS_BIT) +#define IDMA_BASE_ADDR_DEVICE_CS3 (0x17 << IDMA_BASE_ADDR_DEVICE_BUS_BIT) +#define IDMA_BASE_ADDR_BOOT_CS (0x0F << IDMA_BASE_ADDR_DEVICE_BUS_BIT) + +#define IDMA_BASE_ADDR_PCI_SWAP_BIT IDMA_BASE_ADDR_ATTRIBUTE_BIT +#define IDMA_BASE_ADDR_PCI_SWAP_MASK (0x3 << IDMA_BASE_ADDR_PCI_SWAP_BIT) + +#define IDMA_BASE_ADDR_PCI_BYTE_SWAP (~IDMA_BASE_ADDR_PCI_SWAP_MASK) +#define IDMA_BASE_ADDR_PCI_NO_SWAP (0x1 << IDMA_BASE_ADDR_PCI_SWAP_BIT) +#define IDMA_BASE_ADDR_PCI_ALL_SWAP (0x2 << IDMA_BASE_ADDR_PCI_SWAP_BIT) +#define IDMA_BASE_ADDR_PCI_WORD_SWAP (0x3 << IDMA_BASE_ADDR_PCI_SWAP_BIT) + +#define IDMA_BASE_ADDR_PCIX_NS_BIT 10 +#define IDMA_BASE_ADDR_PCIX_NO_SNOOP (0x1 << IDMA_BASE_ADDR_PCIX_NS_BIT) + +#define IDMA_BASE_ADDR_PCI_IO_MEM_BIT 11 +#define IDMA_BASE_ADDR_PCI_MEM_SEL (0x1 << IDMA_BASE_ADDR_PCI_IO_MEM_BIT) + +#define IDMA_BASE_ADDR_PCI_REQ64_BIT 12 +#define IDMA_BASE_ADDR_PCI_REQ64_SIZE (0x1 << IDMA_BASE_ADDR_PCI_REQ64_BIT) + +#define IDMA_BASE_ADDR_SRAM_60X_BIT 11 +#define IDMA_BASE_ADDR_60X_SEL (0x1 << IDMA_BASE_ADDR_SRAM_60X_BIT) + +#define IDMA_BASE_ADDR_BASE_BIT 16 +#define IDMA_BASE_ADDR_BASE_MASK (0xFFFF << IDMA_BASE_ADDR_BASE_BIT) +#define IDMA_CPUIF_ADDR_SHIFT_INDEX IDMA_BASE_ADDR_BASE_BIT + +/* IDMA Window Size Register Encoding Values */ + +#define IDMA_WINDOW_SIZE_BIT 16 +#define IDMA_WINDOW_SIZE_MASK (0xFFFF << IDMA_WINDOW_SIZE_BIT) + +#define IDMA_WINDOW_SIZE_64KB (~IDMA_WINDOW_SIZE_MASK) +#define IDMA_WINDOW_SIZE_128KB (0x1 << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_256KB (0x3 << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_512KB (0x7 << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_1MB (0xF << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_2MB (0x1F << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_4MB (0x3F << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_8MB (0x7F << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_16MB (0xFF << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_32MB (0x1FF << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_64MB (0x3FF << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_128MB (0x7FF << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_256MB (0xFFF << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_512MB (0x1FFF << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_1GB (0x3FFF << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_2GB (0x7FFF << IDMA_WINDOW_SIZE_BIT) +#define IDMA_WINDOW_SIZE_4GB (0xFFFF << IDMA_WINDOW_SIZE_BIT) + +/* IDMA Base Address Window Enable Register */ + +#define IDMA_BASE_ADDR_ENABLE_WIN_MASK 0xFF + +#define IDMA_BASE_ADDR_ENABLE_WIN0 0x01 +#define IDMA_BASE_ADDR_ENABLE_WIN1 0x02 +#define IDMA_BASE_ADDR_ENABLE_WIN2 0x04 +#define IDMA_BASE_ADDR_ENABLE_WIN3 0x08 +#define IDMA_BASE_ADDR_ENABLE_WIN4 0x10 +#define IDMA_BASE_ADDR_ENABLE_WIN5 0x20 +#define IDMA_BASE_ADDR_ENABLE_WIN6 0x40 +#define IDMA_BASE_ADDR_ENABLE_WIN7 0x80 + +/* IDMA Channel Access Protect Register */ + +#define IDMA_CHAN_ACCESS_PROT_MASK 0x3 +#define IDMA_CHAN_ACCESS_PROT_WIN0_BIT 0x0 +#define IDMA_CHAN_ACCESS_PROT_WIN1_BIT 0x2 +#define IDMA_CHAN_ACCESS_PROT_WIN2_BIT 0x4 +#define IDMA_CHAN_ACCESS_PROT_WIN3_BIT 0x6 +#define IDMA_CHAN_ACCESS_PROT_WIN4_BIT 0x8 +#define IDMA_CHAN_ACCESS_PROT_WIN5_BIT 0x10 +#define IDMA_CHAN_ACCESS_PROT_WIN6_BIT 0x12 +#define IDMA_CHAN_ACCESS_PROT_WIN7_BIT 0x14 + +#define IDMA_CHAN_ACCESS_NOT_ALLOWED 0x0 +#define IDMA_CHAN_ACCESS_READ_ONLY 0x1 +#define IDMA_CHAN_ACCESS_FULL 0x3 + +#define IDMA_CHAN_ACCESS_NONE_WIN_ALL 0x00000000 +#define IDMA_CHAN_ACCESS_READ_WIN_ALL 0x00005555 +#define IDMA_CHAN_ACCESS_FULL_WIN_ALL 0x0000FFFF + +/* IDMA Headers Retarget Control Register */ + +#define IDMA_HEADER_RETARGET_ENABLE 0x01 + +#define IDMA_HEADER_RETARGET_BUF_BIT 1 +#define IDMA_HEADER_RETARGET_BUF_MASK (0x7 << IDMA_HEADER_RETARGET_BUF_BIT) + +#define IDMA_HEADER_RETARGET_BUF_256B (~IDMA_HEADER_RETARGET_BUF_MASK) +#define IDMA_HEADER_RETARGET_BUF_512B (0x1 << IDMA_HEADER_RETARGET_BUF_BIT) +#define IDMA_HEADER_RETARGET_BUF_1KB (0x2 << IDMA_HEADER_RETARGET_BUF_BIT) +#define IDMA_HEADER_RETARGET_BUF_2KB (0x3 << IDMA_HEADER_RETARGET_BUF_BIT) +#define IDMA_HEADER_RETARGET_BUF_4KB (0x4 << IDMA_HEADER_RETARGET_BUF_BIT) +#define IDMA_HEADER_RETARGET_BUF_8KB (0x5 << IDMA_HEADER_RETARGET_BUF_BIT) + +#define IDMA_HEADER_RETARGET_MASK_BIT 16 +#define IDMA_HEADER_RETARGET_MASK1 (0xFFFF << IDMA_HEADER_RETARGET_MASK1_BIT) + +#define IDMA_RETARGET_TOTAL_64KB (~IDMA_HEADER_RETARGET_MASK1) +#define IDMA_RETARGET_TOTAL_128KB (0x1 << IDMA_HEADER_RETARGET_MASK1_BIT) +#define IDMA_RETARGET_TOTAL_256KB (0x3 << IDMA_HEADER_RETARGET_MASK1_BIT) +#define IDMA_RETARGET_TOTAL_512KB (0x7 << IDMA_HEADER_RETARGET_MASK1_BIT) +#define IDMA_RETARGET_TOTAL_1MB (0xF << IDMA_HEADER_RETARGET_MASK1_BIT) +#define IDMA_RETARGET_TOTAL_2MB (0x1F << IDMA_HEADER_RETARGET_MASK1_BIT) +#define IDMA_RETARGET_TOTAL_4MB (0x3F << IDMA_HEADER_RETARGET_MASK1_BIT) +#define IDMA_RETARGET_TOTAL_8MB (0x7F << IDMA_HEADER_RETARGET_MASK1_BIT) +#define IDMA_RETARGET_TOTAL_16MB (0xFF << IDMA_HEADER_RETARGET_MASK1_BIT) +#define IDMA_RETARGET_TOTAL_32MB (0x1FF << IDMA_HEADER_RETARGET_MASK1_BIT) +#define IDMA_RETARGET_TOTAL_64MB (0x3FF << IDMA_HEADER_RETARGET_MASK1_BIT) +#define IDMA_RETARGET_TOTAL_128MB (0x7FF << IDMA_HEADER_RETARGET_MASK1_BIT) +#define IDMA_RETARGET_TOTAL_256MB (0xFFF << IDMA_HEADER_RETARGET_MASK1_BIT) + +#define IDMA_HEADER_RETARGET_BASE_BIT 16 +#define IDMA_HEADER_RETARGET_BASE_MASK (0xFFFF << IDMA_HEADER_RETARGET_BASE_BIT) + +/* IDMA Channel Control Register (lower) */ + +#define IDMA_CNTL_DBURST_LIMIT_MASK 0x7 + +#define IDMA_CNTL_DBURST_LIMIT_8B 0x0 +#define IDMA_CNTL_DBURST_LIMIT_16B 0x1 +#define IDMA_CNTL_DBURST_LIMIT_32B 0x3 +#define IDMA_CNTL_DBURST_LIMIT_64B 0x7 +#define IDMA_CNTL_DBURST_LIMIT_128B 0x4 + +#define IDMA_CNTL_HOLD_SRC_ADDR_BIT 3 +#define IDMA_CNTL_HOLD_SRC_ADDR (0x01 << IDMA_CNTL_HOLD_SRC_ADDR_BIT) + +#define IDMA_CNTL_DMA_ACK_WIDTH_BIT 4 +#define IDMA_CNTL_DMA_ACK_DBL_WIDTH (0x01 << IDMA_CNTL_DMA_ACK_WIDTH_BIT) + +#define IDMA_CNTL_HOLD_DEST_ADDR_BIT 5 +#define IDMA_CNTL_HOLD_DEST_ADDR (0x01 << IDMA_CNTL_HOLD_DEST_ADDR_BIT) + +#define IDMA_CNTL_SBURST_LIMIT_BIT 6 +#define IDMA_CNTL_SBURST_LIMIT_MASK (0x7 << IDMA_CNTL_SBURST_LIMIT_BIT) + +#define IDMA_CNTL_SBURST_LIMIT_8B (~IDMA_CNTL_SBURST_LIMIT_MASK) +#define IDMA_CNTL_SBURST_LIMIT_16B (0x1 << IDMA_CNTL_SBURST_LIMIT_BIT) +#define IDMA_CNTL_SBURST_LIMIT_32B (0x3 << IDMA_CNTL_SBURST_LIMIT_BIT) +#define IDMA_CNTL_SBURST_LIMIT_64B (0x7 << IDMA_CNTL_SBURST_LIMIT_BIT) +#define IDMA_CNTL_SBURST_LIMIT_128B (0x4 << IDMA_CNTL_SBURST_LIMIT_BIT) + +#define IDMA_CNTL_CHAIN_MODE_BIT 9 +#define IDMA_CNTL_NON_CHAIN_MODE (0x01 << IDMA_CNTL_CHAIN_MODE_BIT) + +#define IDMA_CNTL_INTERRUPT_MODE_BIT 10 +#define IDMA_CNTL_INTERRUPT_MODE (0x01 << IDMA_CNTL_INTERRUPT_MODE_BIT) + +#define IDMA_CNTL_BLOCK_MODE_BIT 11 +#define IDMA_CNTL_BLOCK_MODE (0x01 << IDMA_CNTL_BLOCK_MODE_BIT) + +#define IDMA_CNTL_CHAN_ENABLE_BIT 12 +#define IDMA_CNTL_CHAN_ENABLE (0x01 << IDMA_CNTL_CHAN_ENABLE_BIT) + +#define IDMA_CNTL_FETCH_NEXT_DESC_BIT 13 +#define IDMA_CNTL_FETCH_NEXT_DESC (0x01 << IDMA_CNTL_FETCH_NEXT_DESC_BIT) + +#define IDMA_CNTL_CHAN_ACTIVE_BIT 14 +#define IDMA_CNTL_CHAN_ACTIVE_MASK (0x01 << IDMA_CNTL_CHAN_ACTIVE_BIT) + +#define IDMA_CNTL_DMA_REQ_DIR_BIT 15 +#define IDMA_CNTL_DMA_REQ_DIR_DEST (0x01 << IDMA_CNTL_DMA_REQ_DIR_BIT) + +#define IDMA_CNTL_DMA_REQ_MODE_BIT 16 +#define IDMA_CNTL_DMA_REQ_MODE_EDGE (0x01 << IDMA_CNTL_DMA_REQ_MODE_BIT) + +#define IDMA_CNTL_CLOSE_DESC_ENA_BIT 17 +#define IDMA_CNTL_CLOSE_DESC_ENABLE (0x01 << IDMA_CNTL_CLOSE_DESC_ENA_BIT) + +#define IDMA_CNTL_END_XFER_ENA_BIT 18 +#define IDMA_CNTL_END_OF_XFER_ENABLE (0x01 << IDMA_CNTL_END_XFER_ENA_BIT) + +#define IDMA_CNTL_END_XFER_MODE_BIT 19 +#define IDMA_CNTL_END_OF_XFER_HALT (0x01 << IDMA_CNTL_END_XFER_MODE_BIT) + +#define IDMA_CNTL_CHAN_ABORT_BIT 20 +#define IDMA_CNTL_CHAN_ABORT (0x01 << IDMA_CNTL_CHAN_ABORT_BIT) + +#define IDMA_CNTL_SADDR_OVERRIDE_BIT 21 +#define IDMA_CNTL_SADDR_OVERRIDE_MASK (0x3 << IDMA_CNTL_SADDR_OVERRIDE_BIT) + +#define IDMA_CNTL_SADDR_OVERRIDE_BAR1 (0x1 << IDMA_CNTL_SADDR_OVERRIDE_BIT) +#define IDMA_CNTL_SADDR_OVERRIDE_BAR2 (0x2 << IDMA_CNTL_SADDR_OVERRIDE_BIT) +#define IDMA_CNTL_SADDR_OVERRIDE_BAR3 (0x3 << IDMA_CNTL_SADDR_OVERRIDE_BIT) + +#define IDMA_CNTL_DADDR_OVERRIDE_BIT 22 +#define IDMA_CNTL_DADDR_OVERRIDE_MASK (0x3 << IDMA_CNTL_DADDR_OVERRIDE_BIT) + +#define IDMA_CNTL_DADDR_OVERRIDE_BAR1 (0x1 << IDMA_CNTL_DADDR_OVERRIDE_BIT) +#define IDMA_CNTL_DADDR_OVERRIDE_BAR2 (0x2 << IDMA_CNTL_DADDR_OVERRIDE_BIT) +#define IDMA_CNTL_DADDR_OVERRIDE_BAR3 (0x3 << IDMA_CNTL_DADDR_OVERRIDE_BIT) + +#define IDMA_CNTL_DESC_OVERRIDE_BIT 25 +#define IDMA_CNTL_DESC_OVERRIDE_MASK (0x3 << IDMA_CNTL_DESC_OVERRIDE_BIT) + +#define IDMA_CNTL_DESC_OVERRIDE_BAR1 (0x1 << IDMA_CNTL_DESC_OVERRIDE_BIT) +#define IDMA_CNTL_DESC_OVERRIDE_BAR2 (0x2 << IDMA_CNTL_DESC_OVERRIDE_BIT) +#define IDMA_CNTL_DESC_OVERRIDE_BAR3 (0x3 << IDMA_CNTL_DESC_OVERRIDE_BIT) + +#define IDMA_CNTL_DMA_ACK_MODE_BIT 27 +#define IDMA_CNTL_DMA_ACK_TRANSACT (0x1 << IDMA_CNTL_DMA_ACK_MODE_BIT) + +#define IDMA_CNTL_DMA_TIMER_REQ_BIT 28 +#define IDMA_CNTL_DMA_TIMER_REQ (0x1 << IDMA_CNTL_DMA_TIMER_REQ_BIT) + +#define IDMA_CNTL_DMA_ACK_DIR_BIT 29 +#define IDMA_CNTL_DMA_ACK_DIR_MASK (0x3 << IDMA_CNTL_DMA_ACK_DIR_BIT) + +#define IDMA_CNTL_DMA_ACK_DIR_DEST (0x1 << IDMA_CNTL_DMA_ACK_DIR_BIT) +#define IDMA_CNTL_DMA_ACK_DIR_SRC (0x2 << IDMA_CNTL_DMA_ACK_DIR_BIT) + +#define IDMA_CNTL_DESC_MODE_BIT 31 +#define IDMA_CNTL_DESC_16MB (0x1 << IDMA_CNTL_DESC_MODE_BIT) +#define IDMA_CNTL_DESC_64KB ~IDMA_CNTL_DESC_16MB + +/* IDMA Channel Control Register (high) */ + +#define IDMA_CNTL_ENDIANESS_BIT 0 +#define IDMA_CNTL_ENDIANESS_LITTLE 0x1 + +#define IDMA_CNTL_DESC_BYTE_SWAP_BIT 1 +#define IDMA CNTL_DESC_BYTE_SWAP_DISABLE (0x01 << IDMA_CNTL_DESC_BYTE_SWAP_BIT) + +/* IDMA Descriptors */ + +#define IDMA_DESC_REMAIN_BYTE_COUNT_MASK 0xFFFF0000 +#define IDMA_DESC_16KB_BYTE_COUNT_MASK 0x0000FFFF +#define IDMA_DESC_16MB_BYTE_COUNT_MASK 0x00FFFFFF + +/* IDMA Arbiter Control Register */ + +#define IDMA_ARBITER_0_BIT 0 +#define IDMA_ARBITER_1_BIT 2 +#define IDMA_ARBITER_2_BIT 4 +#define IDMA_ARBITER_3_BIT 6 +#define IDMA_ARBITER_4_BIT 8 +#define IDMA_ARBITER_5_BIT 10 +#define IDMA_ARBITER_6_BIT 12 +#define IDMA_ARBITER_7_BIT 14 +#define IDMA_ARBITER_8_BIT 16 +#define IDMA_ARBITER_9_BIT 18 +#define IDMA_ARBITER_10_BIT 20 +#define IDMA_ARBITER_11_BIT 22 +#define IDMA_ARBITER_12_BIT 24 +#define IDMA_ARBITER_13_BIT 26 +#define IDMA_ARBITER_14_BIT 28 +#define IDMA_ARBITER_15_BIT 30 +#define IDMA_ARBITER_SLICE_MASK 0x3 + +#define IDMA_ARBITER_CHAN0_SELECT 0x0 +#define IDMA_ARBITER_CHAN1_SELECT 0x1 +#define IDMA_ARBITER_CHAN2_SELECT 0x2 +#define IDMA_ARBITER_CHAN3_SELECT 0x3 + +/* IDMA Crossbar Timeout Register */ + +#define IDMA_CROSSBAR_TIMEOUT_BIT 0 +#define IDMA_CROSSBAR_TIMEOUT_MASK 0xFF +#define IDMA_CROSSBAR_TIMEOUT_PRESET 0xFF + +#define IDMA_CROSSBAR_TIMEOUT_ENA_BIT 16 +#define IDMA_CROSSBAR_TIMEOUT_DISABLE (0x1 << IDMA_CROSSBAR_TIMEOUT_ENA_BIT) + +/* IDMA Interrupt Cause Register */ + +#define IDMA_INT_CAUSE_CHAN0_BIT 0 +#define IDMA_INT_CAUSE_CHAN1_BIT 8 +#define IDMA_INT_CAUSE_CHAN2_BIT 16 +#define IDMA_INT_CAUSE_CHAN3_BIT 24 +#define IDMA_INT_CAUSE_CHAN_MASK 0x1F +#define IDMA_INT_CAUSE_CHAN_ERR_MASK 0x1E + +#define IDMA_INT_CAUSE_DMA_COMPL_BIT 0 +#define IDMA_INT_CAUSE_DMA_COMPL_MASK (0x1 << IDMA_INT_CAUSE_DMA_COMPL_BIT) + +#define IDMA_INT_CAUSE_ADDR_MISS_BIT 1 +#define IDMA_INT_CAUSE_ADDR_MISS_MASK (0x1 << IDMA_INT_CAUSE_ADDR_MISS_BIT) + +#define IDMA_INT_CAUSE_ACC_PROT_BIT 2 +#define IDMA_INT_CAUSE_ACC_PROT_MASK (0x1 << IDMA_INT_CAUSE_ACC_PROT_BIT) + +#define IDMA_INT_CAUSE_WRITE_PROT_BIT 3 +#define IDMA_INT_CAUSE_WRITE_PROT_MASK (0x1 << IDMA_INT_CAUSE_WRITE_PROT_BIT) + +#define IDMA_INT_CAUSE_OWN_VIOL_BIT 4 +#define IDMA_INT_CAUSE_OWN_VIOL_MASK (0x1 << IDMA_INT_CAUSE_OWN_VIOL_BIT) + +/* IDMA Interrupt Mask Register */ + +#define IDMA_INT_MASK_CHAN0_BIT 0 +#define IDMA_INT_MASK_CHAN1_BIT 8 +#define IDMA_INT_MASK_CHAN2_BIT 16 +#define IDMA_INT_MASK_CHAN3_BIT 24 +#define IDMA_INT_MASK_CHAN_MASK 0x1F + +#define IDMA_INT_MASK_CHAN0_MASK (IDMA_INT_MASK_CHAN_MASK << IDMA_INT_MASK_CHAN0_BIT) +#define IDMA_INT_MASK_CHAN1_MASK (IDMA_INT_MASK_CHAN_MASK << IDMA_INT_MASK_CHAN1_BIT) +#define IDMA_INT_MASK_CHAN2_MASK (IDMA_INT_MASK_CHAN_MASK << IDMA_INT_MASK_CHAN2_BIT) +#define IDMA_INT_MASK_CHAN3_MASK (IDMA_INT_MASK_CHAN_MASK << IDMA_INT_MASK_CHAN3_BIT) +#define IDMA_INT_MASK_DMA_COMPL_BIT 0 +#define IDMA_INT_MASK_DMA_COMPL_MASK (0x1 << IDMA_INT_MASK_DMA_COMPL_BIT) + +#define IDMA_INT_MASK_ADDR_MISS_BIT 1 +#define IDMA_INT_MASK_ADDR_MISS_MASK (0x1 << IDMA_INT_MASK_ADDR_MISS_BIT) + +#define IDMA_INT_MASK_ACC_PROT_BIT 2 +#define IDMA_INT_MASK_ACC_PROT_MASK (0x1 << IDMA_INT_MASK_ACC_PROT_BIT) + +#define IDMA_INT_MASK_WRITE_PROT_BIT 3 +#define IDMA_INT_MASK_WRITE_PROT_MASK (0x1 << IDMA_INT_MASK_WRITE_PROT_BIT) + +#define IDMA_INT_MASK_OWN_VIOL_BIT 4 +#define IDMA_INT_MASK_OWN_VIOL_MASK (0x1 << IDMA_INT_MASK_OWN_VIOL_BIT) + +/* IDMA Error Select Register */ + +#define IDMA_ERROR_SEL_MASK 0x1E +#define IDMA_ERROR_SEL_CHAN_MASK 0x18 +#define IDMA_ERROR_SEL_CHAN_BIT 3 + +#define IDMA_ERROR_ADDR_MISS_CHAN0 0x1 +#define IDMA_ERROR_ADDR_MISS_CHAN1 0x9 +#define IDMA_ERROR_ADDR_MISS_CHAN2 0x10 +#define IDMA_ERROR_ADDR_MISS_CHAN3 0x19 + +#define IDMA_ERROR_ACC_PROT_CHAN0 0x2 +#define IDMA_ERROR_ACC_PROT_CHAN1 0xA +#define IDMA_ERROR_ACC_PROT_CHAN2 0x12 +#define IDMA_ERROR_ACC_PROT_CHAN3 0x1A + +#define IDMA_ERROR_WRITE_PROT_CHAN0 0x3 +#define IDMA_ERROR_WRITE_PROT_CHAN1 0xB +#define IDMA_ERROR_WRITE_PROT_CHAN2 0x13 +#define IDMA_ERROR_WRITE_PROT_CHAN3 0x1B + +#define IDMA_ERROR_OWN_VIOL_CHAN0 0x4 +#define IDMA_ERROR_OWN_VIOL_CHAN1 0xC +#define IDMA_ERROR_OWN_VIOL_CHAN2 0x14 +#define IDMA_ERROR_OWN_VIOL_CHAN3 0x1C + +/* CPU to PCI - base address enable bit positions & masks */ + +#define MV64360_BASE_ADDR_ENABLE_CS0_BIT 0 +#define MV64360_BASE_ADDR_ENABLE_CS1_BIT 1 +#define MV64360_BASE_ADDR_ENABLE_CS2_BIT 2 +#define MV64360_BASE_ADDR_ENABLE_CS3_BIT 3 + +#define MV64360_BASE_ADDR_ENABLE_CS_MASK 0x0000000F +#define MV64360_BASE_ADDR_ENABLE_CS_0_MASK (1 << MV64360_BASE_ADDR_ENABLE_CS0_BIT) +#define MV64360_BASE_ADDR_ENABLE_CS_1_MASK (1 << MV64360_BASE_ADDR_ENABLE_CS1_BIT) +#define MV64360_BASE_ADDR_ENABLE_CS_2_MASK (1 << MV64360_BASE_ADDR_ENABLE_CS2_BIT) +#define MV64360_BASE_ADDR_ENABLE_CS_3_MASK (1 << MV64360_BASE_ADDR_ENABLE_CS3_BIT) + + /* IDMA Headers Retarget Registers */ + +#define MV64360_DMA_HEADERS_RETARGET_CONTROL 0xa84 +#define MV64360_DMA_HEADERS_RETARGET_BASE 0xa88 + +#define MV64360_DMA_CHANNEL0_BYTE_COUNT 0x800 +#define MV64360_DMA_CHANNEL1_BYTE_COUNT 0x804 +#define MV64360_DMA_CHANNEL2_BYTE_COUNT 0x808 +#define MV64360_DMA_CHANNEL3_BYTE_COUNT 0x80C +#define MV64360_DMA_CHANNEL0_SOURCE_ADDR 0x810 +#define MV64360_DMA_CHANNEL1_SOURCE_ADDR 0x814 +#define MV64360_DMA_CHANNEL2_SOURCE_ADDR 0x818 +#define MV64360_DMA_CHANNEL3_SOURCE_ADDR 0x81c +#define MV64360_DMA_CHANNEL0_DESTINATION_ADDR 0x820 +#define MV64360_DMA_CHANNEL1_DESTINATION_ADDR 0x824 +#define MV64360_DMA_CHANNEL2_DESTINATION_ADDR 0x828 +#define MV64360_DMA_CHANNEL3_DESTINATION_ADDR 0x82C +#define MV64360_DMA_CHANNEL0_NEXT_DESCRIPTOR_POINTER 0x830 +#define MV64360_DMA_CHANNEL1_NEXT_DESCRIPTOR_POINTER 0x834 +#define MV64360_DMA_CHANNEL2_NEXT_DESCRIPTOR_POINTER 0x838 +#define MV64360_DMA_CHANNEL3_NEXT_DESCRIPTOR_POINTER 0x83C +#define MV64360_DMA_CHANNEL0_CURRENT_DESCRIPTOR_POINTER 0x870 +#define MV64360_DMA_CHANNEL1_CURRENT_DESCRIPTOR_POINTER 0x874 +#define MV64360_DMA_CHANNEL2_CURRENT_DESCRIPTOR_POINTER 0x878 +#define MV64360_DMA_CHANNEL3_CURRENT_DESCRIPTOR_POINTER 0x87C + +#define MV64360_DMA_CHANNEL0_CONTROL 0x840 +#define MV64360_DMA_CHANNEL0_CONTROL_HIGH 0x880 +#define MV64360_DMA_CHANNEL1_CONTROL 0x844 +#define MV64360_DMA_CHANNEL1_CONTROL_HIGH 0x884 +#define MV64360_DMA_CHANNEL2_CONTROL 0x848 +#define MV64360_DMA_CHANNEL2_CONTROL_HIGH 0x888 +#define MV64360_DMA_CHANNEL3_CONTROL 0x84C +#define MV64360_DMA_CHANNEL3_CONTROL_HIGH 0x88C + + /* IDMA Address Decoding High Address Remap and Access + Protection Registers */ + +#define MV64360_DMA_HIGH_ADDR_REMAP_REG0 0xa60 +#define MV64360_DMA_HIGH_ADDR_REMAP_REG1 0xa64 +#define MV64360_DMA_HIGH_ADDR_REMAP_REG2 0xa68 +#define MV64360_DMA_HIGH_ADDR_REMAP_REG3 0xa6C +#define MV64360_DMA_BASE_ADDR_ENABLE_REG 0xa80 +#define MV64360_DMA_CHANNEL0_ACCESS_PROTECTION_REG 0xa70 +#define MV64360_DMA_CHANNEL1_ACCESS_PROTECTION_REG 0xa74 +#define MV64360_DMA_CHANNEL2_ACCESS_PROTECTION_REG 0xa78 +#define MV64360_DMA_CHANNEL3_ACCESS_PROTECTION_REG 0xa7c + +#endif /* __MV64360_DMA_H */ diff -u --new-file --recursive linux-2.6.14.orig/drivers/misc/mv64360_idma/mv64360_dma_interface.h linux-2.6.14.mod/drivers/misc/mv64360_idma/mv64360_dma_interface.h --- linux-2.6.14.orig/drivers/misc/mv64360_idma/mv64360_dma_interface.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/misc/mv64360_idma/mv64360_dma_interface.h 2006-03-07 16:29:20.000000000 -0700 @@ -0,0 +1,86 @@ +#ifndef __MV64360_DMA_INTERFACE +#define __MV64360_DMA_INTERFACE + +#define FIXED_SOURCE 0x00000001 +#define FIXED_DESTINATION 0x00000002 + +/* + * The following structure defines the basic DMA transfer parameters. + */ + +struct dma_descriptor_t { + /* Number of bytes to transfer */ + unsigned int byte_count; + + /* starting addr of source data */ + unsigned int source_addr; + + /* starting addr of destination */ + unsigned int dest_addr; +}; + +/* + * The following structure defines user controlled attributes for a + * given DMA transfer. + */ + +struct dma_attributes_t { + /* Specify whether source or destination is fixed */ + int flags; + + /* Do not increment the source addr */ + int hold_source_addr; + + /* Do not increment the dest addr */ + int hold_dest_addr; +}; + +/* + * The following structure defines DMA status information for the last + * successful DMA transfer or the last error for a particular channel. + * The dma_error_code and dma_error_addr fields are only meaningful if + * dma_complete is non-zero. No error code (0) with a non-zero dma_complete + * status indicates DMA is still in progress. + */ + +struct dma_status_t { + /* O when DMA completes successfully */ + int dma_complete; + + /* Error code when dma_complete is not 0 */ + unsigned int dma_error_code; + + /* Address causing the error code */ + unsigned int dma_error_addr; + + /* Current address of source data */ + unsigned int cur_source_addr; + + /* Current address of destination */ + unsigned int cur_dest_addr; + + /* Address of next descriptor */ + unsigned int cur_next_desc; + + /* Current channel control settings */ + unsigned int chan_cntl_low; +}; + +struct dma_setup_t { + struct dma_descriptor_t dma_descriptor; + struct dma_attributes_t dma_attributes; +}; + +struct dma_arbiter_setup_t { + unsigned int values[16]; +}; + +#define MV64360_DMA_SETUP _IOW('w', 1, struct dma_setup_t) +#define MV64360_DMA_START _IO('w', 2) +#define MV64360_DMA_ABORT _IO('w', 3) +#define MV64360_DMA_PAUSE _IO('w', 4) +#define MV64360_DMA_RESUME _IO('w', 5) +#define MV64360_DMA_STATUS _IOR('w', 6, struct dma_status_t) +#define MV64360_DMA_ARBITER_SETUP _IOW('w', 7, struct dma_arbiter_setup_t) + +#endif /* __MV64360_DMA_INTERFACE */ diff -u --new-file --recursive linux-2.6.14.orig/drivers/mtd/chips/cfi_cmdset_0002.c linux-2.6.14.mod/drivers/mtd/chips/cfi_cmdset_0002.c --- linux-2.6.14.orig/drivers/mtd/chips/cfi_cmdset_0002.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/mtd/chips/cfi_cmdset_0002.c 2005-11-16 10:40:21.000000000 -0700 @@ -371,7 +371,7 @@ /* FIXME: erase-suspend-program is broken. See http://lists.infradead.org/pipermail/linux-mtd/2003-December/009001.html */ - printk(KERN_NOTICE "cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.\n"); + printk(KERN_DEBUG "cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.\n"); __module_get(THIS_MODULE); return mtd; diff -u --new-file --recursive linux-2.6.14.orig/drivers/mtd/maps/Kconfig linux-2.6.14.mod/drivers/mtd/maps/Kconfig --- linux-2.6.14.orig/drivers/mtd/maps/Kconfig 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/mtd/maps/Kconfig 2006-03-14 13:37:55.000000000 -0700 @@ -624,5 +624,37 @@ This selection automatically selects the map_ram driver. +config MTD_MVME3100 + tristate "Flash device mapped on the MVME3100 board" + depends on MVME3100 && MTD_CFI && MTD_PARTITIONS && 85xx + help + This enables access to the Flash on the Motorola ECC + MVME3100 boards. + If you have such a board, say 'Y'. + +config MTD_MVME5500 + tristate "Flash device mapped on the MVME5500 board" + depends on MVME5500 && MTD_CFI && MTD_PARTITIONS + help + This enables access to the Flash on the Motorola ECC + MVME5500 boards. + If you have such a board, say 'Y'. + +config MTD_MVME6100 + tristate "Flash device mapped on the MVME6100 board" + depends on MVME6100 && MTD_CFI && MTD_PARTITIONS + help + This enables access to the Flash on the Motorola ECC + MVME6100 boards. + If you have such a board, say 'Y'. + +config MTD_MCP905 + tristate "Flash device mapped on the MCP905 board" + depends on MCP905 && MTD_CFI && MTD_PARTITIONS + help + This enables access to the Flash on the Motorola ECC + MCP905 boards. + If you have such a board, say 'Y'. + endmenu diff -u --new-file --recursive linux-2.6.14.orig/drivers/mtd/maps/Makefile linux-2.6.14.mod/drivers/mtd/maps/Makefile --- linux-2.6.14.orig/drivers/mtd/maps/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/mtd/maps/Makefile 2006-03-14 13:38:06.000000000 -0700 @@ -70,3 +70,7 @@ obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o +obj-$(CONFIG_MTD_MVME3100) += mvme3100.o +obj-$(CONFIG_MTD_MVME5500) += mvme5500.o +obj-$(CONFIG_MTD_MVME6100) += mvme6100.o +obj-$(CONFIG_MTD_MCP905) += mcp905.o diff -u --new-file --recursive linux-2.6.14.orig/drivers/mtd/maps/mcp905.c linux-2.6.14.mod/drivers/mtd/maps/mcp905.c --- linux-2.6.14.orig/drivers/mtd/maps/mcp905.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/mtd/maps/mcp905.c 2006-06-06 14:22:48.000000000 -0700 @@ -0,0 +1,154 @@ +/* + * + * Mapping for Motorola MCP905 flash + * + * Ajit Prem (Ajit.Prem@motorola.com) + + * Copyright 2006 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mtd_info *flash[2]; + +static struct map_info mcp905_flash0_map = { + .name = "mcp905-flash0", + .size = MCP905_BANK_A_FLASH_SIZE, + .bankwidth = 4, +}; + +static struct map_info mcp905_flash1_map = { + .name = "mcp905-flash1", + .size = MCP905_BANK_B_FLASH_SIZE, + .bankwidth = 4, +}; + +static struct mtd_partition mcp905_flash0_partitions[] = { + { + .name = "Linux Kernel + INITRD", + .offset = 0x00000000, + .size = 0x01400000, + }, + { + .name = "Linux JFFS2 Filesystem", + .offset = 0x01400000, + .size = 0x00b00000, + }, + { + .name = "Bootloader Flash 0", + .offset = 0x01f00000, + .size = 0x00100000, + }, +}; + +static struct mtd_partition mcp905_flash1_partitions[] = { + { + .name = "Linux JFFS2 Filesystem", + .offset = 0x00000000, + .size = 0x00700000, + }, + { + .name = "Bootloader Flash 1", + .offset = 0x00700000, + .size = 0x00100000, + } +}; + + +int __init mcp905_map_init(void) +{ + unsigned long mcp905_flash0_base; + unsigned long mcp905_flash1_base; + + mcp905_flash0_base = MCP905_BANK_A_FLASH_BASE; + + mcp905_flash0_map.phys = mcp905_flash0_base; + mcp905_flash0_map.virt = (unsigned long)ioremap(mcp905_flash0_base, + mcp905_flash0_map.size); + + if (!mcp905_flash0_map.virt) { + printk("Failed to ioremap flash0\n"); + return -EIO; + } + + simple_map_init(&mcp905_flash0_map); + + flash[0] = do_map_probe("cfi_probe", &mcp905_flash0_map); + if (flash[0]) { + flash[0]->owner = THIS_MODULE; + add_mtd_partitions(flash[0], mcp905_flash0_partitions, + ARRAY_SIZE(mcp905_flash0_partitions)); + } else { + printk("map probe failed for flash0\n"); + iounmap((void *)mcp905_flash0_map.virt); + return -ENXIO; + } + + mcp905_flash1_base = MCP905_BANK_B_FLASH_BASE; + + mcp905_flash1_map.phys = mcp905_flash1_base; + mcp905_flash1_map.virt = (unsigned long)ioremap( + mcp905_flash1_base, + mcp905_flash1_map.size); + + if (!mcp905_flash1_map.virt) { + printk("Failed to ioremap flash1\n"); + return -EIO; + } + + simple_map_init(&mcp905_flash1_map); + + flash[1] = do_map_probe("cfi_probe", &mcp905_flash1_map); + if (flash[1]) { + flash[1]->owner = THIS_MODULE; + add_mtd_partitions(flash[1], mcp905_flash1_partitions, + ARRAY_SIZE(mcp905_flash1_partitions)); + } else { + printk("map probe failed for flash1\n"); + iounmap((void *)mcp905_flash0_map.virt); + iounmap((void *)mcp905_flash1_map.virt); + return -ENXIO; + } + + return 0; +} + +static void __exit mcp905_map_exit(void) +{ + int i; + + for (i=0; i<2; i++) { + if (flash[i]) { + del_mtd_partitions(flash[i]); + map_destroy(flash[i]); + } + } + + if (mcp905_flash0_map.virt) { + iounmap((void *)mcp905_flash0_map.virt); + } + if (mcp905_flash1_map.virt) { + iounmap((void *)mcp905_flash1_map.virt); + } +} + +module_init(mcp905_map_init); +module_exit(mcp905_map_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ajit Prem "); +MODULE_DESCRIPTION("MTD map and partitions for Motorola MCP905"); diff -u --new-file --recursive linux-2.6.14.orig/drivers/mtd/maps/mvme3100.c linux-2.6.14.mod/drivers/mtd/maps/mvme3100.c --- linux-2.6.14.orig/drivers/mtd/maps/mvme3100.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/mtd/maps/mvme3100.c 2006-02-13 12:33:39.000000000 -0700 @@ -0,0 +1,165 @@ +/* + * + * Mapping for Motorola MVME3100 flash + * + * Ajit Prem (Ajit.Prem@motorola.com) + * + * Copyright 2005-2006 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mtd_info *flash; + +static struct map_info mvme3100_128M_map = { + .name = "mvme3100-flash", + .size = MVME3100_FLASH_SIZE_128M, + .bankwidth = 4, +}; + +static struct map_info mvme3100_64M_map = { + .name = "mvme3100-flash", + .size = MVME3100_FLASH_SIZE_64M, + .bankwidth = 4, +}; + +static struct map_info mvme3100_map; + +static struct mtd_partition mvme3100_128M_partitions[] = { + { + .name = "Linux Kernel + INITRD", + .offset = 0x00000000, + .size = 0x01000000, + }, + { + .name = "Linux JFFS2 Filesystem", + .offset = 0x01000000, + .size = 0x06e00000, + }, + { + .name = "Bootloader Block B", + .offset = 0x07e00000, + .size = 0x00100000, + }, + { + .name = "Bootloader Block A", + .offset = 0x07f00000, + .size = 0x00100000, + } +}; + +static struct mtd_partition mvme3100_64M_partitions[] = { + { + .name = "Linux Kernel + INITRD", + .offset = 0x00000000, + .size = 0x01000000, + }, + { + .name = "Linux JFFS2 Filesystem", + .offset = 0x01000000, + .size = 0x02e00000, + }, + { + .name = "Bootloader Block B", + .offset = 0x03e00000, + .size = 0x00100000, + }, + { + .name = "Bootloader Block A", + .offset = 0x03f00000, + .size = 0x00100000, + } +}; + + +int __init mvme3100_map_init(void) +{ + unsigned long mvme3100_flash_base; + + mvme3100_flash_base = MVME3100_FLASH_BASE_128M; + + mvme3100_map = mvme3100_128M_map; + + mvme3100_map.phys = mvme3100_flash_base; + mvme3100_map.virt = (unsigned long)ioremap(mvme3100_flash_base, + mvme3100_map.size); + + if (!mvme3100_map.virt) { + printk("Failed to ioremap flash\n"); + return -EIO; + } + + simple_map_init(&mvme3100_map); + + flash = do_map_probe("cfi_probe", &mvme3100_map); + if (flash) { + flash->owner = THIS_MODULE; + add_mtd_partitions(flash, mvme3100_128M_partitions, + ARRAY_SIZE(mvme3100_128M_partitions)); + } else { + iounmap((void *)mvme3100_map.virt); + mvme3100_map.virt = 0; + + mvme3100_flash_base = MVME3100_FLASH_BASE_64M; + mvme3100_map = mvme3100_64M_map; + + mvme3100_map.phys = mvme3100_flash_base; + mvme3100_map.virt = (unsigned long)ioremap( + mvme3100_flash_base, + mvme3100_map.size); + + if (!mvme3100_map.virt) { + printk("Failed to ioremap flash\n"); + return -EIO; + } + + simple_map_init(&mvme3100_map); + + flash = do_map_probe("cfi_probe", &mvme3100_map); + if (flash) { + flash->owner = THIS_MODULE; + add_mtd_partitions(flash, mvme3100_64M_partitions, + ARRAY_SIZE(mvme3100_64M_partitions)); + } else { + printk("map probe failed for flash\n"); + iounmap((void *)mvme3100_map.virt); + return -ENXIO; + } + } + + return 0; +} + +static void __exit mvme3100_map_exit(void) +{ + if (flash) { + del_mtd_partitions(flash); + map_destroy(flash); + } + + if (mvme3100_map.virt) { + iounmap((void *)mvme3100_map.virt); + mvme3100_map.virt = 0; + } +} + +module_init(mvme3100_map_init); +module_exit(mvme3100_map_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ajit Prem "); +MODULE_DESCRIPTION("MTD map and partitions for Motorola MVME3100"); diff -u --new-file --recursive linux-2.6.14.orig/drivers/mtd/maps/mvme5500.c linux-2.6.14.mod/drivers/mtd/maps/mvme5500.c --- linux-2.6.14.orig/drivers/mtd/maps/mvme5500.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/mtd/maps/mvme5500.c 2006-06-06 14:22:03.000000000 -0700 @@ -0,0 +1,154 @@ +/* + * + * Mapping for Motorola MVME5500 flash + * + * Ajit Prem (Ajit.Prem@motorola.com) + + * Copyright 2006 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mtd_info *flash[2]; + +static struct map_info mvme5500_flash0_map = { + .name = "mvme5500-flash0", + .size = MVME5500_BANK_A_FLASH_SIZE, + .bankwidth = 4, +}; + +static struct map_info mvme5500_flash1_map = { + .name = "mvme5500-flash1", + .size = MVME5500_BANK_B_FLASH_SIZE, + .bankwidth = 4, +}; + +static struct mtd_partition mvme5500_flash0_partitions[] = { + { + .name = "Linux Kernel + INITRD", + .offset = 0x00000000, + .size = 0x01400000, + }, + { + .name = "Linux JFFS2 Filesystem", + .offset = 0x01400000, + .size = 0x00b00000, + }, + { + .name = "Bootloader Flash 0", + .offset = 0x01f00000, + .size = 0x00100000, + }, +}; + +static struct mtd_partition mvme5500_flash1_partitions[] = { + { + .name = "Linux JFFS2 Filesystem", + .offset = 0x00000000, + .size = 0x00700000, + }, + { + .name = "Bootloader Flash 1", + .offset = 0x00700000, + .size = 0x00100000, + } +}; + + +int __init mvme5500_map_init(void) +{ + unsigned long mvme5500_flash0_base; + unsigned long mvme5500_flash1_base; + + mvme5500_flash0_base = MVME5500_BANK_A_FLASH_BASE; + + mvme5500_flash0_map.phys = mvme5500_flash0_base; + mvme5500_flash0_map.virt = (unsigned long)ioremap(mvme5500_flash0_base, + mvme5500_flash0_map.size); + + if (!mvme5500_flash0_map.virt) { + printk("Failed to ioremap flash0\n"); + return -EIO; + } + + simple_map_init(&mvme5500_flash0_map); + + flash[0] = do_map_probe("cfi_probe", &mvme5500_flash0_map); + if (flash[0]) { + flash[0]->owner = THIS_MODULE; + add_mtd_partitions(flash[0], mvme5500_flash0_partitions, + ARRAY_SIZE(mvme5500_flash0_partitions)); + } else { + printk("map probe failed for flash0\n"); + iounmap((void *)mvme5500_flash0_map.virt); + return -ENXIO; + } + + mvme5500_flash1_base = MVME5500_BANK_B_FLASH_BASE; + + mvme5500_flash1_map.phys = mvme5500_flash1_base; + mvme5500_flash1_map.virt = (unsigned long)ioremap( + mvme5500_flash1_base, + mvme5500_flash1_map.size); + + if (!mvme5500_flash1_map.virt) { + printk("Failed to ioremap flash1\n"); + return -EIO; + } + + simple_map_init(&mvme5500_flash1_map); + + flash[1] = do_map_probe("cfi_probe", &mvme5500_flash1_map); + if (flash[1]) { + flash[1]->owner = THIS_MODULE; + add_mtd_partitions(flash[1], mvme5500_flash1_partitions, + ARRAY_SIZE(mvme5500_flash1_partitions)); + } else { + printk("map probe failed for flash1\n"); + iounmap((void *)mvme5500_flash0_map.virt); + iounmap((void *)mvme5500_flash1_map.virt); + return -ENXIO; + } + + return 0; +} + +static void __exit mvme5500_map_exit(void) +{ + int i; + + for (i=0; i<2; i++) { + if (flash[i]) { + del_mtd_partitions(flash[i]); + map_destroy(flash[i]); + } + } + + if (mvme5500_flash0_map.virt) { + iounmap((void *)mvme5500_flash0_map.virt); + } + if (mvme5500_flash1_map.virt) { + iounmap((void *)mvme5500_flash1_map.virt); + } +} + +module_init(mvme5500_map_init); +module_exit(mvme5500_map_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ajit Prem "); +MODULE_DESCRIPTION("MTD map and partitions for Motorola MVME5500"); diff -u --new-file --recursive linux-2.6.14.orig/drivers/mtd/maps/mvme6100.c linux-2.6.14.mod/drivers/mtd/maps/mvme6100.c --- linux-2.6.14.orig/drivers/mtd/maps/mvme6100.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/mtd/maps/mvme6100.c 2006-06-06 14:22:38.000000000 -0700 @@ -0,0 +1,154 @@ +/* + * + * Mapping for Motorola MVME6100 flash + * + * Ajit Prem (Ajit.Prem@motorola.com) + + * Copyright 2006 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mtd_info *flash[2]; + +static struct map_info mvme6100_flash0_map = { + .name = "mvme6100-flash0", + .size = MVME6100_BANK_A_FLASH_SIZE, + .bankwidth = 4, +}; + +static struct map_info mvme6100_flash1_map = { + .name = "mvme6100-flash1", + .size = MVME6100_BANK_B_FLASH_SIZE, + .bankwidth = 4, +}; + +static struct mtd_partition mvme6100_flash0_partitions[] = { + { + .name = "Linux Kernel + INITRD", + .offset = 0x00000000, + .size = 0x01400000, + }, + { + .name = "Linux JFFS2 Filesystem", + .offset = 0x01400000, + .size = 0x02b00000, + }, + { + .name = "Bootloader Flash 0", + .offset = 0x03f00000, + .size = 0x00100000, + }, +}; + +static struct mtd_partition mvme6100_flash1_partitions[] = { + { + .name = "Linux JFFS2 Filesystem", + .offset = 0x00000000, + .size = 0x03f00000, + }, + { + .name = "Bootloader Flash 1", + .offset = 0x03f00000, + .size = 0x00100000, + } +}; + + +int __init mvme6100_map_init(void) +{ + unsigned long mvme6100_flash0_base; + unsigned long mvme6100_flash1_base; + + mvme6100_flash0_base = MVME6100_BANK_A_FLASH_BASE; + + mvme6100_flash0_map.phys = mvme6100_flash0_base; + mvme6100_flash0_map.virt = (unsigned long)ioremap(mvme6100_flash0_base, + mvme6100_flash0_map.size); + + if (!mvme6100_flash0_map.virt) { + printk("Failed to ioremap flash0\n"); + return -EIO; + } + + simple_map_init(&mvme6100_flash0_map); + + flash[0] = do_map_probe("cfi_probe", &mvme6100_flash0_map); + if (flash[0]) { + flash[0]->owner = THIS_MODULE; + add_mtd_partitions(flash[0], mvme6100_flash0_partitions, + ARRAY_SIZE(mvme6100_flash0_partitions)); + } else { + printk("map probe failed for flash0\n"); + iounmap((void *)mvme6100_flash0_map.virt); + return -ENXIO; + } + + mvme6100_flash1_base = MVME6100_BANK_B_FLASH_BASE; + + mvme6100_flash1_map.phys = mvme6100_flash1_base; + mvme6100_flash1_map.virt = (unsigned long)ioremap( + mvme6100_flash1_base, + mvme6100_flash1_map.size); + + if (!mvme6100_flash1_map.virt) { + printk("Failed to ioremap flash1\n"); + return -EIO; + } + + simple_map_init(&mvme6100_flash1_map); + + flash[1] = do_map_probe("cfi_probe", &mvme6100_flash1_map); + if (flash[1]) { + flash[1]->owner = THIS_MODULE; + add_mtd_partitions(flash[1], mvme6100_flash1_partitions, + ARRAY_SIZE(mvme6100_flash1_partitions)); + } else { + printk("map probe failed for flash1\n"); + iounmap((void *)mvme6100_flash0_map.virt); + iounmap((void *)mvme6100_flash1_map.virt); + return -ENXIO; + } + + return 0; +} + +static void __exit mvme6100_map_exit(void) +{ + int i; + + for (i=0; i<2; i++) { + if (flash[i]) { + del_mtd_partitions(flash[i]); + map_destroy(flash[i]); + } + } + + if (mvme6100_flash0_map.virt) { + iounmap((void *)mvme6100_flash0_map.virt); + } + if (mvme6100_flash1_map.virt) { + iounmap((void *)mvme6100_flash1_map.virt); + } +} + +module_init(mvme6100_map_init); +module_exit(mvme6100_map_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ajit Prem "); +MODULE_DESCRIPTION("MTD map and partitions for Motorola MVME6100"); diff -u --new-file --recursive linux-2.6.14.orig/drivers/net/gianfar.c linux-2.6.14.mod/drivers/net/gianfar.c --- linux-2.6.14.orig/drivers/net/gianfar.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/net/gianfar.c 2006-03-28 15:55:51.000000000 -0700 @@ -724,6 +724,9 @@ /* Unmask the interrupts we look for */ gfar_write(®s->imask, IMASK_DEFAULT); + + /* Clear the halt bit in RSTAT */ + gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT); } /* Bring the controller up and running */ diff -u --new-file --recursive linux-2.6.14.orig/drivers/net/gianfar_ethtool.c linux-2.6.14.mod/drivers/net/gianfar_ethtool.c --- linux-2.6.14.orig/drivers/net/gianfar_ethtool.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/net/gianfar_ethtool.c 2005-11-16 10:40:21.000000000 -0700 @@ -182,6 +182,44 @@ drvinfo->eedump_len = 0; } +static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct gfar_private *priv = netdev_priv(dev); + + /* Verify the settings we care about. */ + if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE) + return -EINVAL; + + if (cmd->autoneg == AUTONEG_DISABLE + && ((cmd->speed != SPEED_1000 + && cmd->speed != SPEED_100 + && cmd->speed != SPEED_10) + || (cmd->duplex != DUPLEX_HALF + && cmd->duplex != DUPLEX_FULL))) + return -EINVAL; + + if (!priv->mii_info) + return -EIO; + + priv->mii_info->autoneg = cmd->autoneg; + priv->mii_info->speed = cmd->speed; + priv->mii_info->duplex = cmd->duplex; + + if (AUTONEG_ENABLE == cmd->autoneg) + priv->mii_info->advertising |= ADVERTISED_Autoneg; + else + priv->mii_info->advertising &= ~ADVERTISED_Autoneg; + + cmd->advertising = priv->mii_info->advertising; + + if (dev->flags & IFF_UP) { + stop_gfar(dev); + startup_gfar(dev); + } + + return 0; +} + /* Return the current settings in the ethtool_cmd structure */ static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) { @@ -194,22 +232,30 @@ ADVERTISED_1000baseT_Full: 0; cmd->supported = (SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | gigabit_support | SUPPORTED_Autoneg); /* For now, we always advertise everything */ cmd->advertising = (ADVERTISED_10baseT_Half + | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | gigabit_advert | ADVERTISED_Autoneg); - cmd->speed = priv->mii_info->speed; - cmd->duplex = priv->mii_info->duplex; + if (priv->mii_info) { + cmd->speed = priv->mii_info->speed; + cmd->duplex = priv->mii_info->duplex; + cmd->phy_address = priv->mii_info->mii_id; + cmd->autoneg = priv->mii_info->autoneg; + } else { + cmd->speed = -1; + cmd->duplex = -1; + cmd->autoneg = AUTONEG_ENABLE; + } cmd->port = PORT_MII; - cmd->phy_address = priv->mii_info->mii_id; cmd->transceiver = XCVR_EXTERNAL; - cmd->autoneg = AUTONEG_ENABLE; cmd->maxtxpkt = priv->txcount; cmd->maxrxpkt = priv->rxcount; @@ -535,6 +581,7 @@ struct ethtool_ops gfar_ethtool_ops = { + .set_settings = gfar_ssettings, .get_settings = gfar_gsettings, .get_drvinfo = gfar_gdrvinfo, .get_regs_len = gfar_reglen, diff -u --new-file --recursive linux-2.6.14.orig/drivers/net/gianfar.h linux-2.6.14.mod/drivers/net/gianfar.h --- linux-2.6.14.orig/drivers/net/gianfar.h 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/net/gianfar.h 2006-02-14 11:00:09.000000000 -0700 @@ -112,11 +112,11 @@ #define DEFAULT_TX_COALESCE 1 #define DEFAULT_TXCOUNT 16 -#define DEFAULT_TXTIME 400 +#define DEFAULT_TXTIME 4 #define DEFAULT_RX_COALESCE 1 #define DEFAULT_RXCOUNT 16 -#define DEFAULT_RXTIME 400 +#define DEFAULT_RXTIME 4 #define TBIPA_VALUE 0x1f #define MIIMCFG_INIT_VALUE 0x00000007 diff -u --new-file --recursive linux-2.6.14.orig/drivers/net/gianfar_phy.c linux-2.6.14.mod/drivers/net/gianfar_phy.c --- linux-2.6.14.orig/drivers/net/gianfar_phy.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/net/gianfar_phy.c 2005-11-16 10:40:21.000000000 -0700 @@ -145,34 +145,53 @@ u16 ctrl; u32 features = mii_info->phyinfo->features; + ctrl = phy_read(mii_info, MII_BMCR); ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE); ctrl |= BMCR_RESET; + phy_write(mii_info, MII_BMCR, ctrl); + udelay(3); + ctrl = 0; switch(mii_info->speed) { case SPEED_1000: if(features & (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)) { ctrl |= BMCR_SPEED1000; + if ((mii_info->duplex == DUPLEX_FULL) && + (features & SUPPORTED_1000baseT_Full)) { + ctrl |= BMCR_FULLDPLX; + } break; - } - mii_info->speed = SPEED_100; + } else + return; case SPEED_100: if (features & (SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full)) { ctrl |= BMCR_SPEED100; + if ((mii_info->duplex == DUPLEX_FULL) && + (features & SUPPORTED_100baseT_Full)) { + ctrl |= BMCR_FULLDPLX; + } break; - } - mii_info->speed = SPEED_10; + } else + return; case SPEED_10: if (features & (SUPPORTED_10baseT_Half - | SUPPORTED_10baseT_Full)) + | SUPPORTED_10baseT_Full)) { + if ((mii_info->duplex == DUPLEX_FULL) && + (features & SUPPORTED_10baseT_Full)) { + ctrl |= BMCR_FULLDPLX; + } break; + } else + return; + default: /* Unsupported speed! */ printk(KERN_ERR "%s: Bad speed!\n", mii_info->dev->name); - break; + return; } phy_write(mii_info, MII_BMCR, ctrl); @@ -537,14 +556,150 @@ kfree(priv); } -#if 0 -static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info) +static int bcm5461S_init(struct gfar_mii_info *mii_info) { - phy_read(mii_info, MII_DM9161_INTR); + u16 clk_align_ctrl; + + /* Select Clock Alignment Control Register */ + clk_align_ctrl = MIIM_BCM5461S_CLK_ALIGN_SHADOW; + phy_write(mii_info, MIIM_BCM5461S_CLK_ALIGN, clk_align_ctrl); + clk_align_ctrl = phy_read(mii_info, MIIM_BCM5461S_CLK_ALIGN); + clk_align_ctrl &= ~MIIM_BCM5461S_GTX_CLK_ENABLE_DELAY; + clk_align_ctrl |= 0x8000; + phy_write(mii_info, MIIM_BCM5461S_CLK_ALIGN, clk_align_ctrl); + + return 0; +} + +static int bcm5461S_read_status(struct gfar_mii_info *mii_info) +{ + u16 status; + int err; + + /* Update the link, but return if there + * was an error */ + err = genmii_update_link(mii_info); + if (err) + return err; + + /* If the link is up, read the speed and duplex */ + /* If we aren't autonegotiating, assume speeds + * are as set */ + if (mii_info->autoneg && mii_info->link) { + status = phy_read(mii_info, MIIM_BCM5461S_1000T_STATUS); + if (status & MIIM_BCM5461S_1000T_FULL_DUPLEX) { + mii_info->duplex = DUPLEX_FULL; + mii_info->speed = SPEED_1000; + return 0; + } + + if (status & MIIM_BCM5461S_1000T_HALF_DUPLEX) { + mii_info->duplex = DUPLEX_HALF; + mii_info->speed = SPEED_1000; + return 0; + } + + status = phy_read(mii_info, MIIM_BCM5461S_LPA); + if (status & MIIM_BCM5461S_LPA_100T_FULL_DUPLEX) { + mii_info->duplex = DUPLEX_FULL; + mii_info->speed = SPEED_100; + return 0; + } + if (status & MIIM_BCM5461S_LPA_100T_HALF_DUPLEX) { + mii_info->duplex = DUPLEX_HALF; + mii_info->speed = SPEED_100; + return 0; + } + if (status & MIIM_BCM5461S_LPA_10T_FULL_DUPLEX) { + mii_info->duplex = DUPLEX_FULL; + mii_info->speed = SPEED_10; + return 0; + } + if (status & MIIM_BCM5461S_LPA_10T_HALF_DUPLEX) { + mii_info->duplex = DUPLEX_HALF; + mii_info->speed = SPEED_10; + return 0; + } + } + + return 0; +} + +static int bcm5461S_ack_interrupt(struct gfar_mii_info *mii_info) +{ + phy_read(mii_info, MIIM_BCM5461S_IEVENT); + + return 0; +} + +static int bcm5461S_config_intr(struct gfar_mii_info *mii_info) +{ + if (mii_info->interrupts == MII_INTERRUPT_ENABLED) + phy_write(mii_info, MIIM_BCM5461S_IMASK, MIIM_BCM5461S_IMASK_INIT); + else + phy_write(mii_info, MIIM_BCM5461S_IMASK, MIIM_BCM5461S_IMASK_CLEAR); + + return 0; +} + +static int bcm5221_read_status(struct gfar_mii_info *mii_info) +{ + u16 status; + int err; + + /* Update the link, but return if there + * was an error */ + err = genmii_update_link(mii_info); + if (err) + return err; + + /* If the link is up, read the speed and duplex */ + /* If we aren't autonegotiating, assume speeds + * are as set */ + if (mii_info->autoneg && mii_info->link) { + status = phy_read(mii_info, MIIM_BCM5221_LPA); + if (status & (MIIM_BCM5221_LPA_100T_FULL_DUPLEX | + MIIM_BCM5221_LPA_100T)) + mii_info->speed = SPEED_100; + else + mii_info->speed = SPEED_10; + + if (status & (MIIM_BCM5221_LPA_100T_FULL_DUPLEX | + MIIM_BCM5221_LPA_10T_FULL_DUPLEX)) + mii_info->duplex = DUPLEX_FULL; + else + mii_info->duplex = DUPLEX_HALF; + } + + return 0; +} + +static int bcm5221_init(struct gfar_mii_info *mii_info) +{ + u16 temp; + + /* Fix the LED issue */ + temp = phy_read(mii_info, 0x1F); + temp |= 0x0080; + phy_write(mii_info, 0x1F, temp); + + temp = phy_read(mii_info, 0x1A); + temp |= 0x0008; + phy_write(mii_info, 0x1A, temp); + + temp = phy_read(mii_info, 0x1F); + temp &=~ 0x0080; + phy_write(mii_info, 0x1F, temp); + + + /* Isolate the PHY */ + phy_write(mii_info, MII_BMCR, BMCR_ISOLATE); + + /* Reconnect the PHY, and enable Autonegotiation */ + phy_write(mii_info, MII_BMCR, BMCR_ANENABLE); return 0; } -#endif /* Cicada 820x */ static struct phy_info phy_info_cis820x = { @@ -580,6 +735,28 @@ .config_intr = &marvell_config_intr, }; +static struct phy_info phy_info_bcm5461S = { + .phy_id = 0x002060c0, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom 5461S", + .features = MII_GBIT_FEATURES, + .init = bcm5461S_init, + .config_aneg = gbit_config_aneg, + .read_status = bcm5461S_read_status, + .ack_interrupt = bcm5461S_ack_interrupt, + .config_intr = bcm5461S_config_intr, +}; + +static struct phy_info phy_info_bcm5221 = { + .phy_id = 0x004061e0, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom 5221", + .features = MII_BASIC_FEATURES, + .init = bcm5221_init, + .config_aneg = genmii_config_aneg, + .read_status = bcm5221_read_status, +}; + static struct phy_info phy_info_genmii= { .phy_id = 0x00000000, .phy_id_mask = 0x00000000, @@ -593,6 +770,8 @@ &phy_info_cis820x, &phy_info_marvell, &phy_info_dm9161, + &phy_info_bcm5461S, + &phy_info_bcm5221, &phy_info_genmii, NULL }; diff -u --new-file --recursive linux-2.6.14.orig/drivers/net/gianfar_phy.h linux-2.6.14.mod/drivers/net/gianfar_phy.h --- linux-2.6.14.orig/drivers/net/gianfar_phy.h 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/net/gianfar_phy.h 2005-11-16 10:40:21.000000000 -0700 @@ -104,6 +104,42 @@ #define MII_DM9161_10BTCSR 0x12 #define MII_DM9161_10BTCSR_INIT 0x7800 +/* BCM5461S */ +#define MIIM_BCM5461S_RSTAN 0x0200 + +/* BCM5461S 1000T Status Register */ +#define MIIM_BCM5461S_1000T_STATUS 0xa +#define MIIM_BCM5461S_1000T_FULL_DUPLEX 0x0800 +#define MIIM_BCM5461S_1000T_HALF_DUPLEX 0x0400 + +/* BCM5461S LPA Register */ +#define MIIM_BCM5461S_LPA 0x5 +#define MIIM_BCM5461S_LPA_100T_FULL_DUPLEX 0x0100 +#define MIIM_BCM5461S_LPA_100T_HALF_DUPLEX 0x0080 +#define MIIM_BCM5461S_LPA_10T_FULL_DUPLEX 0x0040 +#define MIIM_BCM5461S_LPA_10T_HALF_DUPLEX 0x0020 + +/* BCM5461S Interrupt Status Register */ +#define MIIM_BCM5461S_IEVENT 0x1a +#define MIIM_BCM5461S_IEVENT_CLEAR 0x0000 + +/* BCM5461S Clock Alignment Control Register */ +#define MIIM_BCM5461S_CLK_ALIGN 0x1c +#define MIIM_BCM5461S_CLK_ALIGN_SHADOW 0x0c00 +#define MIIM_BCM5461S_GTX_CLK_ENABLE_DELAY 0x0200 + +/* BCM5461S Interrupt Mask Register */ +#define MIIM_BCM5461S_IMASK 0x1b +#define MIIM_BCM5461S_IMASK_INIT 0xfff1 +#define MIIM_BCM5461S_IMASK_CLEAR 0xffff + +/* BCM5221 LPA Register */ +#define MIIM_BCM5221_LPA 0x5 +#define MIIM_BCM5221_LPA_100T_FULL_DUPLEX 0x0100 +#define MIIM_BCM5221_LPA_100T 0x0080 +#define MIIM_BCM5221_LPA_10T_FULL_DUPLEX 0x0040 +#define MIIM_BCM5221_LPA_10T 0x0020 + #define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | \ SUPPORTED_10baseT_Full | \ SUPPORTED_100baseT_Half | \ diff -u --new-file --recursive linux-2.6.14.orig/drivers/net/gt64260_eth.c linux-2.6.14.mod/drivers/net/gt64260_eth.c --- linux-2.6.14.orig/drivers/net/gt64260_eth.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/net/gt64260_eth.c 2006-02-16 13:14:24.000000000 -0700 @@ -0,0 +1,1967 @@ +/* Driver for EVB64260 ethernet ports + Copyright (C)2000, 2001 Rabeeh Khoury, Marvell */ + +/* + * drivers/net/gt64260_eth.c + * + * Ethernet driver for the Marvell/Galileo GT64260 (Discovery) chip, + * + * Author: Rabeeh Khoury from Marvell + * + * Updated for the 2.6 kernel by Ajit Prem (Motorola) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CONFIG_NET_FASTROUTE +#include +#include +#endif + +#include +#include "gt64260_eth.h" + +extern bd_t ppcboot_bd; +extern int ppcboot_bd_valid; +extern int gt64260_i2cMacGet(char *, int); + +#define BIT(n) (1<<(n)) + +static unsigned char GT64260_ETH_irq[3] = { 32, 33, 34 }; + +static const char *version = "%F% %I% %G% %U% %#%"; + +u32 gt64260_base = CONFIG_MV64X60_NEW_BASE; + +/* set port config value */ + +static inline void +set_port_config(u32 value, unsigned int port) +{ + gt_write(GT64260_ENET_E0PCR + ETHERNET_PORTS_DIFFERENCE_OFFSETS * port, + value); +} + +/* get port config value */ + +inline u32 +get_port_config(unsigned int port) +{ + return gt_read(GT64260_ENET_E0PCR + ETHERNET_PORTS_DIFFERENCE_OFFSETS * port); +} + +/* + * Set Promiscuous mode to normal mode. + * in order to enable Filtering. XXX this should probably go away + */ +static inline void +enableFiltering(u32 port) +{ + ETHERNET_PCR portControlReg; + + portControlReg = get_port_config(port); + portControlReg &= ~(1 << PROMISCUOUS_MODE); + set_port_config(portControlReg, port); +} + +/* + * This function will set the Promiscuous mode to Promiscuous mode. + * in order to disable Filtering. XXX this should probably go away + */ +static inline void +disableFiltering(u32 port) +{ + ETHERNET_PCR portControlReg; + + portControlReg = get_port_config(port); + portControlReg |= (1 << PROMISCUOUS_MODE); + set_port_config(portControlReg, port); +} + +/* From pgtable.h */ +static __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va) +{ + pgd_t *dir = 0; + pmd_t *pmd = 0; + pte_t *pte = 0; + + va &= PAGE_MASK; + + dir = pgd_offset( mm, va ); + if (dir) + { + pmd = pmd_offset(dir, va & PAGE_MASK); + if (pmd && pmd_present(*pmd)) + { + pte = pte_offset_kernel(pmd, va); + } + } + return pte; +} + + + + +/* + * ---------------------------------------------------------------------------- + * Allocate the specified number of pages and mark them uncached. + * ASSUME: kmalloc() supplies page-aligned memory + * mapped to contiguous physical pages + */ +u32 +uncachedPages(u32 pages) +{ + pte_t *pte; + u32 addr; + u32 firstPage; + + firstPage = addr = (u32) kmalloc((pages * PAGE_SIZE), GFP_KERNEL); + if (!addr || (addr & ~PAGE_MASK)) { + panic("uncachedPages: can't get page-aligned memory.\n"); + } + while (pages--) { +// pte = va_to_pte(addr); + pte = my_find_pte(&init_mm, addr); + if (!pte) { + return firstPage; + } + pte_val(*pte) |= (_PAGE_NO_CACHE | _PAGE_GUARDED); +// flush_tlb_page(init_mm.mmap, addr); + flush_tlb_page(find_vma(&init_mm, addr), addr); + invalidate_dcache_range(addr, addr + PAGE_SIZE); + addr += PAGE_SIZE; + } + mb(); + return (firstPage); +} + +#ifdef PHY_LXT97x +static int +dump_intel_phy_state(struct net_device *dev) +{ + unsigned int mii_11 = 0; + gt_eth_priv *private = (gt_eth_priv *) dev->priv; + +#if 1 + etherReadMIIReg(private->port, 0x11, &mii_11); + printk(" mii:%s:%s:%s:%s %s:%s\n", + mii_11 & (1 << 14) ? "100" : " 10", + mii_11 & (1 << 10) ? " Link" : "nLink", + mii_11 & (1 << 9) ? "FD" : "HD", + mii_11 & (1 << 4) ? " FC" : "nFC", + mii_11 & (1 << 7) ? "ANc" : "ANnc", + mii_11 & (1 << 8) ? "AN" : "Manual"); +#else + int i; + for (i = 0; i < 0x15; i++) { + etherReadMIIReg(private->port, i, &mii_11); + printk(" mii %2d 0x%4x", i, mii_11); + if ((i % 4) == 3) + printk("\n"); + } + printk("\n"); +#endif + return 0; +} +#endif + +/* Sometimes it seems the phy and the GT don't always agree. + * Make sure they do, or restart autoneg. */ +static void +check_phy_state(struct net_device *dev) +{ + gt_eth_priv *private = (gt_eth_priv *) dev->priv; + struct mii_if_info *mii = &private->mii_if; + int bmsr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); + + if (mii_link_ok(&private->mii_if) && (bmsr & BMSR_ANEGCOMPLETE)) { + int advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); + int lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA); + int nego = mii_nway_result(advert & lpa); + int psr, wanted = 0; + + switch (nego) { + case LPA_100FULL: + wanted = 0x3; + break; + case LPA_100HALF: + wanted = 0x1; + break; + case LPA_10FULL: + wanted = 0x2; + break; + case LPA_10HALF: + wanted = 0x0; + break; + default: + printk("%s: MII negotiated strange settings %d\n", + dev->name, nego); + break; + } + psr = + gt_read(GT64260_ENET_E0PSR + + (ETH_ADDR_GAP * private->port)); + + if ((psr & 0x3) != wanted) { + printk + ("%s: MII said %x, GT said %x, restarting autoneg\n", + dev->name, wanted, psr); + mii_nway_restart(mii); + } + } +} + +static void +dump_link_state(struct net_device *dev) +{ + gt_eth_priv *private = (gt_eth_priv *) dev->priv; + unsigned int psr; + + psr = gt_read(GT64260_ENET_E0PSR + (ETH_ADDR_GAP * private->port)); + printk("%s: link state:\n" + " GT:%s:%s:%s:%s\n", + dev->name, + psr & 1 ? "100" : " 10", + psr & 8 ? " Link" : "nLink", + psr & 2 ? "FD" : "HD", psr & 4 ? " FC" : "nFC"); + +#ifdef PHY_LXT97x + dump_intel_phy_state(dev); +#endif +} + +/* + * ---------------------------------------------------------------------------- + * Create an addressTable entry from MAC address info + * found in the specifed net_device struct + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + */ +void +gt64260_eth_update_mac_address(struct net_device *dev) +{ + u32 macH; + u32 macL; + u8 *byte; + + byte = dev->dev_addr; + macH = byte[0]; + macH = (macH << 8) | byte[1]; + macL = byte[2]; + macL = (macL << 8) | byte[3]; + macL = (macL << 8) | byte[4]; + macL = (macL << 8) | byte[5]; + + /* + * addAddressTableEntry() will flush Dcache and sync + */ + addAddressTableEntry(((gt_eth_priv *) (dev->priv))->port, macH, macL, 1, + 0); +} + +/* + * ---------------------------------------------------------------------------- + * Set the MAC address for the specified interface + * to the specified value, forsaking all others. + * + * No special hardware thing should be done because XXX_MIKE - old commentary? + * interface is always put in promiscuous mode. XXX_MIKE - old commentary? + * + * Input : pointer to ethernet interface network device structure and + * a pointer to the designated entry to be added to the cache. + * Output : zero upon success, negative upon failure + */ +s32 +gt64260_eth_set_mac_address(struct net_device *dev, void *addr) +{ + u32 i; + struct sockaddr *sock; + + sock = (struct sockaddr *) addr; + for (i = 0; i < 6; i++) { + dev->dev_addr[i] = sock->sa_data[i]; + } + + addressTableClear(((gt_eth_priv *) (dev->priv))->port); /* Does flush */ + gt64260_eth_update_mac_address(dev); + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * Update the statistics structure in the private data structure + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + */ +void +gt64260_eth_update_stat(struct net_device *dev) +{ + gt_eth_priv *private; + struct net_device_stats *stat; + u32 base; + + private = dev->priv; + stat = &(private->stat); + + base = GT64260_ENET_0_MIB_CTRS + (private->port * ETH_ADDR_GAP); + + stat->rx_bytes += gt_read(base + 0x00); + stat->tx_bytes += gt_read(base + 0x04); + stat->rx_packets += gt_read(base + 0x08); + stat->tx_packets += gt_read(base + 0x0c); + stat->rx_errors += gt_read(base + 0x50); + + /* + * Rx dropped is for received packet with CRC error + */ + stat->rx_dropped += gt_read(base + 0x20); + stat->multicast += gt_read(base + 0x1c); + stat->collisions += gt_read(base + 0x30); + + /* + * detailed rx errors + */ + stat->rx_length_errors += gt_read(base + 0x60); + stat->rx_length_errors += gt_read(base + 0x24); + stat->rx_crc_errors += gt_read(base + 0x20); + + /* + * detailed tx errors - XXX_MIKE - INCOMPLETE IMPLEMENTATION ? + */ +} + +/* + * ---------------------------------------------------------------------------- + * Returns a pointer to the interface statistics. + * + * Input : dev - a pointer to the required interface + * + * Output : a pointer to the interface's statistics + */ +struct net_device_stats * +gt64260_eth_get_stats(struct net_device *dev) +{ + gt_eth_priv *private; + + gt64260_eth_update_stat(dev); + private = dev->priv; + return (&(private->stat)); +} + +/* + * ---------------------------------------------------------------------------- + * change rx mode + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + */ +void +gt64260_eth_set_rx_mode(struct net_device *dev) +{ + gt_eth_priv *private; + + private = dev->priv; + if (dev->flags & IFF_PROMISC) { + disableFiltering(private->port); + } else { + enableFiltering(private->port); + } +} + +#ifdef CONFIG_NET_FASTROUTE /* XXX_MIKE - ??? */ +/* + * ---------------------------------------------------------------------------- + * Used to authenticate to the kernel that a fast path entry can be + * added to device's routing table cache + * + * Input : pointer to ethernet interface network device structure and + * a pointer to the designated entry to be added to the cache. + * Output : zero upon success, negative upon failure + */ +static s32 +gt64260_eth_accept_fastpath(struct net_device *dev, struct dst_entry *dst) +{ + struct net_device *odev = dst->dev; + + if ((dst->ops->protocol != __constant_htons(ETH_P_IP)) + || (odev->type != ARPHRD_ETHER) + || !odev->accept_fastpath) { + return (-1); + } + return (0); +} +#endif /* #ifdef CONFIG_NET_FASTROUTE */ + +static int +mdio_read(struct net_device *dev, int phy_id, int location) +{ + unsigned int val; + + etherReadMIIReg(phy_id & 0x1f, location & 0x1f, &val); + + return (val & 0xffff); +} + +static void +mdio_write(struct net_device *dev, int phy_id, int location, int value) +{ + etherWriteMIIReg(phy_id & 0x1f, location & 0x1f, value); +} + +static int +netdev_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + gt_eth_priv *private = (gt_eth_priv *) dev->priv; + u32 ethcmd; + + if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) + return -EFAULT; + + switch (ethcmd) { + + /* Get driver info */ + case ETHTOOL_GDRVINFO:{ + struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; + strncpy(info.driver, "gt64260", + sizeof (info.driver) - 1); + strncpy(info.version, version, + sizeof (info.version) - 1); + if (copy_to_user(useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + /* get settings */ + case ETHTOOL_GSET:{ + struct ethtool_cmd ecmd = { ETHTOOL_GSET }; + spin_lock_irq(&private->lock); + mii_ethtool_gset(&private->mii_if, &ecmd); + spin_unlock_irq(&private->lock); + if (copy_to_user(useraddr, &ecmd, sizeof (ecmd))) + return -EFAULT; + return 0; + } + /* set settings */ + case ETHTOOL_SSET:{ + int r; + struct ethtool_cmd ecmd; + if (copy_from_user(&ecmd, useraddr, sizeof (ecmd))) + return -EFAULT; + spin_lock_irq(&private->lock); + r = mii_ethtool_sset(&private->mii_if, &ecmd); + spin_unlock_irq(&private->lock); + return r; + } + /* restart autonegotiation */ + case ETHTOOL_NWAY_RST:{ + return mii_nway_restart(&private->mii_if); + } + /* get link status */ + case ETHTOOL_GLINK:{ + struct ethtool_value edata = { ETHTOOL_GLINK }; + edata.data = mii_link_ok(&private->mii_if); + if (copy_to_user(useraddr, &edata, sizeof (edata))) + return -EFAULT; + return 0; + } + /* get message-level */ + case ETHTOOL_GMSGLVL:{ + struct ethtool_value edata = { ETHTOOL_GMSGLVL }; + edata.data = 0; /* XXX */ + if (copy_to_user(useraddr, &edata, sizeof (edata))) + return -EFAULT; + return 0; + } + /* set message-level */ + case ETHTOOL_SMSGLVL:{ + struct ethtool_value edata; + if (copy_from_user(&edata, useraddr, sizeof (edata))) + return -EFAULT; +/* debug = edata.data; *//* XXX */ + return 0; + } + } + return -EOPNOTSUPP; +} + +static int +gt64260_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct mii_ioctl_data *data = (struct mii_ioctl_data *) &rq->ifr_data; + int phy = dev->base_addr & 0x1f; + int retval; + + switch (cmd) { + case SIOCETHTOOL: + retval = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); + break; + + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + data->phy_id = phy; + /* Fall through */ + + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE + 1: /* for binary compat, remove in 2.5 */ + data->val_out = + mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f); + retval = 0; + break; + + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE + 2: /* for binary compat, remove in 2.5 */ + if (!capable(CAP_NET_ADMIN)) { + retval = -EPERM; + } else { + mdio_write(dev, data->phy_id & 0x1f, + data->reg_num & 0x1f, data->val_in); + retval = 0; + } + break; + + default: + retval = -EOPNOTSUPP; + break; + } + return retval; +} + +/* + * ---------------------------------------------------------------------------- + * Initializes the ethernet interface's private structure. + * Statistics, descriptors, etc... + * + * Input : pointer to network device structure to be filled + * Output : N/A + */ +void +gt64260_eth_init_priv(struct net_device *dev) +{ + gt_eth_priv *private; + u32 queue; + + private = (gt_eth_priv *) kmalloc(sizeof (*private), GFP_KERNEL); + if (!private) { + panic("gt64260_eth_init_priv : kmalloc1 failed\n"); + } + dev->priv = (void *) private; + memset(private, 0, sizeof (*(private))); + + /* + * The GT64260 Enet engine accesses its queues of DMA + * descriptors in uncached mode, so we dedicate a page + * for each queue and mark each such page uncached. + */ + for (queue = 0; queue < NUM_TX_QUEUES; queue++) { + private->TXqueue[queue] = (gt_dma_desc *) uncachedPages(1); + } + + for (queue = 0; queue < NUM_RX_QUEUES; queue++) { + private->RXqueue[queue] = (gt_dma_desc *) uncachedPages(1); + } + + private->mii_if.dev = dev; + private->mii_if.phy_id = dev->base_addr; + private->mii_if.mdio_read = mdio_read; + private->mii_if.mdio_write = mdio_write; + private->mii_if.advertising = + mdio_read(dev, dev->base_addr, MII_ADVERTISE); + + spin_lock_init(&private->lock); /* XXX_MIKE - broken for SMP */ +} + +/* + * ---------------------------------------------------------------------------- + * Currently a no-op. According to previous commentary, the hardware + * "cannot [!] be stuck because it is a built-in hardware - if we reach + * here the ethernet port might be [physically] disconnected..." + */ +void +gt64260_eth_tx_timeout(struct net_device *dev) +{ +} + +/* + * ---------------------------------------------------------------------------- + * First function called after registering the network device. + * It's purpose is to initialize the device as an ethernet device, + * fill the structure that was given in registration with pointers + * to functions, and setting the MAC address of the interface + * + * Input : pointer to network device structure to be filled + * Output : -ENONMEM if failed, 0 if success + */ +void +gt64260_eth_str2mac(char *str, unsigned char *mac) +{ + int i; + + for (i = 0; i < 12; i += 2) { + mac[i / 2] = ((isdigit(str[i]) ? + str[i] - '0' : + (toupper(str[i]) - 'A' + 10)) << 4) | + (isdigit(str[i + 1]) ? + str[i + 1] - '0' : (toupper(str[i + 1]) - 'A' + 10)); + } + + return; +} + +s32 +gt64260_eth_init(int port_num) +{ +#ifdef CONFIG_GT64260_ETH_2 + static u32 gt64260_eth2_initialized = 0; +#endif /* #ifdef GT64260_ETH_P2 */ +#ifdef CONFIG_GT64260_ETH_1 + static u32 gt64260_eth1_initialized = 0; +#endif +#ifdef CONFIG_GT64260_ETH_0 + static u32 gt64260_eth0_initialized = 0; +#endif + gt_eth_priv *private; + struct net_device *dev; + + dev = alloc_etherdev(sizeof (gt_eth_priv)); + if (!dev) { + panic("gt64260_eth_init : init_etherdev failed\n"); + } + gt64260_eth_init_priv(dev); + private = (gt_eth_priv *) (dev->priv); + + dev->open = gt64260_eth_open; + dev->stop = gt64260_eth_stop; + dev->set_config = NULL; /* no runtime config support for now */ + dev->hard_start_xmit = gt64260_eth_start_xmit; + dev->do_ioctl = gt64260_ioctl; + dev->get_stats = gt64260_eth_get_stats; + dev->set_mac_address = gt64260_eth_set_mac_address; + dev->set_multicast_list = gt64260_eth_set_rx_mode; + dev->tx_timeout = gt64260_eth_tx_timeout; /* Currently no-op */ + dev->watchdog_timeo = 2 * HZ; + dev->flags &= ~IFF_RUNNING; + dev->base_addr = port_num; + +#ifdef CONFIG_NET_FASTROUTE + dev->accept_fastpath = gt64260_eth_accept_fastpath; +#endif /* #ifdef CONFIG_NET_FASTROUTE */ + +#if 0 +#ifdef CONFIG_PPCBOOT + memcpy(dev->dev_addr, boardinfo.bi_enetaddr, 6); +#else /* #ifdef CONFIG_PPCBOOT */ +#if 0 + memcpy(dev->dev_addr, eeprom_param.eth0_mac, 6); +#else + dev->dev_addr[0] = 0x00; + dev->dev_addr[1] = 0xa0; + dev->dev_addr[2] = 0xf7; + dev->dev_addr[3] = 0x33; + dev->dev_addr[4] = 0x34; + dev->dev_addr[5] = 0x36; +#endif +#endif /* #else #ifdef CONFIG_PPCBOOT */ +#endif + + + if (dev->base_addr == 0 || dev->base_addr == 2) { + /* FIXME: find who else is modifying this * (other than ev64260_pci.c) + * Maybe MPSC? - NTL */ +#ifdef TWO_ETHERNET_MII_PORTS + if (dev->base_addr == 0) { + /* connect port 0 to MII */ + gt_set_bits(GT64260_MPP_SERIAL_PORTS_MULTIPLEX, + (1 << 0)); + gt_clr_bits(GT64260_MPP_SERIAL_PORTS_MULTIPLEX, + (1 << 1)); + /* port 1 is RMII/MII */ + /* nothing */ + } +#endif +#ifdef THREE_ETHERNET_RMII_PORTS + /* connect port 0+2 to RMII */ + gt_clr_bits(GT64260_MPP_SERIAL_PORTS_MULTIPLEX, (1 << 0)); + gt_set_bits(GT64260_MPP_SERIAL_PORTS_MULTIPLEX, (1 << 1)); + /* port 1 is RMII/MII */ + /* nothing */ +#endif + } + + switch (dev->base_addr) { +#ifdef CONFIG_GT64260_ETH_0 + case 0: + if (!gt64260_eth0_initialized) { + if (gt64260_i2cMacGet(dev->dev_addr, 0) == -1) { + printk("%s: Couldn't Read Srom MAC address\n", + dev->name); +#ifdef CONFIG_GT64260_ETH_0_MACADDR + gt64260_eth_str2mac(CONFIG_GT64260_ETH_0_MACADDR, + &dev->dev_addr[0]); +#else + + if (ppcboot_bd_valid && + *((unsigned long *) ppcboot_bd.bi_enetaddr) != 0) { + memcpy(dev->dev_addr, + ppcboot_bd.bi_enetaddr, 6); + } else { + printk("%s: Couldn't assign MAC address\n", + dev->name); + return (-ENODEV); + } +#endif + } + private->port = 0; + gt_write(GT64260_ENET_E0SDCR, (2 << 12) | (1 << 9) | (0xf << 2)); // 0000.203c + + /* enable */ + gt_set_bits(GT64260_ENET_E0PCR, (1 << 7)); + /* no promisc */ + gt_clr_bits(GT64260_ENET_E0PCR, (1 << 0)); + + /* + * Receive packets in 1536 bit max length and enable DSCP + */ + gt_write(GT64260_ENET_E0PCXR, + PORT_CONTROL_EXTEND_VALUE); + + /* + * Initialize address table for hash mode 0 with 1/2K size + */ + initAddressTable(private->port, 0, 1, 0); + gt64260_eth0_initialized = 1; + } + break; +#endif /* #ifdef GT64260_ETH_0 */ + +#if 0 + +#ifdef CONFIG_GT64260_ETH_1 /* XXX_MIKE - broken logic? */ + case 1: + if (!gt64260_eth1_initialized) { +#ifdef CONFIG_GT64260_ETH_1_MACADDR + gt64260_eth_str2mac(CONFIG_GT64260_ETH_1_MACADDR, + &dev->dev_addr[0]); +#else + if (ppcboot_bd_valid && + *((unsigned long *) ppcboot_bd.bi_enet1addr) != 0) { + memcpy(dev->dev_addr, ppcboot_bd.bi_enet1addr, + 6); + } else { + printk("%s: Couldn't assign MAC address\n", + dev->name); + return (-ENODEV); + } +#endif + private->port = 1; + gt_write(GT64260_ENET_E1SDCR, 0x0000203c); + + /* enable */ + gt_set_bits(GT64260_ENET_E1PCR, (1 << 7)); + /* no promisc */ + gt_clr_bits(GT64260_ENET_E1PCR, (1 << 0)); + + gt_write(GT64260_ENET_E1PCXR, + PORT_CONTROL_EXTEND_VALUE); + + /* + * Initialize address table for hash mode 0 with 1/2K size + */ + initAddressTable(private->port, 0, 1, 0); + gt64260_eth1_initialized = 1; + } + break; +#endif /* #ifdef GT64260_ETH_P1 */ +#ifdef CONFIG_GT64260_ETH_2 + case 2: + if (!gt64260_eth2_initialized) { +#ifdef CONFIG_GT64260_ETH_2_MACADDR + gt64260_eth_str2mac(CONFIG_GT64260_ETH_2_MACADDR, + &dev->dev_addr[0]); +#else + if (ppcboot_bd_valid && + *((unsigned long *) ppcboot_bd.bi_enet2addr) != 0) { + memcpy(dev->dev_addr, ppcboot_bd.bi_enet2addr, + 6); + } else { + printk("%s: Couldn't assign MAC address\n", + dev->name); + return (-ENODEV); + } +#endif + private->port = 2; + gt_write(GT64260_ENET_E2SDCR, 0x0000203c); + + /* enable */ + gt_set_bits(GT64260_ENET_E2PCR, (1 << 7)); + /* no promisc */ + gt_clr_bits(GT64260_ENET_E2PCR, (1 << 0)); + + gt_write(GT64260_ENET_E2PCXR, + PORT_CONTROL_EXTEND_VALUE); + + /* + * Initialize address table for hash mode 0 with 1/2K size + */ + initAddressTable(private->port, 0, 1, 0); + gt64260_eth2_initialized = 1; + } + break; +#endif + +#endif + default: + return (-ENODEV); /* Trouble if we haven't returned by this point... */ + } + /* + * Read MIB counters on the GT in order to reset them, + * then zero all the stats fields in memory + */ + gt64260_eth_update_stat(dev); + + if (register_netdev(dev) != 0) { + kfree(private); + kfree(dev); + return -ENODEV; + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * This function is called when opening the network device. The function + * should initialize all the hardware, initialize cyclic Rx/Tx + * descriptors chain and buffers and allocate an IRQ to the network + * device. + * + * Input : a pointer to the network device structure + * + * Output : zero if success, nonzero if fails. + */ +s32 +gt64260_eth_open(struct net_device * dev) +{ + gt_dma_desc *desc; + gt_eth_priv *priv; + s32 retval; + struct sk_buff *sk; + u32 count; + u32 gap; + u32 port; + u32 port_status; + u32 queue; + + priv = dev->priv; + + /* + * Initialize the lists of Tx/Rx descriptors (as circular chains, + * each in its own uncached page) using the physical addresses in + * the "next" pointers that the Enet DMA engine expects. The Rx + * descriptors also get an sk_buff pre-allocated for them and their + * "data" pointers set to point to the corresponding sk_buff buffer. + */ + for (queue = 0; queue < NUM_TX_QUEUES; queue++) { + priv->TXskbIndex[queue] = priv->TXindex[queue] = 0; + desc = priv->TXqueue[queue]; + memset((void *) desc, 0, PAGE_SIZE); /* The whole list. */ + for (count = 0; count < Q_INDEX_LIMIT; count++, desc++) { + desc->next = virt_to_phys((void *) (desc + 1)); + priv->TXskbuff[queue][count] = 0; + } + --desc; /* Link last back to first. */ + desc->next = virt_to_phys((void *) (priv->TXqueue[queue])); + flush_dcache_addr_size((u32) (priv->TXqueue[queue]), PAGE_SIZE); + } + + for (queue = 0; queue < NUM_RX_QUEUES; queue++) { + priv->RXindex[queue] = 0; + desc = priv->RXqueue[queue]; + memset((void *) desc, 0, PAGE_SIZE); /* The whole list. */ + for (count = 0; count < Q_INDEX_LIMIT; count++, desc++) { + desc->next = virt_to_phys((void *) (desc + 1)); + desc->count.rx.bufferBytes = MAX_BUFF_SIZE; /* XXX_MIKE: really? */ + desc->command_status = GT_ENET_DESC_OWNERSHIP + | GT_ENET_DESC_INT_ENABLE; + + sk = dev_alloc_skb(MAX_BUFF_SIZE); + desc->data = (void *) virt_to_phys((void *) (sk->data)); + priv->RXskbuff[queue][count] = sk; + invalidate_dcache_range((u32) (sk->data), + (u32) (sk->data) + + MAX_BUFF_SIZE); + } + --desc; /* Link last back to first. */ + desc->next = virt_to_phys((void *) (priv->RXqueue[queue])); + flush_dcache_addr_size((u32) (priv->RXqueue[queue]), PAGE_SIZE); + } + + /* + * Update Hash Table with the dedicated MAC address + * XXX_MIKE - why "update" rather than "set" ? + */ + gt64260_eth_update_mac_address(dev); + + /* + * Initialize DMA descriptor-pointer registers + */ + port = priv->port; + gap = ETH_ADDR_GAP * port; + + gt_write(GT64260_ENET_E0CTDP0 + gap, + virt_to_phys((void *) priv->TXqueue[0])); + gt_write(GT64260_ENET_E0CTDP1 + gap, + virt_to_phys((void *) priv->TXqueue[1])); + + gt_write(GT64260_ENET_E0FRDP0 + gap, + virt_to_phys((void *) priv->RXqueue[0])); + gt_write(GT64260_ENET_E0CRDP0 + gap, + virt_to_phys((void *) priv->RXqueue[0])); + gt_write(GT64260_ENET_E0FRDP1 + gap, + virt_to_phys((void *) priv->RXqueue[1])); + gt_write(GT64260_ENET_E0CRDP1 + gap, + virt_to_phys((void *) priv->RXqueue[1])); + gt_write(GT64260_ENET_E0FRDP2 + gap, + virt_to_phys((void *) priv->RXqueue[2])); + gt_write(GT64260_ENET_E0CRDP2 + gap, + virt_to_phys((void *) priv->RXqueue[2])); + gt_write(GT64260_ENET_E0FRDP3 + gap, + virt_to_phys((void *) priv->RXqueue[3])); + gt_write(GT64260_ENET_E0CRDP3 + gap, + virt_to_phys((void *) priv->RXqueue[3])); + + /* + * Set IP TOS Rx priority queueing + * These registers not #defined in header file. Manual description: + * IP Differentiated Services CodePoint to Priority[01] {low,high} + */ + gt_write(0x2460 + gap, 0xffff0000); + gt_write(0x2464 + gap, 0xffff0000); + gt_write(0x2468 + gap, 0x00000000); + gt_write(0x246c + gap, 0xffffffff); + + /* + * Allocate IRQ + */ +#if 0 /* XXXX */ + for (EVB64260_ETH_irq[port] = 8; + EVB64260_ETH_irq[port] < 32; EVB64260_ETH_irq[port]++) { +#endif + retval = request_irq(GT64260_ETH_irq[port] + gt64260_irq_base, + gt64260_eth_int_handler, + (SA_INTERRUPT | SA_SAMPLE_RANDOM), + "GT64260_Eth", dev); + if (!retval) { + dev->irq = GT64260_ETH_irq[port] + gt64260_irq_base; + printk + ("gt64260_eth_open : Assigned IRQ %d to gt64260_eth%d\n", + dev->irq, port); +#if 0 /* XXXX */ + break; +#endif + } +#if 0 /* XXXX */ + } +#endif + if (retval) { /* XXX_MIKE - flawed logic... */ + printk("Can not assign IRQ number to GT64260_eth%d\n", port); + GT64260_ETH_irq[port] = 0; + return (-1); + } + + /* + * clear all interrupts + */ + gt_write(GT64260_ENET_E0ICR + gap, 0x000000000); + + /* + * enable relevant interrupts on GT + */ + gt_write(GT64260_ENET_E0IMR + gap, 0xb0ff010d); + + /* + * Enable interrupts in high cause register + */ + gt_set_bits(GT64260_IC_CPU_INTR_MASK_HI, BIT(0) << port); + + /* + * Check Link status on Ethernet0 + */ + port_status = gt_read(GT64260_ENET_E0PSR + gap); + if (!(port_status & 0x8)) { + netif_stop_queue(dev); + dev->flags &= ~IFF_RUNNING; + } else { + netif_start_queue(dev); + dev->flags |= IFF_RUNNING; + } + + check_phy_state(dev); + dump_link_state(dev); + /* + * start RX (BIT(7) == EnableRXdma) + */ + gt_write(GT64260_ENET_E0SDCMR + gap, BIT(7)); + spin_lock_init(&dev->xmit_lock); + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * This function is used when closing the network device. It should update + * the hardware, release all memory that holds buffers and descriptors and + * release the IRQ. + * Input : a pointer to the device structure + * Output : zero if success, nonzero if fails + */ +int +gt64260_eth_stop(struct net_device *dev) +{ + gt_eth_priv *priv; + u32 queue; + u32 count; + + priv = dev->priv; + + /* + * stop RX and mask interrupts + */ + gt_clr_bits(GT64260_IC_CPU_INTR_MASK_HI, (BIT(0) << priv->port)); + gt_write(GT64260_ENET_E0SDCMR + + (ETH_ADDR_GAP * priv->port), 0x00008000); + netif_stop_queue(dev); + + /* + * Free RX pre allocated SKB's + */ + for (queue = 0; queue < NUM_RX_QUEUES; queue++) { + for (count = 0; count < Q_INDEX_LIMIT; count++) { + if (priv->RXskbuff[queue][count]) { + dev_kfree_skb(priv->RXskbuff[queue][count]); + priv->RXskbuff[queue][count] = 0; + } + } + } + +#if 0 /* XXXX */ + GT64260_ETH_irq[priv->port] = 0; +#endif + free_irq(dev->irq, dev); + + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * This function queues a packet in the Tx descriptor for required + * port. It checks the IPTOS_PREC_FLASHOVERRIDE bit of the ToS + * field in the IP header and decides where to queue the packet, + * in the high priority queue or in the low priority queue. + * + * Input : skb - a pointer to socket buffer + * dev - a pointer to the required port + * + * Output : zero upon success, negative number upon failure + * (-EBUSY when the interface is busy) + */ +int +gt64260_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + gt_eth_priv *priv; + gt_dma_desc *tx; + struct iphdr *iph; + u32 queue; + u32 TXindex; + + iph = skb->nh.iph; + priv = dev->priv; + spin_lock_irq(&(priv->lock)); + + /* + * Paranoid check - this shouldn't happen + */ + if (skb == NULL) { + priv->stat.tx_dropped++; + return (1); + } + + /* + * Queue packet to either queue 0 (high priority) or 1 (low + * priority) depending on the MSB of the TOS in the IP header + */ + queue = !(IPTOS_PREC(iph->tos) & IPTOS_PREC_FLASHOVERRIDE); + dev->trans_start = jiffies; /* timestamp */ + TXindex = priv->TXindex[queue]; + if (priv->TXskbuff[queue][TXindex]) { + panic("Error on gt64260_eth device driver"); + } + + priv->TXskbuff[queue][TXindex] = skb; + tx = &(priv->TXqueue[queue][TXindex]); + invalidate_dcache_range((u32) tx, (u32) tx); + mb(); + tx->data = (void *) virt_to_phys((void *) skb->data); + tx->count.tx.bytes = skb->len; + + /* + * Flush/sync now before transferring ownership. + */ + flush_dcache_addr_size((u32) skb->data, skb->len); + + /* + * Don't generate interrupts upon routed packets, + * only when reached threshold + */ +#ifdef CONFIG_NET_FASTROUTE + if ((skb->pkt_type == PACKET_FASTROUTE) + && !(TXindex % GT64260_INT_THRE)) { + priv->TXqueue[queue][TXindex].command_status = + BIT(31) | BIT(22) | (7 << 16); + } else { +#endif /* #ifdef CONFIG_NET_FASTROUTE */ + /* + * XXX_MIKE - document these magic numbers and logic + */ + wmb(); + if (1 /*skb->nf.iph->saddr */ ) { + tx->command_status = + (1 << 31) | (1 << 23) | (1 << 22) | (7 << 16); + } else { + if (TXindex % GT64260_INT_THRE) { + tx->command_status = + (1 << 31) | (1 << 22) | (7 << 16); + } else { + tx->command_status = + (1 << 31) | (1 << 23) | (1 << 22) | (7 << + 16); + } + } +#ifdef CONFIG_NET_FASTROUTE + } +#endif /* #ifdef CONFIG_NET_FASTROUTE */ + + /* + * Officially transfer ownership of descriptor to GT + */ + flush_dcache(tx); + mb(); + + TXindex++; + if (TXindex == Q_INDEX_LIMIT) { + TXindex = 0; + } + + /* + * If next descriptor is GT owned then the tx queue is full + * XXX_MIKE - possession of sk_buff is unambiguous sign? + */ + if (priv->TXskbuff[queue][TXindex]) { + // printk ("Stopping queue on port %d\n",priv->port); + netif_stop_queue(dev); + } + priv->TXindex[queue] = TXindex; + + /* + * Start Tx LOW dma + */ + gt_write(GT64260_ENET_E0SDCMR + + (ETH_ADDR_GAP * priv->port), queue ? (1 << 23) : (1 << 24)); + + spin_unlock_irq(&priv->lock); + + return (0); /* success */ +} + +/* + * ---------------------------------------------------------------------------- + * This function is forward packets that are received from the port's + * queues toward kernel core or FastRoute them to another interface. + * + * Input : dev - a pointer to the required interface + * + * Output : number of served packets + */ +u32 +gt64260_eth_receive_queue(struct net_device * dev, s32 queue, u32 max) +{ + gt_eth_priv *priv; + gt_dma_desc *rx; + struct sk_buff *skb; + u32 RXindex; + u32 served; +#ifdef CONFIG_NET_FASTROUTE + struct ethhdr *eth; + struct iphdr *iph; + struct net_device *odev; + struct rtable *rt; + u32 CPU_ID = smp_processor_id(); + u32 fast_routed = 0; + u32 h; +#endif /* #ifdef CONFIG_NET_FASTROUTE */ + + priv = dev->priv; + RXindex = priv->RXindex[queue]; /* Where we left off... */ + served = 0; + while (max) { +#ifdef CONFIG_NET_FASTROUTE + fast_routed = 0; +#endif /* #ifdef CONFIG_NET_FASTROUTE */ + rx = &(priv->RXqueue[queue][RXindex]); + invalidate_dcache(rx); + mb(); + if (rx->command_status & GT_ENET_DESC_OWNERSHIP) { + break; + } + max--; + + /* + * If received packet has errors, keep the socket buffer and change + * descriptor to GT owner ship and continue analyzing next descriptor. + */ + if (rx->command_status & GT_ENET_DESC_ERROR_SUMMARY) { + rx->command_status = GT_ENET_DESC_OWNERSHIP + | GT_ENET_DESC_INT_ENABLE; + flush_dcache(rx); + mb(); + RXindex++; + if (RXindex == Q_INDEX_LIMIT) { + RXindex = 0; + } + continue; + } + served++; + skb = priv->RXskbuff[queue][RXindex]; + invalidate_dcache(rx); + mb(); + if (skb) { + if (skb->len) { + printk + ("gt64260_eth_receive_queue: nonzero existing SKB\n"); + dev_kfree_skb(skb); + skb = dev_alloc_skb(MAX_BUFF_SIZE); + } + + /* + * XXX_MIKE - document these magic numbers + */ + skb_put(skb, (rx->count.rx.bytesReceived - 4)); + invalidate_dcache(rx); + mb(); + +#ifdef CONFIG_NET_FASTROUTE + /* + * Fast Route + */ + eth = (struct ethhdr *) skb->data; + if (eth->h_proto == __constant_htons(ETH_P_IP)) { + iph = (struct iphdr *) (skb->data + ETH_HLEN); + h = (*(u8 *) & iph->daddr + ^ *(u8 *) & iph-> + saddr) & NETDEV_FASTROUTE_HMASK; + rt = (struct rtable *) (dev->fastpath[h]); + if (rt + && ((u16 *) & iph->daddr)[0] == + ((u16 *) & rt->key.dst)[0] + && ((u16 *) & iph->daddr)[1] == + ((u16 *) & rt->key.dst)[1] + && ((u16 *) & iph->saddr)[0] == + ((u16 *) & rt->key.src)[0] + && ((u16 *) & iph->saddr)[1] == + ((u16 *) & rt->key.src)[1] + && !rt->u.dst.obsolete) { + odev = rt->u.dst.dev; + netdev_rx_stat[CPU_ID].fastroute_hit++; + + if (*(u8 *) iph == 0x45 && !(eth->h_dest[0] & 0x80) /* This should be 0x80 */ + &&neigh_is_valid(rt->u.dst. + neighbour) + && iph->ttl > 1) { /* Fast Route Path */ + fast_routed = 1; + if ((!netif_queue_stopped(odev)) + && + (!spin_is_locked + (&odev->xmit_lock))) { + skb->pkt_type = + PACKET_FASTROUTE; + skb->protocol = + __constant_htons + (ETH_P_IP); + + ip_decrease_ttl(iph); + +#if 0 + /* + * UNNECESSARY - a CRC is performed by hardware + */ + skb->ip_summed = + CHECKSUM_NONE; + ip_statistics. + IpInReceives++; + ip_statistics. + IpForwDatagrams++; +#endif /* #if 0 */ + memcpy(eth->h_source, + odev->dev_addr, + 6); + memcpy(eth->h_dest, + rt->u.dst. + neighbour->ha, + 6); + skb->dev = odev; + if (odev-> + hard_start_xmit(skb, + odev) + != 0) { + panic + ("Shit, what went wrong ??!!"); + } + netdev_rx_stat[CPU_ID]. + fastroute_success++; + } else { /* Semi Fast Route Path */ + skb->pkt_type = + PACKET_FASTROUTE; + skb->nh.raw = + skb->data + + ETH_HLEN; + skb->protocol = + __constant_htons + (ETH_P_IP); + netdev_rx_stat[CPU_ID]. + fastroute_defer++; + netif_rx(skb); + } + } + } + } + + if (fast_routed == 0) +#endif /* #ifdef CONFIG_NET_FASTROUTE */ + { + + skb->protocol = eth_type_trans(skb, dev); + skb->pkt_type = PACKET_HOST; + skb->ip_summed = CHECKSUM_NONE; //UNNECESSARY; /* CRC performed by hardware */ + skb->dev = dev; + netif_rx(skb); + } + } + + skb = dev_alloc_skb(MAX_BUFF_SIZE); + priv->RXskbuff[queue][RXindex] = skb; + if (!skb) { + /* + * No memory, quit meantime, and will try to + * recover next received packet or using watchdog + */ + printk("Ethernet ev64260 port %d - no mem\n", + priv->port); + break; /* XXX_MIKE - descriptor not updated? */ + } else { + invalidate_dcache_range((u32) (skb->data), + (u32) (skb->data) + + MAX_BUFF_SIZE); + } + skb->dev = dev; + rx->data = (void *) virt_to_phys((void *) skb->data); + + /* + * Officially transfer ownership of descriptor to GT + */ + rx->command_status = 0x80800000; /* GT owner bit */ + flush_dcache(rx); + mb(); + + RXindex++; + if (RXindex == Q_INDEX_LIMIT) { + RXindex = 0; + } + } + + priv->RXindex[queue] = RXindex; + + return (served); +} + +/* + * ---------------------------------------------------------------------------- + * Input : dev - a pointer to the required interface + * + * Output : N/A + */ +u32 +gt64260_eth_free_tx_queue(struct net_device * dev, s32 queue) +{ + gt_eth_priv *priv; + gt_dma_desc *tx; + struct sk_buff *sk; + u32 freed_skbs; + u32 TXskbIndex; + + priv = dev->priv; + spin_lock(&(priv->lock)); + freed_skbs = 0; + TXskbIndex = priv->TXskbIndex[queue]; + while (1) { + sk = priv->TXskbuff[queue][TXskbIndex]; + if (!sk) { + break; + } + tx = &(priv->TXqueue[queue][TXskbIndex]); /* No write to tx here */ + invalidate_dcache(tx); + mb(); + + if (tx->command_status & 0x80000000) { + break; + } + if (tx->command_status & 0x40) { + priv->stat.tx_fifo_errors++; + } + dev_kfree_skb_irq(sk); + priv->TXskbuff[queue][TXskbIndex] = 0; + TXskbIndex++; + if (TXskbIndex == Q_INDEX_LIMIT) { + TXskbIndex = 0; + } + freed_skbs++; + } + priv->TXskbIndex[queue] = TXskbIndex; + spin_unlock(&(priv->lock)); + + return (freed_skbs); +} + +/* + * ---------------------------------------------------------------------------- + */ +static irqreturn_t +gt64260_eth_int_handler(s32 irq, void *dev_id, struct pt_regs *regs) +{ + gt_eth_priv *priv; + struct net_device *dev; + u32 eth_int_cause; + u32 gap; + + dev = (struct net_device *) dev_id; + priv = dev->priv; + gap = (ETH_ADDR_GAP * priv->port); + eth_int_cause = gt_read(GT64260_ENET_E0ICR + gap); + + if (eth_int_cause & 0xcc) { /* XXX_MIKE - document this */ + if (eth_int_cause & 0x88) { /* Free queue 0, which is TxBufferHigh */ + gt64260_eth_free_tx_queue(dev, 0); + } + if (eth_int_cause & 0x44) { /* Free queue 1, which is TxBufferLow */ + gt64260_eth_free_tx_queue(dev, 1); + } + if (netif_queue_stopped(dev) + && (priv->TXskbuff[0][priv->TXindex[0]] == 0) + && (priv->TXskbuff[1][priv->TXindex[1]] == 0) + && (dev->flags & IFF_RUNNING)) { + netif_wake_queue(dev); + } + eth_int_cause &= ~0xcc; + gt_write(GT64260_ENET_E0ICR + gap, ~(u32) 0xcc); + } + + if (eth_int_cause & 0x101) { /*RxBuffer, RxResource Error */ + /* + * Serve 4 Queues starting from the one with highest priority + */ + if (eth_int_cause & 0x00880100) { + /* + * Rx Return Buffer / Resource Error Priority queue 3 + */ + gt64260_eth_receive_queue(dev, 3, 50); + } + if (eth_int_cause & 0x00440100) { + /* + * Rx Return Buffer / Resource Error Priority queue 2 + */ + gt64260_eth_receive_queue(dev, 2, 25); + } + if (eth_int_cause & 0x00220100) { + /* + * Rx Priority Return Buffer / Resource Error queue 1 + */ + gt64260_eth_receive_queue(dev, 1, 13); + } + if (eth_int_cause & 0x00110100) { + /* + * Rx Priority Return Buffer / Resource Error queue 0 + */ + gt64260_eth_receive_queue(dev, 0, 12); + } + + /* + * start/continue ethernet 0 RX + */ + gt_write(GT64260_ENET_E0SDCMR + gap, (1 << 7)); + eth_int_cause &= ~0x00ff0101; + gt_write(GT64260_ENET_E0ICR + gap, ~0x00ff0101); + } + + if (eth_int_cause & 0x10000000) { /* MII PHY status changed */ + u32 port_status; + + /* + * Check Link status on Ethernet0 + */ + port_status = gt_read(GT64260_ENET_E0PSR + gap); + if (!(port_status & 0x8)) { + if (netif_carrier_ok(dev)) { + printk("%s: changed link status to DOWN\n", + dev->name); + netif_carrier_off(dev); + } + } else { + if (!netif_carrier_ok(dev)) { + printk("%s: changed link status to UP\n", + dev->name); + netif_carrier_on(dev); + } + + /* + * start/continue ethernet 0 TX + */ + gt_write(GT64260_ENET_E0SDCMR + + (0x4000 * priv->port), + ((1 << 23) | (1 << 24))); + } + eth_int_cause &= ~0x10000000; + gt_write(GT64260_ENET_E0ICR + gap, ~0x10000000); + } + + if (eth_int_cause & 0x20000000) { /* MII SMI complete */ + eth_int_cause &= ~0x20000000; + gt_write(GT64260_ENET_E0ICR + gap, ~0x20000000); + } + + if (eth_int_cause & ~(1 << 31)) { + printk("%s: unhandled int %08x\n", dev->name, eth_int_cause); + gt_write(GT64260_ENET_E0ICR + gap, 0); + } + + return IRQ_HANDLED; +} + +typedef struct addressTableEntryStruct { + u32 hi; + u32 lo; +} addrTblEntry; + +static u32 addressTableHashMode[MAX_NUMBER_OF_ETHERNET_PORTS]; +static u32 addressTableHashSize[MAX_NUMBER_OF_ETHERNET_PORTS]; +static addrTblEntry *addressTableBase[MAX_NUMBER_OF_ETHERNET_PORTS]; + +static u32 hashLength[MAX_NUMBER_OF_ETHERNET_PORTS] = { + (0x8000), /* XXX_MIKE - are these correct? *//* 32K entries */ + (0x8000 / 16), /* 2K entries */ +}; + +/* + * clear the address table + * port - ETHERNET port number. + */ +static void +addressTableClear(u32 port) +{ + memset((void *) addressTableBase[port], + 0, (hashLength[addressTableHashSize[port]] * MAC_ENTRY_SIZE)); + + flush_dcache_addr_size((u32) (addressTableBase[port]), + (hashLength[addressTableHashSize[port]] + * MAC_ENTRY_SIZE)); +} + +/* + * ---------------------------------------------------------------------------- + * This function will initialize the address table and will enableFiltering. + * Inputs + * hashMode - hash mode 0 or hash mode 1. + * hashSizeSelector - indicates number of hash table entries (0=0x8000,1=0x800) + * hashDefaultMode - 0 = discard addresses not found in the address table, + * 1 = pass addresses not found in the address table. + * port - ETHERNET port number. + * Outputs + * address table is allocated and initialized. + * Always returns TRUE + */ + +static int +initAddressTable(u32 port, + u32 hashMode, u32 hashSizeSelector, u32 hashDefaultMode) +{ + u32 addr; + u32 bytes; + ETHERNET_PCR portControlReg; + + addressTableHashMode[port] = hashMode; + addressTableHashSize[port] = hashSizeSelector; + + /* + * Allocate memory for the address table, which must reside + * on an 8-byte boundary. + */ + bytes = MAC_ENTRY_SIZE * hashLength[hashSizeSelector]; + if (bytes & ~PAGE_MASK) { + panic("initAddressTable: computed size isn't page-multiple.\n"); + } + addr = uncachedPages(bytes >> PAGE_SHIFT); + memset((void *) addr, 0, bytes); + flush_dcache_addr_size(addr, bytes); + gt_write(GT64260_ENET_E0HTPR + + (ETHERNET_PORTS_DIFFERENCE_OFFSETS * port), + virt_to_phys((void *) addr)); + + invalidate_dcache_range(addr, addr + bytes); + mb(); + addressTableBase[port] = (addrTblEntry *) addr; + + /* + * set hash {size,mode} and HDM in the PCR + */ + portControlReg = get_port_config(port); + portControlReg &= ~((1 << HASH_DEFAULT_MODE) | (1 << HASH_MODE) + | (1 << HASH_SIZE)); + + portControlReg |= ((hashDefaultMode << HASH_DEFAULT_MODE) + | (hashMode << HASH_MODE) + | (hashSizeSelector << HASH_SIZE)); + + set_port_config(portControlReg, port); + enableFiltering(port); + + return (TRUE); +} + +/* + * ---------------------------------------------------------------------------- + * This function will calculate the hash function of the address. + * depends on the hash mode and hash size. + * Inputs + * macH - the 2 most significant bytes of the MAC address. + * macL - the 4 least significant bytes of the MAC address. + * hashMode - hash mode 0 or hash mode 1. + * hashSizeSelector - indicates number of hash table entries (0=0x8000,1=0x800) + * Outputs + * return the calculated entry. + */ +static u32 +hashTableFunction(u32 macH, u32 macL, u32 HashSize, u32 hash_mode) +{ + u32 hashResult; + u32 addrH; + u32 addrL; + u32 addr0; + u32 addr1; + u32 addr2; + u32 addr3; + u32 addrHSwapped; + u32 addrLSwapped; + + addrH = NIBBLE_SWAPPING_16_BIT(macH); + addrL = NIBBLE_SWAPPING_32_BIT(macL); + + addrHSwapped = FLIP_4_BITS(addrH & 0xf) + + ((FLIP_4_BITS((addrH >> 4) & 0xf)) << 4) + + ((FLIP_4_BITS((addrH >> 8) & 0xf)) << 8) + + ((FLIP_4_BITS((addrH >> 12) & 0xf)) << 12); + + addrLSwapped = FLIP_4_BITS(addrL & 0xf) + + ((FLIP_4_BITS((addrL >> 4) & 0xf)) << 4) + + ((FLIP_4_BITS((addrL >> 8) & 0xf)) << 8) + + ((FLIP_4_BITS((addrL >> 12) & 0xf)) << 12) + + ((FLIP_4_BITS((addrL >> 16) & 0xf)) << 16) + + ((FLIP_4_BITS((addrL >> 20) & 0xf)) << 20) + + ((FLIP_4_BITS((addrL >> 24) & 0xf)) << 24) + + ((FLIP_4_BITS((addrL >> 28) & 0xf)) << 28); + + addrH = addrHSwapped; + addrL = addrLSwapped; + + if (hash_mode == 0) { + addr0 = (addrL >> 2) & 0x03f; + addr1 = (addrL & 0x003) | ((addrL >> 8) & 0x7f) << 2; + addr2 = (addrL >> 15) & 0x1ff; + addr3 = ((addrL >> 24) & 0x0ff) | ((addrH & 1) << 8); + } else { + addr0 = FLIP_6_BITS(addrL & 0x03f); + addr1 = FLIP_9_BITS(((addrL >> 6) & 0x1ff)); + addr2 = FLIP_9_BITS((addrL >> 15) & 0x1ff); + addr3 = + FLIP_9_BITS((((addrL >> 24) & 0x0ff) | + ((addrH & 0x1) << 8))); + } + + hashResult = (addr0 << 9) | (addr1 ^ addr2 ^ addr3); + + if (HashSize == _8K_TABLE) { + hashResult = hashResult & 0xffff; + } else { + hashResult = hashResult & 0x07ff; + } + + return (hashResult); +} + +/* + * ---------------------------------------------------------------------------- + * This function will add an entry to the address table. + * depends on the hash mode and hash size that was initialized. + * Inputs + * port - ETHERNET port number. + * macH - the 2 most significant bytes of the MAC address. + * macL - the 4 least significant bytes of the MAC address. + * skip - if 1, skip this address. + * rd - the RD field in the address table. + * Outputs + * address table entry is added. + * TRUE if success. + * FALSE if table full + */ +static int +addAddressTableEntry(u32 port, u32 macH, u32 macL, u32 rd, u32 skip) +{ + addrTblEntry *entry; + u32 newHi; + u32 newLo; + u32 i; + + newLo = (((macH >> 4) & 0xf) << 15) + | (((macH >> 0) & 0xf) << 11) + | (((macH >> 12) & 0xf) << 7) + | (((macH >> 8) & 0xf) << 3) + | (((macL >> 20) & 0x1) << 31) + | (((macL >> 16) & 0xf) << 27) + | (((macL >> 28) & 0xf) << 23) + | (((macL >> 24) & 0xf) << 19) + | (skip << SKIP_BIT) | (rd << 2) | VALID; + + newHi = (((macL >> 4) & 0xf) << 15) + | (((macL >> 0) & 0xf) << 11) + | (((macL >> 12) & 0xf) << 7) + | (((macL >> 8) & 0xf) << 3) + | (((macL >> 21) & 0x7) << 0); + + /* + * Pick the appropriate table, start scanning for free/reusable + * entries at the index obtained by hashing the specified MAC address + */ + entry = addressTableBase[port]; + entry += hashTableFunction(macH, macL, addressTableHashSize[port], + addressTableHashMode[port]); + for (i = 0; i < HOP_NUMBER; i++, entry++) { + if (!(entry->lo & VALID) /*|| (entry->lo & SKIP) */ ) { + break; + } else { /* if same address put in same position */ + if (((entry->lo & 0xfffffff8) == (newLo & 0xfffffff8)) + && (entry->hi == newHi)) { + break; + } + } + } + + if (i == HOP_NUMBER) { + printk("addGT64260addressTableEntry: table section is full\n"); + return (FALSE); + } + + /* + * Update the selected entry + */ + entry->hi = newHi; + entry->lo = newLo; + flush_dcache_addr_size((u32) entry, MAC_ENTRY_SIZE); + return (TRUE); +} + +/* port control extend register funcions */ + +/***************************************************************************** +* +* int etherReadMIIReg (unsigned int portNumber , unsigned int MIIReg, +* unsigned int* value) +* +* Description +* This function will access the MII registers and will read the value of +* the MII register , and will retrieve the value in the pointer. +* Inputs +* portNumber - one of the 2 possiable Ethernet ports (0-1). +* MIIReg - the MII register offset. +* Outputs +* value - pointer to unsigned int which will receive the value. +* Returns Value +* TRUE if success. +* FALSE if fail to make the assignment. +* Error types (and exceptions if exist) +*/ + +static int +etherReadMIIReg(unsigned int portNumber, unsigned int MIIReg, + unsigned int *value) +{ + SMI_REG smiReg; + unsigned int phyAddr; + unsigned int timeOut = 1000; + int i; + + phyAddr = PHY_ADD0 + portNumber; + + /* first check that it is not busy */ + smiReg = gt_read(GT64260_ENET_ESMIR); + while (smiReg & SMI_BUSY) { + if (timeOut-- < 1) { + printk("TimeOut Passed Phy is busy\n"); + return FALSE; + } + for (i = 0; i < 1000; i++) ; + smiReg = gt_read(GT64260_ENET_ESMIR); + } + /* not busy */ + + gt_write(GT64260_ENET_ESMIR, + (SMI_OP_CODE_BIT_READ << 26) | (MIIReg << 21) | (phyAddr << + 16)); + + timeOut = 1000; /* initialize the time out var again */ + + for (i = 0; i < 1000; i++) ; + smiReg = gt_read(GT64260_ENET_ESMIR); + while (!(smiReg & READ_VALID)) { + for (i = 0; i < 1000; i++) ; + smiReg = gt_read(GT64260_ENET_ESMIR); + if (timeOut-- < 1) { + printk("TimeOut Passed Read is not valid\n"); + return FALSE; + } + } + + *value = (unsigned int) (smiReg & 0xffff); + + return TRUE; +} + +/***************************************************************************** +* +* int etherWriteMIIReg (unsigned int portNumber , unsigned int MIIReg, +* unsigned int value) +* +* Description +* This function will access the MII registers and will write the value +* to the MII register. +* Inputs +* portNumber - one of the 2 possiable Ethernet ports (0-1). +* MIIReg - the MII register offset. +* value -the value that will be written. +* Outputs +* Returns Value +* TRUE if success. +* FALSE if fail to make the assignment. +* Error types (and exceptions if exist) +*/ + +static int +etherWriteMIIReg(unsigned int portNumber, unsigned int MIIReg, + unsigned int value) +{ + SMI_REG smiReg; + unsigned int phyAddr; + unsigned int timeOut = 10; /* in 100MS units */ + int i; + + /* first check that it is not busy */ + smiReg = gt_read(GT64260_ENET_ESMIR); + if (smiReg & SMI_BUSY) { + for (i = 0; i < 10000000; i++) ; + do { + smiReg = gt_read(GT64260_ENET_ESMIR); + if (timeOut-- < 1) { + printk("TimeOut Passed Phy is busy\n"); + return FALSE; + } + } while (smiReg & SMI_BUSY); + } + /* not busy */ + + phyAddr = PHY_ADD0 + portNumber; + + smiReg = 0; /* make sure no garbage value in reserved bits */ + smiReg = smiReg | (phyAddr << 16) | (SMI_OP_CODE_BIT_WRITE << 26) | + (MIIReg << 21) | (value & 0xffff); + + gt_write(GT64260_ENET_ESMIR, *((unsigned int *) &smiReg)); + + return (TRUE); +} + +static int __init +gt64260_eth_module_init(void) +{ + int cards = 0; + +#ifdef CONFIG_GT64260_ETH_0 + if (gt64260_eth_init(0)) { + printk(KERN_ERR "Error registering GT64260 ethernet port 0\n"); + } +#endif +#ifdef CONFIG_GT64260_ETH_1 + gt64260_eth_devs[1].base_addr = 1; + if (register_netdev(>64260_eth_devs[1]) == 0) { + cards++; + } +#endif +#ifdef CONFIG_GT64260_ETH_2 + gt64260_eth_devs[2].base_addr = 2; + if (register_netdev(>64260_eth_devs[2]) == 0) { + cards++; + } +#endif + + return cards > 0 ? 0 : -ENODEV; +} + +static void __exit +gt64260_eth_module_exit(void) +{ + +} + +module_init(gt64260_eth_module_init); +module_exit(gt64260_eth_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rabeeh Khoury"); +MODULE_DESCRIPTION("Ethernet driver for Marvell/Galileo GT64260"); diff -u --new-file --recursive linux-2.6.14.orig/drivers/net/gt64260_eth.h linux-2.6.14.mod/drivers/net/gt64260_eth.h --- linux-2.6.14.orig/drivers/net/gt64260_eth.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/net/gt64260_eth.h 2006-01-24 12:20:31.000000000 -0700 @@ -0,0 +1,366 @@ +/* Driver for EVB64260 ethernet ports + Copyright (C)2000, 2001 Rabeeh Khoury, Marvell */ +/* + * drivers/net/gt64260_eth.h + * + * Author: Rabeeh Khoury from Marvell + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#ifndef GT64260_ETH_H +#define GT64260_ETH_H + +#define CONFIG_MOT_MVP 1 /* RF */ + +#include +#include +#include +#include + +#define DESCRIPTOR_SIZE sizeof(gt_dma_desc) +#define Q_INDEX_LIMIT (PAGE_SIZE / DESCRIPTOR_SIZE) + +#define NUM_TX_QUEUES 2 +#define NUM_RX_QUEUES 4 +#define GT64260_INT_THRE 5 +#define GT_ENET_DESC_OWNERSHIP (1<<31) +#define GT_ENET_DESC_INT_ENABLE (1<<23) +#define GT_ENET_DESC_ERROR_SUMMARY (1<<15) +#define MAX_BUFF_SIZE 1536 + +#define ETH_ADDR_GAP ( GT64260_ENET_E1PCR - GT64260_ENET_E0PCR ) + +const char gt64260_eth0_name[] = "GEth0"; +const char gt64260_eth1_name[] = "GEth1"; + +s32 gt64260_eth_init(int port_num); +//s32 gt64260_eth_init(struct net_device *); +s32 gt64260_eth_open(struct net_device *); +s32 gt64260_eth_start_xmit(struct sk_buff *, struct net_device *); +s32 gt64260_eth_stop(struct net_device *); +static irqreturn_t gt64260_eth_int_handler(s32, void *, struct pt_regs *); +s32 gt64260_eth_set_mac_address(struct net_device *, void *); +struct net_device_stats *gt64260_eth_get_stats(struct net_device *); + +typedef volatile struct gt_dma_desc_struct { + volatile union { + volatile struct { + u16 bytes; + u16 reserved; + } tx; + volatile struct { + u16 bufferBytes; + u16 bytesReceived; + } rx; + } count; + + volatile u32 command_status; + volatile u32 next; /* Physical address, only read by the DMA engine. */ + volatile void *data; /* Physical address, only read by the DMA engine. */ + + /* + * Force sizeof(gt64260enetDMAdescriptor) == sizeof(cacheline) + * Not yet sure exactly why this is necessary but the GT64260-B + * part apparently has (yet another) bug that shows itself without + * this padding. The symptom is that all Enet comms simply stop. + */ + u32 cachelineSizePadding[4]; +} gt_dma_desc; + +typedef struct gt_eth_priv_struct { + gt_dma_desc *TXqueue[NUM_TX_QUEUES]; + gt_dma_desc *RXqueue[NUM_RX_QUEUES]; + struct sk_buff *TXskbuff[NUM_TX_QUEUES][Q_INDEX_LIMIT]; + struct sk_buff *RXskbuff[NUM_RX_QUEUES][Q_INDEX_LIMIT]; + u32 TXindex[NUM_TX_QUEUES]; + u32 RXindex[NUM_RX_QUEUES]; + u32 TXskbIndex[NUM_TX_QUEUES]; + u32 irq; + u8 port; + struct net_device_stats stat; + spinlock_t lock; + struct mii_if_info mii_if; + +} gt_eth_priv; + +/* + * ---------------------------------------------------------------------------- + * addressTable.h - this file has all the declarations of the address table + */ + +#define _8K_TABLE 0 +#define ADDRESS_TABLE_ALIGNMENT 8 +#define HASH_DEFAULT_MODE 14 +#define HASH_MODE 13 +#define HASH_SIZE 12 +#define HOP_NUMBER 12 +#define MAC_ADDRESS_STRING_SIZE 12 +#define MAC_ENTRY_SIZE sizeof(addrTblEntry) +#define MAX_NUMBER_OF_ADDRESSES_TO_STORE 1000 +#define PROMISCUOUS_MODE 0 +#define SKIP 1<<1 +#define SKIP_BIT 1 +#define VALID 1 + +/* + * ---------------------------------------------------------------------------- + * XXX_MIKE - potential sign-extension bugs lurk here... + */ +#define NIBBLE_SWAPPING_32_BIT(X) ( (((X) & 0xf0f0f0f0) >> 4) \ + | (((X) & 0x0f0f0f0f) << 4) ) + +#define NIBBLE_SWAPPING_16_BIT(X) ( (((X) & 0x0000f0f0) >> 4) \ + | (((X) & 0x00000f0f) << 4) ) + +#define FLIP_4_BITS(X) ( (((X) & 0x01) << 3) | (((X) & 0x002) << 1) \ + | (((X) & 0x04) >> 1) | (((X) & 0x008) >> 3) ) + +#define FLIP_6_BITS(X) ( (((X) & 0x01) << 5) | (((X) & 0x020) >> 5) \ + | (((X) & 0x02) << 3) | (((X) & 0x010) >> 3) \ + | (((X) & 0x04) << 1) | (((X) & 0x008) >> 1) ) + +#define FLIP_9_BITS(X) ( (((X) & 0x01) << 8) | (((X) & 0x100) >> 8) \ + | (((X) & 0x02) << 6) | (((X) & 0x080) >> 6) \ + | (((X) & 0x04) << 4) | (((X) & 0x040) >> 4) \ + | ((X) & 0x10) | (((X) & 0x08) << 2) | (((X) & 0x020) >> 2) ) + +/* + * V: value we're operating on + * O: offset of rightmost bit in field + * W: width of field to shift + * S: distance to shift left + */ +#define MASK( fieldWidth ) ((1 << (fieldWidth)) - 1) +#define leftShiftedBitfield( V,O,W,S) (((V) & (MASK(W) << (O))) << (S)) +#define rightShiftedBitfield(V,O,W,S) (((u32)((V) & (MASK(W) << (O)))) >> (S)) + +/* cache flushing helpers */ + +#define flush_dcache_addr_size( A, N ) \ + flush_dcache_range( (A), ((u32)(A)+(N)) ) + +#define flush_dcache(x) flush_dcache_range( ((u32)x) , ((u32)x) + sizeof(x)) + +#define invalidate_dcache(x) invalidate_dcache_range( ((u32)x) , ((u32)x) + sizeof(x)) + +static u32 uncachedPages(u32 pages); + +static u32 hashTableFunction(u32 macH, u32 macL, u32 HashSize, u32 hash_mode); + +static void addressTableClear(u32 port); + +static int + initAddressTable(u32 port, u32 hashMode, u32 hashSize, u32 hashDefaultMode); + +static int + addAddressTableEntry(u32 port, u32 macH, u32 macL, u32 rd, u32 skip); + +/* this file has all the ethernet low level definitions */ + + +#define ETHERNET_PORTS_DIFFERENCE_OFFSETS 0x400 + +#define ETHERNET0_HH_PRIORITY 11 +#define ETHERNET0_LL_PRIORITY 2 +#define ETHERNET1_HH_PRIORITY 12 + +/* this macros are used to enable access to SMI_REG */ +#define SMI_OP_CODE_BIT_READ 1 +#define SMI_OP_CODE_BIT_WRITE 0 +#define SMI_BUSY 1<<28 +#define READ_VALID 1<<27 + + +#ifdef CONFIG_ZUMA_V2 +#define PHY_LXT97x +#define PHY_ADD0 0 +#define PHY_ADD1 1 +#elif CONFIG_MOT_MVP +#define PHY_LXT97x +#define PHY_ADD0 4 +#define PHY_ADD1 5 +#else +#define PHY_ADD0 4 +#define PHY_ADD1 5 +#define PHY_ADD2 6 +#endif + +/* this macros are used to enable access to ETHERNET_PCXR */ +#define OVERRIDE_RX_PRIORITY 1<<8 +#define MIB_CLEAR_MODE 1<<16 + +/* this macros are used to enable access to ETHERNET_SDCMR */ +#define START_TX_HIGH 1<<23 +#define START_TX_LOW 1<<24 +#define ENABLE_RX_DMA 1<<7 +#define ABORT_RECEIVE 1<<15 +#define STOP_TX_HIGH 1<<16 +#define STOP_TX_LOW 1<<17 +#define ABORT_TRANSMIT 1<<31 + +/* this macros are used to enable access to ETHERNET_SDCR */ +#define ETHERNET_SDMA_BURST_SIZE 3 + +typedef unsigned int ETHERNET_PCR; +typedef unsigned int ETHERNET_PCXR; +typedef unsigned int ETHERNET_PCMR; +typedef unsigned int ETHERNET_PSR; +typedef unsigned int ETHERNET_SDCMR; +typedef unsigned int ETHERNET_SDCR; + +typedef unsigned int PHY_ADD_REG; +typedef unsigned int SMI_REG; + +typedef struct mibCounters { + unsigned int byteReceived; + unsigned int byteSent; + unsigned int framesReceived; + unsigned int framesSent; + unsigned int totalByteReceived; + unsigned int totalFramesReceived; + unsigned int broadcastFramesReceived; + unsigned int multicastFramesReceived; + unsigned int cRCError; + unsigned int oversizeFrames; + unsigned int fragments; + unsigned int jabber; + unsigned int collision; + unsigned int lateCollision; + unsigned int frames64; + unsigned int frames65_127; + unsigned int frames128_255; + unsigned int frames256_511; + unsigned int frames512_1023; + unsigned int frames1024_MaxSize; + unsigned int macRxError; + unsigned int droppedFrames; + unsigned int outMulticastFrames; + unsigned int outBroadcastFrames; + unsigned int undersizeFrames; +} STRUCT_MIB_COUNTERS; + +static int etherReadMIIReg(unsigned int portNum, unsigned int miiReg, + unsigned int *value); + +static int etherWriteMIIReg(unsigned int portNum, unsigned int miiReg, + unsigned int value); + +#ifdef PHY_LXT97x +#undef THREE_ETHERNET_RMII_PORTS +#define TWO_ETHERNET_MII_PORTS +#else +#define THREE_ETHERNET_RMII_PORTS +#undef TWO_ETHERNET_MII_PORTS +#endif + +#define ETHERNET_PORT2 2 +#define ETHERNET_PORT1 1 +#define ETHERNET_PORT0 0 + +#define MAX_NUMBER_OF_MPSC_PORTS 3 +#define MAX_NUMBER_OF_ETHERNET_PORTS 3 + +#ifdef THREE_ETHERNET_RMII_PORTS +/********/ +/* RMII */ +/********/ + +#define NUMBER_OF_ETHERNET_PORTS 3 +#define NUMBER_OF_MPSC_PORTS 2 +#define MRR_REG_VALUE 0x7ffe38 + +/* connect MPSC0 + 3 ports of RMII */ +#define SERIAL_PORT_MULTIPLEX_REGISTER_VALUE 0x1102 +/* GALILEO value */ +// 0000 0000 0001 0001 20 - RMII +// 16 - clear MIB counters +// 1000 1000 0000 0000 15:14 - 2048 (10) +//#define PORT_CONTROL_EXTEND_VALUE 0x00118000 + +/* PPCBoot value */ +// 0000 0000 0000 0001 20 - RMII +// 0100 1101 0000 0000 15:14 - 1536 (01) +// 11 - dont force link pass +// 10 - disable FC AN +// 8 - prio override +//#define PORT_CONTROL_EXTEND_VALUE 0x00104d00 + +/* Montavista value */ +// 0000 0000 0011 0000 21 - DSCP +// 20 - RMII +// 0100 1100 0010 0010 15:14 - 1536 (01) +// 11 - dont force link pass +// 10 - disable fc AN +// 5:3 - 8pkt high, 1 low (100) +// 1 - bpdu trap +#define PORT_CONTROL_EXTEND_VALUE 0x00304c20 + +#define ETHERNET_DOWNLOADING_PORT ETHERNET_PORT2 + +#else /* if !THREE_ETHERNET_RMII_PORTS */ + +#ifdef TWO_ETHERNET_MII_PORTS +/*******/ +/* MII */ +/*******/ + +#define NUMBER_OF_ETHERNET_PORTS 2 +#define NUMBER_OF_MPSC_PORTS 2 +#define MRR_REG_VALUE 0x7ffe38 +/* connect MPSC0 + 2 ports of MII */ +#define SERIAL_PORT_MULTIPLEX_REGISTER_VALUE 0x1101 +/* GALILEO value */ +// 0000 0000 0000 0001 16 - clear MIB counters +// 1000 1000 0000 0000 15:14 - 2048 (10) +//#define PORT_CONTROL_EXTEND_VALUE 0x00018000 + +/* PPCBoot (ZUMA) value */ +// 0000 0000 0000 0000 +// 0100 1101 0000 0000 15:14 - 1536 (01) +// 11 - dont force link pass +// 10 - disable FC AN +// 8 - prio override +//#define PORT_CONTROL_EXTEND_VALUE 0x00004d00 + +/* Montavista (ZUMA) value */ +// 0000 0000 0010 0000 21 - DSCP +// 0100 1100 0010 0010 15:14 - 1536 (01) +// 11 - dont force link pass +// 10 - disable fc AN +// 5:3 - 8pkt high, 1 low (100) +// 1 - bpdu trap +#ifndef CONFIG_MOT_MVP +#define PORT_CONTROL_EXTEND_VALUE 0x00204c20 +#else +/* Hack, don't allow 10mbit for now */ +// 0000 0000 0010 1100 21 - DSCP +// 0100 1100 0010 0010 18 - Speed (1-> 100mbit) +// 19 - SpeedEn (1-> disable speed AN) +// 15:14 - 1536 (01) +// 11 - dont force link pass +// 10 - disable fc AN +// 5:3 - 8pkt high, 1 low (100) +// 1 - bpdu trap +// +#define PORT_CONTROL_EXTEND_VALUE 0x002c4c20 +#endif + +#define ETHERNET_DOWNLOADING_PORT ETHERNET_PORT1 + +#endif /* endif TWO_ETHERNET_MII_PORTS */ +#endif /* endif !THREE_ETHERNET_RMII_PORTS */ + +#define LL_QUEUE_PRIORITY 1 +#define L_QUEUE_PRIORITY 2 +#define H_QUEUE_PRIORITY 3 +#define HH_QUEUE_PRIORITY 4 + +#define NUMBER_OF_MIB_COUNTERS 25 + +#define TIME_OUT 10 /* 1/6 SEC */ + + +#endif /* #ifndef GT64260_ETH_H */ diff -u --new-file --recursive linux-2.6.14.orig/drivers/net/Kconfig linux-2.6.14.mod/drivers/net/Kconfig --- linux-2.6.14.orig/drivers/net/Kconfig 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/net/Kconfig 2006-01-24 12:20:09.000000000 -0700 @@ -359,6 +359,54 @@ in your kernel. To compile this driver as a module, choose M here. +config GT64260_ETH + tristate "GT64260 Ethernet support" + depends on NET_ETHERNET && GT64260 + help + This is the driver for the Ethernet interface on the Marvell + GT64260. + Say Y here to include the driver for this chip in your kernel. + To compile this driver as a module, choose M here. + +config GT64260_ETH_0 + bool "GT64260 Port 0" + depends on GT64260_ETH + help + This enables support for Port 0 of the Marvell GT64260 Ethernet. + +config GT64260_ETH_0_MACADDR + string "GT64260 Port 0 MAC Address" + depends on GT64260_ETH_0 + default "0001AF12C9E0" + help + Specify MAC address here if you cannot get if from the firmware + +config GT64260_ETH_1 + bool "GT64260 Port 1" + depends on GT64260_ETH + help + This enables support for Port 1 of the Marvell GT64260 Ethernet. + +config GT64260_ETH_1_MACADDR + string "GT64260 Port 1 MAC Address" + depends on GT64260_ETH_1 + default "0001AF12C9E1" + help + Specify MAC address here if you cannot get if from the firmware + +config GT64260_ETH_2 + bool "GT64260 Port 2" + depends on GT64260_ETH + help + This enables support for Port 2 of the Marvell GT64260 Ethernet. + +config GT64260_ETH_2_MACADDR + string "GT64260 Port 2 MAC Address" + depends on GT64260_ETH_2 + default "0001AF12C9E2" + help + Specify MAC address here if you cannot get if from the firmware + config ATARILANCE tristate "Atari Lance support" depends on NET_ETHERNET && ATARI diff -u --new-file --recursive linux-2.6.14.orig/drivers/net/Makefile linux-2.6.14.mod/drivers/net/Makefile --- linux-2.6.14.orig/drivers/net/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/net/Makefile 2006-01-24 12:20:21.000000000 -0700 @@ -154,6 +154,7 @@ obj-$(CONFIG_LASI_82596) += lasi_82596.o obj-$(CONFIG_MVME16x_NET) += 82596.o obj-$(CONFIG_BVME6000_NET) += 82596.o +obj-$(CONFIG_GT64260_ETH) += gt64260_eth.o # This is also a 82596 and should probably be merged obj-$(CONFIG_LP486E) += lp486e.o diff -u --new-file --recursive linux-2.6.14.orig/drivers/net/mv643xx_eth.c linux-2.6.14.mod/drivers/net/mv643xx_eth.c --- linux-2.6.14.orig/drivers/net/mv643xx_eth.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/net/mv643xx_eth.c 2006-02-02 17:29:08.000000000 -0700 @@ -53,6 +53,8 @@ /* Constants */ #define VLAN_HLEN 4 #define FCS_LEN 4 +#define DMA_ALIGN 8 /* hw requires 8-byte alignment */ +#define HW_IP_ALIGN 2 /* hw aligns IP header */ #define WRAP NET_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN #define RX_SKB_SIZE ((dev->mtu + WRAP + 7) & ~0x7) @@ -76,6 +78,7 @@ static int eth_port_link_is_up(unsigned int eth_port_num); static void eth_port_uc_addr_get(struct net_device *dev, unsigned char *MacAddr); +static void eth_port_set_multicast_list(struct net_device *); static int mv643xx_eth_real_open(struct net_device *); static int mv643xx_eth_real_stop(struct net_device *); static int mv643xx_eth_change_mtu(struct net_device *, int); @@ -168,15 +171,19 @@ struct mv643xx_private *mp = netdev_priv(dev); struct pkt_info pkt_info; struct sk_buff *skb; + int unaligned; if (test_and_set_bit(0, &mp->rx_task_busy)) panic("%s: Error in test_set_bit / clear_bit", dev->name); while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) { - skb = dev_alloc_skb(RX_SKB_SIZE); + skb = dev_alloc_skb(RX_SKB_SIZE + DMA_ALIGN); if (!skb) break; mp->rx_ring_skbs++; + unaligned = (u32)skb->data & (DMA_ALIGN - 1); + if (unaligned) + skb_reserve(skb, DMA_ALIGN - unaligned); pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT; pkt_info.byte_cnt = RX_SKB_SIZE; pkt_info.buf_ptr = dma_map_single(NULL, skb->data, RX_SKB_SIZE, @@ -187,7 +194,7 @@ "%s: Error allocating RX Ring\n", dev->name); break; } - skb_reserve(skb, 2); + skb_reserve(skb, HW_IP_ALIGN); } clear_bit(0, &mp->rx_task_busy); /* @@ -265,6 +272,8 @@ mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config); + + eth_port_set_multicast_list(dev); } /* @@ -349,27 +358,19 @@ stats->tx_errors++; } - /* - * If return_info is different than 0, release the skb. - * The case where return_info is not 0 is only in case - * when transmitted a scatter/gather packet, where only - * last skb releases the whole chain. - */ + if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC) + dma_unmap_single(NULL, pkt_info.buf_ptr, + pkt_info.byte_cnt, + DMA_TO_DEVICE); + else + dma_unmap_page(NULL, pkt_info.buf_ptr, + pkt_info.byte_cnt, + DMA_TO_DEVICE); + if (pkt_info.return_info) { - if (skb_shinfo(pkt_info.return_info)->nr_frags) - dma_unmap_page(NULL, pkt_info.buf_ptr, - pkt_info.byte_cnt, - DMA_TO_DEVICE); - else - dma_unmap_single(NULL, pkt_info.buf_ptr, - pkt_info.byte_cnt, - DMA_TO_DEVICE); - dev_kfree_skb_irq(pkt_info.return_info); released = 0; - } else - dma_unmap_page(NULL, pkt_info.buf_ptr, - pkt_info.byte_cnt, DMA_TO_DEVICE); + } } spin_unlock(&mp->lock); @@ -455,6 +456,7 @@ #endif } } + dev->last_rx = jiffies; return received_packets; } @@ -517,7 +519,7 @@ } #else if (eth_int_cause & (BIT2 | BIT11)) - mv643xx_eth_receive_queue(dev, 0); + mv643xx_eth_receive_queue(dev); /* * After forwarded received packets to upper layer, add a task @@ -534,7 +536,9 @@ mp->rx_task.func(dev); #endif #endif +#ifdef MV643XX_NAPI } +#endif /* PHY status changed */ if (eth_int_cause_ext & (BIT16 | BIT20)) { if (eth_port_link_is_up(port_num)) { @@ -652,7 +656,6 @@ unsigned int port_num = mp->port_num; int err; - spin_lock_irq(&mp->lock); err = request_irq(dev->irq, mv643xx_eth_int_handler, SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); @@ -660,26 +663,19 @@ if (err) { printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n", port_num); - err = -EAGAIN; - goto out; + return -EAGAIN; } + spin_lock_irq(&mp->lock); + if (mv643xx_eth_real_open(dev)) { printk("%s: Error opening interface\n", dev->name); + free_irq(dev->irq, dev); err = -EBUSY; - goto out_free; } spin_unlock_irq(&mp->lock); - return 0; - -out_free: - free_irq(dev->irq, dev); - -out: - spin_unlock_irq(&mp->lock); - return err; } @@ -1020,20 +1016,17 @@ struct pkt_info pkt_info; while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) { - if (pkt_info.return_info) { - if (skb_shinfo(pkt_info.return_info)->nr_frags) - dma_unmap_page(NULL, pkt_info.buf_ptr, - pkt_info.byte_cnt, - DMA_TO_DEVICE); - else - dma_unmap_single(NULL, pkt_info.buf_ptr, - pkt_info.byte_cnt, - DMA_TO_DEVICE); - + if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC) + dma_unmap_single(NULL, pkt_info.buf_ptr, + pkt_info.byte_cnt, + DMA_TO_DEVICE); + else + dma_unmap_page(NULL, pkt_info.buf_ptr, + pkt_info.byte_cnt, + DMA_TO_DEVICE); + + if (pkt_info.return_info) dev_kfree_skb_irq(pkt_info.return_info); - } else - dma_unmap_page(NULL, pkt_info.buf_ptr, - pkt_info.byte_cnt, DMA_TO_DEVICE); } if (netif_queue_stopped(dev) && @@ -1533,6 +1526,10 @@ printk(KERN_NOTICE "%s: RX NAPI Enabled \n", dev->name); #endif + if (mp->tx_sram_size > 0) + printk(KERN_NOTICE "%s: Using SRAM\n", dev->name); + + return 0; out: @@ -2048,6 +2045,199 @@ return 1; } +static void eth_port_set_filter_table_entry(int table, unsigned char entry) +{ + unsigned int table_reg; + unsigned int tbl_offset; + unsigned int reg_offset; + + tbl_offset = (entry / 4) * 4; /* Register offset of DA table entry */ + reg_offset = entry % 4; /* Entry offset within the register */ + + /* Set "accepts frame bit" at specified table entry */ + table_reg = mv_read(table + tbl_offset); + table_reg |= 0x01 << (8 * reg_offset); + mv_write(table + tbl_offset, table_reg); +} + +/******************************************************************************* +* eth_port_mc_addr - Multicast address settings. +* +* DESCRIPTION: +* This function controls the MV device MAC multicast support. +* The MV device supports multicast using two tables: +* 1) Special Multicast Table for MAC addresses of the form +* 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0x_FF). +* The MAC DA[7:0] bits are used as a pointer to the Special Multicast +* Table entries in the DA-Filter table. +* 2) Other Multicast Table for multicast of another type. A CRC-8bit +* is used as an index to the Other Multicast Table entries in the +* DA-Filter table. This function calculates the CRC-8bit value. +* In either case, eth_port_set_filter_table_entry() is then called +* to set to set the actual table entry. +* INPUT: +* unsigned int eth_port_num Port number. +* unsigned char *p_addr Unicast MAC Address. +* +* OUTPUT: +* See description. +* +* RETURN: +* None. +* +*******************************************************************************/ +static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr) +{ + unsigned int mac_h; + unsigned int mac_l; + unsigned char crc_result = 0; + int table; + int mac_array[48]; + int crc[8]; + int i; + + if ((p_addr[0] == 0x01) && (p_addr[1] == 0x00) && + (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) { + table = MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE + (eth_port_num); + eth_port_set_filter_table_entry(table, p_addr[5]); + return; + } + + /* Calculate CRC-8 out of the given address */ + mac_h = (p_addr[0] << 8) | (p_addr[1]); + mac_l = (p_addr[2] << 24) | (p_addr[3] << 16) | + (p_addr[4] << 8) | (p_addr[5] << 0); + + for (i = 0; i < 32; i++) + mac_array[i] = (mac_l >> i) & 0x1; + for (i = 32; i < 48; i++) + mac_array[i] = (mac_h >> (i - 32)) & 0x1; + + crc[0] = mac_array[45] ^ mac_array[43] ^ mac_array[40] ^ mac_array[39] ^ + mac_array[35] ^ mac_array[34] ^ mac_array[31] ^ mac_array[30] ^ + mac_array[28] ^ mac_array[23] ^ mac_array[21] ^ mac_array[19] ^ + mac_array[18] ^ mac_array[16] ^ mac_array[14] ^ mac_array[12] ^ + mac_array[8] ^ mac_array[7] ^ mac_array[6] ^ mac_array[0]; + + crc[1] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ mac_array[43] ^ + mac_array[41] ^ mac_array[39] ^ mac_array[36] ^ mac_array[34] ^ + mac_array[32] ^ mac_array[30] ^ mac_array[29] ^ mac_array[28] ^ + mac_array[24] ^ mac_array[23] ^ mac_array[22] ^ mac_array[21] ^ + mac_array[20] ^ mac_array[18] ^ mac_array[17] ^ mac_array[16] ^ + mac_array[15] ^ mac_array[14] ^ mac_array[13] ^ mac_array[12] ^ + mac_array[9] ^ mac_array[6] ^ mac_array[1] ^ mac_array[0]; + + crc[2] = mac_array[47] ^ mac_array[46] ^ mac_array[44] ^ mac_array[43] ^ + mac_array[42] ^ mac_array[39] ^ mac_array[37] ^ mac_array[34] ^ + mac_array[33] ^ mac_array[29] ^ mac_array[28] ^ mac_array[25] ^ + mac_array[24] ^ mac_array[22] ^ mac_array[17] ^ mac_array[15] ^ + mac_array[13] ^ mac_array[12] ^ mac_array[10] ^ mac_array[8] ^ + mac_array[6] ^ mac_array[2] ^ mac_array[1] ^ mac_array[0]; + + crc[3] = mac_array[47] ^ mac_array[45] ^ mac_array[44] ^ mac_array[43] ^ + mac_array[40] ^ mac_array[38] ^ mac_array[35] ^ mac_array[34] ^ + mac_array[30] ^ mac_array[29] ^ mac_array[26] ^ mac_array[25] ^ + mac_array[23] ^ mac_array[18] ^ mac_array[16] ^ mac_array[14] ^ + mac_array[13] ^ mac_array[11] ^ mac_array[9] ^ mac_array[7] ^ + mac_array[3] ^ mac_array[2] ^ mac_array[1]; + + crc[4] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ mac_array[41] ^ + mac_array[39] ^ mac_array[36] ^ mac_array[35] ^ mac_array[31] ^ + mac_array[30] ^ mac_array[27] ^ mac_array[26] ^ mac_array[24] ^ + mac_array[19] ^ mac_array[17] ^ mac_array[15] ^ mac_array[14] ^ + mac_array[12] ^ mac_array[10] ^ mac_array[8] ^ mac_array[4] ^ + mac_array[3] ^ mac_array[2]; + + crc[5] = mac_array[47] ^ mac_array[46] ^ mac_array[45] ^ mac_array[42] ^ + mac_array[40] ^ mac_array[37] ^ mac_array[36] ^ mac_array[32] ^ + mac_array[31] ^ mac_array[28] ^ mac_array[27] ^ mac_array[25] ^ + mac_array[20] ^ mac_array[18] ^ mac_array[16] ^ mac_array[15] ^ + mac_array[13] ^ mac_array[11] ^ mac_array[9] ^ mac_array[5] ^ + mac_array[4] ^ mac_array[3]; + + crc[6] = mac_array[47] ^ mac_array[46] ^ mac_array[43] ^ mac_array[41] ^ + mac_array[38] ^ mac_array[37] ^ mac_array[33] ^ mac_array[32] ^ + mac_array[29] ^ mac_array[28] ^ mac_array[26] ^ mac_array[21] ^ + mac_array[19] ^ mac_array[17] ^ mac_array[16] ^ mac_array[14] ^ + mac_array[12] ^ mac_array[10] ^ mac_array[6] ^ mac_array[5] ^ + mac_array[4]; + + crc[7] = mac_array[47] ^ mac_array[44] ^ mac_array[42] ^ mac_array[39] ^ + mac_array[38] ^ mac_array[34] ^ mac_array[33] ^ mac_array[30] ^ + mac_array[29] ^ mac_array[27] ^ mac_array[22] ^ mac_array[20] ^ + mac_array[18] ^ mac_array[17] ^ mac_array[15] ^ mac_array[13] ^ + mac_array[11] ^ mac_array[7] ^ mac_array[6] ^ mac_array[5]; + + for (i = 0; i < 8; i++) + crc_result = crc_result | (crc[i] << i); + + table = MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num); + eth_port_set_filter_table_entry(table, crc_result); +} + +/** Set the entire multicast list base on dev->mc_list. **/ +static void eth_port_set_multicast_list(struct net_device *dev) +{ + + struct dev_mc_list *mc_list; + int i; + int table_index; + struct mv643xx_private *mp = netdev_priv(dev); + unsigned int eth_port_num = mp->port_num; + + /** If the device is in promiscuous mode or in all multicast mode, + ** we will fully populate both multicast tables with accept. + ** This is guaranteed to yield a match on all multicast addresses... + **/ + if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) { + for (table_index = 0; table_index <= 0xFC; table_index += 4) { + /** Set all entries in DA filter special multicast + ** table (Ex_dFSMT) + ** Set for ETH_Q0 for now + ** Bits + ** 0 Accept=1, Drop=0 + ** 3-1 Queue ETH_Q0=0 + ** 7-4 Reserved = 0; + **/ + + mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101); + + /** Set all entries in DA filter other multicast + ** table (Ex_dFOMT) + ** Set for ETH_Q0 for now + ** Bits + ** 0 Accept=1, Drop=0 + ** 3-1 Queue ETH_Q0=0 + ** 7-4 Reserved = 0; + **/ + + mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101); + } + return; + } + + /** We will clear out multicast tables everytime we get the list. + ** Then add the entire new list... + **/ + for (table_index = 0; table_index <= 0xFC; table_index += 4) { + /* Clear DA filter special multicast table (Ex_dFSMT) */ + mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE + (eth_port_num) + table_index, 0); + + /* Clear DA filter other multicast table (Ex_dFOMT) */ + mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE + (eth_port_num) + table_index, 0); + } + + /** Get pointer to net_device multicast list and add each one... **/ + for(i = 0, mc_list = dev->mc_list; + (i < 256) && (mc_list != NULL) && (i < dev->mc_count); + i++, mc_list = mc_list->next) + if (mc_list->dmi_addrlen == 6) + eth_port_mc_addr(eth_port_num, mc_list->dmi_addr); +} + /* * eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables * @@ -2075,11 +2265,11 @@ for (table_index = 0; table_index <= 0xFC; table_index += 4) { /* Clear DA filter special multicast table (Ex_dFSMT) */ - mv_write((MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE - (eth_port_num) + table_index), 0); + mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE + (eth_port_num) + table_index, 0); /* Clear DA filter other multicast table (Ex_dFOMT) */ - mv_write((MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE - (eth_port_num) + table_index), 0); + mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE + (eth_port_num) + table_index, 0); } } @@ -2664,6 +2854,8 @@ /* Pass the packet information to the caller */ p_pkt_info->cmd_sts = command_status; p_pkt_info->return_info = mp->tx_skb[tx_desc_used]; + p_pkt_info->buf_ptr = p_tx_desc_used->buf_ptr; + p_pkt_info->byte_cnt = p_tx_desc_used->byte_cnt; mp->tx_skb[tx_desc_used] = NULL; /* Update the next descriptor to release. */ diff -u --new-file --recursive linux-2.6.14.orig/drivers/net/tulip/interrupt.c linux-2.6.14.mod/drivers/net/tulip/interrupt.c --- linux-2.6.14.orig/drivers/net/tulip/interrupt.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/net/tulip/interrupt.c 2005-11-16 10:40:21.000000000 -0700 @@ -567,8 +567,9 @@ if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { unsigned int dirty_tx; + unsigned long flags; - spin_lock(&tp->lock); + spin_lock_irqsave(&tp->lock, flags); for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; dirty_tx++) { @@ -640,7 +641,7 @@ dev->name, csr5, ioread32(ioaddr + CSR6), tp->csr6); tulip_restart_rxtx(tp); } - spin_unlock(&tp->lock); + spin_unlock_irqrestore(&tp->lock, flags); } /* Log errors. */ diff -u --new-file --recursive linux-2.6.14.orig/drivers/scsi/Kconfig linux-2.6.14.mod/drivers/scsi/Kconfig --- linux-2.6.14.orig/drivers/scsi/Kconfig 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/scsi/Kconfig 2005-11-16 10:40:21.000000000 -0700 @@ -489,6 +489,14 @@ If unsure, say N. +config SCSI_PATA_PDC2027X + tristate "Promise PATA 2027x support" + depends on SCSI_SATA && PCI + help + This option enables support for Promise PATA pdc20268 to pdc20277 host adapters. + + If unsure, say N. + config SCSI_SATA_PROMISE tristate "Promise SATA TX2/TX4 support" depends on SCSI_SATA && PCI diff -u --new-file --recursive linux-2.6.14.orig/drivers/scsi/Makefile linux-2.6.14.mod/drivers/scsi/Makefile --- linux-2.6.14.orig/drivers/scsi/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/scsi/Makefile 2005-11-16 10:40:21.000000000 -0700 @@ -127,6 +127,7 @@ obj-$(CONFIG_SCSI_SATA_AHCI) += libata.o ahci.o obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o +obj-$(CONFIG_SCSI_PATA_PDC2027X)+= libata.o pata_pdc2027x.o obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o obj-$(CONFIG_SCSI_SATA_QSTOR) += libata.o sata_qstor.o obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o diff -u --new-file --recursive linux-2.6.14.orig/drivers/scsi/pata_pdc2027x.c linux-2.6.14.mod/drivers/scsi/pata_pdc2027x.c --- linux-2.6.14.orig/drivers/scsi/pata_pdc2027x.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/scsi/pata_pdc2027x.c 2006-01-20 16:54:43.000000000 -0700 @@ -0,0 +1,855 @@ +/* + * Promise PATA TX2/TX4/TX2000/133 IDE driver for pdc20268 to pdc20277. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Ported to libata by: + * Albert Lee IBM Corporation + * + * Copyright (C) 1998-2002 Andre Hedrick + * Portions Copyright (C) 1999 Promise Technology, Inc. + * + * Author: Frank Tiernan (frankt@promise.com) + * Released under terms of General Public License + * + * + * libata documentation is available via 'make {ps|pdf}docs', + * as Documentation/DocBook/libata.* + * + * Hardware information only available under NDA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include +#include +#include +#include + +#define DRV_NAME "pata_pdc2027x" +#define DRV_VERSION "0.73" +#undef PDC_DEBUG + +#ifdef PDC_DEBUG +#define PDPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) +#else +#define PDPRINTK(fmt, args...) +#endif + +enum { + PDC_UDMA_100 = 0, + PDC_UDMA_133 = 1, + + PDC_100_MHZ = 100000000, + PDC_133_MHZ = 133333333, + + PDC_SYS_CTL = 0x1100, + PDC_ATA_CTL = 0x1104, + PDC_GLOBAL_CTL = 0x1108, + PDC_CTCR0 = 0x110C, + PDC_CTCR1 = 0x1110, + PDC_BYTE_COUNT = 0x1120, + PDC_PLL_CTL = 0x1202, +}; + +static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); +static void pdc2027x_remove_one(struct pci_dev *pdev); +static void pdc2027x_phy_reset(struct ata_port *ap); +static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev); +static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev); +static void pdc2027x_post_set_mode(struct ata_port *ap); +static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc); + +/* + * ATA Timing Tables based on 133MHz controller clock. + * These tables are only used when the controller is in 133MHz clock. + * If the controller is in 100MHz clock, the ASIC hardware will + * set the timing registers automatically when "set feature" command + * is issued to the device. However, if the controller clock is 133MHz, + * the following tables must be used. + */ +static struct pdc2027x_pio_timing { + u8 value0, value1, value2; +} pdc2027x_pio_timing_tbl [] = { + { 0xfb, 0x2b, 0xac }, /* PIO mode 0 */ + { 0x46, 0x29, 0xa4 }, /* PIO mode 1 */ + { 0x23, 0x26, 0x64 }, /* PIO mode 2 */ + { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */ + { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */ +}; + +static struct pdc2027x_mdma_timing { + u8 value0, value1; +} pdc2027x_mdma_timing_tbl [] = { + { 0xdf, 0x5f }, /* MDMA mode 0 */ + { 0x6b, 0x27 }, /* MDMA mode 1 */ + { 0x69, 0x25 }, /* MDMA mode 2 */ +}; + +static struct pdc2027x_udma_timing { + u8 value0, value1, value2; +} pdc2027x_udma_timing_tbl [] = { + { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */ + { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */ + { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */ + { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */ + { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */ + { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */ + { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */ +}; + +static const struct pci_device_id pdc2027x_pci_tbl[] = { +#ifdef ATA_ENABLE_PATA + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_100 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_100 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, + { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20277, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, +#endif + { } /* terminate list */ +}; + +static struct pci_driver pdc2027x_pci_driver = { + .name = DRV_NAME, + .id_table = pdc2027x_pci_tbl, + .probe = pdc2027x_init_one, + .remove = __devexit_p(pdc2027x_remove_one), +}; + +static Scsi_Host_Template pdc2027x_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations pdc2027x_pata100_ops = { + .port_disable = ata_port_disable, + + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .phy_reset = pdc2027x_phy_reset, + + .check_atapi_dma = pdc2027x_check_atapi_dma, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, + + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_host_stop, +}; + +static struct ata_port_operations pdc2027x_pata133_ops = { + .port_disable = ata_port_disable, + .set_piomode = pdc2027x_set_piomode, + .set_dmamode = pdc2027x_set_dmamode, + + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .phy_reset = pdc2027x_phy_reset, + .post_set_mode = pdc2027x_post_set_mode, + + .check_atapi_dma = pdc2027x_check_atapi_dma, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, + + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_host_stop, +}; + +static struct ata_port_info pdc2027x_port_info[] = { + /* PDC_UDMA_100 */ + { + .sht = &pdc2027x_sht, + .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | + ATA_FLAG_SRST | ATA_FLAG_MMIO, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = ATA_UDMA5, /* udma0-5 */ + .port_ops = &pdc2027x_pata100_ops, + }, + /* PDC_UDMA_133 */ + { + .sht = &pdc2027x_sht, + .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | + ATA_FLAG_SRST | ATA_FLAG_MMIO, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = ATA_UDMA6, /* udma0-6 */ + .port_ops = &pdc2027x_pata133_ops, + }, +}; + +MODULE_AUTHOR("Andre Hedrick, Frank Tiernan, Albert Lee"); +MODULE_DESCRIPTION("libata driver module for Promise PDC20268 to PDC20277"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); +MODULE_DEVICE_TABLE(pci, pdc2027x_pci_tbl); + +/** + * port_mmio - Get the MMIO address of PDC2027x extended registers + * @ap: Port + * @offset: offset from mmio base + */ +static inline void* port_mmio(struct ata_port *ap, unsigned int offset) +{ + return ap->host_set->mmio_base + ap->port_no * 0x100 + offset; +} + +/** + * dev_mmio - Get the MMIO address of PDC2027x extended registers + * @ap: Port + * @adev: device + * @offset: offset from mmio base + */ +static inline void* dev_mmio(struct ata_port *ap, struct ata_device *adev, unsigned int offset) +{ + u8 adj = (adev->devno) ? 0x08 : 0x00; + return port_mmio(ap, offset) + adj; +} + +/** + * pdc2027x_pata_cbl_detect - Probe host controller cable detect info + * @ap: Port for which cable detect info is desired + * + * Read 80c cable indicator from Promise extended register. + * This register is latched when the system is reset. + * + * LOCKING: + * None (inherited from caller). + */ +static void pdc2027x_cbl_detect(struct ata_port *ap) +{ + u32 cgcr; + + /* check cable detect results */ + cgcr = readl(port_mmio(ap, PDC_GLOBAL_CTL)); + if (cgcr & (1 << 26)) + goto cbl40; + + PDPRINTK("No cable or 80-conductor cable on port %d\n", ap->port_no); + + ap->cbl = ATA_CBL_PATA80; + return; + +cbl40: + printk(KERN_INFO DRV_NAME ": 40-conductor cable detected on port %d\n", ap->port_no); + ap->cbl = ATA_CBL_PATA40; + ap->udma_mask &= ATA_UDMA_MASK_40C; +} + +/** + * pdc2027x_port_enabled - Check PDC ATA control register to see whether the port is enabled. + * @ap: Port to check + */ +static inline int pdc2027x_port_enabled(struct ata_port *ap) +{ + return readb(port_mmio(ap, PDC_ATA_CTL)) & 0x02; +} + +/** + * pdc2027x_phy_reset - Probe specified port on PATA host controller + * @ap: Port to probe + * + * Probe PATA phy. + * + * LOCKING: + * None (inherited from caller). + */ +static void pdc2027x_phy_reset(struct ata_port *ap) +{ + /* Check whether port enabled */ + if (!pdc2027x_port_enabled(ap)) { + ata_port_disable(ap); + printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); + return; + } + + pdc2027x_cbl_detect(ap); + ata_port_probe(ap); + ata_bus_reset(ap); +} + +/** + * pdc2027x_set_piomode - Initialize host controller PATA PIO timings + * @ap: Port to configure + * @adev: um + * @pio: PIO mode, 0 - 4 + * + * Set PIO mode for device. + * + * LOCKING: + * None (inherited from caller). + */ +static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev) +{ + unsigned int pio = adev->pio_mode - XFER_PIO_0; + u32 ctcr0, ctcr1; + + PDPRINTK("adev->pio_mode[%X]\n", adev->pio_mode); + + /* Sanity check */ + if (pio > 4) { + printk(KERN_ERR DRV_NAME ": Unknown pio mode [%d] ignored\n", pio); + return; + + } + + /* Set the PIO timing registers using value table for 133MHz */ + PDPRINTK("Set pio regs... \n"); + + ctcr0 = readl(dev_mmio(ap, adev, PDC_CTCR0)); + ctcr0 &= 0xffff0000; + ctcr0 |= pdc2027x_pio_timing_tbl[pio].value0 | + (pdc2027x_pio_timing_tbl[pio].value1 << 8); + writel(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); + + ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); + ctcr1 &= 0x00ffffff; + ctcr1 |= (pdc2027x_pio_timing_tbl[pio].value2 << 24); + writel(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); + + PDPRINTK("Set pio regs done\n"); + + PDPRINTK("Set to pio mode[%u] \n", pio); +} + +/** + * pdc2027x_set_dmamode - Initialize host controller PATA UDMA timings + * @ap: Port to configure + * @adev: um + * @udma: udma mode, XFER_UDMA_0 to XFER_UDMA_6 + * + * Set UDMA mode for device. + * + * LOCKING: + * None (inherited from caller). + */ +static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev) +{ + unsigned int dma_mode = adev->dma_mode; + u32 ctcr0, ctcr1; + + if ((dma_mode >= XFER_UDMA_0) && + (dma_mode <= XFER_UDMA_6)) { + /* Set the UDMA timing registers with value table for 133MHz */ + unsigned int udma_mode = dma_mode & 0x07; + + if (dma_mode == XFER_UDMA_2) { + /* + * Turn off tHOLD. + * If tHOLD is '1', the hardware will add half clock for data hold time. + * This code segment seems to be no effect. tHOLD will be overwritten below. + */ + ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); + writel(ctcr1 & ~(1 << 7), dev_mmio(ap, adev, PDC_CTCR1)); + } + + PDPRINTK("Set udma regs... \n"); + + ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); + ctcr1 &= 0xff000000; + ctcr1 |= pdc2027x_udma_timing_tbl[udma_mode].value0 | + (pdc2027x_udma_timing_tbl[udma_mode].value1 << 8) | + (pdc2027x_udma_timing_tbl[udma_mode].value2 << 16); + writel(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); + + PDPRINTK("Set udma regs done\n"); + + PDPRINTK("Set to udma mode[%u] \n", udma_mode); + + } else if ((dma_mode >= XFER_MW_DMA_0) && + (dma_mode <= XFER_MW_DMA_2)) { + /* Set the MDMA timing registers with value table for 133MHz */ + unsigned int mdma_mode = dma_mode & 0x07; + + PDPRINTK("Set mdma regs... \n"); + ctcr0 = readl(dev_mmio(ap, adev, PDC_CTCR0)); + + ctcr0 &= 0x0000ffff; + ctcr0 |= (pdc2027x_mdma_timing_tbl[mdma_mode].value0 << 16) | + (pdc2027x_mdma_timing_tbl[mdma_mode].value1 << 24); + + writel(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); + PDPRINTK("Set mdma regs done\n"); + + PDPRINTK("Set to mdma mode[%u] \n", mdma_mode); + } else { + printk(KERN_ERR DRV_NAME ": Unknown dma mode [%u] ignored\n", dma_mode); + } +} + +/** + * pdc2027x_post_set_mode - Set the timing registers back to correct values. + * @ap: Port to configure + * + * The pdc2027x hardware will look at "SET FEATURES" and change the timing registers + * automatically. The values set by the hardware might be incorrect, under 133Mhz PLL. + * This function overwrites the possibly incorrect values set by the hardware to be correct. + */ +static void pdc2027x_post_set_mode(struct ata_port *ap) +{ + int i; + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + + if (ata_dev_present(dev)) { + + pdc2027x_set_piomode(ap, dev); + + /* + * Enable prefetch if the device support PIO only. + */ + if (dev->xfer_shift == ATA_SHIFT_PIO) { + u32 ctcr1 = readl(dev_mmio(ap, dev, PDC_CTCR1)); + ctcr1 |= (1 << 25); + writel(ctcr1, dev_mmio(ap, dev, PDC_CTCR1)); + + PDPRINTK("Turn on prefetch\n"); + } else { + pdc2027x_set_dmamode(ap, dev); + } + } + } +} + +/** + * pdc2027x_check_atapi_dma - Check whether ATAPI DMA can be supported for this command + * @qc: Metadata associated with taskfile to check + * + * LOCKING: + * None (inherited from caller). + * + * RETURNS: 0 when ATAPI DMA can be used + * 1 otherwise + */ +static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + u8 *scsicmd = cmd->cmnd; + int rc = 1; /* atapi dma off by default */ + + /* + * This workaround is from Promise's GPL driver. + * If ATAPI DMA is used for commands not in the + * following white list, say MODE_SENSE and REQUEST_SENSE, + * pdc2027x might hit the irq lost problem. + */ + switch (scsicmd[0]) { + case READ_10: + case WRITE_10: + case READ_12: + case WRITE_12: + case READ_6: + case WRITE_6: + case 0xad: /* READ_DVD_STRUCTURE */ + case 0xbe: /* READ_CD */ + /* ATAPI DMA is ok */ + rc = 0; + break; + default: + ; + } + + return rc; +} + +/** + * pdc_read_counter - Read the ctr counter + * @probe_ent: for the port address + */ + +static long pdc_read_counter(struct ata_probe_ent *probe_ent) +{ + long counter; + int retry = 1; + u32 bccrl, bccrh, bccrlv, bccrhv; + +retry: + bccrl = readl(probe_ent->mmio_base + PDC_BYTE_COUNT) & 0xffff; + bccrh = readl(probe_ent->mmio_base + PDC_BYTE_COUNT + 0x100) & 0xffff; + rmb(); + + /* Read the counter values again for verification */ + bccrlv = readl(probe_ent->mmio_base + PDC_BYTE_COUNT) & 0xffff; + bccrhv = readl(probe_ent->mmio_base + PDC_BYTE_COUNT + 0x100) & 0xffff; + rmb(); + + counter = (bccrh << 15) | bccrl; + + PDPRINTK("bccrh [%X] bccrl [%X]\n", bccrh, bccrl); + PDPRINTK("bccrhv[%X] bccrlv[%X]\n", bccrhv, bccrlv); + + /* + * The 30-bit decreasing counter are read by 2 pieces. + * Incorrect value may be read when both bccrh and bccrl are changing. + * Ex. When 7900 decrease to 78FF, wrong value 7800 might be read. + */ + if (retry && !(bccrh == bccrhv && bccrl >= bccrlv)) { + retry--; + PDPRINTK("rereading counter\n"); + goto retry; + } + + return counter; +} + +/** + * adjust_pll - Adjust the PLL input clock in Hz. + * + * @pdc_controller: controller specific information + * @probe_ent: For the port address + * @pll_clock: The input of PLL in HZ + */ +static void pdc_adjust_pll(struct ata_probe_ent *probe_ent, long pll_clock, unsigned int board_idx) +{ + + u16 pll_ctl; + long pll_clock_khz = pll_clock / 1000; + long pout_required = board_idx? PDC_133_MHZ:PDC_100_MHZ; + long ratio = pout_required / pll_clock_khz; + int F, R; + + /* Sanity check */ + if (unlikely(pll_clock_khz < 5000L || pll_clock_khz > 70000L)) { + printk(KERN_ERR DRV_NAME ": Invalid PLL input clock %ldkHz, give up!\n", pll_clock_khz); + return; + } + +#ifdef PDC_DEBUG + PDPRINTK("pout_required is %ld\n", pout_required); + + /* Show the current clock value of PLL control register + * (maybe already configured by the firmware) + */ + pll_ctl = readw(probe_ent->mmio_base + PDC_PLL_CTL); + + PDPRINTK("pll_ctl[%X]\n", pll_ctl); +#endif + + /* + * Calculate the ratio of F, R and OD + * POUT = (F + 2) / (( R + 2) * NO) + */ + if (ratio < 8600L) { /* 8.6x */ + /* Using NO = 0x01, R = 0x0D */ + R = 0x0d; + } else if (ratio < 12900L) { /* 12.9x */ + /* Using NO = 0x01, R = 0x08 */ + R = 0x08; + } else if (ratio < 16100L) { /* 16.1x */ + /* Using NO = 0x01, R = 0x06 */ + R = 0x06; + } else if (ratio < 64000L) { /* 64x */ + R = 0x00; + } else { + /* Invalid ratio */ + printk(KERN_ERR DRV_NAME ": Invalid ratio %ld, give up!\n", ratio); + return; + } + + F = (ratio * (R+2)) / 1000 - 2; + + if (unlikely(F < 0 || F > 127)) { + /* Invalid F */ + printk(KERN_ERR DRV_NAME ": F[%d] invalid!\n", F); + return; + } + + PDPRINTK("F[%d] R[%d] ratio*1000[%ld]\n", F, R, ratio); + + pll_ctl = (R << 8) | F; + + PDPRINTK("Writing pll_ctl[%X]\n", pll_ctl); + + writew(pll_ctl, probe_ent->mmio_base + PDC_PLL_CTL); + readw(probe_ent->mmio_base + PDC_PLL_CTL); /* flush */ + + /* Wait the PLL circuit to be stable */ + mdelay(30); + +#ifdef PDC_DEBUG + /* + * Show the current clock value of PLL control register + * (maybe configured by the firmware) + */ + pll_ctl = readw(probe_ent->mmio_base + PDC_PLL_CTL); + + PDPRINTK("pll_ctl[%X]\n", pll_ctl); +#endif + + return; +} + +/** + * detect_pll_input_clock - Detect the PLL input clock in Hz. + * @probe_ent: for the port address + * Ex. 16949000 on 33MHz PCI bus for pdc20275. + * Half of the PCI clock. + */ +static long pdc_detect_pll_input_clock(struct ata_probe_ent *probe_ent) +{ + u32 scr; + long start_count, end_count; + long pll_clock; + + /* Read current counter value */ + start_count = pdc_read_counter(probe_ent); + + /* Start the test mode */ + scr = readl(probe_ent->mmio_base + PDC_SYS_CTL); + PDPRINTK("scr[%X]\n", scr); + writel(scr | (0x01 << 14), probe_ent->mmio_base + PDC_SYS_CTL); + readl(probe_ent->mmio_base + PDC_SYS_CTL); /* flush */ + + /* Let the counter run for 100 ms. */ + mdelay(100); + + /* Read the counter values again */ + end_count = pdc_read_counter(probe_ent); + + /* Stop the test mode */ + scr = readl(probe_ent->mmio_base + PDC_SYS_CTL); + PDPRINTK("scr[%X]\n", scr); + writel(scr & ~(0x01 << 14), probe_ent->mmio_base + PDC_SYS_CTL); + readl(probe_ent->mmio_base + PDC_SYS_CTL); /* flush */ + + /* calculate the input clock in Hz */ + pll_clock = (start_count - end_count) * 10; + + PDPRINTK("start[%ld] end[%ld] \n", start_count, end_count); + PDPRINTK("PLL input clock[%ld]Hz\n", pll_clock); + + return pll_clock; +} + +/** + * pdc_hardware_init - Initialize the hardware. + * @pdev: instance of pci_dev found + * @pdc_controller: controller specific information + * @pe: for the port address + */ +static int pdc_hardware_init(struct pci_dev *pdev, struct ata_probe_ent *pe, unsigned int board_idx) +{ + long pll_clock; + + /* + * Detect PLL input clock rate. + * On some system, where PCI bus is running at non-standard clock rate. + * Ex. 25MHz or 40MHz, we have to adjust the cycle_time. + * The pdc20275 controller employs PLL circuit to help correct timing registers setting. + */ + pll_clock = pdc_detect_pll_input_clock(pe); + + if (pll_clock < 0) /* counter overflow? Try again. */ + pll_clock = pdc_detect_pll_input_clock(pe); + + dev_printk(KERN_INFO, &pdev->dev, "PLL input clock %ld kHz\n", pll_clock/1000); + + /* Adjust PLL control register */ + pdc_adjust_pll(pe, pll_clock, board_idx); + + return 0; +} + +/** + * pdc_ata_setup_port - setup the mmio address + * @port: ata ioports to setup + * @base: base address + */ +static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base) +{ + port->cmd_addr = + port->data_addr = base; + port->feature_addr = + port->error_addr = base + 0x05; + port->nsect_addr = base + 0x0a; + port->lbal_addr = base + 0x0f; + port->lbam_addr = base + 0x10; + port->lbah_addr = base + 0x15; + port->device_addr = base + 0x1a; + port->command_addr = + port->status_addr = base + 0x1f; + port->altstatus_addr = + port->ctl_addr = base + 0x81a; +} + +/** + * pdc2027x_init_one - PCI probe function + * Called when an instance of PCI adapter is inserted. + * This function checks whether the hardware is supported, + * initialize hardware and register an instance of ata_host_set to + * libata by providing struct ata_probe_ent and ata_device_add(). + * (implements struct pci_driver.probe() ) + * + * @pdev: instance of pci_dev found + * @ent: matching entry in the id_tbl[] + */ +static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + unsigned int board_idx = (unsigned int) ent->driver_data; + + struct ata_probe_ent *probe_ent = NULL; + unsigned long base; + void *mmio_base; + int rc; + + if (!printed_version++) + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + goto err_out_regions; + + /* Prepare the probe entry */ + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (probe_ent == NULL) { + rc = -ENOMEM; + goto err_out_regions; + } + + memset(probe_ent, 0, sizeof(*probe_ent)); + probe_ent->dev = pci_dev_to_dev(pdev); + INIT_LIST_HEAD(&probe_ent->node); + + mmio_base = ioremap(pci_resource_start(pdev, 5), + pci_resource_len(pdev, 5)); + + if (mmio_base == NULL) { + rc = -ENOMEM; + goto err_out_free_ent; + } + + base = (unsigned long) mmio_base; + + probe_ent->sht = pdc2027x_port_info[board_idx].sht; + probe_ent->host_flags = pdc2027x_port_info[board_idx].host_flags; + probe_ent->pio_mask = pdc2027x_port_info[board_idx].pio_mask; + probe_ent->mwdma_mask = pdc2027x_port_info[board_idx].mwdma_mask; + probe_ent->udma_mask = pdc2027x_port_info[board_idx].udma_mask; + probe_ent->port_ops = pdc2027x_port_info[board_idx].port_ops; + + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + probe_ent->mmio_base = mmio_base; + + pdc_ata_setup_port(&probe_ent->port[0], base + 0x17c0); + probe_ent->port[0].bmdma_addr = base + 0x1000; + pdc_ata_setup_port(&probe_ent->port[1], base + 0x15c0); + probe_ent->port[1].bmdma_addr = base + 0x1008; + + probe_ent->n_ports = 2; + + pci_set_master(pdev); + //pci_enable_intx(pdev); + + /* initialize adapter */ + if (pdc_hardware_init(pdev, probe_ent, board_idx) != 0) + goto err_out_free_ent; + + ata_device_add(probe_ent); + kfree(probe_ent); + + return 0; + +err_out_free_ent: + kfree(probe_ent); +err_out_regions: + pci_release_regions(pdev); +err_out: + pci_disable_device(pdev); + return rc; +} + +/** + * pdc2027x_remove_one - Called to remove a single instance of the + * adapter. + * + * @dev: The PCI device to remove. + * FIXME: module load/unload not working yet + */ +static void __devexit pdc2027x_remove_one(struct pci_dev *pdev) +{ + ata_pci_remove_one(pdev); +} + +/** + * pdc2027x_init - Called after this module is loaded into the kernel. + */ +static int __init pdc2027x_init(void) +{ + return pci_module_init(&pdc2027x_pci_driver); +} + +/** + * pdc2027x_exit - Called before this module unloaded from the kernel + */ +static void __exit pdc2027x_exit(void) +{ + pci_unregister_driver(&pdc2027x_pci_driver); +} + +module_init(pdc2027x_init); +module_exit(pdc2027x_exit); diff -u --new-file --recursive linux-2.6.14.orig/drivers/scsi/sata_vsc.c linux-2.6.14.mod/drivers/scsi/sata_vsc.c --- linux-2.6.14.orig/drivers/scsi/sata_vsc.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/scsi/sata_vsc.c 2006-02-02 17:29:33.000000000 -0700 @@ -197,6 +197,9 @@ (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; + vsc_sata_scr_write(ap, VSC_SATA_SCR_ERROR_OFFSET, 0x00010002); + readl((void *)ap->ioaddr.status_addr); + qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.ctl & ATA_NIEN))) handled += ata_host_intr(ap, qc); @@ -230,7 +233,42 @@ .ordered_flush = 1, }; - + +static void vsc_legacy_phy_reset(struct ata_port *ap) +{ + ap->cbl = ATA_CBL_SATA; + ata_port_probe(ap); + ata_bus_reset(ap); +} + +static struct ata_port_operations vsc_legacy_ops = { + .port_disable = ata_port_disable, + + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .phy_reset = vsc_legacy_phy_reset, + + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + + .eng_timeout = ata_eng_timeout, + + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_pci_host_stop, +}; + static struct ata_port_operations vsc_sata_ops = { .port_disable = ata_port_disable, .tf_load = vsc_sata_tf_load, @@ -326,27 +364,14 @@ probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); - mmio_base = pci_iomap(pdev, 0, 0); - if (mmio_base == NULL) { - rc = -ENOMEM; - goto err_out_free_ent; - } - base = (unsigned long) mmio_base; - /* * Due to a bug in the chip, the default cache line size can't be used */ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80); probe_ent->sht = &vsc_sata_sht; - probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_SATA_RESET; - probe_ent->port_ops = &vsc_sata_ops; - probe_ent->n_ports = 4; probe_ent->irq = pdev->irq; probe_ent->irq_flags = SA_SHIRQ; - probe_ent->mmio_base = mmio_base; - /* We don't care much about the PIO/UDMA masks, but the core won't like us * if we don't fill these */ @@ -354,21 +379,56 @@ probe_ent->mwdma_mask = 0x07; probe_ent->udma_mask = 0x7f; - /* We have 4 ports per PCI function */ - vsc_sata_setup_port(&probe_ent->port[0], base + 1 * VSC_SATA_PORT_OFFSET); - vsc_sata_setup_port(&probe_ent->port[1], base + 2 * VSC_SATA_PORT_OFFSET); - vsc_sata_setup_port(&probe_ent->port[2], base + 3 * VSC_SATA_PORT_OFFSET); - vsc_sata_setup_port(&probe_ent->port[3], base + 4 * VSC_SATA_PORT_OFFSET); - - pci_set_master(pdev); + if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) { + probe_ent->host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | + ATA_FLAG_SATA; + probe_ent->port_ops = &vsc_legacy_ops; + + probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); + ata_std_ports(&probe_ent->port[0]); + probe_ent->port[0].altstatus_addr = + probe_ent->port[0].ctl_addr = + pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; + probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4); + + probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); + ata_std_ports(&probe_ent->port[1]); + probe_ent->port[1].altstatus_addr = + probe_ent->port[1].ctl_addr = + pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; + probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8; + probe_ent->n_ports = 2; + pci_set_master(pdev); + + } else { + mmio_base = pci_iomap(pdev, 0, 0); + if (mmio_base == NULL) { + rc = -ENOMEM; + goto err_out_free_ent; + } + base = (unsigned long) mmio_base; - /* - * Config offset 0x98 is "Extended Control and Status Register 0" - * Default value is (1 << 28). All bits except bit 28 are reserved in - * DPA mode. If bit 28 is set, LED 0 reflects all ports' activity. - * If bit 28 is clear, each port has its own LED. - */ - pci_write_config_dword(pdev, 0x98, 0); + probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_SATA_RESET; + probe_ent->port_ops = &vsc_sata_ops; + probe_ent->n_ports = 4; + probe_ent->mmio_base = mmio_base; + + /* We have 4 ports per PCI function */ + vsc_sata_setup_port(&probe_ent->port[0], base + 1 * VSC_SATA_PORT_OFFSET); + vsc_sata_setup_port(&probe_ent->port[1], base + 2 * VSC_SATA_PORT_OFFSET); + vsc_sata_setup_port(&probe_ent->port[2], base + 3 * VSC_SATA_PORT_OFFSET); + vsc_sata_setup_port(&probe_ent->port[3], base + 4 * VSC_SATA_PORT_OFFSET); + + pci_set_master(pdev); + + /* + * Config offset 0x98 is "Extended Control and Status Register 0" * Default value is (1 << 28). All bits except bit 28 are reserved in + * DPA mode. If bit 28 is set, LED 0 reflects all ports' activity. + * If bit 28 is clear, each port has its own LED. + */ + pci_write_config_dword(pdev, 0x98, 0); + } /* FIXME: check ata_device_add return value */ ata_device_add(probe_ent); @@ -394,7 +454,7 @@ */ static struct pci_device_id vsc_sata_pci_tbl[] = { { 0x1725, 0x7174, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, - { 0x8086, 0x3200, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, + { 0x8086, 0x3200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { } }; diff -u --new-file --recursive linux-2.6.14.orig/drivers/serial/Kconfig linux-2.6.14.mod/drivers/serial/Kconfig --- linux-2.6.14.orig/drivers/serial/Kconfig 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/serial/Kconfig 2006-03-09 12:23:30.000000000 -0700 @@ -888,4 +888,14 @@ and wish to use the serial ports on this card, say Y. Otherwise, say N. +config SERIAL_SDD + tristate "Z85230/Z8536 controller serial support" + depends on MVME6100 || MVME5500 || MVME5100 || MCP820 + help + If you have an MCP820 with a transition module, + or if you use an IMPC761 with an MVME6100, MVME5500, + or MVME5100, and you wish to use the Z85230/Z8536 + based serial ports, say Y. + Otherwise, say N. + endmenu diff -u --new-file --recursive linux-2.6.14.orig/drivers/serial/Makefile linux-2.6.14.mod/drivers/serial/Makefile --- linux-2.6.14.orig/drivers/serial/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/drivers/serial/Makefile 2006-03-09 12:23:41.000000000 -0700 @@ -56,3 +56,4 @@ obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o +obj-$(CONFIG_SERIAL_SDD) += sdd.o diff -u --new-file --recursive linux-2.6.14.orig/drivers/serial/sdd.c linux-2.6.14.mod/drivers/serial/sdd.c --- linux-2.6.14.orig/drivers/serial/sdd.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/serial/sdd.c 2006-03-09 12:23:48.000000000 -0700 @@ -0,0 +1,2059 @@ +/* + * sdd.c + * Serial driver for the Zilog Z85230 with a Z8536 + * + * This driver can be used on MVME5100, MVME5500, and + * MVME6100 boards that use an IPMC761 or IPMC712. + * The driver can also be used on MCP750 and MCP820 boards. + * + * The sdd driver has been derived from the macserial driver + * for the boards mentioned above by: + * Ajit Prem (Ajit.Prem@motorola.com) + * + * Derived from macserial.c: Serial port driver for Power Macintosh + * Z8530 serial driver. + * + * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras. + * + * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "sdd.h" + +char kernel_version[] = UTS_RELEASE; + +#define MESQSERIAL_VERSION "2.0" + +/* + * It would be nice to dynamically allocate everything that + * depends on NUM_SERIAL, so we could support any number of + * Z8530s, but for now... + */ +#define NUM_SERIAL 1 /* Max number of ZS chips supported in Mesq */ +#define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */ + +/* On PowerMacs, the hardware takes care of the SCC recovery time, + but we need the eieio to make sure that the accesses occur + in the order we want. */ +#define RECOVERY_DELAY eieio() + +static struct mesq_zschannel zs_channels[NUM_CHANNELS]; + +static struct mesq_serial zs_soft[NUM_CHANNELS]; +static int zs_channels_found; +static struct mesq_serial *zs_chain; /* list of all channels */ + +static spinlock_t z8536_lock; + +#define ZS_CLOCK 10000000 /* Z8530 RTxC input clock rate */ + +/* + * Get the value from the machine specific isa_io_base, see xxx_setup.c + */ +#define Z85C230BA (_IO_BASE+0x840) /* Z85C230 (SCC) base address */ + +#if defined(CONFIG_MVME6100) || defined(CONFIG_MVME5500) +#define Z85230_IRQ 105 +#else +#define Z85230_IRQ 9 +#endif + +static struct tty_driver *serial_driver; + +/* serial subtype definitions */ +#define SERIAL_TYPE_NORMAL 1 + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +/* + * Debugging. + */ +#undef SERIAL_DEBUG_INIT +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW +#undef SERIAL_DEBUG_WRITE +#undef SERIAL_DEBUG_POWER +#undef SERIAL_DEBUG_THROTTLE +#undef SERIAL_DEBUG_STOP +#undef SERIAL_DEBUG_BAUDS + +#define RS_STROBE_TIME 10 +#define RS_ISR_PASS_LIMIT 256 + +#define _INLINE_ inline + +#ifdef SERIAL_DEBUG_OPEN +#define OPNDBG(fmt, arg...) printk(KERN_INFO fmt , ## arg) +#else +#define OPNDBG(fmt, arg...) do { } while (0) +#endif +#ifdef SERIAL_DEBUG_POWER +#define PWRDBG(fmt, arg...) printk(KERN_INFO fmt , ## arg) +#else +#define PWRDBG(fmt, arg...) do { } while (0) +#endif +#ifdef SERIAL_DEBUG_BAUDS +#define BAUDBG(fmt, arg...) printk(fmt , ## arg) +#else +#define BAUDBG(fmt, arg...) do { } while (0) +#endif + +static int probe_sccs(void); +static void change_speed(struct mesq_serial *info, struct termios *old); +static void rs_wait_until_sent(struct tty_struct *tty, int timeout); +static int setup_scc(struct mesq_serial *info); + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the copy_from_user blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char *tmp_buf; +static DECLARE_MUTEX(tmp_buf_sem); + +static inline int +serial_paranoia_check(struct mesq_serial *info, + char *name, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + static const char badmagic[] = KERN_WARNING + "Warning: bad magic number for serial struct %s in %s\n"; + static const char badinfo[] = KERN_WARNING + "Warning: null mac_serial for %s in %s\n"; + + if (!info) { + printk(badinfo, name, routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, name, routine); + return 1; + } +#endif + return 0; +} + +/* + * Reading and writing Z8530 registers. + */ +static inline unsigned char read_zsreg(struct mesq_zschannel *channel, + unsigned char reg) +{ + unsigned char retval; + unsigned long flags; + + /* + * We have to make this atomic. + */ + spin_lock_irqsave(&channel->lock, flags); + if (reg != 0) { + *channel->control = reg; + RECOVERY_DELAY; + } + retval = *channel->control; + RECOVERY_DELAY; + spin_unlock_irqrestore(&channel->lock, flags); + return retval; +} + +static inline void write_zsreg(struct mesq_zschannel *channel, + unsigned char reg, unsigned char value) +{ + unsigned long flags; + + spin_lock_irqsave(&channel->lock, flags); + if (reg != 0) { + *channel->control = reg; + RECOVERY_DELAY; + } + *channel->control = value; + RECOVERY_DELAY; + spin_unlock_irqrestore(&channel->lock, flags); + return; +} + +static inline unsigned char read_zsdata(struct mesq_zschannel *channel) +{ + unsigned char retval; + + retval = *channel->data; + RECOVERY_DELAY; + return retval; +} + +static inline void write_zsdata(struct mesq_zschannel *channel, + unsigned char value) +{ + *channel->data = value; + RECOVERY_DELAY; + return; +} + +/* + * Reading and writing Z8536 registers. + */ +static inline unsigned char read_z8536reg(volatile unsigned char *control_reg, + unsigned char reg_offset) +{ + unsigned char retval; + unsigned long flags; + + /* + * We have to make this atomic. + */ + spin_lock_irqsave(&z8536_lock, flags); + if (reg_offset != 0) { + *control_reg = reg_offset; + RECOVERY_DELAY; + } + retval = *control_reg; + RECOVERY_DELAY; + spin_unlock_irqrestore(&z8536_lock, flags); + return retval; +} + +static inline void write_z8536reg(volatile unsigned char *control_reg, + unsigned char reg_offset, unsigned char value) +{ + unsigned long flags; + + spin_lock_irqsave(&z8536_lock, flags); + if (reg_offset != 0) { + *control_reg = reg_offset; + RECOVERY_DELAY; + } + *control_reg = value; + RECOVERY_DELAY; + spin_unlock_irqrestore(&z8536_lock, flags); + return; +} + +static inline void z8536_dtr_assert(struct mesq_serial *ss) +{ + unsigned long system_base = Z85C230BA; + volatile unsigned char *control_reg; + int data_port; + unsigned char reg; + + if (ss->zs_chan_a == ss->zs_channel) + data_port = Z8536_RO_PAD; + else + data_port = Z8536_RO_PBD; + control_reg = (volatile unsigned char *)system_base + CIOOFFS; + reg = read_z8536reg(control_reg, data_port); + write_z8536reg(control_reg, data_port, reg | Z8536_IOP_DTR); +} + +static inline void dump_zsregs(struct mesq_zschannel *channel, + unsigned char *regs) +{ + printk("rr0 0x%x\n", read_zsreg(channel, 0)); + printk("rr1 0x%x\n", read_zsreg(channel, 1)); + printk("rr2 0x%x\n", read_zsreg(channel, 2)); + printk("rr3 0x%x\n", read_zsreg(channel, 3)); + printk("rr4 0x%x\n", read_zsreg(channel, 4)); + printk("rr5 0x%x\n", read_zsreg(channel, 5)); + printk("rr6 0x%x\n", read_zsreg(channel, 6)); + printk("rr7 0x%x\n", read_zsreg(channel, 7)); + printk("rr8 0x%x\n", read_zsreg(channel, 8)); + printk("rr9 0x%x\n", read_zsreg(channel, 9)); + printk("rr10 0x%x\n", read_zsreg(channel, 10)); + printk("rr11 0x%x\n", read_zsreg(channel, 11)); + printk("rr12 0x%x\n", read_zsreg(channel, 12)); + printk("rr13 0x%x\n", read_zsreg(channel, 13)); + printk("rr14 0x%x\n", read_zsreg(channel, 14)); + printk("rr15 0x%x\n", read_zsreg(channel, 15)); + write_zsreg(channel, R15, regs[R15] | 1); + write_zsreg(channel, R7, 0x40); + printk("wr3 0x%x\n", read_zsreg(channel, 9)); + printk("wr4 0x%x\n", read_zsreg(channel, 4)); + printk("wr5 0x%x\n", read_zsreg(channel, 5)); + printk("wr7p 0x%x\n", read_zsreg(channel, 14)); + printk("wr10 0x%x\n", read_zsreg(channel, 11)); + write_zsreg(channel, R7, 0x00); + write_zsreg(channel, R15, regs[R15]); +} + +static inline void load_zsregs(struct mesq_zschannel *channel, + unsigned char *regs) +{ + ZS_CLEARERR(channel); + ZS_CLEARFIFO(channel); + /* Load 'em up */ + write_zsreg(channel, R4, regs[R4]); + write_zsreg(channel, R10, regs[R10]); + write_zsreg(channel, R3, regs[R3] & ~RxENABLE); + write_zsreg(channel, R5, regs[R5] & ~TxENAB); + write_zsreg(channel, R1, regs[R1]); + write_zsreg(channel, R9, regs[R9]); + write_zsreg(channel, R11, regs[R11]); + write_zsreg(channel, R12, regs[R12]); + write_zsreg(channel, R13, regs[R13]); + write_zsreg(channel, R14, regs[R14]); + write_zsreg(channel, R15, regs[R15]); + write_zsreg(channel, R3, regs[R3]); + write_zsreg(channel, R5, regs[R5]); + return; +} + +/* Sets or clears DTR/RTS on the requested line */ +static void zs_rtsdtr(struct mesq_serial *ss, int set) +{ + z8536_dtr_assert(ss); + + if (set) { + ss->curregs[5] |= RTS; + } else { + ss->curregs[5] &= ~RTS; + } + + write_zsreg(ss->zs_channel, 5, ss->curregs[5]); + return; +} + +/* Utility routines for the Zilog */ +static inline int get_zsbaud(struct mesq_serial *ss) +{ + struct mesq_zschannel *channel = ss->zs_channel; + int brg; + + if ((ss->curregs[R11] & TCBR) == 0) { + /* higher rates don't use the baud rate generator */ + return (ss->curregs[R4] & X32CLK) ? ZS_CLOCK / 32 : ZS_CLOCK / + 16; + } + /* The baud rate is split up between two 8-bit registers in + * what is termed 'BRG time constant' format in my docs for + * the chip, it is a function of the clk rate the chip is + * receiving which happens to be constant. + */ + brg = (read_zsreg(channel, 13) << 8); + brg |= read_zsreg(channel, 12); + return BRG_TO_BPS(brg, (ZS_CLOCK / (ss->clk_divisor))); +} + +/* On receive, this clears errors and the receiver interrupts */ +static inline void rs_recv_clear(struct mesq_zschannel *zsc) +{ + write_zsreg(zsc, 0, ERR_RES); + write_zsreg(zsc, 0, RES_H_IUS); /* XXX this is unnecessary */ +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * rs_interrupt(). They were separated out for readability's sake. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + */ +/* we will "borrow" the MAC bottom half intr position, for now */ +static _INLINE_ void rs_sched_event(struct mesq_serial *info, int event) +{ + info->event |= 1 << event; + schedule_work(&info->tqueue); +} + +/* Work out the flag value for a z8530 status value. */ +static _INLINE_ int stat_to_flag(int stat) +{ + int flag; + + if (stat & Rx_OVR) { + flag = TTY_OVERRUN; + } else if (stat & FRM_ERR) { + flag = TTY_FRAME; + } else if (stat & PAR_ERR) { + flag = TTY_PARITY; + } else + flag = 0; + return flag; +} + +static _INLINE_ void receive_chars(struct mesq_serial *info, + struct pt_regs *regs) +{ + struct tty_struct *tty = info->tty; + unsigned char ch, stat, flag; + + while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) != 0) { + stat = read_zsreg(info->zs_channel, R1); + ch = read_zsdata(info->zs_channel); + + if (!tty) + continue; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + tty_flip_buffer_push(tty); + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + static int flip_buf_ovf; + + if (++flip_buf_ovf <= 1) + printk(KERN_WARNING "FB. overflow: %d\n", + flip_buf_ovf); + break; + } + tty->flip.count++; + { + static int flip_max_cnt; + + if (flip_max_cnt < tty->flip.count) + flip_max_cnt = tty->flip.count; + } + flag = stat_to_flag(stat); + if (flag) + /* reset the error indication */ + write_zsreg(info->zs_channel, 0, ERR_RES); + *tty->flip.flag_buf_ptr++ = flag; + *tty->flip.char_buf_ptr++ = ch; + } + if (tty) + tty_flip_buffer_push(tty); +} + +static void transmit_chars(struct mesq_serial *info) +{ + if ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) + goto out; + info->tx_active = 0; + + if (info->x_char) { + /* Send next char */ + write_zsdata(info->zs_channel, info->x_char); + info->x_char = 0; + info->tx_active = 1; + goto out; + } + + if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped) { + write_zsreg(info->zs_channel, 0, RES_Tx_P); + goto out; + } + + /* Send char */ +#ifdef SERIAL_DEBUG_WRITE + printk("transmit_char: %c\n", info->xmit_buf[info->xmit_tail]); +#endif + write_zsdata(info->zs_channel, info->xmit_buf[info->xmit_tail++]); + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1); + info->xmit_cnt--; + info->tx_active = 1; + + if (info->xmit_cnt < WAKEUP_CHARS) + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + + out: + return; +} + +static _INLINE_ void status_handle(struct mesq_serial *info) +{ + unsigned char status; + + /* Get status from Read Register 0 */ + status = read_zsreg(info->zs_channel, 0); + + /* Check for DCD transitions */ + if (((status ^ info->read_reg_zero) & DCD) != 0 + && info->tty && !C_CLOCAL(info->tty)) { + if (status & DCD) { + wake_up_interruptible(&info->open_wait); + } else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) { + if (info->tty) + tty_hangup(info->tty); + } + } + + /* Check for CTS transitions */ + if (info->tty && C_CRTSCTS(info->tty)) { + /* + * For some reason, on the Power Macintosh, + * it seems that the CTS bit is 1 when CTS is + * *negated* and 0 when it is asserted. + * The DCD bit doesn't seem to be inverted + * like this. + */ + if ((status & CTS) == 0) { + if (info->tx_stopped) { +#ifdef SERIAL_DEBUG_FLOW + printk("CTS up\n"); +#endif + info->tx_stopped = 0; + if (!info->tx_active) + transmit_chars(info); + } + } else { +#ifdef SERIAL_DEBUG_FLOW + printk("CTS down\n"); +#endif + info->tx_stopped = 1; + } + } + + /* Clear status condition... */ + write_zsreg(info->zs_channel, 0, RES_EXT_INT); + info->read_reg_zero = status; +} + +/* + * This is the serial driver's generic interrupt routine + */ + +#define CHAN_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT) + +static irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct mesq_serial *info = (struct mesq_serial *)dev_id; + unsigned char zs_intreg; + int shift; + int handled = 0; + + /* NOTE: The read register 3, which holds the irq status, + * does so for both channels on each chip. Although + * the status value itself must be read from the A + * channel and is only valid when read from channel A. + * Yes... broken hardware... + */ + + if (info->zs_chan_a == info->zs_channel) + shift = 3; /* Channel A */ + else + shift = 0; /* Channel B */ + + if (!(info->flags & ZILOG_INITIALIZED)) { + /* There may be a race condition between clearing the + * ZILOG_INITIALIZED flag and getting an interrupt. + * We must clear a status change. + */ + zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift; + + if (zs_intreg & CHBEXT) + write_zsreg(info->zs_channel, 0, RES_EXT_INT); + + if (zs_intreg & CHBRxIP) + receive_chars(info, regs); + +#ifdef SERIAL_DEBUG_INTR + printk(KERN_DEBUG + ("sdd: rs_interrupt: irq %d, port not initialized, zs_intreg 0x%x\n", + irq, (int)zs_intreg); +#endif + return IRQ_HANDLED; + } + + for (;;) { + zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift; +#ifdef SERIAL_DEBUG_INTR + printk(KERN_DEBUG "rs_interrupt: irq %d, zs_intreg 0x%x\n", + irq, (int)zs_intreg); +#endif + + if ((zs_intreg & CHAN_IRQMASK) == 0) + break; + handled = 1; + + if (zs_intreg & CHBRxIP) + receive_chars(info, regs); + if (zs_intreg & CHBTxIP) + transmit_chars(info); + if (zs_intreg & CHBEXT) + status_handle(info); + } + return IRQ_RETVAL(handled); +} + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * ------------------------------------------------------------ + */ +static void rs_stop(struct tty_struct *tty) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + +#ifdef SERIAL_DEBUG_STOP + printk("rs_stop 0x%x....\n", tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->name, "rs_stop")) + return; + +#if 0 + spin_lock_irqsave(&info->lock, flags); + if (info->curregs[5] & TxENAB) { + info->curregs[5] &= ~TxENAB; + info->pendregs[5] &= ~TxENAB; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + } + spin_unlock_irqrestore(&info->lock, flags); +#endif +} + +static void rs_start(struct tty_struct *tty) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + unsigned long flags; + +#ifdef SERIAL_DEBUG_STOP + printk("rs_start 0x%x....\n", tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->name, "rs_start")) + return; + + spin_lock_irqsave(&info->lock, flags); +#if 0 + if (info->xmit_cnt && info->xmit_buf && !(info->curregs[5] & TxENAB)) { + info->curregs[5] |= TxENAB; + info->pendregs[5] = info->curregs[5]; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + } +#else + if (info->xmit_cnt && info->xmit_buf && !info->tx_active) { + transmit_chars(info); + } +#endif + spin_unlock_irqrestore(&info->lock, flags); +} + +/* + * This routine is used to handle the "bottom half" processing for the + * serial driver, known also the "software interrupt" processing. + * This processing is done at the kernel interrupt level, after the + * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * is where time-consuming activities which can not be done in the + * interrupt driver proper are done; the interrupt driver schedules + * them using rs_sched_event(), and they get done here. + */ + +static void do_softint(void *private_) +{ + struct mesq_serial *info = (struct mesq_serial *)private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup) (tty); + wake_up_interruptible(&tty->write_wait); + } +} + +static int startup(struct mesq_serial *info, int can_sleep) +{ + int delay = 0; + + OPNDBG("startup() (ttyS%d, irq %d)\n", info->line, info->irq); + + if (info->flags & ZILOG_INITIALIZED) { + OPNDBG(" -> already inited\n"); + return 0; + } + + if (!info->xmit_buf) { + info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); + if (!info->xmit_buf) + return -ENOMEM; + } + + OPNDBG("starting up ttyS%d (irq %d)...\n", info->line, info->irq); + + setup_scc(info); + + if (delay) { + if (can_sleep) { + /* we need to wait a bit before using the port */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(delay * HZ / 1000); + } else + mdelay(delay); + } + + OPNDBG("enabling IRQ on ttyS%d (irq %d)...\n", info->line, info->irq); + + info->flags |= ZILOG_INITIALIZED; + + return 0; +} + +static int setup_scc(struct mesq_serial *info) +{ + unsigned long flags; + + OPNDBG("setting up ttyS%d SCC...\n", info->line); + + spin_lock_irqsave(&info->lock, flags); + + /* + * Reset the chip. + */ + write_zsreg(info->zs_channel, 9, + (info->zs_channel == info->zs_chan_a ? CHRA : CHRB)); + udelay(10); + write_zsreg(info->zs_channel, 9, 0); + + /* + * Clear the receive FIFO. + */ + ZS_CLEARFIFO(info->zs_channel); + info->xmit_fifo_size = 1; + + /* + * Clear the interrupt registers. + */ + write_zsreg(info->zs_channel, 0, ERR_RES); + write_zsreg(info->zs_channel, 0, RES_H_IUS); + + /* + * Turn on RTS and DTR. + */ + zs_rtsdtr(info, 1); + + /* + * Finally, enable sequencing and interrupts + */ + /* Interrupt on ext/status changes, all received chars, + transmit ready */ + info->curregs[1] = + (info-> + curregs[1] & ~0x18) | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB); + info->pendregs[1] = info->curregs[1]; + info->curregs[3] |= (RxENABLE | Rx8); + info->pendregs[3] = info->curregs[3]; + info->curregs[5] |= (TxENAB | Tx8); + info->pendregs[5] = info->curregs[5]; + info->curregs[9] |= (NV | MIE); + info->pendregs[9] = info->curregs[9]; + write_zsreg(info->zs_channel, 3, info->curregs[3]); + write_zsreg(info->zs_channel, 5, info->curregs[5]); + write_zsreg(info->zs_channel, 9, info->curregs[9]); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + spin_unlock_irqrestore(&info->lock, flags); + + /* + * Set the speed of the serial port + */ + change_speed(info, 0); + + /* Save the current value of RR0 */ + info->read_reg_zero = read_zsreg(info->zs_channel, 0); + + return 0; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct mesq_serial *info) +{ + OPNDBG("Shutting down serial port %d (irq %d)....\n", info->line, + info->irq); + + if (!(info->flags & ZILOG_INITIALIZED)) { + OPNDBG("(already shutdown)\n"); + return; + } + + info->pendregs[1] = info->curregs[1] = 0; + write_zsreg(info->zs_channel, 1, 0); /* no interrupts */ + + info->curregs[3] &= ~RxENABLE; + info->pendregs[3] = info->curregs[3]; + write_zsreg(info->zs_channel, 3, info->curregs[3]); + + info->curregs[5] &= ~TxENAB; + if (!info->tty || C_HUPCL(info->tty)) + info->curregs[5] &= ~DTR; + info->pendregs[5] = info->curregs[5]; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + if (info->xmit_buf) { + free_page((unsigned long)info->xmit_buf); + info->xmit_buf = 0; + } + + memset(info->curregs, 0, sizeof(info->curregs)); + memset(info->curregs, 0, sizeof(info->pendregs)); + + info->flags &= ~ZILOG_INITIALIZED; +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void change_speed(struct mesq_serial *info, struct termios *old_termios) +{ + unsigned cflag; + int bits; + int brg, baud; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return; + + cflag = info->tty->termios->c_cflag; + baud = tty_get_baud_rate(info->tty); + if (baud == 0) { + if (old_termios) { + info->tty->termios->c_cflag &= ~CBAUD; + info->tty->termios->c_cflag |= + (old_termios->c_cflag & CBAUD); + cflag = info->tty->termios->c_cflag; + baud = tty_get_baud_rate(info->tty); + } else + baud = info->zs_baud; + } + if (baud > 460800) + baud = 460800; + else if (baud == 0) + baud = 38400; + + spin_lock_irqsave(&info->lock, flags); + info->zs_baud = baud; + info->clk_divisor = 16; + + BAUDBG("set speed to %d bds, ", baud); + + switch (baud) { + case 230400: + info->curregs[4] = X1CLK; + info->curregs[11] = TRxCBR | TCBR | RCBR; + brg = BPS_TO_BRG(baud, ZS_CLOCK); + info->curregs[12] = (brg & 255); + info->curregs[13] = ((brg >> 8) & 255); + info->curregs[14] = BRENABL | BRSRC | SSBR; + break; + case 460800: + info->curregs[4] = X1CLK; + info->curregs[11] = TRxCBR | TCBR | RCBR; + brg = BPS_TO_BRG(baud, ZS_CLOCK); + info->curregs[12] = (brg & 255); + info->curregs[13] = ((brg >> 8) & 255); + info->curregs[14] = BRENABL | BRSRC | SSBR; + break; + default: + info->curregs[4] = X16CLK; + info->curregs[11] = TRxCBR | TCBR | RCBR; + brg = BPS_TO_BRG(baud, ZS_CLOCK / info->clk_divisor); + info->curregs[12] = (brg & 255); + info->curregs[13] = ((brg >> 8) & 255); + info->curregs[14] = BRENABL | BRSRC | SSBR; + } + + /* byte size and parity */ + info->curregs[3] &= ~RxNBITS_MASK; + info->curregs[5] &= ~TxNBITS_MASK; + switch (cflag & CSIZE) { + case CS5: + info->curregs[3] |= Rx5; + info->curregs[5] |= Tx5; + BAUDBG("5 bits, "); + bits = 7; + break; + case CS6: + info->curregs[3] |= Rx6; + info->curregs[5] |= Tx6; + BAUDBG("6 bits, "); + bits = 8; + break; + case CS7: + info->curregs[3] |= Rx7; + info->curregs[5] |= Tx7; + BAUDBG("7 bits, "); + bits = 9; + break; + case CS8: + default: /* defaults to 8 bits */ + info->curregs[3] |= Rx8; + info->curregs[5] |= Tx8; + BAUDBG("8 bits, "); + bits = 10; + break; + } + info->pendregs[3] = info->curregs[3]; + info->pendregs[5] = info->curregs[5]; + + info->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); + if (cflag & CSTOPB) { + info->curregs[4] |= SB2; + bits++; + BAUDBG("2 stop, "); + } else { + info->curregs[4] |= SB1; + BAUDBG("1 stop, "); + } + if (cflag & PARENB) { + bits++; + info->curregs[4] |= PAR_ENA; + BAUDBG("parity, "); + } + if (!(cflag & PARODD)) { + info->curregs[4] |= PAR_EVEN; + } + info->pendregs[4] = info->curregs[4]; + + if (!(cflag & CLOCAL)) { + if (!(info->curregs[15] & DCDIE)) + info->read_reg_zero = read_zsreg(info->zs_channel, 0); + info->curregs[15] |= DCDIE; + } else + info->curregs[15] &= ~DCDIE; + if (cflag & CRTSCTS) { + info->curregs[15] |= CTSIE; + if ((read_zsreg(info->zs_channel, 0) & CTS) != 0) + info->tx_stopped = 1; + } else { + info->curregs[15] &= ~CTSIE; + info->tx_stopped = 0; + } + info->pendregs[15] = info->curregs[15]; + + /* Calc timeout value. This is pretty broken with high baud rates with HZ=100. + This code would love a larger HZ and a >1 fifo size, but this is not + a priority. The resulting value must be >HZ/2 + */ + info->timeout = ((info->xmit_fifo_size * HZ * bits) / baud); + info->timeout += HZ / 50 + 1; /* Add .02 seconds of slop */ + + BAUDBG("timeout=%d/%ds, base:%d\n", (int)info->timeout, (int)HZ, + (int)info->baud_base); + + /* Load up the new values */ + load_zsregs(info->zs_channel, info->curregs); + +/* + dump_zsregs(info->zs_channel, info->curregs); +*/ + spin_unlock_irqrestore(&info->lock, flags); +} + +static void rs_flush_chars(struct tty_struct *tty) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) + return; + + spin_lock_irqsave(&info->lock, flags); + if (!(info->xmit_cnt <= 0 || tty->stopped || info->tx_stopped || + !info->xmit_buf)) + /* Enable transmitter */ + transmit_chars(info); + spin_unlock_irqrestore(&info->lock, flags); +} + +static int rs_write(struct tty_struct *tty, + const unsigned char *buf, int count) +{ + int c, ret = 0; + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + unsigned long flags; + +#ifdef SERIAL_DEBUG_WRITE + printk("rs_write: user (%d) count %d\n", from_user, count); +#endif + + if (serial_paranoia_check(info, tty->name, "rs_write")) + return 0; + + if (!tty || !info->xmit_buf || !tmp_buf) + return 0; + + while (1) { + spin_lock_irqsave(&info->lock, flags); + c = MIN(count, + MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { + spin_unlock_irqrestore(&info->lock, flags); + break; + } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE - 1)); + info->xmit_cnt += c; + spin_unlock_irqrestore(&info->lock, flags); + buf += c; + count -= c; + ret += c; + } + if (info->xmit_cnt && !tty->stopped && !info->tx_stopped + && !info->tx_active) + transmit_chars(info); + + return ret; +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + int ret; + + if (serial_paranoia_check(info, tty->name, "rs_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) + return 0; + return info->xmit_cnt; +} + +static void rs_flush_buffer(struct tty_struct *tty) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) + return; + spin_lock_irqsave(&info->lock, flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + spin_unlock_irqrestore(&info->lock, flags); + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup) (tty); +} + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_throttle(struct tty_struct *tty) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + unsigned long flags; + +#ifdef SERIAL_DEBUG_THROTTLE + printk("throttle 0x%x....\n", tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->name, "rs_throttle")) + return; + + if (I_IXOFF(tty)) { + spin_lock_irqsave(&info->lock, flags); + info->x_char = STOP_CHAR(tty); + if (!info->tx_active) + transmit_chars(info); + spin_unlock_irqrestore(&info->lock, flags); + } + + if (C_CRTSCTS(tty)) { + /* + * Here we want to turn off the RTS line. On Macintoshes, + * we only get the DTR line, which goes to both DTR and + * RTS on the modem. RTS doesn't go out to the serial + * port socket. So you should make sure your modem is + * set to ignore DTR if you're using CRTSCTS. + */ + spin_lock_irqsave(&info->lock, flags); + info->curregs[5] &= ~(DTR | RTS); + info->pendregs[5] &= ~(DTR | RTS); + write_zsreg(info->zs_channel, 5, info->curregs[5]); + spin_unlock_irqrestore(&info->lock, flags); + } +#ifdef CDTRCTS + if (tty->termios->c_cflag & CDTRCTS) { + spin_lock_irqsave(&info->lock, flags); + info->curregs[5] &= ~DTR; + info->pendregs[5] &= ~DTR; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + spin_unlock_irqrestore(&info->lock, flags); + } +#endif /* CDTRCTS */ +} + +static void rs_unthrottle(struct tty_struct *tty) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + unsigned long flags; + +#ifdef SERIAL_DEBUG_THROTTLE + printk("unthrottle %d: ...\n", tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) + return; + + if (I_IXOFF(tty)) { + spin_lock_irqsave(&info->lock, flags); + if (info->x_char) + info->x_char = 0; + else { + info->x_char = START_CHAR(tty); + if (!info->tx_active) + transmit_chars(info); + } + spin_unlock_irqrestore(&info->lock, flags); + } + + if (C_CRTSCTS(tty)) { + /* Assert RTS and DTR lines */ + spin_lock_irqsave(&info->lock, flags); + info->curregs[5] |= DTR | RTS; + info->pendregs[5] |= DTR | RTS; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + spin_unlock_irqrestore(&info->lock, flags); + } +#ifdef CDTRCTS + if (tty->termios->c_cflag & CDTRCTS) { + /* Assert DTR line */ + spin_lock_irqsave(&info->lock, flags); + info->curregs[5] |= DTR; + info->pendregs[5] |= DTR; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + spin_unlock_irqrestore(&info->lock, flags); + } +#endif +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static int get_serial_info(struct mesq_serial *info, + struct serial_struct __user * retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->port; + tmp.irq = info->irq; + tmp.flags = info->flags; + tmp.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + tmp.custom_divisor = info->custom_divisor; + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int set_serial_info(struct mesq_serial *info, + struct serial_struct __user * new_info) +{ + struct serial_struct new_serial; + struct mesq_serial old_info; + int retval = 0; + + if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) + return -EFAULT; + old_info = *info; + + if (!capable(CAP_SYS_ADMIN)) { + if ((new_serial.baud_base != info->baud_base) || + (new_serial.type != info->type) || + (new_serial.close_delay != info->close_delay) || + ((new_serial.flags & ~ZILOG_USR_MASK) != + (info->flags & ~ZILOG_USR_MASK))) + return -EPERM; + info->flags = ((info->flags & ~ZILOG_USR_MASK) | + (new_serial.flags & ZILOG_USR_MASK)); + info->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + if (info->count > 1) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + info->baud_base = new_serial.baud_base; + info->flags = ((info->flags & ~ZILOG_FLAGS) | + (new_serial.flags & ZILOG_FLAGS)); + info->type = new_serial.type; + info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; + + check_and_exit: + if (info->flags & ZILOG_INITIALIZED) + retval = setup_scc(info); + return retval; +} + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct mesq_serial *info, unsigned int *value) +{ + unsigned char status; + unsigned long flags; + + spin_lock_irqsave(&info->lock, flags); + status = read_zsreg(info->zs_channel, 0); + spin_unlock_irqrestore(&info->lock, flags); + status = (status & Tx_BUF_EMP) ? TIOCSER_TEMT : 0; + return put_user(status, value); +} + +static int rs_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct mesq_serial * info = (struct mesq_serial *)tty->driver_data; + unsigned char control, status; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + spin_lock_irqsave(&info->lock, flags); + control = info->curregs[5]; + status = read_zsreg(info->zs_channel, 0); + spin_unlock_irqrestore(&info->lock, flags); + return ((control & RTS) ? TIOCM_RTS: 0) + | ((control & DTR) ? TIOCM_DTR: 0) + | ((status & DCD) ? TIOCM_CAR: 0) + | ((status & CTS) ? 0: TIOCM_CTS); +} + +static int rs_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct mesq_serial * info = (struct mesq_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + spin_lock_irqsave(&info->lock, flags); + if (set & TIOCM_RTS) + info->curregs[5] |= RTS; + + if (set & TIOCM_DTR) + info->curregs[5] |= DTR; + if (clear & TIOCM_RTS) + info->curregs[5] &= ~RTS; + if (clear & TIOCM_DTR) + info->curregs[5] &= ~DTR; + + info->pendregs[5] = info->curregs[5]; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + spin_unlock_irqrestore(&info->lock, flags); + return 0; +} + +/* + * rs_break - turn transmit break condition on/off + */ +static void rs_break(struct tty_struct *tty, int break_state) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "rs_break")) + return; + + spin_lock_irqsave(&info->lock, flags); + if (break_state == -1) + info->curregs[5] |= SND_BRK; + else + info->curregs[5] &= ~SND_BRK; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + spin_unlock_irqrestore(&info->lock, flags); +} + +static int rs_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->name, "rs_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TIOCGSERIAL: + return get_serial_info(info, (struct serial_struct __user *)arg); + case TIOCSSERIAL: + return set_serial_info(info, (struct serial_struct __user *)arg); + case TIOCSERGETLSR: /* Get line status register */ + return get_lsr_info(info, (unsigned int *)arg); + + case TIOCSERGSTRUCT: + if (copy_to_user((struct mesq_serial __user *)arg, + info, sizeof(struct mesq_serial))) + return -EFAULT; + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + int was_stopped; + + if (tty->termios->c_cflag == old_termios->c_cflag) + return; + was_stopped = info->tx_stopped; + + change_speed(info, old_termios); + + if (was_stopped && !info->tx_stopped) { + tty->hw_stopped = 0; + rs_start(tty); + } +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. + * Wait for the last remaining data to be sent. + * ------------------------------------------------------------ + */ +static void rs_close(struct tty_struct *tty, struct file *filp) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + unsigned long flags; + + if (!info || serial_paranoia_check(info, tty->name, "rs_close")) + return; + + spin_lock_irqsave(&info->lock, flags); + + if (tty_hung_up_p(filp)) { + spin_unlock_irqrestore(&info->lock, flags); + return; + } + + OPNDBG("rs_close ttyS%d, count = %d\n", info->line, info->count); + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk(KERN_ERR + "rs_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } + if (--info->count < 0) { + printk(KERN_ERR + "rs_close: bad serial port count for ttyS%d: %d\n", + info->line, info->count); + info->count = 0; + } + if (info->count) { + spin_unlock_irqrestore(&info->lock, flags); + return; + } + info->flags |= ZILOG_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + OPNDBG("waiting end of Tx... (timeout:%d)\n", info->closing_wait); + tty->closing = 1; + if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE) { + spin_unlock_irqrestore(&info->lock, flags); + tty_wait_until_sent(tty, info->closing_wait); + spin_lock_irqsave(&info->lock, flags); + } + /* + * At this point we stop accepting input. To do this, we + * disable the receiver and receive interrupts. + */ + info->curregs[3] &= ~RxENABLE; + info->pendregs[3] = info->curregs[3]; + write_zsreg(info->zs_channel, 3, info->curregs[3]); + info->curregs[1] &= ~(0x18); /* disable any rx ints */ + info->pendregs[1] = info->curregs[1]; + write_zsreg(info->zs_channel, 1, info->curregs[1]); + ZS_CLEARFIFO(info->zs_channel); + if (info->flags & ZILOG_INITIALIZED) { + /* + * Before we drop DTR, make sure the SCC transmitter + * has completely drained. + */ + OPNDBG("waiting end of Rx...\n"); + spin_unlock_irqrestore(&info->lock, flags); + rs_wait_until_sent(tty, info->timeout); + spin_lock_irqsave(&info->lock, flags); + } + + shutdown(info); + /* restore flags now since shutdown() will have disabled this port's + specific irqs */ + spin_unlock_irqrestore(&info->lock, flags); + + if (tty->driver->flush_buffer) + tty->driver->flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ZILOG_NORMAL_ACTIVE | ZILOG_CALLOUT_ACTIVE | + ZILOG_CLOSING); + wake_up_interruptible(&info->close_wait); +} + +/* + * rs_wait_until_sent() --- wait until the transmitter is empty + */ +static void rs_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + unsigned long orig_jiffies, char_time; + + if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) + return; + +/* printk("rs_wait_until_sent, timeout:%d, tty_stopped:%d, tx_stopped:%d\n", + timeout, tty->stopped, info->tx_stopped); +*/ + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send also be less than the timeout. + */ + if (info->timeout <= HZ / 50) { + printk("sdd: invalid info->timeout=%d\n", info->timeout); + info->timeout = HZ / 50 + 1; + } + + char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time > HZ) { + printk("sdd: char_time %ld >HZ !!!\n", char_time); + char_time = 1; + } else if (char_time == 0) + char_time = 1; + if (timeout) + char_time = MIN(char_time, timeout); + while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + current->state = TASK_RUNNING; +} + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void rs_hangup(struct tty_struct *tty) +{ + struct mesq_serial *info = (struct mesq_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->name, "rs_hangup")) + return; + + rs_flush_buffer(tty); + shutdown(info); + info->event = 0; + info->count = 0; + info->flags &= ~(ZILOG_NORMAL_ACTIVE | ZILOG_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file *filp, + struct mesq_serial *info) +{ + DECLARE_WAITQUEUE(wait, current); + int retval; + int do_clocal = 0; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (info->flags & ZILOG_CLOSING) { + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ZILOG_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { + info->flags |= ZILOG_NORMAL_ACTIVE; + return 0; + } + + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); + OPNDBG("block_til_ready before block: ttyS%d, count = %d\n", + info->line, info->count); + spin_lock_irq(&info->lock); + if (!tty_hung_up_p(filp)) + info->count--; + spin_unlock_irq(&info->lock); + info->blocked_open++; + while (1) { + spin_lock_irq(&info->lock); + if ((tty->termios->c_cflag & CBAUD) && !info->is_irda) { + zs_rtsdtr(info, 1); + } + spin_unlock_irq(&info->lock); + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || !(info->flags & ZILOG_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & ZILOG_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & ZILOG_CLOSING) && + (do_clocal || (read_zsreg(info->zs_channel, 0) & DCD))) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + OPNDBG("block_til_ready blocking: ttyS%d, count = %d\n", + info->line, info->count); + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) + info->count++; + info->blocked_open--; + OPNDBG("block_til_ready after blocking: ttyS%d, count = %d\n", + info->line, info->count); + if (retval) + return retval; + info->flags |= ZILOG_NORMAL_ACTIVE; + return 0; +} + +static void show_serial_version(void) +{ + printk(KERN_INFO "Z85230/Z8536 serial driver version " MESQSERIAL_VERSION "\n"); +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its ZILOG structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int rs_open(struct tty_struct *tty, struct file *filp) +{ + struct mesq_serial *info; + int retval, line; + unsigned long page; + + line = tty->index; + if ((line < 0) || (line >= zs_channels_found)) + return -ENODEV; + info = zs_soft + line; + + if (serial_paranoia_check(info, tty->name, "rs_open")) + return -ENODEV; + OPNDBG("rs_open %s, count = %d tty=%p\n", + tty->name, info->count, tty); + + info->count++; + tty->driver_data = info; + info->tty = tty; + + if (!tmp_buf) { + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + if (tmp_buf) + free_page(page); + else + tmp_buf = (unsigned char *)page; + } + + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || (info->flags & ZILOG_CLOSING)) { + if (info->flags & ZILOG_CLOSING) + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ZILOG_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * Start up serial port + */ + + retval = startup(info, 1); + if (retval) + return retval; + + + retval = block_til_ready(tty, filp, info); + if (retval) { + OPNDBG("rs_open returning after block_til_ready with %d\n", + retval); + return retval; + } + + OPNDBG("rs_open ttyS%d successful...\n", info->line); + return 0; +} + +static inline int line_info(char *buf, struct mesq_serial *info) +{ + int ret = 0; + + ret += sprintf(buf, "%d: port:0x%X irq:%d", + info->line, info->port, info->irq); + ret += sprintf(buf + ret, "\n"); + return ret; +} + +int mesqserial_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int l, len = 0; + off_t begin = 0; + struct mesq_serial *info; + + len += sprintf(page, "serinfo:1.0 driver:" MESQSERIAL_VERSION "\n"); + for (info = zs_chain; info && len < 4000; info = info->zs_next) { + l = line_info(page + len, info); + len += l; + if (len + begin > off + count) + goto done; + if (len + begin < off) { + begin += len; + len = 0; + } + } + *eof = 1; + done: + if (off >= len + begin) + return 0; + *start = page + (off - begin); + return ((count < begin + len - off) ? count : begin + len - off); +} + +static int probe_sccs() +{ + struct mesq_serial **pp; + int n_chips = 0, n_channels, chip, channel; + unsigned long system_base = Z85C230BA; + struct pci_dev *dev; + +#ifdef SERIAL_DEBUG_INIT + printk("SDD probe \n"); +#endif + + dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + PCI_DEVICE_ID_WINBOND_83C553, NULL); + if (dev == NULL) + return -1; + + n_chips = NUM_SERIAL; + + pp = &zs_chain; + + n_channels = 0; + + for (chip = 0; chip < n_chips; chip++) { + for (channel = 0; channel <= 1; channel++) { + + zs_channels[n_channels].control = + (volatile unsigned char *) + system_base + (0 == channel ? 2 : 0); + zs_channels[n_channels].data = + zs_channels[n_channels].control + 1; + zs_soft[n_channels].zs_channel = + &zs_channels[n_channels]; + + zs_soft[n_channels].irq = Z85230_IRQ; + zs_soft[n_channels].zs_chan_a = &zs_channels[0]; + + *pp = &zs_soft[n_channels]; + pp = &zs_soft[n_channels].zs_next; + n_channels++; + } + } + + *pp = 0; + zs_channels_found = n_channels; +#ifdef SERIAL_DEBUG_INIT + printk("chan_a 0 0x%p ", zs_soft[0].zs_chan_a->control); + printk("chan_a 1 0x%p\n", zs_soft[1].zs_chan_a->control); + printk("SDD probe done\n"); +#endif + return 0; +} + +static void z8536_init(void) +{ + unsigned long system_base = Z85C230BA; + volatile unsigned char *control_reg; + + control_reg = (volatile unsigned char *)system_base + CIOOFFS; + + /* + * Disable master interrupt enable + * Disable all counters + * Disable counters interrupt enables + */ + + write_z8536reg(control_reg, Z8536_RO_MIC, 0x00); + write_z8536reg(control_reg, Z8536_RO_MCC, 0x00); + write_z8536reg(control_reg, Z8536_RO_CT1MS, 0x00); + write_z8536reg(control_reg, Z8536_RO_CT2MS, 0x00); + write_z8536reg(control_reg, Z8536_RO_CT3MS, 0x00); + + /* Setup port specifics */ + + write_z8536reg(control_reg, Z8536_RO_PAD, 0x40); + write_z8536reg(control_reg, Z8536_RO_PBD, 0x00); + write_z8536reg(control_reg, Z8536_RO_PCD, 0x02); + + write_z8536reg(control_reg, Z8536_RO_PAMS, 0x00); + write_z8536reg(control_reg, Z8536_RO_PBMS, 0x00); + + write_z8536reg(control_reg, Z8536_RO_PAHS, 0x00); + write_z8536reg(control_reg, Z8536_RO_PBHS, 0x00); + + write_z8536reg(control_reg, Z8536_RO_PACS, 0x00); + write_z8536reg(control_reg, Z8536_RO_PBCS, 0x00); + + write_z8536reg(control_reg, Z8536_RO_PADPP, 0xBF); + write_z8536reg(control_reg, Z8536_RO_PBDPP, 0x3F); + write_z8536reg(control_reg, Z8536_RO_PCDPP, 0x00); + + write_z8536reg(control_reg, Z8536_RO_PAIOC, 0x00); + write_z8536reg(control_reg, Z8536_RO_PBIOC, 0x00); + write_z8536reg(control_reg, Z8536_RO_PCIOC, 0x00); + + write_z8536reg(control_reg, Z8536_RO_PADD, 0x07); + write_z8536reg(control_reg, Z8536_RO_PBDD, 0xC7); + write_z8536reg(control_reg, Z8536_RO_PCDD, 0x0D); + + /* Enable ports A, B, and C */ + write_z8536reg(control_reg, Z8536_RO_MCC, 0x94); +} + +static struct tty_operations serial_ops = { + .open = rs_open, + .close = rs_close, + .write = rs_write, + .flush_chars = rs_flush_chars, + .write_room = rs_write_room, + .chars_in_buffer = rs_chars_in_buffer, + .ioctl = rs_ioctl, + .set_termios = rs_set_termios, + .throttle = rs_throttle, + .unthrottle = rs_unthrottle, + .stop = rs_stop, + .start = rs_start, + .hangup = rs_hangup, + .break_ctl = rs_break, + .flush_buffer = rs_flush_buffer, + .wait_until_sent = rs_wait_until_sent, + .read_proc = mesqserial_read_proc, + .tiocmget = rs_tiocmget, + .tiocmset = rs_tiocmset, +}; + +/* rs_init inits the driver */ +static int __init mesqserial_init(void) +{ + int channel, i; + unsigned long flags; + struct mesq_serial *info; + int ret; + +#ifdef SERIAL_DEBUG_INIT + printk("SDD init\n"); +#endif + + /* Find out how many Z8530 SCCs we have */ + if (zs_chain == 0) + if (probe_sccs() != 0) + return -ENODEV; + + z8536_init(); + + serial_driver = alloc_tty_driver(zs_channels_found); + if (!serial_driver) + return -ENOMEM; + + /* Register the interrupt handler for each chip */ + local_irq_save(flags); + for (i = 0; i < zs_channels_found; ++i) { + if ((ret = request_irq(zs_soft[i].irq, rs_interrupt, SA_SHIRQ, + "SDD", &zs_soft[i]))) + printk(KERN_ERR "sdd: can't get irq %d, ret=%d\n", + zs_soft[i].irq, ret); + } + local_irq_restore(flags); + + show_serial_version(); + + /* Initialize the tty_driver structure */ + /* Not all of this is exactly right for us. */ + + serial_driver->owner = THIS_MODULE; + serial_driver->driver_name = "mesqserial"; + serial_driver->devfs_name = "tts/"; + serial_driver->name = "ttyS"; + serial_driver->major = TTY_MAJOR; +#if defined(CONFIG_MVME6100) || defined(CONFIG_MVME5500) || defined(CONFIG_MVME5100) + serial_driver->minor_start = 68; +#else + serial_driver->minor_start = 66; +#endif + serial_driver->type = TTY_DRIVER_TYPE_SERIAL; + serial_driver->subtype = SERIAL_TYPE_NORMAL; + serial_driver->init_termios = tty_std_termios; + serial_driver->init_termios.c_cflag = + B38400 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->flags = TTY_DRIVER_REAL_RAW; + + tty_set_operations(serial_driver, &serial_ops); + + if (tty_register_driver(serial_driver)) + panic("Couldn't register serial driver\n"); + + for (channel = 0; channel < zs_channels_found; ++channel) { + zs_soft[channel].clk_divisor = 16; +/* -- we are not sure the SCC is powered ON at this point + zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); +*/ + zs_soft[channel].zs_baud = 38400; + + zs_soft[channel].is_cons = 0; /* no console. */ + zs_soft[channel].is_internal_modem = 0; /* no gatwick-based cobalt modem */ + zs_soft[channel].is_irda = 0; /* no IR led on powerbooks */ + + /* If console serial line, then enable interrupts. */ + if (zs_soft[channel].is_cons) { + printk("sdd: console line, enabling interrupt %d\n", + zs_soft[channel].irq); + panic("sdd: console not supported yet !"); + write_zsreg(zs_soft[channel].zs_channel, R1, + (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB)); + write_zsreg(zs_soft[channel].zs_channel, R9, + (NV | MIE)); + } + } + + for (info = zs_chain, i = 0; info; info = info->zs_next, i++) { + info->magic = SERIAL_MAGIC; + info->port = (int)info->zs_channel->control; + info->line = i; + info->tty = 0; + info->custom_divisor = 16; + info->timeout = 0; + info->close_delay = 50; + info->closing_wait = 3000; + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + INIT_WORK(&info->tqueue, do_softint, info); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + info->timeout = HZ; + printk(KERN_INFO "ttyS%01d at 0x%08x (irq = %d) is a Z85230 ESCC\n", + (serial_driver->minor_start - 64) + info->line, + info->port, + info->irq); + +#ifdef CONFIG_XMON + if (!info->is_internal_modem) + continue; +#endif + } + tmp_buf = 0; +#ifdef SERIAL_DEBUG_INIT + printk("SDD init done\n"); +#endif + + return 0; +} + + +static void __exit mesqserial_exit(void) +{ + int i; + int e1; + unsigned long flags; + struct mesq_serial *info; + + spin_lock_irqsave(&info->lock, flags); + for (i = 0; i < zs_channels_found; ++i) + free_irq(zs_soft[i].irq, &zs_soft[i]); + + spin_unlock_irqrestore(&info->lock, flags); + + if ((e1 = tty_unregister_driver(serial_driver))) + printk("SDD: failed to unregister serial driver (%d)\n", e1); + + put_tty_driver(serial_driver); + if (tmp_buf) { + free_page((unsigned long)tmp_buf); + tmp_buf = 0; + } +} + +module_init(mesqserial_init); +module_exit(mesqserial_exit); + +MODULE_LICENSE("GPL"); + diff -u --new-file --recursive linux-2.6.14.orig/drivers/serial/sdd.h linux-2.6.14.mod/drivers/serial/sdd.h --- linux-2.6.14.orig/drivers/serial/sdd.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/serial/sdd.h 2006-03-09 12:23:51.000000000 -0700 @@ -0,0 +1,510 @@ +/* + * sdd.h: Definitions for the Z85230 serial driver. + * The driver can be used on MVME5100, MVME5500, + * and MVME6100 boards that use an IPMC761 or IPMC712. + * THe driver can also be used on MCP750 and MCP820 boards. + * + * Adapted from macserial.h: Definitions for the Macintosh + * Z8530 serial driver. + * + * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras. + * + * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SDD_H +#define _SDD_H + +#define NUM_ZSREGS 16 + +struct serial_struct { + int type; + int line; + int port; + int irq; + int flags; + int xmit_fifo_size; + int custom_divisor; + int baud_base; + unsigned short close_delay; + char reserved_char[2]; + int hub6; + unsigned short closing_wait; /* time to wait before closing */ + unsigned short closing_wait2; /* no longer used... */ + int reserved[4]; +}; + +/* + * For the close wait times, 0 means wait forever for serial port to + * flush its output. 65535 means don't wait at all. + */ +#define ZILOG_CLOSING_WAIT_INF 0 +#define ZILOG_CLOSING_WAIT_NONE 65535 + +/* + * Definitions for ZILOG_struct (and serial_struct) flags field + */ +#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes + * on the callout port */ +#define ZILOG_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */ +#define ZILOG_SAK 0x0004 /* Secure Attention Key (Orange book) */ +#define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ + +#define ZILOG_SPD_MASK 0x0030 +#define ZILOG_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ + +#define ZILOG_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ +#define ZILOG_SPD_CUST 0x0030 /* Use user-specified divisor */ + +#define ZILOG_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */ +#define ZILOG_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */ +#define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ +#define ZILOG_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ +#define ZILOG_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */ + +#define ZILOG_FLAGS 0x0FFF /* Possible legal ZILOG flags */ +#define ZILOG_USR_MASK 0x0430 /* Legal flags that non-privileged + * users can set or reset */ + +/* Internal flags used only by kernel/chr_drv/serial.c */ +#define ZILOG_INITIALIZED 0x80000000 /* Serial port was initialized */ +#define ZILOG_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ +#define ZILOG_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ +#define ZILOG_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ +#define ZILOG_CLOSING 0x08000000 /* Serial port is closing */ +#define ZILOG_CTS_FLOW 0x04000000 /* Do CTS flow control */ +#define ZILOG_CHECK_CD 0x02000000 /* i.e., CLOCAL */ +#define ZILOG_SLEEPING 0x01000000 /* have shut it down for sleep */ + +/* Software state per channel */ + +#ifdef __KERNEL__ +/* + * This is our internal structure for each serial port's state. + * + * Many fields are paralleled by the structure used by the serial_struct + * structure. + * + * For definitions of the flags field, see tty.h + */ + +struct mesq_serial; + +struct mesq_zschannel { + volatile unsigned char *control; + volatile unsigned char *data; + spinlock_t lock; + /* Used for debugging */ + struct mesq_serial *parent; +}; + +struct mesq_serial { + struct mesq_serial *zs_next; /* For IRQ servicing chain */ + struct mesq_zschannel *zs_channel; /* Channel registers */ + struct mesq_zschannel *zs_chan_a; /* A side registers */ + unsigned char read_reg_zero; + struct device_node *dev_node; + spinlock_t lock; + + char soft_carrier; /* Use soft carrier on this channel */ + char break_abort; /* Is serial console in, so process brk/abrt */ + char kgdb_channel; /* Kgdb is running on this channel */ + + /* these are mac specific */ + + char is_cons; /* Is this our console. */ + char is_internal_modem; /* is connected to an internal modem */ + char is_irda; /* is connected to an IrDA codec */ + + unsigned char tx_active; /* character is being xmitted */ + unsigned char tx_stopped; /* output is suspended */ + + /* We need to know the current clock divisor + * to read the bps rate the chip has currently + * loaded. + */ + unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */ + int zs_baud; + + /* Current write register values */ + unsigned char curregs[NUM_ZSREGS]; + + /* Values we need to set next opportunity */ + unsigned char pendregs[NUM_ZSREGS]; + + char change_needed; + + int magic; + int baud_base; + int port; + int irq; + int flags; /* defined in tty.h */ + int type; /* UART type */ + struct tty_struct *tty; + int read_status_mask; + int ignore_status_mask; + int timeout; + int xmit_fifo_size; + int custom_divisor; + int x_char; /* xon/xoff character */ + int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; + unsigned long event; + unsigned long last_active; + int line; + int count; /* # of fd on device */ + int blocked_open; /* # of blocked opens */ + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + struct work_struct tqueue; + struct work_struct tqueue_hangup; + struct termios normal_termios; + struct termios callout_termios; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; + +}; + +#define SERIAL_MAGIC 0x5301 + +/* + * The size of the serial buffers is 1 page, or 4096 bytes + */ +#define SERIAL_XMIT_SIZE 4096 +#define SERIAL_RECV_SIZE 4096 + +/* + * Events are used to schedule things to happen at timer-interrupt + * time, instead of at rs interrupt time. + */ +#define RS_EVENT_WRITE_WAKEUP 0 + +#endif /* __KERNEL__ */ + +/* Conversion routines to/from brg time constants from/to bits + * per second. + */ +#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2)) +#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2) + +/* The Zilog register set */ + +#define FLAG 0x7e + +/* Write Register 0 */ +#define R0 0 /* Register selects */ +#define R1 1 +#define R2 2 +#define R3 3 +#define R4 4 +#define R5 5 +#define R6 6 +#define R7 7 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +#define NULLCODE 0 /* Null Code */ +#define POINT_HIGH 0x8 /* Select upper half of registers */ +#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */ +#define SEND_ABORT 0x18 /* HDLC Abort */ +#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */ +#define RES_Tx_P 0x28 /* Reset TxINT Pending */ +#define ERR_RES 0x30 /* Error Reset */ +#define RES_H_IUS 0x38 /* Reset highest IUS */ + +#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */ +#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */ +#define RES_EOM_L 0xC0 /* Reset EOM latch */ + +/* Write Register 1 */ + +#define EXT_INT_ENAB 0x1 /* Ext Int Enable */ +#define TxINT_ENAB 0x2 /* Tx Int Enable */ +#define PAR_SPEC 0x4 /* Parity is special condition */ + +#define RxINT_DISAB 0 /* Rx Int Disable */ +#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */ +#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */ +#define INT_ERR_Rx 0x18 /* Int on error only */ + +#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */ +#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */ +#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */ + +/* Write Register #2 (Interrupt Vector) */ + +/* Write Register 3 */ + +#define RxENABLE 0x1 /* Rx Enable */ +#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */ +#define ADD_SM 0x4 /* Address Search Mode (SDLC) */ +#define RxCRC_ENAB 0x8 /* Rx CRC Enable */ +#define ENT_HM 0x10 /* Enter Hunt Mode */ +#define AUTO_ENAB 0x20 /* Auto Enables */ +#define Rx5 0x0 /* Rx 5 Bits/Character */ +#define Rx7 0x40 /* Rx 7 Bits/Character */ +#define Rx6 0x80 /* Rx 6 Bits/Character */ +#define Rx8 0xc0 /* Rx 8 Bits/Character */ +#define RxNBITS_MASK 0xc0 + +/* Write Register 4 */ + +#define PAR_ENA 0x1 /* Parity Enable */ +#define PAR_EVEN 0x2 /* Parity Even/Odd* */ + +#define SYNC_ENAB 0 /* Sync Modes Enable */ +#define SB1 0x4 /* 1 stop bit/char */ +#define SB15 0x8 /* 1.5 stop bits/char */ +#define SB2 0xc /* 2 stop bits/char */ +#define SB_MASK 0xc + +#define MONSYNC 0 /* 8 Bit Sync character */ +#define BISYNC 0x10 /* 16 bit sync character */ +#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */ +#define EXTSYNC 0x30 /* External Sync Mode */ + +#define X1CLK 0x0 /* x1 clock mode */ +#define X16CLK 0x40 /* x16 clock mode */ +#define X32CLK 0x80 /* x32 clock mode */ +#define X64CLK 0xC0 /* x64 clock mode */ +#define XCLK_MASK 0xC0 + +/* Write Register 5 */ + +#define TxCRC_ENAB 0x1 /* Tx CRC Enable */ +#define RTS 0x2 /* RTS */ +#define SDLC_CRC 0x4 /* SDLC/CRC-16 */ +#define TxENAB 0x8 /* Tx Enable */ +#define SND_BRK 0x10 /* Send Break */ +#define Tx5 0x0 /* Tx 5 bits (or less)/character */ +#define Tx7 0x20 /* Tx 7 bits/character */ +#define Tx6 0x40 /* Tx 6 bits/character */ +#define Tx8 0x60 /* Tx 8 bits/character */ +#define TxNBITS_MASK 0x60 +#define DTR 0x80 /* DTR */ + +/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */ + +/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ + +/* Write Register 7' (Some enhanced feature control) */ +#define ENEXREAD 0x40 /* Enable read of some write registers */ + +/* Write Register 8 (transmit buffer) */ + +/* Write Register 9 (Master interrupt control) */ +#define VIS 1 /* Vector Includes Status */ +#define NV 2 /* No Vector */ +#define DLC 4 /* Disable Lower Chain */ +#define MIE 8 /* Master Interrupt Enable */ +#define STATHI 0x10 /* Status high */ +#define NORESET 0 /* No reset on write to R9 */ +#define CHRB 0x40 /* Reset channel B */ +#define CHRA 0x80 /* Reset channel A */ +#define FHWRES 0xc0 /* Force hardware reset */ + +/* Write Register 10 (misc control bits) */ +#define BIT6 1 /* 6 bit/8bit sync */ +#define LOOPMODE 2 /* SDLC Loop mode */ +#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */ +#define MARKIDLE 8 /* Mark/flag on idle */ +#define GAOP 0x10 /* Go active on poll */ +#define NRZ 0 /* NRZ mode */ +#define NRZI 0x20 /* NRZI mode */ +#define FM1 0x40 /* FM1 (transition = 1) */ +#define FM0 0x60 /* FM0 (transition = 0) */ +#define CRCPS 0x80 /* CRC Preset I/O */ + +/* Write Register 11 (Clock Mode control) */ +#define TRxCXT 0 /* TRxC = Xtal output */ +#define TRxCTC 1 /* TRxC = Transmit clock */ +#define TRxCBR 2 /* TRxC = BR Generator Output */ +#define TRxCDP 3 /* TRxC = DPLL output */ +#define TRxCOI 4 /* TRxC O/I */ +#define TCRTxCP 0 /* Transmit clock = RTxC pin */ +#define TCTRxCP 8 /* Transmit clock = TRxC pin */ +#define TCBR 0x10 /* Transmit clock = BR Generator output */ +#define TCDPLL 0x18 /* Transmit clock = DPLL output */ +#define RCRTxCP 0 /* Receive clock = RTxC pin */ +#define RCTRxCP 0x20 /* Receive clock = TRxC pin */ +#define RCBR 0x40 /* Receive clock = BR Generator output */ +#define RCDPLL 0x60 /* Receive clock = DPLL output */ +#define RTxCX 0x80 /* RTxC Xtal/No Xtal */ + +/* Write Register 12 (lower byte of baud rate generator time constant) */ + +/* Write Register 13 (upper byte of baud rate generator time constant) */ + +/* Write Register 14 (Misc control bits) */ +#define BRENABL 1 /* Baud rate generator enable */ +#define BRSRC 2 /* Baud rate generator source */ +#define DTRREQ 4 /* DTR/Request function */ +#define AUTOECHO 8 /* Auto Echo */ +#define LOOPBAK 0x10 /* Local loopback */ +#define SEARCH 0x20 /* Enter search mode */ +#define RMC 0x40 /* Reset missing clock */ +#define DISDPLL 0x60 /* Disable DPLL */ +#define SSBR 0x80 /* Set DPLL source = BR generator */ +#define SSRTxC 0xa0 /* Set DPLL source = RTxC */ +#define SFMM 0xc0 /* Set FM mode */ +#define SNRZI 0xe0 /* Set NRZI mode */ + +/* Write Register 15 (external/status interrupt control) */ +#define EN85C30 1 /* Enable some 85c30-enhanced registers */ +#define ZCIE 2 /* Zero count IE */ +#define ENSTFIFO 4 /* Enable status FIFO (SDLC) */ +#define DCDIE 8 /* DCD IE */ +#define SYNCIE 0x10 /* Sync/hunt IE */ +#define CTSIE 0x20 /* CTS IE */ +#define TxUIE 0x40 /* Tx Underrun/EOM IE */ +#define BRKIE 0x80 /* Break/Abort IE */ + +/* Read Register 0 */ +#define Rx_CH_AV 0x1 /* Rx Character Available */ +#define ZCOUNT 0x2 /* Zero count */ +#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ +#define DCD 0x8 /* DCD */ +#define SYNC_HUNT 0x10 /* Sync/hunt */ +#define CTS 0x20 /* CTS */ +#define TxEOM 0x40 /* Tx underrun */ +#define BRK_ABRT 0x80 /* Break/Abort */ + +/* Read Register 1 */ +#define ALL_SNT 0x1 /* All sent */ +/* Residue Data for 8 Rx bits/char programmed */ +#define RES3 0x8 /* 0/3 */ +#define RES4 0x4 /* 0/4 */ +#define RES5 0xc /* 0/5 */ +#define RES6 0x2 /* 0/6 */ +#define RES7 0xa /* 0/7 */ +#define RES8 0x6 /* 0/8 */ +#define RES18 0xe /* 1/8 */ +#define RES28 0x0 /* 2/8 */ +/* Special Rx Condition Interrupts */ +#define PAR_ERR 0x10 /* Parity error */ +#define Rx_OVR 0x20 /* Rx Overrun Error */ +#define FRM_ERR 0x40 /* CRC/Framing Error */ +#define END_FR 0x80 /* End of Frame (SDLC) */ + +/* Read Register 2 (channel b only) - Interrupt vector */ +#define CHB_Tx_EMPTY 0x00 +#define CHB_EXT_STAT 0x02 +#define CHB_Rx_AVAIL 0x04 +#define CHB_SPECIAL 0x06 +#define CHA_Tx_EMPTY 0x08 +#define CHA_EXT_STAT 0x0a +#define CHA_Rx_AVAIL 0x0c +#define CHA_SPECIAL 0x0e +#define STATUS_MASK 0x06 + +/* Read Register 3 (interrupt pending register) ch a only */ +#define CHBEXT 0x1 /* Channel B Ext/Stat IP */ +#define CHBTxIP 0x2 /* Channel B Tx IP */ +#define CHBRxIP 0x4 /* Channel B Rx IP */ +#define CHAEXT 0x8 /* Channel A Ext/Stat IP */ +#define CHATxIP 0x10 /* Channel A Tx IP */ +#define CHARxIP 0x20 /* Channel A Rx IP */ + +/* Read Register 8 (receive data register) */ + +/* Read Register 10 (misc status bits) */ +#define ONLOOP 2 /* On loop */ +#define LOOPSEND 0x10 /* Loop sending */ +#define CLK2MIS 0x40 /* Two clocks missing */ +#define CLK1MIS 0x80 /* One clock missing */ + +/* Read Register 12 (lower byte of baud rate generator constant) */ + +/* Read Register 13 (upper byte of baud rate generator constant) */ + +/* Read Register 15 (value of WR 15) */ + +/* Misc macros */ +#define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES)) +#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ + garbage = read_zsdata(channel); \ + garbage = read_zsdata(channel); \ + garbage = read_zsdata(channel); \ + } while(0) + +/* Most ECCG boards use the Z8536 CIO chip for asserting DTR */ + +#define CIOOFFS 4 /* Offset of 8536 from 85230 */ +#define CIO_DTR 0x20 /* (output) Data Terminal Ready */ + +#define Z8536_RO_MIC 0x00 /* master interrupt control */ +#define Z8536_RO_MCC 0x01 /* master configuration control */ +#define Z8536_RO_PAIV 0x02 /* port A's interrupt vector */ +#define Z8536_RO_PBIV 0x03 /* port B's interrupt vector */ +#define Z8536_RO_CTIV 0x04 /* counter/timer's interrupt vector */ +#define Z8536_RO_PCDPP 0x05 /* port C's data path polarity */ +#define Z8536_RO_PCDD 0x06 /* port C's data direction */ +#define Z8536_RO_PCIOC 0x07 /* port C's special I/O control */ +#define Z8536_RO_PACS 0x08 /* port A's control/status */ +#define Z8536_RO_PBCS 0x09 /* port B's control/status */ +#define Z8536_RO_CT1CS 0x0A /* counter/timer 1's command/status */ +#define Z8536_RO_CT2CS 0x0B /* counter/timer 2's command/status */ +#define Z8536_RO_CT3CS 0x0C /* counter/timer 3's command/status */ +#define Z8536_RO_PAD 0x0D /* port A's data */ +#define Z8536_RO_PBD 0x0E /* port B's data */ +#define Z8536_RO_PCD 0x0F /* port C's data */ + +#define Z8536_RO_CT1CCM 0x10 /* counter/timer 1's current count MSB */ +#define Z8536_RO_CT1CCL 0x11 /* counter/timer 1's current count LSB */ +#define Z8536_RO_CT2CCM 0x12 /* counter/timer 2's current count MSB */ +#define Z8536_RO_CT2CCL 0x13 /* counter/timer 2's current count LSB */ +#define Z8536_RO_CT3CCM 0x14 /* counter/timer 3's current count MSB */ +#define Z8536_RO_CT3CCL 0x15 /* counter/timer 3's current count LSB */ +#define Z8536_RO_CT1TCM 0x16 /* counter/timer 1's time constant MSB */ +#define Z8536_RO_CT1TCL 0x17 /* counter/timer 1's time constant LSB */ +#define Z8536_RO_CT2TCM 0x18 /* counter/timer 2's time constant MSB */ +#define Z8536_RO_CT2TCL 0x19 /* counter/timer 2's time constant LSB */ +#define Z8536_RO_CT3TCM 0x1A /* counter/timer 3's time constant MSB */ +#define Z8536_RO_CT3TCL 0x1B /* counter/timer 3's time constant LSB */ +#define Z8536_RO_CT1MS 0x1C /* counter/timer 1's mode specification */ +#define Z8536_RO_CT2MS 0x1D /* counter/timer 2's mode specification */ +#define Z8536_RO_CT3MS 0x1E /* counter/timer 3's mode specification */ +#define Z8536_RO_CV 0x1F /* current vector */ + +#define Z8536_RO_PAMS 0x20 /* port A's mode specification */ +#define Z8536_RO_PAHS 0x21 /* port A's handshake specification */ +#define Z8536_RO_PADPP 0x22 /* port A's data path polarity */ +#define Z8536_RO_PADD 0x23 /* port A's data direction */ +#define Z8536_RO_PAIOC 0x24 /* port A's special i/o control */ +#define Z8536_RO_PAPP 0x25 /* port A's pattern polarity */ +#define Z8536_RO_PAPT 0x26 /* port A's pattern transition */ +#define Z8536_RO_PAPM 0x27 /* port A's pattern mask */ + +#define Z8536_RO_PBMS 0x28 /* port B's mode specification */ +#define Z8536_RO_PBHS 0x29 /* port B's handshake specification */ +#define Z8536_RO_PBDPP 0x2A /* port B's data path polarity */ +#define Z8536_RO_PBDD 0x2B /* port B's data direction */ +#define Z8536_RO_PBIOC 0x2C /* port B's special i/o control */ +#define Z8536_RO_PBPP 0x2D /* port B's pattern polarity */ +#define Z8536_RO_PBPT 0x2E /* port B's pattern transition */ +#define Z8536_RO_PBPM 0x2F /* port B's pattern mask */ + +/* + * Z8536 I/O bit ports A and B definitions + */ + +#define Z8536_IOP_TM (1<<0) /* test mode (TM) */ +#define Z8536_IOP_DSR (1<<1) /* data set ready (DSR) */ +#define Z8536_IOP_RI (1<<2) /* ring indicator (RI) */ +#define Z8536_IOP_LLB (1<<3) /* local loopback (LLB) */ +#define Z8536_IOP_RLB (1<<4) /* remote loopback (RLB) */ +#define Z8536_IOP_DTR (1<<5) /* data terminal ready (DTR) */ + +#endif /* !(_SDD_H) */ diff -u --new-file --recursive linux-2.6.14.orig/drivers/vme/ca91c042.c linux-2.6.14.mod/drivers/vme/ca91c042.c --- linux-2.6.14.orig/drivers/vme/ca91c042.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/vme/ca91c042.c 2006-06-13 13:33:47.000000000 -0700 @@ -0,0 +1,1912 @@ +/* + * ca91c042.c + * + * Support for the Tundra Universe I/II VME Bridge chips + * + * Author: Tom Armistead + * Updated and maintained by Ajit Prem + * Copyright 2004 Motorola Inc. + * + * Derived from ca91c042.c by Michael Wyrick + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vmedrv.h" +#include "ca91c042.h" + +//---------------------------------------------------------------------------- +// Prototypes +//---------------------------------------------------------------------------- +extern struct vmeSharedData *vmechip_interboard_data; +extern dma_addr_t vmechip_interboard_datap; +extern const int vmechip_revision; +extern const int vmechip_devid; +extern const int vmechip_irq; +extern int vmechip_irq_overhead_ticks; +extern char *vmechip_baseaddr; +extern const int vme_slotnum; +extern int vme_syscon; +extern char *in_image_ba[]; +extern int in_image_size[]; +extern int in_image_mapped[]; +extern dma_addr_t in_image_pa[]; +extern unsigned int out_image_va[]; +extern unsigned int vme_irqlog[8][0x100]; +extern struct pci_dev *vme_pci_dev; + +static int outCTL[] = { LSI0_CTL, LSI1_CTL, LSI2_CTL, LSI3_CTL, + LSI4_CTL, LSI5_CTL, LSI6_CTL, LSI7_CTL +}; + +static int outBS[] = { LSI0_BS, LSI1_BS, LSI2_BS, LSI3_BS, + LSI4_BS, LSI5_BS, LSI6_BS, LSI7_BS +}; + +static int outBD[] = { LSI0_BD, LSI1_BD, LSI2_BD, LSI3_BD, + LSI4_BD, LSI5_BD, LSI6_BD, LSI7_BD +}; + +static int outTO[] = { LSI0_TO, LSI1_TO, LSI2_TO, LSI3_TO, + LSI4_TO, LSI5_TO, LSI6_TO, LSI7_TO +}; + +static int inCTL[] = { VSI0_CTL, VSI1_CTL, VSI2_CTL, VSI3_CTL, + VSI4_CTL, VSI5_CTL, VSI6_CTL, VSI7_CTL +}; + +static int inBS[] = { VSI0_BS, VSI1_BS, VSI2_BS, VSI3_BS, + VSI4_BS, VSI5_BS, VSI6_BS, VSI7_BS +}; + +static int inBD[] = { VSI0_BD, VSI1_BD, VSI2_BD, VSI3_BD, + VSI4_BD, VSI5_BD, VSI6_BD, VSI7_BD +}; + +static int inTO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO, + VSI4_TO, VSI5_TO, VSI6_TO, VSI7_TO +}; +static int vmevec[7] = { V1_STATID, V2_STATID, V3_STATID, V4_STATID, + V5_STATID, V6_STATID, V7_STATID +}; + +struct interrupt_counters { + unsigned int acfail; + unsigned int sysfail; + unsigned int sw_int; + unsigned int sw_iack; + unsigned int verr; + unsigned int lerr; + unsigned int lm; + unsigned int mbox; + unsigned int dma; + unsigned int virq[7]; + unsigned int vown; +}; + +extern wait_queue_head_t dma_queue[]; +extern wait_queue_head_t lm_queue; +extern wait_queue_head_t mbox_queue; + +extern void vme_sync_data(void); +extern void vme_flush_line(void *); +extern void vme_flush_range(void *, void *); +extern int tb_speed; + +unsigned int uni_irq_time; +unsigned int uni_dma_irq_time; +unsigned int uni_lm_event; + +static spinlock_t lm_lock = SPIN_LOCK_UNLOCKED; + +static struct interrupt_counters Interrupt_counters = { 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + {0, 0, 0, 0, 0, 0, 0}, + 0 +}; + +#define read_register(offset) readl(vmechip_baseaddr + offset) +#define write_register(value,offset) writel(value, vmechip_baseaddr + offset) +#define read_register_word(offset) readw(vmechip_baseaddr + offset) +#define write_register_word(value,offset) writew(value, vmechip_baseaddr + offset) + +//---------------------------------------------------------------------------- +// uni_procinfo() +//---------------------------------------------------------------------------- +int uni_procinfo(char *buf) +{ + char *p; + + p = buf; + + p += sprintf(p, "\n"); + { + unsigned long misc_ctl; + + misc_ctl = read_register(MISC_CTL); + p += sprintf(p, "MISC_CTL:\t\t\t0x%08lx\n", misc_ctl); + p += sprintf(p, "VME Bus Time Out:\t\t"); + switch ((misc_ctl & UNIV_BM_MISC_CTL_VBTO) >> + UNIV_OF_MISC_CTL_VBTO) { + case 0x0: + p += sprintf(p, "Disabled\n"); + break; + case 0x1: + p += sprintf(p, "16 us\n"); + break; + case 0x2: + p += sprintf(p, "32 us\n"); + break; + case 0x3: + p += sprintf(p, "64 us\n"); + break; + case 0x4: + p += sprintf(p, "128 us\n"); + break; + case 0x5: + p += sprintf(p, "256 us\n"); + break; + case 0x6: + p += sprintf(p, "512 us\n"); + break; + case 0x7: + p += sprintf(p, "1024 us\n"); + break; + default: + p += sprintf(p, "Reserved Value, Undefined\n"); + } + p += sprintf(p, "VME Arbitration Time Out:\t"); + switch ((misc_ctl & UNIV_BM_MISC_CTL_VARBTO) >> + UNIV_OF_MISC_CTL_VARBTO) { + case 0x0: + p += sprintf(p, "Disabled"); + break; + case 0x1: + p += sprintf(p, "16 us"); + break; + case 0x2: + p += sprintf(p, "256 us"); + break; + default: + p += sprintf(p, "Reserved Value, Undefined"); + } + if (misc_ctl & UNIV_BM_MISC_CTL_VARB) + p += sprintf(p, ", Priority Arbitration\n"); + else + p += sprintf(p, ", Round Robin Arbitration\n"); + p += sprintf(p, "\n"); + } + + { + unsigned int lmisc; + unsigned int crt; + unsigned int cwt; + + lmisc = read_register(LMISC); + p += sprintf(p, "LMISC:\t\t\t\t0x%08x\n", lmisc); + crt = (lmisc & UNIV_BM_LMISC_CRT) >> UNIV_OF_LMISC_CRT; + cwt = (lmisc & UNIV_BM_LMISC_CWT) >> UNIV_OF_LMISC_CWT; + p += sprintf(p, "Coupled Request Timer:\t\t"); + switch (crt) { + case 0x0: + p += sprintf(p, "Disabled\n"); + break; + case 0x1: + p += sprintf(p, "128 us\n"); + break; + case 0x2: + p += sprintf(p, "256 us\n"); + break; + case 0x3: + p += sprintf(p, "512 us\n"); + break; + case 0x4: + p += sprintf(p, "1024 us\n"); + break; + case 0x5: + p += sprintf(p, "2048 us\n"); + break; + case 0x6: + p += sprintf(p, "4096 us\n"); + break; + default: + p += sprintf(p, "Reserved\n"); + } + p += sprintf(p, "Coupled Window Timer:\t\t"); + switch (cwt) { + case 0x0: + p += sprintf(p, "Disabled\n"); + break; + case 0x1: + p += sprintf(p, "16 PCI Clocks\n"); + break; + case 0x2: + p += sprintf(p, "32 PCI Clocks\n"); + break; + case 0x3: + p += sprintf(p, "64 PCI Clocks\n"); + break; + case 0x4: + p += sprintf(p, "128 PCI Clocks\n"); + break; + case 0x5: + p += sprintf(p, "256 PCI Clocks\n"); + break; + case 0x6: + p += sprintf(p, "512 PCI Clocks\n"); + break; + default: + p += sprintf(p, "Reserved\n"); + } + p += sprintf(p, "\n"); + } + { + unsigned int mast_ctl; + + mast_ctl = read_register(MAST_CTL); + p += sprintf(p, "MAST_CTL:\t\t\t0x%08x\n", mast_ctl); + { + int retries; + + retries = ((mast_ctl & UNIV_BM_MAST_CTL_MAXRTRY) + >> UNIV_OF_MAST_CTL_MAXRTRY) * 64; + p += sprintf(p, "Max PCI Master Retries:\t\t"); + if (retries) + p += sprintf(p, "%d\n", retries); + else + p += sprintf(p, "Forever\n"); + } + + p += sprintf(p, "Posted Write Transfer Count:\t"); + switch ((mast_ctl & UNIV_BM_MAST_CTL_PWON) >> + UNIV_OF_MAST_CTL_PWON) { + case 0x0: + p += sprintf(p, "128 Bytes\n"); + break; + case 0x1: + p += sprintf(p, "256 Bytes\n"); + break; + case 0x2: + p += sprintf(p, "512 Bytes\n"); + break; + case 0x3: + p += sprintf(p, "1024 Bytes\n"); + break; + case 0x4: + p += sprintf(p, "2048 Bytes\n"); + break; + case 0x5: + p += sprintf(p, "4096 Bytes\n"); + break; + default: + p += sprintf(p, "Undefined\n"); + } + + p += sprintf(p, "VMEbus Request Level:\t\t"); + switch ((mast_ctl & UNIV_BM_MAST_CTL_VRL) >> + UNIV_OF_MAST_CTL_VRL) { + case 0x0: + p += sprintf(p, "Level 0\n"); + case 0x1: + p += sprintf(p, "Level 1\n"); + case 0x2: + p += sprintf(p, "Level 2\n"); + case 0x3: + p += sprintf(p, "Level 3\n"); + } + p += sprintf(p, "VMEbus Request Mode:\t\t"); + if (mast_ctl & UNIV_BM_MAST_CTL_VRM) + p += sprintf(p, "Fair Request Mode\n"); + else + p += sprintf(p, "Demand Request Mode\n"); + p += sprintf(p, "VMEbus Release Mode:\t\t"); + if (mast_ctl & UNIV_BM_MAST_CTL_VREL) + p += sprintf(p, "Release on Request\n"); + else + p += sprintf(p, "Release when Done\n"); + p += sprintf(p, "VMEbus Ownership Bit:\t\t"); + if (mast_ctl & UNIV_BM_MAST_CTL_VOWN) + p += sprintf(p, "Acquire and hold VMEbus\n"); + else + p += sprintf(p, "Release VMEbus\n"); + p += sprintf(p, "VMEbus Ownership Bit Ack:\t"); + if (mast_ctl & UNIV_BM_MAST_CTL_VOWN_ACK) + p += sprintf(p, "Owning VMEbus\n"); + else + p += sprintf(p, "Not Owning VMEbus\n"); + p += sprintf(p, "\n"); + } + { + unsigned int misc_stat; + + misc_stat = read_register(MISC_STAT); + p += sprintf(p, "MISC_STAT:\t\t\t0x%08x\n", misc_stat); + p += sprintf(p, "Universe BBSY:\t\t\t"); + if (misc_stat & UNIV_BM_MISC_STAT_MYBBSY) + p += sprintf(p, "Negated\n"); + else + p += sprintf(p, "Asserted\n"); + p += sprintf(p, "Transmit FIFO:\t\t\t"); + if (misc_stat & UNIV_BM_MISC_STAT_TXFE) + p += sprintf(p, "Empty\n"); + else + p += sprintf(p, "Not empty\n"); + p += sprintf(p, "Receive FIFO:\t\t\t"); + if (misc_stat & UNIV_BM_MISC_STAT_RXFE) + p += sprintf(p, "Empty\n"); + else + p += sprintf(p, "Not Empty\n"); + p += sprintf(p, "\n"); + } + + p += sprintf(p, "Latency Timer:\t\t\t%02d Clocks\n\n", + (read_register(UNIV_PCI_MISC0) & + UNIV_BM_PCI_MISC0_LTIMER) >> UNIV_OF_PCI_MISC0_LTIMER); + + { + unsigned int lint_en; + unsigned int lint_stat; + + lint_en = read_register(LINT_EN); + lint_stat = read_register(LINT_STAT); + +#define REPORT_IRQ(name,field) \ + p += sprintf(p, (lint_en & UNIV_BM_LINT_##name) ? "Enabled" : "Masked"); \ + p += sprintf(p, ", triggered %d times", Interrupt_counters.field); \ + p += sprintf(p, (lint_stat & UNIV_BM_LINT_##name) ? ", irq now active\n" : "\n"); + p += sprintf(p, "ACFAIL Interrupt:\t\t"); + REPORT_IRQ(ACFAIL, acfail); + p += sprintf(p, "SYSFAIL Interrupt:\t\t"); + REPORT_IRQ(SYSFAIL, sysfail); + p += sprintf(p, "SW_INT Interrupt:\t\t"); + REPORT_IRQ(SW_INT, sw_int); + p += sprintf(p, "SW_IACK Interrupt:\t\t"); + REPORT_IRQ(SW_IACK, sw_iack); + p += sprintf(p, "VERR Interrupt:\t\t\t"); + REPORT_IRQ(VERR, verr); + p += sprintf(p, "LERR Interrupt:\t\t\t"); + REPORT_IRQ(LERR, lerr); + p += sprintf(p, "LM Interrupt:\t\t\t"); + REPORT_IRQ(LM, lm); + p += sprintf(p, "MBOX Interrupt:\t\t\t"); + REPORT_IRQ(MBOX, mbox); + p += sprintf(p, "DMA Interrupt:\t\t\t"); + REPORT_IRQ(DMA, dma); + p += sprintf(p, "VIRQ7 Interrupt:\t\t"); + REPORT_IRQ(VIRQ7, virq[7 - 1]); + p += sprintf(p, "VIRQ6 Interrupt:\t\t"); + REPORT_IRQ(VIRQ6, virq[6 - 1]); + p += sprintf(p, "VIRQ5 Interrupt:\t\t"); + REPORT_IRQ(VIRQ5, virq[5 - 1]); + p += sprintf(p, "VIRQ4 Interrupt:\t\t"); + REPORT_IRQ(VIRQ4, virq[4 - 1]); + p += sprintf(p, "VIRQ3 Interrupt:\t\t"); + REPORT_IRQ(VIRQ3, virq[3 - 1]); + p += sprintf(p, "VIRQ2 Interrupt:\t\t"); + REPORT_IRQ(VIRQ2, virq[2 - 1]); + p += sprintf(p, "VIRQ1 Interrupt:\t\t"); + REPORT_IRQ(VIRQ1, virq[1 - 1]); + p += sprintf(p, "VOWN Interrupt:\t\t\t"); + REPORT_IRQ(VOWN, vown); + p += sprintf(p, "\n"); +#undef REPORT_IRQ + } + { + unsigned long vrai_ctl; + + vrai_ctl = read_register(VRAI_CTL); + if (vrai_ctl & UNIV_BM_VRAI_CTL_EN) { + unsigned int vrai_bs; + + vrai_bs = read_register(VRAI_BS); + p += sprintf(p, + "VME Register Image:\t\tEnabled at VME-Address 0x%x\n", + vrai_bs); + } else + p += sprintf(p, "VME Register Image:\t\tDisabled\n"); + } + { + unsigned int slsi; + + slsi = read_register(SLSI); + if (slsi & UNIV_BM_SLSI_EN) { + /* Not implemented */ + } else { + p += sprintf(p, "Special PCI Slave Image:\tDisabled\n"); + } + } + { + int i; + + for (i = 0; i < (vmechip_revision > 0 ? 8 : 4); i++) { + unsigned int ctl, bs, bd, to, vstart, vend; + + ctl = readl(vmechip_baseaddr + outCTL[i]); + bs = readl(vmechip_baseaddr + outBS[i]); + bd = readl(vmechip_baseaddr + outBD[i]); + to = readl(vmechip_baseaddr + outTO[i]); + + vstart = bs + to; + vend = bd + to; + + p += sprintf(p, "PCI Slave Image %d:\t\t", i); + if (ctl & UNIV_BM_LSI_CTL_EN) { + p += sprintf(p, "Enabled"); + if (ctl & UNIV_BM_LSI_CTL_PWEN) + p += sprintf(p, + ", Posted Write Enabled\n"); + else + p += sprintf(p, "\n"); + p += sprintf(p, + "\t\t\t\tPCI Addresses from 0x%x to 0x%x\n", + bs, bd); + p += sprintf(p, + "\t\t\t\tVME Addresses from 0x%x to 0x%x\n", + vstart, vend); + } else + p += sprintf(p, "Disabled\n"); + } + p += sprintf(p, "\n"); + } + { + int i; + for (i = 0; i < (vmechip_revision > 0 ? 8 : 4); i++) { + unsigned int ctl, bs, bd, to, vstart, vend; + + ctl = readl(vmechip_baseaddr + inCTL[i]); + bs = readl(vmechip_baseaddr + inBS[i]); + bd = readl(vmechip_baseaddr + inBD[i]); + to = readl(vmechip_baseaddr + inTO[i]); + vstart = bs + to; + vend = bd + to; + p += sprintf(p, "VME Slave Image %d:\t\t", i); + if (ctl & UNIV_BM_LSI_CTL_EN) { + p += sprintf(p, "Enabled"); + if (ctl & UNIV_BM_LSI_CTL_PWEN) + p += sprintf(p, + ", Posted Write Enabled\n"); + else + p += sprintf(p, "\n"); + p += sprintf(p, + "\t\t\t\tVME Addresses from 0x%x to 0x%x\n", + bs, bd); + p += sprintf(p, + "\t\t\t\tPCI Addresses from 0x%x to 0x%x\n", + vstart, vend); + } else + p += sprintf(p, "Disabled\n"); + } + } + + return p - buf; +} + +//---------------------------------------------------------------------------- +// uni_bus_error_chk() +//---------------------------------------------------------------------------- +int uni_bus_error_chk(int clrflag) +{ + int tmp; + tmp = readl(vmechip_baseaddr + PCI_COMMAND); + if (tmp & 0x08000000) { // S_TA is Set + if (clrflag) + writel(tmp | 0x08000000, + vmechip_baseaddr + PCI_COMMAND); + return (1); + } + return (0); +} + +//----------------------------------------------------------------------------- +// Function : DMA_uni_irqhandler +// Inputs : void +// Outputs : void +// Description: Saves DMA completion timestamp and then wakes up DMA queue +//----------------------------------------------------------------------------- +static void DMA_uni_irqhandler(void) +{ + uni_dma_irq_time = uni_irq_time; + wake_up(&dma_queue[0]); +} + +//----------------------------------------------------------------------------- +// Function : LERR_uni_irqhandler +// Inputs : void +// Outputs : void +// Description: +//----------------------------------------------------------------------------- +static void LERR_uni_irqhandler(void) +{ + int val; + + val = readl(vmechip_baseaddr + DGCS); + + if (!(val & 0x00000800)) { + printk(KERN_ERR + "ca91c042: LERR_uni_irqhandler DMA Read Error DGCS=%08X\n", + val); + + } +} + +//----------------------------------------------------------------------------- +// Function : VERR_uni_irqhandler +// Inputs : void +// Outputs : void +// Description: +//----------------------------------------------------------------------------- +static void VERR_uni_irqhandler(void) +{ + int val; + + val = readl(vmechip_baseaddr + DGCS); + + if (!(val & 0x00000800)) { + printk(KERN_ERR + "ca91c042: VERR_uni_irqhandler DMA Read Error DGCS=%08X\n", + val); + } + +} + +//----------------------------------------------------------------------------- +// Function : MB_uni_irqhandler +// Inputs : void +// Outputs : void +// Description: +//----------------------------------------------------------------------------- +static void MB_uni_irqhandler(int mbox_mask) +{ + if (vmechip_irq_overhead_ticks != 0) { + wake_up(&mbox_queue); + } +} + +//----------------------------------------------------------------------------- +// Function : LM_uni_irqhandler +// Inputs : void +// Outputs : void +// Description: +//----------------------------------------------------------------------------- +static void LM_uni_irqhandler(int lm_mask) +{ + uni_lm_event = lm_mask; + wake_up(&lm_queue); +} + +//----------------------------------------------------------------------------- +// Function : VIRQ_uni_irqhandler +// Inputs : void +// Outputs : void +// Description: +//----------------------------------------------------------------------------- +static void VIRQ_uni_irqhandler(int virq_mask) +{ + int iackvec, i; + + for (i = 7; i > 0; i--) { + if (virq_mask & (1 << i)) { + Interrupt_counters.virq[i - 1]++; + iackvec = readl(vmechip_baseaddr + vmevec[i - 1]); + vme_irqlog[i][iackvec]++; + } + } +} + +//----------------------------------------------------------------------------- +// Function : uni_irqhandler +// Inputs : int irq, void *dev_id, struct pt_regs *regs +// Outputs : void +// Description: +//----------------------------------------------------------------------------- +static irqreturn_t uni_irqhandler(int irq, void *dev_id, struct pt_regs *regs) +{ + long stat, enable; + + if (dev_id != vmechip_baseaddr) + return IRQ_NONE; + + uni_irq_time = get_tbl(); + + stat = readl(vmechip_baseaddr + LINT_STAT); + writel(stat, vmechip_baseaddr + LINT_STAT); // Clear all pending ints + enable = readl(vmechip_baseaddr + LINT_EN); + stat = stat & enable; + if (stat & 0x0100) { + Interrupt_counters.dma++; + DMA_uni_irqhandler(); + } + if (stat & 0x0200) { + Interrupt_counters.lerr++; + LERR_uni_irqhandler(); + } + if (stat & 0x0400) { + Interrupt_counters.verr++; + VERR_uni_irqhandler(); + } + if (stat & 0xF0000) { + Interrupt_counters.mbox++; + MB_uni_irqhandler((stat & 0xF0000) >> 16); + } + if (stat & 0xF00000) { + Interrupt_counters.lm++; + LM_uni_irqhandler((stat & 0xF00000) >> 20); + } + if (stat & 0x0000FE) { + VIRQ_uni_irqhandler(stat & 0x0000FE); + } + if (stat & UNIV_BM_LINT_ACFAIL) { + Interrupt_counters.acfail++; + } + if (stat & UNIV_BM_LINT_SYSFAIL) { + Interrupt_counters.sysfail++; + } + if (stat & UNIV_BM_LINT_SW_INT) { + Interrupt_counters.sw_int++; + } + if (stat & UNIV_BM_LINT_SW_IACK) { + Interrupt_counters.sw_iack++; + } + if (stat & UNIV_BM_LINT_VOWN) { + Interrupt_counters.vown++; + } + + return IRQ_HANDLED; +} + +//----------------------------------------------------------------------------- +// Function : uni_generate_irq +// Description: +//----------------------------------------------------------------------------- +int uni_generate_irq(virqInfo_t * vmeIrq) +{ + int timeout; + int looptimeout; + + timeout = vmeIrq->waitTime; + if (timeout == 0) { + timeout++; // Wait at least 1 tick... + } + looptimeout = HZ / 20; // try for 1/20 second + + vmeIrq->timeOutFlag = 0; + + // Validate & setup vector register. + if (vmeIrq->vector & 1) { // Universe can only generate even vectors + return (-EINVAL); + } + writel(vmeIrq->vector << 24, vmechip_baseaddr + STATID); + + // Assert VMEbus IRQ + writel(1 << (vmeIrq->level + 24), vmechip_baseaddr + VINT_EN); + + // Wait for syscon to do iack + while (readl(vmechip_baseaddr + VINT_STAT) & + (1 << (vmeIrq->level + 24))) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(looptimeout); + timeout = timeout - looptimeout; + if (timeout <= 0) { + vmeIrq->timeOutFlag = 1; + break; + } + } + + // Clear VMEbus IRQ bit + writel(0, vmechip_baseaddr + VINT_EN); + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_set_arbiter +// Description: +//----------------------------------------------------------------------------- +int uni_set_arbiter(vmeArbiterCfg_t * vmeArb) +{ + int temp_ctl = 0; + int vbto = 0; + + temp_ctl = readl(vmechip_baseaddr + MISC_CTL); + temp_ctl &= 0x00FFFFFF; + + if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) { + vbto = 7; + } else if (vmeArb->globalTimeoutTimer > 1024) { + return (-EINVAL); + } else if (vmeArb->globalTimeoutTimer == 0) { + vbto = 0; + } else { + vbto = 1; + while ((16 * (1 << (vbto - 1))) < vmeArb->globalTimeoutTimer) { + vbto += 1; + } + } + temp_ctl |= (vbto << 28); + + if (vmeArb->arbiterMode == VME_PRIORITY_MODE) { + temp_ctl |= 1 << 26; + } + + if (vmeArb->arbiterTimeoutFlag) { + temp_ctl |= 2 << 24; + } + + writel(temp_ctl, vmechip_baseaddr + MISC_CTL); + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_get_arbiter +// Description: +//----------------------------------------------------------------------------- +int uni_get_arbiter(vmeArbiterCfg_t * vmeArb) +{ + int temp_ctl = 0; + int vbto = 0; + + temp_ctl = readl(vmechip_baseaddr + MISC_CTL); + + vbto = (temp_ctl >> 28) & 0xF; + if (vbto != 0) { + vmeArb->globalTimeoutTimer = (16 * (1 << (vbto - 1))); + } + + if (temp_ctl & (1 << 26)) { + vmeArb->arbiterMode = VME_PRIORITY_MODE; + } else { + vmeArb->arbiterMode = VME_R_ROBIN_MODE; + } + + if (temp_ctl & (3 << 24)) { + vmeArb->arbiterTimeoutFlag = 1; + } + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_set_requestor +// Description: +//----------------------------------------------------------------------------- +int uni_set_requestor(vmeRequesterCfg_t * vmeReq) +{ + int temp_ctl = 0; + + temp_ctl = readl(vmechip_baseaddr + MAST_CTL); + temp_ctl &= 0xFF0FFFFF; + + if (vmeReq->releaseMode == 1) { + temp_ctl |= (1 << 20); + } + + if (vmeReq->fairMode == 1) { + temp_ctl |= (1 << 21); + } + + temp_ctl |= (vmeReq->requestLevel << 22); + + writel(temp_ctl, vmechip_baseaddr + MAST_CTL); + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_get_requestor +// Description: +//----------------------------------------------------------------------------- +int uni_get_requestor(vmeRequesterCfg_t * vmeReq) +{ + int temp_ctl = 0; + + temp_ctl = readl(vmechip_baseaddr + MAST_CTL); + + if (temp_ctl & (1 << 20)) { + vmeReq->releaseMode = 1; + } + + if (temp_ctl & (1 << 21)) { + vmeReq->fairMode = 1; + } + + vmeReq->requestLevel = (temp_ctl & 0xC00000) >> 22; + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_set_in_bound +// Description: +//----------------------------------------------------------------------------- +int uni_set_in_bound(vmeInWindowCfg_t * vmeIn) +{ + int temp_ctl = 0; + unsigned int win; + struct page *page, *pend; + + // Verify input data + win = vmeIn->windowNbr; + + if (win > 7) + return -EINVAL; + + /* Free previous allocation */ +#ifndef CONFIG_VME_BRIDGE_BOOTMEM + if (in_image_ba[win] != NULL) { +#else + if ((win != 7) && (in_image_ba[win] != NULL)) { +#endif + /* Undo marking the pages as reserved */ + pend = virt_to_page(in_image_ba[win] + in_image_size[win] - 1); + for (page = virt_to_page(in_image_ba[win]); page <= pend; page++) + ClearPageReserved(page); + dma_free_coherent(&vme_pci_dev->dev, + in_image_size[win], + in_image_ba[win], + in_image_pa[win]); + in_image_mapped[win] = 0; + } + + if (vmeIn->windowEnable == 0) { + temp_ctl = readl(vmechip_baseaddr + inCTL[vmeIn->windowNbr]); + temp_ctl &= ~0x80000000; + writel(temp_ctl, vmechip_baseaddr + inCTL[vmeIn->windowNbr]); + return 0; + } + +#ifdef CONFIG_VME_BRIDGE_BOOTMEM + if (win == 7) { + vmeIn->windowSizeL = in_image_size[7]; + vmeIn->windowSizeU = 0; + } +#endif + + if ((vmeIn->vmeAddrU) || (vmeIn->windowSizeU)) + return (-EINVAL); + + if ((vmeIn->vmeAddrL & 0xFFF) || (vmeIn->windowSizeL & 0xFFF)) + return (-EINVAL); + +#ifndef CONFIG_VME_BRIDGE_BOOTMEM + if (vmeIn->windowSizeL > 0x800000) +#else + if ((win != 7) && (vmeIn->windowSizeL > 0x800000)) +#endif + return (-EINVAL); + + if (vmeIn->bcastRespond2esst) + return (-EINVAL); + + switch (vmeIn->addrSpace) { + case VME_A64: + case VME_CRCSR: + case VME_USER3: + case VME_USER4: + return (-EINVAL); + case VME_A16: + temp_ctl |= 0x00000; + break; + case VME_A24: + temp_ctl |= 0x10000; + break; + case VME_A32: + temp_ctl |= 0x20000; + break; + case VME_USER1: + temp_ctl |= 0x60000; + break; + case VME_USER2: + temp_ctl |= 0x70000; + break; + } + +#ifndef CONFIG_VME_BRIDGE_BOOTMEM + if (vmeIn->windowEnable == 1) { +#else + if ((win != 7) && (vmeIn->windowEnable == 1)) { +#endif + in_image_ba[win] = (char *)dma_alloc_coherent((struct device *) + &vme_pci_dev->dev, + vmeIn->windowSizeL, + (dma_addr_t *)&in_image_pa[win], + GFP_KERNEL); + if (!in_image_ba[win]) { + printk("vmedrv: No memory for inbound window\n"); + return -ENOMEM; + } + in_image_size[win] = vmeIn->windowSizeL; + + /* now mark the pages as reserved; otherwise */ + /* remap_pfn_range doesn't do what we want */ + pend = virt_to_page(in_image_ba[win] + in_image_size[win] - 1); + for (page = virt_to_page(in_image_ba[win]); page <= pend; page++) + SetPageReserved(page); + memset(in_image_ba[win], 0, in_image_size[win]); + vme_flush_range(in_image_ba[win], + in_image_ba[win] + in_image_size[win]); + vmeIn->pciAddrL = (unsigned int)in_image_pa[win]; + vmeIn->pciAddrU = 0; +#ifndef CONFIG_VME_BRIDGE_BOOTMEM + } +#else + } else if (win == 7) { + vmeIn->pciAddrL = (unsigned int)in_image_pa[win]; + vmeIn->pciAddrU = 0; + } +#endif + + // Disable while we are mucking around + writel(0x00000000, vmechip_baseaddr + inCTL[vmeIn->windowNbr]); + writel(vmeIn->vmeAddrL, vmechip_baseaddr + inBS[vmeIn->windowNbr]); + writel(vmeIn->vmeAddrL + vmeIn->windowSizeL, + vmechip_baseaddr + inBD[vmeIn->windowNbr]); + writel(vmeIn->pciAddrL - vmeIn->vmeAddrL, + vmechip_baseaddr + inTO[vmeIn->windowNbr]); + + // Setup CTL register. + if (vmeIn->wrPostEnable) + temp_ctl |= 0x40000000; + if (vmeIn->prefetchEnable) + temp_ctl |= 0x20000000; + if (vmeIn->rmwLock) + temp_ctl |= 0x00000040; + if (vmeIn->data64BitCapable) + temp_ctl |= 0x00000080; + if (vmeIn->userAccessType & VME_USER) + temp_ctl |= 0x00100000; + if (vmeIn->userAccessType & VME_SUPER) + temp_ctl |= 0x00200000; + if (vmeIn->dataAccessType & VME_DATA) + temp_ctl |= 0x00400000; + if (vmeIn->dataAccessType & VME_PROG) + temp_ctl |= 0x00800000; + + // Write ctl reg without enable + writel(temp_ctl, vmechip_baseaddr + inCTL[vmeIn->windowNbr]); + + if (vmeIn->windowEnable) + temp_ctl |= 0x80000000; + + writel(temp_ctl, vmechip_baseaddr + inCTL[vmeIn->windowNbr]); + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_get_in_bound +// Description: +//----------------------------------------------------------------------------- +int uni_get_in_bound(vmeInWindowCfg_t * vmeIn) +{ + int temp_ctl = 0; + + // Verify input data + if (vmeIn->windowNbr > 7) { + return (-EINVAL); + } + // Get Window mappings. + vmeIn->vmeAddrL = readl(vmechip_baseaddr + inBS[vmeIn->windowNbr]); + vmeIn->pciAddrL = vmeIn->vmeAddrL + + readl(vmechip_baseaddr + inTO[vmeIn->windowNbr]); + vmeIn->windowSizeL = readl(vmechip_baseaddr + inBD[vmeIn->windowNbr]) - + vmeIn->vmeAddrL; + + temp_ctl = readl(vmechip_baseaddr + inCTL[vmeIn->windowNbr]); + + // Get Control & BUS attributes + if (temp_ctl & 0x40000000) + vmeIn->wrPostEnable = 1; + if (temp_ctl & 0x20000000) + vmeIn->prefetchEnable = 1; + if (temp_ctl & 0x00000040) + vmeIn->rmwLock = 1; + if (temp_ctl & 0x00000080) + vmeIn->data64BitCapable = 1; + if (temp_ctl & 0x00100000) + vmeIn->userAccessType |= VME_USER; + if (temp_ctl & 0x00200000) + vmeIn->userAccessType |= VME_SUPER; + if (temp_ctl & 0x00400000) + vmeIn->dataAccessType |= VME_DATA; + if (temp_ctl & 0x00800000) + vmeIn->dataAccessType |= VME_PROG; + if (temp_ctl & 0x80000000) + vmeIn->windowEnable = 1; + + switch ((temp_ctl & 0x70000) >> 16) { + case 0x0: + vmeIn->addrSpace = VME_A16; + break; + case 0x1: + vmeIn->addrSpace = VME_A24; + break; + case 0x2: + vmeIn->addrSpace = VME_A32; + break; + case 0x6: + vmeIn->addrSpace = VME_USER1; + break; + case 0x7: + vmeIn->addrSpace = VME_USER2; + break; + } + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_set_out_bound +// Description: +//----------------------------------------------------------------------------- +int uni_set_out_bound(vmeOutWindowCfg_t * vmeOut) +{ + int temp_ctl = 0; + + // Verify input data + if (vmeOut->windowNbr > 7) { + return (-EINVAL); + } + + if (vmeOut->windowEnable == 0) { + temp_ctl = readl(vmechip_baseaddr + outCTL[vmeOut->windowNbr]); + temp_ctl &= ~0x80000000; + writel(temp_ctl, vmechip_baseaddr + outCTL[vmeOut->windowNbr]); + } + + if ((vmeOut->xlatedAddrU) || (vmeOut->windowSizeU) + || (vmeOut->pciBusAddrU)) { + return (-EINVAL); + } + if ((vmeOut->xlatedAddrL & 0xFFF) || + (vmeOut->windowSizeL & 0xFFF) || (vmeOut->pciBusAddrL & 0xFFF)) { + return (-EINVAL); + } + if (vmeOut->bcastSelect2esst) { + return (-EINVAL); + } + switch (vmeOut->addrSpace) { + case VME_A64: + case VME_USER3: + case VME_USER4: + return (-EINVAL); + case VME_A16: + temp_ctl |= 0x00000; + break; + case VME_A24: + temp_ctl |= 0x10000; + break; + case VME_A32: + temp_ctl |= 0x20000; + break; + case VME_CRCSR: + temp_ctl |= 0x50000; + break; + case VME_USER1: + temp_ctl |= 0x60000; + break; + case VME_USER2: + temp_ctl |= 0x70000; + break; + } + + // Disable while we are mucking around + writel(0x00000000, vmechip_baseaddr + outCTL[vmeOut->windowNbr]); + writel(vmeOut->pciBusAddrL, + vmechip_baseaddr + outBS[vmeOut->windowNbr]); + writel(vmeOut->pciBusAddrL + vmeOut->windowSizeL, + vmechip_baseaddr + outBD[vmeOut->windowNbr]); + writel(vmeOut->xlatedAddrL - vmeOut->pciBusAddrL, + vmechip_baseaddr + outTO[vmeOut->windowNbr]); + + // Sanity check. + if (vmeOut->pciBusAddrL != + readl(vmechip_baseaddr + outBS[vmeOut->windowNbr])) { + printk(KERN_ERR + "ca91c042: out window: %x, failed to configure\n", + vmeOut->windowNbr); + return (-EINVAL); + } + + if (vmeOut->pciBusAddrL + vmeOut->windowSizeL != + readl(vmechip_baseaddr + outBD[vmeOut->windowNbr])) { + printk(KERN_ERR + "ca91c042: out window: %x, failed to configure\n", + vmeOut->windowNbr); + return (-EINVAL); + } + + if (vmeOut->xlatedAddrL - vmeOut->pciBusAddrL != + readl(vmechip_baseaddr + outTO[vmeOut->windowNbr])) { + printk(KERN_ERR + "ca91c042: out window: %x, failed to configure\n", + vmeOut->windowNbr); + return (-EINVAL); + } + // Setup CTL register. + if (vmeOut->wrPostEnable) + temp_ctl |= 0x40000000; + if (vmeOut->userAccessType & VME_SUPER) + temp_ctl |= 0x001000; + if (vmeOut->dataAccessType & VME_PROG) + temp_ctl |= 0x004000; + if (vmeOut->maxDataWidth == VME_D16) + temp_ctl |= 0x00400000; + if (vmeOut->maxDataWidth == VME_D32) + temp_ctl |= 0x00800000; + if (vmeOut->maxDataWidth == VME_D64) + temp_ctl |= 0x00C00000; + if (vmeOut->xferProtocol & (VME_BLT | VME_MBLT)) + temp_ctl |= 0x00000100; + + // Write ctl reg without enable + writel(temp_ctl, vmechip_baseaddr + outCTL[vmeOut->windowNbr]); + + if (vmeOut->windowEnable) + temp_ctl |= 0x80000000; + + writel(temp_ctl, vmechip_baseaddr + outCTL[vmeOut->windowNbr]); + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_get_out_bound +// Description: +//----------------------------------------------------------------------------- +int uni_get_out_bound(vmeOutWindowCfg_t * vmeOut) +{ + int temp_ctl = 0; + + // Verify input data + if (vmeOut->windowNbr > 7) { + return (-EINVAL); + } + // Get Window mappings. + vmeOut->pciBusAddrL = + readl(vmechip_baseaddr + outBS[vmeOut->windowNbr]); + vmeOut->xlatedAddrL = + vmeOut->pciBusAddrL + readl(vmechip_baseaddr + + outTO[vmeOut->windowNbr]); + vmeOut->windowSizeL = + readl(vmechip_baseaddr + outBD[vmeOut->windowNbr]) - + vmeOut->pciBusAddrL; + + temp_ctl = readl(vmechip_baseaddr + outCTL[vmeOut->windowNbr]); + + // Get Control & BUS attributes + if (temp_ctl & 0x40000000) + vmeOut->wrPostEnable = 1; + if (temp_ctl & 0x001000) + vmeOut->userAccessType = VME_SUPER; + else + vmeOut->userAccessType = VME_USER; + if (temp_ctl & 0x004000) + vmeOut->dataAccessType = VME_PROG; + else + vmeOut->dataAccessType = VME_DATA; + if (temp_ctl & 0x80000000) + vmeOut->windowEnable = 1; + + switch ((temp_ctl & 0x00C00000) >> 22) { + case 0: + vmeOut->maxDataWidth = VME_D8; + break; + case 1: + vmeOut->maxDataWidth = VME_D16; + break; + case 2: + vmeOut->maxDataWidth = VME_D32; + break; + case 3: + vmeOut->maxDataWidth = VME_D64; + break; + } + if (temp_ctl & 0x00000100) + vmeOut->xferProtocol = VME_BLT; + else + vmeOut->xferProtocol = VME_SCT; + + switch ((temp_ctl & 0x70000) >> 16) { + case 0x0: + vmeOut->addrSpace = VME_A16; + break; + case 0x1: + vmeOut->addrSpace = VME_A24; + break; + case 0x2: + vmeOut->addrSpace = VME_A32; + break; + case 0x5: + vmeOut->addrSpace = VME_CRCSR; + break; + case 0x6: + vmeOut->addrSpace = VME_USER1; + break; + case 0x7: + vmeOut->addrSpace = VME_USER2; + break; + } + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_setup_lm +// Description: +//----------------------------------------------------------------------------- +int uni_setup_lm(vmeLmCfg_t * vmeLm) +{ + int temp_ctl = 0; + + if (vmeLm->addrU) { + return (-EINVAL); + } + switch (vmeLm->addrSpace) { + case VME_A64: + case VME_USER3: + case VME_USER4: + return (-EINVAL); + case VME_A16: + temp_ctl |= 0x00000; + break; + case VME_A24: + temp_ctl |= 0x10000; + break; + case VME_A32: + temp_ctl |= 0x20000; + break; + case VME_CRCSR: + temp_ctl |= 0x50000; + break; + case VME_USER1: + temp_ctl |= 0x60000; + break; + case VME_USER2: + temp_ctl |= 0x70000; + break; + } + + // Disable while we are mucking around + writel(0x00000000, vmechip_baseaddr + LM_CTL); + + writel(vmeLm->addr, vmechip_baseaddr + LM_BS); + + // Setup CTL register. + if (vmeLm->userAccessType & VME_SUPER) + temp_ctl |= 0x00200000; + if (vmeLm->userAccessType & VME_USER) + temp_ctl |= 0x00100000; + if (vmeLm->dataAccessType & VME_PROG) + temp_ctl |= 0x00800000; + if (vmeLm->dataAccessType & VME_DATA) + temp_ctl |= 0x00400000; + + uni_lm_event = 0; + + // Write ctl reg and enable + writel(0x80000000 | temp_ctl, vmechip_baseaddr + LM_CTL); + temp_ctl = readl(vmechip_baseaddr + LM_CTL); + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_wait_lm +// Description: +//----------------------------------------------------------------------------- +int uni_wait_lm(vmeLmCfg_t * vmeLm) +{ + unsigned long flags; + unsigned int tmp; + + spin_lock_irqsave(&lm_lock, flags); + tmp = uni_lm_event; + spin_unlock_irqrestore(&lm_lock, flags); + if (tmp == 0) { + if (vmeLm->lmWait < 10) + vmeLm->lmWait = 10; + interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait); + } + writel(0x00000000, vmechip_baseaddr + LM_CTL); + vmeLm->lmEvents = uni_lm_event; + + return (0); +} + +#define SWIZZLE(X) ( ((X & 0xFF000000) >> 24) | ((X & 0x00FF0000) >> 8) | ((X & 0x0000FF00) << 8) | ((X & 0x000000FF) << 24)) + +//----------------------------------------------------------------------------- +// Function : uni_do_rmw +// Description: +//----------------------------------------------------------------------------- +int uni_do_rmw(vmeRmwCfg_t * vmeRmw) +{ + int temp_ctl = 0; + int tempBS = 0; + int tempBD = 0; + int tempTO = 0; + int vmeBS = 0; + int vmeBD = 0; + int *rmw_pci_data_ptr = NULL; + int *vaDataPtr = NULL; + int i; + vmeOutWindowCfg_t vmeOut; + if (vmeRmw->maxAttempts < 1) { + return (-EINVAL); + } + if (vmeRmw->targetAddrU) { + return (-EINVAL); + } + // Find the PCI address that maps to the desired VME address + for (i = 0; i < 8; i++) { + temp_ctl = readl(vmechip_baseaddr + outCTL[i]); + if ((temp_ctl & 0x80000000) == 0) { + continue; + } + memset(&vmeOut, 0, sizeof(vmeOut)); + vmeOut.windowNbr = i; + uni_get_out_bound(&vmeOut); + if (vmeOut.addrSpace != vmeRmw->addrSpace) { + continue; + } + tempBS = readl(vmechip_baseaddr + outBS[i]); + tempBD = readl(vmechip_baseaddr + outBD[i]); + tempTO = readl(vmechip_baseaddr + outTO[i]); + vmeBS = tempBS + tempTO; + vmeBD = tempBD + tempTO; + if ((vmeRmw->targetAddr >= vmeBS) && + (vmeRmw->targetAddr < vmeBD)) { + rmw_pci_data_ptr = + (int *)(tempBS + (vmeRmw->targetAddr - vmeBS)); + vaDataPtr = + (int *)(out_image_va[i] + + (vmeRmw->targetAddr - vmeBS)); + break; + } + } + + // If no window - fail. + if (rmw_pci_data_ptr == NULL) { + return (-EINVAL); + } + // Setup the RMW registers. + writel(0, vmechip_baseaddr + SCYC_CTL); + writel(SWIZZLE(vmeRmw->enableMask), vmechip_baseaddr + SCYC_EN); + writel(SWIZZLE(vmeRmw->compareData), vmechip_baseaddr + SCYC_CMP); + writel(SWIZZLE(vmeRmw->swapData), vmechip_baseaddr + SCYC_SWP); + writel((int)rmw_pci_data_ptr, vmechip_baseaddr + SCYC_ADDR); + writel(1, vmechip_baseaddr + SCYC_CTL); + + // Run the RMW cycle until either success or max attempts. + vmeRmw->numAttempts = 1; + while (vmeRmw->numAttempts <= vmeRmw->maxAttempts) { + + if ((readl(vaDataPtr) & vmeRmw->enableMask) == + (vmeRmw->swapData & vmeRmw->enableMask)) { + + writel(0, vmechip_baseaddr + SCYC_CTL); + break; + + } + vmeRmw->numAttempts++; + } + + // If no success, set num Attempts to be greater than max attempts + if (vmeRmw->numAttempts > vmeRmw->maxAttempts) { + vmeRmw->numAttempts = vmeRmw->maxAttempts + 1; + } + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uniSetupDctlReg +// Description: +//----------------------------------------------------------------------------- +int uniSetupDctlReg(vmeDmaPacket_t * vmeDma, int *dctlregreturn) +{ + unsigned int dctlreg = 0x80; + struct vmeAttr *vmeAttr; + + if (vmeDma->srcBus == VME_DMA_VME) { + dctlreg = 0; + vmeAttr = &vmeDma->srcVmeAttr; + } else { + dctlreg = 0x80000000; + vmeAttr = &vmeDma->dstVmeAttr; + } + + switch (vmeAttr->maxDataWidth) { + case VME_D8: + break; + case VME_D16: + dctlreg |= 0x00400000; + break; + case VME_D32: + dctlreg |= 0x00800000; + break; + case VME_D64: + dctlreg |= 0x00C00000; + break; + } + + switch (vmeAttr->addrSpace) { + case VME_A16: + break; + case VME_A24: + dctlreg |= 0x00010000; + break; + case VME_A32: + dctlreg |= 0x00020000; + break; + case VME_USER1: + dctlreg |= 0x00060000; + break; + case VME_USER2: + dctlreg |= 0x00070000; + break; + + case VME_A64: // not supported in Universe DMA + case VME_CRCSR: + case VME_USER3: + case VME_USER4: + return (-EINVAL); + break; + } + if (vmeAttr->userAccessType == VME_PROG) { + dctlreg |= 0x00004000; + } + if (vmeAttr->dataAccessType == VME_SUPER) { + dctlreg |= 0x00001000; + } + if (vmeAttr->xferProtocol != VME_SCT) { + dctlreg |= 0x00000100; + } + *dctlregreturn = dctlreg; + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_start_dma +// Description: +//----------------------------------------------------------------------------- +unsigned int +uni_start_dma(int channel, unsigned int dgcsreg, TDMA_Cmd_Packet * vmeLL) +{ + unsigned int val; + + // Setup registers as needed for direct or chained. + if (dgcsreg & 0x8000000) { + writel(0, vmechip_baseaddr + DTBC); + writel((unsigned int)vmeLL, vmechip_baseaddr + DCPP); + } else { +#if 0 + printk("Starting: DGCS = %08x\n", dgcsreg); + printk("Starting: DVA = %08x\n", readl(&vmeLL->dva)); + printk("Starting: DLV = %08x\n", readl(&vmeLL->dlv)); + printk("Starting: DTBC = %08x\n", readl(&vmeLL->dtbc)); + printk("Starting: DCTL = %08x\n", readl(&vmeLL->dctl)); +#endif + // Write registers + writel(readl(&vmeLL->dva), vmechip_baseaddr + DVA); + writel(readl(&vmeLL->dlv), vmechip_baseaddr + DLA); + writel(readl(&vmeLL->dtbc), vmechip_baseaddr + DTBC); + writel(readl(&vmeLL->dctl), vmechip_baseaddr + DCTL); + writel(0, vmechip_baseaddr + DCPP); + } + vme_sync_data(); + + // Start the operation + writel(dgcsreg, vmechip_baseaddr + DGCS); + vme_sync_data(); + val = get_tbl(); + writel(dgcsreg | 0x8000000F, vmechip_baseaddr + DGCS); + vme_sync_data(); + return (val); +} + +//----------------------------------------------------------------------------- +// Function : uni_setup_dma +// Description: +//----------------------------------------------------------------------------- +TDMA_Cmd_Packet *uni_setup_dma(vmeDmaPacket_t * vmeDma) +{ + vmeDmaPacket_t *vmeCur; + int maxPerPage; + int currentLLcount; + TDMA_Cmd_Packet *startLL; + TDMA_Cmd_Packet *currentLL; + TDMA_Cmd_Packet *nextLL; + unsigned int dctlreg = 0; + + maxPerPage = PAGESIZE / sizeof(TDMA_Cmd_Packet) - 1; + startLL = (TDMA_Cmd_Packet *) __get_free_pages(GFP_KERNEL, 0); + if (startLL == 0) { + return (startLL); + } + // First allocate pages for descriptors and create linked list + vmeCur = vmeDma; + currentLL = startLL; + currentLLcount = 0; + while (vmeCur != 0) { + if (vmeCur->pNextPacket != 0) { + currentLL->dcpp = (unsigned int)(currentLL + 1); + currentLLcount++; + if (currentLLcount >= maxPerPage) { + currentLL->dcpp = + __get_free_pages(GFP_KERNEL, 0); + currentLLcount = 0; + } + currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp; + } else { + currentLL->dcpp = (unsigned int)0; + } + vmeCur = vmeCur->pNextPacket; + } + + // Next fill in information for each descriptor + vmeCur = vmeDma; + currentLL = startLL; + while (vmeCur != 0) { + if (vmeCur->srcBus == VME_DMA_VME) { + writel(vmeCur->srcAddr, ¤tLL->dva); + writel(vmeCur->dstAddr, ¤tLL->dlv); + } else { + writel(vmeCur->srcAddr, ¤tLL->dlv); + writel(vmeCur->dstAddr, ¤tLL->dva); + } + uniSetupDctlReg(vmeCur, &dctlreg); + writel(dctlreg, ¤tLL->dctl); + writel(vmeCur->byteCount, ¤tLL->dtbc); + + currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp; + vmeCur = vmeCur->pNextPacket; + } + + // Convert Links to PCI addresses. + currentLL = startLL; + while (currentLL != 0) { + nextLL = (TDMA_Cmd_Packet *) currentLL->dcpp; + if (nextLL == 0) { + writel(1, ¤tLL->dcpp); + } else { + writel((unsigned int)virt_to_bus(nextLL), + ¤tLL->dcpp); + } + vme_flush_line(currentLL); + currentLL = nextLL; + } + + // Return pointer to descriptors list + return (startLL); +} + +//----------------------------------------------------------------------------- +// Function : uni_free_dma +// Description: +//----------------------------------------------------------------------------- +int uni_free_dma(TDMA_Cmd_Packet * startLL) +{ + TDMA_Cmd_Packet *currentLL; + TDMA_Cmd_Packet *prevLL; + TDMA_Cmd_Packet *nextLL; + unsigned int dcppreg; + + // Convert Links to virtual addresses. + currentLL = startLL; + while (currentLL != 0) { + dcppreg = readl(¤tLL->dcpp); + dcppreg &= ~6; + if (dcppreg & 1) { + currentLL->dcpp = 0; + } else { + currentLL->dcpp = (unsigned int)bus_to_virt(dcppreg); + } + currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp; + } + + // Free all pages associated with the descriptors. + currentLL = startLL; + prevLL = currentLL; + while (currentLL != 0) { + nextLL = (TDMA_Cmd_Packet *) currentLL->dcpp; + if (currentLL + 1 != nextLL) { + free_pages((int)prevLL, 0); + prevLL = nextLL; + } + currentLL = nextLL; + } + + // Return pointer to descriptors list + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_do_dma +// Description: +//----------------------------------------------------------------------------- +int uni_do_dma(vmeDmaPacket_t * vmeDma) +{ + unsigned int dgcsreg = 0; + unsigned int dctlreg = 0; + int val; + int channel, x; + vmeDmaPacket_t *curDma; + TDMA_Cmd_Packet *dmaLL; + + // Sanity check the VME chain. + channel = vmeDma->channel_number; + if (channel > 0) { + return (-EINVAL); + } + curDma = vmeDma; + while (curDma != 0) { + if (curDma->byteCount == 0) { + return (-EINVAL); + } + if (curDma->byteCount >= 0x1000000) { + return (-EINVAL); + } + if ((curDma->srcAddr & 7) != (curDma->dstAddr & 7)) { + return (-EINVAL); + } + switch (curDma->srcBus) { + case VME_DMA_PCI: + if (curDma->dstBus != VME_DMA_VME) { + return (-EINVAL); + } + break; + case VME_DMA_VME: + if (curDma->dstBus != VME_DMA_PCI) { + return (-EINVAL); + } + break; + default: + return (-EINVAL); + break; + } + if (uniSetupDctlReg(curDma, &dctlreg) < 0) { + return (-EINVAL); + } + + curDma = curDma->pNextPacket; + if (curDma == vmeDma) { // Endless Loop! + return (-EINVAL); + } + } + + // calculate control register + if (vmeDma->pNextPacket != 0) { + dgcsreg = 0x8000000; + } else { + dgcsreg = 0; + } + + for (x = 0; x < 8; x++) { // vme block size + if ((256 << x) >= vmeDma->maxVmeBlockSize) { + break; + } + } + if (x == 8) + x = 7; + dgcsreg |= (x << 20); + + if (vmeDma->vmeBackOffTimer) { + for (x = 1; x < 8; x++) { // vme timer + if ((16 << (x - 1)) >= vmeDma->vmeBackOffTimer) { + break; + } + } + if (x == 8) + x = 7; + dgcsreg |= (x << 16); + } + // Setup the dma chain + dmaLL = uni_setup_dma(vmeDma); + + // Start the DMA + if (dgcsreg & 0x8000000) { + vmeDma->vmeDmaStartTick = + uni_start_dma(channel, dgcsreg, + (TDMA_Cmd_Packet *) virt_to_phys(dmaLL)); + } else { + vmeDma->vmeDmaStartTick = + uni_start_dma(channel, dgcsreg, dmaLL); + } + + wait_event_interruptible(dma_queue[0], + readl(vmechip_baseaddr + DGCS) & 0x800); + + val = readl(vmechip_baseaddr + DGCS); + writel(val | 0xF00, vmechip_baseaddr + DGCS); + + vmeDma->vmeDmaStatus = 0; + vmeDma->vmeDmaStopTick = uni_dma_irq_time; + if (vmeDma->vmeDmaStopTick < vmeDma->vmeDmaStartTick) { + vmeDma->vmeDmaElapsedTime = + (0xFFFFFFFF - vmeDma->vmeDmaStartTick) + + vmeDma->vmeDmaStopTick; + } else { + vmeDma->vmeDmaElapsedTime = + vmeDma->vmeDmaStopTick - vmeDma->vmeDmaStartTick; + } + vmeDma->vmeDmaElapsedTime -= vmechip_irq_overhead_ticks; + vmeDma->vmeDmaElapsedTime /= (tb_speed / 1000000); + + if (!(val & 0x00000800)) { + vmeDma->vmeDmaStatus = val & 0x700; + printk(KERN_ERR + "ca91c042: DMA Error in DMA_uni_irqhandler DGCS=%08X\n", + val); + val = readl(vmechip_baseaddr + DCPP); + printk(KERN_ERR "ca91c042: DCPP=%08X\n", val); + val = readl(vmechip_baseaddr + DCTL); + printk(KERN_ERR "ca91c042: DCTL=%08X\n", val); + val = readl(vmechip_baseaddr + DTBC); + printk(KERN_ERR "ca91c042: DTBC=%08X\n", val); + val = readl(vmechip_baseaddr + DLA); + printk(KERN_ERR "ca91c042: DLA=%08X\n", val); + val = readl(vmechip_baseaddr + DVA); + printk(KERN_ERR "ca91c042: DVA=%08X\n", val); + + } + // Free the dma chain + uni_free_dma(dmaLL); + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : uni_shutdown +// Description: Put VME bridge in quiescent state. +//----------------------------------------------------------------------------- +void uni_shutdown(void) +{ + writel(0, vmechip_baseaddr + LINT_EN); // Turn off Ints + + // Turn off the windows + writel(0x00800000, vmechip_baseaddr + LSI0_CTL); + writel(0x00800000, vmechip_baseaddr + LSI1_CTL); + writel(0x00800000, vmechip_baseaddr + LSI2_CTL); + writel(0x00800000, vmechip_baseaddr + LSI3_CTL); + writel(0x00F00000, vmechip_baseaddr + VSI0_CTL); + writel(0x00F00000, vmechip_baseaddr + VSI1_CTL); + writel(0x00F00000, vmechip_baseaddr + VSI2_CTL); + writel(0x00F00000, vmechip_baseaddr + VSI3_CTL); + if (vmechip_revision >= 2) { + writel(0x00800000, vmechip_baseaddr + LSI4_CTL); + writel(0x00800000, vmechip_baseaddr + LSI5_CTL); + writel(0x00800000, vmechip_baseaddr + LSI6_CTL); + writel(0x00800000, vmechip_baseaddr + LSI7_CTL); + writel(0x00F00000, vmechip_baseaddr + VSI4_CTL); + writel(0x00F00000, vmechip_baseaddr + VSI5_CTL); + writel(0x00F00000, vmechip_baseaddr + VSI6_CTL); + writel(0x00F00000, vmechip_baseaddr + VSI7_CTL); + } +} + +//----------------------------------------------------------------------------- +// Function : uni_init() +// Description: +//----------------------------------------------------------------------------- +int uni_init(void) +{ + int result; + unsigned int tmp; + unsigned int crcsr_addr; + unsigned int irqOverHeadStart; + int overHeadTicks; + + uni_shutdown(); + + // Write to Misc Register + // Set VME Bus Time-out + // Arbitration Mode + // DTACK Enable + tmp = readl(vmechip_baseaddr + MISC_CTL) & 0x0832BFFF; + tmp |= 0x76040000; + writel(tmp, vmechip_baseaddr + MISC_CTL); + if (tmp & 0x20000) { + vme_syscon = 1; + } else { + vme_syscon = 0; + } + + // Clear DMA status log + writel(0x00000F00, vmechip_baseaddr + DGCS); + // Clear and enable error log + writel(0x00800000, vmechip_baseaddr + L_CMDERR); + // Turn off location monitor + writel(0x00000000, vmechip_baseaddr + LM_CTL); + + // Initialize crcsr map + if (vme_slotnum != -1) { + writel(vme_slotnum << 27, vmechip_baseaddr + VCSR_BS); + } + crcsr_addr = readl(vmechip_baseaddr + VCSR_BS) >> 8; + writel((unsigned int)vmechip_interboard_datap - crcsr_addr, + vmechip_baseaddr + VCSR_TO); + if (vme_slotnum != -1) { + writel(0x80000000, vmechip_baseaddr + VCSR_CTL); + } + // Turn off interrupts + writel(0x00000000, vmechip_baseaddr + LINT_EN); // Disable interrupts in the Universe first + writel(0x00FFFFFF, vmechip_baseaddr + LINT_STAT); // Clear Any Pending Interrupts + writel(0x00000000, vmechip_baseaddr + VINT_EN); // Disable interrupts in the Universe first + + result = + request_irq(vmechip_irq, uni_irqhandler, SA_INTERRUPT | SA_SHIRQ, + "VMEBus (ca91c042)", vmechip_baseaddr); + if (result) { + printk(KERN_ERR + "ca91c042: can't get assigned pci irq vector %02X\n", + vmechip_irq); + return (0); + } else { + writel(0x0000, vmechip_baseaddr + LINT_MAP0); // Map all ints to 0 + writel(0x0000, vmechip_baseaddr + LINT_MAP1); // Map all ints to 0 + writel(0x0000, vmechip_baseaddr + LINT_MAP2); // Map all ints to 0 + } + + // Enable DMA, mailbox, VIRQ & LM Interrupts + if (vme_syscon) + tmp = 0x00FF07FE; + else + tmp = 0x00FF0700; + writel(tmp, vmechip_baseaddr + LINT_EN); + + // Do a quick sanity test of the bridge + if (readl(vmechip_baseaddr + LINT_EN) != tmp) { + return (0); + } + if (readl(vmechip_baseaddr + PCI_CLASS_REVISION) != 0x06800002) { + return (0); + } + for (tmp = 1; tmp < 0x80000000; tmp = tmp << 1) { + writel(tmp, vmechip_baseaddr + SCYC_EN); + writel(~tmp, vmechip_baseaddr + SCYC_CMP); + if (readl(vmechip_baseaddr + SCYC_EN) != tmp) { + return (0); + } + if (readl(vmechip_baseaddr + SCYC_CMP) != ~tmp) { + return (0); + } + } + + // do a mail box interrupt to calibrate the interrupt overhead. + + irqOverHeadStart = get_tbl(); + writel(0, vmechip_baseaddr + MBOX1); + for (tmp = 0; tmp < 10; tmp++) { + vme_sync_data(); + } + + irqOverHeadStart = get_tbl(); + writel(0, vmechip_baseaddr + MBOX1); + for (tmp = 0; tmp < 10; tmp++) { + vme_sync_data(); + } + + overHeadTicks = uni_irq_time - irqOverHeadStart; + if (overHeadTicks > 0) { + vmechip_irq_overhead_ticks = overHeadTicks; + } else { + vmechip_irq_overhead_ticks = 1; + } + return (1); +} diff -u --new-file --recursive linux-2.6.14.orig/drivers/vme/ca91c042.h linux-2.6.14.mod/drivers/vme/ca91c042.h --- linux-2.6.14.orig/drivers/vme/ca91c042.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/vme/ca91c042.h 2006-04-20 15:42:11.000000000 -0700 @@ -0,0 +1,391 @@ +/* + * ca91c042.h + * + * Support for the Tundra Universe 1 and Universe II VME bridge chips + * + * Author: Tom Armistead + * Updated and maintained by Ajit Prem + * Copyright 2004 Motorola Inc. + * + * Derived from ca91c042.h by Michael Wyrick + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef _ca91c042_h +#define _ca91c042_h + +//----------------------------------------------------------------------------- +// Public Functions +//----------------------------------------------------------------------------- +// This is the typedef for a VmeIrqHandler +typedef void (*TirqHandler) (int vmeirq, int vector, void *dev_id, + struct pt_regs * regs); +// This is the typedef for a DMA Transfer Callback function +typedef void (*TDMAcallback) (int status); + +// Returns the PCI baseaddress of the Universe chip +char *Universe_BaseAddr(void); +// Returns the PCI IRQ That the universe is using +int Universe_IRQ(void); + +char *mapvme(unsigned int pci, unsigned int vme, unsigned int size, + int image, int ctl); +void unmapvme(char *ptr, int image); + +// Interrupt Stuff +void enable_vmeirq(unsigned int irq); +void disable_vmeirq(unsigned int irq); +int request_vmeirq(unsigned int irq, TirqHandler); +void free_vmeirq(unsigned int irq); + +// DMA Stuff + +int VME_Bus_Error(void); +int uni_procinfo(char *); + +#define IRQ_VOWN 0x0001 +#define IRQ_VIRQ1 0x0002 +#define IRQ_VIRQ2 0x0004 +#define IRQ_VIRQ3 0x0008 +#define IRQ_VIRQ4 0x0010 +#define IRQ_VIRQ5 0x0020 +#define IRQ_VIRQ6 0x0040 +#define IRQ_VIRQ7 0x0080 +#define IRQ_DMA 0x0100 +#define IRQ_LERR 0x0200 +#define IRQ_VERR 0x0400 +#define IRQ_res 0x0800 +#define IRQ_IACK 0x1000 +#define IRQ_SWINT 0x2000 +#define IRQ_SYSFAIL 0x4000 +#define IRQ_ACFAIL 0x8000 + +// See Page 2-77 in the Universe User Manual +typedef struct { + unsigned int dctl; // DMA Control + unsigned int dtbc; // Transfer Byte Count + unsigned int dlv; // PCI Address + unsigned int res1; // Reserved + unsigned int dva; // Vme Address + unsigned int res2; // Reserved + unsigned int dcpp; // Pointer to Numed Cmd Packet with rPN + unsigned int res3; // Reserved +} TDMA_Cmd_Packet; + +/* + * Below here is normaly not used by a user module + */ +#define DMATIMEOUT 2*HZ; + +#define CONFIG_REG_SPACE 0xA0000000 + +/* Universe Register Offsets */ +/* general PCI configuration registers */ +#define UNIV_PCI_ID 0x000 +#define UNIV_PCI_CSR 0x004 +#define UNIV_PCI_CLASS 0x008 +#define UNIV_BM_PCI_CLASS_BASE 0xFF000000 +#define UNIV_OF_PCI_CLASS_BASE 24 +#define UNIV_BM_PCI_CLASS_SUB 0x00FF0000 +#define UNIV_OF_PCI_CLASS_SUB 16 +#define UNIV_BM_PCI_CLASS_PROG 0x0000FF00 +#define UNIV_OF_PCI_CLASS_PROG 8 +#define UNIV_BM_PCI_CLASS_RID 0x000000FF +#define UNIV_OF_PCI_CLASS_RID 0 + +#define UNIV_OF_PCI_CLASS_RID_UNIVERSE_I 0 +#define UNIV_OF_PCI_CLASS_RID_UNIVERSE_II 1 + +#define UNIV_PCI_MISC0 0x00C +#define UNIV_BM_PCI_MISC0_BISTC 0x80000000 +#define UNIV_BM_PCI_MISC0_SBIST 0x60000000 +#define UNIV_BM_PCI_MISC0_CCODE 0x0F000000 +#define UNIV_BM_PCI_MISC0_MFUNCT 0x00800000 +#define UNIV_BM_PCI_MISC0_LAYOUT 0x007F0000 +#define UNIV_BM_PCI_MISC0_LTIMER 0x0000FF00 +#define UNIV_OF_PCI_MISC0_LTIMER 8 +#define UNIV_PCI_BS 0x010 +#define UNIV_PCI_MISC1 0x03C + +#define UNIV_BM_LSI_CTL_EN 0x80000000 +#define UNIV_BM_LSI_CTL_PWEN 0x40000000 +#define UNIV_BM_LSI_CTL_VDW 0x00C00000 +#define UNIV_OF_LSI_CTL_VDW 22 +#define UNIV_BM_LSI_CTL_VAS 0x00070000 +#define UNIV_OF_LSI_CTL_VAS 16 +#define UNIV_BM_LSI_CTL_PGM 0x0000C000 +#define UNIV_OF_LSI_CTL_PGM 14 +#define UNIV_BM_LSI_CTL_SUPER 0x00003000 +#define UNIV_OF_LSI_CTL_SUPER 12 +#define UNIV_BM_LSI_CTL_VCT 0x00000100 +#define UNIV_BM_LSI_CTL_LAS 0x00000003 +#define UNIV_OF_LSI_CTL_LAS 0 +#define UNIV_BM_LSI_CTL_RESERVED (~ (UNIV_BM_LSI_CTL_EN | UNIV_BM_LSI_CTL_PWEN | UNIV_BM_LSI_CTL_VDW | UNIV_BM_LSI_CTL_VAS | UNIV_BM_LSI_CTL_PGM | UNIV_BM_LSI_CTL_SUPER | UNIV_BM_LSI_CTL_VCT | UNIV_BM_LSI_CTL_LAS)) + +#define PCI_SIZE_8 0x0001 +#define PCI_SIZE_16 0x0002 +#define PCI_SIZE_32 0x0003 + +#define IOCTL_SET_CTL 0xF001 +#define IOCTL_SET_BS 0xF002 +#define IOCTL_SET_BD 0xF003 +#define IOCTL_SET_TO 0xF004 +#define IOCTL_PCI_SIZE 0xF005 +#define IOCTL_SET_MODE 0xF006 +#define IOCTL_SET_WINT 0xF007 // Wait for interrupt before read + +#define LSI0_CTL 0x0100 +#define LSI0_BS 0x0104 +#define LSI0_BD 0x0108 +#define LSI0_TO 0x010C + +#define LSI1_CTL 0x0114 +#define LSI1_BS 0x0118 +#define LSI1_BD 0x011C +#define LSI1_TO 0x0120 + +#define LSI2_CTL 0x0128 +#define LSI2_BS 0x012C +#define LSI2_BD 0x0130 +#define LSI2_TO 0x0134 + +#define LSI3_CTL 0x013C +#define LSI3_BS 0x0140 +#define LSI3_BD 0x0144 +#define LSI3_TO 0x0148 + +#define LSI4_CTL 0x01A0 +#define LSI4_BS 0x01A4 +#define LSI4_BD 0x01A8 +#define LSI4_TO 0x01AC + +#define LSI5_CTL 0x01B4 +#define LSI5_BS 0x01B8 +#define LSI5_BD 0x01BC +#define LSI5_TO 0x01C0 + +#define LSI6_CTL 0x01C8 +#define LSI6_BS 0x01CC +#define LSI6_BD 0x01D0 +#define LSI6_TO 0x01D4 + +#define LSI7_CTL 0x01DC +#define LSI7_BS 0x01E0 +#define LSI7_BD 0x01E4 +#define LSI7_TO 0x01E8 + +#define SCYC_CTL 0x0170 +#define SCYC_ADDR 0x0174 +#define SCYC_EN 0x0178 +#define SCYC_CMP 0x017C +#define SCYC_SWP 0x0180 +#define LMISC 0x0184 +#define UNIV_BM_LMISC_CRT 0xF0000000 +#define UNIV_OF_LMISC_CRT 28 +#define UNIV_BM_LMISC_CWT 0x0F000000 +#define UNIV_OF_LMISC_CWT 24 +#define SLSI 0x0188 +#define UNIV_BM_SLSI_EN 0x80000000 +#define UNIV_BM_SLSI_PWEN 0x40000000 +#define UNIV_BM_SLSI_VDW 0x00F00000 +#define UNIV_OF_SLSI_VDW 20 +#define UNIV_BM_SLSI_PGM 0x0000F000 +#define UNIV_OF_SLSI_PGM 12 +#define UNIV_BM_SLSI_SUPER 0x00000F00 +#define UNIV_OF_SLSI_SUPER 8 +#define UNIV_BM_SLSI_BS 0x000000F6 +#define UNIV_OF_SLSI_BS 2 +#define UNIV_BM_SLSI_LAS 0x00000003 +#define UNIV_OF_SLSI_LAS 0 +#define UNIV_BM_SLSI_RESERVED 0x3F0F0000 +#define L_CMDERR 0x018C +#define LAERR 0x0190 + +#define DCTL 0x0200 +#define DTBC 0x0204 +#define DLA 0x0208 +#define DVA 0x0210 +#define DCPP 0x0218 +#define DGCS 0x0220 +#define D_LLUE 0x0224 + +#define LINT_EN 0x0300 +#define UNIV_BM_LINT_ACFAIL 0x00008000 +#define UNIV_BM_LINT_SYSFAIL 0x00004000 +#define UNIV_BM_LINT_SW_INT 0x00002000 +#define UNIV_BM_LINT_SW_IACK 0x00001000 +#define UNIV_BM_LINT_VERR 0x00000400 +#define UNIV_BM_LINT_LERR 0x00000200 +#define UNIV_BM_LINT_DMA 0x00000100 +#define UNIV_BM_LINT_LM 0x00F00000 +#define UNIV_BM_LINT_MBOX 0x000F0000 +#define UNIV_BM_LINT_VIRQ 0x000000FE +#define UNIV_BM_LINT_VIRQ7 0x00000080 +#define UNIV_BM_LINT_VIRQ6 0x00000040 +#define UNIV_BM_LINT_VIRQ5 0x00000020 +#define UNIV_BM_LINT_VIRQ4 0x00000010 +#define UNIV_BM_LINT_VIRQ3 0x00000008 +#define UNIV_BM_LINT_VIRQ2 0x00000004 +#define UNIV_BM_LINT_VIRQ1 0x00000002 +#define UNIV_BM_LINT_VOWN 0x00000001 +#define LINT_STAT 0x0304 +#define LINT_MAP0 0x0308 +#define LINT_MAP1 0x030C +#define VINT_EN 0x0310 +#define VINT_STAT 0x0314 +#define VINT_MAP0 0x0318 +#define VINT_MAP1 0x031C +#define STATID 0x0320 +#define V1_STATID 0x0324 +#define V2_STATID 0x0328 +#define V3_STATID 0x032C +#define V4_STATID 0x0330 +#define V5_STATID 0x0334 +#define V6_STATID 0x0338 +#define V7_STATID 0x033C +#define LINT_MAP2 0x0340 +#define VINT_MAP2 0x0344 + +#define MBOX0 0x0348 +#define MBOX1 0x034C +#define MBOX2 0x0350 +#define MBOX3 0x0354 +#define SEMA0 0x0358 +#define SEMA1 0x035C + +#define MAST_CTL 0x0400 +#define UNIV_BM_MAST_CTL_MAXRTRY 0xF0000000 +#define UNIV_OF_MAST_CTL_MAXRTRY 28 +#define UNIV_BM_MAST_CTL_PWON 0x0F000000 +#define UNIV_OF_MAST_CTL_PWON 24 +#define UNIV_BM_MAST_CTL_VRL 0x00C00000 +#define UNIV_OF_MAST_CTL_VRL 22 +#define UNIV_BM_MAST_CTL_VRM 0x00200000 +#define UNIV_BM_MAST_CTL_VREL 0x00100000 +#define UNIV_BM_MAST_CTL_VOWN 0x00080000 +#define UNIV_BM_MAST_CTL_VOWN_ACK 0x00040000 +#define UNIV_BM_MAST_CTL_PABS 0x00001000 +#define UNIV_BM_MAST_CTL_BUS_NO 0x0000000F +#define UNIV_OF_MAST_CTL_BUS_NO 0 + +#define MISC_CTL 0x0404 +#define UNIV_BM_MISC_CTL_VBTO 0xF0000000 +#define UNIV_OF_MISC_CTL_VBTO 28 +#define UNIV_BM_MISC_CTL_VARB 0x04000000 +#define UNIV_BM_MISC_CTL_VARBTO 0x03000000 +#define UNIV_OF_MISC_CTL_VARBTO 24 +#define UNIV_BM_MISC_CTL_SW_LRST 0x00800000 +#define UNIV_BM_MISC_CTL_SW_SRST 0x00400000 +#define UNIV_BM_MISC_CTL_BI 0x00100000 +#define UNIV_BM_MISC_CTL_ENGBI 0x00080000 +#define UNIV_BM_MISC_CTL_RESCIND 0x00040000 +#define UNIV_BM_MISC_CTL_SYSCON 0x00020000 +#define UNIV_BM_MISC_CTL_V64AUTO 0x00010000 +#define UNIV_BM_MISC_CTL_RESERVED 0x0820FFFF + +#define MISC_STAT 0x0408 +#define UNIV_BM_MISC_STAT_ENDIAN 0x80000000 +#define UNIV_BM_MISC_STAT_LCLSIZE 0x40000000 +#define UNIV_BM_MISC_STAT_DY4AUTO 0x08000000 +#define UNIV_BM_MISC_STAT_MYBBSY 0x00200000 +#define UNIV_BM_MISC_STAT_DY4DONE 0x00080000 +#define UNIV_BM_MISC_STAT_TXFE 0x00040000 +#define UNIV_BM_MISC_STAT_RXFE 0x00020000 +#define UNIV_BM_MISC_STAT_DY4AUTOID 0x0000FF00 +#define UNIV_OF_MISC_STAT_DY4AUTOID 8 + +#define USER_AM 0x040C + +#define VSI0_CTL 0x0F00 +#define VSI0_BS 0x0F04 +#define VSI0_BD 0x0F08 +#define VSI0_TO 0x0F0C + +#define VSI1_CTL 0x0F14 +#define VSI1_BS 0x0F18 +#define VSI1_BD 0x0F1C +#define VSI1_TO 0x0F20 + +#define VSI2_CTL 0x0F28 +#define VSI2_BS 0x0F2C +#define VSI2_BD 0x0F30 +#define VSI2_TO 0x0F34 + +#define VSI3_CTL 0x0F3C +#define VSI3_BS 0x0F40 +#define VSI3_BD 0x0F44 +#define VSI3_TO 0x0F48 + +#define LM_CTL 0x0F64 +#define LM_BS 0x0F68 + +#define VRAI_CTL 0x0F70 +#define UNIV_BM_VRAI_CTL_EN 0x80000000 +#define UNIV_BM_VRAI_CTL_PGM 0x00C00000 +#define UNIV_OF_VRAI_CTL_PGM 22 +#define UNIV_BM_VRAI_CTL_SUPER 0x00300000 +#define UNIV_OF_VRAI_CTL_SUPER 20 +#define UNIV_BM_VRAI_CTL_VAS 0x00030000 +#define UNIV_OF_VRAI_CTL_VAS 16 + +#define VRAI_BS 0x0F74 +#define VCSR_CTL 0x0F80 +#define VCSR_TO 0x0F84 +#define V_AMERR 0x0F88 +#define VAERR 0x0F8C + +#define VSI4_CTL 0x0F90 +#define VSI4_BS 0x0F94 +#define VSI4_BD 0x0F98 +#define VSI4_TO 0x0F9C + +#define VSI5_CTL 0x0FA4 +#define VSI5_BS 0x0FA8 +#define VSI5_BD 0x0FAC +#define VSI5_TO 0x0FB0 + +#define VSI6_CTL 0x0FB8 +#define VSI6_BS 0x0FBC +#define VSI6_BD 0x0FC0 +#define VSI6_TO 0x0FC4 + +#define VSI7_CTL 0x0FCC +#define VSI7_BS 0x0FD0 +#define VSI7_BD 0x0FD4 +#define VSI7_TO 0x0FD8 + +#define VCSR_CLR 0x0FF4 +#define VCSR_SET 0x0FF8 +#define VCSR_BS 0x0FFC + +// DMA General Control/Status Register DGCS (0x220) +// 32-24 || GO | STOPR | HALTR | 0 || CHAIN | 0 | 0 | 0 || +// 23-16 || VON || VOFF || +// 15-08 || ACT | STOP | HALT | 0 || DONE | LERR | VERR | P_ERR || +// 07-00 || 0 | INT_S | INT_H | 0 || I_DNE | I_LER | I_VER | I_PER || + +// VON - Length Per DMA VMEBus Transfer +// 0000 = None +// 0001 = 256 Bytes +// 0010 = 512 +// 0011 = 1024 +// 0100 = 2048 +// 0101 = 4096 +// 0110 = 8192 +// 0111 = 16384 + +// VOFF - wait between DMA tenures +// 0000 = 0 us +// 0001 = 16 +// 0010 = 32 +// 0011 = 64 +// 0100 = 128 +// 0101 = 256 +// 0110 = 512 +// 0111 = 1024 + +#endif /* _ca91c042_h */ diff -u --new-file --recursive linux-2.6.14.orig/drivers/vme/Kconfig linux-2.6.14.mod/drivers/vme/Kconfig --- linux-2.6.14.orig/drivers/vme/Kconfig 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/vme/Kconfig 2006-06-06 14:23:17.000000000 -0700 @@ -0,0 +1,69 @@ +# +# VME bridge device configuration +# + +menu "VME Bridge devices" + depends on (MVME5100 || MVME5500 || MVME6100 || MVME3100) + +config VME_BRIDGE + tristate "VME Bridge Support" + depends on (MVME5100 || MVME5500 || MVME6100 || MVME3100) + help + If you say Y here you get support for the CA91C042 (Universe I/II) + and Tundra TSI148 VME bridge chips. If you have "udev" correctly + configured in your root file system the required device nodes will + get created automatically. Otherwise, create the following character + special files with major number 221 using mknod ("man mknod"). + For details, refer to the VME Driver User's Guide. + + mknod /dev/vme_m0 c 221 0 + mknod /dev/vme_m1 c 221 1 + mknod /dev/vme_m2 c 221 2 + mknod /dev/vme_m3 c 221 3 + mknod /dev/vme_m4 c 221 4 + mknod /dev/vme_m5 c 221 5 + mknod /dev/vme_m6 c 221 6 + mknod /dev/vme_m7 c 221 7 + mknod /dev/vme_s0 c 221 8 + mknod /dev/vme_s1 c 221 9 + mknod /dev/vme_s2 c 221 10 + mknod /dev/vme_s3 c 221 11 + mknod /dev/vme_s4 c 221 12 + mknod /dev/vme_s5 c 221 13 + mknod /dev/vme_s6 c 221 14 + mknod /dev/vme_s7 c 221 15 + mknod /dev/vme_dma0 c 221 16 + mknod /dev/vme_dma1 c 221 17 + mknod /dev/vme_ctl c 221 32 + mknod /dev/vme_regs c 221 33 + mknod /dev/vme_rmw0 c 221 34 + mknod /dev/vme_lm0 c 221 35 + + If unsure, say N. + +config VME_BRIDGE_BOOTMEM + bool "VME Bridge bootmem" + depends on VME_BRIDGE + default n + help + If you say Y here, the VME bridge driver will get memory for + inbound window 7 using the alloc_bootmem* API instead of the + standard DMA API. You want to say Y here if you want + a huge window opened up where you would run into a -ENOMEM error + if you tried to get this memory dynamically. Memory for other + inbound windows will still get dynamically allocated, when + requested, using the DMA API. + +config VME_BRIDGE_BOOTMEM_SIZE + int "VME Bridge bootmem size" + depends on VME_BRIDGE_BOOTMEM + range 8 512 + default "8" + help + The amount of boot memory, in megabytes, to be permanently + allocated for inbound window 7. While this parameter allows + you to ask for upto 512M, the amount of memory that will be + allocated is capped at half the total physical memory or + the maximum that the alloc_bootmem() call makes available. + +endmenu diff -u --new-file --recursive linux-2.6.14.orig/drivers/vme/Makefile linux-2.6.14.mod/drivers/vme/Makefile --- linux-2.6.14.orig/drivers/vme/Makefile 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/vme/Makefile 2005-11-16 10:40:21.000000000 -0700 @@ -0,0 +1,8 @@ +# +# Makefile for the VME bridge device drivers. +# + +vmemod-objs := vmelinux.o vmedrv.o tsi148.o ca91c042.o + +obj-$(CONFIG_VME_BRIDGE) += vmemod.o + diff -u --new-file --recursive linux-2.6.14.orig/drivers/vme/tsi148.c linux-2.6.14.mod/drivers/vme/tsi148.c --- linux-2.6.14.orig/drivers/vme/tsi148.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/vme/tsi148.c 2006-06-26 14:35:06.000000000 -0700 @@ -0,0 +1,1855 @@ +/* + * tsi148.c + * + * Support for the Tundra TSI148 VME Bridge Chip + * + * Author: Tom Armistead + * Updated and maintained by Ajit Prem + * Copyright 2004 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vmedrv.h" +#include "tsi148.h" + +extern struct vmeSharedData *vmechip_interboard_data; +extern dma_addr_t vmechip_interboard_datap; +extern const int vmechip_revision; +extern const int vmechip_devid; +extern const int vmechip_irq; +extern int vmechip_irq_overhead_ticks; +extern char *vmechip_baseaddr; +extern const int vme_slotnum; +extern int vme_syscon; +extern char *in_image_ba[]; +extern int in_image_size[]; +extern int in_image_mapped[]; +extern dma_addr_t in_image_pa[]; +extern unsigned int out_image_va[]; +extern unsigned int vme_irqlog[8][0x100]; +extern struct pci_dev *vme_pci_dev; + +extern wait_queue_head_t dma_queue[]; +extern wait_queue_head_t lm_queue; +extern wait_queue_head_t mbox_queue; + +extern void vme_sync_data(void); +extern void vme_flush_line(void *); +extern void vme_flush_range(void *, void *); +extern int tb_speed; + +unsigned int tempe_irq_time; +unsigned int tempe_dma_irq_time[2]; +unsigned int tempe_lm_event; + +static spinlock_t lm_lock = SPIN_LOCK_UNLOCKED; + +/* + * add64hi - calculate upper 32 bits of 64 bit addition operation. + */ + +static unsigned int +add64hi(unsigned int lo0, unsigned int hi0, unsigned int lo1, unsigned int hi1) +{ + if ((lo1 + lo0) < lo1) { + return (hi0 + hi1 + 1); + } + return (hi0 + hi1); +} + +/* + * sub64hi - calculate upper 32 bits of 64 bit subtraction operation. + */ + +static int +sub64hi(unsigned int lo0, unsigned int hi0, unsigned int lo1, unsigned int hi1) +{ + if (lo0 < lo1) { + return (hi0 - hi1 - 1); + } + return (hi0 - hi1); +} + +/* + * tsi148_procinfo() + */ + +int tsi148_procinfo(char *buf) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + char *p; + unsigned int i; + + p = buf; + + p += sprintf(p, "\n"); + /* Display outbound decoders */ + p += sprintf(p, "Local Control and Status Register Group (LCSR):\n"); + p += sprintf(p, "\nOutbound Translations:\n"); + + p += sprintf(p, + "No. otat otsau:otsal oteau:oteal otofu:otofl\n"); + for (i = 0; i < 8; i += 1) { + p += sprintf(p, "O%d: %08X %08X:%08X %08X:%08X: %08X:%08X\n", + i, + p_tempe->lcsr.outboundTranslation[i].otat, + p_tempe->lcsr.outboundTranslation[i].otsau, + p_tempe->lcsr.outboundTranslation[i].otsal, + p_tempe->lcsr.outboundTranslation[i].oteau, + p_tempe->lcsr.outboundTranslation[i].oteal, + p_tempe->lcsr.outboundTranslation[i].otofu, + p_tempe->lcsr.outboundTranslation[i].otofl); + } + + /* Display inbound decoders */ + p += sprintf(p, "\nInbound Translations:\n"); + p += sprintf(p, + "No. itat itsau:itsal iteau:iteal itofu:itofl\n"); + for (i = 0; i < 8; i += 1) { + p += sprintf(p, "O%d: %08X %08X:%08X %08X:%08X: %08X:%08X\n", + i, + p_tempe->lcsr.inboundTranslation[i].itat, + p_tempe->lcsr.inboundTranslation[i].itsau, + p_tempe->lcsr.inboundTranslation[i].itsal, + p_tempe->lcsr.inboundTranslation[i].iteau, + p_tempe->lcsr.inboundTranslation[i].iteal, + p_tempe->lcsr.inboundTranslation[i].itofu, + p_tempe->lcsr.inboundTranslation[i].itofl); + } + p += sprintf(p, "\nVME Bus Control:\n"); + p += sprintf(p, "\tvmctrl 0x%08x\n", p_tempe->lcsr.vmctrl); + p += sprintf(p, "\tvctrl 0x%08x\n", p_tempe->lcsr.vctrl); + p += sprintf(p, "\tvstat 0x%08x\n", p_tempe->lcsr.vstat); + p += sprintf(p, "PCI Status:\n"); + p += sprintf(p, "\tpstat 0x%08x\n", p_tempe->lcsr.pstat); + p += sprintf(p, "VME Exception Status:\n"); + p += sprintf(p, "\tveau:veal 0x%08x:0x%08x\n", p_tempe->lcsr.veau, + p_tempe->lcsr.veal); + p += sprintf(p, "\tveat 0x%08x\n", p_tempe->lcsr.veat); + p += sprintf(p, "PCI Error Status:\n"); + p += sprintf(p, "\tedpau:edpal 0x%08x:0x%08x\n", p_tempe->lcsr.edpau, + p_tempe->lcsr.edpal); + p += sprintf(p, "\tedpxa 0x%08x\n", p_tempe->lcsr.edpxa); + p += sprintf(p, "\tedpxs 0x%08x\n", p_tempe->lcsr.edpxs); + p += sprintf(p, "\tedpat 0x%08x\n", p_tempe->lcsr.edpat); + p += sprintf(p, "Inbound Translation GCSR:\n"); + p += sprintf(p, "\tgbau:gbal 0x%08x:0x%08x\n", p_tempe->lcsr.gbau, + p_tempe->lcsr.gbal); + p += sprintf(p, "\tgcsrat 0x%08x\n", p_tempe->lcsr.gcsrat); + p += sprintf(p, "Inbound Translation CRG:\n"); + p += sprintf(p, "\tcbau:cbal 0x%08x:0x%08x\n", p_tempe->lcsr.cbau, + p_tempe->lcsr.cbal); + p += sprintf(p, "\tcsrat 0x%08x\n", p_tempe->lcsr.csrat); + p += sprintf(p, "Inbound Translation CR/CSR:\n"); + p += sprintf(p, "\tcrou:crol 0x%08x:0x%08x\n", p_tempe->lcsr.crou, + p_tempe->lcsr.crol); + p += sprintf(p, "\tcrat 0x%08x\n", p_tempe->lcsr.crat); + p += sprintf(p, "Inbound Translation Location Monitor:\n"); + p += sprintf(p, "\tlmbau:lmbal 0x%08x:0x%08x:\n", p_tempe->lcsr.lmbau, + p_tempe->lcsr.lmbal); + p += sprintf(p, "\tlmat 0x%08x\n", p_tempe->lcsr.lmat); + p += sprintf(p, "Interrupt Control:\n"); + p += sprintf(p, "\tvicr 0x%08x\n", p_tempe->lcsr.vicr); + p += sprintf(p, "\tinten 0x%08x\n", p_tempe->lcsr.inten); + p += sprintf(p, "\tinteo 0x%08x\n", p_tempe->lcsr.inteo); + p += sprintf(p, "\tints 0x%08x\n", p_tempe->lcsr.ints); + p += sprintf(p, "\tintc 0x%08x\n", p_tempe->lcsr.intc); + p += sprintf(p, "\tintm1 0x%08x\n", p_tempe->lcsr.intm1); + p += sprintf(p, "\tintm2 0x%08x\n", p_tempe->lcsr.intm2); + + p += sprintf(p, "DMA Control:\n"); + p += sprintf(p, "\tdctl0 0x%08x\n", p_tempe->lcsr.dma[0].dctl); + p += sprintf(p, "\tdctl1 0x%08x\n", p_tempe->lcsr.dma[1].dctl); + + p += sprintf(p, "\nPCFS Register Group:\n"); + p += sprintf(p, "\tpciveni 0x%04x\n", swab16(p_tempe->pcfs.veni)); + p += sprintf(p, "\tpcidevi 0x%04x\n", swab16(p_tempe->pcfs.devi)); + p += sprintf(p, "\tpcicmd 0x%04x\n", swab16(p_tempe->pcfs.cmmd)); + p += sprintf(p, "\tpcistat 0x%04x\n", swab16(p_tempe->pcfs.stat)); + p += sprintf(p, "\tpcirev 0x%02x\n", + (p_tempe->pcfs.reviAndClas >> 24)); + p += sprintf(p, "\tpciclass 0x%06x\n", + ((p_tempe->pcfs.reviAndClas << 24) >> 8) | + swab16((p_tempe->pcfs.reviAndClas << 8) >> 16)); + p += sprintf(p, "\tpciclsz 0x%02x\n", p_tempe->pcfs.clsz); + p += sprintf(p, "\tpcimlat 0x%02x\n", p_tempe->pcfs.mlat); + p += sprintf(p, "\tpcisubv 0x%04x\n", swab16(p_tempe->pcfs.subv)); + p += sprintf(p, "\tpcisubi 0x%04x\n", swab16(p_tempe->pcfs.subi)); + p += sprintf(p, "\tpcixcap 0x%08x\n", p_tempe->pcfs.msiCapID); + p += sprintf(p, "\tpcixstat 0x%08x\n", + swab32(p_tempe->pcfs.msiMsgAddrL)); + + p += sprintf(p, "\nGlobal Control and Status Register Group (GCSR):\n"); + p += sprintf(p, "\tctrl 0x%04x%02x%02x\n", p_tempe->gcsr.ctrl, + p_tempe->gcsr.ga, p_tempe->gcsr.revid); + + p += sprintf(p, "\nCR/CSR Register Group:\n"); + p += sprintf(p, "\tbcr 0x%08x\n", p_tempe->crcsr.csrbcr); + p += sprintf(p, "\tbsr 0x%08x\n", p_tempe->crcsr.csrbsr); + + return p - buf; +} + +/* + * Function : tempe_setup_attribute + * + * Description: helper function for calculating attribute register contents. + * + */ +static int +tempe_setup_attribute(addressMode_t addrSpace, + int userAccessType, + int dataAccessType, + dataWidth_t maxDataWidth, + int xferProtocol, vme2esstRate_t xferRate2esst) +{ + int temp_ctl = 0; + + /* Validate & initialize address space field */ + switch (addrSpace) { + case VME_A16: + temp_ctl |= 0x0; + break; + case VME_A24: + temp_ctl |= 0x1; + break; + case VME_A32: + temp_ctl |= 0x2; + break; + case VME_A64: + temp_ctl |= 0x4; + break; + case VME_CRCSR: + temp_ctl |= 0x5; + break; + case VME_USER1: + temp_ctl |= 0x8; + break; + case VME_USER2: + temp_ctl |= 0x9; + break; + case VME_USER3: + temp_ctl |= 0xA; + break; + case VME_USER4: + temp_ctl |= 0xB; + break; + default: + return (-EINVAL); + } + + /* Setup CTL register */ + if (userAccessType & VME_SUPER) + temp_ctl |= 0x0020; + if (dataAccessType & VME_PROG) + temp_ctl |= 0x0010; + if (maxDataWidth == VME_D16) + temp_ctl |= 0x0000; + if (maxDataWidth == VME_D32) + temp_ctl |= 0x0040; + switch (xferProtocol) { + case VME_SCT: + temp_ctl |= 0x000; + break; + case VME_BLT: + temp_ctl |= 0x100; + break; + case VME_MBLT: + temp_ctl |= 0x200; + break; + case VME_2eVME: + temp_ctl |= 0x300; + break; + case VME_2eSST: + temp_ctl |= 0x400; + break; + case VME_2eSSTB: + temp_ctl |= 0x500; + break; + } + switch (xferRate2esst) { + case VME_SSTNONE: + case VME_SST160: + temp_ctl |= 0x0000; + break; + case VME_SST267: + temp_ctl |= 0x800; + break; + case VME_SST320: + temp_ctl |= 0x1000; + break; + } + + return (temp_ctl); +} + +/* + * tempe_bus_error_chk() + * Return zero if no VME bus error has occured, 1 otherwise. + * Optionally, clear bus error status. + */ + +int tempe_bus_error_chk(int clrflag) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int tmp; + + tmp = p_tempe->lcsr.veat; + if (tmp & 0x80000000) { /* VES is Set */ + if (clrflag) + p_tempe->lcsr.veat = 0x20000000; + return (1); + } + return (0); +} + +/* + * Function: DMA_tempe_irqhandler + * Description: Saves DMA completion timestamp and then wakes up DMA queue + */ + +static void DMA_tempe_irqhandler(int channel_mask) +{ + + if (channel_mask & 1) { + tempe_dma_irq_time[0] = tempe_irq_time; + wake_up(&dma_queue[0]); + } + if (channel_mask & 2) { + tempe_dma_irq_time[1] = tempe_irq_time; + wake_up(&dma_queue[1]); + } +} + +/* + * Function : LERR_tempe_irqhandler + * Description: Display error & status message when LERR (PCI) exception + * interrupt occurs. + * + */ + +static void LERR_tempe_irqhandler(void) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + + printk(KERN_ERR + "tsi148: VME PCI Exception at address: 0x%08x:%08x, attributes: %08x\n", + p_tempe->lcsr.edpau, p_tempe->lcsr.edpal, p_tempe->lcsr.edpat); + printk(KERN_ERR + "tsi148: PCI-X attribute reg: %08x, PCI-X split completion reg: %08x\n", + p_tempe->lcsr.edpxa, p_tempe->lcsr.edpxs); + p_tempe->lcsr.edpat = 0x20000000; + vme_sync_data(); +} + +/* + * Function: VERR_tempe_irqhandler + * Description: Display error & status when VME error interrupt occurs. + * Not normally enabled or used. tempe_bus_error_chk() is used instead. + */ + +static void VERR_tempe_irqhandler(void) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + + printk(KERN_ERR + "tsi148: VME Exception at address: 0x%08x:%08x, attributes: %08x\n", + p_tempe->lcsr.veau, p_tempe->lcsr.veal, p_tempe->lcsr.veat); + p_tempe->lcsr.veat = 0x20000000; + vme_sync_data(); +} + +/* + * Function : MB_tempe_irqhandler + * Description: Wake up mail box queue. + */ + +static void MB_tempe_irqhandler(int mboxMask) +{ + if (vmechip_irq_overhead_ticks != 0) { + wake_up(&mbox_queue); + } +} + +/* + * Function : LM_tempe_irqhandler + * Description: Wake up location monitor queue + */ + +static void LM_tempe_irqhandler(int lm_mask) +{ + tempe_lm_event = lm_mask; + wake_up(&lm_queue); +} + +/* + * Function: VIRQ_tempe_irqhandler + * Description: Record the level & vector from the VME bus interrupt. + */ + +static void VIRQ_tempe_irqhandler(int virq_mask) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int iackvec, i; + + for (i = 7; i > 0; i--) { + if (virq_mask & (1 << i)) { + iackvec = p_tempe->lcsr.viack[(i * 4) + 3]; + vme_irqlog[i][iackvec]++; + } + } +} + +/* + * Function : tempe_irqhandler + * Description: Top level interrupt handler. Clears appropriate interrupt + * status bits and then calls appropriate sub handler(s). + */ + +static irqreturn_t tempe_irqhandler(int irq, void *dev_id, struct pt_regs *regs) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + long stat, enable; + + if (dev_id != p_tempe) + return IRQ_NONE; + + /* Save time that this IRQ occurred at */ + tempe_irq_time = get_tbl(); + + /* Determine which interrupts are unmasked and active */ + enable = p_tempe->lcsr.inteo; + stat = p_tempe->lcsr.ints; + stat = stat & enable; + + /* Clear them */ + p_tempe->lcsr.intc = stat; + vme_sync_data(); + + /* Call subhandlers as appropriate */ + if (stat & 0x03000000) /* DMA irqs */ + DMA_tempe_irqhandler((stat & 0x03000000) >> 24); + if (stat & 0x02000) /* PCI bus error */ + LERR_tempe_irqhandler(); + if (stat & 0x01000) /* VME bus error */ + VERR_tempe_irqhandler(); + if (stat & 0xF0000) /* Mail box irqs */ + MB_tempe_irqhandler((stat & 0xF0000) >> 16); + if (stat & 0xF00000) /* Location monitor irqs */ + LM_tempe_irqhandler((stat & 0xF00000) >> 20); + if (stat & 0x0000FE) /* VME bus irqs */ + VIRQ_tempe_irqhandler(stat & 0x0000FE); + + return IRQ_HANDLED; +} + +/* + * Function : tempe_generate_irq + * Description: Generate a VME bus interrupt at the requested level & vector. + * Wait for system controller to ack the interrupt. + */ +int tempe_generate_irq(virqInfo_t * vmeIrq) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int timeout; + int looptimeout; + unsigned int tmp; + + timeout = vmeIrq->waitTime; + if (timeout == 0) { + timeout += 10; /* Wait at least 10 ticks */ + } + looptimeout = HZ / 20; /* try for 1/20 second */ + + vmeIrq->timeOutFlag = 0; + + /* Validate & setup vector register */ + tmp = p_tempe->lcsr.vicr; + tmp &= ~0xFF; + p_tempe->lcsr.vicr = tmp | vmeIrq->vector; + vme_sync_data(); + + /* Assert VMEbus IRQ */ + p_tempe->lcsr.vicr = tmp | (vmeIrq->level << 8) | vmeIrq->vector; + vme_sync_data(); + + /* Wait for syscon to do iack */ + while (p_tempe->lcsr.vicr & 0x800) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(looptimeout); + timeout = timeout - looptimeout; + if (timeout <= 0) { + vmeIrq->timeOutFlag = 1; + break; + } + } + + return (0); +} + +/* + * Function: tempe_set_arbiter + * Description: Set the VME bus arbiter with the requested attributes + */ + +int tempe_set_arbiter(vmeArbiterCfg_t * vmeArb) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int temp_ctl = 0; + int gto = 0; + + temp_ctl = p_tempe->lcsr.vctrl; + temp_ctl &= 0xFFEFFF00; + + if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) { + gto = 8; + } else if (vmeArb->globalTimeoutTimer > 2048) { + return (-EINVAL); + } else if (vmeArb->globalTimeoutTimer == 0) { + gto = 0; + } else { + gto = 1; + while ((16 * (1 << (gto - 1))) < vmeArb->globalTimeoutTimer) { + gto += 1; + } + } + temp_ctl |= gto; + + if (vmeArb->arbiterMode != VME_PRIORITY_MODE) { + temp_ctl |= 1 << 6; + } + + if (vmeArb->arbiterTimeoutFlag) { + temp_ctl |= 1 << 7; + } + + if (vmeArb->noEarlyReleaseFlag) { + temp_ctl |= 1 << 20; + } + p_tempe->lcsr.vctrl = temp_ctl; + vme_sync_data(); + + return (0); +} + +/* + * Function: tempe_get_arbiter + * Description: Return the attributes of the VME bus arbiter. + */ + +int tempe_get_arbiter(vmeArbiterCfg_t * vmeArb) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int temp_ctl = 0; + int gto = 0; + + temp_ctl = p_tempe->lcsr.vctrl; + + gto = temp_ctl & 0xF; + if (gto != 0) { + vmeArb->globalTimeoutTimer = (16 * (1 << (gto - 1))); + } + + if (temp_ctl & (1 << 6)) { + vmeArb->arbiterMode = VME_R_ROBIN_MODE; + } else { + vmeArb->arbiterMode = VME_PRIORITY_MODE; + } + + if (temp_ctl & (1 << 7)) { + vmeArb->arbiterTimeoutFlag = 1; + } + + if (temp_ctl & (1 << 20)) { + vmeArb->noEarlyReleaseFlag = 1; + } + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : tempe_set_requestor +// Description: Set the VME bus requestor with the requested attributes +//----------------------------------------------------------------------------- +int tempe_set_requestor(vmeRequesterCfg_t * vmeReq) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int temp_ctl = 0; + + temp_ctl = p_tempe->lcsr.vmctrl; + temp_ctl &= 0xFFFF0000; + + if (vmeReq->releaseMode == 1) { + temp_ctl |= (1 << 3); + } + + if (vmeReq->fairMode == 1) { + temp_ctl |= (1 << 2); + } + + temp_ctl |= (vmeReq->timeonTimeoutTimer & 7) << 8; + temp_ctl |= (vmeReq->timeoffTimeoutTimer & 7) << 12; + temp_ctl |= vmeReq->requestLevel; + + p_tempe->lcsr.vmctrl = temp_ctl; + vme_sync_data(); + return (0); +} + +//----------------------------------------------------------------------------- +// Function : tempe_get_requestor +// Description: Return the attributes of the VME bus requestor +//----------------------------------------------------------------------------- +int tempe_get_requestor(vmeRequesterCfg_t * vmeReq) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int temp_ctl = 0; + + temp_ctl = p_tempe->lcsr.vmctrl; + + if (temp_ctl & 0x18) { + vmeReq->releaseMode = 1; + } + + if (temp_ctl & (1 << 2)) { + vmeReq->fairMode = 1; + } + + vmeReq->requestLevel = temp_ctl & 3; + vmeReq->timeonTimeoutTimer = (temp_ctl >> 8) & 7; + vmeReq->timeoffTimeoutTimer = (temp_ctl >> 12) & 7; + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : tempe_set_in_bound +// Description: Initialize an inbound window with the requested attributes. +//----------------------------------------------------------------------------- +int tempe_set_in_bound(vmeInWindowCfg_t * vmeIn) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int temp_ctl = 0; + unsigned int win, x, granularity = 0x10000; + struct page *page, *pend; + + /* Verify input data */ + if (vmeIn->windowNbr > 7) { + return (-EINVAL); + } + win = vmeIn->windowNbr; + + /* Free previous allocation */ +#ifndef CONFIG_VME_BRIDGE_BOOTMEM + if (in_image_ba[win] != NULL) { +#else + if ((win != 7) && (in_image_ba[win] != NULL)) { +#endif + /* Undo marking the pages as reserved */ + pend = virt_to_page(in_image_ba[win] + in_image_size[win] - 1); + for (page = virt_to_page(in_image_ba[win]); page <= pend; page++) + ClearPageReserved(page); + dma_free_coherent(&vme_pci_dev->dev, + in_image_size[win], + in_image_ba[win], + in_image_pa[win]); + in_image_mapped[win] = 0; + } + + if (vmeIn->windowEnable == 0) { + temp_ctl = p_tempe->lcsr.inboundTranslation[win].itat; + temp_ctl &= ~0x80000000; + p_tempe->lcsr.inboundTranslation[win].itat = temp_ctl; + vme_sync_data(); + return 0; + } + + switch (vmeIn->addrSpace) { + case VME_CRCSR: + case VME_USER1: + case VME_USER2: + case VME_USER3: + case VME_USER4: + return (-EINVAL); + case VME_A16: + granularity = 0x10; + temp_ctl |= 0x00; + break; + case VME_A24: + granularity = 0x1000; + temp_ctl |= 0x10; + break; + case VME_A32: + granularity = 0x10000; + temp_ctl |= 0x20; + break; + case VME_A64: + granularity = 0x10000; + temp_ctl |= 0x40; + break; + } + +#ifdef CONFIG_VME_BRIDGE_BOOTMEM + if (win == 7) { + vmeIn->windowSizeL = in_image_size[7]; + vmeIn->windowSizeU = 0; + } +#endif + if ((vmeIn->vmeAddrL & (granularity - 1)) || + (vmeIn->windowSizeL & (granularity - 1))) + return (-EINVAL); + +#ifndef CONFIG_VME_BRIDGE_BOOTMEM + if ((vmeIn->windowSizeL < 0x10) || (vmeIn->windowSizeL > 0x800000)) +#else + if ((win != 7) && + ((vmeIn->windowSizeL < 0x10) || (vmeIn->windowSizeL > 0x800000))) +#endif + return (-EINVAL); + +#ifndef CONFIG_VME_BRIDGE_BOOTMEM + if (vmeIn->windowEnable == 1) { +#else + if ((win != 7) && (vmeIn->windowEnable == 1)) { +#endif + in_image_ba[win] = (char *)dma_alloc_coherent((struct device *) + &vme_pci_dev->dev, + vmeIn->windowSizeL, + (dma_addr_t *)&in_image_pa[win], + GFP_KERNEL); + if (!in_image_ba[win]) { + printk("vmedrv: No memory for inbound window\n"); + return -ENOMEM; + } + in_image_size[win] = vmeIn->windowSizeL; + + /* now mark the pages as reserved; otherwise */ + /* remap_pfn_range doesn't do what we want */ + pend = virt_to_page(in_image_ba[win] + in_image_size[win] - 1); + for (page = virt_to_page(in_image_ba[win]); page <= pend; page++) + SetPageReserved(page); + memset(in_image_ba[win], 0, in_image_size[win]); + vme_flush_range(in_image_ba[win], + in_image_ba[win] + in_image_size[win]); + vmeIn->pciAddrL = (unsigned int)in_image_pa[win]; + vmeIn->pciAddrU = 0; +#ifndef CONFIG_VME_BRIDGE_BOOTMEM + } +#else + } else if (win == 7) { + vmeIn->pciAddrL = (unsigned int)in_image_pa[win]; + vmeIn->pciAddrU = 0; + } +#endif + + // Disable while we are mucking around + p_tempe->lcsr.inboundTranslation[win].itat = 0; + vme_sync_data(); + + p_tempe->lcsr.inboundTranslation[win].itsal = vmeIn->vmeAddrL; + p_tempe->lcsr.inboundTranslation[win].itsau = vmeIn->vmeAddrU; + p_tempe->lcsr.inboundTranslation[win].iteal = + vmeIn->vmeAddrL + vmeIn->windowSizeL - granularity; + + p_tempe->lcsr.inboundTranslation[win].iteau = + add64hi(vmeIn->vmeAddrL, vmeIn->vmeAddrU, + vmeIn->windowSizeL - granularity, vmeIn->windowSizeU); + p_tempe->lcsr.inboundTranslation[win].itofl = + vmeIn->pciAddrL - vmeIn->vmeAddrL; + p_tempe->lcsr.inboundTranslation[win].itofu = + sub64hi(vmeIn->pciAddrL, vmeIn->pciAddrU, vmeIn->vmeAddrL, + vmeIn->vmeAddrU); + + /* Setup CTL register */ + temp_ctl |= (vmeIn->xferProtocol & 0x3E) << 6; + for (x = 0; x < 4; x++) { + if ((64 << x) >= vmeIn->prefetchSize) { + break; + } + } + if (x == 4) + x--; + temp_ctl |= (x << 16); + + if (vmeIn->prefetchThreshold) + + if (vmeIn->prefetchThreshold) + temp_ctl |= 0x40000; + + switch (vmeIn->xferRate2esst) { + case VME_SSTNONE: + break; + case VME_SST160: + temp_ctl |= 0x0400; + break; + case VME_SST267: + temp_ctl |= 0x1400; + break; + case VME_SST320: + temp_ctl |= 0x2400; + break; + } + + if (vmeIn->userAccessType & VME_USER) + temp_ctl |= 0x4; + if (vmeIn->userAccessType & VME_SUPER) + temp_ctl |= 0x8; + if (vmeIn->dataAccessType & VME_DATA) + temp_ctl |= 0x1; + if (vmeIn->dataAccessType & VME_PROG) + temp_ctl |= 0x2; + + /* Write ctl reg without enable */ + p_tempe->lcsr.inboundTranslation[win].itat = temp_ctl; + vme_sync_data(); + + if (vmeIn->windowEnable) + temp_ctl |= 0x80000000; + + p_tempe->lcsr.inboundTranslation[win].itat = temp_ctl; + vme_sync_data(); + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : tempe_get_in_bound +// Description: Return the attributes of an inbound window. +//----------------------------------------------------------------------------- +int tempe_get_in_bound(vmeInWindowCfg_t * vmeIn) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int temp_ctl = 0; + unsigned int i, vme_end_u, vme_end_l; + + /* Verify input data */ + if (vmeIn->windowNbr > 7) { + return (-EINVAL); + } + i = vmeIn->windowNbr; + + temp_ctl = p_tempe->lcsr.inboundTranslation[i].itat; + + // Get Control & BUS attributes + if (temp_ctl & 0x80000000) + vmeIn->windowEnable = 1; + vmeIn->xferProtocol = ((temp_ctl & 0xF80) >> 6) | VME_SCT; + vmeIn->prefetchSize = 64 << ((temp_ctl >> 16) & 3); + vmeIn->wrPostEnable = 1; + vmeIn->prefetchEnable = 1; + if (temp_ctl & 0x40000) + vmeIn->prefetchThreshold = 1; + if (temp_ctl & 0x4) + vmeIn->userAccessType |= VME_USER; + if (temp_ctl & 0x8) + vmeIn->userAccessType |= VME_SUPER; + if (temp_ctl & 0x1) + vmeIn->dataAccessType |= VME_DATA; + if (temp_ctl & 0x2) + vmeIn->dataAccessType |= VME_PROG; + + switch ((temp_ctl & 0x70) >> 4) { + case 0x0: + vmeIn->addrSpace = VME_A16; + break; + case 0x1: + vmeIn->addrSpace = VME_A24; + break; + case 0x2: + vmeIn->addrSpace = VME_A32; + break; + case 0x4: + vmeIn->addrSpace = VME_A64; + break; + } + + switch ((temp_ctl & 0x7000) >> 12) { + case 0x0: + vmeIn->xferRate2esst = VME_SST160; + break; + case 0x1: + vmeIn->xferRate2esst = VME_SST267; + break; + case 0x2: + vmeIn->xferRate2esst = VME_SST320; + break; + } + + // Get VME inbound start & end addresses + vmeIn->vmeAddrL = p_tempe->lcsr.inboundTranslation[i].itsal; + vmeIn->vmeAddrU = p_tempe->lcsr.inboundTranslation[i].itsau; + vme_end_l = p_tempe->lcsr.inboundTranslation[i].iteal; + vme_end_u = p_tempe->lcsr.inboundTranslation[i].iteau; + + // Adjust addresses for window granularity + switch (vmeIn->addrSpace) { + case VME_A16: + vmeIn->vmeAddrU = 0; + vmeIn->vmeAddrL &= 0x0000FFF0; + vme_end_u = 0; + vme_end_l &= 0x0000FFF0; + vme_end_l += 0x10; + break; + case VME_A24: + vmeIn->vmeAddrU = 0; + vmeIn->vmeAddrL &= 0x00FFF000; + vme_end_u = 0; + vme_end_l &= 0x00FFF000; + vme_end_l += 0x1000; + break; + case VME_A32: + vmeIn->vmeAddrU = 0; + vmeIn->vmeAddrL &= 0xFFFF0000; + vme_end_u = 0; + vme_end_l &= 0xFFFF0000; + vme_end_l += 0x10000; + break; + default: + vmeIn->vmeAddrL &= 0xFFFF0000; + vme_end_l &= 0xFFFF0000; + vme_end_l += 0x10000; + break; + } + + /* Calculate size of window */ + vmeIn->windowSizeL = vme_end_l - vmeIn->vmeAddrL; + vmeIn->windowSizeU = sub64hi(vme_end_l, vme_end_u, + vmeIn->vmeAddrL, vmeIn->vmeAddrU); + + /* Calculate corresponding PCI bus address */ + vmeIn->pciAddrL = + vmeIn->vmeAddrL + p_tempe->lcsr.inboundTranslation[i].itofl; + vmeIn->pciAddrU = + add64hi(vmeIn->vmeAddrL, vmeIn->vmeAddrU, + p_tempe->lcsr.inboundTranslation[i].itofl, + p_tempe->lcsr.inboundTranslation[i].itofu); + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : tempe_set_out_bound +// Description: Set the attributes of an outbound window. +//----------------------------------------------------------------------------- +int tempe_set_out_bound(vmeOutWindowCfg_t * vmeOut) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int temp_ctl = 0; + unsigned int i, x; + + /* Verify input data */ + if (vmeOut->windowNbr > 7) { + return (-EINVAL); + } + i = vmeOut->windowNbr; + + if (vmeOut->windowEnable == 0) { + temp_ctl = p_tempe->lcsr.outboundTranslation[i].otat; + temp_ctl &= ~0x80000000; + p_tempe->lcsr.outboundTranslation[i].otat = temp_ctl; + vme_sync_data(); + return 0; + } + + if ((vmeOut->xlatedAddrL & 0xFFFF) || + (vmeOut->windowSizeL & 0xFFFF) || (vmeOut->pciBusAddrL & 0xFFFF)) { + return (-EINVAL); + } + + temp_ctl = tempe_setup_attribute(vmeOut->addrSpace, + vmeOut->userAccessType, + vmeOut->dataAccessType, + vmeOut->maxDataWidth, + vmeOut->xferProtocol, + vmeOut->xferRate2esst); + + if (vmeOut->prefetchEnable) { + for (x = 0; x < 4; x++) { + if ((2 << x) >= vmeOut->prefetchSize) + break; + } + if (x == 4) + x = 3; + temp_ctl |= (x << 16); + } else { + temp_ctl |= 0x40000; + } + // Disable while we are mucking around + p_tempe->lcsr.outboundTranslation[i].otat = 0; + vme_sync_data(); + + p_tempe->lcsr.outboundTranslation[i].otbs = vmeOut->bcastSelect2esst; + p_tempe->lcsr.outboundTranslation[i].otsal = vmeOut->pciBusAddrL; + p_tempe->lcsr.outboundTranslation[i].otsau = vmeOut->pciBusAddrU; + p_tempe->lcsr.outboundTranslation[i].oteal = + vmeOut->pciBusAddrL + (vmeOut->windowSizeL - 0x10000); + p_tempe->lcsr.outboundTranslation[i].oteau = + add64hi(vmeOut->pciBusAddrL, vmeOut->pciBusAddrU, + vmeOut->windowSizeL - 0x10000, vmeOut->windowSizeU); + p_tempe->lcsr.outboundTranslation[i].otofl = + vmeOut->xlatedAddrL - vmeOut->pciBusAddrL; + if (vmeOut->addrSpace == VME_A64) { + p_tempe->lcsr.outboundTranslation[i].otofu = + sub64hi(vmeOut->xlatedAddrL, vmeOut->xlatedAddrU, + vmeOut->pciBusAddrL, vmeOut->pciBusAddrU); + } else { + p_tempe->lcsr.outboundTranslation[i].otofu = 0; + } +#if 0 + printk("Configuring window #%d: ctl = %08x\n", i, temp_ctl); + printk("otbs %08x\n", p_tempe->lcsr.outboundTranslation[i].otbs); + printk("otsal %08x\n", p_tempe->lcsr.outboundTranslation[i].otsal); + printk("otsau %08x\n", p_tempe->lcsr.outboundTranslation[i].otsau); + printk("oteal %08x\n", p_tempe->lcsr.outboundTranslation[i].oteal); + printk("oteau %08x\n", p_tempe->lcsr.outboundTranslation[i].oteau); + printk("otofl %08x\n", p_tempe->lcsr.outboundTranslation[i].otofl); + printk("otofu %08x\n", p_tempe->lcsr.outboundTranslation[i].otofu); +#endif + + // Write ctl reg without enable + p_tempe->lcsr.outboundTranslation[i].otat = temp_ctl; + vme_sync_data(); + + if (vmeOut->windowEnable) + temp_ctl |= 0x80000000; + + p_tempe->lcsr.outboundTranslation[i].otat = temp_ctl; + vme_sync_data(); + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : tempe_get_out_bound +// Description: Return the attributes of an outbound window. +//----------------------------------------------------------------------------- +int tempe_get_out_bound(vmeOutWindowCfg_t * vmeOut) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int temp_ctl = 0; + unsigned int i; + + // Verify input data + if (vmeOut->windowNbr > 7) { + return (-EINVAL); + } + i = vmeOut->windowNbr; + + // Get Control & BUS attributes + temp_ctl = p_tempe->lcsr.outboundTranslation[i].otat; + vmeOut->wrPostEnable = 1; + if (temp_ctl & 0x0020) + vmeOut->userAccessType = VME_SUPER; + else + vmeOut->userAccessType = VME_USER; + if (temp_ctl & 0x0010) + vmeOut->dataAccessType = VME_PROG; + else + vmeOut->dataAccessType = VME_DATA; + if (temp_ctl & 0x80000000) + vmeOut->windowEnable = 1; + + switch ((temp_ctl & 0xC0) >> 6) { + case 0: + vmeOut->maxDataWidth = VME_D16; + break; + case 1: + vmeOut->maxDataWidth = VME_D32; + break; + } + vmeOut->xferProtocol = 1 << ((temp_ctl >> 8) & 7); + + switch (temp_ctl & 0xF) { + case 0x0: + vmeOut->addrSpace = VME_A16; + break; + case 0x1: + vmeOut->addrSpace = VME_A24; + break; + case 0x2: + vmeOut->addrSpace = VME_A32; + break; + case 0x4: + vmeOut->addrSpace = VME_A64; + break; + case 0x5: + vmeOut->addrSpace = VME_CRCSR; + break; + case 0x8: + vmeOut->addrSpace = VME_USER1; + break; + case 0x9: + vmeOut->addrSpace = VME_USER2; + break; + case 0xA: + vmeOut->addrSpace = VME_USER3; + break; + case 0xB: + vmeOut->addrSpace = VME_USER4; + break; + } + + vmeOut->xferRate2esst = VME_SSTNONE; + if (vmeOut->xferProtocol == VME_2eSST) { + + switch (temp_ctl & 0x1800) { + case 0x000: + vmeOut->xferRate2esst = VME_SST160; + break; + case 0x800: + vmeOut->xferRate2esst = VME_SST267; + break; + case 0x1000: + vmeOut->xferRate2esst = VME_SST320; + break; + } + + } + /* Get Window mappings */ + + vmeOut->bcastSelect2esst = p_tempe->lcsr.outboundTranslation[i].otbs; + vmeOut->pciBusAddrL = p_tempe->lcsr.outboundTranslation[i].otsal; + vmeOut->pciBusAddrU = p_tempe->lcsr.outboundTranslation[i].otsau; + + vmeOut->windowSizeL = + (p_tempe->lcsr.outboundTranslation[i].oteal + 0x10000) - + vmeOut->pciBusAddrL; + vmeOut->windowSizeU = + sub64hi(p_tempe->lcsr.outboundTranslation[i].oteal + 0x10000, + p_tempe->lcsr.outboundTranslation[i].oteau, + vmeOut->pciBusAddrL, vmeOut->pciBusAddrU); + vmeOut->xlatedAddrL = + p_tempe->lcsr.outboundTranslation[i].otofl + vmeOut->pciBusAddrL; + if (vmeOut->addrSpace == VME_A64) { + vmeOut->xlatedAddrU = + add64hi(p_tempe->lcsr.outboundTranslation[i].otofl, + p_tempe->lcsr.outboundTranslation[i].otofu, + vmeOut->pciBusAddrL, vmeOut->pciBusAddrU); + } else { + vmeOut->xlatedAddrU = 0; + } + + return (0); +} + +/* + * Function : tempe_setup_lm + * Description: Set the attributes of the location monitor + */ + +int tempe_setup_lm(vmeLmCfg_t * vmeLm) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int temp_ctl = 0; + + /* Setup CTL register */ + switch (vmeLm->addrSpace) { + case VME_A16: + temp_ctl |= 0x00; + break; + case VME_A24: + temp_ctl |= 0x10; + break; + case VME_A32: + temp_ctl |= 0x20; + break; + case VME_A64: + temp_ctl |= 0x40; + break; + default: + return (-EINVAL); + } + if (vmeLm->userAccessType & VME_USER) + temp_ctl |= 0x4; + if (vmeLm->userAccessType & VME_SUPER) + temp_ctl |= 0x8; + if (vmeLm->dataAccessType & VME_DATA) + temp_ctl |= 0x1; + if (vmeLm->dataAccessType & VME_PROG) + temp_ctl |= 0x2; + + /* Disable while we are mucking around */ + p_tempe->lcsr.lmat = 0; + vme_sync_data(); + + p_tempe->lcsr.lmbal = vmeLm->addr; + p_tempe->lcsr.lmbau = vmeLm->addrU; + + tempe_lm_event = 0; + + /* Write ctl reg and enable */ + p_tempe->lcsr.lmat = temp_ctl | 0x80; + vme_sync_data(); + + return (0); +} + +/* + * Function: tempe_wait_lm + * Description: Wait for location monitor to be triggered. + */ + +int tempe_wait_lm(vmeLmCfg_t * vmeLm) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + unsigned long flags; + unsigned int tmp; + + spin_lock_irqsave(&lm_lock, flags); + tmp = tempe_lm_event; + spin_unlock_irqrestore(&lm_lock, flags); + if (tmp == 0) { + if (vmeLm->lmWait < 10) + vmeLm->lmWait = 10; + interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait); + } + p_tempe->lcsr.lmat = 0; + vme_sync_data(); + vmeLm->lmEvents = tempe_lm_event; + return (0); +} + +//----------------------------------------------------------------------------- +// Function : tempe_do_rmw +// Description: Perform an RMW cycle on the VME bus. +// A VME outbound window must already be setup which maps to the desired +// RMW address. +//----------------------------------------------------------------------------- +int tempe_do_rmw(vmeRmwCfg_t * vmeRmw) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int temp_ctl = 0; + unsigned int vme_end_u, vme_end_l; + int *rmw_pci_data_ptr = NULL; + int *va_data_ptr = NULL; + int i; + vmeOutWindowCfg_t vmeOut; + + if (vmeRmw->maxAttempts < 1) { + return (-EINVAL); + } + // Find the PCI address that maps to the desired VME address + for (i = 0; i < 7; i++) { + temp_ctl = p_tempe->lcsr.outboundTranslation[i].otat; + if ((temp_ctl & 0x80000000) == 0) { + continue; + } + memset(&vmeOut, 0, sizeof(vmeOut)); + vmeOut.windowNbr = i; + tempe_get_out_bound(&vmeOut); + if (vmeOut.addrSpace != vmeRmw->addrSpace) { + continue; + } + if (vmeOut.xlatedAddrU > vmeRmw->targetAddrU) { + continue; + } + if (vmeOut.xlatedAddrU == vmeRmw->targetAddrU) { + if (vmeOut.xlatedAddrL > vmeRmw->targetAddr) { + continue; + } + } + vme_end_l = vmeOut.xlatedAddrL + vmeOut.windowSizeL; + vme_end_u = add64hi(vmeOut.xlatedAddrL, vmeOut.xlatedAddrU, + vmeOut.windowSizeL, vmeOut.windowSizeU); + if (sub64hi(vme_end_l, vme_end_u, + vmeRmw->targetAddr, vmeRmw->targetAddrU) >= 0) { + rmw_pci_data_ptr = + (int *)(vmeOut.pciBusAddrL + + (vmeRmw->targetAddr - vmeOut.xlatedAddrL)); + va_data_ptr = + (int *)(out_image_va[i] + + (vmeRmw->targetAddr - vmeOut.xlatedAddrL)); + break; + } + } + + // If no window - fail. + if (rmw_pci_data_ptr == NULL) { + return (-EINVAL); + } + // Setup the RMW registers. + p_tempe->lcsr.vmctrl &= ~0x100000; + vme_sync_data(); + p_tempe->lcsr.rmwen = vmeRmw->enableMask; + p_tempe->lcsr.rmwc = vmeRmw->compareData; + p_tempe->lcsr.rmws = vmeRmw->swapData; + p_tempe->lcsr.rmwau = 0; + p_tempe->lcsr.rmwal = (int)rmw_pci_data_ptr; + p_tempe->lcsr.vmctrl |= 0x100000; + vme_sync_data(); + + // Run the RMW cycle until either success or max attempts. + vmeRmw->numAttempts = 1; + while (vmeRmw->numAttempts <= vmeRmw->maxAttempts) { + + if ((*va_data_ptr & vmeRmw->enableMask) == + (vmeRmw->swapData & vmeRmw->enableMask)) { + + break; + + } + vmeRmw->numAttempts++; + } + + p_tempe->lcsr.vmctrl &= ~0x100000; + vme_sync_data(); + + // If no success, set num Attempts to be greater than max attempts + if (vmeRmw->numAttempts > vmeRmw->maxAttempts) { + vmeRmw->numAttempts = vmeRmw->maxAttempts + 1; + } + + return (0); +} + +//----------------------------------------------------------------------------- +// Function : dma_src_attr, dma_dst_attr +// Description: Helper functions which setup common portions of the +// DMA source and destination attribute registers. +//----------------------------------------------------------------------------- +int dma_src_attr(vmeDmaPacket_t * vmeCur) +{ + + int dsatreg = 0; + // calculate source attribute register + switch (vmeCur->srcBus) { + case VME_DMA_PATTERN_BYTE: + dsatreg = 0x23000000; + break; + case VME_DMA_PATTERN_BYTE_INCREMENT: + dsatreg = 0x22000000; + break; + case VME_DMA_PATTERN_WORD: + dsatreg = 0x21000000; + break; + case VME_DMA_PATTERN_WORD_INCREMENT: + dsatreg = 0x20000000; + break; + case VME_DMA_PCI: + dsatreg = 0x00000000; + break; + case VME_DMA_VME: + dsatreg = 0x10000000; + dsatreg |= tempe_setup_attribute(vmeCur->srcVmeAttr.addrSpace, + vmeCur->srcVmeAttr. + userAccessType, + vmeCur->srcVmeAttr. + dataAccessType, + vmeCur->srcVmeAttr. + maxDataWidth, + vmeCur->srcVmeAttr. + xferProtocol, + vmeCur->srcVmeAttr. + xferRate2esst); + break; + default: + dsatreg = -EINVAL; + break; + } + return (dsatreg); +} + +int dma_dst_attr(vmeDmaPacket_t * vmeCur) +{ + int ddatreg = 0; + // calculate destination attribute register + switch (vmeCur->dstBus) { + case VME_DMA_PCI: + ddatreg = 0x00000000; + break; + case VME_DMA_VME: + ddatreg = 0x10000000; + ddatreg |= tempe_setup_attribute(vmeCur->dstVmeAttr.addrSpace, + vmeCur->dstVmeAttr. + userAccessType, + vmeCur->dstVmeAttr. + dataAccessType, + vmeCur->dstVmeAttr. + maxDataWidth, + vmeCur->dstVmeAttr. + xferProtocol, + vmeCur->dstVmeAttr. + xferRate2esst); + break; + default: + ddatreg = -EINVAL; + break; + } + return (ddatreg); +} + +//----------------------------------------------------------------------------- +// Function : tempe_start_dma +// Description: Write the DMA controller registers with the contents +// needed to actually start the DMA operation. +// returns starting time stamp. +// +// Starts either direct or chained mode as appropriate (based on dctlreg) +//----------------------------------------------------------------------------- +unsigned int +tempe_start_dma(int channel, + unsigned int dctlreg, tsi148DmaDescriptor_t * vmeLL) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + unsigned int val; + + // Setup registers as needed for direct or chained. + if (dctlreg & 0x800000) { + +#if 0 + printk("dsal = %08x\n", vmeLL->dsal); + printk("deal = %08x\n", vmeLL->ddal); + printk("dsat = %08x\n", vmeLL->dsat); + printk("ddat = %08x\n", vmeLL->ddat); + printk("dctl = %08x\n", dctlreg); +#endif + + // Write registers + p_tempe->lcsr.dma[channel].dsau = vmeLL->dsau; + p_tempe->lcsr.dma[channel].dsal = vmeLL->dsal; + p_tempe->lcsr.dma[channel].ddau = vmeLL->ddau; + p_tempe->lcsr.dma[channel].ddal = vmeLL->ddal; + p_tempe->lcsr.dma[channel].dsat = vmeLL->dsat; + p_tempe->lcsr.dma[channel].ddat = vmeLL->ddat; + p_tempe->lcsr.dma[channel].dcnt = vmeLL->dcnt; + p_tempe->lcsr.dma[channel].ddbs = vmeLL->ddbs; + } else { + p_tempe->lcsr.dma[channel].dnlau = 0; + p_tempe->lcsr.dma[channel].dnlal = (unsigned int)vmeLL; + } + vme_sync_data(); + + // Start the operation + p_tempe->lcsr.dma[channel].dctl = dctlreg | 0x2000000; + val = get_tbl(); + vme_sync_data(); + return (val); +} + +//----------------------------------------------------------------------------- +// Function : tempe_setup_dma +// Description: Create a linked list (possibly only 1 element long) of +// Tempe DMA descriptors which will perform the DMA operation described +// by the DMA packet. Flush descriptors from cache. +// Return pointer to beginning of list (or 0 on failure.). +//----------------------------------------------------------------------------- +tsi148DmaDescriptor_t *tempe_setup_dma(vmeDmaPacket_t * vmeDma) +{ + vmeDmaPacket_t *vme_cur; + int max_per_page; + int currentLLcount; + tsi148DmaDescriptor_t *startLL; + tsi148DmaDescriptor_t *currentLL; + tsi148DmaDescriptor_t *nextLL; + + max_per_page = PAGESIZE / sizeof(tsi148DmaDescriptor_t) - 1; + startLL = (tsi148DmaDescriptor_t *) __get_free_pages(GFP_KERNEL, 0); + if (startLL == 0) { + return (startLL); + } + // First allocate pages for descriptors and create linked list + vme_cur = vmeDma; + currentLL = startLL; + currentLLcount = 0; + while (vme_cur != 0) { + if (vme_cur->pNextPacket != 0) { + currentLL->dnlau = (unsigned int)0; + currentLL->dnlal = (unsigned int)(currentLL + 1); + currentLLcount++; + if (currentLLcount >= max_per_page) { + currentLL->dnlal = + __get_free_pages(GFP_KERNEL, 0); + currentLLcount = 0; + } + currentLL = (tsi148DmaDescriptor_t *) currentLL->dnlal; + } else { + currentLL->dnlau = (unsigned int)0; + currentLL->dnlal = (unsigned int)0; + } + vme_cur = vme_cur->pNextPacket; + } + + // Next fill in information for each descriptor + vme_cur = vmeDma; + currentLL = startLL; + while (vme_cur != 0) { + currentLL->dsau = vme_cur->srcAddrU; + currentLL->dsal = vme_cur->srcAddr; + currentLL->ddau = vme_cur->dstAddrU; + currentLL->ddal = vme_cur->dstAddr; + currentLL->dsat = dma_src_attr(vme_cur); + currentLL->ddat = dma_dst_attr(vme_cur); + currentLL->dcnt = vme_cur->byteCount; + currentLL->ddbs = vme_cur->bcastSelect2esst; + + currentLL = (tsi148DmaDescriptor_t *) currentLL->dnlal; + vme_cur = vme_cur->pNextPacket; + } + + // Convert Links to PCI addresses. + currentLL = startLL; + while (currentLL != 0) { + nextLL = (tsi148DmaDescriptor_t *) currentLL->dnlal; + currentLL->dnlal = (unsigned int)virt_to_bus(nextLL); + if (nextLL == 0) + currentLL->dnlal |= 1; + vme_flush_line(currentLL); + vme_flush_line(((char *)currentLL) + LINESIZE); + currentLL = nextLL; + } + + // Return pointer to descriptors list + return (startLL); +} + +//----------------------------------------------------------------------------- +// Function : tempe_free_dma +// Description: Free all memory that is used to hold the DMA +// descriptor linked list. +// +//----------------------------------------------------------------------------- +int tempe_free_dma(tsi148DmaDescriptor_t * startLL) +{ + tsi148DmaDescriptor_t *currentLL; + tsi148DmaDescriptor_t *prevLL; + tsi148DmaDescriptor_t *nextLL; + + // Convert Links to virtual addresses. + currentLL = startLL; + while (currentLL != 0) { + if (currentLL->dnlal & 1) { + currentLL->dnlal = 0; + } else { + currentLL->dnlal = + (unsigned int)bus_to_virt(currentLL->dnlal); + } + currentLL = (tsi148DmaDescriptor_t *) currentLL->dnlal; + } + + // Free all pages associated with the descriptors. + currentLL = startLL; + prevLL = currentLL; + while (currentLL != 0) { + nextLL = (tsi148DmaDescriptor_t *) currentLL->dnlal; + if (currentLL + 1 != nextLL) { + free_pages((int)prevLL, 0); + prevLL = nextLL; + } + currentLL = nextLL; + } + + // Return pointer to descriptors list + return (0); +} + +/* + * Function : tempe_do_dma + * Description: + * Sanity check the DMA request. + * Setup DMA attribute register. + * Create linked list of DMA descriptors. + * Invoke actual DMA operation. + * Wait for completion. Record ending time. + * Free the linked list of DMA descriptors. + */ + +int tempe_do_dma(vmeDmaPacket_t * vmeDma) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + unsigned int dctlreg = 0; + int val; + int channel, x; + vmeDmaPacket_t *cur_dma; + tsi148DmaDescriptor_t *dmaLL; + + /* Sanity check the VME chain */ + channel = vmeDma->channel_number; + if (channel > 1) { + return (-EINVAL); + } + cur_dma = vmeDma; + while (cur_dma != 0) { + if (cur_dma->byteCount == 0) { + return (-EINVAL); + } + if (dma_src_attr(cur_dma) < 0) { + return (-EINVAL); + } + if (dma_dst_attr(cur_dma) < 0) { + return (-EINVAL); + } + + cur_dma = cur_dma->pNextPacket; + if (cur_dma == vmeDma) { // Endless Loop! + return (-EINVAL); + } + } + + /* calculate control register */ + if (vmeDma->pNextPacket != 0) { + dctlreg = 0; + } else { + dctlreg = 0x800000; + } + + for (x = 0; x < 8; x++) { // vme block size + if ((32 << x) >= vmeDma->maxVmeBlockSize) { + break; + } + } + if (x == 8) + x = 7; + dctlreg |= (x << 12); + + for (x = 0; x < 8; x++) { // pci block size + if ((32 << x) >= vmeDma->maxPciBlockSize) { + break; + } + } + if (x == 8) + x = 7; + dctlreg |= (x << 4); + + if (vmeDma->vmeBackOffTimer) { + for (x = 1; x < 8; x++) { // vme timer + if ((1 << (x - 1)) >= vmeDma->vmeBackOffTimer) { + break; + } + } + if (x == 8) + x = 7; + dctlreg |= (x << 8); + } + + if (vmeDma->pciBackOffTimer) { + for (x = 1; x < 8; x++) { // pci timer + if ((1 << (x - 1)) >= vmeDma->pciBackOffTimer) { + break; + } + } + if (x == 8) + x = 7; + dctlreg |= (x << 0); + } + /* Setup the dma chain */ + dmaLL = tempe_setup_dma(vmeDma); + + /* Start the DMA */ + if (dctlreg & 0x800000) { + vmeDma->vmeDmaStartTick = + tempe_start_dma(channel, dctlreg, dmaLL); + } else { + vmeDma->vmeDmaStartTick = + tempe_start_dma(channel, dctlreg, (tsi148DmaDescriptor_t *) + virt_to_phys(dmaLL)); + } + + wait_event_interruptible(dma_queue[channel], + (p_tempe->lcsr.dma[channel]. + dsta & 0x1000000) == 0); + val = p_tempe->lcsr.dma[channel].dsta; + + vmeDma->vmeDmaStopTick = tempe_dma_irq_time[channel]; + vmeDma->vmeDmaStatus = val; + if (vmeDma->vmeDmaStopTick < vmeDma->vmeDmaStartTick) { + vmeDma->vmeDmaElapsedTime = + (0xFFFFFFFF - vmeDma->vmeDmaStartTick) + + vmeDma->vmeDmaStopTick; + } else { + vmeDma->vmeDmaElapsedTime = + vmeDma->vmeDmaStopTick - vmeDma->vmeDmaStartTick; + } + vmeDma->vmeDmaElapsedTime -= vmechip_irq_overhead_ticks; + vmeDma->vmeDmaElapsedTime /= (tb_speed / 1000000); + + vmeDma->vmeDmaStatus = 0; + if (val & 0x10000000) { + printk(KERN_ERR + "tsi148: DMA Error in DMA_tempe_irqhandler DSTA=%08X\n", + val); + vmeDma->vmeDmaStatus = val; + + } + /* Free the dma chain */ + tempe_free_dma(dmaLL); + + return (0); +} + +/* + * Function: tsi148_shutdown + * Description: Put VME bridge in quiescent state. Disable all decoders, + * clear all interrupts. + */ + +void tsi148_shutdown(void) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int i; + + /* + * Shutdown all inbound and outbound windows. + */ + for (i = 0; i < 8; i++) { + p_tempe->lcsr.inboundTranslation[i].itat = 0; + p_tempe->lcsr.outboundTranslation[i].otat = 0; + } + + /* + * Shutdown Location monitor. + */ + p_tempe->lcsr.lmat = 0; + + /* + * Shutdown CRG map. + */ + p_tempe->lcsr.csrat = 0; + + /* + * Clear error status. + */ + p_tempe->lcsr.edpat = 0xFFFFFFFF; + p_tempe->lcsr.veat = 0xFFFFFFFF; + p_tempe->lcsr.pstat = 0x07000700; + + /* + * Remove VIRQ interrupt (if any) + */ + if (p_tempe->lcsr.vicr & 0x800) { + p_tempe->lcsr.vicr = 0x8000; + } + + /* + * Disable and clear all interrupts. + */ + p_tempe->lcsr.inteo = 0; + vme_sync_data(); + p_tempe->lcsr.intc = 0xFFFFFFFF; + vme_sync_data(); + p_tempe->lcsr.inten = 0xFFFFFFFF; + + /* + * Map all Interrupts to PCI INTA + */ + p_tempe->lcsr.intm1 = 0; + p_tempe->lcsr.intm2 = 0; + + vme_sync_data(); +} + +/* + * Function: tempe_init() + * Description: Initialize the VME chip as needed by the driver. + * Quiesce VME bridge. + * Setup default decoders. + * Connect IRQ handler and enable interrupts. + * Conduct quick sanity check of bridge. + */ + +int tempe_init(void) +{ + tsi148_t *p_tempe = (tsi148_t *) vmechip_baseaddr; + int result; + unsigned int tmp; + unsigned int crcsr_addr; + unsigned int irq_overhead_start; + u32 vme_stat_reg; + int overhead_ticks; + + tsi148_shutdown(); + + /* Determine syscon and slot number */ + tmp = p_tempe->lcsr.vstat; + if (tmp & 0x100) { + vme_syscon = 1; + } else { + vme_syscon = 0; + } + + /* Initialize crcsr map */ + if (vme_slotnum != -1) { + p_tempe->crcsr.cbar = vme_slotnum << 3; + crcsr_addr = vme_slotnum * 512 * 1024; + p_tempe->lcsr.crol = (unsigned long)vmechip_interboard_datap; + p_tempe->lcsr.crou = 0; + vme_sync_data(); + p_tempe->lcsr.crat = 0xFFFFFFFF; + } + + result = request_irq(vmechip_irq, + tempe_irqhandler, + SA_SHIRQ | SA_INTERRUPT, + "VMEBus (Tsi148)", vmechip_baseaddr); + if (result) { + printk(KERN_ERR + "tsi148: can't get assigned pci irq vector %02X\n", + vmechip_irq); + return (0); + } + /* Enable DMA, mailbox, VIRQ (syscon only) & LM Interrupts */ + if (vme_syscon) + tmp = 0x03FF20FE; + else + tmp = 0x03FF2000; + p_tempe->lcsr.inteo = tmp; + p_tempe->lcsr.inten = tmp; + + /* Do a quick sanity test of the bridge */ + if (p_tempe->lcsr.inteo != tmp) { + return (0); + } + /* Sanity check register access */ + for (tmp = 1; tmp < 0x80000000; tmp = tmp << 1) { + p_tempe->lcsr.rmwen = tmp; + p_tempe->lcsr.rmwc = ~tmp; + vme_sync_data(); + if (p_tempe->lcsr.rmwen != tmp) { + return (0); + } + if (p_tempe->lcsr.rmwc != ~tmp) { + return (0); + } + } + + /* Calculate IRQ overhead */ + irq_overhead_start = get_tbl(); + p_tempe->gcsr.mbox[0] = 0; + vme_sync_data(); + for (tmp = 0; tmp < 10; tmp++) { + vme_sync_data(); + } + + overhead_ticks = tempe_irq_time - irq_overhead_start; + if (overhead_ticks > 0) { + vmechip_irq_overhead_ticks = overhead_ticks; + } else { + vmechip_irq_overhead_ticks = 1; + } + + /* Clear board fail, and power-up reset */ + vme_stat_reg = p_tempe->lcsr.vstat; + vme_stat_reg &= ~TSI148_LCSR_VSTAT_BRDFL; + vme_stat_reg |= TSI148_LCSR_VSTAT_CPURST; + p_tempe->lcsr.vstat = vme_stat_reg; + + return (1); +} diff -u --new-file --recursive linux-2.6.14.orig/drivers/vme/tsi148.h linux-2.6.14.mod/drivers/vme/tsi148.h --- linux-2.6.14.orig/drivers/vme/tsi148.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/vme/tsi148.h 2005-11-16 10:40:21.000000000 -0700 @@ -0,0 +1,1191 @@ +/* + * tsi148.h + * + * Support for the Tundra TSI148 VME Bridge chip + * + * Author: Tom Armistead + * Updated and maintained by Ajit Prem + * Copyright 2004 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef TSI148_H +#define TSI148_H + +/* + * Define the number of each that the Tsi148 supports. + */ +#define TSI148_MAX_OUT_WINDOWS 8 /* Max Outbound Windows */ +#define TSI148_MAX_IN_WINDOWS 8 /* Max Inbound Windows */ +#define TSI148_MAX_DMA_CNTRLS 2 /* Max DMA Controllers */ +#define TSI148_MAX_MAILBOXES 4 /* Max Mail Box registers */ +#define TSI148_MAX_SEMAPHORES 8 /* Max Semaphores */ + + /* + * Misc Structs that are used as part of the larger structs + */ + + /* + * Outbound Functions used in LCSR + */ +typedef struct { + unsigned int otsau; /* Starting address */ + unsigned int otsal; + unsigned int oteau; /* Ending address */ + unsigned int oteal; + unsigned int otofu; /* Translation offset */ + unsigned int otofl; + unsigned int otbs; /* 2eSST broadcast select */ + unsigned int otat; /* Attributes */ +} tsi148OutboundTranslation_t; + + /* + * Inbound Functions used in LCSR + */ +typedef struct { + unsigned int itsau; /* Starting address */ + unsigned int itsal; + unsigned int iteau; /* Ending address */ + unsigned int iteal; + unsigned int itofu; /* Translation offset */ + unsigned int itofl; + unsigned int itat; /* Attributes */ + unsigned char reserved10[4]; +} tsi148InboundTranslation_t; + + /* + * DMA Controller used in LCSR + */ +typedef struct { + unsigned int dctl; /* Control */ + unsigned int dsta; /* Status */ + unsigned int dcsau; /* RO Current Source address */ + unsigned int dcsal; + unsigned int dcdau; /* RO Current Destination address */ + unsigned int dcdal; + unsigned int dclau; /* RO Current Link address */ + unsigned int dclal; + unsigned int dsau; /* Source Address */ + unsigned int dsal; + unsigned int ddau; /* Destination Address */ + unsigned int ddal; + unsigned int dsat; /* Source attributes */ + unsigned int ddat; /* Destination attributes */ + unsigned int dnlau; /* Next link address */ + unsigned int dnlal; + unsigned int dcnt; /* Byte count */ + unsigned int ddbs; /* 2eSST Broadcast select */ + unsigned char reserved12[0x38]; +} tsi148Dma_t; + + /* + * Layout of a DMAC Linked-List Descriptor + */ +struct tsi148DmaDescriptor { + unsigned int dsau; /* Source Address */ + unsigned int dsal; + unsigned int ddau; /* Destination Address */ + unsigned int ddal; + unsigned int dsat; /* Source attributes */ + unsigned int ddat; /* Destination attributes */ + unsigned int dnlau; /* Next link address */ + unsigned int dnlal; + unsigned int dcnt; /* Byte count */ + unsigned int ddbs; /* 2eSST Broadcast select */ +}; +typedef struct tsi148DmaDescriptor tsi148DmaDescriptor_t; + + /* + * PCFS Configuration - includes memory base address register MBAR + */ +typedef struct { + unsigned short veni; /* PCI header VENI/DEVI */ + unsigned short devi; + unsigned short cmmd; /* PCI header CMMD/STAT */ + unsigned short stat; + unsigned int reviAndClas; /* PCI header REVI/CLAS */ + unsigned char clsz; /* PCI header CLSZ/MLAT/HEAD/reserved */ + unsigned char mlat; + unsigned char head; + unsigned char reserved0[1]; + unsigned int mbarl; /* PCI header MBARL */ + unsigned int mbaru; /* PCI header MBARU */ + unsigned char reserved1[20]; + unsigned short subv; /* PCI header SUBV/SUBI */ + unsigned short subi; + unsigned char reserved2[4]; /* PCI header reserved */ + unsigned char capp; /* PCI header CAPP/reserved */ + unsigned char reserved3[7]; /* PCI header reserved */ + unsigned char intl; /* PCI header INTL/INTP/MNGM/MXLA */ + unsigned char intp; + unsigned char mngn; + unsigned char mxla; + + /* + * offset 40 040 - MSI Capp MSICD/NCAPP/MSCI + * offset 44 044 - MSI Capp MSIAL + * offset 48 048 - MSI Capp MSIAU + * offset 4C 04C - MSI Capp MSIMD/reserved + */ + unsigned char msiCapID; + unsigned char msiNextCapPtr; + unsigned short msiControl; + unsigned int msiMsgAddrL; + unsigned int msiMsgAddrU; + unsigned short msiMsgData; + unsigned char reserved4[2]; + + /* + * offset 50 050 - PCI-X Capp PCIXCD/NCAPP/PCIXCAP + * offset 54 054 - PCI-X Capp PCIXSTAT + */ + unsigned char pcixCapID; + unsigned char pcixNextCapPtr; + unsigned short pcixCommand; + unsigned int pcixStatus; + + /* + * offset 58 058 Reserved + * ... + * offset FF 0FF Reserved + */ + unsigned char reserved5[167]; + +} tsi148Pcfs_t; + + /* + * LCSR definitions + */ +typedef struct { + + /* + * Outbound Translations + */ + tsi148OutboundTranslation_t outboundTranslation[TSI148_MAX_OUT_WINDOWS]; + + /* + * VMEbus interupt ack + * offset 200 + * + * Note: Even though the registers are defined + * as 32-bits in the spec, we only want + * to issue 8-bit IACK cycles on the bus. + */ + unsigned char viack[8 * 4]; + + /* + * RMW + * offset 220 + */ + unsigned int rmwau; + unsigned int rmwal; + unsigned int rmwen; + unsigned int rmwc; + unsigned int rmws; + + /* + * VMEbus control + * offset 234 + */ + unsigned int vmctrl; + unsigned int vctrl; + unsigned int vstat; + + /* + * PCI status + * offset 240 + */ + unsigned int pstat; + unsigned char pstatrsvd[0xc]; + + /* + * VME filter. + * offset 250 + */ + unsigned int vmefl; + unsigned char vmeflrsvd[0xc]; + + /* + * VME exception. + * offset 260 + */ + unsigned int veau; + unsigned int veal; + unsigned int veat; + unsigned char vearsvd[0x4]; + + /* + * PCI error + * offset 270 + */ + unsigned int edpau; + unsigned int edpal; + unsigned int edpxa; + unsigned int edpxs; + unsigned int edpat; + unsigned char edparsvd[0x7c]; + + /* + * Inbound Translations + * offset 300 + */ + tsi148InboundTranslation_t inboundTranslation[TSI148_MAX_IN_WINDOWS]; + + /* + * Inbound Translation GCSR + * offset 400 + */ + unsigned int gbau; + unsigned int gbal; + unsigned int gcsrat; + + /* + * Inbound Translation CRG + * offset 40C + */ + unsigned int cbau; + unsigned int cbal; + unsigned int csrat; + + /* + * Inbound Translation CR/CSR + * CRG + * offset 418 + */ + unsigned int crou; + unsigned int crol; + unsigned int crat; + + /* + * Inbound Translation Location Monitor + * offset 424 + */ + unsigned int lmbau; + unsigned int lmbal; + unsigned int lmat; + + /* + * VMEbus Interrupt Control. + * offset 430 + */ + unsigned int bcu; + unsigned int bcl; + unsigned int bpgtr; + unsigned int bpctr; + unsigned int vicr; + + unsigned char vicrsvd[0x4]; + + /* + * Local Bus Interrupt Control. + * offset 448 + */ + unsigned int inten; + unsigned int inteo; + unsigned int ints; + unsigned int intc; + unsigned int intm1; + unsigned int intm2; + + unsigned char reserved7[0xa0]; + + /* + * DMA Controllers + * offset 500 + */ + tsi148Dma_t dma[TSI148_MAX_DMA_CNTRLS]; + +} tsi148Lcsr_t; + + /* + * GCSR Register Group + */ +typedef struct { + /* + * Header + * GCSR CRG + * offset 00 600 - DEVI/VENI + */ + unsigned short devi; + unsigned short veni; + + /* + * Control + * GCSR CRG + * offset 04 604 - CTRL/GA/REVID + */ + unsigned short ctrl; + unsigned char ga; + unsigned char revid; + + /* + * Semaphore + * GCSR CRG + * offset 08 608 - Semaphore3/2/1/0 + * offset 0C 60C - Seamphore7/6/5/4 + */ + unsigned char semaphore[TSI148_MAX_SEMAPHORES]; + + /* + * Mail Box + * GCSR CRG + * offset 10 610 - Mailbox0 + */ + unsigned int mbox[TSI148_MAX_MAILBOXES]; + +} tsi148Gcsr_t; + + /* + * CR/CSR + */ +typedef struct { + /* + * CR/CSR CRG + * offset 7FFF4 FF4 - CSRBCR + * offset 7FFF8 FF8 - CSRBSR + * offset 7FFFC FFC - CBAR + */ + unsigned int csrbcr; + unsigned int csrbsr; + unsigned int cbar; +} tsi148Crcsr_t; + + /* + * TSI148 ASIC register structure overlays and bit field definitions. + * + * Note: Tsi148 Register Group (CRG) consists of the following + * combination of registers: + * PCFS - PCI Configuration Space Registers + * LCSR - Local Control and Status Registers + * GCSR - Global Control and Status Registers + * CR/CSR - Subset of Configuration ROM / + * Control and Status Registers + */ + + /* + * Combined Register Group (CRG) + */ +typedef struct { + /* + * PCFS + */ + tsi148Pcfs_t pcfs; + + /* + * LCSR + */ + tsi148Lcsr_t lcsr; + + /* + * GCSR + */ + tsi148Gcsr_t gcsr; + + /* + * Fill Space + */ + unsigned char reserved9[0xFF4 - 0x61C - 4]; + + /* + * CR/CSR + */ + tsi148Crcsr_t crcsr; + +} tsi148_t; + + /* + * TSI148 Register Bit Definitions + */ + + /* + * PFCS Register Set + */ + + /* + * Command/Status Registers (CRG + $004) + */ +#define TSI148_PCFS_CMMD_SERR (1<<8) /* SERR_L out pin ssys err */ +#define TSI148_PCFS_CMMD_PERR (1<<6) /* PERR_L out pin parity */ +#define TSI148_PCFS_CMMD_MSTR (1<<2) /* PCI bus master */ +#define TSI148_PCFS_CMMD_MEMSP (1<<1) /* PCI mem space access */ +#define TSI148_PCFS_CMMD_IOSP (1<<0) /* PCI I/O space enable */ + +#define TSI148_PCFS_STAT_RCPVE (1<<15) /* Detected Parity Error */ +#define TSI148_PCFS_STAT_SIGSE (1<<14) /* Signalled System Error */ +#define TSI148_PCFS_STAT_RCVMA (1<<13) /* Received Master Abort */ +#define TSI148_PCFS_STAT_RCVTA (1<<12) /* Received Target Abort */ +#define TSI148_PCFS_STAT_SIGTA (1<<11) /* Signalled Target Abort */ +#define TSI148_PCFS_STAT_SELTIM (3<<9) /* DELSEL Timing */ +#define TSI148_PCFS_STAT_DPAR (1<<8) /* Data Parity Err Reported */ +#define TSI148_PCFS_STAT_FAST (1<<7) /* Fast back-to-back Cap */ +#define TSI148_PCFS_STAT_P66M (1<<5) /* 66 MHz Capable */ +#define TSI148_PCFS_STAT_CAPL (1<<4) /* Capab List - address $34 */ + + /* + * Revision ID/Class Code Registers (CRG +$008) + */ +#define TSI148_PCFS_CLAS_M (0xFF<<24) /* Class ID */ +#define TSI148_PCFS_SUBCLAS_M (0xFF<<16) /* Sub-Class ID */ +#define TSI148_PCFS_PROGIF_M (0xFF<<8) /* Sub-Class ID */ +#define TSI148_PCFS_REVID_M (0xFF<<0) /* Rev ID */ + + /* + * Cache Line Size/ Master Latency Timer/ Header Type Registers (CRG + $00C) + */ +#define TSI148_PCFS_HEAD_M (0xFF<<16) /* Master Lat Timer */ +#define TSI148_PCFS_MLAT_M (0xFF<<8) /* Master Lat Timer */ +#define TSI148_PCFS_CLSZ_M (0xFF<<0) /* Cache Line Size */ + + /* + * Memory Base Address Lower Reg (CRG + $010) + */ +#define TSI148_PCFS_MBARL_BASEL_M (0xFFFFF<<12) /* Base Addr Lower Mask */ +#define TSI148_PCFS_MBARL_PRE (1<<3) /* Prefetch */ +#define TSI148_PCFS_MBARL_MTYPE_M (3<<1) /* Memory Type Mask */ +#define TSI148_PCFS_MBARL_IOMEM (1<<0) /* I/O Space Indicator */ + + /* + * Message Signaled Interrupt Capabilities Register (CRG + $040) + */ +#define TSI148_PCFS_MSICAP_64BAC (1<<7) /* 64-bit Address Capable */ +#define TSI148_PCFS_MSICAP_MME_M (7<<4) /* Multiple Msg Enable Mask */ +#define TSI148_PCFS_MSICAP_MMC_M (7<<1) /* Multiple Msg Capable Mask */ +#define TSI148_PCFS_MSICAP_MSIEN (1<<0) /* Msg signaled INT Enable */ + + /* + * Message Address Lower Register (CRG +$044) + */ +#define TSI148_PCFS_MSIAL_M (0x3FFFFFFF<<2) /* Mask */ + + /* + * Message Data Register (CRG + 4C) + */ +#define TSI148_PCFS_MSIMD_M (0xFFFF<<0) /* Mask */ + + /* + * PCI-X Capabilities Register (CRG + $050) + */ +#define TSI148_PCFS_PCIXCAP_MOST_M (7<<4) /* Max outstanding Split Tran */ +#define TSI148_PCFS_PCIXCAP_MMRBC_M (3<<2) /* Max Mem Read byte cnt */ +#define TSI148_PCFS_PCIXCAP_ERO (1<<1) /* Enable Relaxed Ordering */ +#define TSI148_PCFS_PCIXCAP_DPERE (1<<0) /* Data Parity Recover Enable */ + + /* + * PCI-X Status Register (CRG +$054) + */ +#define TSI148_PCFS_PCIXSTAT_RSCEM (1<<29) /* Recieved Split Comp Error */ +#define TSI148_PCFS_PCIXSTAT_DMCRS_M (7<<26) /* max Cumulative Read Size */ +#define TSI148_PCFS_PCIXSTAT_DMOST_M (7<<23) /* max outstanding Split Trans */ +#define TSI148_PCFS_PCIXSTAT_DMMRC_M (3<<21) /* max mem read byte count */ +#define TSI148_PCFS_PCIXSTAT_DC (1<<20) /* Device Complexity */ +#define TSI148_PCFS_PCIXSTAT_USC (1<<19) /* Unexpected Split comp */ +#define TSI148_PCFS_PCIXSTAT_SCD (1<<18) /* Split completion discard */ +#define TSI148_PCFS_PCIXSTAT_133C (1<<17) /* 133MHz capable */ +#define TSI148_PCFS_PCIXSTAT_64D (1<<16) /* 64 bit device */ +#define TSI148_PCFS_PCIXSTAT_BN_M (0xFF<<8) /* Bus number */ +#define TSI148_PCFS_PCIXSTAT_DN_M (0x1F<<3) /* Device number */ +#define TSI148_PCFS_PCIXSTAT_FN_M (7<<0) /* Function Number */ + + /* + * LCSR Registers + */ + + /* + * Outbound Translation Starting Address Lower + */ +#define TSI148_LCSR_OTSAL_M (0xFFFF<<16) /* Mask */ + + /* + * Outbound Translation Ending Address Lower + */ +#define TSI148_LCSR_OTEAL_M (0xFFFF<<16) /* Mask */ + + /* + * Outbound Translation Offset Lower + */ +#define TSI148_LCSR_OTOFFL_M (0xFFFF<<16) /* Mask */ + + /* + * Outbound Translation 2eSST Broadcast Select + */ +#define TSI148_LCSR_OTBS_M (0xFFFFF<<0) /* Mask */ + + /* + * Outbound Translation Attribute + */ +#define TSI148_LCSR_OTAT_EN (1<<31) /* Window Enable */ +#define TSI148_LCSR_OTAT_MRPFD (1<<18) /* Prefetch Disable */ + +#define TSI148_LCSR_OTAT_PFS_M (3<<16) /* Prefetch Size Mask */ +#define TSI148_LCSR_OTAT_PFS_2 (0<<16) /* 2 Cache Lines P Size */ +#define TSI148_LCSR_OTAT_PFS_4 (1<<16) /* 4 Cache Lines P Size */ +#define TSI148_LCSR_OTAT_PFS_8 (2<<16) /* 8 Cache Lines P Size */ +#define TSI148_LCSR_OTAT_PFS_16 (3<<16) /* 16 Cache Lines P Size */ + +#define TSI148_LCSR_OTAT_2eSSTM_M (3<<11) /* 2eSST Xfer Rate Mask */ +#define TSI148_LCSR_OTAT_2eSSTM_160 (0<<11) /* 160MB/s 2eSST Xfer Rate */ +#define TSI148_LCSR_OTAT_2eSSTM_267 (1<<11) /* 267MB/s 2eSST Xfer Rate */ +#define TSI148_LCSR_OTAT_2eSSTM_320 (2<<11) /* 320MB/s 2eSST Xfer Rate */ + +#define TSI148_LCSR_OTAT_TM_M (7<<8) /* Xfer Protocol Mask */ +#define TSI148_LCSR_OTAT_TM_SCT (0<<8) /* SCT Xfer Protocol */ +#define TSI148_LCSR_OTAT_TM_BLT (1<<8) /* BLT Xfer Protocol */ +#define TSI148_LCSR_OTAT_TM_MBLT (2<<8) /* MBLT Xfer Protocol */ +#define TSI148_LCSR_OTAT_TM_2eVME (3<<8) /* 2eVME Xfer Protocol */ +#define TSI148_LCSR_OTAT_TM_2eSST (4<<8) /* 2eSST Xfer Protocol */ +#define TSI148_LCSR_OTAT_TM_2eSSTB (5<<8) /* 2eSST Bcast Xfer Protocol */ + +#define TSI148_LCSR_OTAT_DBW_M (3<<6) /* Max Data Width */ +#define TSI148_LCSR_OTAT_DBW_16 (0<<6) /* 16-bit Data Width */ +#define TSI148_LCSR_OTAT_DBW_32 (1<<6) /* 32-bit Data Width */ + +#define TSI148_LCSR_OTAT_SUP (1<<5) /* Supervisory Access */ +#define TSI148_LCSR_OTAT_PGM (1<<4) /* Program Access */ + +#define TSI148_LCSR_OTAT_AMODE_M (0xf<<0) /* Address Mode Mask */ +#define TSI148_LCSR_OTAT_AMODE_A16 (0<<0) /* A16 Address Space */ +#define TSI148_LCSR_OTAT_AMODE_A24 (1<<0) /* A24 Address Space */ +#define TSI148_LCSR_OTAT_AMODE_A32 (2<<0) /* A32 Address Space */ +#define TSI148_LCSR_OTAT_AMODE_A64 (4<<0) /* A32 Address Space */ +#define TSI148_LCSR_OTAT_AMODE_CRCSR (5<<0) /* CR/CSR Address Space */ + + /* + * VME Master Control Register CRG+$234 + */ +#define TSI148_LCSR_VMCTRL_VSA (1<<27) /* VMEbus Stop Ack */ +#define TSI148_LCSR_VMCTRL_VS (1<<26) /* VMEbus Stop */ +#define TSI148_LCSR_VMCTRL_DHB (1<<25) /* Device Has Bus */ +#define TSI148_LCSR_VMCTRL_DWB (1<<24) /* Device Wants Bus */ + +#define TSI148_LCSR_VMCTRL_RMWEN (1<<20) /* RMW Enable */ + +#define TSI148_LCSR_VMCTRL_ATO_M (7<<16) /* Master Access Time-out Mask */ +#define TSI148_LCSR_VMCTRL_ATO_32 (0<<16) /* 32 us */ +#define TSI148_LCSR_VMCTRL_ATO_128 (1<<16) /* 128 us */ +#define TSI148_LCSR_VMCTRL_ATO_512 (2<<16) /* 512 us */ +#define TSI148_LCSR_VMCTRL_ATO_2M (3<<16) /* 2 ms */ +#define TSI148_LCSR_VMCTRL_ATO_8M (4<<16) /* 8 ms */ +#define TSI148_LCSR_VMCTRL_ATO_32M (5<<16) /* 32 ms */ +#define TSI148_LCSR_VMCTRL_ATO_128M (6<<16) /* 128 ms */ +#define TSI148_LCSR_VMCTRL_ATO_DIS (7<<16) /* Disabled */ + +#define TSI148_LCSR_VMCTRL_VTOFF_M (7<<12) /* VMEbus Master Time off */ +#define TSI148_LCSR_VMCTRL_VTOFF_0 (0<<12) /* 0us */ +#define TSI148_LCSR_VMCTRL_VTOFF_1 (1<<12) /* 1us */ +#define TSI148_LCSR_VMCTRL_VTOFF_2 (2<<12) /* 2us */ +#define TSI148_LCSR_VMCTRL_VTOFF_4 (3<<12) /* 4us */ +#define TSI148_LCSR_VMCTRL_VTOFF_8 (4<<12) /* 8us */ +#define TSI148_LCSR_VMCTRL_VTOFF_16 (5<<12) /* 16us */ +#define TSI148_LCSR_VMCTRL_VTOFF_32 (6<<12) /* 32us */ +#define TSI148_LCSR_VMCTRL_VTOFF_64 (7<<12) /* 64us */ + +#define TSI148_LCSR_VMCTRL_VTON_M (7<<8) /* VMEbus Master Time On */ +#define TSI148_LCSR_VMCTRL_VTON_4 (0<<8) /* 8us */ +#define TSI148_LCSR_VMCTRL_VTON_8 (1<<8) /* 8us */ +#define TSI148_LCSR_VMCTRL_VTON_16 (2<<8) /* 16us */ +#define TSI148_LCSR_VMCTRL_VTON_32 (3<<8) /* 32us */ +#define TSI148_LCSR_VMCTRL_VTON_64 (4<<8) /* 64us */ +#define TSI148_LCSR_VMCTRL_VTON_128 (5<<8) /* 128us */ +#define TSI148_LCSR_VMCTRL_VTON_256 (6<<8) /* 256us */ +#define TSI148_LCSR_VMCTRL_VTON_512 (7<<8) /* 512us */ + +#define TSI148_LCSR_VMCTRL_VREL_M (3<<3) /* VMEbus Master Rel Mode Mask */ +#define TSI148_LCSR_VMCTRL_VREL_T_D (0<<3) /* Time on or Done */ +#define TSI148_LCSR_VMCTRL_VREL_T_R_D (1<<3) /* Time on and REQ or Done */ +#define TSI148_LCSR_VMCTRL_VREL_T_B_D (2<<3) /* Time on and BCLR or Done */ +#define TSI148_LCSR_VMCTRL_VREL_T_D_R (3<<3) /* Time on or Done and REQ */ + +#define TSI148_LCSR_VMCTRL_VFAIR (1<<2) /* VMEbus Master Fair Mode */ +#define TSI148_LCSR_VMCTRL_VREQL_M (3<<0) /* VMEbus Master Req Level Mask */ + + /* + * VMEbus Control Register CRG+$238 + */ +#define TSI148_LCSR_VCTRL_LRE (1<<31) /* Late Retry Enable */ + +#define TSI148_LCSR_VCTRL_DLT_M (0xF<<24) /* Deadlock Timer */ +#define TSI148_LCSR_VCTRL_DLT_OFF (0<<24) /* Deadlock Timer Off */ +#define TSI148_LCSR_VCTRL_DLT_16 (1<<24) /* 16 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_32 (2<<24) /* 32 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_64 (3<<24) /* 64 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_128 (4<<24) /* 128 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_256 (5<<24) /* 256 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_512 (6<<24) /* 512 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_1024 (7<<24) /* 1024 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_2048 (8<<24) /* 2048 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_4096 (9<<24) /* 4096 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_8192 (0xA<<24) /* 8192 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_16384 (0xB<<24) /* 16384 VCLKS */ +#define TSI148_LCSR_VCTRL_DLT_32768 (0xC<<24) /* 32768 VCLKS */ + +#define TSI148_LCSR_VCTRL_NERBB (1<<20) /* No Early Release of Bus Busy */ + +#define TSI148_LCSR_VCTRL_SRESET (1<<17) /* System Reset */ +#define TSI148_LCSR_VCTRL_LRESET (1<<16) /* Local Reset */ + +#define TSI148_LCSR_VCTRL_SFAILAI (1<<15) /* SYSFAIL Auto Slot ID */ +#define TSI148_LCSR_VCTRL_BID_M (0x1F<<8) /* Broadcast ID Mask */ + +#define TSI148_LCSR_VCTRL_ATOEN (1<<7) /* Arbiter Time-out Enable */ +#define TSI148_LCSR_VCTRL_ROBIN (1<<6) /* VMEbus Round Robin */ + +#define TSI148_LCSR_VCTRL_GTO_M (7<<0) /* VMEbus Global Time-out Mask */ +#define TSI148_LCSR_VCTRL_GTO_8 (0<<0) /* 8 us */ +#define TSI148_LCSR_VCTRL_GTO_16 (1<<0) /* 16 us */ +#define TSI148_LCSR_VCTRL_GTO_32 (2<<0) /* 32 us */ +#define TSI148_LCSR_VCTRL_GTO_64 (3<<0) /* 64 us */ +#define TSI148_LCSR_VCTRL_GTO_128 (4<<0) /* 128 us */ +#define TSI148_LCSR_VCTRL_GTO_256 (5<<0) /* 256 us */ +#define TSI148_LCSR_VCTRL_GTO_512 (6<<0) /* 512 us */ +#define TSI148_LCSR_VCTRL_GTO_DIS (7<<0) /* Disabled */ + + /* + * VMEbus Status Register CRG + $23C + */ +#define TSI148_LCSR_VSTAT_CPURST (1<<15) /* Clear power up reset */ +#define TSI148_LCSR_VSTAT_BRDFL (1<<14) /* Board fail */ +#define TSI148_LCSR_VSTAT_PURSTS (1<<12) /* Power up reset status */ +#define TSI148_LCSR_VSTAT_BDFAILS (1<<11) /* Board Fail Status */ +#define TSI148_LCSR_VSTAT_SYSFAILS (1<<10) /* System Fail Status */ +#define TSI148_LCSR_VSTAT_ACFAILS (1<<9) /* AC fail status */ +#define TSI148_LCSR_VSTAT_SCONS (1<<8) /* System Cont Status */ +#define TSI148_LCSR_VSTAT_GAP (1<<5) /* Geographic Addr Parity */ +#define TSI148_LCSR_VSTAT_GA_M (0x1F<<0) /* Geographic Addr Mask */ + + /* + * PCI Configuration Status Register CRG+$240 + */ +#define TSI148_LCSR_PSTAT_REQ64S (1<<6) /* Request 64 status set */ +#define TSI148_LCSR_PSTAT_M66ENS (1<<5) /* M66ENS 66Mhz enable */ +#define TSI148_LCSR_PSTAT_FRAMES (1<<4) /* Frame Status */ +#define TSI148_LCSR_PSTAT_IRDYS (1<<3) /* IRDY status */ +#define TSI148_LCSR_PSTAT_DEVSELS (1<<2) /* DEVL status */ +#define TSI148_LCSR_PSTAT_STOPS (1<<1) /* STOP status */ +#define TSI148_LCSR_PSTAT_TRDYS (1<<0) /* TRDY status */ + + /* + * Inbound Translation Starting Address Lower + */ +#define TSI148_LCSR_ITSAL6432_M (0xFFFF<<16) /* Mask */ +#define TSI148_LCSR_ITSAL24_M (0x00FFF<<12) /* Mask */ +#define TSI148_LCSR_ITSAL16_M (0x0000FFF<<4) /* Mask */ + + /* + * Inbound Translation Ending Address Lower + */ +#define TSI148_LCSR_ITEAL6432_M (0xFFFF<<16) /* Mask */ +#define TSI148_LCSR_ITEAL24_M (0x00FFF<<12) /* Mask */ +#define TSI148_LCSR_ITEAL16_M (0x0000FFF<<4) /* Mask */ + + /* + * Inbound Translation Offset Lower + */ +#define TSI148_LCSR_ITOFFL6432_M (0xFFFF<<16) /* Mask */ +#define TSI148_LCSR_ITOFFL24_M (0xFFFFF<<12) /* Mask */ +#define TSI148_LCSR_ITOFFL16_M (0xFFFFFFF<<4) /* Mask */ + + /* + * Inbound Translation Attribute + */ +#define TSI148_LCSR_ITAT_EN (1<<31) /* Window Enable */ +#define TSI148_LCSR_ITAT_TH (1<<18) /* Prefetch Threshold */ + +#define TSI148_LCSR_ITAT_VFS_M (3<<16) /* Virtual FIFO Size Mask */ +#define TSI148_LCSR_ITAT_VFS_64 (0<<16) /* 64 bytes Virtual FIFO Size */ +#define TSI148_LCSR_ITAT_VFS_128 (1<<16) /* 128 bytes Virtual FIFO Sz */ +#define TSI148_LCSR_ITAT_VFS_256 (2<<16) /* 256 bytes Virtual FIFO Sz */ +#define TSI148_LCSR_ITAT_VFS_512 (3<<16) /* 512 bytes Virtual FIFO Sz */ + +#define TSI148_LCSR_ITAT_2eSSTM_M (7<<12) /* 2eSST Xfer Rate Mask */ +#define TSI148_LCSR_ITAT_2eSSTM_160 (0<<12) /* 160MB/s 2eSST Xfer Rate */ +#define TSI148_LCSR_ITAT_2eSSTM_267 (1<<12) /* 267MB/s 2eSST Xfer Rate */ +#define TSI148_LCSR_ITAT_2eSSTM_320 (2<<12) /* 320MB/s 2eSST Xfer Rate */ + +#define TSI148_LCSR_ITAT_2eSSTB (1<<11) /* 2eSST Bcast Xfer Protocol */ +#define TSI148_LCSR_ITAT_2eSST (1<<10) /* 2eSST Xfer Protocol */ +#define TSI148_LCSR_ITAT_2eVME (1<<9) /* 2eVME Xfer Protocol */ +#define TSI148_LCSR_ITAT_MBLT (1<<8) /* MBLT Xfer Protocol */ +#define TSI148_LCSR_ITAT_BLT (1<<7) /* BLT Xfer Protocol */ + +#define TSI148_LCSR_ITAT_AS_M (7<<4) /* Address Space Mask */ +#define TSI148_LCSR_ITAT_AS_A16 (0<<4) /* A16 Address Space */ +#define TSI148_LCSR_ITAT_AS_A24 (1<<4) /* A24 Address Space */ +#define TSI148_LCSR_ITAT_AS_A32 (2<<4) /* A32 Address Space */ +#define TSI148_LCSR_ITAT_AS_A64 (4<<4) /* A64 Address Space */ + +#define TSI148_LCSR_ITAT_SUPR (1<<3) /* Supervisor Access */ +#define TSI148_LCSR_ITAT_NPRIV (1<<2) /* Non-Priv (User) Access */ +#define TSI148_LCSR_ITAT_PGM (1<<1) /* Program Access */ +#define TSI148_LCSR_ITAT_DATA (1<<0) /* Data Access */ + + /* + * GCSR Base Address Lower Address CRG +$404 + */ +#define TSI148_LCSR_GBAL_M (0x7FFFFFF<<5) /* Mask */ + + /* + * GCSR Attribute Register CRG + $408 + */ +#define TSI148_LCSR_GCSRAT_EN (1<<7) /* Enable access to GCSR */ + +#define TSI148_LCSR_GCSRAT_AS_M (7<<4) /* Address Space Mask */ +#define TSI148_LCSR_GCSRAT_AS_16 (0<<4) /* Address Space 16 */ +#define TSI148_LCSR_GCSRAT_AS_24 (1<<4) /* Address Space 24 */ +#define TSI148_LCSR_GCSRAT_AS_32 (2<<4) /* Address Space 32 */ +#define TSI148_LCSR_GCSRAT_AS_64 (4<<4) /* Address Space 64 */ + +#define TSI148_LCSR_GCSRAT_SUPR (1<<3) /* Sup set -GCSR decoder */ +#define TSI148_LCSR_GCSRAT_NPRIV (1<<2) /* Non-Privliged set - CGSR */ +#define TSI148_LCSR_GCSRAT_PGM (1<<1) /* Program set - GCSR decoder */ +#define TSI148_LCSR_GCSRAT_DATA (1<<0) /* DATA set GCSR decoder */ + + /* + * CRG Base Address Lower Address CRG + $410 + */ +#define TSI148_LCSR_CBAL_M (0xFFFFF<<12) + + /* + * CRG Attribute Register CRG + $414 + */ +#define TSI148_LCSR_CRGAT_EN (1<<7) /* Enable PRG Access */ + +#define TSI148_LCSR_CRGAT_AS_M (7<<4) /* Address Space */ +#define TSI148_LCSR_CRGAT_AS_16 (0<<4) /* Address Space 16 */ +#define TSI148_LCSR_CRGAT_AS_24 (1<<4) /* Address Space 24 */ +#define TSI148_LCSR_CRGAT_AS_32 (2<<4) /* Address Space 32 */ +#define TSI148_LCSR_CRGAT_AS_64 (4<<4) /* Address Space 64 */ + +#define TSI148_LCSR_CRGAT_SUPR (1<<3) /* Supervisor Access */ +#define TSI148_LCSR_CRGAT_NPRIV (1<<2) /* Non-Privliged(User) Access */ +#define TSI148_LCSR_CRGAT_PGM (1<<1) /* Program Access */ +#define TSI148_LCSR_CRGAT_DATA (1<<0) /* Data Access */ + + /* + * CR/CSR Offset Lower Register CRG + $41C + */ +#define TSI148_LCSR_CROL_M (0x1FFF<<19) /* Mask */ + + /* + * CR/CSR Attribute register CRG + $420 + */ +#define TSI148_LCSR_CRAT_EN (1<<7) /* Enable access to CR/CSR */ + + /* + * Location Monitor base address lower register CRG + $428 + */ +#define TSI148_LCSR_LMBAL_M (0x7FFFFFF<<5) /* Mask */ + + /* + * Location Monitor Attribute Register CRG + $42C + */ +#define TSI148_LCSR_LMAT_EN (1<<7) /* Enable Location Monitor */ + +#define TSI148_LCSR_LMAT_AS_M (7<<4) /* Address Space MASK */ +#define TSI148_LCSR_LMAT_AS_16 (0<<4) /* A16 */ +#define TSI148_LCSR_LMAT_AS_24 (1<<4) /* A24 */ +#define TSI148_LCSR_LMAT_AS_32 (2<<4) /* A32 */ +#define TSI148_LCSR_LMAT_AS_64 (4<<4) /* A64 */ + +#define TSI148_LCSR_LMAT_SUPR (1<<3) /* Supervisor Access */ +#define TSI148_LCSR_LMAT_NPRIV (1<<2) /* Non-Priv (User) Access */ +#define TSI148_LCSR_LMAT_PGM (1<<1) /* Program Access */ +#define TSI148_LCSR_LMAT_DATA (1<<0) /* Data Access */ + + /* + * Broadcast Pulse Generator Timer Register CRG + $438 + */ +#define TSI148_LCSR_BPGTR_BPGT_M (0xFFFF<<0) /* Mask */ + + /* + * Broadcast Programmable Clock Timer Register CRG + $43C + */ +#define TSI148_LCSR_BPCTR_BPCT_M (0xFFFFFF<<0) /* Mask */ + + /* + * VMEbus Interrupt Control Register CRG + $43C + */ +#define TSI148_LCSR_VICR_CNTS_M (3<<22) /* Cntr Source MASK */ +#define TSI148_LCSR_VICR_CNTS_DIS (1<<22) /* Cntr Disable */ +#define TSI148_LCSR_VICR_CNTS_IRQ1 (2<<22) /* IRQ1 to Cntr */ +#define TSI148_LCSR_VICR_CNTS_IRQ2 (3<<22) /* IRQ2 to Cntr */ + +#define TSI148_LCSR_VICR_EDGIS_M (3<<20) /* Edge interupt MASK */ +#define TSI148_LCSR_VICR_EDGIS_DIS (1<<20) /* Edge interupt Disable */ +#define TSI148_LCSR_VICR_EDGIS_IRQ1 (2<<20) /* IRQ1 to Edge */ +#define TSI148_LCSR_VICR_EDGIS_IRQ2 (3<<20) /* IRQ2 to Edge */ + +#define TSI148_LCSR_VICR_IRQIF_M (3<<18) /* IRQ1* Function MASK */ +#define TSI148_LCSR_VICR_IRQIF_NORM (1<<18) /* Normal */ +#define TSI148_LCSR_VICR_IRQIF_PULSE (2<<18) /* Pulse Generator */ +#define TSI148_LCSR_VICR_IRQIF_PROG (3<<18) /* Programmable Clock */ +#define TSI148_LCSR_VICR_IRQIF_1U (4<<18) /* 1us Clock */ + +#define TSI148_LCSR_VICR_IRQ2F_M (3<<16) /* IRQ2* Function MASK */ +#define TSI148_LCSR_VICR_IRQ2F_NORM (1<<16) /* Normal */ +#define TSI148_LCSR_VICR_IRQ2F_PULSE (2<<16) /* Pulse Generator */ +#define TSI148_LCSR_VICR_IRQ2F_PROG (3<<16) /* Programmable Clock */ +#define TSI148_LCSR_VICR_IRQ2F_1U (4<<16) /* 1us Clock */ + +#define TSI148_LCSR_VICR_BIP (1<<15) /* Broadcast Interrupt Pulse */ + +#define TSI148_LCSR_VICR_IRQC (1<<12) /* VMEbus IRQ Clear */ +#define TSI148_LCSR_VICR_IRQS (1<<11) /* VMEbus IRQ Status */ + +#define TSI148_LCSR_VICR_IRQL_M (7<<8) /* VMEbus SW IRQ Level Mask */ +#define TSI148_LCSR_VICR_IRQL_1 (1<<8) /* VMEbus SW IRQ Level 1 */ +#define TSI148_LCSR_VICR_IRQL_2 (2<<8) /* VMEbus SW IRQ Level 2 */ +#define TSI148_LCSR_VICR_IRQL_3 (3<<8) /* VMEbus SW IRQ Level 3 */ +#define TSI148_LCSR_VICR_IRQL_4 (4<<8) /* VMEbus SW IRQ Level 4 */ +#define TSI148_LCSR_VICR_IRQL_5 (5<<8) /* VMEbus SW IRQ Level 5 */ +#define TSI148_LCSR_VICR_IRQL_6 (6<<8) /* VMEbus SW IRQ Level 6 */ +#define TSI148_LCSR_VICR_IRQL_7 (7<<8) /* VMEbus SW IRQ Level 7 */ + +#define TSI148_LCSR_VICR_STID_M (0xFF<<0) /* Status/ID Mask */ + + /* + * Interrupt Enable Register CRG + $440 + */ +#define TSI148_LCSR_INTEN_DMA1EN (1<<25) /* DMAC 1 */ +#define TSI148_LCSR_INTEN_DMA0EN (1<<24) /* DMAC 0 */ +#define TSI148_LCSR_INTEN_LM3EN (1<<23) /* Location Monitor 3 */ +#define TSI148_LCSR_INTEN_LM2EN (1<<22) /* Location Monitor 2 */ +#define TSI148_LCSR_INTEN_LM1EN (1<<21) /* Location Monitor 1 */ +#define TSI148_LCSR_INTEN_LM0EN (1<<20) /* Location Monitor 0 */ +#define TSI148_LCSR_INTEN_MB3EN (1<<19) /* Mail Box 3 */ +#define TSI148_LCSR_INTEN_MB2EN (1<<18) /* Mail Box 2 */ +#define TSI148_LCSR_INTEN_MB1EN (1<<17) /* Mail Box 1 */ +#define TSI148_LCSR_INTEN_MB0EN (1<<16) /* Mail Box 0 */ +#define TSI148_LCSR_INTEN_VBEREN (1<<13) /* VMEbus Error */ +#define TSI148_LCSR_INTEN_VATOEN (1<<12) /* VMEbus Access Time-out */ +#define TSI148_LCSR_INTEN_VIEEN (1<<11) /* VMEbus IRQ Edge */ +#define TSI148_LCSR_INTEN_IACKEN (1<<10) /* IACK */ +#define TSI148_LCSR_INTEN_SYSFLEN (1<<9) /* System Fail */ +#define TSI148_LCSR_INTEN_ACFLEN (1<<8) /* AC Fail */ +#define TSI148_LCSR_INTEN_IRQ7EN (1<<7) /* IRQ7 */ +#define TSI148_LCSR_INTEN_IRQ6EN (1<<6) /* IRQ6 */ +#define TSI148_LCSR_INTEN_IRQ5EN (1<<5) /* IRQ5 */ +#define TSI148_LCSR_INTEN_IRQ4EN (1<<4) /* IRQ4 */ +#define TSI148_LCSR_INTEN_IRQ3EN (1<<3) /* IRQ3 */ +#define TSI148_LCSR_INTEN_IRQ2EN (1<<2) /* IRQ2 */ +#define TSI148_LCSR_INTEN_IRQ1EN (1<<1) /* IRQ1 */ + + /* + * Interrupt Enable Out Register CRG + $444 + */ +#define TSI148_LCSR_INTEO_DMA1EO (1<<25) /* DMAC 1 */ +#define TSI148_LCSR_INTEO_DMA0EO (1<<24) /* DMAC 0 */ +#define TSI148_LCSR_INTEO_LM3EO (1<<23) /* Loc Monitor 3 */ +#define TSI148_LCSR_INTEO_LM2EO (1<<22) /* Loc Monitor 2 */ +#define TSI148_LCSR_INTEO_LM1EO (1<<21) /* Loc Monitor 1 */ +#define TSI148_LCSR_INTEO_LM0EO (1<<20) /* Location Monitor 0 */ +#define TSI148_LCSR_INTEO_MB3EO (1<<19) /* Mail Box 3 */ +#define TSI148_LCSR_INTEO_MB2EO (1<<18) /* Mail Box 2 */ +#define TSI148_LCSR_INTEO_MB1EO (1<<17) /* Mail Box 1 */ +#define TSI148_LCSR_INTEO_MB0EO (1<<16) /* Mail Box 0 */ +#define TSI148_LCSR_INTEO_VBEREO (1<<13) /* VMEbus Error */ +#define TSI148_LCSR_INTEO_VATOEO (1<<12) /* VMEbus Access Time-out */ +#define TSI148_LCSR_INTEO_VIEEO (1<<11) /* VMEbus IRQ Edge */ +#define TSI148_LCSR_INTEO_IACKEO (1<<10) /* IACK */ +#define TSI148_LCSR_INTEO_SYSFLEO (1<<9) /* System Fail */ +#define TSI148_LCSR_INTEO_ACFLEO (1<<8) /* AC Fail */ +#define TSI148_LCSR_INTEO_IRQ7EO (1<<7) /* IRQ7 */ +#define TSI148_LCSR_INTEO_IRQ6EO (1<<6) /* IRQ6 */ +#define TSI148_LCSR_INTEO_IRQ5EO (1<<5) /* IRQ5 */ +#define TSI148_LCSR_INTEO_IRQ4EO (1<<4) /* IRQ4 */ +#define TSI148_LCSR_INTEO_IRQ3EO (1<<3) /* IRQ3 */ +#define TSI148_LCSR_INTEO_IRQ2EO (1<<2) /* IRQ2 */ +#define TSI148_LCSR_INTEO_IRQ1EO (1<<1) /* IRQ1 */ + + /* + * Interrupt Status Register CRG + $448 + */ +#define TSI148_LCSR_INTS_DMA1S (1<<25) /* DMA 1 */ +#define TSI148_LCSR_INTS_DMA0S (1<<24) /* DMA 0 */ +#define TSI148_LCSR_INTS_LM3S (1<<23) /* Location Monitor 3 */ +#define TSI148_LCSR_INTS_LM2S (1<<22) /* Location Monitor 2 */ +#define TSI148_LCSR_INTS_LM1S (1<<21) /* Location Monitor 1 */ +#define TSI148_LCSR_INTS_LM0S (1<<20) /* Location Monitor 0 */ +#define TSI148_LCSR_INTS_MB3S (1<<19) /* Mail Box 3 */ +#define TSI148_LCSR_INTS_MB2S (1<<18) /* Mail Box 2 */ +#define TSI148_LCSR_INTS_MB1S (1<<17) /* Mail Box 1 */ +#define TSI148_LCSR_INTS_MB0S (1<<16) /* Mail Box 0 */ +#define TSI148_LCSR_INTS_VBERS (1<<13) /* VMEbus Error */ +#define TSI148_LCSR_INTS_VATOS (1<<12) /* VMEbus Access Time-out */ +#define TSI148_LCSR_INTS_VIES (1<<11) /* VMEbus IRQ Edge */ +#define TSI148_LCSR_INTS_IACKS (1<<10) /* IACK */ +#define TSI148_LCSR_INTS_SYSFLS (1<<9) /* System Fail */ +#define TSI148_LCSR_INTS_ACFLS (1<<8) /* AC Fail */ +#define TSI148_LCSR_INTS_IRQ7S (1<<7) /* IRQ7 */ +#define TSI148_LCSR_INTS_IRQ6S (1<<6) /* IRQ6 */ +#define TSI148_LCSR_INTS_IRQ5S (1<<5) /* IRQ5 */ +#define TSI148_LCSR_INTS_IRQ4S (1<<4) /* IRQ4 */ +#define TSI148_LCSR_INTS_IRQ3S (1<<3) /* IRQ3 */ +#define TSI148_LCSR_INTS_IRQ2S (1<<2) /* IRQ2 */ +#define TSI148_LCSR_INTS_IRQ1S (1<<1) /* IRQ1 */ + + /* + * Interrupt Clear Register CRG + $44C + */ +#define TSI148_LCSR_INTC_DMA1C (1<<25) /* DMA 1 */ +#define TSI148_LCSR_INTC_DMA0C (1<<24) /* DMA 0 */ +#define TSI148_LCSR_INTC_LM3C (1<<23) /* Location Monitor 3 */ +#define TSI148_LCSR_INTC_LM2C (1<<22) /* Location Monitor 2 */ +#define TSI148_LCSR_INTC_LM1C (1<<21) /* Location Monitor 1 */ +#define TSI148_LCSR_INTC_LM0C (1<<20) /* Location Monitor 0 */ +#define TSI148_LCSR_INTC_MB3C (1<<19) /* Mail Box 3 */ +#define TSI148_LCSR_INTC_MB2C (1<<18) /* Mail Box 2 */ +#define TSI148_LCSR_INTC_MB1C (1<<17) /* Mail Box 1 */ +#define TSI148_LCSR_INTC_MB0C (1<<16) /* Mail Box 0 */ +#define TSI148_LCSR_INTC_VBERC (1<<13) /* VMEbus Error */ +#define TSI148_LCSR_INTC_VATOC (1<<12) /* VMEbus Access Time-out */ +#define TSI148_LCSR_INTC_VIEC (1<<11) /* VMEbus IRQ Edge */ +#define TSI148_LCSR_INTC_IACKC (1<<10) /* IACK */ +#define TSI148_LCSR_INTC_SYSFLC (1<<9) /* System Fail */ +#define TSI148_LCSR_INTC_ACFLC (1<<8) /* AC Fail */ + + /* + * Interrupt Map Register 1 CRG + $458 + */ +#define TSI148_LCSR_INTM1_DMA1M_M (3<<18) /* DMA 1 */ +#define TSI148_LCSR_INTM1_DMA0M_M (3<<16) /* DMA 0 */ +#define TSI148_LCSR_INTM1_LM3M_M (3<<14) /* Location Monitor 3 */ +#define TSI148_LCSR_INTM1_LM2M_M (3<<12) /* Location Monitor 2 */ +#define TSI148_LCSR_INTM1_LM1M_M (3<<10) /* Location Monitor 1 */ +#define TSI148_LCSR_INTM1_LM0M_M (3<<8) /* Location Monitor 0 */ +#define TSI148_LCSR_INTM1_MB3M_M (3<<6) /* Mail Box 3 */ +#define TSI148_LCSR_INTM1_MB2M_M (3<<4) /* Mail Box 2 */ +#define TSI148_LCSR_INTM1_MB1M_M (3<<2) /* Mail Box 1 */ +#define TSI148_LCSR_INTM1_MB0M_M (3<<0) /* Mail Box 0 */ + + /* + * Interrupt Map Register 2 CRG + $45C + */ +#define TSI148_LCSR_INTM2_PERRM_M (3<<26) /* PCI Bus Error */ +#define TSI148_LCSR_INTM2_VERRM_M (3<<24) /* VMEbus Error */ +#define TSI148_LCSR_INTM2_VIEM_M (3<<22) /* VMEbus IRQ Edge */ +#define TSI148_LCSR_INTM2_IACKM_M (3<<20) /* IACK */ +#define TSI148_LCSR_INTM2_SYSFLM_M (3<<18) /* System Fail */ +#define TSI148_LCSR_INTM2_ACFLM_M (3<<16) /* AC Fail */ +#define TSI148_LCSR_INTM2_IRQ7M_M (3<<14) /* IRQ7 */ +#define TSI148_LCSR_INTM2_IRQ6M_M (3<<12) /* IRQ6 */ +#define TSI148_LCSR_INTM2_IRQ5M_M (3<<10) /* IRQ5 */ +#define TSI148_LCSR_INTM2_IRQ4M_M (3<<8) /* IRQ4 */ +#define TSI148_LCSR_INTM2_IRQ3M_M (3<<6) /* IRQ3 */ +#define TSI148_LCSR_INTM2_IRQ2M_M (3<<4) /* IRQ2 */ +#define TSI148_LCSR_INTM2_IRQ1M_M (3<<2) /* IRQ1 */ + + /* + * DMA Control (0-1) Registers CRG + $500 + */ +#define TSI148_LCSR_DCTL_ABT (1<<27) /* Abort */ +#define TSI148_LCSR_DCTL_PAU (1<<26) /* Pause */ +#define TSI148_LCSR_DCTL_DGO (1<<25) /* DMA Go */ + +#define TSI148_LCSR_DCTL_MOD (1<<23) /* Mode */ + +#define TSI148_LCSR_DCTL_VBKS_M (7<<12) /* VMEbus block Size MASK */ +#define TSI148_LCSR_DCTL_VBKS_32 (0<<12) /* VMEbus block Size 32 */ +#define TSI148_LCSR_DCTL_VBKS_64 (1<<12) /* VMEbus block Size 64 */ +#define TSI148_LCSR_DCTL_VBKS_128 (2<<12) /* VMEbus block Size 128 */ +#define TSI148_LCSR_DCTL_VBKS_256 (3<<12) /* VMEbus block Size 256 */ +#define TSI148_LCSR_DCTL_VBKS_512 (4<<12) /* VMEbus block Size 512 */ +#define TSI148_LCSR_DCTL_VBKS_1024 (5<<12) /* VMEbus block Size 1024 */ +#define TSI148_LCSR_DCTL_VBKS_2048 (6<<12) /* VMEbus block Size 2048 */ +#define TSI148_LCSR_DCTL_VBKS_4096 (7<<12) /* VMEbus block Size 4096 */ + +#define TSI148_LCSR_DCTL_VBOT_M (7<<8) /* VMEbus back-off MASK */ +#define TSI148_LCSR_DCTL_VBOT_0 (0<<8) /* VMEbus back-off 0us */ +#define TSI148_LCSR_DCTL_VBOT_1 (1<<8) /* VMEbus back-off 1us */ +#define TSI148_LCSR_DCTL_VBOT_2 (2<<8) /* VMEbus back-off 2us */ +#define TSI148_LCSR_DCTL_VBOT_4 (3<<8) /* VMEbus back-off 4us */ +#define TSI148_LCSR_DCTL_VBOT_8 (4<<8) /* VMEbus back-off 8us */ +#define TSI148_LCSR_DCTL_VBOT_16 (5<<8) /* VMEbus back-off 16us */ +#define TSI148_LCSR_DCTL_VBOT_32 (6<<8) /* VMEbus back-off 32us */ +#define TSI148_LCSR_DCTL_VBOT_64 (7<<8) /* VMEbus back-off 64us */ + +#define TSI148_LCSR_DCTL_PBKS_M (7<<4) /* PCI block size MASK */ +#define TSI148_LCSR_DCTL_PBKS_32 (0<<4) /* PCI block size 32 bytes */ +#define TSI148_LCSR_DCTL_PBKS_64 (1<<4) /* PCI block size 64 bytes */ +#define TSI148_LCSR_DCTL_PBKS_128 (2<<4) /* PCI block size 128 bytes */ +#define TSI148_LCSR_DCTL_PBKS_256 (3<<4) /* PCI block size 256 bytes */ +#define TSI148_LCSR_DCTL_PBKS_512 (4<<4) /* PCI block size 512 bytes */ +#define TSI148_LCSR_DCTL_PBKS_1024 (5<<4) /* PCI block size 1024 bytes */ +#define TSI148_LCSR_DCTL_PBKS_2048 (6<<4) /* PCI block size 2048 bytes */ +#define TSI148_LCSR_DCTL_PBKS_4096 (7<<4) /* PCI block size 4096 bytes */ + +#define TSI148_LCSR_DCTL_PBOT_M (7<<0) /* PCI back off MASK */ +#define TSI148_LCSR_DCTL_PBOT_0 (0<<0) /* PCI back off 0us */ +#define TSI148_LCSR_DCTL_PBOT_1 (1<<0) /* PCI back off 1us */ +#define TSI148_LCSR_DCTL_PBOT_2 (2<<0) /* PCI back off 2us */ +#define TSI148_LCSR_DCTL_PBOT_4 (3<<0) /* PCI back off 3us */ +#define TSI148_LCSR_DCTL_PBOT_8 (4<<0) /* PCI back off 4us */ +#define TSI148_LCSR_DCTL_PBOT_16 (5<<0) /* PCI back off 8us */ +#define TSI148_LCSR_DCTL_PBOT_32 (6<<0) /* PCI back off 16us */ +#define TSI148_LCSR_DCTL_PBOT_64 (7<<0) /* PCI back off 32us */ + + /* + * DMA Status Registers (0-1) CRG + $504 + */ +#define TSI148_LCSR_DSTA_SMA (1<<31) /* PCI Signalled Master Abt */ +#define TSI148_LCSR_DSTA_RTA (1<<30) /* PCI Received Target Abt */ +#define TSI148_LCSR_DSTA_MRC (1<<29) /* PCI Max Retry Count */ +#define TSI148_LCSR_DSTA_VBE (1<<28) /* VMEbus error */ +#define TSI148_LCSR_DSTA_ABT (1<<27) /* Abort */ +#define TSI148_LCSR_DSTA_PAU (1<<26) /* Pause */ +#define TSI148_LCSR_DSTA_DON (1<<25) /* Done */ +#define TSI148_LCSR_DSTA_BSY (1<<24) /* Busy */ + + /* + * DMA Current Link Address Lower (0-1) + */ +#define TSI148_LCSR_DCLAL_M (0x3FFFFFF<<6) /* Mask */ + + /* + * DMA Source Attribute (0-1) Reg + */ +#define TSI148_LCSR_DSAT_TYP_M (3<<28) /* Source Bus Type */ +#define TSI148_LCSR_DSAT_TYP_PCI (0<<28) /* PCI Bus */ +#define TSI148_LCSR_DSAT_TYP_VME (1<<28) /* VMEbus */ +#define TSI148_LCSR_DSAT_TYP_PAT (2<<28) /* Data Pattern */ + +#define TSI148_LCSR_DSAT_PSZ (1<<25) /* Pattern Size */ +#define TSI148_LCSR_DSAT_NIN (1<<24) /* No Increment */ + +#define TSI148_LCSR_DSAT_2eSSTM_M (3<<11) /* 2eSST Trans Rate Mask */ +#define TSI148_LCSR_DSAT_2eSSTM_160 (0<<11) /* 160 MB/s */ +#define TSI148_LCSR_DSAT_2eSSTM_267 (1<<11) /* 267 MB/s */ +#define TSI148_LCSR_DSAT_2eSSTM_320 (2<<11) /* 320 MB/s */ + +#define TSI148_LCSR_DSAT_TM_M (7<<8) /* Bus Transfer Protocol Mask */ +#define TSI148_LCSR_DSAT_TM_SCT (0<<8) /* SCT */ +#define TSI148_LCSR_DSAT_TM_BLT (1<<8) /* BLT */ +#define TSI148_LCSR_DSAT_TM_MBLT (2<<8) /* MBLT */ +#define TSI148_LCSR_DSAT_TM_2eVME (3<<8) /* 2eVME */ +#define TSI148_LCSR_DSAT_TM_2eSST (4<<8) /* 2eSST */ +#define TSI148_LCSR_DSAT_TM_2eSSTB (5<<8) /* 2eSST Broadcast */ + +#define TSI148_LCSR_DSAT_DBW_M (3<<6) /* Max Data Width MASK */ +#define TSI148_LCSR_DSAT_DBW_16 (0<<6) /* 16 Bits */ +#define TSI148_LCSR_DSAT_DBW_32 (1<<6) /* 32 Bits */ + +#define TSI148_LCSR_DSAT_SUP (1<<5) /* Supervisory Mode */ +#define TSI148_LCSR_DSAT_PGM (1<<4) /* Program Mode */ + +#define TSI148_LCSR_DSAT_AMODE_M (0xf<<0) /* Address Space Mask */ +#define TSI148_LCSR_DSAT_AMODE_16 (0<<0) /* A16 */ +#define TSI148_LCSR_DSAT_AMODE_24 (1<<0) /* A24 */ +#define TSI148_LCSR_DSAT_AMODE_32 (2<<0) /* A32 */ +#define TSI148_LCSR_DSAT_AMODE_64 (4<<0) /* A64 */ +#define TSI148_LCSR_DSAT_AMODE_CRCSR (5<<0) /* CR/CSR */ +#define TSI148_LCSR_DSAT_AMODE_USER1 (8<<0) /* User1 */ +#define TSI148_LCSR_DSAT_AMODE_USER2 (9<<0) /* User2 */ +#define TSI148_LCSR_DSAT_AMODE_USER3 (0xa<<0) /* User3 */ +#define TSI148_LCSR_DSAT_AMODE_USER4 (0xb<<0) /* User4 */ + + /* + * DMA Destination Attribute Registers (0-1) + */ +#define TSI148_LCSR_DDAT_TYP_VME (1<<28) /* Destination VMEbus */ +#define TSI148_LCSR_DDAT_TYP_PCI (0<<28) /* Destination PCI Bus */ + +#define TSI148_LCSR_DDAT_NIN (1<<24) /* No Increment */ + +#define TSI148_LCSR_DDAT_2eSSTM_M (3<<11) /* 2eSST Transfer Rate Mask */ +#define TSI148_LCSR_DDAT_2eSSTM_160 (0<<11) /* 160 MB/s */ +#define TSI148_LCSR_DDAT_2eSSTM_267 (1<<11) /* 267 MB/s */ +#define TSI148_LCSR_DDAT_2eSSTM_320 (2<<11) /* 320 MB/s */ + +#define TSI148_LCSR_DDAT_TM_M (7<<8) /* Bus Transfer Protocol Mask */ +#define TSI148_LCSR_DDAT_TM_SCT (0<<8) /* SCT */ +#define TSI148_LCSR_DDAT_TM_BLT (1<<8) /* BLT */ +#define TSI148_LCSR_DDAT_TM_MBLT (2<<8) /* MBLT */ +#define TSI148_LCSR_DDAT_TM_2eVME (3<<8) /* 2eVME */ +#define TSI148_LCSR_DDAT_TM_2eSST (4<<8) /* 2eSST */ +#define TSI148_LCSR_DDAT_TM_2eSSTB (5<<8) /* 2eSST Broadcast */ + +#define TSI148_LCSR_DDAT_DBW_M (3<<6) /* Max Data Width MASK */ +#define TSI148_LCSR_DDAT_DBW_16 (0<<6) /* 16 Bits */ +#define TSI148_LCSR_DDAT_DBW_32 (1<<6) /* 32 Bits */ + +#define TSI148_LCSR_DDAT_SUP (1<<5) /* Supervisory/User Access */ +#define TSI148_LCSR_DDAT_PGM (1<<4) /* Program/Data Access */ + +#define TSI148_LCSR_DDAT_AMODE_M (0xf<<0) /* Address Space Mask */ +#define TSI148_LCSR_DDAT_AMODE_16 (0<<0) /* A16 */ +#define TSI148_LCSR_DDAT_AMODE_24 (1<<0) /* A24 */ +#define TSI148_LCSR_DDAT_AMODE_32 (2<<0) /* A32 */ +#define TSI148_LCSR_DDAT_AMODE_64 (4<<0) /* A64 */ +#define TSI148_LCSR_DDAT_AMODE_CRCSR (5<<0) /* CRC/SR */ +#define TSI148_LCSR_DDAT_AMODE_USER1 (8<<0) /* User1 */ +#define TSI148_LCSR_DDAT_AMODE_USER2 (9<<0) /* User2 */ +#define TSI148_LCSR_DDAT_AMODE_USER3 (0xA<<0) /* User3 */ +#define TSI148_LCSR_DDAT_AMODE_USER4 (0xB<<0) /* User4 */ + + /* + * DMA Next Link Address Lower + */ +#define TSI148_LCSR_DNLAL_DNLAL_M (0x3FFFFFF<<6) /* Address Mask */ +#define TSI148_LCSR_DNLAL_LLA (1<<0) /* Last Link Address Indicator */ + + /* + * DMA 2eSST Broadcast Select + */ +#define TSI148_LCSR_DBS_M (0x1FFFFF<<0) /* Mask */ + + /* + * GCSR Register Group + */ + + /* + * GCSR Control and Status Register CRG + $604 + */ +#define TSI148_GCSR_GCTRL_LRST (1<<15) /* Local Reset */ +#define TSI148_GCSR_GCTRL_SFAILEN (1<<14) /* System Fail enable */ +#define TSI148_GCSR_GCTRL_BDFAILS (1<<13) /* Board Fail Status */ +#define TSI148_GCSR_GCTRL_SCON (1<<12) /* System Copntroller */ +#define TSI148_GCSR_GCTRL_MEN (1<<11) /* Module Enable (READY) */ + +#define TSI148_GCSR_GCTRL_LMI3S (1<<7) /* Loc Monitor 3 Int Status */ +#define TSI148_GCSR_GCTRL_LMI2S (1<<6) /* Loc Monitor 2 Int Status */ +#define TSI148_GCSR_GCTRL_LMI1S (1<<5) /* Loc Monitor 1 Int Status */ +#define TSI148_GCSR_GCTRL_LMI0S (1<<4) /* Loc Monitor 0 Int Status */ +#define TSI148_GCSR_GCTRL_MBI3S (1<<3) /* Mail box 3 Int Status */ +#define TSI148_GCSR_GCTRL_MBI2S (1<<2) /* Mail box 2 Int Status */ +#define TSI148_GCSR_GCTRL_MBI1S (1<<1) /* Mail box 1 Int Status */ +#define TSI148_GCSR_GCTRL_MBI0S (1<<0) /* Mail box 0 Int Status */ + +#define TSI148_GCSR_GAP (1<<5) /* Geographic Addr Parity */ +#define TSI148_GCSR_GA_M (0x1F<<0) /* Geographic Address Mask */ + + /* + * CR/CSR Register Group + */ + + /* + * CR/CSR Bit Clear Register CRG + $FF4 + */ +#define TSI148_CRCSR_CSRBCR_LRSTC (1<<7) /* Local Reset Clear */ +#define TSI148_CRCSR_CSRBCR_SFAILC (1<<6) /* System Fail Enable Clear */ +#define TSI148_CRCSR_CSRBCR_BDFAILS (1<<5) /* Board Fail Status */ +#define TSI148_CRCSR_CSRBCR_MENC (1<<4) /* Module Enable Clear */ +#define TSI148_CRCSR_CSRBCR_BERRSC (1<<3) /* Bus Error Status Clear */ + + /* + * CR/CSR Bit Set Register CRG+$FF8 + */ +#define TSI148_CRCSR_CSRBSR_LISTS (1<<7) /* Local Reset Clear */ +#define TSI148_CRCSR_CSRBSR_SFAILS (1<<6) /* System Fail Enable Clear */ +#define TSI148_CRCSR_CSRBSR_BDFAILS (1<<5) /* Board Fail Status */ +#define TSI148_CRCSR_CSRBSR_MENS (1<<4) /* Module Enable Clear */ +#define TSI148_CRCSR_CSRBSR_BERRS (1<<3) /* Bus Error Status Clear */ + + /* + * CR/CSR Base Address Register CRG + FFC + */ +#define TSI148_CRCSR_CBAR_M (0x1F<<3) /* Mask */ + +#endif /* TSI148_H */ diff -u --new-file --recursive linux-2.6.14.orig/drivers/vme/vmedrv.c linux-2.6.14.mod/drivers/vme/vmedrv.c --- linux-2.6.14.orig/drivers/vme/vmedrv.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/vme/vmedrv.c 2006-06-13 13:34:27.000000000 -0700 @@ -0,0 +1,769 @@ +/* + * vmedrv.c + * + * Provided generic (non bridge specific) entry-points. The entry-points + * call CA91C042 or TSI148 specific routines and return the result. + * + * Author: Tom Armistead + * Updated and maintained by Ajit Prem + * + * Copyright 2004 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vmedrv.h" +#include "ca91c042.h" + +extern struct resource *vmepcimem; +extern struct pci_dev *vme_pci_dev; + +/* Global VME controller information */ +int vmechip_irq; // PCI irq +int vmechip_irq_overhead_ticks; // Interrupt overhead +int vmechip_devid; // PCI devID +int vmeparent_devid; // VME bridge parent ID +int vmechip_revision; // PCI revision +int vmechip_bus; // PCI bus number. +char *vmechip_baseaddr; // virtual address of chip registers +int vme_slotnum = -1; // VME slot num (-1 = unknown) +int vme_syscon = -1; // VME sys controller (-1 = unknown) + +/* address of board data */ +extern struct vmeSharedData *vmechip_interboard_data; + +extern struct resource out_resource[VME_MAX_WINDOWS]; +unsigned int out_image_va[VME_MAX_WINDOWS]; // Base virtual address + +/* + * External functions + */ +extern int uni_init(void *); +extern void uni_shutdown(void); +extern int uni_set_arbiter(vmeArbiterCfg_t * vmeArb); +extern int uni_get_arbiter(vmeArbiterCfg_t * vmeArb); +extern int uni_set_requestor(vmeRequesterCfg_t * vmeReq); +extern int uni_get_requestor(vmeRequesterCfg_t * vmeReq); +extern int uni_set_in_bound(vmeInWindowCfg_t * vmeIn); +extern int uni_get_in_bound(vmeInWindowCfg_t * vmeIn); +extern int uni_set_out_bound(vmeOutWindowCfg_t * vmeOut); +extern int uni_get_out_bound(vmeOutWindowCfg_t * vmeOut); +extern int uni_setup_lm(vmeLmCfg_t * vmeLm); +extern int uni_wait_lm(vmeLmCfg_t * vmeLm); +extern int uni_do_rmw(vmeRmwCfg_t * vmeRmw); +extern int uni_do_dma(vmeDmaPacket_t * vmeDma); +extern int uni_generate_irq(virqInfo_t *); +extern int uni_bus_error_chk(int); + +extern int tempe_init(void *); +extern void tempe_shutdown(void); +extern int tempe_set_arbiter(vmeArbiterCfg_t * vmeArb); +extern int tempe_get_arbiter(vmeArbiterCfg_t * vmeArb); +extern int tempe_set_requestor(vmeRequesterCfg_t * vmeReq); +extern int tempe_get_requestor(vmeRequesterCfg_t * vmeReq); +extern int tempe_set_in_bound(vmeInWindowCfg_t * vmeIn); +extern int tempe_get_in_bound(vmeInWindowCfg_t * vmeIn); +extern int tempe_set_out_bound(vmeOutWindowCfg_t * vmeOut); +extern int tempe_get_out_bound(vmeOutWindowCfg_t * vmeOut); +extern int tempe_setup_lm(vmeLmCfg_t * vmeLm); +extern int tempe_wait_lm(vmeLmCfg_t * vmeLm); +extern int tempe_do_rmw(vmeRmwCfg_t * vmeRmw); +extern int tempe_do_dma(vmeDmaPacket_t * vmeDma); +extern int tempe_generate_irq(virqInfo_t *); +extern int tempe_bus_error_chk(int); + +int vme_irqlog[8][0x100]; + +//---------------------------------------------------------------------------- +// Some kernels don't supply pci_bus_mem_base_phys()... this subroutine +// provides that functionality. +//---------------------------------------------------------------------------- + +#ifdef SIMPCIMEMBASE +unsigned int pci_bus_mem_base_phys_val = 0; + +unsigned int pci_bus_mem_base_phys(int bus) +{ + return (pci_bus_mem_base_phys_val); +} +#endif + +//---------------------------------------------------------------------------- +// vme_sync_data() +// Ensure completion of all previously issued loads/stores +//---------------------------------------------------------------------------- +void vme_sync_data(void) +{ + asm("sync"); // PPC specific. + asm("eieio"); +} + +//---------------------------------------------------------------------------- +// vme_flush_line(void *ptr) +// Flush & invalidate a cache line +//---------------------------------------------------------------------------- +void vme_flush_line(void *ptr) +{ +#ifdef CONFIG_MVME6100 + asm("dcbf 0,3"); // PPC specific. + asm("sync"); // PPC specific. +#endif +} + +//---------------------------------------------------------------------------- +// vme_flush_range() +// Flush & invalidate a range of memory +//---------------------------------------------------------------------------- +void vme_flush_range(char *start, char *end) +{ +#ifdef CONFIG_MVME6100 + while (start < end) { + vme_flush_line(start); + start += LINESIZE; + } +#endif +} + +//---------------------------------------------------------------------------- +// vme_bus_error_chk() +// Return 1 if VME bus error occured, 0 otherwise. +// Optionally clear VME bus error status. +//---------------------------------------------------------------------------- +int vme_bus_error_chk(int clrflag) +{ + vme_sync_data(); + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_bus_error_chk(clrflag)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_bus_error_chk(clrflag)); + break; + } + return (0); +} + +//---------------------------------------------------------------------------- +// vme_get_slot_num +// Determine the slot number that we are in. Uses CR/CSR base +// address reg if it contains a valid value. If not, obtains +// slot number from board level register. +//---------------------------------------------------------------------------- +int vme_get_slot_num(void) +{ + int slotnum = 0; + + // get slot num from VME chip reg if it is set. + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + slotnum = readl(vmechip_baseaddr + VCSR_BS); + slotnum = (slotnum >> 27) & 0x1F; + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + slotnum = *(int *)(vmechip_baseaddr + 0x23C); + slotnum = slotnum & 0x1F; + return (slotnum); + break; + } + + // Following is board specific!! + +#ifdef MCG_MVME2600 + if (slotnum == 0) + slotnum = ~inb(0x1006) & 0x1F; // Genesis2 slot register +#endif +#ifdef MCG_MVME2400 + if (slotnum == 0) + slotnum = ~inb(0x1006) & 0x1F; // Genesis2 slot register +#endif +#ifdef MCG_MVME2300 + if (slotnum == 0) + slotnum = ~inb(0x1006) & 0x1F; // Genesis2 slot register +#endif + + return (slotnum); +} + +//---------------------------------------------------------------------------- +// vme_get_out_bound +// Return attributes of an outbound window. +//---------------------------------------------------------------------------- +int vme_get_out_bound(vmeOutWindowCfg_t * vmeOut) +{ + int window_number; + + window_number = vmeOut->windowNbr; + memset(vmeOut, 0, sizeof(vmeOutWindowCfg_t)); + vmeOut->windowNbr = window_number; + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_get_out_bound(vmeOut)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_get_out_bound(vmeOut)); + break; + } + return (0); +} + +//---------------------------------------------------------------------------- +// vme_set_out_bound +// Set attributes of an outbound window. +//---------------------------------------------------------------------------- +int vme_set_out_bound(vmeOutWindowCfg_t * vmeOut) +{ + int window_number = vmeOut->windowNbr; + unsigned int existing_size; + char *res_name = NULL; + + if (vmeOut->windowNbr > 7) + return (-EINVAL); + + if (vmepcimem == 0) + return (-ENOMEM); + + // Allocate and map PCI memory space for this window. + existing_size = + out_resource[window_number].end - out_resource[window_number].start; + + if ((vmeOut->windowEnable == 0) || + (existing_size != vmeOut->windowSizeL)) { + if (existing_size != 0) { + if (out_image_va[window_number] != 0) + iounmap((char *)out_image_va[window_number]); + if (out_resource[window_number].name != NULL) + kfree(out_resource[window_number].name); + release_resource(&out_resource[window_number]); + memset(&out_resource[window_number], 0, sizeof(struct resource)); + } + } + + if ((vmeOut->windowEnable) && + (existing_size != vmeOut->windowSizeL)) { + + if (vmeOut->windowSizeL == 0) + return (-EINVAL); + + res_name = kmalloc(32, GFP_KERNEL); + if (!res_name) + printk(KERN_ERR "vmedrv: kmalloc() failed!\n"); + else + sprintf(res_name, "VME Window %01x", window_number); + out_resource[window_number].name = (char *)res_name; + out_resource[window_number].start = 0; + out_resource[window_number].end = vmeOut->windowSizeL; + out_resource[window_number].flags = IORESOURCE_MEM; + + if (pci_bus_alloc_resource(vme_pci_dev->bus, + &out_resource[window_number], + vmeOut->windowSizeL, + vmeOut->windowSizeL, + PCIBIOS_MIN_MEM, 0, NULL, NULL)) { + printk(KERN_ERR + "vmedrv: Failed to allocate mem resource for window %d size 0x%x start 0x%lx\n", + window_number, vmeOut->windowSizeL, + out_resource[window_number].start); + if (out_resource[window_number].name != NULL) + kfree(out_resource[window_number].name); + memset(&out_resource[window_number], 0, sizeof(struct resource)); + return (-ENOMEM); + } + + out_image_va[window_number] = (int)ioremap(out_resource[window_number].start, + vmeOut->windowSizeL); + if (out_image_va[window_number] == 0) { + printk(KERN_ERR + "vmedrv: No memory for outbound window\n"); + if (out_resource[window_number].name != NULL) + kfree(out_resource[window_number].name); + release_resource(&out_resource[window_number]); + memset(&out_resource[window_number], 0, sizeof(struct resource)); + return (-ENOMEM); + } + vmeOut->pciBusAddrL = out_resource[window_number].start + - pci_bus_mem_base_phys(vmechip_bus); + } + + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_set_out_bound(vmeOut)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_set_out_bound(vmeOut)); + break; + } + return (-ENODEV); +} + +/* + * vme_get_in_bound + * Return attributes of an inbound window. + */ + +int vme_get_in_bound(vmeInWindowCfg_t * vmeIn) +{ + int window_number; + + window_number = vmeIn->windowNbr; + memset(vmeIn, 0, sizeof(vmeInWindowCfg_t)); + vmeIn->windowNbr = window_number; + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_get_in_bound(vmeIn)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_get_in_bound(vmeIn)); + break; + } + return (-ENODEV); +} + +//---------------------------------------------------------------------------- +// vme_set_in_bound +// Set attributes of an inbound window. +//---------------------------------------------------------------------------- +int vme_set_in_bound(vmeInWindowCfg_t * vmeIn) +{ + int status = -ENODEV; + + // Mask off VME address bits per address space. + switch (vmeIn->addrSpace) { + case VME_A16: + vmeIn->vmeAddrU = 0; + vmeIn->vmeAddrL &= 0xFFFF; + break; + case VME_A24: + case VME_CRCSR: + vmeIn->vmeAddrU = 0; + vmeIn->vmeAddrL &= 0xFFFFFF; + break; + case VME_A32: + vmeIn->vmeAddrU = 0; + break; + case VME_A64: + case VME_USER1: + case VME_USER2: + case VME_USER3: + case VME_USER4: + break; + } + + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + status = uni_set_in_bound(vmeIn); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + status = tempe_set_in_bound(vmeIn); + break; + } + + if (!status) { + vmechip_interboard_data->inBoundVmeSize[vmeIn->windowNbr] = + vmeIn->windowSizeL; + vme_flush_line((char *)&vmechip_interboard_data-> + inBoundVmeSize[vmeIn->windowNbr]); + + vmechip_interboard_data->inBoundVmeAddrHi[vmeIn->windowNbr] = + vmeIn->vmeAddrU; + vme_flush_line((char *)&vmechip_interboard_data-> + inBoundVmeAddrHi[vmeIn->windowNbr]); + + vmechip_interboard_data->inBoundVmeAddrLo[vmeIn->windowNbr] = + vmeIn->vmeAddrL; + vme_flush_line((char *)&vmechip_interboard_data-> + inBoundVmeAddrLo[vmeIn->windowNbr]); + + vmechip_interboard_data->inBoundVmeAM[vmeIn->windowNbr] = + vmeIn->addrSpace; + vme_flush_line((char *)&vmechip_interboard_data-> + inBoundVmeAM[vmeIn->windowNbr]); + } + + return (status); +} + +//---------------------------------------------------------------------------- +// vme_do_dma() +// Perform the requested DMA operation. +// Caller must assure exclusive access to the DMA channel. +//---------------------------------------------------------------------------- +int vme_do_dma(vmeDmaPacket_t * vmeDma) +{ + int retval = -ENODEV; + + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + retval = uni_do_dma(vmeDma); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + retval = tempe_do_dma(vmeDma); + break; + } + + return (retval); +} + +//---------------------------------------------------------------------------- +// vme_get_slot_info() +// Obtain information about the board (if any) that is present in +// a specified VME bus slot. +// +// (Note VME slot numbers start at 1, not 0). +// Depends on board mapping in CS/CSR space. Boards which do not +// support or are not configured to respond in CS/CSR space will +// not be detected by this routine. +//---------------------------------------------------------------------------- +int vme_get_slot_info(vmeInfoCfg_t * vmeInfo) +{ + int slot_of_interest; + unsigned int temp; + int i; + + struct vmeSharedData *remote_data; + unsigned int *remote_csr; + + slot_of_interest = vmeInfo->vmeSlotNum; + memset(vmeInfo, 0, sizeof(vmeInfoCfg_t)); + + if (slot_of_interest > 21) { + return (-EINVAL); + } + // Fill in information for our own board. + if ((slot_of_interest == 0) || (slot_of_interest == vme_slotnum)) { + vmeInfo->vmeSlotNum = vme_slotnum; + vmeInfo->boardResponded = 1; + vmeInfo->sysConFlag = vme_syscon; + vmeInfo->vmeControllerID = + PCI_VENDOR_ID_TUNDRA | (vmechip_devid << 16); + vmeInfo->vmeControllerRev = vmechip_revision; + strcpy(vmeInfo->osName, "Linux"); + vmeInfo->vmeDriverRev = VMEDRV_REV; + return (0); + } + // Fill in information for another board in the chassis. + vmeInfo->vmeSlotNum = slot_of_interest; + if (out_image_va[7] == 0) { + return (-ENODEV); + } + // See if something responds at that slot. + remote_data = (struct vmeSharedData *) + (vmeInfo->vmeSlotNum * 512 * 1024 + out_image_va[7]); + + remote_csr = (unsigned int *)remote_data; + temp = remote_csr[0x7FFFC / 4]; + if (vme_bus_error_chk(1)) { + return (0); // no response. + } + if (temp != (slot_of_interest << 3)) { + return (0); // non-sensical response. + } + vmeInfo->boardResponded = 1; + vmeInfo->vmeControllerID = readl(&remote_csr[0x7F000 / 4]); + vmeInfo->vmeControllerRev = readl(&remote_csr[0x7F008 / 4]) & 0xFF; + + // If there is no valid driver data structure there, + // nothing left to do + + if (strcmp("VME", remote_data->validity1) || + strcmp("RDY", remote_data->validity2)) { + return (0); + } + // Copy information from struct + vmeInfo->vmeSharedDataValid = 1; + vmeInfo->vmeDriverRev = remote_data->driverRev; + strncpy(vmeInfo->osName, remote_data->osname, 8); + for (i = 0; i < 8; i++) { + vmeInfo->vmeAddrHi[i] = remote_data->inBoundVmeAddrHi[i]; + vmeInfo->vmeAddrLo[i] = remote_data->inBoundVmeAddrLo[i]; + vmeInfo->vmeAm[i] = remote_data->inBoundVmeAM[i]; + vmeInfo->vmeSize[i] = remote_data->inBoundVmeSize[i]; + } + + return (0); +} + +//---------------------------------------------------------------------------- +// vme_get_requestor +// Return current VME bus requestor attributes. +//---------------------------------------------------------------------------- +int vme_get_requestor(vmeRequesterCfg_t * vmeReq) +{ + memset(vmeReq, 0, sizeof(vmeRequesterCfg_t)); + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_get_requestor(vmeReq)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_get_requestor(vmeReq)); + break; + } + return (-ENODEV); +} + +//---------------------------------------------------------------------------- +// vme_set_requestor +// Set VME bus requestor attributes. +//---------------------------------------------------------------------------- +int vme_set_requestor(vmeRequesterCfg_t * vmeReq) +{ + if (vmeReq->requestLevel > 3) { + return (-EINVAL); + } + + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_set_requestor(vmeReq)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_set_requestor(vmeReq)); + break; + } + return (-ENODEV); +} + +//---------------------------------------------------------------------------- +// vme_get_arbiter +// Return VME bus arbiter attributes. +//---------------------------------------------------------------------------- +int vme_get_arbiter(vmeArbiterCfg_t * vmeArb) +{ + + // Only valid for system controller. + if (vme_syscon == 0) { + return (-EINVAL); + } + memset(vmeArb, 0, sizeof(vmeArbiterCfg_t)); + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_get_arbiter(vmeArb)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_get_arbiter(vmeArb)); + break; + } + return (-ENODEV); +} + +//---------------------------------------------------------------------------- +// vme_set_arbiter +// Set VME bus arbiter attributes. +//---------------------------------------------------------------------------- +int vme_set_arbiter(vmeArbiterCfg_t * vmeArb) +{ + // Only valid for system controller. + if (vme_syscon == 0) { + return (-EINVAL); + } + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_set_arbiter(vmeArb)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_set_arbiter(vmeArb)); + break; + } + return (-ENODEV); +} + +//---------------------------------------------------------------------------- +// vme_generate_irq +// Generate a VME bus interrupt at the specified level & vector. +// +// Caller must assure exclusive access to the VIRQ generator. +//---------------------------------------------------------------------------- +int vme_generate_irq(virqInfo_t * vmeIrq) +{ + int status = -ENODEV; + + // Only valid for non system controller. + if (vme_syscon != 0) { + return (-EINVAL); + } + if ((vmeIrq->level < 1) || (vmeIrq->level > 7)) { + return (-EINVAL); + } + if ((vmeIrq->vector < 0) || (vmeIrq->vector > 0xFF)) { + return (-EINVAL); + } + + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + status = uni_generate_irq(vmeIrq); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + status = tempe_generate_irq(vmeIrq); + break; + } + + return (status); +} + +//---------------------------------------------------------------------------- +// vme_get_irq_status() +// Wait for a specific or any VME bus interrupt to occur. +//---------------------------------------------------------------------------- +int vme_get_irq_status(virqInfo_t * vmeIrq) +{ + int timeout; + int looptimeout = 1; + int i, j; + + // Only valid for system controller. + if (vme_syscon == 0) { + return (-EINVAL); + } + if ((vmeIrq->level >= 8) || (vmeIrq->vector > 0xFF)) { + return (-EINVAL); + } + if ((vmeIrq->level == 0) && (vmeIrq->vector != 0)) { + return (-EINVAL); + } + + vmeIrq->timeOutFlag = 0; + timeout = vmeIrq->waitTime; + do { + if ((vmeIrq->level == 0) && (vmeIrq->vector == 0)) { + for (i = 1; i < 8; i++) { + for (j = 0; j <= 0xFF; j++) { + if (vme_irqlog[i][j] != 0) { + vmeIrq->level = i; + vmeIrq->vector = j; + return (0); + } + } + } + } + if (vme_irqlog[vmeIrq->level][vmeIrq->vector] != 0) { + return (0); + } + + if (timeout <= 0) { + vmeIrq->timeOutFlag = 1; + return (0); + } + // Delay a bit before checking again + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(looptimeout); + timeout = timeout - looptimeout; + + } while (1); + + return (0); +} + +//---------------------------------------------------------------------------- +// vme_clr_irq_status() +// Clear irq log of a specific or all VME interrupts. +//---------------------------------------------------------------------------- +int vme_clr_irq_status(virqInfo_t * vmeIrq) +{ + + int i, j; + + // Only valid for system controller. + if (vme_syscon == 0) { + return (-EINVAL); + } + // Sanity check input + if ((vmeIrq->level >= 8) || (vmeIrq->vector > 0xFF)) { + return (-EINVAL); + } + if ((vmeIrq->level == 0) && (vmeIrq->vector != 0)) { + return (-EINVAL); + } + + if ((vmeIrq->level == 0) && (vmeIrq->vector == 0)) { + + // Clear all irqs. + for (i = 1; i < 8; i++) { + for (j = 0; j <= 0xFF; j++) { + vme_irqlog[i][j] = 0; + } + } + } + // Clear a single irq. + vme_irqlog[vmeIrq->level][vmeIrq->vector] = 0; + return (0); +} + +//---------------------------------------------------------------------------- +// vme_do_rmw() +// Perform a RMW operation on the VME bus. +//---------------------------------------------------------------------------- +int vme_do_rmw(vmeRmwCfg_t * vmeRmw) +{ + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_do_rmw(vmeRmw)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_do_rmw(vmeRmw)); + break; + } + return (-ENODEV); +} + +//---------------------------------------------------------------------------- +// vme_setup_lm() +// Setup the VME bus location monitor to detect the specified access. +//---------------------------------------------------------------------------- +int vme_setup_lm(vmeLmCfg_t * vmeLm) +{ + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_setup_lm(vmeLm)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_setup_lm(vmeLm)); + break; + } + return (-ENODEV); +} + +//---------------------------------------------------------------------------- +// vme_wait_lm() +// Wait for the location monitor to trigger. +//---------------------------------------------------------------------------- +int vme_wait_lm(vmeLmCfg_t * vmeLm) +{ + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_wait_lm(vmeLm)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_wait_lm(vmeLm)); + break; + } + return (-ENODEV); +} + +//---------------------------------------------------------------------------- +// vme_init() +// Initialize the VME bridge. +//---------------------------------------------------------------------------- +int vme_init(void *driverdata) +{ + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (uni_init(driverdata)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + return (tempe_init(driverdata)); + break; + } + return (0); +} diff -u --new-file --recursive linux-2.6.14.orig/drivers/vme/vmedrv.h linux-2.6.14.mod/drivers/vme/vmedrv.h --- linux-2.6.14.orig/drivers/vme/vmedrv.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/vme/vmedrv.h 2005-11-16 10:40:21.000000000 -0700 @@ -0,0 +1,454 @@ +/* + * vmedrv.h + * + * Application interface to VME device nodes + * + * Author: Tom Armistead + * Updated and maintained by Ajit Prem + * Copyright 2004 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/* + * The reserved elements in the following structures are + * intended to allow future versions of the driver to + * maintain backwards compatibility. Applications should + * initialize reserved locations to zero. + */ + +#ifndef VMEDRV_H +#define VMEDRV_H + +#define VMEDRV_REV 0x0301 + +#define VME_MINOR_TYPE_MASK 0xF0 +#define VME_MINOR_OUT 0x00 +#define VME_MINOR_DMA 0x10 +#define VME_MINOR_MISC 0x20 +#define VME_MINOR_SLOTS1 0x30 +#define VME_MINOR_SLOTS2 0x40 + +#define VME_MINOR_CTL 0x20 +#define VME_MINOR_REGS 0x21 +#define VME_MINOR_RMW 0x22 +#define VME_MINOR_LM 0x23 +#ifndef PAGESIZE +#define PAGESIZE 4096 +#endif +#ifndef LINESIZE +#define LINESIZE 0x20 +#endif +#define VME_MAX_WINDOWS 8 + +#ifndef PCI_DEVICE_ID_TUNDRA_TSI148 +#define PCI_DEVICE_ID_TUNDRA_TSI148 0x148 +#endif + +#ifndef PCI_DEVICE_ID_TUNDRA_TEMPE +#define PCI_DEVICE_ID_TUNDRA_TEMPE 0x148 +#endif + +/* + * VME access type definitions + */ +#define VME_DATA 1 +#define VME_PROG 2 +#define VME_USER 4 +#define VME_SUPER 8 + +/* + * VME address type definitions + */ +typedef enum { + VME_A16, + VME_A24, + VME_A32, + VME_A64, + VME_CRCSR, + VME_USER1, + VME_USER2, + VME_USER3, + VME_USER4 +} addressMode_t; + +/* + * VME Transfer Protocol Definitions + */ +#define VME_SCT 0x1 +#define VME_BLT 0x2 +#define VME_MBLT 0x4 +#define VME_2eVME 0x8 +#define VME_2eSST 0x10 +#define VME_2eSSTB 0x20 + +/* + * Data Widths + */ +typedef enum { + VME_D8 = 8, + VME_D16 = 16, + VME_D32 = 32, + VME_D64 = 64 +} dataWidth_t; + +/* + * 2eSST Data Transfer Rate Codes + */ +typedef enum { + VME_SSTNONE = 0, + VME_SST160 = 160, + VME_SST267 = 267, + VME_SST320 = 320 +} vme2esstRate_t; + +/* + * Arbitration Scheduling Modes + */ +typedef enum { + VME_R_ROBIN_MODE, + VME_PRIORITY_MODE +} vme2ArbMode_t; + +/* + * /dev/vme_m* Outbound Window Ioctl Commands + */ +#define VME_IOCTL_SET_OUTBOUND 0x10 +#define VME_IOCTL_GET_OUTBOUND 0x11 +/* + * VMEbus OutBound Window Arg Structure + * NOTE: + * If pciBusAddr[U,L] are 0, then kernel will dynamically assign + * pci start address on PCI bus. + */ +struct vmeOutWindowCfg { + int windowNbr; /* Window Number */ + char windowEnable; /* State of Window */ + unsigned int pciBusAddrU; /* Start Address on the PCI Bus */ + unsigned int pciBusAddrL; /* Start Address on the PCI Bus */ + unsigned int windowSizeU; /* Window Size */ + unsigned int windowSizeL; /* Window Size */ + unsigned int xlatedAddrU; /* Starting Address on the VMEbus */ + unsigned int xlatedAddrL; /* Starting Address on the VMEbus */ + int bcastSelect2esst; /* 2eSST Broadcast Select */ + char wrPostEnable; /* Write Post State */ + char prefetchEnable; /* Prefetch Read Enable State */ + int prefetchSize; /* Prefetch Read Size (in Cache Lines) */ + vme2esstRate_t xferRate2esst; /* 2eSST Transfer Rate */ + addressMode_t addrSpace; /* Address Space */ + dataWidth_t maxDataWidth; /* Maximum Data Width */ + int xferProtocol; /* Transfer Protocol */ + int userAccessType; /* User/Supervisor Access Type */ + int dataAccessType; /* Data/Program Access Type */ + int reserved; /* For future use */ +}; +typedef struct vmeOutWindowCfg vmeOutWindowCfg_t; + +/* + * /dev/vme_dma* DMA commands + */ +#define VME_IOCTL_START_DMA 0x30 +#define VME_IOCTL_PAUSE_DMA 0x31 +#define VME_IOCTL_CONTINUE_DMA 0x32 +#define VME_IOCTL_ABORT_DMA 0x33 +#define VME_IOCTL_WAIT_DMA 0x34 + +typedef enum { + /* NOTE: PATTERN entries only valid as source of data */ + VME_DMA_PATTERN_BYTE, + VME_DMA_PATTERN_BYTE_INCREMENT, + VME_DMA_PATTERN_WORD, + VME_DMA_PATTERN_WORD_INCREMENT, + VME_DMA_USER, + VME_DMA_KERNEL, + VME_DMA_PCI, + VME_DMA_VME +} dmaData_t; + +/* + * VMEbus Transfer Attributes + */ +struct vmeAttr { + dataWidth_t maxDataWidth; /* Maximum Data Width */ + vme2esstRate_t xferRate2esst; /* 2eSST Transfer Rate */ + int bcastSelect2esst; /* 2eSST Broadcast Select */ + addressMode_t addrSpace; /* Address Space */ + int userAccessType; /* User/Supervisor Access Type */ + int dataAccessType; /* Data/Program Access Type */ + int xferProtocol; /* Transfer Protocol */ + int reserved; /* For future use */ +}; +typedef struct vmeAttr vmeAttr_t; + +/* + * DMA arg info + * NOTE: + * structure contents relating to VME are don't care for + * PCI transactions + * structure contents relating to PCI are don't care for + * VME transactions + * If source or destination is user memory and transaction + * will cross page boundary, the DMA request will be split + * into multiple DMA transactions. + */ +typedef struct vmeDmaPacket { + int vmeDmaToken; /* Token for driver use */ + int vmeDmaWait; /* Time to wait for completion */ + unsigned int vmeDmaStartTick; /* Time DMA started */ + unsigned int vmeDmaStopTick; /* Time DMA stopped */ + unsigned int vmeDmaElapsedTime; /* Elapsed time */ + int vmeDmaStatus; /* DMA completion status */ + + int byteCount; /* Byte Count */ + int bcastSelect2esst; /* 2eSST Broadcast Select */ + + /* + * DMA Source Data + */ + dmaData_t srcBus; + unsigned int srcAddrU; + unsigned int srcAddr; + int pciReadCmd; + struct vmeAttr srcVmeAttr; + char srcfifoEnable; + + /* + * DMA Destination Data + */ + dmaData_t dstBus; + unsigned int dstAddrU; + unsigned int dstAddr; + int pciWriteCmd; + struct vmeAttr dstVmeAttr; + char dstfifoEnable; + + /* + * BUS usage control + */ + int maxCpuBusBlkSz; /* CPU Bus Maximum Block Size */ + int maxPciBlockSize; /* PCI Bus Maximum Block Size */ + int pciBackOffTimer; /* PCI Bus Back-Off Timer */ + int maxVmeBlockSize; /* VMEbus Maximum Block Size */ + int vmeBackOffTimer; /* VMEbus Back-Off Timer */ + + int channel_number; /* Channel number */ + int reserved; /* For future use */ + /* + * Ptr to next Packet + * (NULL == No more Packets) + */ + struct vmeDmaPacket *pNextPacket; + +} vmeDmaPacket_t; + +/* + * /dev/vme_ctl ioctl Commands + */ +#define VME_IOCTL_GET_SLOT_VME_INFO 0x41 +/* + * VMEbus GET INFO Arg Structure + */ +struct vmeInfoCfg { + int vmeSlotNum; /* VME slot number of interest */ + int boardResponded; /* Board responded */ + char sysConFlag; /* System controller flag */ + int vmeControllerID; /* Vendor/device ID of VME bridge */ + int vmeControllerRev; /* Revision of VME bridge */ + char osName[8]; /* Name of OS e.g. "Linux" */ + int vmeSharedDataValid; /* Validity of data struct */ + int vmeDriverRev; /* Revision of VME driver */ + unsigned int vmeAddrHi[8]; /* Address on VME bus */ + unsigned int vmeAddrLo[8]; /* Address on VME bus */ + unsigned int vmeSize[8]; /* Size on VME bus */ + unsigned int vmeAm[8]; /* Address modifier on VME bus */ + int reserved; /* For future use */ +}; +typedef struct vmeInfoCfg vmeInfoCfg_t; + +#define VME_IOCTL_SET_REQUESTOR 0x42 +#define VME_IOCTL_GET_REQUESTOR 0x43 +/* + * VMEbus Requester Arg Structure + */ +struct vmeRequesterCfg { + int requestLevel; /* Requester Bus Request Level */ + char fairMode; /* Requester Fairness Mode Indicator */ + int releaseMode; /* Requester Bus Release Mode */ + int timeonTimeoutTimer; /* Master Time-on Time-out Timer */ + int timeoffTimeoutTimer; /* Master Time-off Time-out Timer */ + int reserved; /* For future use */ +}; +typedef struct vmeRequesterCfg vmeRequesterCfg_t; + +#define VME_IOCTL_SET_CONTROLLER 0x44 +#define VME_IOCTL_GET_CONTROLLER 0x45 + +/* + * VMEbus Arbiter Arg Structure + */ +struct vmeArbiterCfg { + vme2ArbMode_t arbiterMode; /* Arbitration Scheduling Algorithm */ + char arbiterTimeoutFlag; /* Arbiter Time-out Timer Indicator */ + int globalTimeoutTimer; /* VMEbus Global Time-out Timer */ + char noEarlyReleaseFlag; /* No Early Release on BBUSY */ + int reserved; /* For future use */ +}; +typedef struct vmeArbiterCfg vmeArbiterCfg_t; + +#define VME_IOCTL_GENERATE_IRQ 0x46 +#define VME_IOCTL_GET_IRQ_STATUS 0x47 +#define VME_IOCTL_CLR_IRQ_STATUS 0x48 + +/* + * VMEbus IRQ Info + */ +typedef struct virqInfo { + /* + * Time to wait for Event to occur (in clock ticks) + */ + short waitTime; + short timeOutFlag; + + /* + * VMEbus Interrupt Level and Vector Data + */ + int level; + int vector; + int reserved; /* For future use */ + +} virqInfo_t; + +#define VME_IOCTL_SET_INBOUND 0x49 +#define VME_IOCTL_GET_INBOUND 0x50 + +/* + * VMEbus InBound Window Arg Structure + * NOTE: + * If pciBusAddr[U,L] and windowSize[U,L] are 0, then kernel + * will dynamically assign inbound window to map to a kernel + * supplied buffer. + */ +struct vmeInWindowCfg { + int windowNbr; /* Window Number */ + char windowEnable; /* State of Window */ + unsigned int vmeAddrU; /* Start Address responded to on the VMEbus */ + unsigned int vmeAddrL; /* Start Address responded to on the VMEbus */ + unsigned int windowSizeU; /* Window Size */ + unsigned int windowSizeL; /* Window Size */ + unsigned int pciAddrU; /* Start Address appearing on the PCI Bus */ + unsigned int pciAddrL; /* Start Address appearing on the PCI Bus */ + char wrPostEnable; /* Write Post State */ + char prefetchEnable; /* Prefetch Read State */ + char prefetchThreshold; /* Prefetch Read Threshold State */ + int prefetchSize; /* Prefetch Read Size */ + char rmwLock; /* Lock PCI during RMW Cycles */ + char data64BitCapable; /* non-VMEbus capable of 64-bit Data */ + addressMode_t addrSpace; /* Address Space */ + int userAccessType; /* User/Supervisor Access Type */ + int dataAccessType; /* Data/Program Access Type */ + int xferProtocol; /* Transfer Protocol */ + vme2esstRate_t xferRate2esst; /* 2eSST Transfer Rate */ + char bcastRespond2esst; /* Respond to 2eSST Broadcast */ + int reserved; /* For future use */ + +}; +typedef struct vmeInWindowCfg vmeInWindowCfg_t; + +/* + * /dev/vme_rmw RMW Ioctl Commands + */ +#define VME_IOCTL_DO_RMW 0x60 +/* + * VMEbus RMW Configuration Data + */ +struct vmeRmwCfg { + unsigned int targetAddrU; /* VME Address (Upper) to trigger RMW cycle */ + unsigned int targetAddr; /* VME Address (Lower) to trigger RMW cycle */ + addressMode_t addrSpace; /* VME Address Space */ + int enableMask; /* Bit mask defining the bits of interest */ + int compareData; /* Data to be compared with the data read */ + int swapData; /* Data written to the VMEbus on success */ + int maxAttempts; /* Maximum times to try */ + int numAttempts; /* Number of attempts before success */ + int reserved; /* For future use */ + +}; +typedef struct vmeRmwCfg vmeRmwCfg_t; + +/* + * /dev/vme_lm location Monitor Ioctl Commands + */ +#define VME_IOCTL_SETUP_LM 0x70 +#define VME_IOCTL_WAIT_LM 0x71 +/* + * VMEbus Location Monitor Arg Structure + */ +struct vmeLmCfg { + unsigned int addrU; /* Location Monitor Address upper */ + unsigned int addr; /* Location Monitor Address lower */ + addressMode_t addrSpace; /* Address Space */ + int userAccessType; /* User/Supervisor Access Type */ + int dataAccessType; /* Data/Program Access Type */ + int lmWait; /* Time to wait for access */ + int lmEvents; /* Lm event mask */ + int reserved; /* For future use */ +}; +typedef struct vmeLmCfg vmeLmCfg_t; + +/* + * Data structure created for each board in CS/CSR space. + */ +struct vmeSharedData { + /* + * Public elements + */ + char validity1[4]; /* "VME" when contents are valid */ + char validity2[4]; /* "RDY" when contents are valid */ + int structureRev; /* Revision of this structure */ + int reserved1; + + char osname[8]; /* OS name string */ + int driverRev; /* Revision of VME driver */ + int reserved2; + + char boardString[16]; /* type of board */ + + int vmeControllerType; + int vmeControllerRev; + int boardSemaphore[8]; /* for use by remote */ + unsigned int inBoundVmeAddrHi[8]; /* This boards VME windows */ + unsigned int inBoundVmeAddrLo[8]; /* This boards VME windows */ + addressMode_t inBoundVmeAM[8]; /* Address modifier */ + int inBoundVmeSize[8]; /* size available to remotes */ + char reserved3[0x1000 - 248]; /* Pad to 4k boundary */ + + int readTestPatterns[1024]; + int remoteScratchArea[24][256]; /* 1k scratch for each remote */ + /* + * Private areas for use by driver only. + */ + char driverScratch[4096]; + struct { + char Eye[4]; + int Offset; + int Head; + int Tail; + int Size; + int Reserved1; + int Reserved2; + int Reserved3; + char Data[4096 - 32]; + } boardFifo[23]; +}; + +/* + * Driver errors reported back to the Application (other than the + * stanard Linux errnos...). + */ +#define VME_ERR_VERR 1 /* VME bus error detected */ +#define VME_ERR_PERR 2 /* PCI bus error detected */ + +#endif /* VMEDRV_H */ diff -u --new-file --recursive linux-2.6.14.orig/drivers/vme/vmelinux.c linux-2.6.14.mod/drivers/vme/vmelinux.c --- linux-2.6.14.orig/drivers/vme/vmelinux.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/drivers/vme/vmelinux.c 2006-06-26 14:34:57.000000000 -0700 @@ -0,0 +1,2510 @@ +/* + * vmelinux.c + * + * Provides the device node interface from the user space programs to + * the VME bridge. Primary purpose is to convert user space + * data to kernel and back. + * + * This driver supports both the Tempe, and the Universe/Universe II chips. + * + * Author: Tom Armistead + * Updated and maintained by Ajit Prem + * Copyright 2004 Motorola Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vmedrv.h" + +static char Version[] = "3.6 06/14/2006"; + +static int vme_open(struct inode *, struct file *); +static int vme_release(struct inode *, struct file *); +static ssize_t vme_read(struct file *, char *, size_t, loff_t *); +static ssize_t vme_write(struct file *, const char *, size_t, loff_t *); +static unsigned int vme_poll(struct file *, poll_table *); +static int vme_ioctl(struct inode *, struct file *, unsigned int, + unsigned long); +static int vme_mmap(struct file *file, struct vm_area_struct *vma); +//static int vme_select(struct inode *inode,struct file *file,int mode, select_table *table); +static int vme_procinfo(char *, char **, off_t, int, int *, void *); +static struct class *vme_class; + +void vmemod_setup_options(char *cmd_line); + +extern unsigned tb_ticks_per_jiffy; + +static struct proc_dir_entry *vme_procdir; + +static struct file_operations vme_fops = { + .owner = THIS_MODULE, + .read = vme_read, + .write = vme_write, + .poll = vme_poll, + .ioctl = vme_ioctl, + .mmap = vme_mmap, + .open = vme_open, + .release = vme_release +}; + +#define VME_MAJOR 221 +#define MAX_MINOR 0xFF + +#define DMATYPE_SINGLE 1 +#define DMATYPE_LLIST 2 + +#define INTERBOARD_BUFFER_SIZE 512 * 1024 +#define DEFAULT_INBOUND_WINDOW_BUFFER_SIZE 4 * 1024 * 1024 + +static unsigned long opened[MAX_MINOR + 1]; +struct semaphore devinuse[MAX_MINOR + 1]; + +// Global VME controller information +extern int vmechip_irq; // PCI irq +extern int vmechip_devid; // PCI devID of VME bridge +extern int vmeparent_devid; // PCI devID of VME bridge parent +extern int vmechip_revision; // PCI revision +extern int vmechip_bus; // PCI bus number. +extern char *vmechip_baseaddr; // virtual address of chip registers +extern int vme_slotnum; // VME slot num (-1 = unknown) +extern int vme_syscon; // VME sys controller (-1 = unknown) + +#ifdef CONFIG_VME_BRIDGE_BOOTMEM +extern void *vme_driver_bootmem; +extern unsigned int vme_bootmem_size; +#endif + +char *in_image_ba[0x8]; // Virtual Address +dma_addr_t in_image_pa[0x8]; // Physical Address +int in_image_size[0x8]; // Size +int in_image_mapped[0x8]; +static int out_image_mapped[0x8]; +static struct semaphore in_image_sem[0x8]; +static struct semaphore out_image_sem[0x8]; + +struct resource out_resource[0x8]; +extern unsigned int out_image_va[8]; // Base virtual address +extern unsigned int out_image_valid[8]; // validity + +/* + * External functions + */ +extern void uni_shutdown(void); +extern void tsi148_shutdown(void); + +extern int vme_init(void *); +extern int vme_bus_error_chk(int); +extern int vme_get_slot_num(void); +extern int vme_get_out_bound(vmeOutWindowCfg_t *); +extern int vme_set_out_bound(vmeOutWindowCfg_t *); +extern int vme_do_dma(vmeDmaPacket_t *); +extern int vme_get_slot_info(vmeInfoCfg_t *); +extern int vme_get_requestor(vmeRequesterCfg_t *); +extern int vme_set_requestor(vmeRequesterCfg_t *); +extern int vme_get_arbiter(vmeArbiterCfg_t *); +extern int vme_set_arbiter(vmeArbiterCfg_t *); +extern int vme_generate_irq(virqInfo_t *); +extern int vme_get_irq_status(virqInfo_t *); +extern int vme_clr_irq_status(virqInfo_t *); +extern int vme_get_in_bound(vmeInWindowCfg_t *); +extern int vme_set_in_bound(vmeInWindowCfg_t *); +extern int vme_do_rmw(vmeRmwCfg_t *); +extern int vme_setup_lm(vmeLmCfg_t *); +extern int vme_wait_lm(vmeLmCfg_t *); + +extern void vme_sync_data(void); +extern void vme_flush_line(void *); +extern void vme_flush_range(void *, void *); + +extern int uni_procinfo(char *); +extern int tsi148_procinfo(char *); + +#define DEV_VALID 1 +#define DEV_EXCLUSIVE 2 +#define DEV_RW 4 + +static char vme_minor_dev_flags[] = { + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_m0 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_m1 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_m2 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_m3 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_m4 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_m5 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_m6 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_m7 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_s0 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_s1 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_s2 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_s3 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_s4 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_s5 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_s6 */ + DEV_VALID | DEV_EXCLUSIVE | DEV_RW, /* /dev/vme_s7 */ + DEV_VALID, /* /dev/vme_dma0 */ + DEV_VALID, /* /dev/vme_dma1 */ + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + DEV_VALID, /* /dev/vme_ctl */ + DEV_VALID | DEV_RW, /* /dev/vme_regs */ + DEV_VALID | DEV_EXCLUSIVE, /* /dev/vme_rmw0 */ + DEV_VALID | DEV_EXCLUSIVE, /* /dev/vme_lm0 */ + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + DEV_VALID | DEV_RW, /* /dev/vme_slot0 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot1 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot2 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot3 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot4 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot5 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot6 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot7 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot8 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot9 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot10 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot11 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot12 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot13 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot14 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot15 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot16 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot17 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot18 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot19 */ + DEV_VALID | DEV_RW, /* /dev/vme_slot20 */ + DEV_VALID | DEV_RW /* /dev/vme_slot21 */ +}; + +static unsigned int reads; +static unsigned int writes; +static unsigned int ioctls; + +/* Shared global */ +wait_queue_head_t dma_queue[2]; +wait_queue_head_t lm_queue; +wait_queue_head_t mbox_queue; +struct vmeSharedData *vmechip_interboard_data; // vaddress of board data +dma_addr_t vmechip_interboard_datap; // paddress of board data +struct resource *vmepcimem; +int tb_speed; +struct semaphore virq_inuse; +struct pci_dev *vme_pci_dev; + +MODULE_PARM_DESC(vmechip_irq, "VME chip irq in the range 1-255"); +module_param(vmechip_irq, int, 0); +MODULE_PARM_DESC(vme_slotnum, "Slot Number in the range 1-21"); +module_param(vme_slotnum, int, 0); +MODULE_LICENSE("GPL"); + +static int vme_minor_type(int minor) +{ + if (minor > sizeof(vme_minor_dev_flags)) { + return (0); + } + return (vme_minor_dev_flags[minor]); +} + +/* + * vme_alloc_buffers() + * + * Obtain a buffer for the data structure that will be + * advertized through CS/CSR space. The CS/CSR decoder only + * allows remapping on 512K boundaries so this buffer must be + * aligned on a 512K byte boundary. + * + */ + +static int vme_alloc_buffers(void) +{ + struct page *page, *pend; + + if (vmechip_interboard_data == NULL) { + vmechip_interboard_data = (struct vmeSharedData *) + dma_alloc_coherent((struct device *)&vme_pci_dev->dev, + INTERBOARD_BUFFER_SIZE, + (dma_addr_t *) & + vmechip_interboard_datap, GFP_DMA); + if (!vmechip_interboard_data) { + printk("tsi148: No memory for interboard data\n"); + return -ENOMEM; + } + if (((int)vmechip_interboard_data & 0x7FFFF) != 0) { + printk + ("tsi148: Unable to get DMA buffer with required alignment\n"); + return -1; + } + } +#ifdef CONFIG_VME_BRIDGE_BOOTMEM + in_image_size[7] = vme_bootmem_size; + if (vme_driver_bootmem != NULL) { + in_image_ba[7] = (char *) vme_driver_bootmem; + in_image_pa[7] = __pa(in_image_ba[7]); + /* now mark the pages as reserved; otherwise */ + /* remap_pfn_range doesn't do what we want */ + pend = virt_to_page(in_image_ba[7] + in_image_size[7] - 1); + for (page = virt_to_page(in_image_ba[7]); page <= pend; page++) + SetPageReserved(page); + } +#endif + return (0); +} + +//---------------------------------------------------------------------------- +// vme_free_buffers() +// Free all buffers allocated by this driver. +//---------------------------------------------------------------------------- +void vme_free_buffers(void) +{ + int i; + struct page *page, *pend; + + /* + * clear valid flags of interboard data and free it + */ + if (vmechip_interboard_data != NULL) { + strcpy(vmechip_interboard_data->validity1, "OFF"); + strcpy(vmechip_interboard_data->validity2, "OFF"); + dma_free_coherent(&vme_pci_dev->dev, + INTERBOARD_BUFFER_SIZE, + vmechip_interboard_data, + vmechip_interboard_datap); + } + // free inbound buffers + for (i = 0; i < 8; i++) { + if (in_image_ba[i] != NULL) { + /* undo marking the pages as reserved */ + pend = virt_to_page(in_image_ba[i] + in_image_size[i] - 1); + for (page = virt_to_page(in_image_ba[i]); page <= pend; page++) + ClearPageReserved(page); + + if (i == 7) { +#ifndef CONFIG_VME_BRIDGE_BOOTMEM + dma_free_coherent(&vme_pci_dev->dev, + in_image_size[i], + in_image_ba[i], in_image_pa[i]); +#endif + in_image_mapped[i] = 0; + } else { + dma_free_coherent(&vme_pci_dev->dev, + in_image_size[i], + in_image_ba[i], in_image_pa[i]); + in_image_mapped[i] = 0; + } + } + } +} + +//---------------------------------------------------------------------------- +// vme_init_test_data() +// Initialize the test area of the interboard data structure +// with the expected data patterns. +//---------------------------------------------------------------------------- +void vme_init_test_data(int testdata[]) +{ + int i; + + // walking 1 & walking 0 + for (i = 0; i < 32; i++) { + testdata[i * 2] = 1 << i; + testdata[i * 2 + 1] = ~(1 << i); + } + + // all 0, all 1's, 55's and AA's + testdata[64] = 0x0; + testdata[65] = 0xFFFFFFFF; + testdata[66] = 0x55555555; + testdata[67] = 0xAAAAAAAA; + + // Incrementing data. + for (i = 68; i < 1024; i++) { + testdata[i] = i; + } +} + +//---------------------------------------------------------------------------- +// vme_init_interboard_data() +// Initialize the interboard data structure. +//---------------------------------------------------------------------------- +void vme_init_interboard_data(struct vmeSharedData *ptr) +{ + if (ptr == NULL) + return; + + memset(ptr, 0, sizeof(struct vmeSharedData)); + vme_init_test_data(&ptr->readTestPatterns[0]); + + ptr->structureRev = 1; + strcpy(&ptr->osname[0], "linux"); + + ptr->driverRev = 1; + +#ifdef CONFIG_MVME3100 + strcpy(&ptr->boardString[0], "MVME3100"); +#endif +#ifdef CONFIG_MVME6100 + strcpy(&ptr->boardString[0], "MVME6100"); +#endif +#ifdef CONFIG_MVME5500 + strcpy(&ptr->boardString[0], "MVME5500"); +#endif +#ifdef CONFIG_MVME5100 + strcpy(&ptr->boardString[0], "MVME5100"); +#endif + ptr->vmeControllerType = vmechip_devid; + ptr->vmeControllerRev = vmechip_revision; + + /* Set valid strings "VME", "RDY" */ + strcpy(ptr->validity1, "VME"); + strcpy(ptr->validity2, "RDY"); + vme_flush_range(ptr, ptr + 1); +} + +/* + * vme_procinfo() + * /proc interface into this driver + */ + +static int vme_procinfo(char *buf, char **start, off_t fpos, int length, + int *eof, void *data) +{ + char *p; + + p = buf; + p += sprintf(p, "VME driver %s\n\n", Version); + + p += sprintf(p, "vmechip baseaddr = %08X\n", (int)vmechip_baseaddr); + p += sprintf(p, "vmechip device = %08X\n", (int)vmechip_devid); + p += sprintf(p, "vmechip revision = %08X\n", (int)vmechip_revision); + p += sprintf(p, "vme slot number = %2d\n", (int)vme_slotnum); + if (vme_syscon) + p += sprintf(p, "vme system controller = TRUE\n"); + else + p += sprintf(p, "vme system controller = FALSE\n"); + + if (vmechip_devid == PCI_DEVICE_ID_TUNDRA_TSI148) { + p += tsi148_procinfo(p); + } + + if (vmechip_devid == PCI_DEVICE_ID_TUNDRA_CA91C042) { + p += uni_procinfo(p); + } + + p += sprintf(p, "\n"); + p += sprintf(p, "statistics: reads = %i writes = %i ioctls = %i\n\n", + reads, writes, ioctls); + p += sprintf(p, "\n"); + + *eof = 1; + return p - buf; +} + +/* + register_proc() +*/ +static void register_proc(void) +{ + vme_procdir = create_proc_entry("vmeinfo", S_IFREG | S_IRUGO, 0); + vme_procdir->read_proc = vme_procinfo; +} + +/* + unregister_proc() +*/ +static void unregister_proc(void) +{ + remove_proc_entry("vmeinfo", 0); +} + +//---------------------------------------------------------------------------- +// vme_chip_reg_read +// Read a VME chip register. +// +// Note that Tempe swizzles registers at offsets > 0x100 on its own. +//---------------------------------------------------------------------------- +unsigned int vme_chip_reg_read(unsigned int *ptr) +{ + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + return (readl(ptr)); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + if (((char *)ptr) - ((char *)vmechip_baseaddr) > 0x100) { + return (*ptr); + } + return (readl(ptr)); + break; + } + return (0); +} + +/* + vme_chip_reg_write + Write a VME chip register. + + Note that Tempe swizzles registers at offsets > 0x100 on its own. +*/ +void vme_chip_reg_write(unsigned int *ptr, unsigned int value) +{ + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + writel(value, ptr); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + if (((char *)ptr) - ((char *)vmechip_baseaddr) > 0x100) { + *ptr = value; + } else { + writel(value, ptr); + } + break; + } +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) +/* + Pin down user pages and put them into a scatter gather list. + Returns <= 0 if: + -- mapping of all pages not successful + (i.e., either completely successful or fails) +*/ +static int sgl_map_user_pages(struct scatterlist *sgl, + const unsigned int max_pages, unsigned long uaddr, + size_t count, int rw) +{ + int res, i, j; + unsigned int nr_pages; + struct page **pages; + + nr_pages = ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT; + + /* User attempted Overflow! */ + if ((uaddr + count) < uaddr) + return -EINVAL; + + /* Too big */ + if (nr_pages > max_pages) + return -ENOMEM; + + /* Hmm? */ + if (count == 0) + return 0; + + if ((pages = kmalloc(max_pages * sizeof(*pages), GFP_ATOMIC)) == NULL) + return -ENOMEM; + + /* Try to fault in all of the necessary pages */ + down_read(¤t->mm->mmap_sem); + /* rw==READ means read from controller, write into memory area */ + res = get_user_pages(current, current->mm, uaddr, nr_pages, rw == READ, 0, /* don't force */ + pages, NULL); + up_read(¤t->mm->mmap_sem); + + /* Errors and no page mapped should return here */ + if (res < nr_pages) + goto out_unmap; + + for (i = 0; i < nr_pages; i++) { + /* FIXME: flush superflous for rw==READ, + * probably wrong function for rw==WRITE + */ + flush_dcache_page(pages[i]); + } + + /* Populate the scatter/gather list */ + sgl[0].page = pages[0]; + sgl[0].offset = uaddr & ~PAGE_MASK; + if (nr_pages > 1) { + sgl[0].length = PAGE_SIZE - sgl[0].offset; + count -= sgl[0].length; + for (i = 1; i < nr_pages; i++) { + sgl[i].offset = 0; + sgl[i].page = pages[i]; + sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE; + count -= PAGE_SIZE; + + } + } else { + sgl[0].length = count; + } + + kfree(pages); + return nr_pages; + + out_unmap: + if (res > 0) { + for (j = 0; j < res; j++) + page_cache_release(pages[j]); + } + kfree(pages); + return res; +} + +/* And unmap them... */ +static int sgl_unmap_user_pages(struct scatterlist *sgl, + const unsigned int nr_pages, int dirtied) +{ + int i; + + for (i = 0; i < nr_pages; i++) { + if (dirtied && !PageReserved(sgl[i].page)) + SetPageDirty(sgl[i].page); + /* FIXME: cache flush missing for rw==READ + * FIXME: call the correct reference counting function + */ + page_cache_release(sgl[i].page); + } + + return 0; +} + +/* + Function : vme_ioctl_user_free_dma + Description: Free the pages that comprise the linked list of DMA packets. +*/ +int +vme_ioctl_user_free_dma(vmeDmaPacket_t * user_start_pkt, + struct scatterlist *src_sgl, + struct scatterlist *dst_sgl) +{ + vmeDmaPacket_t *current_pkt; + vmeDmaPacket_t *previous_pkt; + vmeDmaPacket_t *next_pkt; + int pageno = 0; + + /* Free all pages associated with the packets. */ + current_pkt = user_start_pkt; + previous_pkt = current_pkt; + while (current_pkt != 0) { + next_pkt = current_pkt->pNextPacket; + if (current_pkt + 1 != next_pkt) { + free_pages((int)previous_pkt, 0); + previous_pkt = next_pkt; + } + current_pkt = next_pkt; + pageno++; + } + return (0); +} + +/* + Function : vme_ioctl_user_setup_dma + Description: Create DMA linked list that corresponds to a buffer + in user space. +*/ +vmeDmaPacket_t *vme_ioctl_user_setup_dma(vmeDmaPacket_t * vme_dma, + char *src_addr, + struct scatterlist * src_sgl, + char *dst_addr, + struct scatterlist * dst_sgl, + int *return_status) +{ + int max_per_page; + int current_pktcount; + vmeDmaPacket_t *user_start_pkt; + vmeDmaPacket_t *current_pkt; + int remainingbytecount; + int thispacketbytecount; + + max_per_page = PAGESIZE / sizeof(vmeDmaPacket_t) - 1; + user_start_pkt = (vmeDmaPacket_t *) __get_free_pages(GFP_KERNEL, 0); + if (user_start_pkt == 0) { + *return_status = -ENOMEM; + return (0); + } + + /* First allocate pages for packets and create linked list */ + remainingbytecount = vme_dma->byteCount; + current_pkt = user_start_pkt; + current_pktcount = 0; + while (remainingbytecount > 0) { + memcpy(current_pkt, vme_dma, sizeof(vmeDmaPacket_t)); + current_pkt->pNextPacket = 0; + + /* Calculate # of bytes for this DMA packet. */ + thispacketbytecount = PAGESIZE; + if (src_sgl != 0) { + thispacketbytecount = src_sgl->length; + } + if (dst_sgl != 0) { + thispacketbytecount = dst_sgl->length; + } + if (thispacketbytecount > remainingbytecount) { + thispacketbytecount = remainingbytecount; + } + /* Setup Source address for this packet */ + switch (vme_dma->srcBus) { + case VME_DMA_USER: + current_pkt->srcAddr = (unsigned int) + kmap(src_sgl->page) + src_sgl->offset; + current_pkt->srcBus = VME_DMA_KERNEL; + break; + case VME_DMA_PATTERN_BYTE: + case VME_DMA_PATTERN_WORD: + break; + case VME_DMA_PATTERN_WORD_INCREMENT: + current_pkt->srcAddr = (unsigned int)src_addr; + src_addr += (thispacketbytecount / 4); + break; + case VME_DMA_PATTERN_BYTE_INCREMENT: + default: + current_pkt->srcAddr = (unsigned int)src_addr; + src_addr += thispacketbytecount; + break; + } + if (current_pkt->srcBus == VME_DMA_KERNEL) { + current_pkt->srcAddr = + virt_to_bus((void *)current_pkt->srcAddr); + current_pkt->srcBus = VME_DMA_PCI; + } + /* Setup destination address for this packet */ + switch (vme_dma->dstBus) { + case VME_DMA_USER: + current_pkt->dstAddr = (unsigned int) + kmap(dst_sgl->page) + dst_sgl->offset; + current_pkt->dstBus = VME_DMA_KERNEL; + break; + default: + current_pkt->dstAddr = (unsigned int)dst_addr; + dst_addr += thispacketbytecount; + break; + } + if (current_pkt->dstBus == VME_DMA_KERNEL) { + current_pkt->dstAddr = + virt_to_bus((void *)current_pkt->dstAddr); + current_pkt->dstBus = VME_DMA_PCI; + } + + current_pkt->byteCount = thispacketbytecount; + + remainingbytecount -= thispacketbytecount; + if (remainingbytecount > 0) { + current_pkt->pNextPacket = current_pkt + 1; + current_pktcount++; + if (current_pktcount >= max_per_page) { + current_pkt->pNextPacket = (vmeDmaPacket_t *) + __get_free_pages(GFP_KERNEL, 0); + current_pktcount = 0; + } + } + current_pkt = current_pkt->pNextPacket; + if (src_sgl != NULL) + src_sgl++; + if (dst_sgl != NULL) + dst_sgl++; + } + + /* Return to packets list */ + *return_status = 0; + return (user_start_pkt); +} + +//----------------------------------------------------------------------------- +// Function : vme_do_user_dma +// Description: Setup and perform a VME DMA to/from a buffer in user space. +//----------------------------------------------------------------------------- +int vme_do_user_dma(vmeDmaPacket_t * start_pkt) +{ + struct scatterlist *src_sgl = 0; + struct scatterlist *dst_sgl = 0; + int result = 0; + vmeDmaPacket_t *newstart_pkt; + int nr_pages = 0; + + // allocate scatter gather lists as needed for source & destination + if (start_pkt->srcBus == VME_DMA_USER) { + nr_pages = + ((start_pkt->srcAddr & ~PAGE_MASK) + start_pkt->byteCount - + 1 + ~PAGE_MASK) + >> PAGE_SHIFT; + src_sgl = (struct scatterlist *) + kmalloc(sizeof(struct scatterlist) * nr_pages, GFP_KERNEL); + if (src_sgl == NULL) + return (-ENOMEM); + } + if (start_pkt->dstBus == VME_DMA_USER) { + nr_pages = + ((start_pkt->dstAddr & ~PAGE_MASK) + start_pkt->byteCount - + 1 + ~PAGE_MASK) + >> PAGE_SHIFT; + dst_sgl = (struct scatterlist *) + kmalloc(sizeof(struct scatterlist) * nr_pages, GFP_KERNEL); + if (dst_sgl == NULL) { + if (src_sgl != 0) + kfree(src_sgl); + return (-ENOMEM); + } + } + + if (src_sgl != 0) { + result = sgl_map_user_pages(src_sgl, nr_pages, + start_pkt->srcAddr, + start_pkt->byteCount, WRITE); + if (result <= 0) { + if (src_sgl != 0) + kfree(src_sgl); + if (dst_sgl != 0) + kfree(dst_sgl); + return (-ENOMEM); + } + } + + if (dst_sgl != 0) { + result = sgl_map_user_pages(dst_sgl, nr_pages, + start_pkt->dstAddr, + start_pkt->byteCount, READ); + if (result <= 0) { + if (src_sgl != 0) + sgl_unmap_user_pages(src_sgl, nr_pages, 0); + if (src_sgl != 0) + kfree(src_sgl); + if (dst_sgl != 0) + kfree(dst_sgl); + return (-ENOMEM); + } + } + + newstart_pkt = vme_ioctl_user_setup_dma(start_pkt, + (char *)start_pkt->srcAddr, + src_sgl, + (char *)start_pkt->dstAddr, + dst_sgl, &result); + + if (result == 0) { + result = vme_do_dma(newstart_pkt); + memcpy(start_pkt, newstart_pkt, sizeof(vmeDmaPacket_t)); + start_pkt->pNextPacket = 0; + vme_ioctl_user_free_dma(newstart_pkt, src_sgl, dst_sgl); + } + + if (src_sgl != 0) + sgl_unmap_user_pages(src_sgl, nr_pages, 0); + if (dst_sgl != 0) + sgl_unmap_user_pages(dst_sgl, nr_pages, 1); + if (src_sgl != 0) + kfree(src_sgl); + if (dst_sgl != 0) + kfree(dst_sgl); + + return (result); +} + +#else + +//----------------------------------------------------------------------------- +// Function : vme_ioctl_user_free_dma +// Description: Free the pages that comprise the linked list of DMA packets. +//----------------------------------------------------------------------------- +int +vme_ioctl_user_free_dma(vmeDmaPacket_t * user_start_pkt, + struct kiobuf *src_kiobuf, struct kiobuf *dst_kiobuf) +{ + vmeDmaPacket_t *current_pkt; + vmeDmaPacket_t *previous_pkt; + vmeDmaPacket_t *next_pkt; + int pageno = 0; + + // Free all pages associated with the packets. + current_pkt = user_start_pkt; + previous_pkt = current_pkt; + while (current_pkt != 0) { + if (src_kiobuf != 0) { + kunmap(src_kiobuf->maplist[pageno]); + } + if (dst_kiobuf != 0) { + kunmap(dst_kiobuf->maplist[pageno]); + } + next_pkt = current_pkt->pNextPacket; + if (current_pkt + 1 != next_pkt) { + free_pages((int)previous_pkt, 0); + previous_pkt = next_pkt; + } + current_pkt = next_pkt; + pageno++; + } + return (0); +} + +//----------------------------------------------------------------------------- +// Function : vme_ioctl_user_setup_dma +// Description: Create DMA linked list that corresponds to a buffer +// in user space. +//----------------------------------------------------------------------------- +vmeDmaPacket_t *vme_ioctl_user_setup_dma(vmeDmaPacket_t * vme_dma, + char *src_addr, + struct kiobuf * src_kiobuf, + char *dst_addr, + struct kiobuf * dst_kiobuf, + int *return_status) +{ + int max_per_page; + int current_pktcount; + vmeDmaPacket_t *user_start_pkt; + vmeDmaPacket_t *current_pkt; + int pageno = 0; + int remainingbytecount; + int thispacketbytecount; + + max_per_page = PAGESIZE / sizeof(vmeDmaPacket_t) - 1; + user_start_pkt = (vmeDmaPacket_t *) __get_free_pages(GFP_KERNEL, 0); + if (user_start_pkt == 0) { + *return_status = -ENOMEM; + return (0); + } + // First allocate pages for packets and create linked list + remainingbytecount = vme_dma->byteCount; + current_pkt = user_start_pkt; + current_pktcount = 0; + while (remainingbytecount > 0) { + memcpy(current_pkt, vme_dma, sizeof(vmeDmaPacket_t)); + current_pkt->pNextPacket = 0; + + // Calculate # of bytes for this DMA packet. + thispacketbytecount = PAGESIZE; + if (src_kiobuf != 0) { + if (src_kiobuf->offset != 0) { + thispacketbytecount = + PAGESIZE - src_kiobuf->offset; + } + } + if (dst_kiobuf != 0) { + if (dst_kiobuf->offset != 0) { + thispacketbytecount = + PAGESIZE - dst_kiobuf->offset; + } + } + if (thispacketbytecount > remainingbytecount) { + thispacketbytecount = remainingbytecount; + } + // Setup Source address for this packet + switch (vme_dma->srcBus) { + case VME_DMA_USER: + current_pkt->srcAddr = (unsigned int) + kmap(src_kiobuf->maplist[pageno]) + + src_kiobuf->offset; + src_kiobuf->offset += thispacketbytecount; + if (src_kiobuf->offset == PAGESIZE) { + src_kiobuf->offset = 0; + } + current_pkt->srcBus = VME_DMA_KERNEL; + break; + case VME_DMA_PATTERN_BYTE: + case VME_DMA_PATTERN_WORD: + break; + case VME_DMA_PATTERN_WORD_INCREMENT: + current_pkt->srcAddr = (unsigned int)src_addr; + src_addr += (thispacketbytecount / 4); + break; + case VME_DMA_PATTERN_BYTE_INCREMENT: + default: + current_pkt->srcAddr = (unsigned int)src_addr; + src_addr += thispacketbytecount; + break; + } + if (current_pkt->srcBus == VME_DMA_KERNEL) { + current_pkt->srcAddr = + virt_to_bus((void *)current_pkt->srcAddr); + current_pkt->srcBus = VME_DMA_PCI; + } + // Setup destination address for this packet + switch (vme_dma->dstBus) { + case VME_DMA_USER: + current_pkt->dstAddr = (unsigned int) + kmap(dst_kiobuf->maplist[pageno]) + + dst_kiobuf->offset; + dst_kiobuf->offset += thispacketbytecount; + if (dst_kiobuf->offset == PAGESIZE) { + dst_kiobuf->offset = 0; + } + current_pkt->dstBus = VME_DMA_KERNEL; + break; + default: + current_pkt->dstAddr = (unsigned int)dst_addr; + dst_addr += thispacketbytecount; + break; + } + if (current_pkt->dstBus == VME_DMA_KERNEL) { + current_pkt->dstAddr = + virt_to_bus((void *)current_pkt->dstAddr); + current_pkt->dstBus = VME_DMA_PCI; + } + + current_pkt->byteCount = thispacketbytecount; + + remainingbytecount -= thispacketbytecount; + if (remainingbytecount > 0) { + current_pkt->pNextPacket = current_pkt + 1; + current_pktcount++; + if (current_pktcount >= max_per_page) { + current_pkt->pNextPacket = (vmeDmaPacket_t *) + __get_free_pages(GFP_KERNEL, 0); + current_pktcount = 0; + } + } + current_pkt = current_pkt->pNextPacket; + pageno++; + } + + // Return to packets list + *return_status = 0; + return (user_start_pkt); +} + +//----------------------------------------------------------------------------- +// Function : vme_do_user_dma +// Description: Setup and perform a VME DMA to/from a buffer in user space. +//----------------------------------------------------------------------------- +int vme_do_user_dma(vmeDmaPacket_t * start_pkt) +{ + struct kiobuf *src_iobuf = 0; + struct kiobuf *dst_iobuf = 0; + int result = 0; + vmeDmaPacket_t *newstart_pkt; + + // allocate kiovecs as needed for source & destination + if (start_pkt->srcBus == VME_DMA_USER) { + if (alloc_kiovec(1, &src_iobuf)) { + return (-ENOMEM); + } + } + if (start_pkt->dstBus == VME_DMA_USER) { + if (alloc_kiovec(1, &dst_iobuf)) { + if (src_iobuf != 0) + free_kiovec(1, &src_iobuf); + return (-ENOMEM); + } + } + + if (src_iobuf != 0) + result = map_user_kiobuf(WRITE, src_iobuf, + start_pkt->srcAddr, + start_pkt->byteCount); + if (result) { + if (src_iobuf != 0) + free_kiovec(1, &src_iobuf); + if (dst_iobuf != 0) + free_kiovec(1, &dst_iobuf); + return (-ENOMEM); + } + if (dst_iobuf != 0) + result = map_user_kiobuf(READ, dst_iobuf, + start_pkt->dstAddr, + start_pkt->byteCount); + if (result) { + if (src_iobuf != 0) + unmap_kiobuf(src_iobuf); + if (src_iobuf != 0) + free_kiovec(1, &src_iobuf); + if (dst_iobuf != 0) + free_kiovec(1, &dst_iobuf); + return (-ENOMEM); + } + + newstart_pkt = vme_ioctl_user_setup_dma(start_pkt, + (char *)start_pkt->srcAddr, + src_iobuf, + (char *)start_pkt->dstAddr, + dst_iobuf, &result); + + if (result == 0) { + result = vme_do_dma(newstart_pkt); + memcpy(start_pkt, newstart_pkt, sizeof(vmeDmaPacket_t)); + start_pkt->pNextPacket = 0; + vme_ioctl_user_free_dma(newstart_pkt, src_iobuf, dst_iobuf); + } + + if (src_iobuf != 0) + unmap_kiobuf(src_iobuf); + if (dst_iobuf != 0) + unmap_kiobuf(dst_iobuf); + if (src_iobuf != 0) + free_kiovec(1, &src_iobuf); + if (dst_iobuf != 0) + free_kiovec(1, &dst_iobuf); + + return (result); +} +#endif + +/* + Function : vme_ioctl_free_dma + Description: Free the pages associated with the linked list of DMA packets. +*/ +int vme_ioctl_free_dma(vmeDmaPacket_t * start_pkt) +{ + vmeDmaPacket_t *current_pkt; + vmeDmaPacket_t *previous_pkt; + vmeDmaPacket_t *next_pkt; + + /* Free all pages associated with the packets. */ + current_pkt = start_pkt; + previous_pkt = current_pkt; + while (current_pkt != 0) { + next_pkt = current_pkt->pNextPacket; + if (current_pkt + 1 != next_pkt) { + free_pages((int)previous_pkt, 0); + previous_pkt = next_pkt; + } + current_pkt = next_pkt; + } + return (0); +} + +/* + Function : vme_ioctl_setup_dma + Description: + Read descriptors from user space and create a linked list + of DMA packets. +*/ +vmeDmaPacket_t *vme_ioctl_setup_dma(vmeDmaPacket_t * vme_dma, + int *return_status) +{ + vmeDmaPacket_t *vme_current; + int max_per_page; + int current_pktcount; + vmeDmaPacket_t *start_pkt; + vmeDmaPacket_t *current_pkt; + + max_per_page = PAGESIZE / sizeof(vmeDmaPacket_t) - 1; + start_pkt = (vmeDmaPacket_t *) __get_free_pages(GFP_KERNEL, 0); + if (start_pkt == 0) { + *return_status = -ENOMEM; + return (0); + } + /* First allocate pages for packets and create linked list */ + vme_current = vme_dma; + current_pkt = start_pkt; + current_pktcount = 0; + + while (vme_current != 0) { + if (copy_from_user + (current_pkt, vme_current, sizeof(vmeDmaPacket_t))) { + current_pkt->pNextPacket = 0; + vme_ioctl_free_dma(start_pkt); + *return_status = -EFAULT; + return (0); + } + if (current_pkt != start_pkt) { + if ((current_pkt->srcBus == VME_DMA_USER) || + (current_pkt->dstBus == VME_DMA_USER)) { + current_pkt->pNextPacket = 0; + vme_ioctl_free_dma(start_pkt); + *return_status = -EINVAL; + return (0); + } + } + if (current_pkt->srcBus == VME_DMA_KERNEL) { + current_pkt->srcAddr = + virt_to_bus((void *)current_pkt->srcAddr); + } + if (current_pkt->dstBus == VME_DMA_KERNEL) { + current_pkt->dstAddr = + virt_to_bus((void *)current_pkt->dstAddr); + } + if (current_pkt->pNextPacket == NULL) { + break; + } + vme_current = current_pkt->pNextPacket; + + current_pkt->pNextPacket = current_pkt + 1; + current_pktcount++; + if (current_pktcount >= max_per_page) { + current_pkt->pNextPacket = + (vmeDmaPacket_t *) __get_free_pages(GFP_KERNEL, 0); + current_pktcount = 0; + } + current_pkt = current_pkt->pNextPacket; + } + + /* Return to packets list */ + *return_status = 0; + return (start_pkt); +} + +//----------------------------------------------------------------------------- +// Function : vme_ioctl_dma() +// Inputs : +// User pointer to DMA packet (possibly chained) +// DMA channel number. +// Outputs : returns 0 on success, error code on failure. +// Description: +// Copy DMA chain into kernel space. +// Verify validity of chain. +// Wait, if needed, for DMA channel to be available. +// Do the DMA operation. +// Free the DMA channel. +// Copy the DMA packet with status back to user space. +// Free resources allocated by this operation. +// Remarks : +// Note, due to complexity, DMA to/from a user space buffer is dealt with +// via a separate routine. +// History : +//----------------------------------------------------------------------------- +int vme_ioctl_dma(vmeDmaPacket_t * vme_dma, int channel) +{ + + vmeDmaPacket_t *start_pkt; + int status = 0; + + // Read the (possibly linked) descriptors from the user + start_pkt = vme_ioctl_setup_dma(vme_dma, &status); + if (status < 0) { + return (status); + } + + start_pkt->channel_number = channel; + if (start_pkt->byteCount <= 0) { + vme_ioctl_free_dma(start_pkt); + return (-EINVAL); + } + // If user to user mode, buffers must be page aligned. + if ((start_pkt->srcBus == VME_DMA_USER) && + (start_pkt->dstBus == VME_DMA_USER)) { + if ((start_pkt->dstAddr & (PAGESIZE - 1)) != + (start_pkt->srcAddr & (PAGESIZE - 1))) { + vme_ioctl_free_dma(start_pkt); + return (-EINVAL); + } + } + // user mode DMA can only support one DMA packet. + if ((start_pkt->srcBus == VME_DMA_USER) || + (start_pkt->dstBus == VME_DMA_USER)) { + if (start_pkt->pNextPacket != NULL) { + vme_ioctl_free_dma(start_pkt); + return (-EINVAL); + } + } + // Wait for DMA channel to be available. + if (down_interruptible(&devinuse[channel + VME_MINOR_DMA])) { + vme_ioctl_free_dma(start_pkt); + return (-ERESTARTSYS); + } + // Do the DMA. + if ((start_pkt->srcBus == VME_DMA_USER) || + (start_pkt->dstBus == VME_DMA_USER)) { + status = vme_do_user_dma(start_pkt); + } else { + status = vme_do_dma(start_pkt); + } + + // Free the DMA channel. + up(&devinuse[channel + VME_MINOR_DMA]); + + // Copy the result back to the user. + if (copy_to_user(vme_dma, start_pkt, sizeof(vmeDmaPacket_t))) { + vme_ioctl_free_dma(start_pkt); + return (-EFAULT); + } + // Free the linked list. + vme_ioctl_free_dma(start_pkt); + return (status); +} + +//---------------------------------------------------------------------------- +// +// vme_poll() +// Place holder - this driver function not implemented. +// +//---------------------------------------------------------------------------- +static unsigned int vme_poll(struct file *file, poll_table * wait) +{ + return 0; +} + +static int vme_mmap(struct file *file, struct vm_area_struct *vma) +{ + int minor; + int ret = 0; + + if ((!file) || (!vma)) + return -ENXIO; + minor = MINOR(file->f_dentry->d_inode->i_rdev); + + if ((minor < 0) || (minor > 15)) + return -EINVAL; + + if (minor > 7) { + /* Inbound windows */ + minor -= 8; + + if (vma->vm_pgoff) + return -EINVAL; /* want no offset */ + + /* + * Lock a read or write against an mmap. + */ + down(&in_image_sem[minor]); + ret = -EAGAIN; + if (remap_pfn_range(vma, + vma->vm_start, + in_image_pa[minor] >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) + goto mmap_in; + in_image_mapped[minor] = 1; + ret = 0; +mmap_in: + up(&in_image_sem[minor]); + return ret; + } else { + unsigned long vsize = vma->vm_end - vma->vm_start; + unsigned long psize; + + /* Outbound windows */ + if (out_image_va[minor] == 0) + return (-EINVAL); + + psize = out_resource[minor].end - out_resource[minor].start + 1; + if (vsize > psize) + return -EINVAL; + /* + * Lock a read or write against an mmap. + */ + down(&out_image_sem[minor]); + ret = -EAGAIN; + vma->vm_page_prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; + if (io_remap_pfn_range(vma, + vma->vm_start, + (out_resource[minor].start - + pci_bus_mem_base_phys(vmechip_bus)) >> + PAGE_SHIFT, vma->vm_end - vma->vm_start, + vma->vm_page_prot)) + goto mmap_out; + out_image_mapped[minor] = 1; + ret = 0; +mmap_out: + up(&out_image_sem[minor]); + return ret; + } +} + +/* + Function : vme_open() + Inputs : standard Linux device driver open arguments. + Outputs : returns 0 on success, error code on failure. + Description: + Verify device is valid, + If device is exclusive use and already open, return -EBUSY + Increment device use count. +*/ +static int vme_open(struct inode *inode, struct file *file) +{ + unsigned int minor = iminor(inode); + int minor_flags; + + /* Check for valid minor num */ + minor_flags = vme_minor_type(minor); + if (!minor_flags) + return -ENODEV; + + /* Restrict exclusive use devices to one open */ + if ((minor_flags & DEV_EXCLUSIVE) && + test_and_set_bit(0, &opened[minor])) + return -EBUSY; + return (0); +} + +/* + Function : vme_release() + Inputs : standard Linux device driver release arguments. + Outputs : returns 0. + Description: + Decrement use count and return. +*/ +static int vme_release(struct inode *inode, struct file *file) +{ + unsigned int minor = iminor(inode); + int minor_flags; + + minor_flags = vme_minor_type(minor); + if ((minor & VME_MINOR_TYPE_MASK) == VME_MINOR_OUT) { + int decoder_num; + + decoder_num = minor & 0xF; /* Get outbound window num */ + + if (decoder_num < 8) + out_image_mapped[decoder_num] = 0; + else + in_image_mapped[decoder_num - 8] = 0; + } + clear_bit(0, &opened[minor]); + + return 0; +} + +//----------------------------------------------------------------------------- +// Function : vme_read() +// Inputs : standard linux device driver read() arguments. +// Outputs : count of bytes read or error code. +// Description: +// Sanity check inputs, +// If register read, write user buffer from chip registers +// If VME window read, find the outbound window and read data +// through the window. Return number of bytes successfully read. +// Remarks : +// History : +//----------------------------------------------------------------------------- +static ssize_t vme_read(struct file *file, char *buf, size_t count, + loff_t * ppos) +{ + int x = 0; + int decoder_num; + int okcount = 0; + char *image_p; + unsigned int v, numt, remain; + char *temp = buf; + unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int foffset; + + unsigned char vc; + unsigned short vs; + unsigned int vl; + int minor_flags; + int image_size; + + minor_flags = vme_minor_type(minor); + if (!(minor_flags & DEV_RW)) { + return (-EINVAL); + } + + if (*ppos > 0xFFFFFFFF) { + return (-EINVAL); + } + foffset = *ppos; + + if (minor == VME_MINOR_REGS) { + if ((count != 4) || (foffset & (4 - 1))) { /* word access only */ + return (-EINVAL); + } + if (foffset >= 0x1000) { /* Truncate at end of reg image */ + return (0); + } + v = vme_chip_reg_read((unsigned int *)(vmechip_baseaddr + + foffset)); + __copy_to_user(temp, &v, 4); + } + + if ((minor & VME_MINOR_TYPE_MASK) == VME_MINOR_OUT) { + + decoder_num = minor & 0xF; /* Get outbound window num */ + + if (decoder_num < 8) { + if (out_image_va[decoder_num] == 0) { + return (-EINVAL); + } + if (out_image_mapped[decoder_num]) + return -ENXIO; + image_size = + out_resource[decoder_num].end - + out_resource[decoder_num].start + 1; + if (foffset >= image_size) { + return (0); + } + down(&out_image_sem[decoder_num]); + if ((foffset + count) > image_size) { + count = image_size - foffset; + } + reads++; + image_p = (char *)(out_image_va[decoder_num] + foffset); + + // Calc the number of longs we need + numt = count / 4; + remain = count % 4; + for (x = 0; x < numt; x++) { + vl = *(int *)(image_p); + + // Lets Check for a Bus Error + if (vme_bus_error_chk(1)) { + up(&out_image_sem[decoder_num]); + return (okcount); + } + okcount += 4; + + __copy_to_user(temp, &vl, 4); + image_p += 4; + temp += 4; + } + + // Calc the number of Words we need + numt = remain / 2; + remain = remain % 2; + for (x = 0; x < numt; x++) { + vs = *(short *)(image_p); + + // Lets Check for a Bus Error + if (vme_bus_error_chk(1)) { + up(&out_image_sem[decoder_num]); + return (okcount); + } + okcount += 2; + + __copy_to_user(temp, &vs, 2); + image_p += 2; + temp += 2; + } + + for (x = 0; x < remain; x++) { + vc = readb(image_p); + + // Lets Check for a Bus Error + if (vme_bus_error_chk(1)) { + up(&out_image_sem[decoder_num]); + return (okcount); + } + okcount++; + + __copy_to_user(temp, &vc, 1); + image_p += 1; + temp += 1; + } + up(&out_image_sem[decoder_num]); + } else { /* inbound windows */ + decoder_num -= 8; + if (in_image_ba[decoder_num] == 0) + return -EINVAL; + if (in_image_mapped[decoder_num]) + return -ENXIO; + image_size = in_image_size[decoder_num]; + if (foffset >= image_size) { + return (0); + } + down(&in_image_sem[decoder_num]); + if ((foffset + count) > image_size) { + count = image_size - foffset; + } + reads++; + image_p = (char *)(in_image_ba[decoder_num] + foffset); + + // Calc the number of longs we need + numt = count / 4; + remain = count % 4; + for (x = 0; x < numt; x++) { + vl = *(int *)(image_p); + __copy_to_user(temp, &vl, 4); + image_p += 4; + temp += 4; + } + + // Calc the number of Words we need + numt = remain / 2; + remain = remain % 2; + for (x = 0; x < numt; x++) { + vs = *(short *)(image_p); + __copy_to_user(temp, &vs, 2); + image_p += 2; + temp += 2; + } + + for (x = 0; x < remain; x++) { + vc = *(char *)(image_p); + __copy_to_user(temp, &vc, 1); + image_p += 1; + temp += 1; + } + up(&in_image_sem[decoder_num]); + } + } + + if (((minor & VME_MINOR_TYPE_MASK) == VME_MINOR_SLOTS1) || + ((minor & VME_MINOR_TYPE_MASK) == VME_MINOR_SLOTS2)) { + return (-EINVAL); /* Not implemented yet */ + } + *ppos += count; + return (count); +} + +//----------------------------------------------------------------------------- +// Function : vme_write() +// Inputs : standard linux device driver write() arguments. +// Outputs : count of bytes written or error code. +// Description: +// Sanity check inputs, +// If register write, write VME chip registers with the user data +// If VME window write, find the outbound window and write user data +// through the window. Return number of bytes successfully written. +// Remarks : +// History : +//----------------------------------------------------------------------------- +static ssize_t vme_write(struct file *file, const char *buf, size_t count, + loff_t * ppos) +{ + int x; + int decoder_num; + char *image_p; + int okcount = 0; + unsigned int numt, remain; + char *temp = (char *)buf; + unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int foffset; + + unsigned char vc; + unsigned short vs; + unsigned int vl; + int minor_flags; + int image_size; + + minor_flags = vme_minor_type(minor); + if (!(minor_flags & DEV_RW)) { + return (-EINVAL); + } + + if (*ppos > 0xFFFFFFFF) { + return (-EINVAL); + } + foffset = *ppos; + + writes++; + if (minor == VME_MINOR_REGS) { + if ((count != 4) || (foffset & (4 - 1))) { /* word access only */ + return (-EINVAL); + } + if (foffset >= 0x1000) { /* Truncate at end of reg image */ + return (0); + } + __copy_from_user(&vl, temp, 4); + vme_chip_reg_write((unsigned int *)(vmechip_baseaddr + foffset), + vl); + } + + if ((minor & VME_MINOR_TYPE_MASK) == VME_MINOR_OUT) { + + decoder_num = minor & 0xF; /* Get outbound window num */ + if (decoder_num < 8) { + if (out_image_va[decoder_num] == 0) { + return (-EINVAL); + } + if (out_image_mapped[decoder_num]) + return -ENXIO; + + image_size = + out_resource[decoder_num].end - + out_resource[decoder_num].start; + + if (foffset >= image_size) { + return (0); + } + down(&out_image_sem[decoder_num]); + if ((foffset + count) > image_size) { + count = image_size - foffset; + } + // Calc the number of longs we need + numt = count / 4; + remain = count % 4; + image_p = (char *)(out_image_va[decoder_num] + foffset); + + for (x = 0; x < numt; x++) { + __copy_from_user(&vl, temp, 4); + *(int *)image_p = vl; + + // Lets Check for a Bus Error + if (vme_bus_error_chk(1)) { + up(&out_image_sem[decoder_num]); + return (okcount); + } else + okcount += 4; + + image_p += 4; + temp += 4; + } + + // Calc the number of Words we need + numt = remain / 2; + remain = remain % 2; + + for (x = 0; x < numt; x++) { + __copy_from_user(&vs, temp, 2); + writew(vs, image_p); + + // Lets Check for a Bus Error + if (vme_bus_error_chk(1)) { + up(&out_image_sem[decoder_num]); + return (okcount); + } else + okcount += 2; + + image_p += 2; + temp += 2; + } + + for (x = 0; x < remain; x++) { + __copy_from_user(&vc, temp, 1); + writeb(vc, image_p); + + // Lets Check for a Bus Error + if (vme_bus_error_chk(1)) { + up(&out_image_sem[decoder_num]); + return (okcount); + } else + okcount += 2; + + image_p += 1; + temp += 1; + } + up(&out_image_sem[decoder_num]); + } else { /* inbound windows */ + decoder_num -= 8; + if (in_image_ba[decoder_num] == 0) + return -EINVAL; + if (in_image_mapped[decoder_num]) + return -ENXIO; + + image_size = in_image_size[decoder_num]; + + if (foffset >= image_size) { + return (0); + } + down(&in_image_sem[decoder_num]); + if ((foffset + count) > image_size) { + count = image_size - foffset; + } + // Calc the number of longs we need + numt = count / 4; + remain = count % 4; + image_p = (char *)(in_image_ba[decoder_num] + foffset); + + for (x = 0; x < numt; x++) { + __copy_from_user(&vl, temp, 4); + *(int *)image_p = vl; + image_p += 4; + temp += 4; + } + + // Calc the number of Words we need + numt = remain / 2; + remain = remain % 2; + + for (x = 0; x < numt; x++) { + __copy_from_user(&vs, temp, 2); + *(short *)image_p = vs; + image_p += 2; + temp += 2; + } + + for (x = 0; x < remain; x++) { + __copy_from_user(&vc, temp, 1); + *(char *)image_p = vc; + image_p += 1; + temp += 1; + } + up(&in_image_sem[decoder_num]); + } + } + + if (((minor & VME_MINOR_TYPE_MASK) == VME_MINOR_SLOTS1) || + ((minor & VME_MINOR_TYPE_MASK) == VME_MINOR_SLOTS2)) { + return (-EINVAL); /* Not implemented yet */ + } + + *ppos += count; + return (count); +} + +//----------------------------------------------------------------------------- +// Function : vme_ioctl() +// Inputs : +// cmd -> the IOCTL command +// arg -> pointer (if any) to the user ioctl buffer +// Outputs : 0 for sucess or errorcode for failure. +// Description: +// Copy in, if needed, the user input buffer pointed to by arg. +// Call vme driver to perform actual ioctl +// Copy out, if needed, the user output buffer pointed to be arg. +// Remarks : +// History : +//----------------------------------------------------------------------------- +static int vme_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned int minor = iminor(inode); + vmeOutWindowCfg_t vme_out; + vmeInfoCfg_t vme_info; + vmeRequesterCfg_t vme_req; + vmeArbiterCfg_t vme_arb; + vmeInWindowCfg_t vme_in; + virqInfo_t vme_irq; + vmeRmwCfg_t vme_rmw; + vmeLmCfg_t vme_lm; + int status; + + ioctls++; + + switch (minor & VME_MINOR_TYPE_MASK) { + case VME_MINOR_OUT: + switch (cmd) { + case VME_IOCTL_GET_OUTBOUND: + if (copy_from_user + (&vme_out, (void *)arg, sizeof(vme_out))) + return -EFAULT; + status = vme_get_out_bound(&vme_out); + if (status != 0) + return (status); + if (copy_to_user + ((void *)arg, &vme_out, sizeof(vme_out))) + return -EFAULT; + break; + case VME_IOCTL_SET_OUTBOUND: + if (copy_from_user + (&vme_out, (void *)arg, sizeof(vme_out))) + return -EFAULT; + if ((vme_out.windowNbr < 0) || (vme_out.windowNbr > 7)) + return -EINVAL; + if (out_image_mapped[vme_out.windowNbr]) + return -ENXIO; + + status = vme_set_out_bound(&vme_out); + if (status != 0) + return (status); + break; + default: + return -EINVAL; + } + break; + + case VME_MINOR_DMA: + switch (cmd) { + case VME_IOCTL_PAUSE_DMA: + case VME_IOCTL_CONTINUE_DMA: + case VME_IOCTL_ABORT_DMA: + case VME_IOCTL_WAIT_DMA: + return (-EINVAL); /* Not supported for now. */ + break; + case VME_IOCTL_START_DMA: + status = + vme_ioctl_dma((vmeDmaPacket_t *) arg, + minor - VME_MINOR_DMA); + if (status != 0) + return (status); + break; + default: + return (-EINVAL); + } + break; + + case VME_MINOR_MISC: + switch (minor) { + case VME_MINOR_CTL: + switch (cmd) { + case VME_IOCTL_GET_SLOT_VME_INFO: + if (copy_from_user + (&vme_info, (void *)arg, sizeof(vme_info))) + return (-EFAULT); + status = vme_get_slot_info(&vme_info); + if (status != 0) + return (status); + if (copy_to_user + ((void *)arg, &vme_info, sizeof(vme_info))) + return (-EFAULT); + break; + case VME_IOCTL_SET_REQUESTOR: + if (copy_from_user + (&vme_req, (void *)arg, sizeof(vme_req))) + return (-EFAULT); + status = vme_set_requestor(&vme_req); + if (status != 0) + return (status); + break; + case VME_IOCTL_GET_REQUESTOR: + if (copy_from_user + (&vme_req, (void *)arg, sizeof(vme_req))) + return (-EFAULT); + status = vme_get_requestor(&vme_req); + if (status != 0) + return (status); + if (copy_to_user + ((void *)arg, &vme_req, sizeof(vme_req))) + return (-EFAULT); + break; + case VME_IOCTL_SET_CONTROLLER: + if (copy_from_user + (&vme_arb, (void *)arg, sizeof(vme_arb))) + return (-EFAULT); + status = vme_set_arbiter(&vme_arb); + if (status != 0) + return (status); + if (copy_to_user + ((void *)arg, &vme_arb, sizeof(vme_arb))) + return (-EFAULT); + break; + case VME_IOCTL_GET_CONTROLLER: + status = vme_get_arbiter(&vme_arb); + if (status != 0) + return (status); + if (copy_to_user + ((void *)arg, &vme_arb, sizeof(vme_arb))) + return (-EFAULT); + break; + /* For legacy purposes, VME_IOCTL_GET_INBOUND + * and VME_IOCTL_SET_INBOUND are done here + */ + case VME_IOCTL_SET_INBOUND: + if (copy_from_user + (&vme_in, (void *)arg, sizeof(vme_in))) + return -EFAULT; + if ((vme_in.windowNbr < 0) || + (vme_in.windowNbr > 7)) + return -EINVAL; + if (in_image_mapped[vme_in.windowNbr]) + return -ENXIO; + status = vme_set_in_bound(&vme_in); + if (status != 0) + return (status); + break; + case VME_IOCTL_GET_INBOUND: + if (copy_from_user + (&vme_in, (void *)arg, sizeof(vme_in))) + return -EFAULT; + status = vme_get_in_bound(&vme_in); + if (status != 0) + return (status); + if (copy_to_user + ((void *)arg, &vme_in, sizeof(vme_in))) + return (-EFAULT); + break; + case VME_IOCTL_GENERATE_IRQ: + + if (copy_from_user + (&vme_irq, (void *)arg, sizeof(vme_irq))) + return (-EFAULT); + + // Obtain access to VIRQ generator. + if (down_interruptible(&virq_inuse)) + return (-ERESTARTSYS); + status = vme_generate_irq(&vme_irq); + up(&virq_inuse); // Release VIRQ generator. + + if (status != 0) + return (status); + if (copy_to_user + ((void *)arg, &vme_irq, sizeof(vme_irq))) + return (-EFAULT); + break; + + case VME_IOCTL_GET_IRQ_STATUS: + if (copy_from_user + (&vme_irq, (void *)arg, sizeof(vme_irq))) + return (-EFAULT); + status = vme_get_irq_status(&vme_irq); + if (status != 0) + return (status); + if (copy_to_user + ((void *)arg, &vme_irq, sizeof(vme_irq))) + return (-EFAULT); + break; + case VME_IOCTL_CLR_IRQ_STATUS: + if (copy_from_user + (&vme_irq, (void *)arg, sizeof(vme_irq))) + return (-EFAULT); + status = vme_clr_irq_status(&vme_irq); + if (status != 0) + return (status); + break; + default: + return (-EINVAL); + } + break; + case VME_MINOR_REGS: + return (-EINVAL); + case VME_MINOR_RMW: + if (copy_from_user + (&vme_rmw, (void *)arg, sizeof(vme_rmw))) + return (-EFAULT); + switch (cmd) { + case VME_IOCTL_DO_RMW: + status = vme_do_rmw(&vme_rmw); + if (status != 0) + return (status); + break; + default: + return (-EINVAL); + } + if (copy_to_user + ((void *)arg, &vme_rmw, sizeof(vme_rmw))) + return (-EFAULT); + break; + + case VME_MINOR_LM: + if (copy_from_user + (&vme_lm, (void *)arg, sizeof(vme_lm))) + return (-EFAULT); + switch (cmd) { + case VME_IOCTL_SETUP_LM: + status = vme_setup_lm(&vme_lm); + if (status != 0) + return (status); + break; + case VME_IOCTL_WAIT_LM: + status = vme_wait_lm(&vme_lm); + if (status != 0) + return (status); + break; + default: + return (-EINVAL); + } + if (copy_to_user((void *)arg, &vme_lm, sizeof(vme_lm))) + return (-EFAULT); + break; + + default: + return (-EINVAL); + } + break; + +#if 0 // interboard data channels not implemented yet + case VME_MINOR_SLOTS1: + case VME_MINOR_SLOTS3: + break; +#endif + default: + return (-EINVAL); + } // masked minor + return (status); +} + +//----------------------------------------------------------------------------- +// Function : find_vme_bridge() +// Inputs : void +// Outputs : failed flag. +// Description: +// Search for a supported VME bridge chip. +// Initialize VME config registers. +// Remarks : +// History : +//----------------------------------------------------------------------------- +static +struct pci_dev *find_vme_bridge(void) +{ + struct pci_dev *vme_pci_dev = NULL; + + if ((vme_pci_dev = pci_find_device(PCI_VENDOR_ID_TUNDRA, + PCI_DEVICE_ID_TUNDRA_CA91C042, + vme_pci_dev))) { + vmechip_devid = PCI_DEVICE_ID_TUNDRA_CA91C042; + } + if (vme_pci_dev == NULL) { + if ((vme_pci_dev = pci_find_device(PCI_VENDOR_ID_TUNDRA, + PCI_DEVICE_ID_TUNDRA_TSI148, + vme_pci_dev))) { + vmechip_devid = PCI_DEVICE_ID_TUNDRA_TSI148; + } + } + if (vme_pci_dev == NULL) { + printk(KERN_ERR "vmemod: VME bridge not found on PCI Bus.\n"); + return (vme_pci_dev); + } + // read revision. + pci_read_config_dword(vme_pci_dev, PCI_CLASS_REVISION, + &vmechip_revision); + printk(KERN_DEBUG "vmemod: PCI_CLASS_REVISION = %08x\n", + vmechip_revision); + vmechip_revision &= 0xFF; + + // Unless user has already specified it, + // determine the VMEchip IRQ number. + if (vmechip_irq == 0) { + pci_read_config_dword(vme_pci_dev, PCI_INTERRUPT_LINE, + &vmechip_irq); + printk(KERN_DEBUG "vmemod: PCI_INTLINE = %08x\n", vmechip_irq); + vmechip_irq &= 0x000000FF; // Only a byte in size + if (vmechip_irq == 0) + vmechip_irq = 0x00000050; // Only a byte in size + } + if ((vmechip_irq == 0) || (vmechip_irq == 0xFF)) { + printk(KERN_ERR "vmemod: Bad VME IRQ number: %02x\n", + vmechip_irq); + return (NULL); + } + + return (vme_pci_dev); +} + +//----------------------------------------------------------------------------- +// Function : map_in_vme_bridge() +// Inputs : void +// Outputs : failed flag. +// Description: +// Map VME chip registers in. Perform basic sanity check of chip ID. +// Remarks : +// History : +//----------------------------------------------------------------------------- +int map_in_vme_bridge(struct pci_dev *vme_pci_dev) +{ + unsigned int temp, ba; + + // Setup VME Bridge Register Space + // This is a 4k wide memory area that need to be mapped into the kernel + // virtual memory space so we can access it. + ba = pci_resource_start(vme_pci_dev, 0); + vmechip_baseaddr = (char *)ioremap(ba, 4096); + if (!vmechip_baseaddr) { + printk(" ioremap failed to map VMEchip to Kernel Space.\r"); + return 1; + } + // Check to see if the Mapping Worked out + temp = readl(vmechip_baseaddr) & 0x0000FFFF; + if (temp != PCI_VENDOR_ID_TUNDRA) { + printk(" VME Chip Failed to Return PCI_ID in Memory Map.\n"); + iounmap(vmechip_baseaddr); + return 1; + } + return (0); +} + +//----------------------------------------------------------------------------- +// Function : vme_driver_setup_windows() +// Inputs : void +// Outputs : void +// Description: +// Creates initial inbound & outbound VME windows. +// Remarks : +// History : +//----------------------------------------------------------------------------- +static void vme_driver_setup_windows(void) +{ + vmeOutWindowCfg_t vme_driver_window; + + // Setup the outbound CRCSR window for use by the driver. + memset(&vme_driver_window, 0, sizeof(vme_driver_window)); + vme_driver_window.windowNbr = 7; + vme_driver_window.windowEnable = 1; + vme_driver_window.windowSizeL = (512 * 1024) * 32; + vme_driver_window.xlatedAddrL = 0; + vme_driver_window.wrPostEnable = 1; + vme_driver_window.addrSpace = VME_CRCSR; + vme_driver_window.maxDataWidth = VME_D32; + vme_driver_window.xferProtocol = 0; + vme_driver_window.dataAccessType = VME_DATA; + vme_driver_window.userAccessType = VME_SUPER; + vme_set_out_bound(&vme_driver_window); + +#if 0 + /* Setup the inbound windows */ + if (vme_slotnum > 0) { + vmeInWindowCfg_t vme_in_window; + unsigned int x; + + memset(&vme_in_window, 0, sizeof(vme_in_window)); + if (in_image_size[x] != 0) { + memset(in_image_ba[x], 0, in_image_size[x]); + vme_flush_range(in_image_ba[x], in_image_ba[x] + in_image_size[x]); + vme_in_window.windowNbr = x; + vme_in_window.windowEnable = 1; + vme_in_window.windowSizeL = in_image_size[x]; + vme_in_window.pciAddrL = (unsigned int)in_image_pa[x]; + vme_in_window.vmeAddrL = + 0x80000000 + (vme_slotnum * 0x02000000) + (0x400000 * x); + vme_in_window.wrPostEnable = 1; + vme_in_window.addrSpace = VME_A32; + vme_in_window.xferProtocol = + VME_SCT | VME_BLT | VME_MBLT | VME_2eVME | VME_2eSST; + /* 2eSST Transfer Rate */ + vme_in_window.xferRate2esst = VME_SST320; + vme_in_window.dataAccessType = VME_DATA | VME_PROG; + vme_in_window.userAccessType = VME_SUPER | VME_USER; + vme_set_in_bound(&vme_in_window); + + } + } +#endif +} + +void __init vmemod_setup_options(char *cmdline) +{ + char *options; + + /* + * Look for vme=option on command line + * Accept something like: + * vme=vme_slotnum= + * vme=vme_slotnum=,vmechip_irq= + */ + + options = strstr(cmdline, "vme="); + if (!options) + return; + options = strchr(options, '=') + 1; + if (options && !strncmp(options, "vme_slotnum=", 12)) { + vme_slotnum = simple_strtoul(options + 12, NULL, 0); + options = strchr(options, ','); + if (!options) + return; + if (!strncmp(options + 1, "vmechip_irq=", 12)) { + vmechip_irq = simple_strtoul(options + 13, NULL, 0); + } + } else if (options && !strncmp(options, "vmechip_irq=", 12)) { + vmechip_irq = simple_strtoul(options + 12, NULL, 0); + options = strchr(options, ','); + if (!options) + return; + if (!strncmp(options + 1, "vme_slotnum=", 12)) { + vme_slotnum = simple_strtoul(options + 13, NULL, 0); + } + } + return; +} + +//----------------------------------------------------------------------------- +// Function : cleanup_module +// Inputs : void +// Outputs : void +// Description: +// Initialize VME chip to quiescent state. +// Free driver resources. +// Remarks : +// History : +//----------------------------------------------------------------------------- +static void __exit vme_bridge_exit(void) +{ + int x; + + // Quiesce the hardware. + switch (vmechip_devid) { + case PCI_DEVICE_ID_TUNDRA_CA91C042: + uni_shutdown(); + break; + case PCI_DEVICE_ID_TUNDRA_TSI148: + tsi148_shutdown(); + break; + } + + // Free & unmap resources + free_irq(vmechip_irq, vmechip_baseaddr); + iounmap(vmechip_baseaddr); + vme_free_buffers(); + + for (x = 0; x < 8; x++) { + if (out_image_va[x] != 0) { + iounmap((void *)out_image_va[x]); + out_image_va[x] = 0; + out_image_mapped[x] = 0; + } + if (out_resource[x].end - out_resource[x].start) { + iounmap((void *)out_image_va[x]); + if (out_resource[x].name != NULL) + kfree(out_resource[x].name); + release_resource(&out_resource[x]); + memset(&out_resource[x], 0, sizeof(struct resource)); + } + } + + unregister_proc(); + unregister_chrdev(VME_MAJOR, "vme"); + devfs_remove("vme_m0"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 0)); + devfs_remove("vme_m1"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 1)); + devfs_remove("vme_m2"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 2)); + devfs_remove("vme_m3"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 3)); + devfs_remove("vme_m4"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 4)); + devfs_remove("vme_m5"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 5)); + devfs_remove("vme_m6"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 6)); + devfs_remove("vme_m7"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 7)); + devfs_remove("vme_s0"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 8)); + devfs_remove("vme_s1"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 9)); + devfs_remove("vme_s2"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 10)); + devfs_remove("vme_s3"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 11)); + devfs_remove("vme_s4"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 12)); + devfs_remove("vme_s5"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 13)); + devfs_remove("vme_s6"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 14)); + devfs_remove("vme_s7"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 15)); + devfs_remove("vme_dma0"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 16)); + devfs_remove("vme_dma1"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 17)); + devfs_remove("vme_ctl"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 32)); + devfs_remove("vme_regs"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 33)); + devfs_remove("vme_rmw0"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 34)); + devfs_remove("vme_lm"); + class_device_destroy(vme_class, MKDEV(VME_MAJOR, 35)); + class_destroy(vme_class); +} + +//----------------------------------------------------------------------------- +// Function : init_module() +// Inputs : void +// Outputs : module initialization fail flag +// Description: +// top level module initialization. +// find VME bridge +// initialize VME bridge chip. +// Sanity check bridge chip. +// allocate and initialize driver resources. +// Remarks : +// History : +//----------------------------------------------------------------------------- + +static int __init vme_bridge_init(void) +{ + int x; + unsigned int temp; + struct resource pcimemres; +#ifdef CONFIG_MVME5500 + struct pci_dev *vme_ptp_pci_dev = NULL; +#endif +#ifdef CONFIG_MVME6100 + unsigned int *mv64360; +#endif + + printk("Tundra TSI148/CA91C042 PCI-VME Bridge Driver %s\n", Version); + + // find VME bridge + vme_pci_dev = find_vme_bridge(); + if (vme_pci_dev == NULL) { + return -ENODEV; + } +#ifdef CONFIG_MVME6100 +#define DISABLE_MV64360_SNOOP_WORKAROUND 0 +#ifdef DISABLE_MV64360_SNOOP_WORKAROUND + // This is ugly but needed for now. Disable snoop at 64360. + if (vmechip_devid == PCI_DEVICE_ID_TUNDRA_TSI148) { + mv64360 = (unsigned int *)ioremap(0xF1000000, 0x100000); + mv64360[0x1E00 / 4] = mv64360[0x1E00 / 4] & ~0x0C000000; + vme_sync_data(); + iounmap(mv64360); + } +#endif +#endif + + // Get parent PCI resource & verify enough space is available. + memset(&pcimemres, 0, sizeof(pcimemres)); + pcimemres.flags = IORESOURCE_MEM; + vmepcimem = pci_find_parent_resource(vme_pci_dev, &pcimemres); + if (vmepcimem == 0) { + printk(KERN_ERR + "vmemod: cannot get VME parent device PCI resource\n"); + return -ENODEV; + } +#ifdef CONFIG_MVME5500 +#define VME_BEHIND_BRIDGE_WORKAROUND 1 +#ifdef VME_BEHIND_BRIDGE_WORKAROUND + // If the VME bridge is behind a PCI bridge, only a meg of PCI MEM space + // has been allocated. Bump it up. This is ugly too but is needed + // esp on the MVME5500. + if ((vmepcimem->end - vmepcimem->start + 1) == 0x100000) { + // find bridge VME is under info + vme_ptp_pci_dev = vme_pci_dev->bus->self; + pci_write_config_word(vme_ptp_pci_dev, PCI_MEMORY_BASE, 0x8000); + vmepcimem->start = 0x80000000; + } +#endif +#endif + + if ((vmepcimem->end - vmepcimem->start) < 0x2000000) { + printk(" Not enough PCI memory space available %08x\n", + (unsigned int)(vmepcimem->end - vmepcimem->start)); + return -ENOMEM; + } + // Map in VME Bridge registers. + if (map_in_vme_bridge(vme_pci_dev)) { + return -ENODEV; + } + // Unless, user has already specified it, + // determine the VME slot that we are in. + if (vme_slotnum == -1) { + vme_slotnum = vme_get_slot_num(); + } + if (vme_slotnum <= 0) { + printk(KERN_ERR "Bad VME slot #%02d\n", vme_slotnum); + iounmap(vmechip_baseaddr); + return -ENODEV; + } + // Initialize wait queues & mutual exclusion flags + init_waitqueue_head(&dma_queue[0]); + init_waitqueue_head(&dma_queue[1]); + init_waitqueue_head(&lm_queue); + init_waitqueue_head(&mbox_queue); + sema_init(&virq_inuse, 1); + for (x = 0; x < MAX_MINOR + 1; x++) { + sema_init(&devinuse[x], 1); + } + for (x = 0; x < 8; x++) { + init_MUTEX(&in_image_sem[x]); + } + for (x = 0; x < 8; x++) { + init_MUTEX(&out_image_sem[x]); + } + + // allocate buffers needed by the driver. + if (vme_alloc_buffers() != 0) + return -ENODEV; + + // Initialize the interboard data structure. + if (vmechip_interboard_data != NULL) { + vme_init_interboard_data(vmechip_interboard_data); + } + // Display VME information + printk(KERN_DEBUG + "Vendor = %04X Device = %04X Revision = %02X\n", + vme_pci_dev->vendor, vme_pci_dev->device, vmechip_revision); + printk(KERN_DEBUG "Class = %08X\n", vme_pci_dev->class); + + pci_read_config_dword(vme_pci_dev, PCI_CACHE_LINE_SIZE, &temp); + printk(KERN_DEBUG "Misc0 = %08X\n", temp); + printk(KERN_DEBUG "Irq = %04X\n", vmechip_irq); + if (vme_slotnum == -1) { + printk("VME slot number: unknown\n"); + } else { + printk("VME slot number: %d\n", vme_slotnum); + } + + // Initialize chip registers and register module. + if (!vme_init(vmechip_interboard_data)) { + printk(KERN_ERR "vmemod: VME Chip Initialization failed.\n"); + iounmap(vmechip_baseaddr); + vme_free_buffers(); + return -ENODEV; + } + if (register_chrdev(VME_MAJOR, "vme", &vme_fops)) { + printk(KERN_ERR "vmemod: Unable to get major number.\n"); + iounmap(vmechip_baseaddr); + vme_free_buffers(); + return -ENODEV; + } + vme_class = class_create(THIS_MODULE, "vme"); + class_device_create(vme_class, MKDEV(VME_MAJOR, 0), NULL, "vme_m0"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 0), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_m0"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 1), NULL, "vme_m1"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 1), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_m1"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 2), NULL, "vme_m2"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 2), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_m2"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 3), NULL, "vme_m3"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 3), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_m3"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 4), NULL, "vme_m4"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 4), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_m4"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 5), NULL, "vme_m5"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 5), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_m5"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 6), NULL, "vme_m6"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 6), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_m6"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 7), NULL, "vme_m7"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 7), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_m7"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 8), NULL, "vme_s0"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 8), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_s0"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 9), NULL, "vme_s1"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 9), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_s1"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 10), NULL, "vme_s2"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 10), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_s2"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 11), NULL, "vme_s3"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 11), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_s3"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 12), NULL, "vme_s4"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 12), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_s4"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 13), NULL, "vme_s5"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 13), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_s5"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 14), NULL, "vme_s6"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 14), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_s6"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 15), NULL, "vme_s7"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 15), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_s7"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 16), NULL, "vme_dma0"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 16), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_dma0"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 17), NULL, "vme_dma1"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 17), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_dma1"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 32), NULL, "vme_ctl"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 32), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_ctl"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 33), NULL, "vme_regs"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 33), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_regs"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 34), NULL, "vme_rmw0"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 34), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_rmw0"); + + class_device_create(vme_class, MKDEV(VME_MAJOR, 35), NULL, "vme_lm0"); + devfs_mk_cdev(MKDEV(VME_MAJOR, 35), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, "vme_lm0"); + + if (vme_syscon == 0) { + printk("Board is not the VME system controller\n"); + } + if (vme_syscon == 1) { + printk("Board is the VME system controller\n"); + } + + register_proc(); + + // Get time base speed. Needed to support DMA throughput measurements + tb_speed = tb_ticks_per_jiffy * HZ; + + // Open up the default VME windows. + vme_driver_setup_windows(); + + return 0; +} + +module_init(vme_bridge_init) + module_exit(vme_bridge_exit) diff -u --new-file --recursive linux-2.6.14.orig/include/asm-ppc/mpc85xx_dma.h linux-2.6.14.mod/include/asm-ppc/mpc85xx_dma.h --- linux-2.6.14.orig/include/asm-ppc/mpc85xx_dma.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/include/asm-ppc/mpc85xx_dma.h 2005-11-16 10:40:21.000000000 -0700 @@ -0,0 +1,187 @@ +#ifndef __MPC85xx_DMA_H +#define __MPC85xx_DMA_H + +#include +#include + +/* Mode Registers */ + +#define MPC85xx_MR_EMP_EN 0x00200000 +#define MPC85xx_MR_EMS_EN 0x00040000 +#define MPC85xx_MR_SAHTS_1 0x00000000 +#define MPC85xx_MR_SAHTS_2 0x00004000 +#define MPC85xx_MR_SAHTS_4 0x00008000 +#define MPC85xx_MR_SAHTS_8 0x0000C000 +#define MPC85xx_MR_DAHE 0x00002000 +#define MPC85xx_MR_SAHE 0x00001000 +#define MPC85xx_MR_SRW 0x00000400 +#define MPC85xx_MR_EOSIE 0x00000200 +#define MPC85xx_MR_EOLNIE 0x00000100 +#define MPC85xx_MR_EOLSIE 0x00000080 +#define MPC85xx_MR_EIE 0x00000040 +#define MPC85xx_MR_XFE 0x00000020 +#define MPC85xx_MR_CDSM 0x00000010 +#define MPC85xx_MR_SWSM 0x00000010 +#define MPC85xx_MR_CA 0x00000008 +#define MPC85xx_MR_CTM 0x00000004 +#define MPC85xx_MR_CC 0x00000002 +#define MPC85xx_MR_CS 0x00000001 + + + + +/* Status Register */ + +#define MPC85xx_SR_TE 0x00000080 +#define MPC85xx_SR_CH 0x00000020 +#define MPC85xx_SR_PE 0x00000010 +#define MPC85xx_SR_EOLNI 0x00000008 +#define MPC85xx_SR_CB 0x00000004 +#define MPC85xx_SR_CB 0x00000004 +#define MPC85xx_SR_EOSI 0x00000002 +#define MPC85xx_SR_EOLSI 0x00000001 + + +/* Source Attribute Registers */ + +#define MPC85xx_SATR_SREADTYPE_L_NO_SNOOP 0x00040000 +#define MPC85xx_SATR_SREADTYPE_L_SNOOP 0x00050000 + + +/* Destination Attribute Registers */ + +#define MPC85xx_DATR_DWRITETYPE_L_NO_SNOOP 0x00040000 +#define MPC85xx_DATR_DWRITETYPE_L_SNOOP 0x00050000 + +/* Next Link Descriptor Address Registers */ + +#define MPC85xx_NLNDAR_NDEOSIE 0x00000008 +#define MPC85xx_NLNDAR_EOLND 0x00000001 + +#define MPC85xx_BCR_MASK 0x03ffffff + +/* Physical layout of DMA chain descriptors */ +struct mpc85xx_dma_desc { + uint32_t satr; /* Source attributes */ + uint32_t sar; /* Source physical address */ + uint32_t datr; /* Dest attributes */ + uint32_t dar; /* Dest physical address */ + uint32_t res_1; + uint32_t nlndar; /* Next link physical address */ + uint32_t bcr; /* Byte count */ + uint32_t res_2; +}; + +#define MPC85xx_DMA_EVENT_DONE (1 << 0) +#define MPC85xx_DMA_EVENT_HALTED (1 << 1) +#define MPC85xx_DMA_EVENT_ERROR (1 << 2) + +#define MPC85xx_DMA_CONTROL_DST_HOLD MPC85xx_MR_DAHE +#define MPC85xx_DMA_CONTROL_DST_1 MPC85xx_MR_DAHTS_1 +#define MPC85xx_DMA_CONTROL_DST_2 MPC85xx_MR_DAHTS_2 +#define MPC85xx_DMA_CONTROL_DST_4 MPC85xx_MR_DAHTS_4 +#define MPC85xx_DMA_CONTROL_DST_8 MPC85xx_MR_DAHTS_8 + +#define MPC85xx_DMA_CONTROL_SRC_HOLD MPC85xx_MR_SAHE +#define MPC85xx_DMA_CONTROL_SRC_1 MPC85xx_MR_SAHTS_1 +#define MPC85xx_DMA_CONTROL_SRC_2 MPC85xx_MR_SAHTS_2 +#define MPC85xx_DMA_CONTROL_SRC_4 MPC85xx_MR_SAHTS_4 +#define MPC85xx_DMA_CONTROL_SRC_8 MPC85xx_MR_SAHTS_8 + +#define MPC85xx_DMA_BYTE_MASK MPC85xx_BCR_MASK +#define MPC85xx_DMA_CONTROL_MASTER_START MPC85xx_MR_EMS_EN +#define MPC85xx_DMA_CONTROL_MASTER_PAUSE MPC85xx_MR_EMP_EN + +#define MPC85xx_DMA_CONTROL_PAUSE_2 MPC85xx_MR_BWC_2 +#define MPC85xx_DMA_CONTROL_PAUSE_4 MPC85xx_MR_BWC_4 +#define MPC85xx_DMA_CONTROL_PAUSE_8 MPC85xx_MR_BWC_8 +#define MPC85xx_DMA_CONTROL_PAUSE_16 MPC85xx_MR_BWC_16 +#define MPC85xx_DMA_CONTROL_PAUSE_32 MPC85xx_MR_BWC_32 +#define MPC85xx_DMA_CONTROL_PAUSE_64 MPC85xx_MR_BWC_64 +#define MPC85xx_DMA_CONTROL_PAUSE_128 MPC85xx_MR_BWC_128 +#define MPC85xx_DMA_CONTROL_PAUSE_256 MPC85xx_MR_BWC_256 +#define MPC85xx_DMA_CONTROL_PAUSE_512 MPC85xx_MR_BWC_512 + +/** DMA Engine **/ + +/* + * 'event' is a mask of MPC85xx_DMA_EVENT_* + */ +typedef void (*mpc85xx_dma_f)(int channel, int event_mask, void *data); + +/* + * You can request a DMA channel (0-3). Your handler will be called + * on all events that happen on the channel. If another + * routine is already registered for the requested channel, this + * call will fail. Only if you succeed in this call may you + * call any other DMA routines! + */ +int mpc85xx_dma_request(int channel, const char *name, mpc85xx_dma_f func, void *data); +void mpc85xx_dma_free(int channel, void *data); + +/* + * Runs a single-shot DMA transfer. + * 'flags' is options to MPC85xx_DMA_CONTROL + */ +int mpc85xx_dma_xfer(int channel, int flags, phys_addr_t dst, phys_addr_t src, size_t bytes); + +/* + * Stops the current DMA transfer immediately. + */ +void mpc85xx_dma_abort(int channel); + +/* + * Halts the DMA unit after the next successful transfer. + */ +void mpc85xx_dma_halt(int channel); + +/* + * Indicates if the DMA channel is busy + */ +int mpc85xx_dma_busy(int channel); + + +/************** DMA chains **************/ +struct mpc85xx_dma_chain; + +/* + * Allocate a DMA chain + */ +struct mpc85xx_dma_chain *mpc85xx_dma_chain_alloc(int links); + +/* + * Erase all blocks in the DMA chain. + * DO NOT USE if the chain is DMAing. + */ +void mpc85xx_dma_chain_clear(struct mpc85xx_dma_chain *chain); + +/* + * Free a DMA chain + * DO NOT USE if the chain is DMAing. + */ +void mpc85xx_dma_chain_free(struct mpc85xx_dma_chain *chain); + +/* + * Will return -ENOMEM if you're out of chain slots. + * DO NOT USE if the chain is DMAing. + */ +int mpc85xx_dma_chain_append(struct mpc85xx_dma_chain *chain, + phys_addr_t dst_addr, + phys_addr_t src_addr, + size_t len_in_bytes); + +/* + * Makes a ring out of a chain. + * Append can still be called after this function + * (makes the ring larger). + * DO NOT USE if the chain is DMAing. + */ +int mpc85xx_dma_chain_ring(struct mpc85xx_dma_chain *chain); + +/* + * 'flags' is options to MPC85xx_DMA_CONTROL + * (see include/asm-ppc/mpc85xx_defs.h) + */ +int mpc85xx_dma_chain_xfer(int channel, int flags, struct mpc85xx_dma_chain *chain); + +#endif /* __MPC85xx_DMA_H */ diff -u --new-file --recursive linux-2.6.14.orig/include/asm-ppc/mpc85xx.h linux-2.6.14.mod/include/asm-ppc/mpc85xx.h --- linux-2.6.14.orig/include/asm-ppc/mpc85xx.h 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/include/asm-ppc/mpc85xx.h 2005-11-16 10:40:21.000000000 -0700 @@ -37,6 +37,9 @@ #ifdef CONFIG_STX_GP3 #include #endif +#ifdef CONFIG_MVME3100 +#include +#endif #define _IO_BASE isa_io_base #define _ISA_MEM_BASE isa_mem_base @@ -46,11 +49,24 @@ #define PCI_DRAM_OFFSET 0 #endif +#ifdef CONFIG_UBOOT /* * The "residual" board information structure the boot loader passes * into the kernel. */ extern unsigned char __res[]; + +#define UBOOT_BINFO() ((bd_t *)__res) +#define BINFO_INTFREQ (UBOOT_BINFO()->bi_intfreq) +#define BINFO_BUSFREQ (UBOOT_BINFO()->bi_busfreq) +#define BINFO_IMMR_BASE (UBOOT_BINFO()->bi_immr_base) +#define BINFO_MEMSIZE (UBOOT_BINFO()->bi_memsize) +#define BINFO_BRGFREQ (UBOOT_BINFO()->bi_brgfreq) +#define BINFO_BAUDRATE (UBOOT_BINFO()->bi_baudrate) +#elif !defined(BINFO_INTFREQ) +#error Either define CONFIG_UBOOT, or hand-define the BINFO_ macros +#error in your +#endif /* Offset from CCSRBAR */ #define MPC85xx_CPM_OFFSET (0x80000) diff -u --new-file --recursive linux-2.6.14.orig/include/asm-ppc/mv64x60.h linux-2.6.14.mod/include/asm-ppc/mv64x60.h --- linux-2.6.14.orig/include/asm-ppc/mv64x60.h 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/include/asm-ppc/mv64x60.h 2006-01-10 16:55:22.000000000 -0700 @@ -31,6 +31,68 @@ extern spinlock_t mv64x60_lock; +#define NO_BIT 0x00000000 +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + /* Size defintions */ +#define _1K 0x00000400 +#define _2K 0x00000800 +#define _4K 0x00001000 +#define _8K 0x00002000 +#define _16K 0x00004000 +#define _32K 0x00008000 +#define _64K 0x00010000 +#define _128K 0x00020000 +#define _256K 0x00040000 +#define _512K 0x00080000 +#define _1M 0x00100000 +#define _2M 0x00200000 +#define _3M 0x00300000 +#define _4M 0x00400000 +#define _5M 0x00500000 +#define _6M 0x00600000 +#define _7M 0x00700000 +#define _8M 0x00800000 +#define _9M 0x00900000 +#define _10M 0x00a00000 +#define _11M 0x00b00000 +#define _12M 0x00c00000 +#define _13M 0x00d00000 +#define _14M 0x00e00000 +#define _15M 0x00f00000 +#define _16M 0x01000000 +#define _32M 0x02000000 + /* 32-bit Window table entry defines */ #define MV64x60_CPU2MEM_0_WIN 0 #define MV64x60_CPU2MEM_1_WIN 1 @@ -119,6 +181,7 @@ #define MV64x60_64BIT_WIN_COUNT 24 + /* Watchdog Platform Device, Driver Data */ #define MV64x60_WDT_NAME "wdt" diff -u --new-file --recursive linux-2.6.14.orig/include/asm-ppc/mvme3100_timer.h linux-2.6.14.mod/include/asm-ppc/mvme3100_timer.h --- linux-2.6.14.orig/include/asm-ppc/mvme3100_timer.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.14.mod/include/asm-ppc/mvme3100_timer.h 2005-11-16 10:40:21.000000000 -0700 @@ -0,0 +1,42 @@ +#ifndef __MVME3100_TIMER_H +#define __MVME3100_TIMER_H + +#include + +#define MVME3100_MIN_TIMER_NUMBER 0 +#define MVME3100_MAX_TIMER_NUMBER 3 + +#define MIN_TICKS_PER_MICROSECOND 1 +#define MAX_TICKS_PER_MICROSECOND 25 + +typedef void (*mvme3100_timer_f) (void *data); + +/* + * Start a timer + * Call func(data) after so many microsecoonds + * The function will be called in interrupt context. + */ +int mvme3100_timer_start(int timer_number, unsigned long microseconds, + mvme3100_timer_f func, void *data, int periodic); + +/* + * Stop a timer + */ +int mvme3100_timer_stop(int timer_number); + +/* + * Get the timer resolution, in microseconds/tick + */ +unsigned long mvme3100_timer_get_resolution(void); + +/* + * Set the timer resolution, in ticks/microseconds + */ +int mvme3100_timer_set_resolution(unsigned long ticks); + +/* + * Get a timer counter value, in ticks + */ +unsigned long mvme3100_timer_get_ticks(int timer_number); + +#endif /* __MVME3100_TIMER_H */ diff -u --new-file --recursive linux-2.6.14.orig/include/asm-ppc/reg_booke.h linux-2.6.14.mod/include/asm-ppc/reg_booke.h --- linux-2.6.14.orig/include/asm-ppc/reg_booke.h 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/include/asm-ppc/reg_booke.h 2005-11-16 10:40:21.000000000 -0700 @@ -104,6 +104,59 @@ #define PMRN_UPMLCB3 0x103 /* User PM Local Control B3 */ #define PMRN_UPMGC0 0x180 /* User PM Global Control 0 */ +/* Freescale Book E Performance Monitor APU Registers */ +#define PMRN_PMC0 0x010 /* Performance Monitor Counter 0 */ +#define PMRN_PMC1 0x011 /* Performance Monitor Counter 1 */ +#define PMRN_PMC2 0x012 /* Performance Monitor Counter 1 */ +#define PMRN_PMC3 0x013 /* Performance Monitor Counter 1 */ +#define PMRN_PMLCA0 0x090 /* PM Local Control A0 */ +#define PMRN_PMLCA1 0x091 /* PM Local Control A1 */ +#define PMRN_PMLCA2 0x092 /* PM Local Control A2 */ +#define PMRN_PMLCA3 0x093 /* PM Local Control A3 */ + +#define PMLCA_FC 0x80000000 /* Freeze Counter */ +#define PMLCA_FCS 0x40000000 /* Freeze in Supervisor */ +#define PMLCA_FCU 0x20000000 /* Freeze in User */ +#define PMLCA_FCM1 0x10000000 /* Freeze when PMM==1 */ +#define PMLCA_FCM0 0x08000000 /* Freeze when PMM==0 */ +#define PMLCA_CE 0x04000000 /* Condition Enable */ + +#define PMLCA_EVENT_MASK 0x007f0000 /* Event field */ +#define PMLCA_EVENT_SHIFT 16 + +#define PMRN_PMLCB0 0x110 /* PM Local Control B0 */ +#define PMRN_PMLCB1 0x111 /* PM Local Control B1 */ +#define PMRN_PMLCB2 0x112 /* PM Local Control B2 */ +#define PMRN_PMLCB3 0x113 /* PM Local Control B3 */ + +#define PMLCB_THRESHMUL_MASK 0x0700 /* Threshhold Multiple Field */ +#define PMLCB_THRESHMUL_SHIFT 8 + +#define PMLCB_THRESHOLD_MASK 0x003f /* Threshold Field */ +#define PMLCB_THRESHOLD_SHIFT 0 + +#define PMRN_PMGC0 0x190 /* PM Global Control 0 */ + +#define PMGC0_FAC 0x80000000 /* Freeze all Counters */ +#define PMGC0_PMIE 0x40000000 /* Interrupt Enable */ +#define PMGC0_FCECE 0x20000000 /* Freeze countes on + Enabled Condition or + Event */ + +#define PMRN_UPMC0 0x000 /* User Performance Monitor Counter 0 */ +#define PMRN_UPMC1 0x001 /* User Performance Monitor Counter 1 */ +#define PMRN_UPMC2 0x002 /* User Performance Monitor Counter 1 */ +#define PMRN_UPMC3 0x003 /* User Performance Monitor Counter 1 */ +#define PMRN_UPMLCA0 0x080 /* User PM Local Control A0 */ +#define PMRN_UPMLCA1 0x081 /* User PM Local Control A1 */ +#define PMRN_UPMLCA2 0x082 /* User PM Local Control A2 */ +#define PMRN_UPMLCA3 0x083 /* User PM Local Control A3 */ +#define PMRN_UPMLCB0 0x100 /* User PM Local Control B0 */ +#define PMRN_UPMLCB1 0x101 /* User PM Local Control B1 */ +#define PMRN_UPMLCB2 0x102 /* User PM Local Control B2 */ +#define PMRN_UPMLCB3 0x103 /* User PM Local Control B3 */ +#define PMRN_UPMGC0 0x180 /* User PM Global Control 0 */ + /* Machine State Register (MSR) Fields */ #define MSR_UCLE (1<<26) /* User-mode cache lock enable */ @@ -118,7 +171,7 @@ #if defined (CONFIG_40x) #define MSR_KERNEL (MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE) #elif defined(CONFIG_BOOKE) -#define MSR_KERNEL (MSR_ME|MSR_RI|MSR_CE) +#define MSR_KERNEL (MSR_ME|MSR_RI|MSR_CE|MSR_DE) #endif /* Special Purpose Registers (SPRNs)*/ @@ -157,6 +210,8 @@ #define SPRN_SPEFSCR 0x200 /* SPE & Embedded FP Status & Control */ #define SPRN_BBEAR 0x201 /* Branch Buffer Entry Address Register */ #define SPRN_BBTAR 0x202 /* Branch Buffer Target Address Register */ +#define SPRN_L1CFG0 0x203 /* L1 Cache Configuration Register 0 */ +#define SPRN_L1CFG1 0x204 /* L1 Cache Configuration Register 1 */ #define SPRN_IVOR32 0x210 /* Interrupt Vector Offset Register 32 */ #define SPRN_IVOR33 0x211 /* Interrupt Vector Offset Register 33 */ #define SPRN_IVOR34 0x212 /* Interrupt Vector Offset Register 34 */ @@ -352,8 +407,17 @@ #define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */ /* Bit definitions related to the TCR. */ -#define TCR_WP(x) (((x)&0x3)<<30) /* WDT Period */ -#define TCR_WP_MASK TCR_WP(3) +#ifdef CONFIG_E500 +#define TCR_WP(x) ((((x)&0x3c)<<15)|(((x)&0x3)<<30)) /* WDT Period */ +#define TCR_WP_MASK TCR_WP(0x3f) +#define TCR_FP(x) ((((x)&0x3c)<<11)|(((x)&0x3)<<24)) /* FIT Period */ +#define TCR_FP_MASK TCR_FP(0x3f) +#else /* 4xx series */ +#define TCR_WP(x) (((x)&0x3)<<30) /* WDT Period */ +#define TCR_WP_MASK TCR_WP(3) +#define TCR_FP(x) (((x)&0x3)<<24) /* FIT Period */ +#define TCR_FP_MASK TCR_FP(3) +#endif #define WP_2_17 0 /* 2^17 clocks */ #define WP_2_21 1 /* 2^21 clocks */ #define WP_2_25 2 /* 2^25 clocks */ @@ -367,8 +431,6 @@ #define TCR_WIE 0x08000000 /* WDT Interrupt Enable */ #define TCR_PIE 0x04000000 /* PIT Interrupt Enable */ #define TCR_DIE TCR_PIE /* DEC Interrupt Enable */ -#define TCR_FP(x) (((x)&0x3)<<24) /* FIT Period */ -#define TCR_FP_MASK TCR_FP(3) #define FP_2_9 0 /* 2^9 clocks */ #define FP_2_13 1 /* 2^13 clocks */ #define FP_2_17 2 /* 2^17 clocks */ diff -u --new-file --recursive linux-2.6.14.orig/include/asm-ppc/reg.h linux-2.6.14.mod/include/asm-ppc/reg.h --- linux-2.6.14.orig/include/asm-ppc/reg.h 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/include/asm-ppc/reg.h 2005-11-16 10:40:21.000000000 -0700 @@ -383,6 +383,8 @@ #define PVR_7400 0x000C0000 #define PVR_7410 0x800C0000 #define PVR_7450 0x80000000 +#define PVR_7455 0x80010000 +#define PVR_7457 0x80020000 #define PVR_8540 0x80200000 #define PVR_8560 0x80200000 /* diff -u --new-file --recursive linux-2.6.14.orig/include/asm-ppc/serial.h linux-2.6.14.mod/include/asm-ppc/serial.h --- linux-2.6.14.orig/include/asm-ppc/serial.h 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/include/asm-ppc/serial.h 2006-01-20 16:55:41.000000000 -0700 @@ -20,6 +20,12 @@ #include #elif defined(CONFIG_MVME5100) #include +#elif defined(CONFIG_MVME5500) +#include +#elif defined(CONFIG_MVME6100) +#include +#elif defined(CONFIG_MCP905) +#include #elif defined(CONFIG_PAL4) #include #elif defined(CONFIG_PRPMC750) diff -u --new-file --recursive linux-2.6.14.orig/include/linux/i2c-id.h linux-2.6.14.mod/include/linux/i2c-id.h --- linux-2.6.14.orig/include/linux/i2c-id.h 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/include/linux/i2c-id.h 2005-11-16 10:40:21.000000000 -0700 @@ -99,6 +99,7 @@ #define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */ #define I2C_DRIVERID_SAA7114H 64 /* video decoder */ #define I2C_DRIVERID_DS1374 65 /* DS1374 real time clock */ +#define I2C_DRIVERID_DS1375 66 /* DS1375 real time clock */ #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ diff -u --new-file --recursive linux-2.6.14.orig/include/linux/libata.h linux-2.6.14.mod/include/linux/libata.h --- linux-2.6.14.orig/include/linux/libata.h 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/include/linux/libata.h 2006-01-20 16:55:21.000000000 -0700 @@ -40,7 +40,7 @@ #undef ATA_VERBOSE_DEBUG /* yet more debugging output */ #undef ATA_IRQ_TRAP /* define to ack screaming irqs */ #undef ATA_NDEBUG /* define to disable quick runtime checks */ -#undef ATA_ENABLE_PATA /* define to enable PATA support in some +#define ATA_ENABLE_PATA /* define to enable PATA support in some * low-level drivers */ #undef ATAPI_ENABLE_DMADIR /* enables ATAPI DMADIR bridge support */ diff -u --new-file --recursive linux-2.6.14.orig/include/linux/pci_ids.h linux-2.6.14.mod/include/linux/pci_ids.h --- linux-2.6.14.orig/include/linux/pci_ids.h 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/include/linux/pci_ids.h 2005-11-16 10:40:21.000000000 -0700 @@ -2550,6 +2550,7 @@ #define PCI_DEVICE_ID_INTEL_ICH7_21 0x27df #define PCI_DEVICE_ID_INTEL_ICH7_22 0x27e0 #define PCI_DEVICE_ID_INTEL_ICH7_23 0x27e2 +#define PCI_DEVICE_ID_INTEL_GD31244 0x3200 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_ESB2_19 0x3500 #define PCI_DEVICE_ID_INTEL_ESB2_20 0x3501 diff -u --new-file --recursive linux-2.6.14.orig/init/do_mounts.c linux-2.6.14.mod/init/do_mounts.c --- linux-2.6.14.orig/init/do_mounts.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/init/do_mounts.c 2005-11-16 10:40:21.000000000 -0700 @@ -286,6 +286,7 @@ char *fs_names = __getname(); char *p; char b[BDEVNAME_SIZE]; + int retries = 0; get_fs_names(fs_names); retry: @@ -305,11 +306,22 @@ * and bad superblock on root device. */ __bdevname(ROOT_DEV, b); - printk("VFS: Cannot open root device \"%s\" or %s\n", + printk("VFS: Cannot open root device \"%s\" or %s, retrying in 1s.\n", root_device_name, b); - printk("Please append a correct \"root=\" boot option\n"); - - panic("VFS: Unable to mount root fs on %s", b); + retries++; + if (retries < 10) { + /* wait 1 second and try again */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ); + root_device_name = saved_root_name; + ROOT_DEV = name_to_dev_t(root_device_name); + if (strncmp(root_device_name, "/dev/", 5) == 0) + root_device_name += 5; + create_dev("/dev/root", ROOT_DEV, root_device_name); + get_fs_names(fs_names); + goto retry; + } else + panic("VFS: Unable to mount root fs on %s", b); } panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b)); out: diff -u --new-file --recursive linux-2.6.14.orig/Makefile linux-2.6.14.mod/Makefile --- linux-2.6.14.orig/Makefile 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/Makefile 2006-01-26 12:10:08.000000000 -0700 @@ -192,6 +192,10 @@ ARCH ?= $(SUBARCH) CROSS_COMPILE ?= +#ARCH ?= ppc +#CROSS_COMPILE ?= ppc_85xx- +#CROSS_COMPILE ?= ppc_74xx- + # Architecture as present in compile.h UTS_MACHINE := $(ARCH) diff -u --new-file --recursive linux-2.6.14.orig/mm/mmap.c linux-2.6.14.mod/mm/mmap.c --- linux-2.6.14.orig/mm/mmap.c 2005-10-27 17:02:08.000000000 -0700 +++ linux-2.6.14.mod/mm/mmap.c 2005-11-16 10:40:21.000000000 -0700 @@ -59,7 +59,7 @@ __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111 }; -int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */ +int sysctl_overcommit_memory = OVERCOMMIT_NEVER; int sysctl_overcommit_ratio = 50; /* default is 50% */ int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT; atomic_t vm_committed_space = ATOMIC_INIT(0);